From webhook-mailer at python.org Sun Mar 1 13:43:08 2020 From: webhook-mailer at python.org (Gregory P. Smith) Date: Sun, 01 Mar 2020 18:43:08 -0000 Subject: [Python-checkins] bpo-39769: Fix compileall ddir for subpkgs. (GH-18676) (GH-18718) Message-ID: https://github.com/python/cpython/commit/ce720d3e0674d6ac6f1b950c20a89be4cfde7853 commit: ce720d3e0674d6ac6f1b950c20a89be4cfde7853 branch: 3.8 author: Gregory P. Smith committer: GitHub date: 2020-03-01T10:42:56-08:00 summary: bpo-39769: Fix compileall ddir for subpkgs. (GH-18676) (GH-18718) Fix compileall.compile_dir() ddir= behavior on sub-packages. Fixes compileall.compile_dir's ddir parameter and compileall command line flag `-d` to no longer write the wrong pathname to the generated pyc file for submodules beneath the root of the directory tree being compiled. This fixes a regression introduced with Python 3.5. Tests backported from GH 02673352b5db6ca4d3dc804965facbedfe66425d, the implementation is different due to intervening code changes. But still quiet simple. Why was the bug ever introduced? The refactoring to add parallel execution kept the ddir -> dfile computations but discarded the results instead of sending them to compile_file(). This fixes that. Lack of tests meant this went unnoticed. files: A Misc/NEWS.d/next/Library/2020-02-29-13-20-33.bpo-39769.hJmxu4.rst M Lib/compileall.py M Lib/test/test_compileall.py M Lib/test/test_importlib/util.py diff --git a/Lib/compileall.py b/Lib/compileall.py index 49306d9dabbc5..bfac8efc804d0 100644 --- a/Lib/compileall.py +++ b/Lib/compileall.py @@ -41,7 +41,7 @@ def _walk_dir(dir, ddir=None, maxlevels=10, quiet=0): else: dfile = None if not os.path.isdir(fullname): - yield fullname + yield fullname, ddir elif (maxlevels > 0 and name != os.curdir and name != os.pardir and os.path.isdir(fullname) and not os.path.islink(fullname)): yield from _walk_dir(fullname, ddir=dfile, @@ -76,28 +76,33 @@ def compile_dir(dir, maxlevels=10, ddir=None, force=False, rx=None, from concurrent.futures import ProcessPoolExecutor except ImportError: workers = 1 - files = _walk_dir(dir, quiet=quiet, maxlevels=maxlevels, - ddir=ddir) + files_and_ddirs = _walk_dir(dir, quiet=quiet, maxlevels=maxlevels, + ddir=ddir) success = True if workers != 1 and ProcessPoolExecutor is not None: # If workers == 0, let ProcessPoolExecutor choose workers = workers or None with ProcessPoolExecutor(max_workers=workers) as executor: - results = executor.map(partial(compile_file, - ddir=ddir, force=force, - rx=rx, quiet=quiet, - legacy=legacy, - optimize=optimize, - invalidation_mode=invalidation_mode), - files) + results = executor.map( + partial(_compile_file_tuple, + force=force, rx=rx, quiet=quiet, + legacy=legacy, optimize=optimize, + invalidation_mode=invalidation_mode, + ), + files_and_ddirs) success = min(results, default=True) else: - for file in files: - if not compile_file(file, ddir, force, rx, quiet, + for file, dfile in files_and_ddirs: + if not compile_file(file, dfile, force, rx, quiet, legacy, optimize, invalidation_mode): success = False return success +def _compile_file_tuple(file_and_dfile, **kwargs): + """Needs to be toplevel for ProcessPoolExecutor.""" + file, dfile = file_and_dfile + return compile_file(file, dfile, **kwargs) + def compile_file(fullname, ddir=None, force=False, rx=None, quiet=0, legacy=False, optimize=-1, invalidation_mode=None): diff --git a/Lib/test/test_compileall.py b/Lib/test/test_compileall.py index 04f6e1e049dde..64f092b53b500 100644 --- a/Lib/test/test_compileall.py +++ b/Lib/test/test_compileall.py @@ -577,6 +577,47 @@ def test_workers_available_cores(self, compile_dir): self.assertTrue(compile_dir.called) self.assertEqual(compile_dir.call_args[-1]['workers'], 0) + def _test_ddir_only(self, *, ddir, parallel=True): + """Recursive compile_dir ddir must contain package paths; bpo39769.""" + fullpath = ["test", "foo"] + path = self.directory + mods = [] + for subdir in fullpath: + path = os.path.join(path, subdir) + os.mkdir(path) + script_helper.make_script(path, "__init__", "") + mods.append(script_helper.make_script(path, "mod", + "def fn(): 1/0\nfn()\n")) + compileall.compile_dir( + self.directory, quiet=True, ddir=ddir, + workers=2 if parallel else 1) + self.assertTrue(mods) + for mod in mods: + self.assertTrue(mod.startswith(self.directory), mod) + modcode = importlib.util.cache_from_source(mod) + modpath = mod[len(self.directory+os.sep):] + _, _, err = script_helper.assert_python_failure(modcode) + expected_in = os.path.join(ddir, modpath) + mod_code_obj = test.test_importlib.util._get_code_from_pyc(modcode) + self.assertEqual(mod_code_obj.co_filename, expected_in) + self.assertIn(f'"{expected_in}"', os.fsdecode(err)) + + def test_ddir_only_one_worker(self): + """Recursive compile_dir ddir= contains package paths; bpo39769.""" + return self._test_ddir_only(ddir="", parallel=False) + + def test_ddir_multiple_workers(self): + """Recursive compile_dir ddir= contains package paths; bpo39769.""" + return self._test_ddir_only(ddir="", parallel=True) + + def test_ddir_empty_only_one_worker(self): + """Recursive compile_dir ddir='' contains package paths; bpo39769.""" + return self._test_ddir_only(ddir="", parallel=False) + + def test_ddir_empty_multiple_workers(self): + """Recursive compile_dir ddir='' contains package paths; bpo39769.""" + return self._test_ddir_only(ddir="", parallel=True) + class CommmandLineTestsWithSourceEpoch(CommandLineTestsBase, unittest.TestCase, diff --git a/Lib/test/test_importlib/util.py b/Lib/test/test_importlib/util.py index e016ea49119ae..e6a1476875b5e 100644 --- a/Lib/test/test_importlib/util.py +++ b/Lib/test/test_importlib/util.py @@ -7,6 +7,7 @@ from importlib import machinery, util, invalidate_caches from importlib.abc import ResourceReader import io +import marshal import os import os.path from pathlib import Path, PurePath @@ -118,6 +119,16 @@ def submodule(parent, name, pkg_dir, content=''): return '{}.{}'.format(parent, name), path +def _get_code_from_pyc(pyc_path): + """Reads a pyc file and returns the unmarshalled code object within. + + No header validation is performed. + """ + with open(pyc_path, 'rb') as pyc_f: + pyc_f.seek(16) + return marshal.load(pyc_f) + + @contextlib.contextmanager def uncache(*names): """Uncache a module from sys.modules. diff --git a/Misc/NEWS.d/next/Library/2020-02-29-13-20-33.bpo-39769.hJmxu4.rst b/Misc/NEWS.d/next/Library/2020-02-29-13-20-33.bpo-39769.hJmxu4.rst new file mode 100644 index 0000000000000..9b564bd10d3b3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-02-29-13-20-33.bpo-39769.hJmxu4.rst @@ -0,0 +1,4 @@ +The :func:`compileall.compile_dir` function's *ddir* parameter and the +compileall command line flag `-d` no longer write the wrong pathname to the +generated pyc file for submodules beneath the root of the directory tree +being compiled. This fixes a regression introduced with Python 3.5. From webhook-mailer at python.org Sun Mar 1 14:06:59 2020 From: webhook-mailer at python.org (Gregory P. Smith) Date: Sun, 01 Mar 2020 19:06:59 -0000 Subject: [Python-checkins] [3.7] bpo-39769: Fix compileall ddir for subpkgs. (GH-18676) (GH-18718) (GH-18725) Message-ID: https://github.com/python/cpython/commit/7c64726ced3d6b5d04537386d6a9ca6d179c3be4 commit: 7c64726ced3d6b5d04537386d6a9ca6d179c3be4 branch: 3.7 author: Gregory P. Smith committer: GitHub date: 2020-03-01T11:06:54-08:00 summary: [3.7] bpo-39769: Fix compileall ddir for subpkgs. (GH-18676) (GH-18718) (GH-18725) Fix compileall.compile_dir() ddir= behavior on sub-packages. Fixes compileall.compile_dir's ddir parameter and compileall command line flag `-d` to no longer write the wrong pathname to the generated pyc file for submodules beneath the root of the directory tree being compiled. This fixes a regression introduced with Python 3.5. Tests backported from GH 02673352b5db6ca4d3dc804965facbedfe66425d, the implementation is different due to intervening code changes. But still quiet simple. Why was the bug ever introduced? The refactoring to add parallel execution kept the ddir -> dfile computations but discarded the results instead of sending them to compile_file(). This fixes that. Lack of tests meant this went unnoticed.. (cherry picked from commit ce720d3e0674d6ac6f1b950c20a89be4cfde7853) Co-authored-by: Gregory P. Smith [Google] files: A Misc/NEWS.d/next/Library/2020-02-29-13-20-33.bpo-39769.hJmxu4.rst M Lib/compileall.py M Lib/test/test_compileall.py M Lib/test/test_importlib/util.py diff --git a/Lib/compileall.py b/Lib/compileall.py index aa65c6b904e79..ff5af96d5bc92 100644 --- a/Lib/compileall.py +++ b/Lib/compileall.py @@ -41,7 +41,7 @@ def _walk_dir(dir, ddir=None, maxlevels=10, quiet=0): else: dfile = None if not os.path.isdir(fullname): - yield fullname + yield fullname, ddir elif (maxlevels > 0 and name != os.curdir and name != os.pardir and os.path.isdir(fullname) and not os.path.islink(fullname)): yield from _walk_dir(fullname, ddir=dfile, @@ -77,27 +77,32 @@ def compile_dir(dir, maxlevels=10, ddir=None, force=False, rx=None, from concurrent.futures import ProcessPoolExecutor except ImportError: workers = 1 - files = _walk_dir(dir, quiet=quiet, maxlevels=maxlevels, - ddir=ddir) + files_and_ddirs = _walk_dir(dir, quiet=quiet, maxlevels=maxlevels, + ddir=ddir) success = True if workers is not None and workers != 1 and ProcessPoolExecutor is not None: workers = workers or None with ProcessPoolExecutor(max_workers=workers) as executor: - results = executor.map(partial(compile_file, - ddir=ddir, force=force, - rx=rx, quiet=quiet, - legacy=legacy, - optimize=optimize, - invalidation_mode=invalidation_mode), - files) + results = executor.map( + partial(_compile_file_tuple, + force=force, rx=rx, quiet=quiet, + legacy=legacy, optimize=optimize, + invalidation_mode=invalidation_mode, + ), + files_and_ddirs) success = min(results, default=True) else: - for file in files: - if not compile_file(file, ddir, force, rx, quiet, + for file, dfile in files_and_ddirs: + if not compile_file(file, dfile, force, rx, quiet, legacy, optimize, invalidation_mode): success = False return success +def _compile_file_tuple(file_and_dfile, **kwargs): + """Needs to be toplevel for ProcessPoolExecutor.""" + file, dfile = file_and_dfile + return compile_file(file, dfile, **kwargs) + def compile_file(fullname, ddir=None, force=False, rx=None, quiet=0, legacy=False, optimize=-1, invalidation_mode=None): diff --git a/Lib/test/test_compileall.py b/Lib/test/test_compileall.py index 2e2552303f8d5..07c31cedb17ba 100644 --- a/Lib/test/test_compileall.py +++ b/Lib/test/test_compileall.py @@ -578,6 +578,47 @@ def test_workers_available_cores(self, compile_dir): self.assertTrue(compile_dir.called) self.assertEqual(compile_dir.call_args[-1]['workers'], None) + def _test_ddir_only(self, *, ddir, parallel=True): + """Recursive compile_dir ddir must contain package paths; bpo39769.""" + fullpath = ["test", "foo"] + path = self.directory + mods = [] + for subdir in fullpath: + path = os.path.join(path, subdir) + os.mkdir(path) + script_helper.make_script(path, "__init__", "") + mods.append(script_helper.make_script(path, "mod", + "def fn(): 1/0\nfn()\n")) + compileall.compile_dir( + self.directory, quiet=True, ddir=ddir, + workers=2 if parallel else 1) + self.assertTrue(mods) + for mod in mods: + self.assertTrue(mod.startswith(self.directory), mod) + modcode = importlib.util.cache_from_source(mod) + modpath = mod[len(self.directory+os.sep):] + _, _, err = script_helper.assert_python_failure(modcode) + expected_in = os.path.join(ddir, modpath) + mod_code_obj = test.test_importlib.util._get_code_from_pyc(modcode) + self.assertEqual(mod_code_obj.co_filename, expected_in) + self.assertIn(f'"{expected_in}"', os.fsdecode(err)) + + def test_ddir_only_one_worker(self): + """Recursive compile_dir ddir= contains package paths; bpo39769.""" + return self._test_ddir_only(ddir="", parallel=False) + + def test_ddir_multiple_workers(self): + """Recursive compile_dir ddir= contains package paths; bpo39769.""" + return self._test_ddir_only(ddir="", parallel=True) + + def test_ddir_empty_only_one_worker(self): + """Recursive compile_dir ddir='' contains package paths; bpo39769.""" + return self._test_ddir_only(ddir="", parallel=False) + + def test_ddir_empty_multiple_workers(self): + """Recursive compile_dir ddir='' contains package paths; bpo39769.""" + return self._test_ddir_only(ddir="", parallel=True) + class CommmandLineTestsWithSourceEpoch(CommandLineTestsBase, unittest.TestCase, diff --git a/Lib/test/test_importlib/util.py b/Lib/test/test_importlib/util.py index b0badebc2b8c0..101b7d22bf922 100644 --- a/Lib/test/test_importlib/util.py +++ b/Lib/test/test_importlib/util.py @@ -7,6 +7,7 @@ from importlib import machinery, util, invalidate_caches from importlib.abc import ResourceReader import io +import marshal import os import os.path from pathlib import Path, PurePath @@ -118,6 +119,16 @@ def submodule(parent, name, pkg_dir, content=''): return '{}.{}'.format(parent, name), path +def _get_code_from_pyc(pyc_path): + """Reads a pyc file and returns the unmarshalled code object within. + + No header validation is performed. + """ + with open(pyc_path, 'rb') as pyc_f: + pyc_f.seek(16) + return marshal.load(pyc_f) + + @contextlib.contextmanager def uncache(*names): """Uncache a module from sys.modules. diff --git a/Misc/NEWS.d/next/Library/2020-02-29-13-20-33.bpo-39769.hJmxu4.rst b/Misc/NEWS.d/next/Library/2020-02-29-13-20-33.bpo-39769.hJmxu4.rst new file mode 100644 index 0000000000000..9b564bd10d3b3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-02-29-13-20-33.bpo-39769.hJmxu4.rst @@ -0,0 +1,4 @@ +The :func:`compileall.compile_dir` function's *ddir* parameter and the +compileall command line flag `-d` no longer write the wrong pathname to the +generated pyc file for submodules beneath the root of the directory tree +being compiled. This fixes a regression introduced with Python 3.5. From webhook-mailer at python.org Sun Mar 1 14:59:35 2020 From: webhook-mailer at python.org (Vlad Emelianov) Date: Sun, 01 Mar 2020 19:59:35 -0000 Subject: [Python-checkins] bpo-38641: Add lib2to3 support for starred expressions in return/yield statements (GH-16994) Message-ID: https://github.com/python/cpython/commit/768d739c1cd8c1d41902229581811a9b86bcc76e commit: 768d739c1cd8c1d41902229581811a9b86bcc76e branch: master author: Vlad Emelianov committer: GitHub date: 2020-03-01T19:59:26Z summary: bpo-38641: Add lib2to3 support for starred expressions in return/yield statements (GH-16994) files: A Misc/NEWS.d/next/Library/2019-10-30-15-31-09.bpo-38641.HrTL9k.rst M Lib/lib2to3/Grammar.txt M Lib/lib2to3/tests/data/py3_test_grammar.py M Misc/ACKS diff --git a/Lib/lib2to3/Grammar.txt b/Lib/lib2to3/Grammar.txt index 68b73868b5828..51f58209f036f 100644 --- a/Lib/lib2to3/Grammar.txt +++ b/Lib/lib2to3/Grammar.txt @@ -49,7 +49,7 @@ pass_stmt: 'pass' flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt break_stmt: 'break' continue_stmt: 'continue' -return_stmt: 'return' [testlist] +return_stmt: 'return' [testlist_star_expr] yield_stmt: yield_expr raise_stmt: 'raise' [test ['from' test | ',' test [',' test]]] import_stmt: import_name | import_from @@ -151,4 +151,4 @@ testlist1: test (',' test)* encoding_decl: NAME yield_expr: 'yield' [yield_arg] -yield_arg: 'from' test | testlist +yield_arg: 'from' test | testlist_star_expr diff --git a/Lib/lib2to3/tests/data/py3_test_grammar.py b/Lib/lib2to3/tests/data/py3_test_grammar.py index e0b682837e1d8..d06223207e1ec 100644 --- a/Lib/lib2to3/tests/data/py3_test_grammar.py +++ b/Lib/lib2to3/tests/data/py3_test_grammar.py @@ -473,15 +473,27 @@ def test_inner(extra_burning_oil = 1, count=0): test_inner() def testReturn(self): - # 'return' [testlist] + # 'return' [testlist_star_expr] def g1(): return def g2(): return 1 + return_list = [2, 3] + def g3(): return 1, *return_list g1() x = g2() + x3 = g3() check_syntax_error(self, "class foo:return 1") def testYield(self): + # 'yield' [yield_arg] + def g1(): yield 1 + yield_list = [2, 3] + def g2(): yield 1, *yield_list + def g3(): yield from iter(yield_list) + x1 = g1() + x2 = g2() + x3 = g3() check_syntax_error(self, "class foo:yield 1") + check_syntax_error(self, "def g4(): yield from *a") def testRaise(self): # 'raise' test [',' test] diff --git a/Misc/ACKS b/Misc/ACKS index 1b5febb1d19d8..b36e2de4c2ba5 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1914,5 +1914,6 @@ Jelle Zijlstra Gennadiy Zlobin Doug Zongker Peter ?strand +Vlad Emelianov (Entries should be added in rough alphabetical order by last names) diff --git a/Misc/NEWS.d/next/Library/2019-10-30-15-31-09.bpo-38641.HrTL9k.rst b/Misc/NEWS.d/next/Library/2019-10-30-15-31-09.bpo-38641.HrTL9k.rst new file mode 100644 index 0000000000000..c547712d81367 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-10-30-15-31-09.bpo-38641.HrTL9k.rst @@ -0,0 +1,2 @@ +Added starred expressions support to ``return`` and ``yield`` statements for +``lib2to3``. Patch by Vlad Emelianov. From webhook-mailer at python.org Sun Mar 1 15:49:19 2020 From: webhook-mailer at python.org (Thomas Moreau) Date: Sun, 01 Mar 2020 20:49:19 -0000 Subject: [Python-checkins] bpo-39678: refactor queue manager thread (GH-18551) Message-ID: https://github.com/python/cpython/commit/0e89076247580ba0e570c4816f0e5628a7e36e83 commit: 0e89076247580ba0e570c4816f0e5628a7e36e83 branch: master author: Thomas Moreau committer: GitHub date: 2020-03-01T21:49:14+01:00 summary: bpo-39678: refactor queue manager thread (GH-18551) files: A Misc/NEWS.d/next/Library/2020-02-28-12-59-30.bpo-39678.3idfxM.rst M Lib/concurrent/futures/process.py M Lib/test/test_concurrent_futures.py diff --git a/Lib/concurrent/futures/process.py b/Lib/concurrent/futures/process.py index d77322831a6c6..39fadcce027c2 100644 --- a/Lib/concurrent/futures/process.py +++ b/Lib/concurrent/futures/process.py @@ -49,7 +49,6 @@ import os from concurrent.futures import _base import queue -from queue import Full import multiprocessing as mp import multiprocessing.connection from multiprocessing.queues import Queue @@ -176,8 +175,9 @@ def _on_queue_feeder_error(self, e, obj): e.__cause__ = _RemoteTraceback('\n"""\n{}"""'.format(''.join(tb))) work_item = self.pending_work_items.pop(obj.work_id, None) self.thread_wakeup.wakeup() - # work_item can be None if another process terminated. In this case, - # the queue_manager_thread fails all work_items with BrokenProcessPool + # work_item can be None if another process terminated. In this + # case, the executor_manager_thread fails all work_items + # with BrokenProcessPool if work_item is not None: work_item.future.set_exception(e) else: @@ -193,6 +193,7 @@ def _get_chunks(*iterables, chunksize): return yield chunk + def _process_chunk(fn, chunk): """ Processes a chunk of an iterable passed to map. @@ -256,122 +257,123 @@ def _process_worker(call_queue, result_queue, initializer, initargs): del call_item -def _add_call_item_to_queue(pending_work_items, - work_ids, - call_queue): - """Fills call_queue with _WorkItems from pending_work_items. +class _ExecutorManagerThread(threading.Thread): + """Manages the communication between this process and the worker processes. - This function never blocks. + The manager is run in a local thread. Args: - pending_work_items: A dict mapping work ids to _WorkItems e.g. - {5: <_WorkItem...>, 6: <_WorkItem...>, ...} - work_ids: A queue.Queue of work ids e.g. Queue([5, 6, ...]). Work ids - are consumed and the corresponding _WorkItems from - pending_work_items are transformed into _CallItems and put in - call_queue. - call_queue: A multiprocessing.Queue that will be filled with _CallItems - derived from _WorkItems. + executor: A reference to the ProcessPoolExecutor that owns + this thread. A weakref will be own by the manager as well as + references to internal objects used to introspect the state of + the executor. """ - while True: - if call_queue.full(): - return - try: - work_id = work_ids.get(block=False) - except queue.Empty: - return - else: - work_item = pending_work_items[work_id] - - if work_item.future.set_running_or_notify_cancel(): - call_queue.put(_CallItem(work_id, - work_item.fn, - work_item.args, - work_item.kwargs), - block=True) - else: - del pending_work_items[work_id] - continue + def __init__(self, executor): + # Store references to necessary internals of the executor. -def _queue_management_worker(executor_reference, - processes, - pending_work_items, - work_ids_queue, - call_queue, - result_queue, - thread_wakeup): - """Manages the communication between this process and the worker processes. + # A _ThreadWakeup to allow waking up the queue_manager_thread from the + # main Thread and avoid deadlocks caused by permanently locked queues. + self.thread_wakeup = executor._executor_manager_thread_wakeup - This function is run in a local thread. + # A weakref.ref to the ProcessPoolExecutor that owns this thread. Used + # to determine if the ProcessPoolExecutor has been garbage collected + # and that the manager can exit. + # When the executor gets garbage collected, the weakref callback + # will wake up the queue management thread so that it can terminate + # if there is no pending work item. + def weakref_cb(_, thread_wakeup=self.thread_wakeup): + mp.util.debug('Executor collected: triggering callback for' + ' QueueManager wakeup') + thread_wakeup.wakeup() - Args: - executor_reference: A weakref.ref to the ProcessPoolExecutor that owns - this thread. Used to determine if the ProcessPoolExecutor has been - garbage collected and that this function can exit. - process: A list of the ctx.Process instances used as - workers. - pending_work_items: A dict mapping work ids to _WorkItems e.g. - {5: <_WorkItem...>, 6: <_WorkItem...>, ...} - work_ids_queue: A queue.Queue of work ids e.g. Queue([5, 6, ...]). - call_queue: A ctx.Queue that will be filled with _CallItems - derived from _WorkItems for processing by the process workers. - result_queue: A ctx.SimpleQueue of _ResultItems generated by the - process workers. - thread_wakeup: A _ThreadWakeup to allow waking up the - queue_manager_thread from the main Thread and avoid deadlocks - caused by permanently locked queues. - """ - executor = None + self.executor_reference = weakref.ref(executor, weakref_cb) - def shutting_down(): - return (_global_shutdown or executor is None - or executor._shutdown_thread) + # A list of the ctx.Process instances used as workers. + self.processes = executor._processes - def shutdown_worker(): - # This is an upper bound on the number of children alive. - n_children_alive = sum(p.is_alive() for p in processes.values()) - n_children_to_stop = n_children_alive - n_sentinels_sent = 0 - # Send the right number of sentinels, to make sure all children are - # properly terminated. - while n_sentinels_sent < n_children_to_stop and n_children_alive > 0: - for i in range(n_children_to_stop - n_sentinels_sent): - try: - call_queue.put_nowait(None) - n_sentinels_sent += 1 - except Full: - break - n_children_alive = sum(p.is_alive() for p in processes.values()) + # A ctx.Queue that will be filled with _CallItems derived from + # _WorkItems for processing by the process workers. + self.call_queue = executor._call_queue - # Release the queue's resources as soon as possible. - call_queue.close() - call_queue.join_thread() - thread_wakeup.close() - # If .join() is not called on the created processes then - # some ctx.Queue methods may deadlock on Mac OS X. - for p in processes.values(): - p.join() + # A ctx.SimpleQueue of _ResultItems generated by the process workers. + self.result_queue = executor._result_queue - result_reader = result_queue._reader - wakeup_reader = thread_wakeup._reader - readers = [result_reader, wakeup_reader] + # A queue.Queue of work ids e.g. Queue([5, 6, ...]). + self.work_ids_queue = executor._work_ids - while True: - _add_call_item_to_queue(pending_work_items, - work_ids_queue, - call_queue) + # A dict mapping work ids to _WorkItems e.g. + # {5: <_WorkItem...>, 6: <_WorkItem...>, ...} + self.pending_work_items = executor._pending_work_items + + # Set this thread to be daemonized + super().__init__() + self.daemon = True + def run(self): + # Main loop for the executor manager thread. + + while True: + self.add_call_item_to_queue() + + result_item, is_broken, cause = self.wait_result_broken_or_wakeup() + + if is_broken: + self.terminate_broken(cause) + return + if result_item is not None: + self.process_result_item(result_item) + # Delete reference to result_item to avoid keeping references + # while waiting on new results. + del result_item + + if self.is_shutting_down(): + self.flag_executor_shutting_down() + + # Since no new work items can be added, it is safe to shutdown + # this thread if there are no pending work items. + if not self.pending_work_items: + self.join_executor_internals() + return + + def add_call_item_to_queue(self): + # Fills call_queue with _WorkItems from pending_work_items. + # This function never blocks. + while True: + if self.call_queue.full(): + return + try: + work_id = self.work_ids_queue.get(block=False) + except queue.Empty: + return + else: + work_item = self.pending_work_items[work_id] + + if work_item.future.set_running_or_notify_cancel(): + self.call_queue.put(_CallItem(work_id, + work_item.fn, + work_item.args, + work_item.kwargs), + block=True) + else: + del self.pending_work_items[work_id] + continue + + def wait_result_broken_or_wakeup(self): # Wait for a result to be ready in the result_queue while checking # that all worker processes are still running, or for a wake up # signal send. The wake up signals come either from new tasks being # submitted, from the executor being shutdown/gc-ed, or from the # shutdown of the python interpreter. - worker_sentinels = [p.sentinel for p in processes.values()] + result_reader = self.result_queue._reader + wakeup_reader = self.thread_wakeup._reader + readers = [result_reader, wakeup_reader] + worker_sentinels = [p.sentinel for p in self.processes.values()] ready = mp.connection.wait(readers + worker_sentinels) cause = None is_broken = True + result_item = None if result_reader in ready: try: result_item = result_reader.recv() @@ -381,97 +383,135 @@ def shutdown_worker(): elif wakeup_reader in ready: is_broken = False - result_item = None - thread_wakeup.clear() - if is_broken: - # Mark the process pool broken so that submits fail right now. - executor = executor_reference() - if executor is not None: - executor._broken = ('A child process terminated ' - 'abruptly, the process pool is not ' - 'usable anymore') - executor._shutdown_thread = True - executor = None - bpe = BrokenProcessPool("A process in the process pool was " - "terminated abruptly while the future was " - "running or pending.") - if cause is not None: - bpe.__cause__ = _RemoteTraceback( - f"\n'''\n{''.join(cause)}'''") - # All futures in flight must be marked failed - for work_id, work_item in pending_work_items.items(): - work_item.future.set_exception(bpe) - # Delete references to object. See issue16284 - del work_item - pending_work_items.clear() - # Terminate remaining workers forcibly: the queues or their - # locks may be in a dirty state and block forever. - for p in processes.values(): - p.terminate() - shutdown_worker() - return + self.thread_wakeup.clear() + + return result_item, is_broken, cause + + def process_result_item(self, result_item): + # Process the received a result_item. This can be either the PID of a + # worker that exited gracefully or a _ResultItem + if isinstance(result_item, int): # Clean shutdown of a worker using its PID # (avoids marking the executor broken) - assert shutting_down() - p = processes.pop(result_item) + assert self.is_shutting_down() + p = self.processes.pop(result_item) p.join() - if not processes: - shutdown_worker() + if not self.processes: + self.join_executor_internals() return - elif result_item is not None: - work_item = pending_work_items.pop(result_item.work_id, None) + else: + # Received a _ResultItem so mark the future as completed. + work_item = self.pending_work_items.pop(result_item.work_id, None) # work_item can be None if another process terminated (see above) if work_item is not None: if result_item.exception: work_item.future.set_exception(result_item.exception) else: work_item.future.set_result(result_item.result) - # Delete references to object. See issue16284 - del work_item - # Delete reference to result_item - del result_item - # Check whether we should start shutting down. - executor = executor_reference() + def is_shutting_down(self): + # Check whether we should start shutting down the executor. + executor = self.executor_reference() # No more work items can be added if: # - The interpreter is shutting down OR # - The executor that owns this worker has been collected OR # - The executor that owns this worker has been shutdown. - if shutting_down(): - try: - # Flag the executor as shutting down as early as possible if it - # is not gc-ed yet. - if executor is not None: - executor._shutdown_thread = True - # Unless there are pending work items, we have nothing to cancel. - if pending_work_items and executor._cancel_pending_futures: - # Cancel all pending futures and update pending_work_items - # to only have futures that are currently running. - new_pending_work_items = {} - for work_id, work_item in pending_work_items.items(): - if not work_item.future.cancel(): - new_pending_work_items[work_id] = work_item - - pending_work_items = new_pending_work_items - # Drain work_ids_queue since we no longer need to - # add items to the call queue. - while True: - try: - work_ids_queue.get_nowait() - except queue.Empty: - break + return (_global_shutdown or executor is None + or executor._shutdown_thread) - # Since no new work items can be added, it is safe to shutdown - # this thread if there are no pending work items. - if not pending_work_items: - shutdown_worker() - return - except Full: - # This is not a problem: we will eventually be woken up (in - # result_queue.get()) and be able to send a sentinel again. - pass - executor = None + def terminate_broken(self, cause): + # Terminate the executor because it is in a broken state. The cause + # argument can be used to display more information on the error that + # lead the executor into becoming broken. + + # Mark the process pool broken so that submits fail right now. + executor = self.executor_reference() + if executor is not None: + executor._broken = ('A child process terminated ' + 'abruptly, the process pool is not ' + 'usable anymore') + executor._shutdown_thread = True + executor = None + + # All pending tasks are to be marked failed with the following + # BrokenProcessPool error + bpe = BrokenProcessPool("A process in the process pool was " + "terminated abruptly while the future was " + "running or pending.") + if cause is not None: + bpe.__cause__ = _RemoteTraceback( + f"\n'''\n{''.join(cause)}'''") + + # Mark pending tasks as failed. + for work_id, work_item in self.pending_work_items.items(): + work_item.future.set_exception(bpe) + # Delete references to object. See issue16284 + del work_item + self.pending_work_items.clear() + + # Terminate remaining workers forcibly: the queues or their + # locks may be in a dirty state and block forever. + for p in self.processes.values(): + p.terminate() + + # clean up resources + self.join_executor_internals() + + def flag_executor_shutting_down(self): + # Flag the executor as shutting down and cancel remaining tasks if + # requested as early as possible if it is not gc-ed yet. + executor = self.executor_reference() + if executor is not None: + executor._shutdown_thread = True + # Cancel pending work items if requested. + if executor._cancel_pending_futures: + # Cancel all pending futures and update pending_work_items + # to only have futures that are currently running. + new_pending_work_items = {} + for work_id, work_item in self.pending_work_items.items(): + if not work_item.future.cancel(): + new_pending_work_items[work_id] = work_item + self.pending_work_items = new_pending_work_items + # Drain work_ids_queue since we no longer need to + # add items to the call queue. + while True: + try: + self.work_ids_queue.get_nowait() + except queue.Empty: + break + # Make sure we do this only once to not waste time looping + # on running processes over and over. + executor._cancel_pending_futures = False + + def shutdown_workers(self): + n_children_to_stop = self.get_n_children_alive() + n_sentinels_sent = 0 + # Send the right number of sentinels, to make sure all children are + # properly terminated. + while (n_sentinels_sent < n_children_to_stop + and self.get_n_children_alive() > 0): + for i in range(n_children_to_stop - n_sentinels_sent): + try: + self.call_queue.put_nowait(None) + n_sentinels_sent += 1 + except queue.Full: + break + + def join_executor_internals(self): + self.shutdown_workers() + # Release the queue's resources as soon as possible. + self.call_queue.close() + self.call_queue.join_thread() + self.thread_wakeup.close() + # If .join() is not called on the created processes then + # some ctx.Queue methods may deadlock on Mac OS X. + for p in self.processes.values(): + p.join() + + def get_n_children_alive(self): + # This is an upper bound on the number of children alive. + return sum(p.is_alive() for p in self.processes.values()) _system_limits_checked = False @@ -562,7 +602,7 @@ def __init__(self, max_workers=None, mp_context=None, self._initargs = initargs # Management thread - self._queue_management_thread = None + self._executor_manager_thread = None # Map of pids to processes self._processes = {} @@ -576,12 +616,12 @@ def __init__(self, max_workers=None, mp_context=None, self._cancel_pending_futures = False # _ThreadWakeup is a communication channel used to interrupt the wait - # of the main loop of queue_manager_thread from another thread (e.g. + # of the main loop of executor_manager_thread from another thread (e.g. # when calling executor.submit or executor.shutdown). We do not use the - # _result_queue to send the wakeup signal to the queue_manager_thread + # _result_queue to send wakeup signals to the executor_manager_thread # as it could result in a deadlock if a worker process dies with the # _result_queue write lock still acquired. - self._queue_management_thread_wakeup = _ThreadWakeup() + self._executor_manager_thread_wakeup = _ThreadWakeup() # Create communication channels for the executor # Make the call queue slightly larger than the number of processes to @@ -591,7 +631,7 @@ def __init__(self, max_workers=None, mp_context=None, self._call_queue = _SafeQueue( max_size=queue_size, ctx=self._mp_context, pending_work_items=self._pending_work_items, - thread_wakeup=self._queue_management_thread_wakeup) + thread_wakeup=self._executor_manager_thread_wakeup) # Killed worker processes can produce spurious "broken pipe" # tracebacks in the queue's own worker thread. But we detect killed # processes anyway, so silence the tracebacks. @@ -599,32 +639,14 @@ def __init__(self, max_workers=None, mp_context=None, self._result_queue = mp_context.SimpleQueue() self._work_ids = queue.Queue() - def _start_queue_management_thread(self): - if self._queue_management_thread is None: - # When the executor gets garbarge collected, the weakref callback - # will wake up the queue management thread so that it can terminate - # if there is no pending work item. - def weakref_cb(_, - thread_wakeup=self._queue_management_thread_wakeup): - mp.util.debug('Executor collected: triggering callback for' - ' QueueManager wakeup') - thread_wakeup.wakeup() + def _start_executor_manager_thread(self): + if self._executor_manager_thread is None: # Start the processes so that their sentinels are known. self._adjust_process_count() - self._queue_management_thread = threading.Thread( - target=_queue_management_worker, - args=(weakref.ref(self, weakref_cb), - self._processes, - self._pending_work_items, - self._work_ids, - self._call_queue, - self._result_queue, - self._queue_management_thread_wakeup), - name="QueueManagerThread") - self._queue_management_thread.daemon = True - self._queue_management_thread.start() - _threads_wakeups[self._queue_management_thread] = \ - self._queue_management_thread_wakeup + self._executor_manager_thread = _ExecutorManagerThread(self) + self._executor_manager_thread.start() + _threads_wakeups[self._executor_manager_thread] = \ + self._executor_manager_thread_wakeup def _adjust_process_count(self): for _ in range(len(self._processes), self._max_workers): @@ -654,9 +676,9 @@ def submit(self, fn, /, *args, **kwargs): self._work_ids.put(self._queue_count) self._queue_count += 1 # Wake up queue management thread - self._queue_management_thread_wakeup.wakeup() + self._executor_manager_thread_wakeup.wakeup() - self._start_queue_management_thread() + self._start_executor_manager_thread() return f submit.__doc__ = _base.Executor.submit.__doc__ @@ -694,20 +716,20 @@ def shutdown(self, wait=True, *, cancel_futures=False): self._cancel_pending_futures = cancel_futures self._shutdown_thread = True - if self._queue_management_thread: + if self._executor_manager_thread: # Wake up queue management thread - self._queue_management_thread_wakeup.wakeup() + self._executor_manager_thread_wakeup.wakeup() if wait: - self._queue_management_thread.join() + self._executor_manager_thread.join() # To reduce the risk of opening too many files, remove references to # objects that use file descriptors. - self._queue_management_thread = None + self._executor_manager_thread = None self._call_queue = None self._result_queue = None self._processes = None - if self._queue_management_thread_wakeup: - self._queue_management_thread_wakeup = None + if self._executor_manager_thread_wakeup: + self._executor_manager_thread_wakeup = None shutdown.__doc__ = _base.Executor.shutdown.__doc__ diff --git a/Lib/test/test_concurrent_futures.py b/Lib/test/test_concurrent_futures.py index a7381f9d13eb1..868415ab29916 100644 --- a/Lib/test/test_concurrent_futures.py +++ b/Lib/test/test_concurrent_futures.py @@ -508,15 +508,15 @@ def test_context_manager_shutdown(self): def test_del_shutdown(self): executor = futures.ProcessPoolExecutor(max_workers=5) res = executor.map(abs, range(-5, 5)) - queue_management_thread = executor._queue_management_thread + executor_manager_thread = executor._executor_manager_thread processes = executor._processes call_queue = executor._call_queue - queue_management_thread = executor._queue_management_thread + executor_manager_thread = executor._executor_manager_thread del executor # Make sure that all the executor resources were properly cleaned by # the shutdown process - queue_management_thread.join() + executor_manager_thread.join() for p in processes.values(): p.join() call_queue.join_thread() @@ -532,12 +532,12 @@ def test_shutdown_no_wait(self): res = executor.map(abs, range(-5, 5)) processes = executor._processes call_queue = executor._call_queue - queue_management_thread = executor._queue_management_thread + executor_manager_thread = executor._executor_manager_thread executor.shutdown(wait=False) # Make sure that all the executor resources were properly cleaned by # the shutdown process - queue_management_thread.join() + executor_manager_thread.join() for p in processes.values(): p.join() call_queue.join_thread() @@ -1139,11 +1139,11 @@ def test_shutdown_deadlock_pickle(self): mp_context=get_context(self.ctx)) as executor: self.executor = executor # Allow clean up in fail_on_deadlock - # Start the executor and get the queue_management_thread to collect + # Start the executor and get the executor_manager_thread to collect # the threads and avoid dangling thread that should be cleaned up # asynchronously. executor.submit(id, 42).result() - queue_manager = executor._queue_management_thread + executor_manager = executor._executor_manager_thread # Submit a task that fails at pickle and shutdown the executor # without waiting @@ -1154,7 +1154,7 @@ def test_shutdown_deadlock_pickle(self): # Make sure the executor is eventually shutdown and do not leave # dangling threads - queue_manager.join() + executor_manager.join() create_executor_tests(ExecutorDeadlockTest, diff --git a/Misc/NEWS.d/next/Library/2020-02-28-12-59-30.bpo-39678.3idfxM.rst b/Misc/NEWS.d/next/Library/2020-02-28-12-59-30.bpo-39678.3idfxM.rst new file mode 100644 index 0000000000000..8b18e2259c5c7 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-02-28-12-59-30.bpo-39678.3idfxM.rst @@ -0,0 +1,2 @@ +Refactor queue_manager in :class:`concurrent.futures.ProcessPoolExecutor` to +make it easier to maintain. \ No newline at end of file From webhook-mailer at python.org Sun Mar 1 16:26:47 2020 From: webhook-mailer at python.org (Andy Lester) Date: Sun, 01 Mar 2020 21:26:47 -0000 Subject: [Python-checkins] closes bpo-39803: Remove unused str from _PyLong_FormatAdvancedWriter. (GH-18709) Message-ID: https://github.com/python/cpython/commit/3fe9117779f0c75f7a0c3d7748c5bf281fbc1e4c commit: 3fe9117779f0c75f7a0c3d7748c5bf281fbc1e4c branch: master author: Andy Lester committer: GitHub date: 2020-03-01T13:26:43-08:00 summary: closes bpo-39803: Remove unused str from _PyLong_FormatAdvancedWriter. (GH-18709) files: M Python/formatter_unicode.c diff --git a/Python/formatter_unicode.c b/Python/formatter_unicode.c index 41a2478e0a817..705e12dd446da 100644 --- a/Python/formatter_unicode.c +++ b/Python/formatter_unicode.c @@ -1458,7 +1458,7 @@ _PyLong_FormatAdvancedWriter(_PyUnicodeWriter *writer, PyObject *format_spec, Py_ssize_t start, Py_ssize_t end) { - PyObject *tmp = NULL, *str = NULL; + PyObject *tmp = NULL; InternalFormatSpec format; int result = -1; @@ -1511,7 +1511,6 @@ _PyLong_FormatAdvancedWriter(_PyUnicodeWriter *writer, done: Py_XDECREF(tmp); - Py_XDECREF(str); return result; } From webhook-mailer at python.org Sun Mar 1 19:08:33 2020 From: webhook-mailer at python.org (Pablo Galindo) Date: Mon, 02 Mar 2020 00:08:33 -0000 Subject: [Python-checkins] [3.8] bpo-39815: add cached_property to all (GH-18726) (GH-18728) Message-ID: https://github.com/python/cpython/commit/12b714391e485d0150b343b114999bae4a0d34dd commit: 12b714391e485d0150b343b114999bae4a0d34dd branch: 3.8 author: Pablo Galindo committer: GitHub date: 2020-03-02T00:08:29Z summary: [3.8] bpo-39815: add cached_property to all (GH-18726) (GH-18728) Automerge-Triggered-By: @pablogsal. (cherry picked from commit 217dce9ee6e3cf27a0cedbe1e4a6455776373ec2) Co-authored-by: Hakan ?elik files: M Lib/functools.py M Misc/ACKS diff --git a/Lib/functools.py b/Lib/functools.py index b41dea79083fc..4cde5f590cf29 100644 --- a/Lib/functools.py +++ b/Lib/functools.py @@ -11,7 +11,8 @@ __all__ = ['update_wrapper', 'wraps', 'WRAPPER_ASSIGNMENTS', 'WRAPPER_UPDATES', 'total_ordering', 'cmp_to_key', 'lru_cache', 'reduce', 'partial', - 'partialmethod', 'singledispatch', 'singledispatchmethod'] + 'partialmethod', 'singledispatch', 'singledispatchmethod', + "cached_property"] from abc import get_cache_token from collections import namedtuple diff --git a/Misc/ACKS b/Misc/ACKS index 8fd4df5bf3f19..ef13d55e756bd 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -362,6 +362,7 @@ Tom Culliton Ra?l Cumplido Antonio Cuni Brian Curtin +Hakan Celik Paul Dagnelie Lisandro Dalcin Darren Dale From webhook-mailer at python.org Sun Mar 1 22:14:13 2020 From: webhook-mailer at python.org (Pablo Galindo) Date: Mon, 02 Mar 2020 03:14:13 -0000 Subject: [Python-checkins] bpo-39199: Add descriptions of non-deprecated nodes to the AST module documentation (GH-17812) Message-ID: https://github.com/python/cpython/commit/114081f8adafa16283df30c456716a1bef4758d0 commit: 114081f8adafa16283df30c456716a1bef4758d0 branch: master author: Pablo Galindo committer: GitHub date: 2020-03-02T03:14:06Z summary: bpo-39199: Add descriptions of non-deprecated nodes to the AST module documentation (GH-17812) Adapted from https://greentreesnakes.readthedocs.io Co-authored-by: Karthikeyan Singaravelan Co-authored-by: Carol Willing files: M Doc/library/ast.rst diff --git a/Doc/library/ast.rst b/Doc/library/ast.rst index bfd571deb4fd1..ea3057867b0f0 100644 --- a/Doc/library/ast.rst +++ b/Doc/library/ast.rst @@ -7,6 +7,10 @@ .. sectionauthor:: Martin v. L?wis .. sectionauthor:: Georg Brandl +.. testsetup:: + + import ast + **Source code:** :source:`Lib/ast.py` -------------- @@ -23,6 +27,17 @@ classes all inherit from :class:`ast.AST`. An abstract syntax tree can be compiled into a Python code object using the built-in :func:`compile` function. +.. _abstract-grammar: + +Abstract Grammar +---------------- + +The abstract grammar is currently defined as follows: + +.. literalinclude:: ../../Parser/Python.asdl + :language: none + + Node classes ------------ @@ -112,16 +127,1492 @@ Node classes but they will be removed in future Python releases. In the meanwhile, instantiating them will return an instance of a different class. +Literals +^^^^^^^^ + +.. class:: Constant(value) + + A constant value. The ``value`` attribute of the ``Constant`` literal contains the + Python object it represents. The values represented can be simple types + such as a number, string or ``None``, but also immutable container types + (tuples and frozensets) if all of their elements are constant. + + .. doctest:: + + >>> print(ast.dump(ast.parse("123"), indent=4)) + Module( + body=[ + Expr( + value=Constant(value=123, kind=None))], + type_ignores=[]) + + +.. class:: FormattedValue(value, conversion, format_spec) + + Node representing a single formatting field in an f-string. If the string + contains a single formatting field and nothing else the node can be + isolated otherwise it appears in :class:`JoinedStr`. + + * ``value`` is any expression node (such as a literal, a variable, or a + function call). + * ``conversion`` is an integer: + + * -1: no formatting + * 115: ``!s`` string formatting + * 114: ``!r`` repr formatting + * 97: ``!a`` ascii formatting + + * ``format_spec`` is a :class:`JoinedStr` node representing the formatting + of the value, or ``None`` if no format was specified. Both + ``conversion`` and ``format_spec`` can be set at the same time. + + +.. class:: JoinedStr(values) + + An f-string, comprising a series of :class:`FormattedValue` and :class:`Constant` + nodes. + + .. doctest:: + + >>> print(ast.dump(ast.parse('f"sin({a}) is {sin(a):.3}"'), indent=4)) + Module( + body=[ + Expr( + value=JoinedStr( + values=[ + Constant(value='sin(', kind=None), + FormattedValue( + value=Name(id='a', ctx=Load()), + conversion=-1, + format_spec=None), + Constant(value=') is ', kind=None), + FormattedValue( + value=Call( + func=Name(id='sin', ctx=Load()), + args=[ + Name(id='a', ctx=Load())], + keywords=[]), + conversion=-1, + format_spec=JoinedStr( + values=[ + Constant(value='.3', kind=None)]))]))], + type_ignores=[]) + + +.. class:: List(elts, ctx) + Tuple(elts, ctx) + + A list or tuple. ``elts`` holds a list of nodes representing the elements. + ``ctx`` is :class:`Store` if the container is an assignment target (i.e. + ``(x,y)=something``), and :class:`Load` otherwise. + + .. doctest:: + + >>> print(ast.dump(ast.parse("[1, 2, 3]"), indent=4)) + Module( + body=[ + Expr( + value=List( + elts=[ + Constant(value=1, kind=None), + Constant(value=2, kind=None), + Constant(value=3, kind=None)], + ctx=Load()))], + type_ignores=[]) + + >>> print(ast.dump(ast.parse("(1, 2, 3)"), indent=4)) + Module( + body=[ + Expr( + value=Tuple( + elts=[ + Constant(value=1, kind=None), + Constant(value=2, kind=None), + Constant(value=3, kind=None)], + ctx=Load()))], + type_ignores=[]) + + +.. class:: Set(elts) + + A set. ``elts`` holds a list of nodes representing the set's elements. + + .. doctest:: + + >>> print(ast.dump(ast.parse("{1, 2, 3}"), indent=4)) + Module( + body=[ + Expr( + value=Set( + elts=[ + Constant(value=1, kind=None), + Constant(value=2, kind=None), + Constant(value=3, kind=None)]))], + type_ignores=[]) + + +.. class:: Dict(keys, values) + + A dictionary. ``keys`` and ``values`` hold lists of nodes representing the + keys and the values respectively, in matching order (what would be returned + when calling :code:`dictionary.keys()` and :code:`dictionary.values()`). + + When doing dictionary unpacking using dictionary literals the expression to be + expanded goes in the ``values`` list, with a ``None`` at the corresponding + position in ``keys``. + + .. doctest:: + + >>> print(ast.dump(ast.parse("{'a':1, **d}"), indent=4)) + Module( + body=[ + Expr( + value=Dict( + keys=[ + Constant(value='a', kind=None), + None], + values=[ + Constant(value=1, kind=None), + Name(id='d', ctx=Load())]))], + type_ignores=[]) + + +Variables +^^^^^^^^^ + +.. class:: Name(id, ctx) + + A variable name. ``id`` holds the name as a string, and ``ctx`` is one of + the following types. + + +.. class:: Load() + Store() + Del() + + Variable references can be used to load the value of a variable, to assign + a new value to it, or to delete it. Variable references are given a context + to distinguish these cases. + + .. doctest:: + + >>> print(ast.dump(ast.parse('a'), indent=4)) + Module( + body=[ + Expr( + value=Name(id='a', ctx=Load()))], + type_ignores=[]) + + >>> print(ast.dump(ast.parse('a = 1'), indent=4)) + Module( + body=[ + Assign( + targets=[ + Name(id='a', ctx=Store())], + value=Constant(value=1, kind=None), + type_comment=None)], + type_ignores=[]) + + >>> print(ast.dump(ast.parse('del a'), indent=4)) + Module( + body=[ + Delete( + targets=[ + Name(id='a', ctx=Del())])], + type_ignores=[]) + + +.. class:: Starred(value, ctx) + + A ``*var`` variable reference. ``value`` holds the variable, typically a + :class:`Name` node. This type must be used when building a :class:`Call` + node with ``*args``. + + .. doctest:: -.. _abstract-grammar: + >>> print(ast.dump(ast.parse('a, *b = it'), indent=4)) + Module( + body=[ + Assign( + targets=[ + Tuple( + elts=[ + Name(id='a', ctx=Store()), + Starred( + value=Name(id='b', ctx=Store()), + ctx=Store())], + ctx=Store())], + value=Name(id='it', ctx=Load()), + type_comment=None)], + type_ignores=[]) -Abstract Grammar ----------------- -The abstract grammar is currently defined as follows: +Expressions +^^^^^^^^^^^ -.. literalinclude:: ../../Parser/Python.asdl - :language: none +.. class:: Expr(value) + + When an expression, such as a function call, appears as a statement by itself + with its return value not used or stored, it is wrapped in this container. + ``value`` holds one of the other nodes in this section, a :class:`Constant`, a + :class:`Name`, a :class:`Lambda`, a :class:`Yield` or :class:`YieldFrom` node. + + .. doctest:: + + >>> print(ast.dump(ast.parse('-a'), indent=4)) + Module( + body=[ + Expr( + value=UnaryOp( + op=USub(), + operand=Name(id='a', ctx=Load())))], + type_ignores=[]) + + +.. class:: UnaryOp(op, operand) + + A unary operation. ``op`` is the operator, and ``operand`` any expression + node. + + +.. class:: UAdd + USub + Not + Invert + + Unary operator tokens. :class:`Not` is the ``not`` keyword, :class:`Invert` + is the ``~`` operator. + + .. doctest:: + + >>> print(ast.dump(ast.parse("not x"), indent=4)) + Module( + body=[ + Expr( + value=UnaryOp( + op=Not(), + operand=Name(id='x', ctx=Load())))], + type_ignores=[]) + + +.. class:: BinOp(left, op, right) + + A binary operation (like addition or division). ``op`` is the operator, and + ``left`` and ``right`` are any expression nodes. + + .. doctest:: + + >>> print(ast.dump(ast.parse("x + y"), indent=4)) + Module( + body=[ + Expr( + value=BinOp( + left=Name(id='x', ctx=Load()), + op=Add(), + right=Name(id='y', ctx=Load())))], + type_ignores=[]) + + +.. class:: Add + Sub + Mult + Div + FloorDiv + Mod + Pow + LShift + RShift + BitOr + BitXor + BitAnd + MatMult + + Binary operator tokens. + + +.. class:: BoolOp(op, values) + + A boolean operation, 'or' or 'and'. ``op`` is :class:`Or` or :class:`And`. + ``values`` are the values involved. Consecutive operations with the same + operator, such as ``a or b or c``, are collapsed into one node with several + values. + + This doesn't include ``not``, which is a :class:`UnaryOp`. + + .. doctest:: + + >>> print(ast.dump(ast.parse("x or y"), indent=4)) + Module( + body=[ + Expr( + value=BoolOp( + op=Or(), + values=[ + Name(id='x', ctx=Load()), + Name(id='y', ctx=Load())]))], + type_ignores=[]) + + +.. class:: And + Or + + Boolean operator tokens. + + +.. class:: Compare(left, ops, comparators) + + A comparison of two or more values. ``left`` is the first value in the + comparison, ``ops`` the list of operators, and ``comparators`` the list + of values after the first element in the comparison. + + .. doctest:: + + >>> print(ast.dump(ast.parse("1 < a < 10"), indent=4)) + Module( + body=[ + Expr( + value=Compare( + left=Constant(value=1, kind=None), + ops=[ + Lt(), + Lt()], + comparators=[ + Name(id='a', ctx=Load()), + Constant(value=10, kind=None)]))], + type_ignores=[]) + + +.. class:: Eq + NotEq + Lt + LtE + Gt + GtE + Is + IsNot + In + NotIn + + Comparison operator tokens. + + +.. class:: Call(func, args, keywords, starargs, kwargs) + + A function call. ``func`` is the function, which will often be a + :class:`Name` or :class:`Attribute` object. Of the arguments: + + * ``args`` holds a list of the arguments passed by position. + * ``keywords`` holds a list of :class:`keyword` objects representing + arguments passed by keyword. + + When creating a ``Call`` node, ``args`` and ``keywords`` are required, but + they can be empty lists. ``starargs`` and ``kwargs`` are optional. + + .. doctest:: + + >>> print(ast.dump(ast.parse('func(a, b=c, *d, **e)'), indent=4)) + Module( + body=[ + Expr( + value=Call( + func=Name(id='func', ctx=Load()), + args=[ + Name(id='a', ctx=Load()), + Starred( + value=Name(id='d', ctx=Load()), + ctx=Load())], + keywords=[ + keyword( + arg='b', + value=Name(id='c', ctx=Load())), + keyword( + arg=None, + value=Name(id='e', ctx=Load()))]))], + type_ignores=[]) + + +.. class:: keyword(arg, value) + + A keyword argument to a function call or class definition. ``arg`` is a raw + string of the parameter name, ``value`` is a node to pass in. + + +.. class:: IfExp(test, body, orelse) + + An expression such as ``a if b else c``. Each field holds a single node, so + in the following example, all three are :class:`Name` nodes. + + .. doctest:: + + >>> print(ast.dump(ast.parse("a if b else c"), indent=4)) + Module( + body=[ + Expr( + value=IfExp( + test=Name(id='b', ctx=Load()), + body=Name(id='a', ctx=Load()), + orelse=Name(id='c', ctx=Load())))], + type_ignores=[]) + + +.. class:: Attribute(value, attr, ctx) + + Attribute access, e.g. ``d.keys``. ``value`` is a node, typically a + :class:`Name`. ``attr`` is a bare string giving the name of the attribute, + and ``ctx`` is :class:`Load`, :class:`Store` or :class:`Del` according to how + the attribute is acted on. + + .. doctest:: + + >>> print(ast.dump(ast.parse('snake.colour'), indent=4)) + Module( + body=[ + Expr( + value=Attribute( + value=Name(id='snake', ctx=Load()), + attr='colour', + ctx=Load()))], + type_ignores=[]) + + +.. class:: NamedExpr(target, value) + + A named expression. This AST node is produced by the assignment expressions + operator (also known as the walrus operator). As opposed to the :class:`Assign` + node in which the first argument can be multiple nodes, in this case both + ``target`` and ``value`` must be single nodes. + + .. doctest:: + + >>> print(ast.dump(ast.parse("(x := 4)"), indent=4)) + Module( + body=[ + Expr( + value=NamedExpr( + target=Name(id='x', ctx=Store()), + value=Constant(value=4, kind=None)))], + type_ignores=[]) + + +Subscripting +~~~~~~~~~~~~ + +.. class:: Subscript(value, slice, ctx) + + A subscript, such as ``l[1]``. ``value`` is the object, often a + :class:`Name`. ``slice`` is one of :class:`Index`, :class:`Slice` or + :class:`ExtSlice`. ``ctx`` is :class:`Load`, :class:`Store` or :class:`Del` + according to the action performed with the subscript. + + +.. class:: Index(value) + + Simple subscripting with a single value + + .. doctest:: + + >>> print(ast.dump(ast.parse('l[1]'), indent=4)) + Module( + body=[ + Expr( + value=Subscript( + value=Name(id='l', ctx=Load()), + slice=Index( + value=Constant(value=1, kind=None)), + ctx=Load()))], + type_ignores=[]) + + +.. class:: Slice(lower, upper, step) + + Regular slicing (on the form x:y). + + .. doctest:: + + >>> print(ast.dump(ast.parse('l[1:2]'), indent=4)) + Module( + body=[ + Expr( + value=Subscript( + value=Name(id='l', ctx=Load()), + slice=Slice( + lower=Constant(value=1, kind=None), + upper=Constant(value=2, kind=None), + step=None), + ctx=Load()))], + type_ignores=[]) + + +.. class:: ExtSlice(dims) + + Advanced slicing. ``dims`` holds a list of :class:`Slice` and + :class:`Index` nodes + + .. doctest:: + + >>> print(ast.dump(ast.parse('l[1:2, 3]'), indent=4)) + Module( + body=[ + Expr( + value=Subscript( + value=Name(id='l', ctx=Load()), + slice=ExtSlice( + dims=[ + Slice( + lower=Constant(value=1, kind=None), + upper=Constant(value=2, kind=None), + step=None), + Index( + value=Constant(value=3, kind=None))]), + ctx=Load()))], + type_ignores=[]) + + +Comprehensions +~~~~~~~~~~~~~~ + +.. class:: ListComp(elt, generators) + SetComp(elt, generators) + GeneratorExp(elt, generators) + DictComp(key, value, generators) + + List and set comprehensions, generator expressions, and dictionary + comprehensions. ``elt`` (or ``key`` and ``value``) is a single node + representing the part that will be evaluated for each item. + + ``generators`` is a list of :class:`comprehension` nodes. + + .. doctest:: + + >>> print(ast.dump(ast.parse("[x for x in numbers]"), indent=4)) + Module( + body=[ + Expr( + value=ListComp( + elt=Name(id='x', ctx=Load()), + generators=[ + comprehension( + target=Name(id='x', ctx=Store()), + iter=Name(id='numbers', ctx=Load()), + ifs=[], + is_async=0)]))], + type_ignores=[]) + + >>> print(ast.dump(ast.parse("{x: x**2 for x in numbers}"), indent=4)) + Module( + body=[ + Expr( + value=DictComp( + key=Name(id='x', ctx=Load()), + value=BinOp( + left=Name(id='x', ctx=Load()), + op=Pow(), + right=Constant(value=2, kind=None)), + generators=[ + comprehension( + target=Name(id='x', ctx=Store()), + iter=Name(id='numbers', ctx=Load()), + ifs=[], + is_async=0)]))], + type_ignores=[]) + + >>> print(ast.dump(ast.parse("{x for x in numbers}"), indent=4)) + Module( + body=[ + Expr( + value=SetComp( + elt=Name(id='x', ctx=Load()), + generators=[ + comprehension( + target=Name(id='x', ctx=Store()), + iter=Name(id='numbers', ctx=Load()), + ifs=[], + is_async=0)]))], + type_ignores=[]) + + +.. class:: comprehension(target, iter, ifs, is_async) + + One ``for`` clause in a comprehension. ``target`` is the reference to use for + each element - typically a :class:`Name` or :class:`Tuple` node. ``iter`` + is the object to iterate over. ``ifs`` is a list of test expressions: each + ``for`` clause can have multiple ``ifs``. + + ``is_async`` indicates a comprehension is asynchronous (using an + ``async for`` instead of ``for``). The value is an integer (0 or 1). + + .. doctest:: + + >>> print(ast.dump(ast.parse("[ord(c) for line in file for c in line]", mode='eval'), + ... indent=4)) # Multiple comprehensions in one. + Expression( + body=ListComp( + elt=Call( + func=Name(id='ord', ctx=Load()), + args=[ + Name(id='c', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='line', ctx=Store()), + iter=Name(id='file', ctx=Load()), + ifs=[], + is_async=0), + comprehension( + target=Name(id='c', ctx=Store()), + iter=Name(id='line', ctx=Load()), + ifs=[], + is_async=0)])) + + >>> print(ast.dump(ast.parse("(n**2 for n in it if n>5 if n<10)", mode='eval'), + ... indent=4)) # generator comprehension + Expression( + body=GeneratorExp( + elt=BinOp( + left=Name(id='n', ctx=Load()), + op=Pow(), + right=Constant(value=2, kind=None)), + generators=[ + comprehension( + target=Name(id='n', ctx=Store()), + iter=Name(id='it', ctx=Load()), + ifs=[ + Compare( + left=Name(id='n', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Constant(value=5, kind=None)]), + Compare( + left=Name(id='n', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Constant(value=10, kind=None)])], + is_async=0)])) + + >>> print(ast.dump(ast.parse("async def f():" + ... " return [i async for i in soc]"), + ... indent=4)) # Async comprehension + Module( + body=[ + AsyncFunctionDef( + name='f', + args=arguments( + posonlyargs=[], + args=[], + vararg=None, + kwonlyargs=[], + kw_defaults=[], + kwarg=None, + defaults=[]), + body=[ + Return( + value=ListComp( + elt=Name(id='i', ctx=Load()), + generators=[ + comprehension( + target=Name(id='i', ctx=Store()), + iter=Name(id='soc', ctx=Load()), + ifs=[], + is_async=1)]))], + decorator_list=[], + returns=None, + type_comment=None)], + type_ignores=[]) + +Statements +^^^^^^^^^^ + +.. class:: Assign(targets, value, type_comment) + + An assignment. ``targets`` is a list of nodes, and ``value`` is a single node. + + Multiple nodes in ``targets`` represents assigning the same value to each. + Unpacking is represented by putting a :class:`Tuple` or :class:`List` + within ``targets``. + + .. attribute:: type_comment + + ``type_comment`` is an optional string with the type annotation as a comment. + + .. doctest:: + + >>> print(ast.dump(ast.parse("a = b = 1"), indent=4)) # Multiple assignment + Module( + body=[ + Assign( + targets=[ + Name(id='a', ctx=Store()), + Name(id='b', ctx=Store())], + value=Constant(value=1, kind=None), + type_comment=None)], + type_ignores=[]) + + >>> print(ast.dump(ast.parse("a,b = c"), indent=4)) # Unpacking + Module( + body=[ + Assign( + targets=[ + Tuple( + elts=[ + Name(id='a', ctx=Store()), + Name(id='b', ctx=Store())], + ctx=Store())], + value=Name(id='c', ctx=Load()), + type_comment=None)], + type_ignores=[]) + + +.. class:: AnnAssign(target, annotation, value, simple) + + An assignment with a type annotation. ``target`` is a single node and can + be a :class:`Name`, a :class:`Attribute` or a :class:`Subscript`. + ``annotation`` is the annotation, such as a :class:`Constant` or :class:`Name` + node. ``value`` is a single optional node. ``simple`` is a boolean integer + set to True for a :class:`Name` node in ``target`` that do not appear in + between parenthesis and are hence pure names and not expressions. + + .. doctest:: + + >>> print(ast.dump(ast.parse("c: int"), indent=4)) + Module( + body=[ + AnnAssign( + target=Name(id='c', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + value=None, + simple=1)], + type_ignores=[]) + + >>> print(ast.dump(ast.parse("(a): int = 1"), indent=4)) # Annotation with parenthesis + Module( + body=[ + AnnAssign( + target=Name(id='a', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + value=Constant(value=1, kind=None), + simple=0)], + type_ignores=[]) + + >>> print(ast.dump(ast.parse("a.b: int"), indent=4)) # Attribute annotation + Module( + body=[ + AnnAssign( + target=Attribute( + value=Name(id='a', ctx=Load()), + attr='b', + ctx=Store()), + annotation=Name(id='int', ctx=Load()), + value=None, + simple=0)], + type_ignores=[]) + + >>> print(ast.dump(ast.parse("a[1]: int"), indent=4)) # Subscript annotation + Module( + body=[ + AnnAssign( + target=Subscript( + value=Name(id='a', ctx=Load()), + slice=Index( + value=Constant(value=1, kind=None)), + ctx=Store()), + annotation=Name(id='int', ctx=Load()), + value=None, + simple=0)], + type_ignores=[]) + + +.. class:: AugAssign(target, op, value) + + Augmented assignment, such as ``a += 1``. In the following example, + ``target`` is a :class:`Name` node for ``x`` (with the :class:`Store` + context), ``op`` is :class:`Add`, and ``value`` is a :class:`Constant` with + value for 1. + + The ``target`` attribute connot be of class :class:`Tuple` or :class:`List`, + unlike the targets of :class:`Assign`. + + .. doctest:: + + >>> print(ast.dump(ast.parse("x += 2"), indent=4)) + Module( + body=[ + AugAssign( + target=Name(id='x', ctx=Store()), + op=Add(), + value=Constant(value=2, kind=None))], + type_ignores=[]) + + +.. class:: Raise(exc, cause) + + A ``raise`` statement. ``exc`` is the exception object to be raised, normally a + :class:`Call` or :class:`Name`, or ``None`` for a standalone ``raise``. + ``cause`` is the optional part for ``y`` in ``raise x from y``. + + .. doctest:: + + >>> print(ast.dump(ast.parse("raise x from y"), indent=4)) + Module( + body=[ + Raise( + exc=Name(id='x', ctx=Load()), + cause=Name(id='y', ctx=Load()))], + type_ignores=[]) + + +.. class:: Assert(test, msg) + + An assertion. ``test`` holds the condition, such as a :class:`Compare` node. + ``msg`` holds the failure message. + + .. doctest:: + + >>> print(ast.dump(ast.parse("assert x,y"), indent=4)) + Module( + body=[ + Assert( + test=Name(id='x', ctx=Load()), + msg=Name(id='y', ctx=Load()))], + type_ignores=[]) + + +.. class:: Delete(targets) + + Represents a ``del`` statement. ``targets`` is a list of nodes, such as + :class:`Name`, :class:`Attribute` or :class:`Subscript` nodes. + + .. doctest:: + + >>> print(ast.dump(ast.parse("del x,y,z"), indent=4)) + Module( + body=[ + Delete( + targets=[ + Name(id='x', ctx=Del()), + Name(id='y', ctx=Del()), + Name(id='z', ctx=Del())])], + type_ignores=[]) + + +.. class:: Pass() + + A ``pass`` statement. + + .. doctest:: + + >>> print(ast.dump(ast.parse("pass"), indent=4)) + Module( + body=[ + Pass()], + type_ignores=[]) + + +Other statements which are only applicable inside functions or loops are +described in other sections. + +Imports +~~~~~~~ + +.. class:: Import(names) + + An import statement. ``names`` is a list of :class:`alias` nodes. + + .. doctest:: + + >>> print(ast.dump(ast.parse("import x,y,z"), indent=4)) + Module( + body=[ + Import( + names=[ + alias(name='x', asname=None), + alias(name='y', asname=None), + alias(name='z', asname=None)])], + type_ignores=[]) + + +.. class:: ImportFrom(module, names, level) + + Represents ``from x import y``. ``module`` is a raw string of the 'from' name, + without any leading dots, or ``None`` for statements such as ``from . import foo``. + ``level`` is an integer holding the level of the relative import (0 means + absolute import). + + .. doctest:: + + >>> print(ast.dump(ast.parse("from y import x,y,z"), indent=4)) + Module( + body=[ + ImportFrom( + module='y', + names=[ + alias(name='x', asname=None), + alias(name='y', asname=None), + alias(name='z', asname=None)], + level=0)], + type_ignores=[]) + + +.. class:: alias(name, asname) + + Both parameters are raw strings of the names. ``asname`` can be ``None`` if + the regular name is to be used. + + .. doctest:: + + >>> print(ast.dump(ast.parse("from ..foo.bar import a as b, c"), indent=4)) + Module( + body=[ + ImportFrom( + module='foo.bar', + names=[ + alias(name='a', asname='b'), + alias(name='c', asname=None)], + level=2)], + type_ignores=[]) + +Control flow +^^^^^^^^^^^^ + +.. note:: + Optional clauses such as ``else`` are stored as an empty list if they're + not present. + +.. class:: If(test, body, orelse) + + An ``if`` statement. ``test`` holds a single node, such as a :class:`Compare` + node. ``body`` and ``orelse`` each hold a list of nodes. + + ``elif`` clauses don't have a special representation in the AST, but rather + appear as extra :class:`If` nodes within the ``orelse`` section of the + previous one. + + .. doctest:: + + >>> print(ast.dump(ast.parse(""" + ... if x: + ... ... + ... elif y: + ... ... + ... else: + ... ... + ... """), indent=4)) + Module( + body=[ + If( + test=Name(id='x', ctx=Load()), + body=[ + Expr( + value=Constant(value=Ellipsis, kind=None))], + orelse=[ + If( + test=Name(id='y', ctx=Load()), + body=[ + Expr( + value=Constant(value=Ellipsis, kind=None))], + orelse=[ + Expr( + value=Constant(value=Ellipsis, kind=None))])])], + type_ignores=[]) + + +.. class:: For(target, iter, body, orelse, type_comment) + + A ``for`` loop. ``target`` holds the variable(s) the loop assigns to, as a + single :class:`Name`, :class:`Tuple` or :class:`List` node. ``iter`` holds + the item to be looped over, again as a single node. ``body`` and ``orelse`` + contain lists of nodes to execute. Those in ``orelse`` are executed if the + loop finishes normally, rather than via a ``break`` statement. + + .. attribute:: type_comment + + ``type_comment`` is an optional string with the type annotation as a comment. + + .. doctest:: + + >>> print(ast.dump(ast.parse(""" + ... for x in y: + ... ... + ... else: + ... ... + ... """), indent=4)) + Module( + body=[ + For( + target=Name(id='x', ctx=Store()), + iter=Name(id='y', ctx=Load()), + body=[ + Expr( + value=Constant(value=Ellipsis, kind=None))], + orelse=[ + Expr( + value=Constant(value=Ellipsis, kind=None))], + type_comment=None)], + type_ignores=[]) + + +.. class:: While(test, body, orelse) + + A ``while`` loop. ``test`` holds the condition, such as a :class:`Compare` + node. + + .. doctest:: + + >> print(ast.dump(ast.parse(""" + ... while x: + ... ... + ... else: + ... ... + ... """), indent=4)) + Module( + body=[ + While( + test=Name(id='x', ctx=Load()), + body=[ + Expr( + value=Constant(value=Ellipsis, kind=None))], + orelse=[ + Expr( + value=Constant(value=Ellipsis, kind=None))])], + type_ignores=[]) + + +.. class:: Break + Continue + + The ``break`` and ``continue`` statements. + + .. doctest:: + + >>> print(ast.dump(ast.parse("""\ + ... for a in b: + ... if a > 5: + ... break + ... else: + ... continue + ... + ... """), indent=4)) + Module( + body=[ + For( + target=Name(id='a', ctx=Store()), + iter=Name(id='b', ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='a', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Constant(value=5, kind=None)]), + body=[ + Break()], + orelse=[ + Continue()])], + orelse=[], + type_comment=None)], + type_ignores=[]) + + +.. class:: Try(body, handlers, orelse, finalbody) + + ``try`` blocks. All attributes are list of nodes to execute, except for + ``handlers``, which is a list of :class:`ExceptHandler` nodes. + + .. doctest:: + + >>> print(ast.dump(ast.parse(""" + ... try: + ... ... + ... except Exception: + ... ... + ... except OtherException as e: + ... ... + ... else: + ... ... + ... finally: + ... ... + ... """), indent=4)) + Module( + body=[ + Try( + body=[ + Expr( + value=Constant(value=Ellipsis, kind=None))], + handlers=[ + ExceptHandler( + type=Name(id='Exception', ctx=Load()), + name=None, + body=[ + Expr( + value=Constant(value=Ellipsis, kind=None))]), + ExceptHandler( + type=Name(id='OtherException', ctx=Load()), + name='e', + body=[ + Expr( + value=Constant(value=Ellipsis, kind=None))])], + orelse=[ + Expr( + value=Constant(value=Ellipsis, kind=None))], + finalbody=[ + Expr( + value=Constant(value=Ellipsis, kind=None))])], + type_ignores=[]) + + +.. class:: ExceptHandler(type, name, body) + + A single ``except`` clause. ``type`` is the exception type it will match, + typically a :class:`Name` node (or ``None`` for a catch-all ``except:`` clause). + ``name`` is a raw string for the name to hold the exception, or ``None`` if + the clause doesn't have ``as foo``. ``body`` is a list of nodes. + + .. doctest:: + + >>> print(ast.dump(ast.parse("""\ + ... try: + ... a + 1 + ... except TypeError: + ... pass + ... """), indent=4)) + Module( + body=[ + Try( + body=[ + Expr( + value=BinOp( + left=Name(id='a', ctx=Load()), + op=Add(), + right=Constant(value=1, kind=None)))], + handlers=[ + ExceptHandler( + type=Name(id='TypeError', ctx=Load()), + name=None, + body=[ + Pass()])], + orelse=[], + finalbody=[])], + type_ignores=[]) + + +.. class:: With(items, body, type_comment) + + A ``with`` block. ``items`` is a list of :class:`withitem` nodes representing + the context managers, and ``body`` is the indented block inside the context. + + .. attribute:: type_comment + + ``type_comment`` is an optional string with the type annotation as a comment. + + +.. class:: withitem(context_expr, optional_vars) + + A single context manager in a ``with`` block. ``context_expr`` is the context + manager, often a :class:`Call` node. ``optional_vars`` is a :class:`Name`, + :class:`Tuple` or :class:`List` for the ``as foo`` part, or ``None`` if that + isn't used. + + .. doctest:: + + >>> print(ast.dump(ast.parse("""\ + ... with a as b, c as d: + ... something(b, d) + ... """), indent=4)) + Module( + body=[ + With( + items=[ + withitem( + context_expr=Name(id='a', ctx=Load()), + optional_vars=Name(id='b', ctx=Store())), + withitem( + context_expr=Name(id='c', ctx=Load()), + optional_vars=Name(id='d', ctx=Store()))], + body=[ + Expr( + value=Call( + func=Name(id='something', ctx=Load()), + args=[ + Name(id='b', ctx=Load()), + Name(id='d', ctx=Load())], + keywords=[]))], + type_comment=None)], + type_ignores=[]) + + +Function and class definitions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. class:: FunctionDef(name, args, body, decorator_list, returns, type_comment) + + A function definition. + + * ``name`` is a raw string of the function name. + * ``args`` is a :class:`arguments` node. + * ``body`` is the list of nodes inside the function. + * ``decorator_list`` is the list of decorators to be applied, stored outermost + first (i.e. the first in the list will be applied last). + * ``returns`` is the return annotation. + + .. attribute:: type_comment + + ``type_comment`` is an optional string with the type annotation as a comment. + + +.. class:: Lambda(args, body) + + ``lambda`` is a minimal function definition that can be used inside an + expression. Unlike :class:`FunctionDef`, ``body`` holds a single node. + + .. doctest:: + + >>> print(ast.dump(ast.parse("lambda x,y: ..."), indent=4)) + Module( + body=[ + Expr( + value=Lambda( + args=arguments( + posonlyargs=[], + args=[ + arg(arg='x', annotation=None, type_comment=None), + arg(arg='y', annotation=None, type_comment=None)], + vararg=None, + kwonlyargs=[], + kw_defaults=[], + kwarg=None, + defaults=[]), + body=Constant(value=Ellipsis, kind=None)))], + type_ignores=[]) + + +.. class:: arguments(posonlyargs, args, vararg, kwonlyargs, kw_defaults, kwarg, defaults) + + The arguments for a function. + + * ``posonlyargs``, ``args`` and ``kwonlyargs`` are lists of :class:`arg` nodes. + * ``vararg`` and ``kwarg`` are single :class:`arg` nodes, referring to the + ``*args, **kwargs`` parameters. + * ``kw_defaults`` is a list of default values for keyword-only arguments. If + one is ``None``, the corresponding argument is required. + * ``defaults`` is a list of default values for arguments that can be passed + positionally. If there are fewer defaults, they correspond to the last n + arguments. + + +.. class:: arg(arg, annotation, type_comment) + + A single argument in a list. ``arg`` is a raw string of the argument + name, ``annotation`` is its annotation, such as a :class:`Str` or + :class:`Name` node. + + .. attribute:: type_comment + + ``type_comment`` is an optional string with the type annotation as a comment + + .. doctest:: + + >>> print(ast.dump(ast.parse("""\ + ... @decorator1 + ... @decorator2 + ... def f(a: 'annotation', b=1, c=2, *d, e, f=3, **g) -> 'return annotation': + ... pass + ... """), indent=4)) + Module( + body=[ + FunctionDef( + name='f', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='a', + annotation=Constant(value='annotation', kind=None), + type_comment=None), + arg(arg='b', annotation=None, type_comment=None), + arg(arg='c', annotation=None, type_comment=None)], + vararg=arg(arg='d', annotation=None, type_comment=None), + kwonlyargs=[ + arg(arg='e', annotation=None, type_comment=None), + arg(arg='f', annotation=None, type_comment=None)], + kw_defaults=[ + None, + Constant(value=3, kind=None)], + kwarg=arg(arg='g', annotation=None, type_comment=None), + defaults=[ + Constant(value=1, kind=None), + Constant(value=2, kind=None)]), + body=[ + Pass()], + decorator_list=[ + Name(id='decorator1', ctx=Load()), + Name(id='decorator2', ctx=Load())], + returns=Constant(value='return annotation', kind=None), + type_comment=None)], + type_ignores=[]) + + +.. class:: Return(value) + + A ``return`` statement. + + .. doctest:: + + >>> print(ast.dump(ast.parse("return 4"), indent=4)) + Module( + body=[ + Return( + value=Constant(value=4, kind=None))], + type_ignores=[]) + + +.. class:: Yield(value) + YieldFrom(value) + + A ``yield`` or ``yield from`` expression. Because these are expressions, they + must be wrapped in a :class:`Expr` node if the value sent back is not used. + + .. doctest:: + + >>> print(ast.dump(ast.parse("yield x"), indent=4)) + Module( + body=[ + Expr( + value=Yield( + value=Name(id='x', ctx=Load())))], + type_ignores=[]) + + >>> print(ast.dump(ast.parse("yield from x"), indent=4)) + Module( + body=[ + Expr( + value=YieldFrom( + value=Name(id='x', ctx=Load())))], + type_ignores=[]) + + +.. class:: Global(names) + Nonlocal(names) + + ``global`` and ``nonlocal`` statements. ``names`` is a list of raw strings. + + .. doctest:: + + >>> print(ast.dump(ast.parse("global x,y,z"), indent=4)) + Module( + body=[ + Global( + names=[ + 'x', + 'y', + 'z'])], + type_ignores=[]) + + >>> print(ast.dump(ast.parse("nonlocal x,y,z"), indent=4)) + Module( + body=[ + Nonlocal( + names=[ + 'x', + 'y', + 'z'])], + type_ignores=[]) + + +.. class:: ClassDef(name, bases, keywords, starargs, kwargs, body, decorator_list) + + A class definition. + + * ``name`` is a raw string for the class name + * ``bases`` is a list of nodes for explicitly specified base classes. + * ``keywords`` is a list of :class:`keyword` nodes, principally for 'metaclass'. + Other keywords will be passed to the metaclass, as per `PEP-3115 + `_. + * ``starargs`` and ``kwargs`` are each a single node, as in a function call. + starargs will be expanded to join the list of base classes, and kwargs will + be passed to the metaclass. + * ``body`` is a list of nodes representing the code within the class + definition. + * ``decorator_list`` is a list of nodes, as in :class:`FunctionDef`. + + .. doctest:: + + >>> print(ast.dump(ast.parse("""\ + ... @decorator1 + ... @decorator2 + ... class Foo(base1, base2, metaclass=meta): + ... pass + ... """), indent=4)) + Module( + body=[ + ClassDef( + name='Foo', + bases=[ + Name(id='base1', ctx=Load()), + Name(id='base2', ctx=Load())], + keywords=[ + keyword( + arg='metaclass', + value=Name(id='meta', ctx=Load()))], + body=[ + Pass()], + decorator_list=[ + Name(id='decorator1', ctx=Load()), + Name(id='decorator2', ctx=Load())])], + type_ignores=[]) + +Async and await +^^^^^^^^^^^^^^^ + +.. class:: AsyncFunctionDef(name, args, body, decorator_list, returns, type_comment) + + An ``async def`` function definition. Has the same fields as + :class:`FunctionDef`. + + +.. class:: Await(value) + + An ``await`` expression. ``value`` is what it waits for. + Only valid in the body of an :class:`AsyncFunctionDef`. + +.. doctest:: + + >>> print(ast.dump(ast.parse("""\ + ... async def f(): + ... await other_func() + ... """), indent=4)) + Module( + body=[ + AsyncFunctionDef( + name='f', + args=arguments( + posonlyargs=[], + args=[], + vararg=None, + kwonlyargs=[], + kw_defaults=[], + kwarg=None, + defaults=[]), + body=[ + Expr( + value=Await( + value=Call( + func=Name(id='other_func', ctx=Load()), + args=[], + keywords=[])))], + decorator_list=[], + returns=None, + type_comment=None)], + type_ignores=[]) + + +.. class:: AsyncFor(target, iter, body, orelse, type_comment) + AsyncWith(items, body, type_comment) + + ``async for`` loops and ``async with`` context managers. They have the same + fields as :class:`For` and :class:`With`, respectively. Only valid in the + body of an :class:`AsyncFunctionDef`. :mod:`ast` Helpers From webhook-mailer at python.org Mon Mar 2 01:29:01 2020 From: webhook-mailer at python.org (Hai Shi) Date: Mon, 02 Mar 2020 06:29:01 -0000 Subject: [Python-checkins] bpo-39378: partial of PickleState struct should be traversed. (GH-18046) Message-ID: https://github.com/python/cpython/commit/1f577ce363121d590b51abf5c41d1bcf3d751436 commit: 1f577ce363121d590b51abf5c41d1bcf3d751436 branch: master author: Hai Shi committer: GitHub date: 2020-03-02T08:28:44+02:00 summary: bpo-39378: partial of PickleState struct should be traversed. (GH-18046) files: M Modules/_pickle.c diff --git a/Modules/_pickle.c b/Modules/_pickle.c index a75035107a28e..bcbd3c0102965 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -7965,6 +7965,7 @@ pickle_traverse(PyObject *m, visitproc visit, void *arg) Py_VISIT(st->import_mapping_3to2); Py_VISIT(st->codecs_encode); Py_VISIT(st->getattr); + Py_VISIT(st->partial); return 0; } From webhook-mailer at python.org Mon Mar 2 01:33:28 2020 From: webhook-mailer at python.org (Shantanu) Date: Mon, 02 Mar 2020 06:33:28 -0000 Subject: [Python-checkins] bpo-39495: Remove default value from C impl of TreeBuilder.start (GH-18275) Message-ID: https://github.com/python/cpython/commit/4edc95cf0a2960431621eee9bc194f6225f1690b commit: 4edc95cf0a2960431621eee9bc194f6225f1690b branch: master author: Shantanu committer: GitHub date: 2020-03-02T08:33:24+02:00 summary: bpo-39495: Remove default value from C impl of TreeBuilder.start (GH-18275) files: A Misc/NEWS.d/next/Library/2020-01-30-07-02-02.bpo-39495.8LsIRN.rst M Lib/test/test_xml_etree.py M Modules/_elementtree.c M Modules/clinic/_elementtree.c.h diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py index 09c234ca6890a..785edb737021a 100644 --- a/Lib/test/test_xml_etree.py +++ b/Lib/test/test_xml_etree.py @@ -2259,6 +2259,10 @@ def test_expat224_utf8_bug_file(self): text = text[6:-4] self.assertEqual(root.get('b'), text) + def test_39495_treebuilder_start(self): + self.assertRaises(TypeError, ET.TreeBuilder().start, "tag") + self.assertRaises(TypeError, ET.TreeBuilder().start, "tag", None) + # -------------------------------------------------------------------- diff --git a/Misc/NEWS.d/next/Library/2020-01-30-07-02-02.bpo-39495.8LsIRN.rst b/Misc/NEWS.d/next/Library/2020-01-30-07-02-02.bpo-39495.8LsIRN.rst new file mode 100644 index 0000000000000..116a5187c2efc --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-01-30-07-02-02.bpo-39495.8LsIRN.rst @@ -0,0 +1 @@ +Remove default value from *attrs* parameter of :meth:`xml.etree.ElementTree.TreeBuilder.start` for consistency between Python and C implementations. diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index 4498c5ffd54e0..c0f771f7d9305 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -3038,7 +3038,7 @@ _elementtree_TreeBuilder_close_impl(TreeBuilderObject *self) _elementtree.TreeBuilder.start tag: object - attrs: object = None + attrs: object(subclass_of='&PyDict_Type') / [clinic start generated code]*/ @@ -3046,7 +3046,7 @@ _elementtree.TreeBuilder.start static PyObject * _elementtree_TreeBuilder_start_impl(TreeBuilderObject *self, PyObject *tag, PyObject *attrs) -/*[clinic end generated code: output=e7e9dc2861349411 input=95fc1758dd042c65]*/ +/*[clinic end generated code: output=e7e9dc2861349411 input=7288e9e38e63b2b6]*/ { return treebuilder_handle_start(self, tag, attrs); } diff --git a/Modules/clinic/_elementtree.c.h b/Modules/clinic/_elementtree.c.h index a184b0ffb7873..dae5233ee8d8a 100644 --- a/Modules/clinic/_elementtree.c.h +++ b/Modules/clinic/_elementtree.c.h @@ -761,7 +761,7 @@ _elementtree_TreeBuilder_close(TreeBuilderObject *self, PyObject *Py_UNUSED(igno } PyDoc_STRVAR(_elementtree_TreeBuilder_start__doc__, -"start($self, tag, attrs=None, /)\n" +"start($self, tag, attrs, /)\n" "--\n" "\n"); @@ -777,17 +777,17 @@ _elementtree_TreeBuilder_start(TreeBuilderObject *self, PyObject *const *args, P { PyObject *return_value = NULL; PyObject *tag; - PyObject *attrs = Py_None; + PyObject *attrs; - if (!_PyArg_CheckPositional("start", nargs, 1, 2)) { + if (!_PyArg_CheckPositional("start", nargs, 2, 2)) { goto exit; } tag = args[0]; - if (nargs < 2) { - goto skip_optional; + if (!PyDict_Check(args[1])) { + _PyArg_BadArgument("start", "argument 2", "dict", args[1]); + goto exit; } attrs = args[1]; -skip_optional: return_value = _elementtree_TreeBuilder_start_impl(self, tag, attrs); exit: @@ -916,4 +916,4 @@ _elementtree_XMLParser__setevents(XMLParserObject *self, PyObject *const *args, exit: return return_value; } -/*[clinic end generated code: output=bee26d0735a3fddc input=a9049054013a1b77]*/ +/*[clinic end generated code: output=3ad029ba71f5ae39 input=a9049054013a1b77]*/ From webhook-mailer at python.org Mon Mar 2 01:39:57 2020 From: webhook-mailer at python.org (Chris A) Date: Mon, 02 Mar 2020 06:39:57 -0000 Subject: [Python-checkins] bpo-38971: Open file in codecs.open() closes if exception raised. (GH-17666) Message-ID: https://github.com/python/cpython/commit/2565edec2c974b2acca03b4cc5025e83f903ddd7 commit: 2565edec2c974b2acca03b4cc5025e83f903ddd7 branch: master author: Chris A committer: GitHub date: 2020-03-02T08:39:50+02:00 summary: bpo-38971: Open file in codecs.open() closes if exception raised. (GH-17666) Open issue in the BPO indicated a desire to make the implementation of codecs.open() at parity with io.open(), which implements a try/except to assure file stream gets closed before an exception is raised. files: A Misc/NEWS.d/next/Library/2019-12-20-16-06-28.bpo-38971.fKRYlF.rst M Lib/codecs.py M Lib/test/test_codecs.py diff --git a/Lib/codecs.py b/Lib/codecs.py index 21c45a7d10a4c..7f23e9775df80 100644 --- a/Lib/codecs.py +++ b/Lib/codecs.py @@ -905,11 +905,16 @@ def open(filename, mode='r', encoding=None, errors='strict', buffering=-1): file = builtins.open(filename, mode, buffering) if encoding is None: return file - info = lookup(encoding) - srw = StreamReaderWriter(file, info.streamreader, info.streamwriter, errors) - # Add attributes to simplify introspection - srw.encoding = encoding - return srw + + try: + info = lookup(encoding) + srw = StreamReaderWriter(file, info.streamreader, info.streamwriter, errors) + # Add attributes to simplify introspection + srw.encoding = encoding + return srw + except: + file.close() + raise def EncodedFile(file, data_encoding, file_encoding=None, errors='strict'): diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py index 8d9cb9089039c..dcdd574bc7f4d 100644 --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -1154,6 +1154,7 @@ def test_stream_bare(self): got = ostream.getvalue() self.assertEqual(got, unistring) + class EscapeDecodeTest(unittest.TestCase): def test_empty(self): self.assertEqual(codecs.escape_decode(b""), (b"", 0)) @@ -1725,6 +1726,14 @@ def test_undefined(self): self.assertRaises(UnicodeError, codecs.decode, b'abc', 'undefined', errors) + def test_file_closes_if_lookup_error_raised(self): + mock_open = mock.mock_open() + with mock.patch('builtins.open', mock_open) as file: + with self.assertRaises(LookupError): + codecs.open(support.TESTFN, 'wt', 'invalid-encoding') + + file().close.assert_called() + class StreamReaderTest(unittest.TestCase): diff --git a/Misc/NEWS.d/next/Library/2019-12-20-16-06-28.bpo-38971.fKRYlF.rst b/Misc/NEWS.d/next/Library/2019-12-20-16-06-28.bpo-38971.fKRYlF.rst new file mode 100644 index 0000000000000..9676d72b44abc --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-12-20-16-06-28.bpo-38971.fKRYlF.rst @@ -0,0 +1,3 @@ +Open issue in the BPO indicated a desire to make the implementation of +codecs.open() at parity with io.open(), which implements a try/except to +assure file stream gets closed before an exception is raised. \ No newline at end of file From webhook-mailer at python.org Mon Mar 2 01:42:46 2020 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Mon, 02 Mar 2020 06:42:46 -0000 Subject: [Python-checkins] bpo-38913: Fix segfault in Py_BuildValue("(s#O)", ...) if entered with exception raised. (GH-18656) Message-ID: https://github.com/python/cpython/commit/28d0bcac8b7e6dbd28311f1283dabb6a4d649fcb commit: 28d0bcac8b7e6dbd28311f1283dabb6a4d649fcb branch: master author: Serhiy Storchaka committer: GitHub date: 2020-03-02T08:42:39+02:00 summary: bpo-38913: Fix segfault in Py_BuildValue("(s#O)", ...) if entered with exception raised. (GH-18656) files: A Misc/NEWS.d/next/C API/2020-02-25-20-10-34.bpo-38913.siF1lS.rst M Modules/_testcapimodule.c M Python/modsupport.c diff --git a/Misc/NEWS.d/next/C API/2020-02-25-20-10-34.bpo-38913.siF1lS.rst b/Misc/NEWS.d/next/C API/2020-02-25-20-10-34.bpo-38913.siF1lS.rst new file mode 100644 index 0000000000000..0e4d1210315d8 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2020-02-25-20-10-34.bpo-38913.siF1lS.rst @@ -0,0 +1,2 @@ +Fixed segfault in ``Py_BuildValue()`` called with a format containing "#" +and undefined PY_SSIZE_T_CLEAN whwn an exception is set. diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index eb31a0ef5c933..23a27e368c066 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -5258,6 +5258,9 @@ meth_fastcall_keywords(PyObject* self, PyObject* const* args, return Py_BuildValue("NNN", _null_to_none(self), pyargs, pykwargs); } + +static PyObject *test_buildvalue_issue38913(PyObject *, PyObject *); + static PyMethodDef TestMethods[] = { {"raise_exception", raise_exception, METH_VARARGS}, {"raise_memoryerror", raise_memoryerror, METH_NOARGS}, @@ -5322,6 +5325,7 @@ static PyMethodDef TestMethods[] = { {"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}, + {"test_buildvalue_issue38913", test_buildvalue_issue38913, METH_NOARGS}, {"get_args", get_args, METH_VARARGS}, {"get_kwargs", (PyCFunction)(void(*)(void))get_kwargs, METH_VARARGS|METH_KEYWORDS}, {"getargs_tuple", getargs_tuple, METH_VARARGS}, @@ -6791,3 +6795,42 @@ PyInit__testcapi(void) PyState_AddModule(m, &_testcapimodule); return m; } + + +/* Test the C API exposed when PY_SSIZE_T_CLEAN is not defined */ + +#undef Py_BuildValue +PyAPI_FUNC(PyObject *) Py_BuildValue(const char *, ...); + +static PyObject * +test_buildvalue_issue38913(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + PyObject *res; + const char str[] = "string"; + const Py_UNICODE unicode[] = L"unicode"; + PyErr_SetNone(PyExc_ZeroDivisionError); + + res = Py_BuildValue("(s#O)", str, 1, Py_None); + assert(res == NULL); + if (!PyErr_ExceptionMatches(PyExc_ZeroDivisionError)) { + return NULL; + } + res = Py_BuildValue("(z#O)", str, 1, Py_None); + assert(res == NULL); + if (!PyErr_ExceptionMatches(PyExc_ZeroDivisionError)) { + return NULL; + } + res = Py_BuildValue("(y#O)", str, 1, Py_None); + assert(res == NULL); + if (!PyErr_ExceptionMatches(PyExc_ZeroDivisionError)) { + return NULL; + } + res = Py_BuildValue("(u#O)", unicode, 1, Py_None); + assert(res == NULL); + if (!PyErr_ExceptionMatches(PyExc_ZeroDivisionError)) { + return NULL; + } + + PyErr_Clear(); + Py_RETURN_NONE; +} diff --git a/Python/modsupport.c b/Python/modsupport.c index 6255822107746..7271af3ac5332 100644 --- a/Python/modsupport.c +++ b/Python/modsupport.c @@ -343,11 +343,11 @@ do_mkvalue(const char **p_format, va_list *p_va, int flags) if (flags & FLAG_SIZE_T) n = va_arg(*p_va, Py_ssize_t); else { + n = va_arg(*p_va, int); if (PyErr_WarnEx(PyExc_DeprecationWarning, "PY_SSIZE_T_CLEAN will be required for '#' formats", 1)) { return NULL; } - n = va_arg(*p_va, int); } } else @@ -396,11 +396,11 @@ do_mkvalue(const char **p_format, va_list *p_va, int flags) if (flags & FLAG_SIZE_T) n = va_arg(*p_va, Py_ssize_t); else { + n = va_arg(*p_va, int); if (PyErr_WarnEx(PyExc_DeprecationWarning, "PY_SSIZE_T_CLEAN will be required for '#' formats", 1)) { return NULL; } - n = va_arg(*p_va, int); } } else @@ -434,11 +434,11 @@ do_mkvalue(const char **p_format, va_list *p_va, int flags) if (flags & FLAG_SIZE_T) n = va_arg(*p_va, Py_ssize_t); else { + n = va_arg(*p_va, int); if (PyErr_WarnEx(PyExc_DeprecationWarning, "PY_SSIZE_T_CLEAN will be required for '#' formats", 1)) { return NULL; } - n = va_arg(*p_va, int); } } else From webhook-mailer at python.org Mon Mar 2 01:47:03 2020 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 02 Mar 2020 06:47:03 -0000 Subject: [Python-checkins] bpo-39378: partial of PickleState struct should be traversed. (GH-18046) Message-ID: https://github.com/python/cpython/commit/d3c24350892b55b4ea6fb81b84e577968c1f2f91 commit: d3c24350892b55b4ea6fb81b84e577968c1f2f91 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2020-03-01T22:46:59-08:00 summary: bpo-39378: partial of PickleState struct should be traversed. (GH-18046) (cherry picked from commit 1f577ce363121d590b51abf5c41d1bcf3d751436) Co-authored-by: Hai Shi files: M Modules/_pickle.c diff --git a/Modules/_pickle.c b/Modules/_pickle.c index dd45772595bc9..ef83da02e2e41 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -7436,6 +7436,7 @@ pickle_traverse(PyObject *m, visitproc visit, void *arg) Py_VISIT(st->import_mapping_3to2); Py_VISIT(st->codecs_encode); Py_VISIT(st->getattr); + Py_VISIT(st->partial); return 0; } From webhook-mailer at python.org Mon Mar 2 01:47:27 2020 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 02 Mar 2020 06:47:27 -0000 Subject: [Python-checkins] bpo-39378: partial of PickleState struct should be traversed. (GH-18046) Message-ID: https://github.com/python/cpython/commit/5f2ade20a556f8c20555c7032436477d6dc86d4f commit: 5f2ade20a556f8c20555c7032436477d6dc86d4f branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2020-03-01T22:47:23-08:00 summary: bpo-39378: partial of PickleState struct should be traversed. (GH-18046) (cherry picked from commit 1f577ce363121d590b51abf5c41d1bcf3d751436) Co-authored-by: Hai Shi files: M Modules/_pickle.c diff --git a/Modules/_pickle.c b/Modules/_pickle.c index 55e2734ca2f31..55affb2c7c479 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -7961,6 +7961,7 @@ pickle_traverse(PyObject *m, visitproc visit, void *arg) Py_VISIT(st->import_mapping_3to2); Py_VISIT(st->codecs_encode); Py_VISIT(st->getattr); + Py_VISIT(st->partial); return 0; } From webhook-mailer at python.org Mon Mar 2 02:54:49 2020 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Mon, 02 Mar 2020 07:54:49 -0000 Subject: [Python-checkins] [3.8] bpo-38913: Fix segfault in Py_BuildValue("(sGH-O)", ...) if entered with exception raised. (GH-18656). (GH-18732) Message-ID: https://github.com/python/cpython/commit/a7b8a969eb3daacb1fcb029a8c5fecb5d09c964b commit: a7b8a969eb3daacb1fcb029a8c5fecb5d09c964b branch: 3.8 author: Serhiy Storchaka committer: GitHub date: 2020-03-02T09:54:43+02:00 summary: [3.8] bpo-38913: Fix segfault in Py_BuildValue("(sGH-O)", ...) if entered with exception raised. (GH-18656). (GH-18732) (cherry picked from commit 28d0bcac8b7e6dbd28311f1283dabb6a4d649fcb) files: A Misc/NEWS.d/next/C API/2020-02-25-20-10-34.bpo-38913.siF1lS.rst M Modules/_testcapimodule.c M Python/modsupport.c diff --git a/Misc/NEWS.d/next/C API/2020-02-25-20-10-34.bpo-38913.siF1lS.rst b/Misc/NEWS.d/next/C API/2020-02-25-20-10-34.bpo-38913.siF1lS.rst new file mode 100644 index 0000000000000..0e4d1210315d8 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2020-02-25-20-10-34.bpo-38913.siF1lS.rst @@ -0,0 +1,2 @@ +Fixed segfault in ``Py_BuildValue()`` called with a format containing "#" +and undefined PY_SSIZE_T_CLEAN whwn an exception is set. diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index b54071669cf99..a8f8e683b2013 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -5063,6 +5063,8 @@ test_write_unraisable_exc(PyObject *self, PyObject *args) } +static PyObject *test_buildvalue_issue38913(PyObject *, PyObject *); + static PyMethodDef TestMethods[] = { {"raise_exception", raise_exception, METH_VARARGS}, {"raise_memoryerror", raise_memoryerror, METH_NOARGS}, @@ -5122,6 +5124,7 @@ static PyMethodDef TestMethods[] = { #endif {"getbuffer_with_null_view", getbuffer_with_null_view, METH_O}, {"test_buildvalue_N", test_buildvalue_N, METH_NOARGS}, + {"test_buildvalue_issue38913", test_buildvalue_issue38913, METH_NOARGS}, {"get_args", get_args, METH_VARARGS}, {"get_kwargs", (PyCFunction)(void(*)(void))get_kwargs, METH_VARARGS|METH_KEYWORDS}, {"getargs_tuple", getargs_tuple, METH_VARARGS}, @@ -6332,3 +6335,42 @@ PyInit__testcapi(void) PyState_AddModule(m, &_testcapimodule); return m; } + + +/* Test the C API exposed when PY_SSIZE_T_CLEAN is not defined */ + +#undef Py_BuildValue +PyAPI_FUNC(PyObject *) Py_BuildValue(const char *, ...); + +static PyObject * +test_buildvalue_issue38913(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + PyObject *res; + const char str[] = "string"; + const Py_UNICODE unicode[] = L"unicode"; + PyErr_SetNone(PyExc_ZeroDivisionError); + + res = Py_BuildValue("(s#O)", str, 1, Py_None); + assert(res == NULL); + if (!PyErr_ExceptionMatches(PyExc_ZeroDivisionError)) { + return NULL; + } + res = Py_BuildValue("(z#O)", str, 1, Py_None); + assert(res == NULL); + if (!PyErr_ExceptionMatches(PyExc_ZeroDivisionError)) { + return NULL; + } + res = Py_BuildValue("(y#O)", str, 1, Py_None); + assert(res == NULL); + if (!PyErr_ExceptionMatches(PyExc_ZeroDivisionError)) { + return NULL; + } + res = Py_BuildValue("(u#O)", unicode, 1, Py_None); + assert(res == NULL); + if (!PyErr_ExceptionMatches(PyExc_ZeroDivisionError)) { + return NULL; + } + + PyErr_Clear(); + Py_RETURN_NONE; +} diff --git a/Python/modsupport.c b/Python/modsupport.c index 6255822107746..7271af3ac5332 100644 --- a/Python/modsupport.c +++ b/Python/modsupport.c @@ -343,11 +343,11 @@ do_mkvalue(const char **p_format, va_list *p_va, int flags) if (flags & FLAG_SIZE_T) n = va_arg(*p_va, Py_ssize_t); else { + n = va_arg(*p_va, int); if (PyErr_WarnEx(PyExc_DeprecationWarning, "PY_SSIZE_T_CLEAN will be required for '#' formats", 1)) { return NULL; } - n = va_arg(*p_va, int); } } else @@ -396,11 +396,11 @@ do_mkvalue(const char **p_format, va_list *p_va, int flags) if (flags & FLAG_SIZE_T) n = va_arg(*p_va, Py_ssize_t); else { + n = va_arg(*p_va, int); if (PyErr_WarnEx(PyExc_DeprecationWarning, "PY_SSIZE_T_CLEAN will be required for '#' formats", 1)) { return NULL; } - n = va_arg(*p_va, int); } } else @@ -434,11 +434,11 @@ do_mkvalue(const char **p_format, va_list *p_va, int flags) if (flags & FLAG_SIZE_T) n = va_arg(*p_va, Py_ssize_t); else { + n = va_arg(*p_va, int); if (PyErr_WarnEx(PyExc_DeprecationWarning, "PY_SSIZE_T_CLEAN will be required for '#' formats", 1)) { return NULL; } - n = va_arg(*p_va, int); } } else From webhook-mailer at python.org Mon Mar 2 02:58:52 2020 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Mon, 02 Mar 2020 07:58:52 -0000 Subject: [Python-checkins] bpo-38410: Properly handle PySys_Audit() failures (GH-18658) Message-ID: https://github.com/python/cpython/commit/87a4cd5fbebdd0e6166b421d2c3706bc2f2e5a11 commit: 87a4cd5fbebdd0e6166b421d2c3706bc2f2e5a11 branch: 3.8 author: Serhiy Storchaka committer: GitHub date: 2020-03-02T09:58:48+02:00 summary: bpo-38410: Properly handle PySys_Audit() failures (GH-18658) _PyEval_SetAsyncGenFinalizer() and _PyEval_SetAsyncGenFirstiter() didn't include proper error handling for their PySys_Audit() calls. Co-authored-by: Zackery Spytz files: A Misc/NEWS.d/next/Library/2019-10-09-08-14-25.bpo-38410._YyoMV.rst M Python/ceval.c M Python/sysmodule.c diff --git a/Misc/NEWS.d/next/Library/2019-10-09-08-14-25.bpo-38410._YyoMV.rst b/Misc/NEWS.d/next/Library/2019-10-09-08-14-25.bpo-38410._YyoMV.rst new file mode 100644 index 0000000000000..fcfd7936e63ac --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-10-09-08-14-25.bpo-38410._YyoMV.rst @@ -0,0 +1,2 @@ +Properly handle :func:`sys.audit` failures in +:func:`sys.set_asyncgen_hooks`. Based on patch by Zackery Spytz. diff --git a/Python/ceval.c b/Python/ceval.c index 3306fb9728e8c..5d78d5a39357d 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4742,19 +4742,6 @@ _PyEval_GetCoroutineOriginTrackingDepth(void) return tstate->coroutine_origin_tracking_depth; } -void -_PyEval_SetAsyncGenFirstiter(PyObject *firstiter) -{ - PyThreadState *tstate = _PyThreadState_GET(); - - if (PySys_Audit("sys.set_asyncgen_hook_firstiter", NULL) < 0) { - return; - } - - Py_XINCREF(firstiter); - Py_XSETREF(tstate->async_gen_firstiter, firstiter); -} - PyObject * _PyEval_GetAsyncGenFirstiter(void) { @@ -4762,19 +4749,6 @@ _PyEval_GetAsyncGenFirstiter(void) return tstate->async_gen_firstiter; } -void -_PyEval_SetAsyncGenFinalizer(PyObject *finalizer) -{ - PyThreadState *tstate = _PyThreadState_GET(); - - if (PySys_Audit("sys.set_asyncgen_hook_finalizer", NULL) < 0) { - return; - } - - Py_XINCREF(finalizer); - Py_XSETREF(tstate->async_gen_finalizer, finalizer); -} - PyObject * _PyEval_GetAsyncGenFinalizer(void) { diff --git a/Python/sysmodule.c b/Python/sysmodule.c index da4b6e1a7806b..b544f2b793ec9 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -1178,6 +1178,51 @@ static PyStructSequence_Desc asyncgen_hooks_desc = { 2 }; +static int +set_async_gen_firstiter(PyObject *firstiter) +{ + PyThreadState *tstate = _PyThreadState_GET(); + + if (PySys_Audit("sys.set_asyncgen_hook_firstiter", NULL) < 0) { + return -1; + } + + Py_XINCREF(firstiter); + Py_XSETREF(tstate->async_gen_firstiter, firstiter); + return 0; +} + +void +_PyEval_SetAsyncGenFirstiter(PyObject *firstiter) +{ + if (set_async_gen_firstiter(firstiter) < 0) { + PyErr_WriteUnraisable(NULL); + } +} + +static int +set_async_gen_finalizer(PyObject *finalizer) +{ + PyThreadState *tstate = _PyThreadState_GET(); + + if (PySys_Audit("sys.set_asyncgen_hook_finalizer", NULL) < 0) { + return -1; + } + + Py_XINCREF(finalizer); + Py_XSETREF(tstate->async_gen_finalizer, finalizer); + return 0; +} + +void +_PyEval_SetAsyncGenFinalizer(PyObject *finalizer) +{ + if (set_async_gen_finalizer(finalizer) < 0) { + PyErr_WriteUnraisable(NULL); + } +} + + static PyObject * sys_set_asyncgen_hooks(PyObject *self, PyObject *args, PyObject *kw) { @@ -1198,10 +1243,12 @@ sys_set_asyncgen_hooks(PyObject *self, PyObject *args, PyObject *kw) Py_TYPE(finalizer)->tp_name); return NULL; } - _PyEval_SetAsyncGenFinalizer(finalizer); + if (set_async_gen_finalizer(finalizer) < 0) { + return NULL; + } } - else if (finalizer == Py_None) { - _PyEval_SetAsyncGenFinalizer(NULL); + else if (finalizer == Py_None && set_async_gen_finalizer(NULL) < 0) { + return NULL; } if (firstiter && firstiter != Py_None) { @@ -1211,10 +1258,12 @@ sys_set_asyncgen_hooks(PyObject *self, PyObject *args, PyObject *kw) Py_TYPE(firstiter)->tp_name); return NULL; } - _PyEval_SetAsyncGenFirstiter(firstiter); + if (set_async_gen_firstiter(firstiter) < 0) { + return NULL; + } } - else if (firstiter == Py_None) { - _PyEval_SetAsyncGenFirstiter(NULL); + else if (firstiter == Py_None && set_async_gen_firstiter(NULL) < 0) { + return NULL; } Py_RETURN_NONE; From webhook-mailer at python.org Mon Mar 2 03:02:21 2020 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 02 Mar 2020 08:02:21 -0000 Subject: [Python-checkins] bpo-38971: Open file in codecs.open() closes if exception raised. (GH-17666) Message-ID: https://github.com/python/cpython/commit/f4d709f4a3c69bd940bd6968a70241277132bed7 commit: f4d709f4a3c69bd940bd6968a70241277132bed7 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2020-03-02T00:02:16-08:00 summary: bpo-38971: Open file in codecs.open() closes if exception raised. (GH-17666) Open issue in the BPO indicated a desire to make the implementation of codecs.open() at parity with io.open(), which implements a try/except to assure file stream gets closed before an exception is raised. (cherry picked from commit 2565edec2c974b2acca03b4cc5025e83f903ddd7) Co-authored-by: Chris A files: A Misc/NEWS.d/next/Library/2019-12-20-16-06-28.bpo-38971.fKRYlF.rst M Lib/codecs.py M Lib/test/test_codecs.py diff --git a/Lib/codecs.py b/Lib/codecs.py index cfca5d38b0795..5d95f25612e96 100644 --- a/Lib/codecs.py +++ b/Lib/codecs.py @@ -904,11 +904,16 @@ def open(filename, mode='r', encoding=None, errors='strict', buffering=1): file = builtins.open(filename, mode, buffering) if encoding is None: return file - info = lookup(encoding) - srw = StreamReaderWriter(file, info.streamreader, info.streamwriter, errors) - # Add attributes to simplify introspection - srw.encoding = encoding - return srw + + try: + info = lookup(encoding) + srw = StreamReaderWriter(file, info.streamreader, info.streamwriter, errors) + # Add attributes to simplify introspection + srw.encoding = encoding + return srw + except: + file.close() + raise def EncodedFile(file, data_encoding, file_encoding=None, errors='strict'): diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py index 5a450ebd9dc2b..ea9e719e7478b 100644 --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -1206,6 +1206,7 @@ def test_stream_bare(self): got = ostream.getvalue() self.assertEqual(got, unistring) + class EscapeDecodeTest(unittest.TestCase): def test_empty(self): self.assertEqual(codecs.escape_decode(b""), (b"", 0)) @@ -1869,6 +1870,14 @@ def test_undefined(self): self.assertRaises(UnicodeError, codecs.decode, b'abc', 'undefined', errors) + def test_file_closes_if_lookup_error_raised(self): + mock_open = mock.mock_open() + with mock.patch('builtins.open', mock_open) as file: + with self.assertRaises(LookupError): + codecs.open(support.TESTFN, 'wt', 'invalid-encoding') + + file().close.assert_called() + class StreamReaderTest(unittest.TestCase): diff --git a/Misc/NEWS.d/next/Library/2019-12-20-16-06-28.bpo-38971.fKRYlF.rst b/Misc/NEWS.d/next/Library/2019-12-20-16-06-28.bpo-38971.fKRYlF.rst new file mode 100644 index 0000000000000..9676d72b44abc --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-12-20-16-06-28.bpo-38971.fKRYlF.rst @@ -0,0 +1,3 @@ +Open issue in the BPO indicated a desire to make the implementation of +codecs.open() at parity with io.open(), which implements a try/except to +assure file stream gets closed before an exception is raised. \ No newline at end of file From webhook-mailer at python.org Mon Mar 2 03:03:12 2020 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 02 Mar 2020 08:03:12 -0000 Subject: [Python-checkins] bpo-38971: Open file in codecs.open() closes if exception raised. (GH-17666) Message-ID: https://github.com/python/cpython/commit/f28b0c74e54a133cb0287b4297af67d0d7c14d6e commit: f28b0c74e54a133cb0287b4297af67d0d7c14d6e branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2020-03-02T00:03:08-08:00 summary: bpo-38971: Open file in codecs.open() closes if exception raised. (GH-17666) Open issue in the BPO indicated a desire to make the implementation of codecs.open() at parity with io.open(), which implements a try/except to assure file stream gets closed before an exception is raised. (cherry picked from commit 2565edec2c974b2acca03b4cc5025e83f903ddd7) Co-authored-by: Chris A files: A Misc/NEWS.d/next/Library/2019-12-20-16-06-28.bpo-38971.fKRYlF.rst M Lib/codecs.py M Lib/test/test_codecs.py diff --git a/Lib/codecs.py b/Lib/codecs.py index 21c45a7d10a4c..7f23e9775df80 100644 --- a/Lib/codecs.py +++ b/Lib/codecs.py @@ -905,11 +905,16 @@ def open(filename, mode='r', encoding=None, errors='strict', buffering=-1): file = builtins.open(filename, mode, buffering) if encoding is None: return file - info = lookup(encoding) - srw = StreamReaderWriter(file, info.streamreader, info.streamwriter, errors) - # Add attributes to simplify introspection - srw.encoding = encoding - return srw + + try: + info = lookup(encoding) + srw = StreamReaderWriter(file, info.streamreader, info.streamwriter, errors) + # Add attributes to simplify introspection + srw.encoding = encoding + return srw + except: + file.close() + raise def EncodedFile(file, data_encoding, file_encoding=None, errors='strict'): diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py index 8c10e948e8041..0fd258ca8abf6 100644 --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -1142,6 +1142,7 @@ def test_stream_bare(self): got = ostream.getvalue() self.assertEqual(got, unistring) + class EscapeDecodeTest(unittest.TestCase): def test_empty(self): self.assertEqual(codecs.escape_decode(b""), (b"", 0)) @@ -1713,6 +1714,14 @@ def test_undefined(self): self.assertRaises(UnicodeError, codecs.decode, b'abc', 'undefined', errors) + def test_file_closes_if_lookup_error_raised(self): + mock_open = mock.mock_open() + with mock.patch('builtins.open', mock_open) as file: + with self.assertRaises(LookupError): + codecs.open(support.TESTFN, 'wt', 'invalid-encoding') + + file().close.assert_called() + class StreamReaderTest(unittest.TestCase): diff --git a/Misc/NEWS.d/next/Library/2019-12-20-16-06-28.bpo-38971.fKRYlF.rst b/Misc/NEWS.d/next/Library/2019-12-20-16-06-28.bpo-38971.fKRYlF.rst new file mode 100644 index 0000000000000..9676d72b44abc --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-12-20-16-06-28.bpo-38971.fKRYlF.rst @@ -0,0 +1,3 @@ +Open issue in the BPO indicated a desire to make the implementation of +codecs.open() at parity with io.open(), which implements a try/except to +assure file stream gets closed before an exception is raised. \ No newline at end of file From webhook-mailer at python.org Mon Mar 2 03:57:38 2020 From: webhook-mailer at python.org (Mark Dickinson) Date: Mon, 02 Mar 2020 08:57:38 -0000 Subject: [Python-checkins] Fix misleading statement about mixed-type numeric comparisons (GH-18615) Message-ID: https://github.com/python/cpython/commit/9f1cb1bb49476246de5d9ed5fe680301cf7f7571 commit: 9f1cb1bb49476246de5d9ed5fe680301cf7f7571 branch: master author: Mark Dickinson committer: GitHub date: 2020-03-02T08:57:27Z summary: Fix misleading statement about mixed-type numeric comparisons (GH-18615) files: A Misc/NEWS.d/next/Documentation/2020-02-23-13-26-40.bpo-39530._bCvzQ.rst M Doc/library/stdtypes.rst diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 435ba5b74ff34..881c15d8f7c5d 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -261,8 +261,10 @@ and imaginary parts. Python fully supports mixed arithmetic: when a binary arithmetic operator has operands of different numeric types, the operand with the "narrower" type is widened to that of the other, where integer is narrower than floating point, -which is narrower than complex. Comparisons between numbers of mixed type use -the same rule. [2]_ The constructors :func:`int`, :func:`float`, and +which is narrower than complex. A comparison between numbers of different types +behaves as though the exact values of those numbers were being compared. [2]_ + +The constructors :func:`int`, :func:`float`, and :func:`complex` can be used to produce numbers of a specific type. All numeric types (except complex) support the following operations (for priorities of diff --git a/Misc/NEWS.d/next/Documentation/2020-02-23-13-26-40.bpo-39530._bCvzQ.rst b/Misc/NEWS.d/next/Documentation/2020-02-23-13-26-40.bpo-39530._bCvzQ.rst new file mode 100644 index 0000000000000..b7a02522bbb1c --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2020-02-23-13-26-40.bpo-39530._bCvzQ.rst @@ -0,0 +1 @@ +Fix misleading documentation about mixed-type numeric comparisons. From webhook-mailer at python.org Mon Mar 2 04:54:53 2020 From: webhook-mailer at python.org (Inada Naoki) Date: Mon, 02 Mar 2020 09:54:53 -0000 Subject: [Python-checkins] bpo-39775: inspect: Change Signature.parameters back to OrderedDict. (GH-18684) Message-ID: https://github.com/python/cpython/commit/211055176157545ce98e6c02b09d624719e6dd30 commit: 211055176157545ce98e6c02b09d624719e6dd30 branch: master author: Inada Naoki committer: GitHub date: 2020-03-02T18:54:48+09:00 summary: bpo-39775: inspect: Change Signature.parameters back to OrderedDict. (GH-18684) files: A Misc/NEWS.d/next/Library/2020-02-28-16-42-16.bpo-39775.IuSvVb.rst M Doc/library/inspect.rst M Doc/whatsnew/3.9.rst M Lib/inspect.py diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst index 9b9bc99f43d48..d00a30ff00406 100644 --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -624,18 +624,15 @@ function. .. attribute:: Signature.parameters - An dictionary of :class:`Parameter` objects. Parameters appear in strict - definition order, including keyword-only parameters. + An ordered mapping of parameters' names to the corresponding + :class:`Parameter` objects. Parameters appear in strict definition + order, including keyword-only parameters. .. versionchanged:: 3.7 Python only explicitly guaranteed that it preserved the declaration order of keyword-only parameters as of version 3.7, although in practice this order had always been preserved in Python 3. - .. versionchanged:: 3.9 - :attr:`parameters` is now of type :class:`dict`. Formerly, it was of - type :class:`collections.OrderedDict`. - .. attribute:: Signature.return_annotation The "return" annotation for the callable. If the callable has no "return" @@ -824,7 +821,7 @@ function. .. attribute:: BoundArguments.arguments - An ordered, mutable mapping of parameters' names to arguments' values. + A mutable mapping of parameters' names to arguments' values. Contains only explicitly bound arguments. Changes in :attr:`arguments` will reflect in :attr:`args` and :attr:`kwargs`. diff --git a/Doc/whatsnew/3.9.rst b/Doc/whatsnew/3.9.rst index 3364f392f15c7..f49575d89da67 100644 --- a/Doc/whatsnew/3.9.rst +++ b/Doc/whatsnew/3.9.rst @@ -218,6 +218,12 @@ now raises :exc:`ImportError` instead of :exc:`ValueError` for invalid relative import attempts. (Contributed by Ngalim Siregar in :issue:`37444`.) +inspect +------- + +:attr:`inspect.BoundArguments.arguments` is changed from ``OrderedDict`` to regular +dict. (Contributed by Inada Naoki in :issue:`36350` and :issue:`39775`.) + ipaddress --------- diff --git a/Lib/inspect.py b/Lib/inspect.py index 950bdb221798d..bb82f96fdf374 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -48,7 +48,7 @@ import functools import builtins from operator import attrgetter -from collections import namedtuple +from collections import namedtuple, OrderedDict # Create constants for the compiler flags in Include/code.h # We try to get them from dis to avoid duplication @@ -1727,7 +1727,7 @@ def _signature_get_partial(wrapped_sig, partial, extra_args=()): """ old_params = wrapped_sig.parameters - new_params = {} + new_params = OrderedDict(old_params.items()) partial_args = partial.args or () partial_keywords = partial.keywords or {} @@ -1743,7 +1743,6 @@ def _signature_get_partial(wrapped_sig, partial, extra_args=()): transform_to_kwonly = False - kwonly_params = {} # Keyword only parameters are moved to end. for param_name, param in old_params.items(): try: arg_value = ba.arguments[param_name] @@ -1753,6 +1752,7 @@ def _signature_get_partial(wrapped_sig, partial, extra_args=()): if param.kind is _POSITIONAL_ONLY: # If positional-only parameter is bound by partial, # it effectively disappears from the signature + new_params.pop(param_name) continue if param.kind is _POSITIONAL_OR_KEYWORD: @@ -1771,26 +1771,28 @@ def _signature_get_partial(wrapped_sig, partial, extra_args=()): # multiple values. transform_to_kwonly = True # Set the new default value - param = param.replace(default=arg_value) + new_params[param_name] = param.replace(default=arg_value) else: # was passed as a positional argument + new_params.pop(param.name) continue if param.kind is _KEYWORD_ONLY: # Set the new default value - param = param.replace(default=arg_value) + new_params[param_name] = param.replace(default=arg_value) if transform_to_kwonly: assert param.kind is not _POSITIONAL_ONLY if param.kind is _POSITIONAL_OR_KEYWORD: - kwonly_params[param_name] = param.replace(kind=_KEYWORD_ONLY) + new_param = new_params[param_name].replace(kind=_KEYWORD_ONLY) + new_params[param_name] = new_param + new_params.move_to_end(param_name) elif param.kind in (_KEYWORD_ONLY, _VAR_KEYWORD): - kwonly_params[param_name] = param - else: - new_params[param_name] = param + new_params.move_to_end(param_name) + elif param.kind is _VAR_POSITIONAL: + new_params.pop(param.name) - new_params.update(kwonly_params) return wrapped_sig.replace(parameters=new_params.values()) diff --git a/Misc/NEWS.d/next/Library/2020-02-28-16-42-16.bpo-39775.IuSvVb.rst b/Misc/NEWS.d/next/Library/2020-02-28-16-42-16.bpo-39775.IuSvVb.rst new file mode 100644 index 0000000000000..1667b43a902fe --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-02-28-16-42-16.bpo-39775.IuSvVb.rst @@ -0,0 +1,2 @@ +Change ``inspect.Signature.parameters`` back to ``collections.OrderedDict``. +This was changed to ``dict`` in Python 3.9.0a4. From webhook-mailer at python.org Mon Mar 2 07:25:20 2020 From: webhook-mailer at python.org (Erlend Egeberg Aasland) Date: Mon, 02 Mar 2020 12:25:20 -0000 Subject: [Python-checkins] bpo-38380: Update macOS & Windows builds to SQLite v3.31.1 (GH-18678) Message-ID: https://github.com/python/cpython/commit/1382c3289bcfd34ac6811fdf9aa5bc09ca8c320e commit: 1382c3289bcfd34ac6811fdf9aa5bc09ca8c320e branch: master author: Erlend Egeberg Aasland committer: GitHub date: 2020-03-02T04:25:10-08:00 summary: bpo-38380: Update macOS & Windows builds to SQLite v3.31.1 (GH-18678) Automerge-Triggered-By: @zooba files: A Misc/NEWS.d/next/Windows/2020-02-28-23-51-27.bpo-38380.TpOBCj.rst A Misc/NEWS.d/next/macOS/2020-02-28-23-51-47.bpo-38380.u-ySyA.rst M Mac/BuildScript/build-installer.py M PCbuild/get_externals.bat M PCbuild/python.props M PCbuild/readme.txt diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index 3d1381b895b2f..0d69c04ba26b2 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -313,9 +313,9 @@ def library_recipes(): ), ), dict( - name="SQLite 3.28.0", - url="https://www.sqlite.org/2019/sqlite-autoconf-3280000.tar.gz", - checksum='3c68eb400f8354605736cd55400e1572', + name="SQLite 3.31.1", + url="https://sqlite.org/2020/sqlite-autoconf-3310100.tar.gz", + checksum='2d0a553534c521504e3ac3ad3b90f125', extra_cflags=('-Os ' '-DSQLITE_ENABLE_FTS5 ' '-DSQLITE_ENABLE_FTS4 ' diff --git a/Misc/NEWS.d/next/Windows/2020-02-28-23-51-27.bpo-38380.TpOBCj.rst b/Misc/NEWS.d/next/Windows/2020-02-28-23-51-27.bpo-38380.TpOBCj.rst new file mode 100644 index 0000000000000..521075d628f42 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2020-02-28-23-51-27.bpo-38380.TpOBCj.rst @@ -0,0 +1 @@ +Update Windows builds to use SQLite 3.31.1 diff --git a/Misc/NEWS.d/next/macOS/2020-02-28-23-51-47.bpo-38380.u-ySyA.rst b/Misc/NEWS.d/next/macOS/2020-02-28-23-51-47.bpo-38380.u-ySyA.rst new file mode 100644 index 0000000000000..908281b5d172f --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2020-02-28-23-51-47.bpo-38380.u-ySyA.rst @@ -0,0 +1 @@ +Update macOS builds to use SQLite 3.31.1 diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat index f6daf325ef537..a079b752ce559 100644 --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -54,7 +54,7 @@ set libraries= set libraries=%libraries% bzip2-1.0.6 if NOT "%IncludeLibffiSrc%"=="false" set libraries=%libraries% libffi if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-1.1.1d -set libraries=%libraries% sqlite-3.28.0.0 +set libraries=%libraries% sqlite-3.31.1.0 if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.9.0 if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tk-8.6.9.0 if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tix-8.4.3.6 diff --git a/PCbuild/python.props b/PCbuild/python.props index 8583138feb6be..4cba669a427bc 100644 --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -56,7 +56,7 @@ $(EXTERNALS_DIR) $([System.IO.Path]::GetFullPath(`$(PySourcePath)externals`)) $(ExternalsDir)\ - $(ExternalsDir)sqlite-3.28.0.0\ + $(ExternalsDir)sqlite-3.31.1.0\ $(ExternalsDir)bzip2-1.0.6\ $(ExternalsDir)xz-5.2.2\ $(ExternalsDir)libffi\ diff --git a/PCbuild/readme.txt b/PCbuild/readme.txt index 90aac3aa0cab0..5fe3e8c36ecf5 100644 --- a/PCbuild/readme.txt +++ b/PCbuild/readme.txt @@ -184,7 +184,7 @@ _ssl again when building. _sqlite3 - Wraps SQLite 3.28.0.0, which is itself built by sqlite3.vcxproj + Wraps SQLite 3.31.1.0, which is itself built by sqlite3.vcxproj Homepage: http://www.sqlite.org/ _tkinter From webhook-mailer at python.org Mon Mar 2 07:46:04 2020 From: webhook-mailer at python.org (Lidi Zheng) Date: Mon, 02 Mar 2020 12:46:04 -0000 Subject: [Python-checkins] bpo-39764: Make Task.get_stack accept ag_frame (#18669) Message-ID: https://github.com/python/cpython/commit/4482337decdbd0c6e2150346a68b3616bda664aa commit: 4482337decdbd0c6e2150346a68b3616bda664aa branch: master author: Lidi Zheng committer: GitHub date: 2020-03-02T14:45:54+02:00 summary: bpo-39764: Make Task.get_stack accept ag_frame (#18669) Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com> files: A Misc/NEWS.d/next/Library/2020-02-27-18-21-07.bpo-39764.wqPk68.rst M Lib/asyncio/base_tasks.py M Lib/test/test_asyncgen.py diff --git a/Lib/asyncio/base_tasks.py b/Lib/asyncio/base_tasks.py index e2da462fde740..09bb171a2ce75 100644 --- a/Lib/asyncio/base_tasks.py +++ b/Lib/asyncio/base_tasks.py @@ -24,11 +24,18 @@ def _task_repr_info(task): def _task_get_stack(task, limit): frames = [] - try: - # 'async def' coroutines + if hasattr(task._coro, 'cr_frame'): + # case 1: 'async def' coroutines f = task._coro.cr_frame - except AttributeError: + elif hasattr(task._coro, 'gi_frame'): + # case 2: legacy coroutines f = task._coro.gi_frame + elif hasattr(task._coro, 'ag_frame'): + # case 3: async generators + f = task._coro.ag_frame + else: + # case 4: unknown objects + f = None if f is not None: while f is not None: if limit is not None: diff --git a/Lib/test/test_asyncgen.py b/Lib/test/test_asyncgen.py index fb6321d2264f3..62bf877416652 100644 --- a/Lib/test/test_asyncgen.py +++ b/Lib/test/test_asyncgen.py @@ -1191,5 +1191,20 @@ def test_async_gen_aclose_after_exhaustion(self): self.loop.run_until_complete(run()) + def test_async_gen_aclose_compatible_with_get_stack(self): + async def async_generator(): + yield object() + + async def run(): + ag = async_generator() + asyncio.create_task(ag.aclose()) + tasks = asyncio.all_tasks() + for task in tasks: + # No AttributeError raised + task.get_stack() + + self.loop.run_until_complete(run()) + + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Library/2020-02-27-18-21-07.bpo-39764.wqPk68.rst b/Misc/NEWS.d/next/Library/2020-02-27-18-21-07.bpo-39764.wqPk68.rst new file mode 100644 index 0000000000000..d61db2ea221f2 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-02-27-18-21-07.bpo-39764.wqPk68.rst @@ -0,0 +1 @@ +Fix AttributeError when calling get_stack on a PyAsyncGenObject Task \ No newline at end of file From webhook-mailer at python.org Mon Mar 2 08:04:08 2020 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 02 Mar 2020 13:04:08 -0000 Subject: [Python-checkins] bpo-39764: Make Task.get_stack accept ag_frame (GH-18669) Message-ID: https://github.com/python/cpython/commit/43932dc1eaf36d75b2ee0420d8be747001315c26 commit: 43932dc1eaf36d75b2ee0420d8be747001315c26 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2020-03-02T05:03:50-08:00 summary: bpo-39764: Make Task.get_stack accept ag_frame (GH-18669) Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com> (cherry picked from commit 4482337decdbd0c6e2150346a68b3616bda664aa) Co-authored-by: Lidi Zheng files: A Misc/NEWS.d/next/Library/2020-02-27-18-21-07.bpo-39764.wqPk68.rst M Lib/asyncio/base_tasks.py M Lib/test/test_asyncgen.py diff --git a/Lib/asyncio/base_tasks.py b/Lib/asyncio/base_tasks.py index e2da462fde740..09bb171a2ce75 100644 --- a/Lib/asyncio/base_tasks.py +++ b/Lib/asyncio/base_tasks.py @@ -24,11 +24,18 @@ def _task_repr_info(task): def _task_get_stack(task, limit): frames = [] - try: - # 'async def' coroutines + if hasattr(task._coro, 'cr_frame'): + # case 1: 'async def' coroutines f = task._coro.cr_frame - except AttributeError: + elif hasattr(task._coro, 'gi_frame'): + # case 2: legacy coroutines f = task._coro.gi_frame + elif hasattr(task._coro, 'ag_frame'): + # case 3: async generators + f = task._coro.ag_frame + else: + # case 4: unknown objects + f = None if f is not None: while f is not None: if limit is not None: diff --git a/Lib/test/test_asyncgen.py b/Lib/test/test_asyncgen.py index fb6321d2264f3..62bf877416652 100644 --- a/Lib/test/test_asyncgen.py +++ b/Lib/test/test_asyncgen.py @@ -1191,5 +1191,20 @@ def test_async_gen_aclose_after_exhaustion(self): self.loop.run_until_complete(run()) + def test_async_gen_aclose_compatible_with_get_stack(self): + async def async_generator(): + yield object() + + async def run(): + ag = async_generator() + asyncio.create_task(ag.aclose()) + tasks = asyncio.all_tasks() + for task in tasks: + # No AttributeError raised + task.get_stack() + + self.loop.run_until_complete(run()) + + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Library/2020-02-27-18-21-07.bpo-39764.wqPk68.rst b/Misc/NEWS.d/next/Library/2020-02-27-18-21-07.bpo-39764.wqPk68.rst new file mode 100644 index 0000000000000..d61db2ea221f2 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-02-27-18-21-07.bpo-39764.wqPk68.rst @@ -0,0 +1 @@ +Fix AttributeError when calling get_stack on a PyAsyncGenObject Task \ No newline at end of file From webhook-mailer at python.org Mon Mar 2 09:02:26 2020 From: webhook-mailer at python.org (Victor Stinner) Date: Mon, 02 Mar 2020 14:02:26 -0000 Subject: [Python-checkins] bpo-39796: Fix _warnings module initialization (GH-18739) Message-ID: https://github.com/python/cpython/commit/66b7973c1b2e6aa6a2462c6b13971a08cd665af2 commit: 66b7973c1b2e6aa6a2462c6b13971a08cd665af2 branch: master author: Victor Stinner committer: GitHub date: 2020-03-02T15:02:18+01:00 summary: bpo-39796: Fix _warnings module initialization (GH-18739) * Add _PyWarnings_InitState() which only initializes the _warnings module state (tstate->interp->warnings) without creating a module object * Py_InitializeFromConfig() now calls _PyWarnings_InitState() instead of _PyWarnings_Init() * Rename also private functions of _warnings.c to avoid confusion between the public C API and the private C API. files: M Include/internal/pycore_warnings.h M Python/_warnings.c M Python/pylifecycle.c diff --git a/Include/internal/pycore_warnings.h b/Include/internal/pycore_warnings.h index 9a72526279b87..cafe305edb0e0 100644 --- a/Include/internal/pycore_warnings.h +++ b/Include/internal/pycore_warnings.h @@ -17,6 +17,8 @@ struct _warnings_runtime_state { long filters_version; }; +extern PyStatus _PyWarnings_InitState(PyThreadState *tstate); + #ifdef __cplusplus } #endif diff --git a/Python/_warnings.c b/Python/_warnings.c index acef313fc9f25..9ea81bbc6e65f 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -1,4 +1,5 @@ #include "Python.h" +#include "pycore_initconfig.h" #include "pycore_pyerrors.h" #include "pycore_pystate.h" #include "frameobject.h" @@ -28,12 +29,12 @@ _Py_IDENTIFIER(__name__); /* Given a module object, get its per-module state. */ static WarningsState * -_Warnings_GetState() +warnings_get_state(void) { PyThreadState *tstate = _PyThreadState_GET(); if (tstate == NULL) { _PyErr_SetString(tstate, PyExc_RuntimeError, - "_Warnings_GetState: could not identify " + "warnings_get_state: could not identify " "current interpreter"); return NULL; } @@ -42,7 +43,7 @@ _Warnings_GetState() /* Clear the given warnings module state. */ static void -_Warnings_ClearState(WarningsState *st) +warnings_clear_state(WarningsState *st) { Py_CLEAR(st->filters); Py_CLEAR(st->once_registry); @@ -112,7 +113,7 @@ init_filters(void) /* Initialize the given warnings module state. */ static int -_Warnings_InitState(WarningsState *st) +warnings_init_state(WarningsState *st) { if (st->filters == NULL) { st->filters = init_filters(); @@ -140,7 +141,7 @@ _Warnings_InitState(WarningsState *st) return 0; error: - _Warnings_ClearState(st); + warnings_clear_state(st); return -1; } @@ -286,7 +287,7 @@ get_filter(PyObject *category, PyObject *text, Py_ssize_t lineno, Py_ssize_t i; PyObject *warnings_filters; _Py_IDENTIFIER(filters); - WarningsState *st = _Warnings_GetState(); + WarningsState *st = warnings_get_state(); if (st == NULL) { return NULL; } @@ -388,7 +389,7 @@ already_warned(PyObject *registry, PyObject *key, int should_set) if (key == NULL) return -1; - WarningsState *st = _Warnings_GetState(); + WarningsState *st = warnings_get_state(); if (st == NULL) { return -1; } @@ -706,7 +707,7 @@ warn_explicit(PyObject *category, PyObject *message, if (_PyUnicode_EqualToASCIIString(action, "once")) { if (registry == NULL || registry == Py_None) { - WarningsState *st = _Warnings_GetState(); + WarningsState *st = warnings_get_state(); if (st == NULL) { goto cleanup; } @@ -1066,7 +1067,7 @@ warnings_warn_explicit(PyObject *self, PyObject *args, PyObject *kwds) static PyObject * warnings_filters_mutated(PyObject *self, PyObject *args) { - WarningsState *st = _Warnings_GetState(); + WarningsState *st = warnings_get_state(); if (st == NULL) { return NULL; } @@ -1333,6 +1334,16 @@ static struct PyModuleDef warningsmodule = { }; +PyStatus +_PyWarnings_InitState(PyThreadState *tstate) +{ + if (warnings_init_state(&tstate->interp->warnings) < 0) { + return _PyStatus_ERR("can't initialize warnings"); + } + return _PyStatus_OK(); +} + + PyMODINIT_FUNC _PyWarnings_Init(void) { @@ -1343,11 +1354,11 @@ _PyWarnings_Init(void) return NULL; } - WarningsState *st = _Warnings_GetState(); + WarningsState *st = warnings_get_state(); if (st == NULL) { goto error; } - if (_Warnings_InitState(st) < 0) { + if (warnings_init_state(st) < 0) { goto error; } @@ -1370,7 +1381,7 @@ _PyWarnings_Init(void) error: if (st != NULL) { - _Warnings_ClearState(st); + warnings_clear_state(st); } Py_DECREF(m); return NULL; @@ -1380,5 +1391,5 @@ _PyWarnings_Init(void) void _PyWarnings_Fini(PyInterpreterState *interp) { - _Warnings_ClearState(&interp->warnings); + warnings_clear_state(&interp->warnings); } diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index fbeebbdf99da5..7fa165b736869 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -677,8 +677,9 @@ pycore_init_import_warnings(PyThreadState *tstate, PyObject *sysmod) const PyConfig *config = &tstate->interp->config; if (_Py_IsMainInterpreter(tstate)) { /* Initialize _warnings. */ - if (_PyWarnings_Init() == NULL) { - return _PyStatus_ERR("can't initialize warnings"); + status = _PyWarnings_InitState(tstate); + if (_PyStatus_EXCEPTION(status)) { + return status; } if (config->_install_importlib) { From webhook-mailer at python.org Mon Mar 2 10:02:12 2020 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 02 Mar 2020 15:02:12 -0000 Subject: [Python-checkins] bpo-38380: Update macOS & Windows builds to SQLite v3.31.1 (GH-18678) Message-ID: https://github.com/python/cpython/commit/7ca251bd85f1182b9734579975c17fbd0488e2a4 commit: 7ca251bd85f1182b9734579975c17fbd0488e2a4 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2020-03-02T07:02:08-08:00 summary: bpo-38380: Update macOS & Windows builds to SQLite v3.31.1 (GH-18678) Automerge-Triggered-By: @zooba (cherry picked from commit 1382c3289bcfd34ac6811fdf9aa5bc09ca8c320e) Co-authored-by: Erlend Egeberg Aasland files: A Misc/NEWS.d/next/Windows/2020-02-28-23-51-27.bpo-38380.TpOBCj.rst A Misc/NEWS.d/next/macOS/2020-02-28-23-51-47.bpo-38380.u-ySyA.rst M Mac/BuildScript/build-installer.py M PCbuild/get_externals.bat M PCbuild/python.props M PCbuild/readme.txt diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index 6c6c5d2048d19..81d3f4643f441 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -313,9 +313,9 @@ def library_recipes(): ), ), dict( - name="SQLite 3.28.0", - url="https://www.sqlite.org/2019/sqlite-autoconf-3280000.tar.gz", - checksum='3c68eb400f8354605736cd55400e1572', + name="SQLite 3.31.1", + url="https://sqlite.org/2020/sqlite-autoconf-3310100.tar.gz", + checksum='2d0a553534c521504e3ac3ad3b90f125', extra_cflags=('-Os ' '-DSQLITE_ENABLE_FTS5 ' '-DSQLITE_ENABLE_FTS4 ' diff --git a/Misc/NEWS.d/next/Windows/2020-02-28-23-51-27.bpo-38380.TpOBCj.rst b/Misc/NEWS.d/next/Windows/2020-02-28-23-51-27.bpo-38380.TpOBCj.rst new file mode 100644 index 0000000000000..521075d628f42 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2020-02-28-23-51-27.bpo-38380.TpOBCj.rst @@ -0,0 +1 @@ +Update Windows builds to use SQLite 3.31.1 diff --git a/Misc/NEWS.d/next/macOS/2020-02-28-23-51-47.bpo-38380.u-ySyA.rst b/Misc/NEWS.d/next/macOS/2020-02-28-23-51-47.bpo-38380.u-ySyA.rst new file mode 100644 index 0000000000000..908281b5d172f --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2020-02-28-23-51-47.bpo-38380.u-ySyA.rst @@ -0,0 +1 @@ +Update macOS builds to use SQLite 3.31.1 diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat index 83596989e4f1f..cbf193b665c52 100644 --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -50,7 +50,7 @@ echo.Fetching external libraries... set libraries= set libraries=%libraries% bzip2-1.0.6 if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-1.1.1d -set libraries=%libraries% sqlite-3.28.0.0 +set libraries=%libraries% sqlite-3.31.1.0 if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.9.0 if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tk-8.6.9.0 if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tix-8.4.3.6 diff --git a/PCbuild/python.props b/PCbuild/python.props index 6de150be02a5a..7ff32a81b6a52 100644 --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -46,7 +46,7 @@ $(EXTERNALS_DIR) $([System.IO.Path]::GetFullPath(`$(PySourcePath)externals`)) $(ExternalsDir)\ - $(ExternalsDir)sqlite-3.28.0.0\ + $(ExternalsDir)sqlite-3.31.1.0\ $(ExternalsDir)bzip2-1.0.6\ $(ExternalsDir)xz-5.2.2\ $(ExternalsDir)openssl-1.1.1d\ diff --git a/PCbuild/readme.txt b/PCbuild/readme.txt index 664e97f3111b5..9c521fa52d898 100644 --- a/PCbuild/readme.txt +++ b/PCbuild/readme.txt @@ -184,7 +184,7 @@ _ssl again when building. _sqlite3 - Wraps SQLite 3.28.0.0, which is itself built by sqlite3.vcxproj + Wraps SQLite 3.31.1.0, which is itself built by sqlite3.vcxproj Homepage: http://www.sqlite.org/ _tkinter From webhook-mailer at python.org Mon Mar 2 10:02:12 2020 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 02 Mar 2020 15:02:12 -0000 Subject: [Python-checkins] bpo-38380: Update macOS & Windows builds to SQLite v3.31.1 (GH-18678) Message-ID: https://github.com/python/cpython/commit/7ad99821d8ae75222c50e69194a39f535bb058f5 commit: 7ad99821d8ae75222c50e69194a39f535bb058f5 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2020-03-02T07:02:03-08:00 summary: bpo-38380: Update macOS & Windows builds to SQLite v3.31.1 (GH-18678) Automerge-Triggered-By: @zooba (cherry picked from commit 1382c3289bcfd34ac6811fdf9aa5bc09ca8c320e) Co-authored-by: Erlend Egeberg Aasland files: A Misc/NEWS.d/next/Windows/2020-02-28-23-51-27.bpo-38380.TpOBCj.rst A Misc/NEWS.d/next/macOS/2020-02-28-23-51-47.bpo-38380.u-ySyA.rst M Mac/BuildScript/build-installer.py M PCbuild/get_externals.bat M PCbuild/python.props M PCbuild/readme.txt diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index 0dd53647dd33e..31e80637d8a85 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -313,9 +313,9 @@ def library_recipes(): ), ), dict( - name="SQLite 3.28.0", - url="https://www.sqlite.org/2019/sqlite-autoconf-3280000.tar.gz", - checksum='3c68eb400f8354605736cd55400e1572', + name="SQLite 3.31.1", + url="https://sqlite.org/2020/sqlite-autoconf-3310100.tar.gz", + checksum='2d0a553534c521504e3ac3ad3b90f125', extra_cflags=('-Os ' '-DSQLITE_ENABLE_FTS5 ' '-DSQLITE_ENABLE_FTS4 ' diff --git a/Misc/NEWS.d/next/Windows/2020-02-28-23-51-27.bpo-38380.TpOBCj.rst b/Misc/NEWS.d/next/Windows/2020-02-28-23-51-27.bpo-38380.TpOBCj.rst new file mode 100644 index 0000000000000..521075d628f42 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2020-02-28-23-51-27.bpo-38380.TpOBCj.rst @@ -0,0 +1 @@ +Update Windows builds to use SQLite 3.31.1 diff --git a/Misc/NEWS.d/next/macOS/2020-02-28-23-51-47.bpo-38380.u-ySyA.rst b/Misc/NEWS.d/next/macOS/2020-02-28-23-51-47.bpo-38380.u-ySyA.rst new file mode 100644 index 0000000000000..908281b5d172f --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2020-02-28-23-51-47.bpo-38380.u-ySyA.rst @@ -0,0 +1 @@ +Update macOS builds to use SQLite 3.31.1 diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat index 100149e83c164..36ccbd38ad102 100644 --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -54,7 +54,7 @@ set libraries= set libraries=%libraries% bzip2-1.0.6 if NOT "%IncludeLibffiSrc%"=="false" set libraries=%libraries% libffi-3.3.0-rc0-r1 if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-1.1.1d -set libraries=%libraries% sqlite-3.28.0.0 +set libraries=%libraries% sqlite-3.31.1.0 if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.9.0 if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tk-8.6.9.0 if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tix-8.4.3.6 diff --git a/PCbuild/python.props b/PCbuild/python.props index 8583138feb6be..4cba669a427bc 100644 --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -56,7 +56,7 @@ $(EXTERNALS_DIR) $([System.IO.Path]::GetFullPath(`$(PySourcePath)externals`)) $(ExternalsDir)\ - $(ExternalsDir)sqlite-3.28.0.0\ + $(ExternalsDir)sqlite-3.31.1.0\ $(ExternalsDir)bzip2-1.0.6\ $(ExternalsDir)xz-5.2.2\ $(ExternalsDir)libffi\ diff --git a/PCbuild/readme.txt b/PCbuild/readme.txt index 80e3359df3ddb..ceed5dc9c3e72 100644 --- a/PCbuild/readme.txt +++ b/PCbuild/readme.txt @@ -184,7 +184,7 @@ _ssl again when building. _sqlite3 - Wraps SQLite 3.28.0.0, which is itself built by sqlite3.vcxproj + Wraps SQLite 3.31.1.0, which is itself built by sqlite3.vcxproj Homepage: http://www.sqlite.org/ _tkinter From webhook-mailer at python.org Mon Mar 2 15:05:13 2020 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Mon, 02 Mar 2020 20:05:13 -0000 Subject: [Python-checkins] bpo-39831: Fix a reference leak in PyErr_WarnEx(). (GH-18750) Message-ID: https://github.com/python/cpython/commit/2d2f85517f8216146a2f888d1ad4d765b3be2339 commit: 2d2f85517f8216146a2f888d1ad4d765b3be2339 branch: master author: Serhiy Storchaka committer: GitHub date: 2020-03-02T22:05:08+02:00 summary: bpo-39831: Fix a reference leak in PyErr_WarnEx(). (GH-18750) files: M Python/_warnings.c diff --git a/Python/_warnings.c b/Python/_warnings.c index 9ea81bbc6e65f..92378faa61f3e 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -859,11 +859,11 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno, int rc; if (PyErr_Occurred()) { - return 0; + goto handle_error; } *registry = PyDict_New(); if (*registry == NULL) - return 0; + goto handle_error; rc = _PyDict_SetItemId(globals, &PyId___warningregistry__, *registry); if (rc < 0) @@ -893,6 +893,7 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno, dangling reference. */ Py_XDECREF(*registry); Py_XDECREF(*module); + Py_XDECREF(*filename); return 0; } From webhook-mailer at python.org Mon Mar 2 15:22:43 2020 From: webhook-mailer at python.org (Stefan Krah) Date: Mon, 02 Mar 2020 20:22:43 -0000 Subject: [Python-checkins] bpo-39776: Lock ++interp->tstate_next_unique_id. (GH-18746) (#18746) Message-ID: https://github.com/python/cpython/commit/b3b9ade4a3d3fe00d933bcd8fc5c5c755d1024f9 commit: b3b9ade4a3d3fe00d933bcd8fc5c5c755d1024f9 branch: master author: Stefan Krah committer: GitHub date: 2020-03-02T21:22:36+01:00 summary: bpo-39776: Lock ++interp->tstate_next_unique_id. (GH-18746) (#18746) - Threads created by PyGILState_Ensure() could have a duplicate tstate->id. files: A Misc/NEWS.d/next/Core and Builtins/2020-03-02-20-12-33.bpo-39776.fNaxi_.rst M Python/pystate.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-03-02-20-12-33.bpo-39776.fNaxi_.rst b/Misc/NEWS.d/next/Core and Builtins/2020-03-02-20-12-33.bpo-39776.fNaxi_.rst new file mode 100644 index 0000000000000..e5a00bd96ae47 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2020-03-02-20-12-33.bpo-39776.fNaxi_.rst @@ -0,0 +1,6 @@ +Fix race condition where threads created by PyGILState_Ensure() could get a +duplicate id. + +This affects consumers of tstate->id like the contextvar caching machinery, +which could return invalid cached objects under heavy thread load (observed +in embedded scenarios). diff --git a/Python/pystate.c b/Python/pystate.c index ebc17ea5a7219..4001c63ff25ee 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -606,13 +606,12 @@ new_threadstate(PyInterpreterState *interp, int init) tstate->context = NULL; tstate->context_ver = 1; - tstate->id = ++interp->tstate_next_unique_id; - if (init) { _PyThreadState_Init(tstate); } HEAD_LOCK(runtime); + tstate->id = ++interp->tstate_next_unique_id; tstate->prev = NULL; tstate->next = interp->tstate_head; if (tstate->next) From webhook-mailer at python.org Mon Mar 2 18:12:58 2020 From: webhook-mailer at python.org (Pablo Galindo) Date: Mon, 02 Mar 2020 23:12:58 -0000 Subject: [Python-checkins] bpo-39778: Don't traverse weak-reference lists OrderedDict's tp_traverse and tp_clear (GH-18749) Message-ID: https://github.com/python/cpython/commit/0c2b509f9d1d3a9065bc62c2407e1dc2ed70e9c2 commit: 0c2b509f9d1d3a9065bc62c2407e1dc2ed70e9c2 branch: master author: Pablo Galindo committer: GitHub date: 2020-03-02T23:12:54Z summary: bpo-39778: Don't traverse weak-reference lists OrderedDict's tp_traverse and tp_clear (GH-18749) Objects do not own weak references to them directly through the __weakref__ list so these do not need to be traversed by the GC. files: A Misc/NEWS.d/next/Core and Builtins/2020-03-02-19-21-21.bpo-39778._YGLEc.rst M Lib/test/test_ordered_dict.py M Objects/odictobject.c diff --git a/Lib/test/test_ordered_dict.py b/Lib/test/test_ordered_dict.py index f337be8eb8551..eb0a8f4ba0d48 100644 --- a/Lib/test/test_ordered_dict.py +++ b/Lib/test/test_ordered_dict.py @@ -753,6 +753,26 @@ def test_iterators_pickling(self): self.assertEqual(list(unpickled), expected) self.assertEqual(list(it), expected) + @support.cpython_only + def test_weakref_list_is_not_traversed(self): + # Check that the weakref list is not traversed when collecting + # OrderedDict objects. See bpo-39778 for more information. + + gc.collect() + + x = self.OrderedDict() + x.cycle = x + + cycle = [] + cycle.append(cycle) + + x_ref = weakref.ref(x) + cycle.append(x_ref) + + del x, cycle, x_ref + + gc.collect() + class PurePythonOrderedDictSubclassTests(PurePythonOrderedDictTests): diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-03-02-19-21-21.bpo-39778._YGLEc.rst b/Misc/NEWS.d/next/Core and Builtins/2020-03-02-19-21-21.bpo-39778._YGLEc.rst new file mode 100644 index 0000000000000..dc49512167365 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2020-03-02-19-21-21.bpo-39778._YGLEc.rst @@ -0,0 +1,2 @@ +Fixed a crash due to incorrect handling of weak references in +``collections.OrderedDict`` classes. Patch by Pablo Galindo. diff --git a/Objects/odictobject.c b/Objects/odictobject.c index f412220e8cc02..6813cddfddca5 100644 --- a/Objects/odictobject.c +++ b/Objects/odictobject.c @@ -1454,7 +1454,6 @@ odict_traverse(PyODictObject *od, visitproc visit, void *arg) _ODictNode *node; Py_VISIT(od->od_inst_dict); - Py_VISIT(od->od_weakreflist); _odict_FOREACH(od, node) { Py_VISIT(_odictnode_KEY(node)); } @@ -1467,7 +1466,6 @@ static int odict_tp_clear(PyODictObject *od) { Py_CLEAR(od->od_inst_dict); - Py_CLEAR(od->od_weakreflist); PyDict_Clear((PyObject *)od); _odict_clear_nodes(od); return 0; From webhook-mailer at python.org Mon Mar 2 18:53:07 2020 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 02 Mar 2020 23:53:07 -0000 Subject: [Python-checkins] bpo-39778: Don't traverse weak-reference lists OrderedDict's tp_traverse and tp_clear (GH-18749) Message-ID: https://github.com/python/cpython/commit/69ded3944c202da972754644c0bbf7f77cc5e8ea commit: 69ded3944c202da972754644c0bbf7f77cc5e8ea branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2020-03-02T15:53:03-08:00 summary: bpo-39778: Don't traverse weak-reference lists OrderedDict's tp_traverse and tp_clear (GH-18749) Objects do not own weak references to them directly through the __weakref__ list so these do not need to be traversed by the GC. (cherry picked from commit 0c2b509f9d1d3a9065bc62c2407e1dc2ed70e9c2) Co-authored-by: Pablo Galindo files: A Misc/NEWS.d/next/Core and Builtins/2020-03-02-19-21-21.bpo-39778._YGLEc.rst M Lib/test/test_ordered_dict.py M Objects/odictobject.c diff --git a/Lib/test/test_ordered_dict.py b/Lib/test/test_ordered_dict.py index b1d7f86a6760b..0e5c7fc750389 100644 --- a/Lib/test/test_ordered_dict.py +++ b/Lib/test/test_ordered_dict.py @@ -749,6 +749,26 @@ def test_iterators_pickling(self): self.assertEqual(list(unpickled), expected) self.assertEqual(list(it), expected) + @support.cpython_only + def test_weakref_list_is_not_traversed(self): + # Check that the weakref list is not traversed when collecting + # OrderedDict objects. See bpo-39778 for more information. + + gc.collect() + + x = self.OrderedDict() + x.cycle = x + + cycle = [] + cycle.append(cycle) + + x_ref = weakref.ref(x) + cycle.append(x_ref) + + del x, cycle, x_ref + + gc.collect() + class PurePythonOrderedDictSubclassTests(PurePythonOrderedDictTests): diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-03-02-19-21-21.bpo-39778._YGLEc.rst b/Misc/NEWS.d/next/Core and Builtins/2020-03-02-19-21-21.bpo-39778._YGLEc.rst new file mode 100644 index 0000000000000..dc49512167365 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2020-03-02-19-21-21.bpo-39778._YGLEc.rst @@ -0,0 +1,2 @@ +Fixed a crash due to incorrect handling of weak references in +``collections.OrderedDict`` classes. Patch by Pablo Galindo. diff --git a/Objects/odictobject.c b/Objects/odictobject.c index 88afc61f6071d..c1fee04c4227d 100644 --- a/Objects/odictobject.c +++ b/Objects/odictobject.c @@ -1463,7 +1463,6 @@ odict_traverse(PyODictObject *od, visitproc visit, void *arg) _ODictNode *node; Py_VISIT(od->od_inst_dict); - Py_VISIT(od->od_weakreflist); _odict_FOREACH(od, node) { Py_VISIT(_odictnode_KEY(node)); } @@ -1476,7 +1475,6 @@ static int odict_tp_clear(PyODictObject *od) { Py_CLEAR(od->od_inst_dict); - Py_CLEAR(od->od_weakreflist); PyDict_Clear((PyObject *)od); _odict_clear_nodes(od); return 0; From webhook-mailer at python.org Mon Mar 2 18:55:24 2020 From: webhook-mailer at python.org (Pablo Galindo) Date: Mon, 02 Mar 2020 23:55:24 -0000 Subject: [Python-checkins] [3.8] bpo-39778: Don't traverse weak-reference lists OrderedDict's tp_traverse and tp_clear (GH-18749) (GH-18756) Message-ID: https://github.com/python/cpython/commit/9ddcb914f9c2debe7c1359b2450cd1573e86b91c commit: 9ddcb914f9c2debe7c1359b2450cd1573e86b91c branch: 3.8 author: Pablo Galindo committer: GitHub date: 2020-03-02T23:55:20Z summary: [3.8] bpo-39778: Don't traverse weak-reference lists OrderedDict's tp_traverse and tp_clear (GH-18749) (GH-18756) Objects do not own weak references to them directly through the __weakref__ list so these do not need to be traversed by the GC. (cherry picked from commit 0c2b509) files: A Misc/NEWS.d/next/Core and Builtins/2020-03-02-19-21-21.bpo-39778._YGLEc.rst M Lib/test/test_ordered_dict.py M Objects/odictobject.c diff --git a/Lib/test/test_ordered_dict.py b/Lib/test/test_ordered_dict.py index 148a9bdc35ee3..085e5f60ed93b 100644 --- a/Lib/test/test_ordered_dict.py +++ b/Lib/test/test_ordered_dict.py @@ -753,6 +753,26 @@ def test_iterators_pickling(self): self.assertEqual(list(unpickled), expected) self.assertEqual(list(it), expected) + @support.cpython_only + def test_weakref_list_is_not_traversed(self): + # Check that the weakref list is not traversed when collecting + # OrderedDict objects. See bpo-39778 for more information. + + gc.collect() + + x = self.OrderedDict() + x.cycle = x + + cycle = [] + cycle.append(cycle) + + x_ref = weakref.ref(x) + cycle.append(x_ref) + + del x, cycle, x_ref + + gc.collect() + class PurePythonOrderedDictSubclassTests(PurePythonOrderedDictTests): diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-03-02-19-21-21.bpo-39778._YGLEc.rst b/Misc/NEWS.d/next/Core and Builtins/2020-03-02-19-21-21.bpo-39778._YGLEc.rst new file mode 100644 index 0000000000000..dc49512167365 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2020-03-02-19-21-21.bpo-39778._YGLEc.rst @@ -0,0 +1,2 @@ +Fixed a crash due to incorrect handling of weak references in +``collections.OrderedDict`` classes. Patch by Pablo Galindo. diff --git a/Objects/odictobject.c b/Objects/odictobject.c index 4c9ae3bc93468..ac0da9bd5bae3 100644 --- a/Objects/odictobject.c +++ b/Objects/odictobject.c @@ -1453,7 +1453,6 @@ odict_traverse(PyODictObject *od, visitproc visit, void *arg) _ODictNode *node; Py_VISIT(od->od_inst_dict); - Py_VISIT(od->od_weakreflist); _odict_FOREACH(od, node) { Py_VISIT(_odictnode_KEY(node)); } @@ -1466,7 +1465,6 @@ static int odict_tp_clear(PyODictObject *od) { Py_CLEAR(od->od_inst_dict); - Py_CLEAR(od->od_weakreflist); PyDict_Clear((PyObject *)od); _odict_clear_nodes(od); return 0; From webhook-mailer at python.org Mon Mar 2 19:04:19 2020 From: webhook-mailer at python.org (Steve Dower) Date: Tue, 03 Mar 2020 00:04:19 -0000 Subject: [Python-checkins] bpo-38597: Never statically link extension initialization code on Windows (GH-18724) Message-ID: https://github.com/python/cpython/commit/ce3a4984089b8e0ce5422ca32d75ad057b008074 commit: ce3a4984089b8e0ce5422ca32d75ad057b008074 branch: master author: Steve Dower committer: GitHub date: 2020-03-03T00:04:11Z summary: bpo-38597: Never statically link extension initialization code on Windows (GH-18724) files: A Misc/NEWS.d/next/Windows/2020-03-01-15-04-54.bpo-38597.MnHdYl.rst M Lib/distutils/_msvccompiler.py M Lib/distutils/tests/test_msvccompiler.py M PCbuild/pythoncore.vcxproj diff --git a/Lib/distutils/_msvccompiler.py b/Lib/distutils/_msvccompiler.py index e8e4b717b9736..03a5986d984dc 100644 --- a/Lib/distutils/_msvccompiler.py +++ b/Lib/distutils/_msvccompiler.py @@ -97,28 +97,11 @@ def _find_vc2017(): } def _find_vcvarsall(plat_spec): + # bpo-38597: Removed vcruntime return value _, best_dir = _find_vc2017() - vcruntime = None - - if plat_spec in PLAT_SPEC_TO_RUNTIME: - vcruntime_plat = PLAT_SPEC_TO_RUNTIME[plat_spec] - else: - vcruntime_plat = 'x64' if 'amd64' in plat_spec else 'x86' - - if best_dir: - vcredist = os.path.join(best_dir, "..", "..", "redist", "MSVC", "**", - vcruntime_plat, "Microsoft.VC14*.CRT", "vcruntime140.dll") - try: - import glob - vcruntime = glob.glob(vcredist, recursive=True)[-1] - except (ImportError, OSError, LookupError): - vcruntime = None if not best_dir: best_version, best_dir = _find_vc2015() - if best_version: - vcruntime = os.path.join(best_dir, 'redist', vcruntime_plat, - "Microsoft.VC140.CRT", "vcruntime140.dll") if not best_dir: log.debug("No suitable Visual C++ version found") @@ -129,11 +112,7 @@ def _find_vcvarsall(plat_spec): log.debug("%s cannot be found", vcvarsall) return None, None - if not vcruntime or not os.path.isfile(vcruntime): - log.debug("%s cannot be found", vcruntime) - vcruntime = None - - return vcvarsall, vcruntime + return vcvarsall, None def _get_vc_env(plat_spec): if os.getenv("DISTUTILS_USE_SDK"): @@ -142,7 +121,7 @@ def _get_vc_env(plat_spec): for key, value in os.environ.items() } - vcvarsall, vcruntime = _find_vcvarsall(plat_spec) + vcvarsall, _ = _find_vcvarsall(plat_spec) if not vcvarsall: raise DistutilsPlatformError("Unable to find vcvarsall.bat") @@ -163,8 +142,6 @@ def _get_vc_env(plat_spec): if key and value } - if vcruntime: - env['py_vcruntime_redist'] = vcruntime return env def _find_exe(exe, paths=None): @@ -194,12 +171,6 @@ def _find_exe(exe, paths=None): 'win-arm64' : 'x86_arm64' } -# A set containing the DLLs that are guaranteed to be available for -# all micro versions of this Python version. Known extension -# dependencies that are not in this set will be copied to the output -# path. -_BUNDLED_DLLS = frozenset(['vcruntime140.dll']) - class MSVCCompiler(CCompiler) : """Concrete class that implements an interface to Microsoft Visual C++, as defined by the CCompiler abstract class.""" @@ -263,7 +234,6 @@ def initialize(self, plat_name=None): self.rc = _find_exe("rc.exe", paths) # resource compiler self.mc = _find_exe("mc.exe", paths) # message compiler self.mt = _find_exe("mt.exe", paths) # message compiler - self._vcruntime_redist = vc_env.get('py_vcruntime_redist', '') for dir in vc_env.get('include', '').split(os.pathsep): if dir: @@ -274,13 +244,12 @@ def initialize(self, plat_name=None): self.add_library_dir(dir.rstrip(os.sep)) self.preprocess_options = None - # If vcruntime_redist is available, link against it dynamically. Otherwise, - # use /MT[d] to build statically, then switch from libucrt[d].lib to ucrt[d].lib - # later to dynamically link to ucrtbase but not vcruntime. + # bpo-38597: Always compile with dynamic linking + # Future releases of Python 3.x will include all past + # versions of vcruntime*.dll for compatibility. self.compile_options = [ - '/nologo', '/Ox', '/W3', '/GL', '/DNDEBUG' + '/nologo', '/Ox', '/W3', '/GL', '/DNDEBUG', '/MD' ] - self.compile_options.append('/MD' if self._vcruntime_redist else '/MT') self.compile_options_debug = [ '/nologo', '/Od', '/MDd', '/Zi', '/W3', '/D_DEBUG' @@ -289,8 +258,6 @@ def initialize(self, plat_name=None): ldflags = [ '/nologo', '/INCREMENTAL:NO', '/LTCG' ] - if not self._vcruntime_redist: - ldflags.extend(('/nodefaultlib:libucrt.lib', 'ucrt.lib')) ldflags_debug = [ '/nologo', '/INCREMENTAL:NO', '/LTCG', '/DEBUG:FULL' @@ -532,24 +499,11 @@ def link(self, try: log.debug('Executing "%s" %s', self.linker, ' '.join(ld_args)) self.spawn([self.linker] + ld_args) - self._copy_vcruntime(output_dir) except DistutilsExecError as msg: raise LinkError(msg) else: log.debug("skipping %s (up-to-date)", output_filename) - def _copy_vcruntime(self, output_dir): - vcruntime = self._vcruntime_redist - if not vcruntime or not os.path.isfile(vcruntime): - return - - if os.path.basename(vcruntime).lower() in _BUNDLED_DLLS: - return - - log.debug('Copying "%s"', vcruntime) - vcruntime = shutil.copy(vcruntime, output_dir) - os.chmod(vcruntime, stat.S_IWRITE) - def spawn(self, cmd): old_path = os.getenv('path') try: diff --git a/Lib/distutils/tests/test_msvccompiler.py b/Lib/distutils/tests/test_msvccompiler.py index 70a9c93a4e880..b518d6a78b332 100644 --- a/Lib/distutils/tests/test_msvccompiler.py +++ b/Lib/distutils/tests/test_msvccompiler.py @@ -32,57 +32,6 @@ def _find_vcvarsall(plat_spec): finally: _msvccompiler._find_vcvarsall = old_find_vcvarsall - def test_compiler_options(self): - import distutils._msvccompiler as _msvccompiler - # suppress path to vcruntime from _find_vcvarsall to - # check that /MT is added to compile options - old_find_vcvarsall = _msvccompiler._find_vcvarsall - def _find_vcvarsall(plat_spec): - return old_find_vcvarsall(plat_spec)[0], None - _msvccompiler._find_vcvarsall = _find_vcvarsall - try: - compiler = _msvccompiler.MSVCCompiler() - compiler.initialize() - - self.assertIn('/MT', compiler.compile_options) - self.assertNotIn('/MD', compiler.compile_options) - finally: - _msvccompiler._find_vcvarsall = old_find_vcvarsall - - def test_vcruntime_copy(self): - import distutils._msvccompiler as _msvccompiler - # force path to a known file - it doesn't matter - # what we copy as long as its name is not in - # _msvccompiler._BUNDLED_DLLS - old_find_vcvarsall = _msvccompiler._find_vcvarsall - def _find_vcvarsall(plat_spec): - return old_find_vcvarsall(plat_spec)[0], __file__ - _msvccompiler._find_vcvarsall = _find_vcvarsall - try: - tempdir = self.mkdtemp() - compiler = _msvccompiler.MSVCCompiler() - compiler.initialize() - compiler._copy_vcruntime(tempdir) - - self.assertTrue(os.path.isfile(os.path.join( - tempdir, os.path.basename(__file__)))) - finally: - _msvccompiler._find_vcvarsall = old_find_vcvarsall - - def test_vcruntime_skip_copy(self): - import distutils._msvccompiler as _msvccompiler - - tempdir = self.mkdtemp() - compiler = _msvccompiler.MSVCCompiler() - compiler.initialize() - dll = compiler._vcruntime_redist - self.assertTrue(os.path.isfile(dll), dll or "") - - compiler._copy_vcruntime(tempdir) - - self.assertFalse(os.path.isfile(os.path.join( - tempdir, os.path.basename(dll))), dll or "") - def test_get_vc_env_unicode(self): import distutils._msvccompiler as _msvccompiler diff --git a/Misc/NEWS.d/next/Windows/2020-03-01-15-04-54.bpo-38597.MnHdYl.rst b/Misc/NEWS.d/next/Windows/2020-03-01-15-04-54.bpo-38597.MnHdYl.rst new file mode 100644 index 0000000000000..7f3a2e756c5a1 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2020-03-01-15-04-54.bpo-38597.MnHdYl.rst @@ -0,0 +1,4 @@ +:mod:`distutils` will no longer statically link :file:`vcruntime140.dll` +when a redistributable version is unavailable. All future releases of +CPython will include a copy of this DLL to ensure distributed extensions can +continue to load. diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index 0acf7f4a8de80..ac73a912630b5 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -536,6 +536,8 @@ + + From webhook-mailer at python.org Mon Mar 2 19:26:31 2020 From: webhook-mailer at python.org (Steve Dower) Date: Tue, 03 Mar 2020 00:26:31 -0000 Subject: [Python-checkins] [3.7] bpo-38597: Never statically link extension initialization code on Windows (GH-18724) (GH-18759) Message-ID: https://github.com/python/cpython/commit/8a5f7ad5e423b74ea612e25472e5bff3adf1ea87 commit: 8a5f7ad5e423b74ea612e25472e5bff3adf1ea87 branch: 3.7 author: Steve Dower committer: GitHub date: 2020-03-02T16:26:26-08:00 summary: [3.7] bpo-38597: Never statically link extension initialization code on Windows (GH-18724) (GH-18759) Automerge-Triggered-By: @zooba files: A Misc/NEWS.d/next/Windows/2020-03-01-15-04-54.bpo-38597.MnHdYl.rst M Lib/distutils/_msvccompiler.py M Lib/distutils/tests/test_msvccompiler.py M PCbuild/pythoncore.vcxproj diff --git a/Lib/distutils/_msvccompiler.py b/Lib/distutils/_msvccompiler.py index 26112b481af3d..37ac478fb6f59 100644 --- a/Lib/distutils/_msvccompiler.py +++ b/Lib/distutils/_msvccompiler.py @@ -90,23 +90,11 @@ def _find_vc2017(): return None, None def _find_vcvarsall(plat_spec): + # bpo-38597: Removed vcruntime return value _, best_dir = _find_vc2017() - vcruntime = None - vcruntime_plat = 'x64' if 'amd64' in plat_spec else 'x86' - if best_dir: - vcredist = os.path.join(best_dir, "..", "..", "redist", "MSVC", "**", - vcruntime_plat, "Microsoft.VC14*.CRT", "vcruntime140.dll") - try: - import glob - vcruntime = glob.glob(vcredist, recursive=True)[-1] - except (ImportError, OSError, LookupError): - vcruntime = None if not best_dir: best_version, best_dir = _find_vc2015() - if best_version: - vcruntime = os.path.join(best_dir, 'redist', vcruntime_plat, - "Microsoft.VC140.CRT", "vcruntime140.dll") if not best_dir: log.debug("No suitable Visual C++ version found") @@ -117,11 +105,7 @@ def _find_vcvarsall(plat_spec): log.debug("%s cannot be found", vcvarsall) return None, None - if not vcruntime or not os.path.isfile(vcruntime): - log.debug("%s cannot be found", vcruntime) - vcruntime = None - - return vcvarsall, vcruntime + return vcvarsall, None def _get_vc_env(plat_spec): if os.getenv("DISTUTILS_USE_SDK"): @@ -130,7 +114,7 @@ def _get_vc_env(plat_spec): for key, value in os.environ.items() } - vcvarsall, vcruntime = _find_vcvarsall(plat_spec) + vcvarsall, _ = _find_vcvarsall(plat_spec) if not vcvarsall: raise DistutilsPlatformError("Unable to find vcvarsall.bat") @@ -151,8 +135,6 @@ def _get_vc_env(plat_spec): if key and value } - if vcruntime: - env['py_vcruntime_redist'] = vcruntime return env def _find_exe(exe, paths=None): @@ -180,12 +162,6 @@ def _find_exe(exe, paths=None): 'win-amd64' : 'x86_amd64', } -# A set containing the DLLs that are guaranteed to be available for -# all micro versions of this Python version. Known extension -# dependencies that are not in this set will be copied to the output -# path. -_BUNDLED_DLLS = frozenset(['vcruntime140.dll']) - class MSVCCompiler(CCompiler) : """Concrete class that implements an interface to Microsoft Visual C++, as defined by the CCompiler abstract class.""" @@ -249,7 +225,6 @@ def initialize(self, plat_name=None): self.rc = _find_exe("rc.exe", paths) # resource compiler self.mc = _find_exe("mc.exe", paths) # message compiler self.mt = _find_exe("mt.exe", paths) # message compiler - self._vcruntime_redist = vc_env.get('py_vcruntime_redist', '') for dir in vc_env.get('include', '').split(os.pathsep): if dir: @@ -260,13 +235,12 @@ def initialize(self, plat_name=None): self.add_library_dir(dir.rstrip(os.sep)) self.preprocess_options = None - # If vcruntime_redist is available, link against it dynamically. Otherwise, - # use /MT[d] to build statically, then switch from libucrt[d].lib to ucrt[d].lib - # later to dynamically link to ucrtbase but not vcruntime. + # bpo-38597: Always compile with dynamic linking + # Future releases of Python 3.x will include all past + # versions of vcruntime*.dll for compatibility. self.compile_options = [ - '/nologo', '/Ox', '/W3', '/GL', '/DNDEBUG' + '/nologo', '/Ox', '/W3', '/GL', '/DNDEBUG', '/MD' ] - self.compile_options.append('/MD' if self._vcruntime_redist else '/MT') self.compile_options_debug = [ '/nologo', '/Od', '/MDd', '/Zi', '/W3', '/D_DEBUG' @@ -275,8 +249,6 @@ def initialize(self, plat_name=None): ldflags = [ '/nologo', '/INCREMENTAL:NO', '/LTCG' ] - if not self._vcruntime_redist: - ldflags.extend(('/nodefaultlib:libucrt.lib', 'ucrt.lib')) ldflags_debug = [ '/nologo', '/INCREMENTAL:NO', '/LTCG', '/DEBUG:FULL' @@ -518,24 +490,11 @@ def link(self, try: log.debug('Executing "%s" %s', self.linker, ' '.join(ld_args)) self.spawn([self.linker] + ld_args) - self._copy_vcruntime(output_dir) except DistutilsExecError as msg: raise LinkError(msg) else: log.debug("skipping %s (up-to-date)", output_filename) - def _copy_vcruntime(self, output_dir): - vcruntime = self._vcruntime_redist - if not vcruntime or not os.path.isfile(vcruntime): - return - - if os.path.basename(vcruntime).lower() in _BUNDLED_DLLS: - return - - log.debug('Copying "%s"', vcruntime) - vcruntime = shutil.copy(vcruntime, output_dir) - os.chmod(vcruntime, stat.S_IWRITE) - def spawn(self, cmd): old_path = os.getenv('path') try: diff --git a/Lib/distutils/tests/test_msvccompiler.py b/Lib/distutils/tests/test_msvccompiler.py index 70a9c93a4e880..b518d6a78b332 100644 --- a/Lib/distutils/tests/test_msvccompiler.py +++ b/Lib/distutils/tests/test_msvccompiler.py @@ -32,57 +32,6 @@ def _find_vcvarsall(plat_spec): finally: _msvccompiler._find_vcvarsall = old_find_vcvarsall - def test_compiler_options(self): - import distutils._msvccompiler as _msvccompiler - # suppress path to vcruntime from _find_vcvarsall to - # check that /MT is added to compile options - old_find_vcvarsall = _msvccompiler._find_vcvarsall - def _find_vcvarsall(plat_spec): - return old_find_vcvarsall(plat_spec)[0], None - _msvccompiler._find_vcvarsall = _find_vcvarsall - try: - compiler = _msvccompiler.MSVCCompiler() - compiler.initialize() - - self.assertIn('/MT', compiler.compile_options) - self.assertNotIn('/MD', compiler.compile_options) - finally: - _msvccompiler._find_vcvarsall = old_find_vcvarsall - - def test_vcruntime_copy(self): - import distutils._msvccompiler as _msvccompiler - # force path to a known file - it doesn't matter - # what we copy as long as its name is not in - # _msvccompiler._BUNDLED_DLLS - old_find_vcvarsall = _msvccompiler._find_vcvarsall - def _find_vcvarsall(plat_spec): - return old_find_vcvarsall(plat_spec)[0], __file__ - _msvccompiler._find_vcvarsall = _find_vcvarsall - try: - tempdir = self.mkdtemp() - compiler = _msvccompiler.MSVCCompiler() - compiler.initialize() - compiler._copy_vcruntime(tempdir) - - self.assertTrue(os.path.isfile(os.path.join( - tempdir, os.path.basename(__file__)))) - finally: - _msvccompiler._find_vcvarsall = old_find_vcvarsall - - def test_vcruntime_skip_copy(self): - import distutils._msvccompiler as _msvccompiler - - tempdir = self.mkdtemp() - compiler = _msvccompiler.MSVCCompiler() - compiler.initialize() - dll = compiler._vcruntime_redist - self.assertTrue(os.path.isfile(dll), dll or "") - - compiler._copy_vcruntime(tempdir) - - self.assertFalse(os.path.isfile(os.path.join( - tempdir, os.path.basename(dll))), dll or "") - def test_get_vc_env_unicode(self): import distutils._msvccompiler as _msvccompiler diff --git a/Misc/NEWS.d/next/Windows/2020-03-01-15-04-54.bpo-38597.MnHdYl.rst b/Misc/NEWS.d/next/Windows/2020-03-01-15-04-54.bpo-38597.MnHdYl.rst new file mode 100644 index 0000000000000..7f3a2e756c5a1 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2020-03-01-15-04-54.bpo-38597.MnHdYl.rst @@ -0,0 +1,4 @@ +:mod:`distutils` will no longer statically link :file:`vcruntime140.dll` +when a redistributable version is unavailable. All future releases of +CPython will include a copy of this DLL to ensure distributed extensions can +continue to load. diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index a56fb7a9cc46b..a66dac066e289 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -469,6 +469,8 @@ + + From webhook-mailer at python.org Mon Mar 2 19:30:26 2020 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 03 Mar 2020 00:30:26 -0000 Subject: [Python-checkins] bpo-38597: Never statically link extension initialization code on Windows (GH-18724) Message-ID: https://github.com/python/cpython/commit/0d20364b132014eec609b900997c34779a4d548c commit: 0d20364b132014eec609b900997c34779a4d548c branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2020-03-02T16:30:18-08:00 summary: bpo-38597: Never statically link extension initialization code on Windows (GH-18724) (cherry picked from commit ce3a4984089b8e0ce5422ca32d75ad057b008074) Co-authored-by: Steve Dower files: A Misc/NEWS.d/next/Windows/2020-03-01-15-04-54.bpo-38597.MnHdYl.rst M Lib/distutils/_msvccompiler.py M Lib/distutils/tests/test_msvccompiler.py M PCbuild/pythoncore.vcxproj diff --git a/Lib/distutils/_msvccompiler.py b/Lib/distutils/_msvccompiler.py index e8e4b717b9736..03a5986d984dc 100644 --- a/Lib/distutils/_msvccompiler.py +++ b/Lib/distutils/_msvccompiler.py @@ -97,28 +97,11 @@ def _find_vc2017(): } def _find_vcvarsall(plat_spec): + # bpo-38597: Removed vcruntime return value _, best_dir = _find_vc2017() - vcruntime = None - - if plat_spec in PLAT_SPEC_TO_RUNTIME: - vcruntime_plat = PLAT_SPEC_TO_RUNTIME[plat_spec] - else: - vcruntime_plat = 'x64' if 'amd64' in plat_spec else 'x86' - - if best_dir: - vcredist = os.path.join(best_dir, "..", "..", "redist", "MSVC", "**", - vcruntime_plat, "Microsoft.VC14*.CRT", "vcruntime140.dll") - try: - import glob - vcruntime = glob.glob(vcredist, recursive=True)[-1] - except (ImportError, OSError, LookupError): - vcruntime = None if not best_dir: best_version, best_dir = _find_vc2015() - if best_version: - vcruntime = os.path.join(best_dir, 'redist', vcruntime_plat, - "Microsoft.VC140.CRT", "vcruntime140.dll") if not best_dir: log.debug("No suitable Visual C++ version found") @@ -129,11 +112,7 @@ def _find_vcvarsall(plat_spec): log.debug("%s cannot be found", vcvarsall) return None, None - if not vcruntime or not os.path.isfile(vcruntime): - log.debug("%s cannot be found", vcruntime) - vcruntime = None - - return vcvarsall, vcruntime + return vcvarsall, None def _get_vc_env(plat_spec): if os.getenv("DISTUTILS_USE_SDK"): @@ -142,7 +121,7 @@ def _get_vc_env(plat_spec): for key, value in os.environ.items() } - vcvarsall, vcruntime = _find_vcvarsall(plat_spec) + vcvarsall, _ = _find_vcvarsall(plat_spec) if not vcvarsall: raise DistutilsPlatformError("Unable to find vcvarsall.bat") @@ -163,8 +142,6 @@ def _get_vc_env(plat_spec): if key and value } - if vcruntime: - env['py_vcruntime_redist'] = vcruntime return env def _find_exe(exe, paths=None): @@ -194,12 +171,6 @@ def _find_exe(exe, paths=None): 'win-arm64' : 'x86_arm64' } -# A set containing the DLLs that are guaranteed to be available for -# all micro versions of this Python version. Known extension -# dependencies that are not in this set will be copied to the output -# path. -_BUNDLED_DLLS = frozenset(['vcruntime140.dll']) - class MSVCCompiler(CCompiler) : """Concrete class that implements an interface to Microsoft Visual C++, as defined by the CCompiler abstract class.""" @@ -263,7 +234,6 @@ def initialize(self, plat_name=None): self.rc = _find_exe("rc.exe", paths) # resource compiler self.mc = _find_exe("mc.exe", paths) # message compiler self.mt = _find_exe("mt.exe", paths) # message compiler - self._vcruntime_redist = vc_env.get('py_vcruntime_redist', '') for dir in vc_env.get('include', '').split(os.pathsep): if dir: @@ -274,13 +244,12 @@ def initialize(self, plat_name=None): self.add_library_dir(dir.rstrip(os.sep)) self.preprocess_options = None - # If vcruntime_redist is available, link against it dynamically. Otherwise, - # use /MT[d] to build statically, then switch from libucrt[d].lib to ucrt[d].lib - # later to dynamically link to ucrtbase but not vcruntime. + # bpo-38597: Always compile with dynamic linking + # Future releases of Python 3.x will include all past + # versions of vcruntime*.dll for compatibility. self.compile_options = [ - '/nologo', '/Ox', '/W3', '/GL', '/DNDEBUG' + '/nologo', '/Ox', '/W3', '/GL', '/DNDEBUG', '/MD' ] - self.compile_options.append('/MD' if self._vcruntime_redist else '/MT') self.compile_options_debug = [ '/nologo', '/Od', '/MDd', '/Zi', '/W3', '/D_DEBUG' @@ -289,8 +258,6 @@ def initialize(self, plat_name=None): ldflags = [ '/nologo', '/INCREMENTAL:NO', '/LTCG' ] - if not self._vcruntime_redist: - ldflags.extend(('/nodefaultlib:libucrt.lib', 'ucrt.lib')) ldflags_debug = [ '/nologo', '/INCREMENTAL:NO', '/LTCG', '/DEBUG:FULL' @@ -532,24 +499,11 @@ def link(self, try: log.debug('Executing "%s" %s', self.linker, ' '.join(ld_args)) self.spawn([self.linker] + ld_args) - self._copy_vcruntime(output_dir) except DistutilsExecError as msg: raise LinkError(msg) else: log.debug("skipping %s (up-to-date)", output_filename) - def _copy_vcruntime(self, output_dir): - vcruntime = self._vcruntime_redist - if not vcruntime or not os.path.isfile(vcruntime): - return - - if os.path.basename(vcruntime).lower() in _BUNDLED_DLLS: - return - - log.debug('Copying "%s"', vcruntime) - vcruntime = shutil.copy(vcruntime, output_dir) - os.chmod(vcruntime, stat.S_IWRITE) - def spawn(self, cmd): old_path = os.getenv('path') try: diff --git a/Lib/distutils/tests/test_msvccompiler.py b/Lib/distutils/tests/test_msvccompiler.py index 70a9c93a4e880..b518d6a78b332 100644 --- a/Lib/distutils/tests/test_msvccompiler.py +++ b/Lib/distutils/tests/test_msvccompiler.py @@ -32,57 +32,6 @@ def _find_vcvarsall(plat_spec): finally: _msvccompiler._find_vcvarsall = old_find_vcvarsall - def test_compiler_options(self): - import distutils._msvccompiler as _msvccompiler - # suppress path to vcruntime from _find_vcvarsall to - # check that /MT is added to compile options - old_find_vcvarsall = _msvccompiler._find_vcvarsall - def _find_vcvarsall(plat_spec): - return old_find_vcvarsall(plat_spec)[0], None - _msvccompiler._find_vcvarsall = _find_vcvarsall - try: - compiler = _msvccompiler.MSVCCompiler() - compiler.initialize() - - self.assertIn('/MT', compiler.compile_options) - self.assertNotIn('/MD', compiler.compile_options) - finally: - _msvccompiler._find_vcvarsall = old_find_vcvarsall - - def test_vcruntime_copy(self): - import distutils._msvccompiler as _msvccompiler - # force path to a known file - it doesn't matter - # what we copy as long as its name is not in - # _msvccompiler._BUNDLED_DLLS - old_find_vcvarsall = _msvccompiler._find_vcvarsall - def _find_vcvarsall(plat_spec): - return old_find_vcvarsall(plat_spec)[0], __file__ - _msvccompiler._find_vcvarsall = _find_vcvarsall - try: - tempdir = self.mkdtemp() - compiler = _msvccompiler.MSVCCompiler() - compiler.initialize() - compiler._copy_vcruntime(tempdir) - - self.assertTrue(os.path.isfile(os.path.join( - tempdir, os.path.basename(__file__)))) - finally: - _msvccompiler._find_vcvarsall = old_find_vcvarsall - - def test_vcruntime_skip_copy(self): - import distutils._msvccompiler as _msvccompiler - - tempdir = self.mkdtemp() - compiler = _msvccompiler.MSVCCompiler() - compiler.initialize() - dll = compiler._vcruntime_redist - self.assertTrue(os.path.isfile(dll), dll or "") - - compiler._copy_vcruntime(tempdir) - - self.assertFalse(os.path.isfile(os.path.join( - tempdir, os.path.basename(dll))), dll or "") - def test_get_vc_env_unicode(self): import distutils._msvccompiler as _msvccompiler diff --git a/Misc/NEWS.d/next/Windows/2020-03-01-15-04-54.bpo-38597.MnHdYl.rst b/Misc/NEWS.d/next/Windows/2020-03-01-15-04-54.bpo-38597.MnHdYl.rst new file mode 100644 index 0000000000000..7f3a2e756c5a1 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2020-03-01-15-04-54.bpo-38597.MnHdYl.rst @@ -0,0 +1,4 @@ +:mod:`distutils` will no longer statically link :file:`vcruntime140.dll` +when a redistributable version is unavailable. All future releases of +CPython will include a copy of this DLL to ensure distributed extensions can +continue to load. diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index 13c3b594e4431..bd16c1e070bc2 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -528,6 +528,8 @@ + + From webhook-mailer at python.org Mon Mar 2 20:13:18 2020 From: webhook-mailer at python.org (Pablo Galindo) Date: Tue, 03 Mar 2020 01:13:18 -0000 Subject: [Python-checkins] [3.8] bpo-39831: Fix a reference leak in PyErr_WarnEx(). (GH-18750) (GH-18761) Message-ID: https://github.com/python/cpython/commit/394dc0db878c08d003772de163a57ac12046d865 commit: 394dc0db878c08d003772de163a57ac12046d865 branch: 3.8 author: Pablo Galindo committer: GitHub date: 2020-03-03T01:13:10Z summary: [3.8] bpo-39831: Fix a reference leak in PyErr_WarnEx(). (GH-18750) (GH-18761) (cherry picked from commit 2d2f855) Co-authored-by: Serhiy Storchaka files: M Python/_warnings.c diff --git a/Python/_warnings.c b/Python/_warnings.c index e02d28305126d..87269dd4dbc9e 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -856,11 +856,11 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno, int rc; if (PyErr_Occurred()) { - return 0; + goto handle_error; } *registry = PyDict_New(); if (*registry == NULL) - return 0; + goto handle_error; rc = _PyDict_SetItemId(globals, &PyId___warningregistry__, *registry); if (rc < 0) @@ -890,6 +890,7 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno, dangling reference. */ Py_XDECREF(*registry); Py_XDECREF(*module); + Py_XDECREF(*filename); return 0; } From webhook-mailer at python.org Mon Mar 2 20:13:28 2020 From: webhook-mailer at python.org (Pablo Galindo) Date: Tue, 03 Mar 2020 01:13:28 -0000 Subject: [Python-checkins] [3.7] bpo-39831: Fix a reference leak in PyErr_WarnEx(). (GH-18750). (GH-18760) Message-ID: https://github.com/python/cpython/commit/499c926fbeafa7e4c15d925fea27fe8a65cc3b25 commit: 499c926fbeafa7e4c15d925fea27fe8a65cc3b25 branch: 3.7 author: Pablo Galindo committer: GitHub date: 2020-03-03T01:13:24Z summary: [3.7] bpo-39831: Fix a reference leak in PyErr_WarnEx(). (GH-18750). (GH-18760) (cherry picked from commit 2d2f85517f8216146a2f888d1ad4d765b3be2339) Co-authored-by: Serhiy Storchaka files: M Python/_warnings.c diff --git a/Python/_warnings.c b/Python/_warnings.c index e86a582a01cf4..1a2035eb250d5 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -710,7 +710,7 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno, *registry = PyDict_New(); if (*registry == NULL) - return 0; + goto handle_error; rc = PyDict_SetItemString(globals, "__warningregistry__", *registry); if (rc < 0) @@ -802,6 +802,7 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno, dangling reference. */ Py_XDECREF(*registry); Py_XDECREF(*module); + Py_XDECREF(*filename); return 0; } From webhook-mailer at python.org Mon Mar 2 20:37:32 2020 From: webhook-mailer at python.org (Armin Rigo) Date: Tue, 03 Mar 2020 01:37:32 -0000 Subject: [Python-checkins] bpo-38091: Import deadlock detection causes deadlock (GH-17518) Message-ID: https://github.com/python/cpython/commit/6daa37fd42c5d5300172728e8b4de74fe0b319fc commit: 6daa37fd42c5d5300172728e8b4de74fe0b319fc branch: master author: Armin Rigo committer: GitHub date: 2020-03-02T17:37:25-08:00 summary: bpo-38091: Import deadlock detection causes deadlock (GH-17518) Automerge-Triggered-By: @brettcannon files: A Misc/NEWS.d/next/Core and Builtins/2020-02-14-23-10-07.bpo-38091.pwR0K7.rst M Lib/importlib/_bootstrap.py M Lib/test/test_import/__init__.py M Python/importlib.h diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py index 7b74e88820d03..e00b27ece2603 100644 --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -67,6 +67,7 @@ def has_deadlock(self): # Deadlock avoidance for concurrent circular imports. me = _thread.get_ident() tid = self.owner + seen = set() while True: lock = _blocking_on.get(tid) if lock is None: @@ -74,6 +75,14 @@ def has_deadlock(self): tid = lock.owner if tid == me: return True + if tid in seen: + # bpo 38091: the chain of tid's we encounter here + # eventually leads to a fixpoint or a cycle, but + # does not reach 'me'. This means we would not + # actually deadlock. This can happen if other + # threads are at the beginning of acquire() below. + return False + seen.add(tid) def acquire(self): """ diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py index 482fe6a9216a5..d50befc030a48 100644 --- a/Lib/test/test_import/__init__.py +++ b/Lib/test/test_import/__init__.py @@ -436,16 +436,24 @@ def test_issue31492(self): os.does_not_exist def test_concurrency(self): + # bpo 38091: this is a hack to slow down the code that calls + # has_deadlock(); the logic was itself sometimes deadlocking. + def delay_has_deadlock(frame, event, arg): + if event == 'call' and frame.f_code.co_name == 'has_deadlock': + time.sleep(0.1) + sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'data')) try: exc = None def run(): + sys.settrace(delay_has_deadlock) event.wait() try: import package except BaseException as e: nonlocal exc exc = e + sys.settrace(None) for i in range(10): event = threading.Event() diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-02-14-23-10-07.bpo-38091.pwR0K7.rst b/Misc/NEWS.d/next/Core and Builtins/2020-02-14-23-10-07.bpo-38091.pwR0K7.rst new file mode 100644 index 0000000000000..55e326155cea2 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2020-02-14-23-10-07.bpo-38091.pwR0K7.rst @@ -0,0 +1 @@ +Tweak import deadlock detection code to not deadlock itself. diff --git a/Python/importlib.h b/Python/importlib.h index 7f999704f31a3..7cffb3df3e416 100644 --- a/Python/importlib.h +++ b/Python/importlib.h @@ -118,1692 +118,1695 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 58,0,0,0,115,12,0,0,0,0,1,10,1,10,1,6, 1,6,1,6,1,122,20,95,77,111,100,117,108,101,76,111, 99,107,46,95,95,105,110,105,116,95,95,99,1,0,0,0, - 0,0,0,0,0,0,0,0,4,0,0,0,3,0,0,0, - 67,0,0,0,115,60,0,0,0,116,0,160,1,161,0,125, - 1,124,0,106,2,125,2,116,3,160,4,124,2,161,1,125, - 3,124,3,100,0,117,0,114,36,100,1,83,0,124,3,106, - 2,125,2,124,2,124,1,107,2,114,14,100,2,83,0,113, - 14,100,0,83,0,41,3,78,70,84,41,5,114,23,0,0, - 0,218,9,103,101,116,95,105,100,101,110,116,114,26,0,0, - 0,218,12,95,98,108,111,99,107,105,110,103,95,111,110,218, - 3,103,101,116,41,4,114,30,0,0,0,90,2,109,101,218, - 3,116,105,100,114,24,0,0,0,114,10,0,0,0,114,10, - 0,0,0,114,11,0,0,0,218,12,104,97,115,95,100,101, - 97,100,108,111,99,107,66,0,0,0,115,16,0,0,0,0, - 2,8,1,6,2,10,1,8,1,4,1,6,1,8,1,122, - 24,95,77,111,100,117,108,101,76,111,99,107,46,104,97,115, - 95,100,101,97,100,108,111,99,107,99,1,0,0,0,0,0, - 0,0,0,0,0,0,2,0,0,0,8,0,0,0,67,0, - 0,0,115,210,0,0,0,116,0,160,1,161,0,125,1,124, - 0,116,2,124,1,60,0,122,180,124,0,106,3,143,126,1, - 0,124,0,106,4,100,1,107,2,115,46,124,0,106,5,124, - 1,107,2,114,90,124,1,124,0,95,5,124,0,4,0,106, - 4,100,2,55,0,2,0,95,4,87,0,100,3,4,0,4, - 0,131,3,1,0,87,0,116,2,124,1,61,0,100,4,83, - 0,124,0,160,6,161,0,114,110,116,7,100,5,124,0,22, - 0,131,1,130,1,124,0,106,8,160,9,100,6,161,1,114, - 136,124,0,4,0,106,10,100,2,55,0,2,0,95,10,87, - 0,100,3,4,0,4,0,131,3,1,0,110,16,49,0,115, - 156,48,0,1,0,1,0,1,0,89,0,1,0,124,0,106, - 8,160,9,161,0,1,0,124,0,106,8,160,11,161,0,1, - 0,113,18,87,0,116,2,124,1,61,0,110,8,116,2,124, - 1,61,0,48,0,100,3,83,0,41,7,122,185,10,32,32, - 32,32,32,32,32,32,65,99,113,117,105,114,101,32,116,104, - 101,32,109,111,100,117,108,101,32,108,111,99,107,46,32,32, - 73,102,32,97,32,112,111,116,101,110,116,105,97,108,32,100, - 101,97,100,108,111,99,107,32,105,115,32,100,101,116,101,99, - 116,101,100,44,10,32,32,32,32,32,32,32,32,97,32,95, - 68,101,97,100,108,111,99,107,69,114,114,111,114,32,105,115, - 32,114,97,105,115,101,100,46,10,32,32,32,32,32,32,32, - 32,79,116,104,101,114,119,105,115,101,44,32,116,104,101,32, - 108,111,99,107,32,105,115,32,97,108,119,97,121,115,32,97, - 99,113,117,105,114,101,100,32,97,110,100,32,84,114,117,101, - 32,105,115,32,114,101,116,117,114,110,101,100,46,10,32,32, - 32,32,32,32,32,32,114,22,0,0,0,233,1,0,0,0, - 78,84,122,23,100,101,97,100,108,111,99,107,32,100,101,116, - 101,99,116,101,100,32,98,121,32,37,114,70,41,12,114,23, - 0,0,0,114,32,0,0,0,114,33,0,0,0,114,24,0, - 0,0,114,27,0,0,0,114,26,0,0,0,114,36,0,0, - 0,114,19,0,0,0,114,25,0,0,0,218,7,97,99,113, - 117,105,114,101,114,28,0,0,0,218,7,114,101,108,101,97, - 115,101,169,2,114,30,0,0,0,114,35,0,0,0,114,10, - 0,0,0,114,10,0,0,0,114,11,0,0,0,114,38,0, - 0,0,78,0,0,0,115,36,0,0,0,0,6,8,1,8, - 1,2,2,8,1,20,1,6,1,14,1,14,9,6,247,4, - 1,8,1,12,1,12,1,44,2,10,1,14,2,8,0,122, - 19,95,77,111,100,117,108,101,76,111,99,107,46,97,99,113, - 117,105,114,101,99,1,0,0,0,0,0,0,0,0,0,0, - 0,2,0,0,0,8,0,0,0,67,0,0,0,115,142,0, - 0,0,116,0,160,1,161,0,125,1,124,0,106,2,143,108, - 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,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,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, - 100,0,4,0,4,0,131,3,1,0,110,16,49,0,115,128, - 48,0,1,0,1,0,1,0,89,0,1,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,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,114,28,0,0,0,114,25,0,0, - 0,114,39,0,0,0,114,40,0,0,0,114,10,0,0,0, - 114,10,0,0,0,114,11,0,0,0,114,39,0,0,0,103, - 0,0,0,115,22,0,0,0,0,1,8,1,8,1,10,1, - 8,1,14,1,14,1,10,1,6,1,6,1,14,1,122,19, - 95,77,111,100,117,108,101,76,111,99,107,46,114,101,108,101, - 97,115,101,99,1,0,0,0,0,0,0,0,0,0,0,0, - 1,0,0,0,5,0,0,0,67,0,0,0,115,18,0,0, - 0,100,1,160,0,124,0,106,1,116,2,124,0,131,1,161, - 2,83,0,41,2,78,122,23,95,77,111,100,117,108,101,76, - 111,99,107,40,123,33,114,125,41,32,97,116,32,123,125,169, - 3,218,6,102,111,114,109,97,116,114,17,0,0,0,218,2, - 105,100,169,1,114,30,0,0,0,114,10,0,0,0,114,10, - 0,0,0,114,11,0,0,0,218,8,95,95,114,101,112,114, - 95,95,116,0,0,0,115,2,0,0,0,0,1,122,20,95, - 77,111,100,117,108,101,76,111,99,107,46,95,95,114,101,112, - 114,95,95,78,41,9,114,1,0,0,0,114,0,0,0,0, - 114,2,0,0,0,114,3,0,0,0,114,31,0,0,0,114, - 36,0,0,0,114,38,0,0,0,114,39,0,0,0,114,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,0,0,0,0,0,0, - 0,0,0,0,0,0,0,2,0,0,0,64,0,0,0,115, - 48,0,0,0,101,0,90,1,100,0,90,2,100,1,90,3, - 100,2,100,3,132,0,90,4,100,4,100,5,132,0,90,5, - 100,6,100,7,132,0,90,6,100,8,100,9,132,0,90,7, - 100,10,83,0,41,11,218,16,95,68,117,109,109,121,77,111, - 100,117,108,101,76,111,99,107,122,86,65,32,115,105,109,112, - 108,101,32,95,77,111,100,117,108,101,76,111,99,107,32,101, - 113,117,105,118,97,108,101,110,116,32,102,111,114,32,80,121, - 116,104,111,110,32,98,117,105,108,100,115,32,119,105,116,104, - 111,117,116,10,32,32,32,32,109,117,108,116,105,45,116,104, - 114,101,97,100,105,110,103,32,115,117,112,112,111,114,116,46, - 99,2,0,0,0,0,0,0,0,0,0,0,0,2,0,0, - 0,2,0,0,0,67,0,0,0,115,16,0,0,0,124,1, - 124,0,95,0,100,1,124,0,95,1,100,0,83,0,114,21, - 0,0,0,41,2,114,17,0,0,0,114,27,0,0,0,114, - 29,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, - 0,0,0,114,31,0,0,0,124,0,0,0,115,4,0,0, - 0,0,1,6,1,122,25,95,68,117,109,109,121,77,111,100, - 117,108,101,76,111,99,107,46,95,95,105,110,105,116,95,95, - 99,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0, - 0,3,0,0,0,67,0,0,0,115,18,0,0,0,124,0, - 4,0,106,0,100,1,55,0,2,0,95,0,100,2,83,0, - 41,3,78,114,37,0,0,0,84,41,1,114,27,0,0,0, - 114,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,99,113,117,105,114,101, - 99,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0, - 0,3,0,0,0,67,0,0,0,115,36,0,0,0,124,0, - 106,0,100,1,107,2,114,18,116,1,100,2,131,1,130,1, - 124,0,4,0,106,0,100,3,56,0,2,0,95,0,100,0, - 83,0,41,4,78,114,22,0,0,0,114,41,0,0,0,114, - 37,0,0,0,41,2,114,27,0,0,0,114,42,0,0,0, - 114,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,46,114,101,108,101,97, - 115,101,99,1,0,0,0,0,0,0,0,0,0,0,0,1, - 0,0,0,5,0,0,0,67,0,0,0,115,18,0,0,0, - 100,1,160,0,124,0,106,1,116,2,124,0,131,1,161,2, - 83,0,41,2,78,122,28,95,68,117,109,109,121,77,111,100, + 0,0,0,0,0,0,0,0,5,0,0,0,3,0,0,0, + 67,0,0,0,115,88,0,0,0,116,0,160,1,161,0,125, + 1,124,0,106,2,125,2,116,3,131,0,125,3,116,4,160, + 5,124,2,161,1,125,4,124,4,100,0,117,0,114,42,100, + 1,83,0,124,4,106,2,125,2,124,2,124,1,107,2,114, + 60,100,2,83,0,124,2,124,3,118,0,114,72,100,1,83, + 0,124,3,160,6,124,2,161,1,1,0,113,20,100,0,83, + 0,41,3,78,70,84,41,7,114,23,0,0,0,218,9,103, + 101,116,95,105,100,101,110,116,114,26,0,0,0,218,3,115, + 101,116,218,12,95,98,108,111,99,107,105,110,103,95,111,110, + 218,3,103,101,116,218,3,97,100,100,41,5,114,30,0,0, + 0,90,2,109,101,218,3,116,105,100,90,4,115,101,101,110, + 114,24,0,0,0,114,10,0,0,0,114,10,0,0,0,114, + 11,0,0,0,218,12,104,97,115,95,100,101,97,100,108,111, + 99,107,66,0,0,0,115,24,0,0,0,0,2,8,1,6, + 1,6,2,10,1,8,1,4,1,6,1,8,1,4,1,8, + 6,4,1,122,24,95,77,111,100,117,108,101,76,111,99,107, + 46,104,97,115,95,100,101,97,100,108,111,99,107,99,1,0, + 0,0,0,0,0,0,0,0,0,0,2,0,0,0,8,0, + 0,0,67,0,0,0,115,210,0,0,0,116,0,160,1,161, + 0,125,1,124,0,116,2,124,1,60,0,122,180,124,0,106, + 3,143,126,1,0,124,0,106,4,100,1,107,2,115,46,124, + 0,106,5,124,1,107,2,114,90,124,1,124,0,95,5,124, + 0,4,0,106,4,100,2,55,0,2,0,95,4,87,0,100, + 3,4,0,4,0,131,3,1,0,87,0,116,2,124,1,61, + 0,100,4,83,0,124,0,160,6,161,0,114,110,116,7,100, + 5,124,0,22,0,131,1,130,1,124,0,106,8,160,9,100, + 6,161,1,114,136,124,0,4,0,106,10,100,2,55,0,2, + 0,95,10,87,0,100,3,4,0,4,0,131,3,1,0,110, + 16,49,0,115,156,48,0,1,0,1,0,1,0,89,0,1, + 0,124,0,106,8,160,9,161,0,1,0,124,0,106,8,160, + 11,161,0,1,0,113,18,87,0,116,2,124,1,61,0,110, + 8,116,2,124,1,61,0,48,0,100,3,83,0,41,7,122, + 185,10,32,32,32,32,32,32,32,32,65,99,113,117,105,114, + 101,32,116,104,101,32,109,111,100,117,108,101,32,108,111,99, + 107,46,32,32,73,102,32,97,32,112,111,116,101,110,116,105, + 97,108,32,100,101,97,100,108,111,99,107,32,105,115,32,100, + 101,116,101,99,116,101,100,44,10,32,32,32,32,32,32,32, + 32,97,32,95,68,101,97,100,108,111,99,107,69,114,114,111, + 114,32,105,115,32,114,97,105,115,101,100,46,10,32,32,32, + 32,32,32,32,32,79,116,104,101,114,119,105,115,101,44,32, + 116,104,101,32,108,111,99,107,32,105,115,32,97,108,119,97, + 121,115,32,97,99,113,117,105,114,101,100,32,97,110,100,32, + 84,114,117,101,32,105,115,32,114,101,116,117,114,110,101,100, + 46,10,32,32,32,32,32,32,32,32,114,22,0,0,0,233, + 1,0,0,0,78,84,122,23,100,101,97,100,108,111,99,107, + 32,100,101,116,101,99,116,101,100,32,98,121,32,37,114,70, + 41,12,114,23,0,0,0,114,32,0,0,0,114,34,0,0, + 0,114,24,0,0,0,114,27,0,0,0,114,26,0,0,0, + 114,38,0,0,0,114,19,0,0,0,114,25,0,0,0,218, + 7,97,99,113,117,105,114,101,114,28,0,0,0,218,7,114, + 101,108,101,97,115,101,169,2,114,30,0,0,0,114,37,0, + 0,0,114,10,0,0,0,114,10,0,0,0,114,11,0,0, + 0,114,40,0,0,0,87,0,0,0,115,36,0,0,0,0, + 6,8,1,8,1,2,2,8,1,20,1,6,1,14,1,14, + 9,6,247,4,1,8,1,12,1,12,1,44,2,10,1,14, + 2,8,0,122,19,95,77,111,100,117,108,101,76,111,99,107, + 46,97,99,113,117,105,114,101,99,1,0,0,0,0,0,0, + 0,0,0,0,0,2,0,0,0,8,0,0,0,67,0,0, + 0,115,142,0,0,0,116,0,160,1,161,0,125,1,124,0, + 106,2,143,108,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,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,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,100,0,4,0,4,0,131,3,1,0,110,16, + 49,0,115,128,48,0,1,0,1,0,1,0,89,0,1,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,39,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,114,28,0,0,0, + 114,25,0,0,0,114,41,0,0,0,114,42,0,0,0,114, + 10,0,0,0,114,10,0,0,0,114,11,0,0,0,114,41, + 0,0,0,112,0,0,0,115,22,0,0,0,0,1,8,1, + 8,1,10,1,8,1,14,1,14,1,10,1,6,1,6,1, + 14,1,122,19,95,77,111,100,117,108,101,76,111,99,107,46, + 114,101,108,101,97,115,101,99,1,0,0,0,0,0,0,0, + 0,0,0,0,1,0,0,0,5,0,0,0,67,0,0,0, + 115,18,0,0,0,100,1,160,0,124,0,106,1,116,2,124, + 0,131,1,161,2,83,0,41,2,78,122,23,95,77,111,100, 117,108,101,76,111,99,107,40,123,33,114,125,41,32,97,116, - 32,123,125,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,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,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,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,5,100,6,132,0,90, - 5,100,7,83,0,41,8,218,18,95,77,111,100,117,108,101, - 76,111,99,107,77,97,110,97,103,101,114,99,2,0,0,0, - 0,0,0,0,0,0,0,0,2,0,0,0,2,0,0,0, - 67,0,0,0,115,16,0,0,0,124,1,124,0,95,0,100, - 0,124,0,95,1,100,0,83,0,114,13,0,0,0,41,2, - 218,5,95,110,97,109,101,218,5,95,108,111,99,107,114,29, - 0,0,0,114,10,0,0,0,114,10,0,0,0,114,11,0, - 0,0,114,31,0,0,0,143,0,0,0,115,4,0,0,0, - 0,1,6,1,122,27,95,77,111,100,117,108,101,76,111,99, - 107,77,97,110,97,103,101,114,46,95,95,105,110,105,116,95, - 95,99,1,0,0,0,0,0,0,0,0,0,0,0,1,0, - 0,0,2,0,0,0,67,0,0,0,115,26,0,0,0,116, - 0,124,0,106,1,131,1,124,0,95,2,124,0,106,2,160, - 3,161,0,1,0,100,0,83,0,114,13,0,0,0,41,4, - 218,16,95,103,101,116,95,109,111,100,117,108,101,95,108,111, - 99,107,114,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,77,97,110,97,103,101, - 114,46,95,95,101,110,116,101,114,95,95,99,1,0,0,0, - 0,0,0,0,0,0,0,0,3,0,0,0,2,0,0,0, - 79,0,0,0,115,14,0,0,0,124,0,106,0,160,1,161, - 0,1,0,100,0,83,0,114,13,0,0,0,41,2,114,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, + 32,123,125,169,3,218,6,102,111,114,109,97,116,114,17,0, + 0,0,218,2,105,100,169,1,114,30,0,0,0,114,10,0, 0,0,114,10,0,0,0,114,11,0,0,0,218,8,95,95, - 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,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,136,0,0,0,116,0,160,1,161,0, - 1,0,122,112,122,14,116,2,124,0,25,0,131,0,125,1, - 87,0,110,22,4,0,116,3,121,46,1,0,1,0,1,0, - 100,1,125,1,89,0,110,2,48,0,124,1,100,1,117,0, - 114,110,116,4,100,1,117,0,114,74,116,5,124,0,131,1, - 125,1,110,8,116,6,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,116,0,160,9,161,0, - 1,0,110,10,116,0,160,9,161,0,1,0,48,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, - 109,111,100,117,108,101,32,110,97,109,101,46,10,10,32,32, - 32,32,65,99,113,117,105,114,101,47,114,101,108,101,97,115, - 101,32,105,110,116,101,114,110,97,108,108,121,32,116,104,101, - 32,103,108,111,98,97,108,32,105,109,112,111,114,116,32,108, - 111,99,107,32,116,111,32,112,114,111,116,101,99,116,10,32, - 32,32,32,95,109,111,100,117,108,101,95,108,111,99,107,115, - 46,78,99,2,0,0,0,0,0,0,0,0,0,0,0,2, - 0,0,0,8,0,0,0,83,0,0,0,115,56,0,0,0, - 116,0,160,1,161,0,1,0,122,32,116,2,160,3,124,1, - 161,1,124,0,117,0,114,30,116,2,124,1,61,0,87,0, - 116,0,160,4,161,0,1,0,110,10,116,0,160,4,161,0, - 1,0,48,0,100,0,83,0,114,13,0,0,0,41,5,218, - 4,95,105,109,112,218,12,97,99,113,117,105,114,101,95,108, - 111,99,107,218,13,95,109,111,100,117,108,101,95,108,111,99, - 107,115,114,34,0,0,0,218,12,114,101,108,101,97,115,101, - 95,108,111,99,107,41,2,218,3,114,101,102,114,17,0,0, + 114,101,112,114,95,95,125,0,0,0,115,2,0,0,0,0, + 1,122,20,95,77,111,100,117,108,101,76,111,99,107,46,95, + 95,114,101,112,114,95,95,78,41,9,114,1,0,0,0,114, + 0,0,0,0,114,2,0,0,0,114,3,0,0,0,114,31, + 0,0,0,114,38,0,0,0,114,40,0,0,0,114,41,0, + 0,0,114,49,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, + 21,8,25,8,13,114,20,0,0,0,99,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,64, + 0,0,0,115,48,0,0,0,101,0,90,1,100,0,90,2, + 100,1,90,3,100,2,100,3,132,0,90,4,100,4,100,5, + 132,0,90,5,100,6,100,7,132,0,90,6,100,8,100,9, + 132,0,90,7,100,10,83,0,41,11,218,16,95,68,117,109, + 109,121,77,111,100,117,108,101,76,111,99,107,122,86,65,32, + 115,105,109,112,108,101,32,95,77,111,100,117,108,101,76,111, + 99,107,32,101,113,117,105,118,97,108,101,110,116,32,102,111, + 114,32,80,121,116,104,111,110,32,98,117,105,108,100,115,32, + 119,105,116,104,111,117,116,10,32,32,32,32,109,117,108,116, + 105,45,116,104,114,101,97,100,105,110,103,32,115,117,112,112, + 111,114,116,46,99,2,0,0,0,0,0,0,0,0,0,0, + 0,2,0,0,0,2,0,0,0,67,0,0,0,115,16,0, + 0,0,124,1,124,0,95,0,100,1,124,0,95,1,100,0, + 83,0,114,21,0,0,0,41,2,114,17,0,0,0,114,27, + 0,0,0,114,29,0,0,0,114,10,0,0,0,114,10,0, + 0,0,114,11,0,0,0,114,31,0,0,0,133,0,0,0, + 115,4,0,0,0,0,1,6,1,122,25,95,68,117,109,109, + 121,77,111,100,117,108,101,76,111,99,107,46,95,95,105,110, + 105,116,95,95,99,1,0,0,0,0,0,0,0,0,0,0, + 0,1,0,0,0,3,0,0,0,67,0,0,0,115,18,0, + 0,0,124,0,4,0,106,0,100,1,55,0,2,0,95,0, + 100,2,83,0,41,3,78,114,39,0,0,0,84,41,1,114, + 27,0,0,0,114,48,0,0,0,114,10,0,0,0,114,10, + 0,0,0,114,11,0,0,0,114,40,0,0,0,137,0,0, + 0,115,4,0,0,0,0,1,14,1,122,24,95,68,117,109, + 109,121,77,111,100,117,108,101,76,111,99,107,46,97,99,113, + 117,105,114,101,99,1,0,0,0,0,0,0,0,0,0,0, + 0,1,0,0,0,3,0,0,0,67,0,0,0,115,36,0, + 0,0,124,0,106,0,100,1,107,2,114,18,116,1,100,2, + 131,1,130,1,124,0,4,0,106,0,100,3,56,0,2,0, + 95,0,100,0,83,0,41,4,78,114,22,0,0,0,114,43, + 0,0,0,114,39,0,0,0,41,2,114,27,0,0,0,114, + 44,0,0,0,114,48,0,0,0,114,10,0,0,0,114,10, + 0,0,0,114,11,0,0,0,114,41,0,0,0,141,0,0, + 0,115,6,0,0,0,0,1,10,1,8,1,122,24,95,68, + 117,109,109,121,77,111,100,117,108,101,76,111,99,107,46,114, + 101,108,101,97,115,101,99,1,0,0,0,0,0,0,0,0, + 0,0,0,1,0,0,0,5,0,0,0,67,0,0,0,115, + 18,0,0,0,100,1,160,0,124,0,106,1,116,2,124,0, + 131,1,161,2,83,0,41,2,78,122,28,95,68,117,109,109, + 121,77,111,100,117,108,101,76,111,99,107,40,123,33,114,125, + 41,32,97,116,32,123,125,114,45,0,0,0,114,48,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,12,0,0,0,0,1,8, - 1,2,4,14,1,8,2,10,0,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,56,0,0,0,114,57, - 0,0,0,114,58,0,0,0,218,8,75,101,121,69,114,114, - 111,114,114,23,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, - 114,59,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,30, - 0,0,0,0,6,8,1,2,1,2,1,14,1,12,1,10, - 2,8,1,8,1,10,2,8,2,12,11,18,2,10,0,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, - 52,0,0,0,116,0,124,0,131,1,125,1,122,12,124,1, - 160,1,161,0,1,0,87,0,110,18,4,0,116,2,121,38, - 1,0,1,0,1,0,89,0,110,10,48,0,124,1,160,3, - 161,0,1,0,100,1,83,0,41,2,122,189,65,99,113,117, - 105,114,101,115,32,116,104,101,110,32,114,101,108,101,97,115, - 101,115,32,116,104,101,32,109,111,100,117,108,101,32,108,111, - 99,107,32,102,111,114,32,97,32,103,105,118,101,110,32,109, - 111,100,117,108,101,32,110,97,109,101,46,10,10,32,32,32, - 32,84,104,105,115,32,105,115,32,117,115,101,100,32,116,111, - 32,101,110,115,117,114,101,32,97,32,109,111,100,117,108,101, - 32,105,115,32,99,111,109,112,108,101,116,101,108,121,32,105, - 110,105,116,105,97,108,105,122,101,100,44,32,105,110,32,116, - 104,101,10,32,32,32,32,101,118,101,110,116,32,105,116,32, - 105,115,32,98,101,105,110,103,32,105,109,112,111,114,116,101, - 100,32,98,121,32,97,110,111,116,104,101,114,32,116,104,114, - 101,97,100,46,10,32,32,32,32,78,41,4,114,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,12,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,4,0,0,0,79, - 0,0,0,115,14,0,0,0,124,0,124,1,105,0,124,2, - 164,1,142,1,83,0,41,1,97,46,1,0,0,114,101,109, - 111,118,101,95,105,109,112,111,114,116,108,105,98,95,102,114, - 97,109,101,115,32,105,110,32,105,109,112,111,114,116,46,99, - 32,119,105,108,108,32,97,108,119,97,121,115,32,114,101,109, - 111,118,101,32,115,101,113,117,101,110,99,101,115,10,32,32, - 32,32,111,102,32,105,109,112,111,114,116,108,105,98,32,102, - 114,97,109,101,115,32,116,104,97,116,32,101,110,100,32,119, - 105,116,104,32,97,32,99,97,108,108,32,116,111,32,116,104, - 105,115,32,102,117,110,99,116,105,111,110,10,10,32,32,32, - 32,85,115,101,32,105,116,32,105,110,115,116,101,97,100,32, - 111,102,32,97,32,110,111,114,109,97,108,32,99,97,108,108, - 32,105,110,32,112,108,97,99,101,115,32,119,104,101,114,101, - 32,105,110,99,108,117,100,105,110,103,32,116,104,101,32,105, - 109,112,111,114,116,108,105,98,10,32,32,32,32,102,114,97, - 109,101,115,32,105,110,116,114,111,100,117,99,101,115,32,117, - 110,119,97,110,116,101,100,32,110,111,105,115,101,32,105,110, - 116,111,32,116,104,101,32,116,114,97,99,101,98,97,99,107, - 32,40,101,46,103,46,32,119,104,101,110,32,101,120,101,99, - 117,116,105,110,103,10,32,32,32,32,109,111,100,117,108,101, - 32,99,111,100,101,41,10,32,32,32,32,114,10,0,0,0, - 41,3,218,1,102,114,54,0,0,0,90,4,107,119,100,115, + 114,49,0,0,0,146,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,40,0,0,0,114,41,0,0, + 0,114,49,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,129, + 0,0,0,115,10,0,0,0,8,1,4,3,8,4,8,4, + 8,5,114,50,0,0,0,99,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,2,0,0,0,64,0,0,0, + 115,36,0,0,0,101,0,90,1,100,0,90,2,100,1,100, + 2,132,0,90,3,100,3,100,4,132,0,90,4,100,5,100, + 6,132,0,90,5,100,7,83,0,41,8,218,18,95,77,111, + 100,117,108,101,76,111,99,107,77,97,110,97,103,101,114,99, + 2,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0, + 2,0,0,0,67,0,0,0,115,16,0,0,0,124,1,124, + 0,95,0,100,0,124,0,95,1,100,0,83,0,114,13,0, + 0,0,41,2,218,5,95,110,97,109,101,218,5,95,108,111, + 99,107,114,29,0,0,0,114,10,0,0,0,114,10,0,0, + 0,114,11,0,0,0,114,31,0,0,0,152,0,0,0,115, + 4,0,0,0,0,1,6,1,122,27,95,77,111,100,117,108, + 101,76,111,99,107,77,97,110,97,103,101,114,46,95,95,105, + 110,105,116,95,95,99,1,0,0,0,0,0,0,0,0,0, + 0,0,1,0,0,0,2,0,0,0,67,0,0,0,115,26, + 0,0,0,116,0,124,0,106,1,131,1,124,0,95,2,124, + 0,106,2,160,3,161,0,1,0,100,0,83,0,114,13,0, + 0,0,41,4,218,16,95,103,101,116,95,109,111,100,117,108, + 101,95,108,111,99,107,114,52,0,0,0,114,53,0,0,0, + 114,40,0,0,0,114,48,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,156,0,0,0,115,4,0,0,0,0,1,12, + 1,122,28,95,77,111,100,117,108,101,76,111,99,107,77,97, + 110,97,103,101,114,46,95,95,101,110,116,101,114,95,95,99, + 1,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0, + 2,0,0,0,79,0,0,0,115,14,0,0,0,124,0,106, + 0,160,1,161,0,1,0,100,0,83,0,114,13,0,0,0, + 41,2,114,53,0,0,0,114,41,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,160,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,55,0,0,0,114,57, + 0,0,0,114,10,0,0,0,114,10,0,0,0,114,10,0, + 0,0,114,11,0,0,0,114,51,0,0,0,150,0,0,0, + 115,6,0,0,0,8,2,8,4,8,4,114,51,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,136,0,0,0,116,0, + 160,1,161,0,1,0,122,112,122,14,116,2,124,0,25,0, + 131,0,125,1,87,0,110,22,4,0,116,3,121,46,1,0, + 1,0,1,0,100,1,125,1,89,0,110,2,48,0,124,1, + 100,1,117,0,114,110,116,4,100,1,117,0,114,74,116,5, + 124,0,131,1,125,1,110,8,116,6,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,116,0, + 160,9,161,0,1,0,110,10,116,0,160,9,161,0,1,0, + 48,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,109,111,100,117,108,101,32,110,97,109,101,46, + 10,10,32,32,32,32,65,99,113,117,105,114,101,47,114,101, + 108,101,97,115,101,32,105,110,116,101,114,110,97,108,108,121, + 32,116,104,101,32,103,108,111,98,97,108,32,105,109,112,111, + 114,116,32,108,111,99,107,32,116,111,32,112,114,111,116,101, + 99,116,10,32,32,32,32,95,109,111,100,117,108,101,95,108, + 111,99,107,115,46,78,99,2,0,0,0,0,0,0,0,0, + 0,0,0,2,0,0,0,8,0,0,0,83,0,0,0,115, + 56,0,0,0,116,0,160,1,161,0,1,0,122,32,116,2, + 160,3,124,1,161,1,124,0,117,0,114,30,116,2,124,1, + 61,0,87,0,116,0,160,4,161,0,1,0,110,10,116,0, + 160,4,161,0,1,0,48,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,35,0,0,0,218,12,114,101,108, + 101,97,115,101,95,108,111,99,107,41,2,218,3,114,101,102, + 114,17,0,0,0,114,10,0,0,0,114,10,0,0,0,114, + 11,0,0,0,218,2,99,98,185,0,0,0,115,12,0,0, + 0,0,1,8,1,2,4,14,1,8,2,10,0,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,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,50,0,0,0, + 114,20,0,0,0,218,8,95,119,101,97,107,114,101,102,114, + 62,0,0,0,114,61,0,0,0,41,3,114,17,0,0,0, + 114,24,0,0,0,114,63,0,0,0,114,10,0,0,0,114, + 10,0,0,0,114,11,0,0,0,114,54,0,0,0,166,0, + 0,0,115,30,0,0,0,0,6,8,1,2,1,2,1,14, + 1,12,1,10,2,8,1,8,1,10,2,8,2,12,11,18, + 2,10,0,10,2,114,54,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,116,0,124,0,131,1,125,1, + 122,12,124,1,160,1,161,0,1,0,87,0,110,18,4,0, + 116,2,121,38,1,0,1,0,1,0,89,0,110,10,48,0, + 124,1,160,3,161,0,1,0,100,1,83,0,41,2,122,189, + 65,99,113,117,105,114,101,115,32,116,104,101,110,32,114,101, + 108,101,97,115,101,115,32,116,104,101,32,109,111,100,117,108, + 101,32,108,111,99,107,32,102,111,114,32,97,32,103,105,118, + 101,110,32,109,111,100,117,108,101,32,110,97,109,101,46,10, + 10,32,32,32,32,84,104,105,115,32,105,115,32,117,115,101, + 100,32,116,111,32,101,110,115,117,114,101,32,97,32,109,111, + 100,117,108,101,32,105,115,32,99,111,109,112,108,101,116,101, + 108,121,32,105,110,105,116,105,97,108,105,122,101,100,44,32, + 105,110,32,116,104,101,10,32,32,32,32,101,118,101,110,116, + 32,105,116,32,105,115,32,98,101,105,110,103,32,105,109,112, + 111,114,116,101,100,32,98,121,32,97,110,111,116,104,101,114, + 32,116,104,114,101,97,100,46,10,32,32,32,32,78,41,4, + 114,54,0,0,0,114,40,0,0,0,114,19,0,0,0,114, + 41,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, - 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,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,106,2, - 124,1,107,5,114,50,124,0,160,3,100,1,161,1,115,30, - 100,2,124,0,23,0,125,0,116,4,124,0,106,5,124,2, - 142,0,116,0,106,6,100,3,141,2,1,0,100,4,83,0, - 41,5,122,61,80,114,105,110,116,32,116,104,101,32,109,101, - 115,115,97,103,101,32,116,111,32,115,116,100,101,114,114,32, - 105,102,32,45,118,47,80,89,84,72,79,78,86,69,82,66, - 79,83,69,32,105,115,32,116,117,114,110,101,100,32,111,110, - 46,41,2,250,1,35,122,7,105,109,112,111,114,116,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,44,0,0,0,218,6,115,116,100, - 101,114,114,41,3,218,7,109,101,115,115,97,103,101,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,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,0,131, - 2,1,0,124,1,83,0,41,3,122,49,68,101,99,111,114, - 97,116,111,114,32,116,111,32,118,101,114,105,102,121,32,116, - 104,101,32,110,97,109,101,100,32,109,111,100,117,108,101,32, - 105,115,32,98,117,105,108,116,45,105,110,46,99,2,0,0, - 0,0,0,0,0,0,0,0,0,2,0,0,0,4,0,0, - 0,19,0,0,0,115,38,0,0,0,124,1,116,0,106,1, - 118,1,114,28,116,2,100,1,160,3,124,1,161,1,124,1, - 100,2,141,2,130,1,136,0,124,0,124,1,131,2,83,0, - 41,3,78,250,29,123,33,114,125,32,105,115,32,110,111,116, - 32,97,32,98,117,105,108,116,45,105,110,32,109,111,100,117, - 108,101,114,16,0,0,0,41,4,114,15,0,0,0,218,20, - 98,117,105,108,116,105,110,95,109,111,100,117,108,101,95,110, - 97,109,101,115,218,11,73,109,112,111,114,116,69,114,114,111, - 114,114,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,97,112, - 112,101,114,232,0,0,0,115,10,0,0,0,0,1,10,1, - 10,1,2,255,6,2,122,52,95,114,101,113,117,105,114,101, - 115,95,98,117,105,108,116,105,110,46,60,108,111,99,97,108, - 115,62,46,95,114,101,113,117,105,114,101,115,95,98,117,105, - 108,116,105,110,95,119,114,97,112,112,101,114,169,1,114,12, - 0,0,0,41,2,114,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,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,3,122, - 47,68,101,99,111,114,97,116,111,114,32,116,111,32,118,101, - 114,105,102,121,32,116,104,101,32,110,97,109,101,100,32,109, - 111,100,117,108,101,32,105,115,32,102,114,111,122,101,110,46, + 19,95,108,111,99,107,95,117,110,108,111,99,107,95,109,111, + 100,117,108,101,203,0,0,0,115,12,0,0,0,0,6,8, + 1,2,1,12,1,12,3,6,2,114,66,0,0,0,99,1, + 0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,4, + 0,0,0,79,0,0,0,115,14,0,0,0,124,0,124,1, + 105,0,124,2,164,1,142,1,83,0,41,1,97,46,1,0, + 0,114,101,109,111,118,101,95,105,109,112,111,114,116,108,105, + 98,95,102,114,97,109,101,115,32,105,110,32,105,109,112,111, + 114,116,46,99,32,119,105,108,108,32,97,108,119,97,121,115, + 32,114,101,109,111,118,101,32,115,101,113,117,101,110,99,101, + 115,10,32,32,32,32,111,102,32,105,109,112,111,114,116,108, + 105,98,32,102,114,97,109,101,115,32,116,104,97,116,32,101, + 110,100,32,119,105,116,104,32,97,32,99,97,108,108,32,116, + 111,32,116,104,105,115,32,102,117,110,99,116,105,111,110,10, + 10,32,32,32,32,85,115,101,32,105,116,32,105,110,115,116, + 101,97,100,32,111,102,32,97,32,110,111,114,109,97,108,32, + 99,97,108,108,32,105,110,32,112,108,97,99,101,115,32,119, + 104,101,114,101,32,105,110,99,108,117,100,105,110,103,32,116, + 104,101,32,105,109,112,111,114,116,108,105,98,10,32,32,32, + 32,102,114,97,109,101,115,32,105,110,116,114,111,100,117,99, + 101,115,32,117,110,119,97,110,116,101,100,32,110,111,105,115, + 101,32,105,110,116,111,32,116,104,101,32,116,114,97,99,101, + 98,97,99,107,32,40,101,46,103,46,32,119,104,101,110,32, + 101,120,101,99,117,116,105,110,103,10,32,32,32,32,109,111, + 100,117,108,101,32,99,111,100,101,41,10,32,32,32,32,114, + 10,0,0,0,41,3,218,1,102,114,56,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,220,0, + 0,0,115,2,0,0,0,0,8,114,68,0,0,0,114,39, + 0,0,0,41,1,218,9,118,101,114,98,111,115,105,116,121, + 99,1,0,0,0,0,0,0,0,1,0,0,0,3,0,0, + 0,4,0,0,0,71,0,0,0,115,54,0,0,0,116,0, + 106,1,106,2,124,1,107,5,114,50,124,0,160,3,100,1, + 161,1,115,30,100,2,124,0,23,0,125,0,116,4,124,0, + 106,5,124,2,142,0,116,0,106,6,100,3,141,2,1,0, + 100,4,83,0,41,5,122,61,80,114,105,110,116,32,116,104, + 101,32,109,101,115,115,97,103,101,32,116,111,32,115,116,100, + 101,114,114,32,105,102,32,45,118,47,80,89,84,72,79,78, + 86,69,82,66,79,83,69,32,105,115,32,116,117,114,110,101, + 100,32,111,110,46,41,2,250,1,35,122,7,105,109,112,111, + 114,116,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,46,0,0,0,218, + 6,115,116,100,101,114,114,41,3,218,7,109,101,115,115,97, + 103,101,114,69,0,0,0,114,56,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,231,0,0, + 0,115,8,0,0,0,0,2,12,1,10,1,8,1,114,77, + 0,0,0,99,1,0,0,0,0,0,0,0,0,0,0,0, + 2,0,0,0,3,0,0,0,3,0,0,0,115,26,0,0, + 0,135,0,102,1,100,1,100,2,132,8,125,1,116,0,124, + 1,136,0,131,2,1,0,124,1,83,0,41,3,122,49,68, + 101,99,111,114,97,116,111,114,32,116,111,32,118,101,114,105, + 102,121,32,116,104,101,32,110,97,109,101,100,32,109,111,100, + 117,108,101,32,105,115,32,98,117,105,108,116,45,105,110,46, 99,2,0,0,0,0,0,0,0,0,0,0,0,2,0,0, - 0,4,0,0,0,19,0,0,0,115,38,0,0,0,116,0, - 160,1,124,1,161,1,115,28,116,2,100,1,160,3,124,1, + 0,4,0,0,0,19,0,0,0,115,38,0,0,0,124,1, + 116,0,106,1,118,1,114,28,116,2,100,1,160,3,124,1, 161,1,124,1,100,2,141,2,130,1,136,0,124,0,124,1, - 131,2,83,0,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,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,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,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,118,0, - 114,50,116,1,106,2,124,1,25,0,125,3,116,3,124,2, - 124,3,131,2,1,0,116,1,106,2,124,1,25,0,83,0, - 116,4,124,2,131,1,83,0,100,1,83,0,41,2,122,128, - 76,111,97,100,32,116,104,101,32,115,112,101,99,105,102,105, - 101,100,32,109,111,100,117,108,101,32,105,110,116,111,32,115, - 121,115,46,109,111,100,117,108,101,115,32,97,110,100,32,114, - 101,116,117,114,110,32,105,116,46,10,10,32,32,32,32,84, - 104,105,115,32,109,101,116,104,111,100,32,105,115,32,100,101, - 112,114,101,99,97,116,101,100,46,32,32,85,115,101,32,108, - 111,97,100,101,114,46,101,120,101,99,95,109,111,100,117,108, - 101,32,105,110,115,116,101,97,100,46,10,10,32,32,32,32, - 78,41,5,218,16,115,112,101,99,95,102,114,111,109,95,108, - 111,97,100,101,114,114,15,0,0,0,218,7,109,111,100,117, - 108,101,115,218,5,95,101,120,101,99,218,5,95,108,111,97, - 100,41,4,114,30,0,0,0,114,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,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,218,0,0,0,116,0,124,0,100,1,100,0,131,3,125, - 1,116,1,124,1,100,2,131,2,114,54,122,12,124,1,160, - 2,124,0,161,1,87,0,83,0,4,0,116,3,121,52,1, - 0,1,0,1,0,89,0,110,2,48,0,122,10,124,0,106, - 4,125,2,87,0,110,18,4,0,116,5,121,82,1,0,1, - 0,1,0,89,0,110,18,48,0,124,2,100,0,117,1,114, - 100,116,6,124,2,131,1,83,0,122,10,124,0,106,7,125, - 3,87,0,110,22,4,0,116,5,121,132,1,0,1,0,1, - 0,100,3,125,3,89,0,110,2,48,0,122,10,124,0,106, - 8,125,4,87,0,110,56,4,0,116,5,121,200,1,0,1, - 0,1,0,124,1,100,0,117,0,114,180,100,4,160,9,124, - 3,161,1,6,0,89,0,83,0,100,5,160,9,124,3,124, - 1,161,2,6,0,89,0,83,0,89,0,110,14,48,0,100, - 6,160,9,124,3,124,4,161,2,83,0,100,0,83,0,41, - 7,78,218,10,95,95,108,111,97,100,101,114,95,95,218,11, - 109,111,100,117,108,101,95,114,101,112,114,250,1,63,250,13, - 60,109,111,100,117,108,101,32,123,33,114,125,62,250,20,60, - 109,111,100,117,108,101,32,123,33,114,125,32,40,123,33,114, - 125,41,62,250,23,60,109,111,100,117,108,101,32,123,33,114, - 125,32,102,114,111,109,32,123,33,114,125,62,41,10,114,6, - 0,0,0,114,4,0,0,0,114,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,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,12,1,6,1,2,1,10,1,12,1,6,2,8,1,8, - 4,2,1,10,1,12,1,10,1,2,1,10,1,12,1,8, - 1,14,2,22,2,114,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,100,6,100,7,132,0,90,5,100,8, - 100,9,132,0,90,6,101,7,100,10,100,11,132,0,131,1, - 90,8,101,8,106,9,100,12,100,11,132,0,131,1,90,8, - 101,7,100,13,100,14,132,0,131,1,90,10,101,7,100,15, - 100,16,132,0,131,1,90,11,101,11,106,9,100,17,100,16, - 132,0,131,1,90,11,100,2,83,0,41,18,218,10,77,111, - 100,117,108,101,83,112,101,99,97,208,5,0,0,84,104,101, - 32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,102, - 111,114,32,97,32,109,111,100,117,108,101,44,32,117,115,101, - 100,32,102,111,114,32,108,111,97,100,105,110,103,46,10,10, - 32,32,32,32,65,32,109,111,100,117,108,101,39,115,32,115, - 112,101,99,32,105,115,32,116,104,101,32,115,111,117,114,99, - 101,32,102,111,114,32,105,110,102,111,114,109,97,116,105,111, - 110,32,97,98,111,117,116,32,116,104,101,32,109,111,100,117, - 108,101,46,32,32,70,111,114,10,32,32,32,32,100,97,116, - 97,32,97,115,115,111,99,105,97,116,101,100,32,119,105,116, - 104,32,116,104,101,32,109,111,100,117,108,101,44,32,105,110, - 99,108,117,100,105,110,103,32,115,111,117,114,99,101,44,32, - 117,115,101,32,116,104,101,32,115,112,101,99,39,115,10,32, - 32,32,32,108,111,97,100,101,114,46,10,10,32,32,32,32, - 96,110,97,109,101,96,32,105,115,32,116,104,101,32,97,98, - 115,111,108,117,116,101,32,110,97,109,101,32,111,102,32,116, - 104,101,32,109,111,100,117,108,101,46,32,32,96,108,111,97, - 100,101,114,96,32,105,115,32,116,104,101,32,108,111,97,100, - 101,114,10,32,32,32,32,116,111,32,117,115,101,32,119,104, - 101,110,32,108,111,97,100,105,110,103,32,116,104,101,32,109, - 111,100,117,108,101,46,32,32,96,112,97,114,101,110,116,96, - 32,105,115,32,116,104,101,32,110,97,109,101,32,111,102,32, - 116,104,101,10,32,32,32,32,112,97,99,107,97,103,101,32, - 116,104,101,32,109,111,100,117,108,101,32,105,115,32,105,110, - 46,32,32,84,104,101,32,112,97,114,101,110,116,32,105,115, - 32,100,101,114,105,118,101,100,32,102,114,111,109,32,116,104, - 101,32,110,97,109,101,46,10,10,32,32,32,32,96,105,115, - 95,112,97,99,107,97,103,101,96,32,100,101,116,101,114,109, - 105,110,101,115,32,105,102,32,116,104,101,32,109,111,100,117, - 108,101,32,105,115,32,99,111,110,115,105,100,101,114,101,100, - 32,97,32,112,97,99,107,97,103,101,32,111,114,10,32,32, - 32,32,110,111,116,46,32,32,79,110,32,109,111,100,117,108, - 101,115,32,116,104,105,115,32,105,115,32,114,101,102,108,101, - 99,116,101,100,32,98,121,32,116,104,101,32,96,95,95,112, - 97,116,104,95,95,96,32,97,116,116,114,105,98,117,116,101, - 46,10,10,32,32,32,32,96,111,114,105,103,105,110,96,32, - 105,115,32,116,104,101,32,115,112,101,99,105,102,105,99,32, - 108,111,99,97,116,105,111,110,32,117,115,101,100,32,98,121, - 32,116,104,101,32,108,111,97,100,101,114,32,102,114,111,109, - 32,119,104,105,99,104,32,116,111,10,32,32,32,32,108,111, - 97,100,32,116,104,101,32,109,111,100,117,108,101,44,32,105, - 102,32,116,104,97,116,32,105,110,102,111,114,109,97,116,105, - 111,110,32,105,115,32,97,118,97,105,108,97,98,108,101,46, - 32,32,87,104,101,110,32,102,105,108,101,110,97,109,101,32, - 105,115,10,32,32,32,32,115,101,116,44,32,111,114,105,103, - 105,110,32,119,105,108,108,32,109,97,116,99,104,46,10,10, - 32,32,32,32,96,104,97,115,95,108,111,99,97,116,105,111, - 110,96,32,105,110,100,105,99,97,116,101,115,32,116,104,97, - 116,32,97,32,115,112,101,99,39,115,32,34,111,114,105,103, - 105,110,34,32,114,101,102,108,101,99,116,115,32,97,32,108, - 111,99,97,116,105,111,110,46,10,32,32,32,32,87,104,101, - 110,32,116,104,105,115,32,105,115,32,84,114,117,101,44,32, - 96,95,95,102,105,108,101,95,95,96,32,97,116,116,114,105, - 98,117,116,101,32,111,102,32,116,104,101,32,109,111,100,117, - 108,101,32,105,115,32,115,101,116,46,10,10,32,32,32,32, - 96,99,97,99,104,101,100,96,32,105,115,32,116,104,101,32, - 108,111,99,97,116,105,111,110,32,111,102,32,116,104,101,32, - 99,97,99,104,101,100,32,98,121,116,101,99,111,100,101,32, - 102,105,108,101,44,32,105,102,32,97,110,121,46,32,32,73, - 116,10,32,32,32,32,99,111,114,114,101,115,112,111,110,100, - 115,32,116,111,32,116,104,101,32,96,95,95,99,97,99,104, - 101,100,95,95,96,32,97,116,116,114,105,98,117,116,101,46, - 10,10,32,32,32,32,96,115,117,98,109,111,100,117,108,101, - 95,115,101,97,114,99,104,95,108,111,99,97,116,105,111,110, - 115,96,32,105,115,32,116,104,101,32,115,101,113,117,101,110, - 99,101,32,111,102,32,112,97,116,104,32,101,110,116,114,105, - 101,115,32,116,111,10,32,32,32,32,115,101,97,114,99,104, - 32,119,104,101,110,32,105,109,112,111,114,116,105,110,103,32, - 115,117,98,109,111,100,117,108,101,115,46,32,32,73,102,32, - 115,101,116,44,32,105,115,95,112,97,99,107,97,103,101,32, - 115,104,111,117,108,100,32,98,101,10,32,32,32,32,84,114, - 117,101,45,45,97,110,100,32,70,97,108,115,101,32,111,116, - 104,101,114,119,105,115,101,46,10,10,32,32,32,32,80,97, - 99,107,97,103,101,115,32,97,114,101,32,115,105,109,112,108, - 121,32,109,111,100,117,108,101,115,32,116,104,97,116,32,40, - 109,97,121,41,32,104,97,118,101,32,115,117,98,109,111,100, - 117,108,101,115,46,32,32,73,102,32,97,32,115,112,101,99, - 10,32,32,32,32,104,97,115,32,97,32,110,111,110,45,78, - 111,110,101,32,118,97,108,117,101,32,105,110,32,96,115,117, - 98,109,111,100,117,108,101,95,115,101,97,114,99,104,95,108, - 111,99,97,116,105,111,110,115,96,44,32,116,104,101,32,105, - 109,112,111,114,116,10,32,32,32,32,115,121,115,116,101,109, - 32,119,105,108,108,32,99,111,110,115,105,100,101,114,32,109, - 111,100,117,108,101,115,32,108,111,97,100,101,100,32,102,114, - 111,109,32,116,104,101,32,115,112,101,99,32,97,115,32,112, - 97,99,107,97,103,101,115,46,10,10,32,32,32,32,79,110, - 108,121,32,102,105,110,100,101,114,115,32,40,115,101,101,32, - 105,109,112,111,114,116,108,105,98,46,97,98,99,46,77,101, - 116,97,80,97,116,104,70,105,110,100,101,114,32,97,110,100, - 10,32,32,32,32,105,109,112,111,114,116,108,105,98,46,97, - 98,99,46,80,97,116,104,69,110,116,114,121,70,105,110,100, - 101,114,41,32,115,104,111,117,108,100,32,109,111,100,105,102, - 121,32,77,111,100,117,108,101,83,112,101,99,32,105,110,115, - 116,97,110,99,101,115,46,10,10,32,32,32,32,78,41,3, - 218,6,111,114,105,103,105,110,218,12,108,111,97,100,101,114, - 95,115,116,97,116,101,218,10,105,115,95,112,97,99,107,97, - 103,101,99,3,0,0,0,0,0,0,0,3,0,0,0,6, - 0,0,0,2,0,0,0,67,0,0,0,115,54,0,0,0, - 124,1,124,0,95,0,124,2,124,0,95,1,124,3,124,0, - 95,2,124,4,124,0,95,3,124,5,114,32,103,0,110,2, - 100,0,124,0,95,4,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,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,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,101,83,112,101,99,46,95,95,105,110, - 105,116,95,95,99,1,0,0,0,0,0,0,0,0,0,0, - 0,2,0,0,0,6,0,0,0,67,0,0,0,115,102,0, - 0,0,100,1,160,0,124,0,106,1,161,1,100,2,160,0, - 124,0,106,2,161,1,103,2,125,1,124,0,106,3,100,0, - 117,1,114,52,124,1,160,4,100,3,160,0,124,0,106,3, - 161,1,161,1,1,0,124,0,106,5,100,0,117,1,114,80, - 124,1,160,4,100,4,160,0,124,0,106,5,161,1,161,1, - 1,0,100,5,160,0,124,0,106,6,106,7,100,6,160,8, - 124,1,161,1,161,2,83,0,41,7,78,122,9,110,97,109, - 101,61,123,33,114,125,122,11,108,111,97,100,101,114,61,123, - 33,114,125,122,11,111,114,105,103,105,110,61,123,33,114,125, - 122,29,115,117,98,109,111,100,117,108,101,95,115,101,97,114, - 99,104,95,108,111,99,97,116,105,111,110,115,61,123,125,122, - 6,123,125,40,123,125,41,122,2,44,32,41,9,114,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,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,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,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,121,100,1,0,1,0,1,0, - 116,7,6,0,89,0,83,0,48,0,100,0,83,0,114,13, - 0,0,0,41,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,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,12,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,117,0,114, - 52,124,0,106,1,100,0,117,1,114,52,124,0,106,2,114, - 52,116,3,100,0,117,0,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,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,46, + 131,2,83,0,41,3,78,250,29,123,33,114,125,32,105,115, + 32,110,111,116,32,97,32,98,117,105,108,116,45,105,110,32, + 109,111,100,117,108,101,114,16,0,0,0,41,4,114,15,0, + 0,0,218,20,98,117,105,108,116,105,110,95,109,111,100,117, + 108,101,95,110,97,109,101,115,218,11,73,109,112,111,114,116, + 69,114,114,111,114,114,46,0,0,0,169,2,114,30,0,0, + 0,218,8,102,117,108,108,110,97,109,101,169,1,218,3,102, + 120,110,114,10,0,0,0,114,11,0,0,0,218,25,95,114, + 101,113,117,105,114,101,115,95,98,117,105,108,116,105,110,95, + 119,114,97,112,112,101,114,241,0,0,0,115,10,0,0,0, + 0,1,10,1,10,1,2,255,6,2,122,52,95,114,101,113, + 117,105,114,101,115,95,98,117,105,108,116,105,110,46,60,108, + 111,99,97,108,115,62,46,95,114,101,113,117,105,114,101,115, + 95,98,117,105,108,116,105,110,95,119,114,97,112,112,101,114, + 169,1,114,12,0,0,0,41,2,114,84,0,0,0,114,85, + 0,0,0,114,10,0,0,0,114,83,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,239,0,0,0,115,6,0,0,0,0,2, + 12,5,10,1,114,87,0,0,0,99,1,0,0,0,0,0, + 0,0,0,0,0,0,2,0,0,0,3,0,0,0,3,0, + 0,0,115,26,0,0,0,135,0,102,1,100,1,100,2,132, + 8,125,1,116,0,124,1,136,0,131,2,1,0,124,1,83, + 0,41,3,122,47,68,101,99,111,114,97,116,111,114,32,116, + 111,32,118,101,114,105,102,121,32,116,104,101,32,110,97,109, + 101,100,32,109,111,100,117,108,101,32,105,115,32,102,114,111, + 122,101,110,46,99,2,0,0,0,0,0,0,0,0,0,0, + 0,2,0,0,0,4,0,0,0,19,0,0,0,115,38,0, + 0,0,116,0,160,1,124,1,161,1,115,28,116,2,100,1, + 160,3,124,1,161,1,124,1,100,2,141,2,130,1,136,0, + 124,0,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, + 58,0,0,0,218,9,105,115,95,102,114,111,122,101,110,114, + 80,0,0,0,114,46,0,0,0,114,81,0,0,0,114,83, + 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,252,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,86, + 0,0,0,41,2,114,84,0,0,0,114,90,0,0,0,114, + 10,0,0,0,114,83,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, + 250,0,0,0,115,6,0,0,0,0,2,12,5,10,1,114, + 91,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,118,0,114,50,116,1,106,2,124,1,25,0,125,3, + 116,3,124,2,124,3,131,2,1,0,116,1,106,2,124,1, + 25,0,83,0,116,4,124,2,131,1,83,0,100,1,83,0, + 41,2,122,128,76,111,97,100,32,116,104,101,32,115,112,101, + 99,105,102,105,101,100,32,109,111,100,117,108,101,32,105,110, + 116,111,32,115,121,115,46,109,111,100,117,108,101,115,32,97, + 110,100,32,114,101,116,117,114,110,32,105,116,46,10,10,32, + 32,32,32,84,104,105,115,32,109,101,116,104,111,100,32,105, + 115,32,100,101,112,114,101,99,97,116,101,100,46,32,32,85, + 115,101,32,108,111,97,100,101,114,46,101,120,101,99,95,109, + 111,100,117,108,101,32,105,110,115,116,101,97,100,46,10,10, + 32,32,32,32,78,41,5,218,16,115,112,101,99,95,102,114, + 111,109,95,108,111,97,100,101,114,114,15,0,0,0,218,7, + 109,111,100,117,108,101,115,218,5,95,101,120,101,99,218,5, + 95,108,111,97,100,41,4,114,30,0,0,0,114,82,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,6,1,0,0,115,12,0,0,0,0,6,10,1,10,1, + 10,1,10,1,10,2,114,98,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,218,0,0,0,116,0,124,0,100,1,100, + 0,131,3,125,1,116,1,124,1,100,2,131,2,114,54,122, + 12,124,1,160,2,124,0,161,1,87,0,83,0,4,0,116, + 3,121,52,1,0,1,0,1,0,89,0,110,2,48,0,122, + 10,124,0,106,4,125,2,87,0,110,18,4,0,116,5,121, + 82,1,0,1,0,1,0,89,0,110,18,48,0,124,2,100, + 0,117,1,114,100,116,6,124,2,131,1,83,0,122,10,124, + 0,106,7,125,3,87,0,110,22,4,0,116,5,121,132,1, + 0,1,0,1,0,100,3,125,3,89,0,110,2,48,0,122, + 10,124,0,106,8,125,4,87,0,110,56,4,0,116,5,121, + 200,1,0,1,0,1,0,124,1,100,0,117,0,114,180,100, + 4,160,9,124,3,161,1,6,0,89,0,83,0,100,5,160, + 9,124,3,124,1,161,2,6,0,89,0,83,0,89,0,110, + 14,48,0,100,6,160,9,124,3,124,4,161,2,83,0,100, + 0,83,0,41,7,78,218,10,95,95,108,111,97,100,101,114, + 95,95,218,11,109,111,100,117,108,101,95,114,101,112,114,250, + 1,63,250,13,60,109,111,100,117,108,101,32,123,33,114,125, + 62,250,20,60,109,111,100,117,108,101,32,123,33,114,125,32, + 40,123,33,114,125,41,62,250,23,60,109,111,100,117,108,101, + 32,123,33,114,125,32,102,114,111,109,32,123,33,114,125,62, + 41,10,114,6,0,0,0,114,4,0,0,0,114,100,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,46,0, + 0,0,41,5,114,97,0,0,0,218,6,108,111,97,100,101, + 114,114,96,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,22,1,0,0,115,46,0,0,0,0,2,12,1,10, + 4,2,1,12,1,12,1,6,1,2,1,10,1,12,1,6, + 2,8,1,8,4,2,1,10,1,12,1,10,1,2,1,10, + 1,12,1,8,1,14,2,22,2,114,112,0,0,0,99,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4, + 0,0,0,64,0,0,0,115,114,0,0,0,101,0,90,1, + 100,0,90,2,100,1,90,3,100,2,100,2,100,2,100,3, + 156,3,100,4,100,5,132,2,90,4,100,6,100,7,132,0, + 90,5,100,8,100,9,132,0,90,6,101,7,100,10,100,11, + 132,0,131,1,90,8,101,8,106,9,100,12,100,11,132,0, + 131,1,90,8,101,7,100,13,100,14,132,0,131,1,90,10, + 101,7,100,15,100,16,132,0,131,1,90,11,101,11,106,9, + 100,17,100,16,132,0,131,1,90,11,100,2,83,0,41,18, + 218,10,77,111,100,117,108,101,83,112,101,99,97,208,5,0, + 0,84,104,101,32,115,112,101,99,105,102,105,99,97,116,105, + 111,110,32,102,111,114,32,97,32,109,111,100,117,108,101,44, + 32,117,115,101,100,32,102,111,114,32,108,111,97,100,105,110, + 103,46,10,10,32,32,32,32,65,32,109,111,100,117,108,101, + 39,115,32,115,112,101,99,32,105,115,32,116,104,101,32,115, + 111,117,114,99,101,32,102,111,114,32,105,110,102,111,114,109, + 97,116,105,111,110,32,97,98,111,117,116,32,116,104,101,32, + 109,111,100,117,108,101,46,32,32,70,111,114,10,32,32,32, + 32,100,97,116,97,32,97,115,115,111,99,105,97,116,101,100, + 32,119,105,116,104,32,116,104,101,32,109,111,100,117,108,101, + 44,32,105,110,99,108,117,100,105,110,103,32,115,111,117,114, + 99,101,44,32,117,115,101,32,116,104,101,32,115,112,101,99, + 39,115,10,32,32,32,32,108,111,97,100,101,114,46,10,10, + 32,32,32,32,96,110,97,109,101,96,32,105,115,32,116,104, + 101,32,97,98,115,111,108,117,116,101,32,110,97,109,101,32, + 111,102,32,116,104,101,32,109,111,100,117,108,101,46,32,32, + 96,108,111,97,100,101,114,96,32,105,115,32,116,104,101,32, + 108,111,97,100,101,114,10,32,32,32,32,116,111,32,117,115, + 101,32,119,104,101,110,32,108,111,97,100,105,110,103,32,116, + 104,101,32,109,111,100,117,108,101,46,32,32,96,112,97,114, + 101,110,116,96,32,105,115,32,116,104,101,32,110,97,109,101, + 32,111,102,32,116,104,101,10,32,32,32,32,112,97,99,107, + 97,103,101,32,116,104,101,32,109,111,100,117,108,101,32,105, + 115,32,105,110,46,32,32,84,104,101,32,112,97,114,101,110, + 116,32,105,115,32,100,101,114,105,118,101,100,32,102,114,111, + 109,32,116,104,101,32,110,97,109,101,46,10,10,32,32,32, + 32,96,105,115,95,112,97,99,107,97,103,101,96,32,100,101, + 116,101,114,109,105,110,101,115,32,105,102,32,116,104,101,32, + 109,111,100,117,108,101,32,105,115,32,99,111,110,115,105,100, + 101,114,101,100,32,97,32,112,97,99,107,97,103,101,32,111, + 114,10,32,32,32,32,110,111,116,46,32,32,79,110,32,109, + 111,100,117,108,101,115,32,116,104,105,115,32,105,115,32,114, + 101,102,108,101,99,116,101,100,32,98,121,32,116,104,101,32, + 96,95,95,112,97,116,104,95,95,96,32,97,116,116,114,105, + 98,117,116,101,46,10,10,32,32,32,32,96,111,114,105,103, + 105,110,96,32,105,115,32,116,104,101,32,115,112,101,99,105, + 102,105,99,32,108,111,99,97,116,105,111,110,32,117,115,101, + 100,32,98,121,32,116,104,101,32,108,111,97,100,101,114,32, + 102,114,111,109,32,119,104,105,99,104,32,116,111,10,32,32, + 32,32,108,111,97,100,32,116,104,101,32,109,111,100,117,108, + 101,44,32,105,102,32,116,104,97,116,32,105,110,102,111,114, + 109,97,116,105,111,110,32,105,115,32,97,118,97,105,108,97, + 98,108,101,46,32,32,87,104,101,110,32,102,105,108,101,110, + 97,109,101,32,105,115,10,32,32,32,32,115,101,116,44,32, + 111,114,105,103,105,110,32,119,105,108,108,32,109,97,116,99, + 104,46,10,10,32,32,32,32,96,104,97,115,95,108,111,99, + 97,116,105,111,110,96,32,105,110,100,105,99,97,116,101,115, + 32,116,104,97,116,32,97,32,115,112,101,99,39,115,32,34, + 111,114,105,103,105,110,34,32,114,101,102,108,101,99,116,115, + 32,97,32,108,111,99,97,116,105,111,110,46,10,32,32,32, + 32,87,104,101,110,32,116,104,105,115,32,105,115,32,84,114, + 117,101,44,32,96,95,95,102,105,108,101,95,95,96,32,97, + 116,116,114,105,98,117,116,101,32,111,102,32,116,104,101,32, + 109,111,100,117,108,101,32,105,115,32,115,101,116,46,10,10, + 32,32,32,32,96,99,97,99,104,101,100,96,32,105,115,32, + 116,104,101,32,108,111,99,97,116,105,111,110,32,111,102,32, + 116,104,101,32,99,97,99,104,101,100,32,98,121,116,101,99, + 111,100,101,32,102,105,108,101,44,32,105,102,32,97,110,121, + 46,32,32,73,116,10,32,32,32,32,99,111,114,114,101,115, + 112,111,110,100,115,32,116,111,32,116,104,101,32,96,95,95, + 99,97,99,104,101,100,95,95,96,32,97,116,116,114,105,98, + 117,116,101,46,10,10,32,32,32,32,96,115,117,98,109,111, + 100,117,108,101,95,115,101,97,114,99,104,95,108,111,99,97, + 116,105,111,110,115,96,32,105,115,32,116,104,101,32,115,101, + 113,117,101,110,99,101,32,111,102,32,112,97,116,104,32,101, + 110,116,114,105,101,115,32,116,111,10,32,32,32,32,115,101, + 97,114,99,104,32,119,104,101,110,32,105,109,112,111,114,116, + 105,110,103,32,115,117,98,109,111,100,117,108,101,115,46,32, + 32,73,102,32,115,101,116,44,32,105,115,95,112,97,99,107, + 97,103,101,32,115,104,111,117,108,100,32,98,101,10,32,32, + 32,32,84,114,117,101,45,45,97,110,100,32,70,97,108,115, + 101,32,111,116,104,101,114,119,105,115,101,46,10,10,32,32, + 32,32,80,97,99,107,97,103,101,115,32,97,114,101,32,115, + 105,109,112,108,121,32,109,111,100,117,108,101,115,32,116,104, + 97,116,32,40,109,97,121,41,32,104,97,118,101,32,115,117, + 98,109,111,100,117,108,101,115,46,32,32,73,102,32,97,32, + 115,112,101,99,10,32,32,32,32,104,97,115,32,97,32,110, + 111,110,45,78,111,110,101,32,118,97,108,117,101,32,105,110, + 32,96,115,117,98,109,111,100,117,108,101,95,115,101,97,114, + 99,104,95,108,111,99,97,116,105,111,110,115,96,44,32,116, + 104,101,32,105,109,112,111,114,116,10,32,32,32,32,115,121, + 115,116,101,109,32,119,105,108,108,32,99,111,110,115,105,100, + 101,114,32,109,111,100,117,108,101,115,32,108,111,97,100,101, + 100,32,102,114,111,109,32,116,104,101,32,115,112,101,99,32, + 97,115,32,112,97,99,107,97,103,101,115,46,10,10,32,32, + 32,32,79,110,108,121,32,102,105,110,100,101,114,115,32,40, + 115,101,101,32,105,109,112,111,114,116,108,105,98,46,97,98, + 99,46,77,101,116,97,80,97,116,104,70,105,110,100,101,114, + 32,97,110,100,10,32,32,32,32,105,109,112,111,114,116,108, + 105,98,46,97,98,99,46,80,97,116,104,69,110,116,114,121, + 70,105,110,100,101,114,41,32,115,104,111,117,108,100,32,109, + 111,100,105,102,121,32,77,111,100,117,108,101,83,112,101,99, + 32,105,110,115,116,97,110,99,101,115,46,10,10,32,32,32, + 32,78,41,3,218,6,111,114,105,103,105,110,218,12,108,111, + 97,100,101,114,95,115,116,97,116,101,218,10,105,115,95,112, + 97,99,107,97,103,101,99,3,0,0,0,0,0,0,0,3, + 0,0,0,6,0,0,0,2,0,0,0,67,0,0,0,115, + 54,0,0,0,124,1,124,0,95,0,124,2,124,0,95,1, + 124,3,124,0,95,2,124,4,124,0,95,3,124,5,114,32, + 103,0,110,2,100,0,124,0,95,4,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,110,0,0,0,114,114,0,0,0,114, + 115,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,110,0,0,0,114,114,0,0,0,114,115, + 0,0,0,114,116,0,0,0,114,10,0,0,0,114,10,0, + 0,0,114,11,0,0,0,114,31,0,0,0,95,1,0,0, + 115,14,0,0,0,0,2,6,1,6,1,6,1,6,1,14, + 3,6,1,122,19,77,111,100,117,108,101,83,112,101,99,46, + 95,95,105,110,105,116,95,95,99,1,0,0,0,0,0,0, + 0,0,0,0,0,2,0,0,0,6,0,0,0,67,0,0, + 0,115,102,0,0,0,100,1,160,0,124,0,106,1,161,1, + 100,2,160,0,124,0,106,2,161,1,103,2,125,1,124,0, + 106,3,100,0,117,1,114,52,124,1,160,4,100,3,160,0, + 124,0,106,3,161,1,161,1,1,0,124,0,106,5,100,0, + 117,1,114,80,124,1,160,4,100,4,160,0,124,0,106,5, + 161,1,161,1,1,0,100,5,160,0,124,0,106,6,106,7, + 100,6,160,8,124,1,161,1,161,2,83,0,41,7,78,122, + 9,110,97,109,101,61,123,33,114,125,122,11,108,111,97,100, + 101,114,61,123,33,114,125,122,11,111,114,105,103,105,110,61, + 123,33,114,125,122,29,115,117,98,109,111,100,117,108,101,95, + 115,101,97,114,99,104,95,108,111,99,97,116,105,111,110,115, + 61,123,125,122,6,123,125,40,123,125,41,122,2,44,32,41, + 9,114,46,0,0,0,114,17,0,0,0,114,110,0,0,0, + 114,114,0,0,0,218,6,97,112,112,101,110,100,114,117,0, + 0,0,218,9,95,95,99,108,97,115,115,95,95,114,1,0, + 0,0,218,4,106,111,105,110,41,2,114,30,0,0,0,114, + 56,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, + 0,0,0,114,49,0,0,0,107,1,0,0,115,20,0,0, + 0,0,1,10,1,10,255,4,2,10,1,18,1,10,1,8, + 1,4,255,6,2,122,19,77,111,100,117,108,101,83,112,101, + 99,46,95,95,114,101,112,114,95,95,99,2,0,0,0,0, + 0,0,0,0,0,0,0,3,0,0,0,8,0,0,0,67, + 0,0,0,115,106,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,121,100,1,0, + 1,0,1,0,116,7,6,0,89,0,83,0,48,0,100,0, + 83,0,114,13,0,0,0,41,8,114,117,0,0,0,114,17, + 0,0,0,114,110,0,0,0,114,114,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,107,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,117,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,12,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,117,0,114,52,124,0,106,1,100,0,117,1,114,52,124, + 0,106,2,114,52,116,3,100,0,117,0,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,114,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,48,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, + 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,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,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,117,0,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, - 115,0,0,0,114,17,0,0,0,218,10,114,112,97,114,116, - 105,116,105,111,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,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,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,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,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,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,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,152,0, - 0,0,116,0,124,1,100,1,131,2,114,74,116,1,100,2, - 117,0,114,22,116,2,130,1,116,1,106,3,125,4,124,3, - 100,2,117,0,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, - 117,0,114,136,116,0,124,1,100,5,131,2,114,132,122,14, - 124,1,160,4,124,0,161,1,125,3,87,0,113,136,4,0, - 116,5,121,128,1,0,1,0,1,0,100,2,125,3,89,0, - 113,136,48,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,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,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,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,12,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,42,1,0,0, - 122,10,124,0,106,0,125,3,87,0,110,18,4,0,116,1, - 121,28,1,0,1,0,1,0,89,0,110,14,48,0,124,3, - 100,0,117,1,114,42,124,3,83,0,124,0,106,2,125,4, - 124,1,100,0,117,0,114,86,122,10,124,0,106,3,125,1, - 87,0,110,18,4,0,116,1,121,84,1,0,1,0,1,0, - 89,0,110,2,48,0,122,10,124,0,106,4,125,5,87,0, - 110,22,4,0,116,1,121,118,1,0,1,0,1,0,100,0, - 125,5,89,0,110,2,48,0,124,2,100,0,117,0,114,176, - 124,5,100,0,117,0,114,172,122,10,124,1,106,5,125,2, - 87,0,113,176,4,0,116,1,121,168,1,0,1,0,1,0, - 100,0,125,2,89,0,113,176,48,0,110,4,124,5,125,2, - 122,10,124,0,106,6,125,6,87,0,110,22,4,0,116,1, - 121,208,1,0,1,0,1,0,100,0,125,6,89,0,110,2, - 48,0,122,14,116,7,124,0,106,8,131,1,125,7,87,0, - 110,22,4,0,116,1,121,246,1,0,1,0,1,0,100,0, - 125,7,89,0,110,2,48,0,116,9,124,4,124,1,124,2, - 100,1,141,3,125,3,124,5,100,0,117,0,144,1,114,20, - 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, - 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,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,12,1,6,2,8,1, - 4,2,6,1,8,1,2,1,10,1,12,2,6,1,2,1, - 10,1,12,1,10,1,8,1,8,1,2,1,10,1,12,1, - 12,2,4,1,2,1,10,1,12,1,10,1,2,1,14,1, - 12,1,10,2,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,210,1,0,0,124,2,115,20, - 116,0,124,1,100,1,100,0,131,3,100,0,117,0,114,52, - 122,12,124,0,106,1,124,1,95,2,87,0,110,18,4,0, - 116,3,121,50,1,0,1,0,1,0,89,0,110,2,48,0, - 124,2,115,72,116,0,124,1,100,2,100,0,131,3,100,0, - 117,0,114,174,124,0,106,4,125,3,124,3,100,0,117,0, - 114,144,124,0,106,5,100,0,117,1,114,144,116,6,100,0, - 117,0,114,108,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,18,4,0,116,3,121,172,1,0, - 1,0,1,0,89,0,110,2,48,0,124,2,115,194,116,0, - 124,1,100,3,100,0,131,3,100,0,117,0,114,226,122,12, - 124,0,106,13,124,1,95,14,87,0,110,18,4,0,116,3, - 121,224,1,0,1,0,1,0,89,0,110,2,48,0,122,10, - 124,0,124,1,95,15,87,0,110,18,4,0,116,3,121,254, - 1,0,1,0,1,0,89,0,110,2,48,0,124,2,144,1, - 115,24,116,0,124,1,100,4,100,0,131,3,100,0,117,0, - 144,1,114,70,124,0,106,5,100,0,117,1,144,1,114,70, - 122,12,124,0,106,5,124,1,95,16,87,0,110,20,4,0, - 116,3,144,1,121,68,1,0,1,0,1,0,89,0,110,2, - 48,0,124,0,106,17,144,1,114,206,124,2,144,1,115,102, - 116,0,124,1,100,5,100,0,131,3,100,0,117,0,144,1, - 114,136,122,12,124,0,106,18,124,1,95,11,87,0,110,20, - 4,0,116,3,144,1,121,134,1,0,1,0,1,0,89,0, - 110,2,48,0,124,2,144,1,115,160,116,0,124,1,100,6, - 100,0,131,3,100,0,117,0,144,1,114,206,124,0,106,19, - 100,0,117,1,144,1,114,206,122,12,124,0,106,19,124,1, - 95,20,87,0,110,20,4,0,116,3,144,1,121,204,1,0, + 0,0,114,123,0,0,0,138,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,117,0,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,48,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,142,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,48,0,0,0,114,10,0,0, + 0,114,10,0,0,0,114,11,0,0,0,114,124,0,0,0, + 150,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,154,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,49,0,0,0,114, + 126,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,131,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,113,0,0,0,58,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,113,0,0,0,169,2,114,114, + 0,0,0,114,116,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,152,0,0,0,116,0,124,1,100,1,131,2,114,74, + 116,1,100,2,117,0,114,22,116,2,130,1,116,1,106,3, + 125,4,124,3,100,2,117,0,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,117,0,114,136,116,0,124,1,100,5,131,2, + 114,132,122,14,124,1,160,4,124,0,161,1,125,3,87,0, + 113,136,4,0,116,5,121,128,1,0,1,0,1,0,100,2, + 125,3,89,0,113,136,48,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,110,0,0,0,41,2,114, + 110,0,0,0,114,117,0,0,0,114,116,0,0,0,70,114, + 136,0,0,0,41,7,114,4,0,0,0,114,127,0,0,0, + 114,128,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,116, + 0,0,0,114,80,0,0,0,114,113,0,0,0,41,6,114, + 17,0,0,0,114,110,0,0,0,114,114,0,0,0,114,116, + 0,0,0,114,137,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, + 92,0,0,0,159,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,12,1,12,3,4, + 2,114,92,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, + 42,1,0,0,122,10,124,0,106,0,125,3,87,0,110,18, + 4,0,116,1,121,28,1,0,1,0,1,0,89,0,110,14, + 48,0,124,3,100,0,117,1,114,42,124,3,83,0,124,0, + 106,2,125,4,124,1,100,0,117,0,114,86,122,10,124,0, + 106,3,125,1,87,0,110,18,4,0,116,1,121,84,1,0, + 1,0,1,0,89,0,110,2,48,0,122,10,124,0,106,4, + 125,5,87,0,110,22,4,0,116,1,121,118,1,0,1,0, + 1,0,100,0,125,5,89,0,110,2,48,0,124,2,100,0, + 117,0,114,176,124,5,100,0,117,0,114,172,122,10,124,1, + 106,5,125,2,87,0,113,176,4,0,116,1,121,168,1,0, + 1,0,1,0,100,0,125,2,89,0,113,176,48,0,110,4, + 124,5,125,2,122,10,124,0,106,6,125,6,87,0,110,22, + 4,0,116,1,121,208,1,0,1,0,1,0,100,0,125,6, + 89,0,110,2,48,0,122,14,116,7,124,0,106,8,131,1, + 125,7,87,0,110,22,4,0,116,1,121,246,1,0,1,0, + 1,0,100,0,125,7,89,0,110,2,48,0,116,9,124,4, + 124,1,124,2,100,1,141,3,125,3,124,5,100,0,117,0, + 144,1,114,20,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,114,0,0,0,70,84,41,13,114,106,0,0, + 0,114,107,0,0,0,114,1,0,0,0,114,99,0,0,0, + 114,109,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,113,0,0,0,114, + 118,0,0,0,114,123,0,0,0,114,117,0,0,0,41,8, + 114,97,0,0,0,114,110,0,0,0,114,114,0,0,0,114, + 96,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,185, + 1,0,0,115,72,0,0,0,0,2,2,1,10,1,12,1, + 6,2,8,1,4,2,6,1,8,1,2,1,10,1,12,2, + 6,1,2,1,10,1,12,1,10,1,8,1,8,1,2,1, + 10,1,12,1,12,2,4,1,2,1,10,1,12,1,10,1, + 2,1,14,1,12,1,10,2,14,1,20,1,6,1,6,1, + 114,143,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,210,1,0,0, + 124,2,115,20,116,0,124,1,100,1,100,0,131,3,100,0, + 117,0,114,52,122,12,124,0,106,1,124,1,95,2,87,0, + 110,18,4,0,116,3,121,50,1,0,1,0,1,0,89,0, + 110,2,48,0,124,2,115,72,116,0,124,1,100,2,100,0, + 131,3,100,0,117,0,114,174,124,0,106,4,125,3,124,3, + 100,0,117,0,114,144,124,0,106,5,100,0,117,1,114,144, + 116,6,100,0,117,0,114,108,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,18,4,0,116,3, + 121,172,1,0,1,0,1,0,89,0,110,2,48,0,124,2, + 115,194,116,0,124,1,100,3,100,0,131,3,100,0,117,0, + 114,226,122,12,124,0,106,13,124,1,95,14,87,0,110,18, + 4,0,116,3,121,224,1,0,1,0,1,0,89,0,110,2, + 48,0,122,10,124,0,124,1,95,15,87,0,110,18,4,0, + 116,3,121,254,1,0,1,0,1,0,89,0,110,2,48,0, + 124,2,144,1,115,24,116,0,124,1,100,4,100,0,131,3, + 100,0,117,0,144,1,114,70,124,0,106,5,100,0,117,1, + 144,1,114,70,122,12,124,0,106,5,124,1,95,16,87,0, + 110,20,4,0,116,3,144,1,121,68,1,0,1,0,1,0, + 89,0,110,2,48,0,124,0,106,17,144,1,114,206,124,2, + 144,1,115,102,116,0,124,1,100,5,100,0,131,3,100,0, + 117,0,144,1,114,136,122,12,124,0,106,18,124,1,95,11, + 87,0,110,20,4,0,116,3,144,1,121,134,1,0,1,0, + 1,0,89,0,110,2,48,0,124,2,144,1,115,160,116,0, + 124,1,100,6,100,0,131,3,100,0,117,0,144,1,114,206, + 124,0,106,19,100,0,117,1,144,1,114,206,122,12,124,0, + 106,19,124,1,95,20,87,0,110,20,4,0,116,3,144,1, + 121,204,1,0,1,0,1,0,89,0,110,2,48,0,124,1, + 83,0,41,7,78,114,1,0,0,0,114,99,0,0,0,218, + 11,95,95,112,97,99,107,97,103,101,95,95,114,142,0,0, + 0,114,109,0,0,0,114,140,0,0,0,41,21,114,6,0, + 0,0,114,17,0,0,0,114,1,0,0,0,114,107,0,0, + 0,114,110,0,0,0,114,117,0,0,0,114,127,0,0,0, + 114,128,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,109,0,0,0,114,99,0,0, + 0,114,131,0,0,0,114,146,0,0,0,114,106,0,0,0, + 114,142,0,0,0,114,124,0,0,0,114,114,0,0,0,114, + 123,0,0,0,114,140,0,0,0,41,5,114,96,0,0,0, + 114,97,0,0,0,114,145,0,0,0,114,110,0,0,0,114, + 147,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,230,1,0,0,115,96,0,0,0, + 0,4,20,1,2,1,12,1,12,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,12,1,6,2,20,1,2,1,12,1, + 12,1,6,2,2,1,10,1,12,1,6,2,24,1,12,1, + 2,1,12,1,14,1,6,2,8,1,24,1,2,1,12,1, + 14,1,6,2,24,1,12,1,2,1,12,1,14,1,6,1, + 114,149,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,117,0,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,110,0,0, + 0,114,150,0,0,0,114,80,0,0,0,114,18,0,0,0, + 114,17,0,0,0,114,149,0,0,0,169,2,114,96,0,0, + 0,114,97,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,46,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,153,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,117,0,114,14,100, + 2,110,4,124,0,106,0,125,1,124,0,106,1,100,1,117, + 0,114,66,124,0,106,2,100,1,117,0,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,101,0,0,0,114, + 102,0,0,0,114,103,0,0,0,114,104,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,114,0,0,0,114,110, + 0,0,0,114,46,0,0,0,114,124,0,0,0,41,2,114, + 96,0,0,0,114,17,0,0,0,114,10,0,0,0,114,10, + 0,0,0,114,11,0,0,0,114,108,0,0,0,63,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,108,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,250,0,0,0,124,0,106,0,125,2,116, + 1,124,2,131,1,143,216,1,0,116,2,106,3,160,4,124, + 2,161,1,124,1,117,1,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, + 132,124,0,106,7,100,3,117,0,114,106,124,0,106,8,100, + 3,117,0,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,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,110,28,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,48, + 0,87,0,100,3,4,0,4,0,131,3,1,0,110,16,49, + 0,115,236,48,0,1,0,1,0,1,0,89,0,1,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,144,0,0,0,114,151,0,0,0,41,14, + 114,17,0,0,0,114,51,0,0,0,114,15,0,0,0,114, + 93,0,0,0,114,35,0,0,0,114,46,0,0,0,114,80, + 0,0,0,114,110,0,0,0,114,117,0,0,0,114,149,0, + 0,0,114,4,0,0,0,218,11,108,111,97,100,95,109,111, + 100,117,108,101,114,151,0,0,0,218,3,112,111,112,41,4, + 114,96,0,0,0,114,97,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,94,0,0,0,80,2,0,0,115,38,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,14,4,14, + 1,14,255,14,1,44,1,114,94,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,20,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,118,0,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, + 48,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,117,0,114,146,122,12,124,0, + 106,0,124,1,95,7,87,0,110,18,4,0,116,8,121,144, + 1,0,1,0,1,0,89,0,110,2,48,0,116,6,124,1, + 100,2,100,0,131,3,100,0,117,0,114,222,122,40,124,1, + 106,9,124,1,95,10,116,11,124,1,100,3,131,2,115,200, + 124,0,106,2,160,12,100,4,161,1,100,5,25,0,124,1, + 95,10,87,0,110,18,4,0,116,8,121,220,1,0,1,0, + 1,0,89,0,110,2,48,0,116,6,124,1,100,6,100,0, + 131,3,100,0,117,0,144,1,114,16,122,10,124,0,124,1, + 95,13,87,0,110,20,4,0,116,8,144,1,121,14,1,0, 1,0,1,0,89,0,110,2,48,0,124,1,83,0,41,7, - 78,114,1,0,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,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,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, + 78,114,99,0,0,0,114,146,0,0,0,114,142,0,0,0, + 114,129,0,0,0,114,22,0,0,0,114,106,0,0,0,41, + 14,114,110,0,0,0,114,156,0,0,0,114,17,0,0,0, + 114,15,0,0,0,114,93,0,0,0,114,157,0,0,0,114, + 6,0,0,0,114,99,0,0,0,114,107,0,0,0,114,1, + 0,0,0,114,146,0,0,0,114,4,0,0,0,114,130,0, + 0,0,114,106,0,0,0,114,152,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,110,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,12,1,6,1,16,1,2, + 4,8,1,10,1,22,1,12,1,6,1,18,1,2,1,10, + 1,14,1,6,1,114,159,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,224,0,0,0,124,0,106,0,100,0,117,1, + 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,166,124,1,116,5,106,6,124,0,106,7, + 60,0,122,52,124,0,106,0,100,0,117,0,114,96,124,0, + 106,8,100,0,117,0,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,48,1,0,1,0,1,0,122,14, + 116,5,106,6,124,0,106,7,61,0,87,0,110,18,4,0, + 116,11,121,150,1,0,1,0,1,0,89,0,110,2,48,0, + 130,0,89,0,110,2,48,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,100,6,124,0,95,4,110,8,100,6,124,0, + 95,4,48,0,124,1,83,0,41,7,78,114,151,0,0,0, + 84,114,155,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,110,0,0,0,114,4,0,0,0,114,159,0,0, + 0,114,153,0,0,0,90,13,95,105,110,105,116,105,97,108, + 105,122,105,110,103,114,15,0,0,0,114,93,0,0,0,114, + 17,0,0,0,114,117,0,0,0,114,80,0,0,0,114,151, + 0,0,0,114,64,0,0,0,114,157,0,0,0,114,77,0, + 0,0,114,152,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,147,2,0,0,115,48,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,12, + 1,6,1,8,5,14,1,12,1,18,2,8,0,8,2,114, + 160,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,54,0, + 0,0,116,0,124,0,106,1,131,1,143,24,1,0,116,2, + 124,0,131,1,87,0,2,0,100,1,4,0,4,0,131,3, + 1,0,83,0,49,0,115,40,48,0,1,0,1,0,1,0, + 89,0,1,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,51, + 0,0,0,114,17,0,0,0,114,160,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,95,0,0,0,189,2,0,0,115,4,0,0, + 0,0,9,12,1,114,95,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,140,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,20,100,6,100,7,132,1,131,1, + 90,8,101,7,100,21,100,8,100,9,132,1,131,1,90,9, + 101,7,100,10,100,11,132,0,131,1,90,10,101,7,100,12, + 100,13,132,0,131,1,90,11,101,7,101,12,100,14,100,15, + 132,0,131,1,131,1,90,13,101,7,101,12,100,16,100,17, + 132,0,131,1,131,1,90,14,101,7,101,12,100,18,100,19, + 132,0,131,1,131,1,90,15,101,7,101,16,131,1,90,17, + 100,5,83,0,41,22,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,122,8,98,117,105,108,116, + 45,105,110,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,22,0,0, + 0,100,1,124,0,106,0,155,2,100,2,116,1,106,2,155, + 0,100,3,157,5,83,0,41,4,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,8, + 60,109,111,100,117,108,101,32,122,2,32,40,122,2,41,62, + 41,3,114,1,0,0,0,114,161,0,0,0,114,139,0,0, + 0,41,1,114,97,0,0,0,114,10,0,0,0,114,10,0, + 0,0,114,11,0,0,0,114,100,0,0,0,215,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,46, + 0,0,0,124,2,100,0,117,1,114,12,100,0,83,0,116, + 0,160,1,124,1,161,1,114,38,116,2,124,1,124,0,124, + 0,106,3,100,1,141,3,83,0,100,0,83,0,100,0,83, + 0,169,2,78,114,138,0,0,0,41,4,114,58,0,0,0, + 90,10,105,115,95,98,117,105,108,116,105,110,114,92,0,0, + 0,114,139,0,0,0,169,4,218,3,99,108,115,114,82,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, - 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,12,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,12,1,6,2,20,1,2,1,12,1,12,1,6,2, - 2,1,10,1,12,1,6,2,24,1,12,1,2,1,12,1, - 14,1,6,2,8,1,24,1,2,1,12,1,14,1,6,2, - 24,1,12,1,2,1,12,1,14,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,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,117,0,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,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,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,117,0,114,14,100,2,110,4,124, - 0,106,0,125,1,124,0,106,1,100,1,117,0,114,66,124, - 0,106,2,100,1,117,0,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,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,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,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,250,0,0,0,124,0,106,0,125,2,116,1,124,2,131, - 1,143,216,1,0,116,2,106,3,160,4,124,2,161,1,124, - 1,117,1,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,132,124,0,106, - 7,100,3,117,0,114,106,124,0,106,8,100,3,117,0,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,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,110, - 28,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,48,0,87,0,100, - 3,4,0,4,0,131,3,1,0,110,16,49,0,115,236,48, - 0,1,0,1,0,1,0,89,0,1,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,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,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,149,0,0,0,218,3,112,111,112,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,38,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,14,4,14,1,14,255,14, - 1,44,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,20,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,118,0,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,48,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,117,0,114,146,122,12,124,0,106,0,124,1, - 95,7,87,0,110,18,4,0,116,8,121,144,1,0,1,0, - 1,0,89,0,110,2,48,0,116,6,124,1,100,2,100,0, - 131,3,100,0,117,0,114,222,122,40,124,1,106,9,124,1, - 95,10,116,11,124,1,100,3,131,2,115,200,124,0,106,2, - 160,12,100,4,161,1,100,5,25,0,124,1,95,10,87,0, - 110,18,4,0,116,8,121,220,1,0,1,0,1,0,89,0, - 110,2,48,0,116,6,124,1,100,6,100,0,131,3,100,0, - 117,0,144,1,114,16,122,10,124,0,124,1,95,13,87,0, - 110,20,4,0,116,8,144,1,121,14,1,0,1,0,1,0, - 89,0,110,2,48,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,154,0,0,0,114,17,0,0,0,114,15,0,0, - 0,114,91,0,0,0,114,155,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,12,1,6,1,16,1,2,4,8,1,10, - 1,22,1,12,1,6,1,18,1,2,1,10,1,14,1,6, - 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, - 224,0,0,0,124,0,106,0,100,0,117,1,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,166,124,1,116,5,106,6,124,0,106,7,60,0,122,52, - 124,0,106,0,100,0,117,0,114,96,124,0,106,8,100,0, - 117,0,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,48,1,0,1,0,1,0,122,14,116,5,106,6, - 124,0,106,7,61,0,87,0,110,18,4,0,116,11,121,150, - 1,0,1,0,1,0,89,0,110,2,48,0,130,0,89,0, - 110,2,48,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, - 100,6,124,0,95,4,110,8,100,6,124,0,95,4,48,0, - 124,1,83,0,41,7,78,114,149,0,0,0,84,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,70,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,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,155,0,0,0,114,75,0,0,0,114,150, + 9,102,105,110,100,95,115,112,101,99,224,2,0,0,115,10, + 0,0,0,0,2,8,1,4,1,10,1,16,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,117,1,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,168,0,0,0,114, + 110,0,0,0,41,4,114,165,0,0,0,114,82,0,0,0, + 114,166,0,0,0,114,96,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,233,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,118,1,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,78,0,0,0,114,16,0, + 0,0,41,8,114,17,0,0,0,114,15,0,0,0,114,79, + 0,0,0,114,80,0,0,0,114,46,0,0,0,114,68,0, + 0,0,114,58,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,96, 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,48,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,12,1,6,1,8, - 5,14,1,12,1,18,2,8,0,8,2,114,158,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,54,0,0,0,116,0, - 124,0,106,1,131,1,143,24,1,0,116,2,124,0,131,1, - 87,0,2,0,100,1,4,0,4,0,131,3,1,0,83,0, - 49,0,115,40,48,0,1,0,1,0,1,0,89,0,1,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,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,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, - 140,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,20,100,6,100,7,132,1,131,1,90,8,101,7, - 100,21,100,8,100,9,132,1,131,1,90,9,101,7,100,10, - 100,11,132,0,131,1,90,10,101,7,100,12,100,13,132,0, - 131,1,90,11,101,7,101,12,100,14,100,15,132,0,131,1, - 131,1,90,13,101,7,101,12,100,16,100,17,132,0,131,1, - 131,1,90,14,101,7,101,12,100,18,100,19,132,0,131,1, - 131,1,90,15,101,7,101,16,131,1,90,17,100,5,83,0, - 41,22,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, + 0,0,114,150,0,0,0,245,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,68,0,0,0,114,58,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,97,0,0,0,114,10,0,0,0,114,10,0, + 0,0,114,11,0,0,0,114,151,0,0,0,253,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,165,0,0,0, + 114,82,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,2,3, + 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,170,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,8,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,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,170, + 0,0,0,114,10,0,0,0,114,10,0,0,0,114,11,0, + 0,0,114,116,0,0,0,14,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,18,114,1,0,0,0,114,0,0,0, + 0,114,2,0,0,0,114,3,0,0,0,114,139,0,0,0, + 218,12,115,116,97,116,105,99,109,101,116,104,111,100,114,100, + 0,0,0,218,11,99,108,97,115,115,109,101,116,104,111,100, + 114,168,0,0,0,114,169,0,0,0,114,150,0,0,0,114, + 151,0,0,0,114,87,0,0,0,114,171,0,0,0,114,172, + 0,0,0,114,116,0,0,0,114,98,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,161,0,0,0,204,2,0,0,115, + 44,0,0,0,8,2,4,7,4,2,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,161,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,122,8,98,117,105,108,116,45,105,110,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,22,0,0,0,100,1,124, - 0,106,0,155,2,100,2,116,1,106,2,155,0,100,3,157, - 5,83,0,41,4,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,8,60,109,111,100, - 117,108,101,32,122,2,32,40,122,2,41,62,41,3,114,1, - 0,0,0,114,159,0,0,0,114,137,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,206,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,46,0,0,0,124, - 2,100,0,117,1,114,12,100,0,83,0,116,0,160,1,124, - 1,161,1,114,38,116,2,124,1,124,0,124,0,106,3,100, - 1,141,3,83,0,100,0,83,0,100,0,83,0,169,2,78, - 114,136,0,0,0,41,4,114,56,0,0,0,90,10,105,115, - 95,98,117,105,108,116,105,110,114,90,0,0,0,114,137,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,215,2,0,0,115,10,0,0,0,0, - 2,8,1,4,1,10,1,16,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,117,1,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,108,0,0,0, - 41,4,114,163,0,0,0,114,80,0,0,0,114,164,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,224,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,118,1,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,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,94,0,0,0,114, - 10,0,0,0,114,10,0,0,0,114,11,0,0,0,114,148, - 0,0,0,236,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, + 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,162,0, + 0,0,114,154,0,0,0,41,4,114,46,0,0,0,114,1, + 0,0,0,114,175,0,0,0,114,139,0,0,0,41,1,218, + 1,109,114,10,0,0,0,114,10,0,0,0,114,11,0,0, + 0,114,100,0,0,0,34,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,114,163, + 0,0,0,41,4,114,58,0,0,0,114,89,0,0,0,114, + 92,0,0,0,114,139,0,0,0,114,164,0,0,0,114,10, + 0,0,0,114,10,0,0,0,114,11,0,0,0,114,168,0, + 0,0,43,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, + 58,0,0,0,114,89,0,0,0,41,3,114,165,0,0,0, + 114,82,0,0,0,114,166,0,0,0,114,10,0,0,0,114, + 10,0,0,0,114,11,0,0,0,114,169,0,0,0,50,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,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,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,149,0,0,0,244,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,80,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,165,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,59,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,88,0,0,0,41,10,114,106,0,0,0,114,17, + 0,0,0,114,58,0,0,0,114,89,0,0,0,114,80,0, + 0,0,114,46,0,0,0,114,68,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,97,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,151,0,0,0, + 63,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,98,0,0,0,114,170,0,0,0,114,10,0,0,0,114, + 10,0,0,0,114,11,0,0,0,114,156,0,0,0,72,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,58,0,0,0,114,177,0,0,0,114,170,0,0,0,114, + 10,0,0,0,114,10,0,0,0,114,11,0,0,0,114,171, + 0,0,0,81,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,170,0,0,0,114,10, + 0,0,0,114,10,0,0,0,114,11,0,0,0,114,172,0, + 0,0,87,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,58,0,0,0,90,17,105,115,95,102,114, + 111,122,101,110,95,112,97,99,107,97,103,101,114,170,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,249,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,255,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,114, - 0,0,0,5,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,18,114,1,0,0,0,114,0,0,0,0,114,2,0, - 0,0,114,3,0,0,0,114,137,0,0,0,218,12,115,116, - 97,116,105,99,109,101,116,104,111,100,114,98,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,148,0,0,0,114,149,0,0,0, - 114,85,0,0,0,114,169,0,0,0,114,170,0,0,0,114, - 114,0,0,0,114,96,0,0,0,114,154,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,44,0,0,0, - 8,2,4,7,4,2,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,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,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,160,0,0,0,114,152, - 0,0,0,41,4,114,44,0,0,0,114,1,0,0,0,114, - 173,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,98,0, - 0,0,25,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,114,161,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,162,0,0,0,114,10,0,0,0,114, - 10,0,0,0,114,11,0,0,0,114,166,0,0,0,34,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,56,0,0,0, - 114,87,0,0,0,41,3,114,163,0,0,0,114,80,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,41,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,94, + 114,116,0,0,0,93,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,139,0,0,0,114,173,0, + 0,0,114,100,0,0,0,114,174,0,0,0,114,168,0,0, + 0,114,169,0,0,0,114,150,0,0,0,114,151,0,0,0, + 114,156,0,0,0,114,91,0,0,0,114,171,0,0,0,114, + 172,0,0,0,114,116,0,0,0,114,10,0,0,0,114,10, + 0,0,0,114,10,0,0,0,114,11,0,0,0,114,175,0, + 0,0,23,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,175,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,58,0,0,0,114,59,0,0,0,114,48,0,0,0, + 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,114, + 55,0,0,0,106,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,58,0,0,0,114, + 61,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,57, + 0,0,0,110,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,55,0,0,0,114,57,0,0,0,114,10,0,0, + 0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, + 114,180,0,0,0,102,3,0,0,115,6,0,0,0,8,2, + 4,2,8,4,114,180,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,129,0, + 0,0,114,39,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,80,0,0,0,114,46,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,115,3,0,0,115,10,0,0,0,0,2,16,1,12,1, + 8,1,8,1,114,189,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,117,0,114,24,100,0,83,0,116, + 1,124,1,124,3,131,2,83,0,114,13,0,0,0,41,2, + 114,169,0,0,0,114,92,0,0,0,41,4,218,6,102,105, + 110,100,101,114,114,17,0,0,0,114,166,0,0,0,114,110, 0,0,0,114,10,0,0,0,114,10,0,0,0,114,11,0, - 0,0,114,148,0,0,0,50,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,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,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,149,0,0,0,54,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,96,0,0, - 0,114,168,0,0,0,114,10,0,0,0,114,10,0,0,0, - 114,11,0,0,0,114,154,0,0,0,63,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,56,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,72, - 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,78,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,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,114,0,0, - 0,84,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,137,0,0,0,114,171,0,0,0,114,98, - 0,0,0,114,172,0,0,0,114,166,0,0,0,114,167,0, - 0,0,114,148,0,0,0,114,149,0,0,0,114,154,0,0, - 0,114,89,0,0,0,114,169,0,0,0,114,170,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,14,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,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, - 97,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,56,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,0,0,114,55,0,0,0,101, - 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,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,93,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,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,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,106,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,117,0,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,90,0,0,0,41,4,218,6,102,105,110,100,101,114, - 114,17,0,0,0,114,164,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,115,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,32,1,0,0,116,0,106,1,125,3,124,3,100,1,117, - 0,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,118,0,125,4,124,3,68,0,93,230,125,5,116,7,131, - 0,143,94,1,0,122,10,124,5,106,8,125,6,87,0,110, - 54,4,0,116,9,121,128,1,0,1,0,1,0,116,10,124, - 5,124,0,124,1,131,3,125,7,124,7,100,1,117,0,114, - 124,89,0,87,0,100,1,4,0,4,0,131,3,1,0,113, - 52,89,0,110,14,48,0,124,6,124,0,124,1,124,2,131, - 3,125,7,87,0,100,1,4,0,4,0,131,3,1,0,110, - 16,49,0,115,162,48,0,1,0,1,0,1,0,89,0,1, - 0,124,7,100,1,117,1,114,52,124,4,144,1,115,18,124, - 0,116,0,106,6,118,0,144,1,114,18,116,0,106,6,124, - 0,25,0,125,8,122,10,124,8,106,11,125,9,87,0,110, - 26,4,0,116,9,121,244,1,0,1,0,1,0,124,7,6, - 0,89,0,2,0,1,0,83,0,48,0,124,9,100,1,117, - 0,144,1,114,8,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,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,91,0,0,0,114,178,0,0,0,114, - 166,0,0,0,114,105,0,0,0,114,189,0,0,0,114,104, - 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,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,124,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,12,1,12,1,8,1,22,2,42, - 1,8,2,18,1,10,1,2,1,10,1,12,4,14,2,10, - 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,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,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,171,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,9,0, - 0,0,8,0,0,0,67,0,0,0,115,22,1,0,0,100, - 0,125,2,124,0,160,0,100,1,161,1,100,2,25,0,125, - 3,124,3,114,132,124,3,116,1,106,2,118,1,114,42,116, - 3,124,1,124,3,131,2,1,0,124,0,116,1,106,2,118, - 0,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,48,4,0,116,5,121,130,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,48,0,116,9,124,0,124,2,131,2,125,6,124,6,100, - 0,117,0,114,170,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,144,1,114,18,116,1,106,2,124,3,25,0,125, - 4,124,0,160,0,100,1,161,1,100,5,25,0,125,8,122, - 16,116,11,124,4,124,8,124,7,131,3,1,0,87,0,110, - 48,4,0,116,5,144,1,121,16,1,0,1,0,1,0,100, - 6,124,3,155,2,100,7,124,8,155,2,157,4,125,5,116, - 12,160,13,124,5,116,14,161,2,1,0,89,0,110,2,48, - 0,124,7,83,0,41,8,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,122,27,67,97,110,110,111,116,32,115,101, - 116,32,97,110,32,97,116,116,114,105,98,117,116,101,32,111, - 110,32,122,18,32,102,111,114,32,99,104,105,108,100,32,109, - 111,100,117,108,101,32,41,15,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, - 158,0,0,0,114,5,0,0,0,114,191,0,0,0,114,192, - 0,0,0,114,193,0,0,0,41,9,114,17,0,0,0,218, - 7,105,109,112,111,114,116,95,114,164,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, - 90,5,99,104,105,108,100,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,190, - 3,0,0,115,52,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,12,1, - 16,1,20,1,10,1,8,1,20,2,8,1,6,2,10,1, - 14,1,2,1,16,1,14,1,16,1,18,1,114,205,0,0, - 0,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,128,0,0,0,116, - 0,124,0,131,1,143,62,1,0,116,1,106,2,160,3,124, - 0,116,4,161,2,125,2,124,2,116,4,117,0,114,56,116, - 5,124,0,124,1,131,2,87,0,2,0,100,1,4,0,4, - 0,131,3,1,0,83,0,87,0,100,1,4,0,4,0,131, - 3,1,0,110,16,49,0,115,76,48,0,1,0,1,0,1, - 0,89,0,1,0,124,2,100,1,117,0,114,116,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,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,44,0,0,0,114,203,0,0, - 0,114,64,0,0,0,41,4,114,17,0,0,0,114,204,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,225,3,0,0,115, - 22,0,0,0,0,2,10,1,14,1,8,1,54,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,241,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,232,0, - 0,0,124,1,68,0,93,222,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,226, - 116,5,124,0,100,6,131,2,114,226,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,121,224,1,0,125,7, - 1,0,122,54,124,7,106,11,124,6,107,2,114,202,116,12, - 106,13,160,14,124,6,116,15,161,2,100,10,117,1,114,202, - 87,0,89,0,100,10,125,7,126,7,113,4,130,0,87,0, - 89,0,100,10,125,7,126,7,113,4,100,10,125,7,126,7, - 48,0,48,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,44,0,0,0,114,66,0,0,0,114,203,0,0, - 0,114,17,0,0,0,114,15,0,0,0,114,91,0,0,0, - 114,34,0,0,0,114,206,0,0,0,41,8,114,95,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,0,4,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,14,4,10,1, - 16,255,2,2,12,1,26,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,117,1,114,82,124,2,100,3,117,1,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,117,1,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,118,1,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,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,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,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,191,0,0, - 0,114,192,0,0,0,114,193,0,0,0,114,128,0,0,0, - 41,3,218,7,103,108,111,98,97,108,115,114,185,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,37,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,117,1,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,127,0,0,0,114,140,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,91,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,95,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, + 0,0,218,17,95,102,105,110,100,95,115,112,101,99,95,108, + 101,103,97,99,121,124,3,0,0,115,8,0,0,0,0,3, + 12,1,8,1,4,1,114,191,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,32,1,0,0,116,0,106,1,125,3,124, + 3,100,1,117,0,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,118,0,125,4,124,3,68,0,93,230,125, + 5,116,7,131,0,143,94,1,0,122,10,124,5,106,8,125, + 6,87,0,110,54,4,0,116,9,121,128,1,0,1,0,1, + 0,116,10,124,5,124,0,124,1,131,3,125,7,124,7,100, + 1,117,0,114,124,89,0,87,0,100,1,4,0,4,0,131, + 3,1,0,113,52,89,0,110,14,48,0,124,6,124,0,124, + 1,124,2,131,3,125,7,87,0,100,1,4,0,4,0,131, + 3,1,0,110,16,49,0,115,162,48,0,1,0,1,0,1, + 0,89,0,1,0,124,7,100,1,117,1,114,52,124,4,144, + 1,115,18,124,0,116,0,106,6,118,0,144,1,114,18,116, + 0,106,6,124,0,25,0,125,8,122,10,124,8,106,11,125, + 9,87,0,110,26,4,0,116,9,121,244,1,0,1,0,1, + 0,124,7,6,0,89,0,2,0,1,0,83,0,48,0,124, + 9,100,1,117,0,144,1,114,8,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,80,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,93,0,0,0,114,180, + 0,0,0,114,168,0,0,0,114,107,0,0,0,114,191,0, + 0,0,114,106,0,0,0,41,10,114,17,0,0,0,114,166, + 0,0,0,114,167,0,0,0,114,192,0,0,0,90,9,105, + 115,95,114,101,108,111,97,100,114,190,0,0,0,114,168,0, + 0,0,114,96,0,0,0,114,97,0,0,0,114,106,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,133,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,12,1,12,1,8, + 1,22,2,42,1,8,2,18,1,10,1,2,1,10,1,12, + 4,14,2,10,1,8,2,10,2,10,2,114,196,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, + 46,0,0,0,114,14,0,0,0,218,10,86,97,108,117,101, + 69,114,114,111,114,114,80,0,0,0,169,3,114,17,0,0, + 0,114,187,0,0,0,114,188,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,180,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,202,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,9,0,0,0,8,0,0,0,67,0,0,0,115,22, + 1,0,0,100,0,125,2,124,0,160,0,100,1,161,1,100, + 2,25,0,125,3,124,3,114,132,124,3,116,1,106,2,118, + 1,114,42,116,3,124,1,124,3,131,2,1,0,124,0,116, + 1,106,2,118,0,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,48,4,0,116,5,121,130,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,48,0,116,9,124,0,124,2,131,2,125, + 6,124,6,100,0,117,0,114,170,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,144,1,114,18,116,1,106,2,124, + 3,25,0,125,4,124,0,160,0,100,1,161,1,100,5,25, + 0,125,8,122,16,116,11,124,4,124,8,124,7,131,3,1, + 0,87,0,110,48,4,0,116,5,144,1,121,16,1,0,1, + 0,1,0,100,6,124,3,155,2,100,7,124,8,155,2,157, + 4,125,5,116,12,160,13,124,5,116,14,161,2,1,0,89, + 0,110,2,48,0,124,7,83,0,41,8,78,114,129,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,122,27,67,97,110,110,111, + 116,32,115,101,116,32,97,110,32,97,116,116,114,105,98,117, + 116,101,32,111,110,32,122,18,32,102,111,114,32,99,104,105, + 108,100,32,109,111,100,117,108,101,32,41,15,114,130,0,0, + 0,114,15,0,0,0,114,93,0,0,0,114,68,0,0,0, + 114,142,0,0,0,114,107,0,0,0,218,8,95,69,82,82, + 95,77,83,71,114,46,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,196, + 0,0,0,114,160,0,0,0,114,5,0,0,0,114,193,0, + 0,0,114,194,0,0,0,114,195,0,0,0,41,9,114,17, + 0,0,0,218,7,105,109,112,111,114,116,95,114,166,0,0, + 0,114,131,0,0,0,90,13,112,97,114,101,110,116,95,109, + 111,100,117,108,101,114,158,0,0,0,114,96,0,0,0,114, + 97,0,0,0,90,5,99,104,105,108,100,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,199,3,0,0,115,52,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,12,1,16,1,20,1,10,1,8,1,20,2,8,1, + 6,2,10,1,14,1,2,1,16,1,14,1,16,1,18,1, + 114,207,0,0,0,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,128, + 0,0,0,116,0,124,0,131,1,143,62,1,0,116,1,106, + 2,160,3,124,0,116,4,161,2,125,2,124,2,116,4,117, + 0,114,56,116,5,124,0,124,1,131,2,87,0,2,0,100, + 1,4,0,4,0,131,3,1,0,83,0,87,0,100,1,4, + 0,4,0,131,3,1,0,110,16,49,0,115,76,48,0,1, + 0,1,0,1,0,89,0,1,0,124,2,100,1,117,0,114, + 116,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,51,0,0,0,114,15,0,0,0,114,93,0,0, + 0,114,35,0,0,0,218,14,95,78,69,69,68,83,95,76, + 79,65,68,73,78,71,114,207,0,0,0,114,46,0,0,0, + 114,205,0,0,0,114,66,0,0,0,41,4,114,17,0,0, + 0,114,206,0,0,0,114,97,0,0,0,114,76,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,234, + 3,0,0,115,22,0,0,0,0,2,10,1,14,1,8,1, + 54,2,8,1,4,1,2,255,4,2,12,2,8,1,114,209, + 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,202,0,0,0,114,189,0,0,0,114,209,0,0,0,218, + 11,95,103,99,100,95,105,109,112,111,114,116,114,201,0,0, + 0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, + 114,210,0,0,0,250,3,0,0,115,8,0,0,0,0,9, + 12,1,8,1,12,1,114,210,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,232,0,0,0,124,1,68,0,93,222,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,226,116,5,124,0,100,6,131,2,114,226,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,121,224, + 1,0,125,7,1,0,122,54,124,7,106,11,124,6,107,2, + 114,202,116,12,106,13,160,14,124,6,116,15,161,2,100,10, + 117,1,114,202,87,0,89,0,100,10,125,7,126,7,113,4, + 130,0,87,0,89,0,100,10,125,7,126,7,113,4,100,10, + 125,7,126,7,48,0,48,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,211,0,0,0,114,184,0,0,0,78,41, + 16,114,197,0,0,0,114,198,0,0,0,114,1,0,0,0, + 114,199,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,214,0,0,0,114,46,0,0,0,114,68,0,0,0, + 114,205,0,0,0,114,17,0,0,0,114,15,0,0,0,114, + 93,0,0,0,114,35,0,0,0,114,208,0,0,0,41,8, + 114,97,0,0,0,218,8,102,114,111,109,108,105,115,116,114, + 206,0,0,0,114,212,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,215,0,0,0,9,4,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, + 14,4,10,1,16,255,2,2,12,1,26,1,114,215,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,117,1,114,82,124,2,100,3,117, + 1,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,117,1,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,118,1,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,146,0,0, + 0,114,106,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,142,0,0,0,114,129,0,0,0,114, + 22,0,0,0,41,6,114,35,0,0,0,114,131,0,0,0, + 114,193,0,0,0,114,194,0,0,0,114,195,0,0,0,114, + 130,0,0,0,41,3,218,7,103,108,111,98,97,108,115,114, + 187,0,0,0,114,96,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,46,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,221,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,117,1,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,129,0,0,0,114, + 142,0,0,0,41,9,114,210,0,0,0,114,221,0,0,0, + 218,9,112,97,114,116,105,116,105,111,110,114,186,0,0,0, + 114,15,0,0,0,114,93,0,0,0,114,1,0,0,0,114, + 4,0,0,0,114,215,0,0,0,41,9,114,17,0,0,0, + 114,220,0,0,0,218,6,108,111,99,97,108,115,114,216,0, + 0,0,114,188,0,0,0,114,97,0,0,0,90,8,103,108, + 111,98,97,108,115,95,114,187,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,73, + 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,224,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,117,0,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, + 161,0,0,0,114,168,0,0,0,114,80,0,0,0,114,160, + 0,0,0,41,2,114,17,0,0,0,114,96,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,110,4,0,0,115,8,0,0,0,0,1,10,1,8, + 1,12,1,114,225,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,118,0,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,118,1,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,193,0,0,0,114,65,0,0,0,78,41,15,114,58, + 0,0,0,114,15,0,0,0,114,14,0,0,0,114,93,0, + 0,0,218,5,105,116,101,109,115,114,197,0,0,0,114,79, + 0,0,0,114,161,0,0,0,114,89,0,0,0,114,175,0, + 0,0,114,143,0,0,0,114,149,0,0,0,114,1,0,0, + 0,114,225,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,97,0,0,0,114,110,0, + 0,0,114,96,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,117,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,229,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,229,0,0,0,114,15,0,0,0, + 114,192,0,0,0,114,120,0,0,0,114,161,0,0,0,114, + 175,0,0,0,41,2,114,227,0,0,0,114,228,0,0,0, 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,64,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,117,0,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,159,0,0,0, - 114,166,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,101,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,118,0,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,118,1, - 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,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,195,0,0,0,114,77,0,0,0,114, - 159,0,0,0,114,87,0,0,0,114,173,0,0,0,114,141, - 0,0,0,114,147,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,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,114,10,0,0,0,114,11,0,0,0,218,6,95, - 115,101,116,117,112,108,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, + 8,95,105,110,115,116,97,108,108,152,4,0,0,115,6,0, + 0,0,0,2,10,2,12,1,114,230,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,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,118,0,0,0,114,159,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,143,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,125,0,0,0,114,228,0, - 0,0,114,15,0,0,0,114,91,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,151,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,125,0,0, - 0,114,12,0,0,0,114,18,0,0,0,114,58,0,0,0, - 114,33,0,0,0,114,42,0,0,0,114,19,0,0,0,114, - 20,0,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,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, - 75,14,79,14,13,8,9,8,9,10,47,8,16,4,1,8, - 2,8,32,6,3,8,16,10,15,14,37,8,27,10,37,8, - 7,8,35,8,8, + 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,127,0,0, + 0,114,230,0,0,0,114,15,0,0,0,114,93,0,0,0, + 114,1,0,0,0,41,1,114,231,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,160,4,0,0,115,6,0,0, + 0,0,3,8,1,4,1,114,232,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,127,0,0,0,114,12,0,0,0,114,18,0,0,0,114, + 60,0,0,0,114,34,0,0,0,114,44,0,0,0,114,19, + 0,0,0,114,20,0,0,0,114,50,0,0,0,114,51,0, + 0,0,114,54,0,0,0,114,66,0,0,0,114,68,0,0, + 0,114,77,0,0,0,114,87,0,0,0,114,91,0,0,0, + 114,98,0,0,0,114,112,0,0,0,114,113,0,0,0,114, + 92,0,0,0,114,143,0,0,0,114,149,0,0,0,114,153, + 0,0,0,114,108,0,0,0,114,94,0,0,0,114,159,0, + 0,0,114,160,0,0,0,114,95,0,0,0,114,161,0,0, + 0,114,175,0,0,0,114,180,0,0,0,114,189,0,0,0, + 114,191,0,0,0,114,196,0,0,0,114,202,0,0,0,90, + 15,95,69,82,82,95,77,83,71,95,80,82,69,70,73,88, + 114,204,0,0,0,114,207,0,0,0,218,6,111,98,106,101, + 99,116,114,208,0,0,0,114,209,0,0,0,114,210,0,0, + 0,114,215,0,0,0,114,221,0,0,0,114,224,0,0,0, + 114,225,0,0,0,114,229,0,0,0,114,230,0,0,0,114, + 232,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,77,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,75,14,79,14,13,8,9,8,9,10,47,8, + 16,4,1,8,2,8,32,6,3,8,16,10,15,14,37,8, + 27,10,37,8,7,8,35,8,8, }; From webhook-mailer at python.org Mon Mar 2 21:50:45 2020 From: webhook-mailer at python.org (Pablo Galindo) Date: Tue, 03 Mar 2020 02:50:45 -0000 Subject: [Python-checkins] bpo-39778: Add clarification about tp_traverse and ownership (GH-18754) Message-ID: https://github.com/python/cpython/commit/6df421fe87a9418d6c59f89dbc5d5573b6826855 commit: 6df421fe87a9418d6c59f89dbc5d5573b6826855 branch: master author: Pablo Galindo committer: GitHub date: 2020-03-02T18:50:40-08:00 summary: bpo-39778: Add clarification about tp_traverse and ownership (GH-18754) Automerge-Triggered-By: @pablogsal files: M Doc/c-api/typeobj.rst diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst index ff0e70e6e52e2..ce4e8c926b294 100644 --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -1192,7 +1192,7 @@ and :c:type:`PyType_Type` effectively act as defaults.) The :c:member:`~PyTypeObject.tp_traverse` pointer is used by the garbage collector to detect reference cycles. A typical implementation of a :c:member:`~PyTypeObject.tp_traverse` function simply calls :c:func:`Py_VISIT` on each of the instance's members that are Python - objects. For example, this is function :c:func:`local_traverse` from the + objects that the instance owns. For example, this is function :c:func:`local_traverse` from the :mod:`_thread` extension module:: static int @@ -1212,6 +1212,18 @@ and :c:type:`PyType_Type` effectively act as defaults.) debugging aid you may want to visit it anyway just so the :mod:`gc` module's :func:`~gc.get_referents` function will include it. + .. warning:: + When implementing :c:member:`~PyTypeObject.tp_traverse`, only the members + that the instance *owns* (by having strong references to them) must be + visited. For instance, if an object supports weak references via the + :c:member:`~PyTypeObject.tp_weaklist` slot, the pointer supporting + the linked list (what *tp_weaklist* points to) must **not** be + visited as the instance does not directly own the weak references to itself + (the weakreference list is there to support the weak reference machinery, + but the instance has no strong reference to the elements inside it, as they + are allowed to be removed even if the instance is still alive). + + Note that :c:func:`Py_VISIT` requires the *visit* and *arg* parameters to :c:func:`local_traverse` to have these specific names; don't name them just anything. From webhook-mailer at python.org Mon Mar 2 22:04:05 2020 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 03 Mar 2020 03:04:05 -0000 Subject: [Python-checkins] bpo-39778: Add clarification about tp_traverse and ownership (GH-18754) Message-ID: https://github.com/python/cpython/commit/72fff60d7649df88026838d8b5f14f541393f268 commit: 72fff60d7649df88026838d8b5f14f541393f268 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2020-03-02T19:03:56-08:00 summary: bpo-39778: Add clarification about tp_traverse and ownership (GH-18754) Automerge-Triggered-By: @pablogsal (cherry picked from commit 6df421fe87a9418d6c59f89dbc5d5573b6826855) Co-authored-by: Pablo Galindo files: M Doc/c-api/typeobj.rst diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst index 71b45a6e7158f..057187e4ba846 100644 --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -496,7 +496,7 @@ type objects) *must* have the :attr:`ob_size` field. The :c:member:`~PyTypeObject.tp_traverse` pointer is used by the garbage collector to detect reference cycles. A typical implementation of a :c:member:`~PyTypeObject.tp_traverse` function simply calls :c:func:`Py_VISIT` on each of the instance's members that are Python - objects. For example, this is function :c:func:`local_traverse` from the + objects that the instance owns. For example, this is function :c:func:`local_traverse` from the :mod:`_thread` extension module:: static int @@ -516,6 +516,18 @@ type objects) *must* have the :attr:`ob_size` field. debugging aid you may want to visit it anyway just so the :mod:`gc` module's :func:`~gc.get_referents` function will include it. + .. warning:: + When implementing :c:member:`~PyTypeObject.tp_traverse`, only the members + that the instance *owns* (by having strong references to them) must be + visited. For instance, if an object supports weak references via the + :c:member:`~PyTypeObject.tp_weaklist` slot, the pointer supporting + the linked list (what *tp_weaklist* points to) must **not** be + visited as the instance does not directly own the weak references to itself + (the weakreference list is there to support the weak reference machinery, + but the instance has no strong reference to the elements inside it, as they + are allowed to be removed even if the instance is still alive). + + Note that :c:func:`Py_VISIT` requires the *visit* and *arg* parameters to :c:func:`local_traverse` to have these specific names; don't name them just anything. From webhook-mailer at python.org Mon Mar 2 22:04:17 2020 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 03 Mar 2020 03:04:17 -0000 Subject: [Python-checkins] bpo-39778: Add clarification about tp_traverse and ownership (GH-18754) Message-ID: https://github.com/python/cpython/commit/1827fc30f463786ebff13752e35c3224652bc94e commit: 1827fc30f463786ebff13752e35c3224652bc94e branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2020-03-02T19:04:13-08:00 summary: bpo-39778: Add clarification about tp_traverse and ownership (GH-18754) Automerge-Triggered-By: @pablogsal (cherry picked from commit 6df421fe87a9418d6c59f89dbc5d5573b6826855) Co-authored-by: Pablo Galindo files: M Doc/c-api/typeobj.rst diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst index bff5abfea48ee..163f599d1c264 100644 --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -1218,7 +1218,7 @@ and :c:type:`PyType_Type` effectively act as defaults.) The :c:member:`~PyTypeObject.tp_traverse` pointer is used by the garbage collector to detect reference cycles. A typical implementation of a :c:member:`~PyTypeObject.tp_traverse` function simply calls :c:func:`Py_VISIT` on each of the instance's members that are Python - objects. For example, this is function :c:func:`local_traverse` from the + objects that the instance owns. For example, this is function :c:func:`local_traverse` from the :mod:`_thread` extension module:: static int @@ -1238,6 +1238,18 @@ and :c:type:`PyType_Type` effectively act as defaults.) debugging aid you may want to visit it anyway just so the :mod:`gc` module's :func:`~gc.get_referents` function will include it. + .. warning:: + When implementing :c:member:`~PyTypeObject.tp_traverse`, only the members + that the instance *owns* (by having strong references to them) must be + visited. For instance, if an object supports weak references via the + :c:member:`~PyTypeObject.tp_weaklist` slot, the pointer supporting + the linked list (what *tp_weaklist* points to) must **not** be + visited as the instance does not directly own the weak references to itself + (the weakreference list is there to support the weak reference machinery, + but the instance has no strong reference to the elements inside it, as they + are allowed to be removed even if the instance is still alive). + + Note that :c:func:`Py_VISIT` requires the *visit* and *arg* parameters to :c:func:`local_traverse` to have these specific names; don't name them just anything. From webhook-mailer at python.org Tue Mar 3 03:19:17 2020 From: webhook-mailer at python.org (Stefan Krah) Date: Tue, 03 Mar 2020 08:19:17 -0000 Subject: [Python-checkins] bpo-39776: Lock ++interp->tstate_next_unique_id. (GH-18746) (#18746) (#18752) Message-ID: https://github.com/python/cpython/commit/5a92f42d8723ee865be80f028d402204649da15d commit: 5a92f42d8723ee865be80f028d402204649da15d branch: 3.8 author: Stefan Krah committer: GitHub date: 2020-03-03T09:18:55+01:00 summary: bpo-39776: Lock ++interp->tstate_next_unique_id. (GH-18746) (#18746) (#18752) - Threads created by PyGILState_Ensure() could have a duplicate tstate->id. (cherry picked from commit b3b9ade4a3d3fe00d933bcd8fc5c5c755d1024f9) files: A Misc/NEWS.d/next/Core and Builtins/2020-03-02-20-12-33.bpo-39776.fNaxi_.rst M Python/pystate.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-03-02-20-12-33.bpo-39776.fNaxi_.rst b/Misc/NEWS.d/next/Core and Builtins/2020-03-02-20-12-33.bpo-39776.fNaxi_.rst new file mode 100644 index 0000000000000..e5a00bd96ae47 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2020-03-02-20-12-33.bpo-39776.fNaxi_.rst @@ -0,0 +1,6 @@ +Fix race condition where threads created by PyGILState_Ensure() could get a +duplicate id. + +This affects consumers of tstate->id like the contextvar caching machinery, +which could return invalid cached objects under heavy thread load (observed +in embedded scenarios). diff --git a/Python/pystate.c b/Python/pystate.c index aba673c00a432..9f99060feceb2 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -606,13 +606,12 @@ new_threadstate(PyInterpreterState *interp, int init) tstate->context = NULL; tstate->context_ver = 1; - tstate->id = ++interp->tstate_next_unique_id; - if (init) { _PyThreadState_Init(runtime, tstate); } HEAD_LOCK(runtime); + tstate->id = ++interp->tstate_next_unique_id; tstate->prev = NULL; tstate->next = interp->tstate_head; if (tstate->next) From webhook-mailer at python.org Tue Mar 3 03:20:02 2020 From: webhook-mailer at python.org (Stefan Krah) Date: Tue, 03 Mar 2020 08:20:02 -0000 Subject: [Python-checkins] bpo-39776: Lock ++interp->tstate_next_unique_id (GH-18746) Message-ID: https://github.com/python/cpython/commit/852aee69f49c654a03ad1f64d90a78ba8848e2c6 commit: 852aee69f49c654a03ad1f64d90a78ba8848e2c6 branch: 3.7 author: Stefan Krah committer: GitHub date: 2020-03-03T09:19:58+01:00 summary: bpo-39776: Lock ++interp->tstate_next_unique_id (GH-18746) - Threads created by PyGILState_Ensure() could have a duplicate tstate->id. (cherry picked from commit b3b9ade4a3d3fe00d933bcd8fc5c5c755d1024f9) files: A Misc/NEWS.d/next/Core and Builtins/2020-03-02-20-12-33.bpo-39776.fNaxi_.rst M Python/pystate.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-03-02-20-12-33.bpo-39776.fNaxi_.rst b/Misc/NEWS.d/next/Core and Builtins/2020-03-02-20-12-33.bpo-39776.fNaxi_.rst new file mode 100644 index 0000000000000..e5a00bd96ae47 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2020-03-02-20-12-33.bpo-39776.fNaxi_.rst @@ -0,0 +1,6 @@ +Fix race condition where threads created by PyGILState_Ensure() could get a +duplicate id. + +This affects consumers of tstate->id like the contextvar caching machinery, +which could return invalid cached objects under heavy thread load (observed +in embedded scenarios). diff --git a/Python/pystate.c b/Python/pystate.c index 90cd56bb05f4e..ebfe6ce65de03 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -411,12 +411,12 @@ new_threadstate(PyInterpreterState *interp, int init) tstate->context = NULL; tstate->context_ver = 1; - tstate->id = ++interp->tstate_next_unique_id; if (init) _PyThreadState_Init(tstate); HEAD_LOCK(); + tstate->id = ++interp->tstate_next_unique_id; tstate->prev = NULL; tstate->next = interp->tstate_head; if (tstate->next) From webhook-mailer at python.org Tue Mar 3 05:11:22 2020 From: webhook-mailer at python.org (Michael Felt) Date: Tue, 03 Mar 2020 10:11:22 -0000 Subject: [Python-checkins] bpo-12915: Skip test_pkgutil.test_name_resolution() non-encodable filenames (GH-18720) Message-ID: https://github.com/python/cpython/commit/e0acec15412203359d59db33e447698ee51e07fc commit: e0acec15412203359d59db33e447698ee51e07fc branch: master author: Michael Felt committer: GitHub date: 2020-03-03T11:11:11+01:00 summary: bpo-12915: Skip test_pkgutil.test_name_resolution() non-encodable filenames (GH-18720) When filesystem encoding cannot encode the Unicode string used for a filename continue testing with the next example. files: M Lib/test/test_pkgutil.py diff --git a/Lib/test/test_pkgutil.py b/Lib/test/test_pkgutil.py index 53456c2f7659e..b162f9949ff69 100644 --- a/Lib/test/test_pkgutil.py +++ b/Lib/test/test_pkgutil.py @@ -246,7 +246,11 @@ def test_name_resolution(self): for uw in unicode_words: d = os.path.join(self.dirname, uw) - os.makedirs(d, exist_ok=True) + try: + os.makedirs(d, exist_ok=True) + except UnicodeEncodeError: + # When filesystem encoding cannot encode uw: skip this test + continue # make an empty __init__.py file f = os.path.join(d, '__init__.py') with open(f, 'w') as f: From webhook-mailer at python.org Tue Mar 3 11:23:05 2020 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 03 Mar 2020 16:23:05 -0000 Subject: [Python-checkins] Fix misleading statement about mixed-type numeric comparisons (GH-18615) (GH-18737) Message-ID: https://github.com/python/cpython/commit/f8f163c38f29e409b044e17afb01ca38485a7227 commit: f8f163c38f29e409b044e17afb01ca38485a7227 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2020-03-03T11:22:56-05:00 summary: Fix misleading statement about mixed-type numeric comparisons (GH-18615) (GH-18737) (cherry picked from commit 9f1cb1bb49476246de5d9ed5fe680301cf7f7571) Co-authored-by: Mark Dickinson files: A Misc/NEWS.d/next/Documentation/2020-02-23-13-26-40.bpo-39530._bCvzQ.rst M Doc/library/stdtypes.rst diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index 5e9b59eb84bbb..c4c4ccd76d5a7 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -263,8 +263,10 @@ and imaginary parts. Python fully supports mixed arithmetic: when a binary arithmetic operator has operands of different numeric types, the operand with the "narrower" type is widened to that of the other, where integer is narrower than floating point, -which is narrower than complex. Comparisons between numbers of mixed type use -the same rule. [2]_ The constructors :func:`int`, :func:`float`, and +which is narrower than complex. A comparison between numbers of different types +behaves as though the exact values of those numbers were being compared. [2]_ + +The constructors :func:`int`, :func:`float`, and :func:`complex` can be used to produce numbers of a specific type. All numeric types (except complex) support the following operations (for priorities of diff --git a/Misc/NEWS.d/next/Documentation/2020-02-23-13-26-40.bpo-39530._bCvzQ.rst b/Misc/NEWS.d/next/Documentation/2020-02-23-13-26-40.bpo-39530._bCvzQ.rst new file mode 100644 index 0000000000000..b7a02522bbb1c --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2020-02-23-13-26-40.bpo-39530._bCvzQ.rst @@ -0,0 +1 @@ +Fix misleading documentation about mixed-type numeric comparisons. From webhook-mailer at python.org Tue Mar 3 11:31:19 2020 From: webhook-mailer at python.org (Victor Stinner) Date: Tue, 03 Mar 2020 16:31:19 -0000 Subject: [Python-checkins] bpo-39674: Update collections ABC deprecation doc (GH-18747) Message-ID: https://github.com/python/cpython/commit/91fe4142642286b65c166f7b6e27de16f42b1286 commit: 91fe4142642286b65c166f7b6e27de16f42b1286 branch: master author: Victor Stinner committer: GitHub date: 2020-03-03T17:31:11+01:00 summary: bpo-39674: Update collections ABC deprecation doc (GH-18747) files: M Doc/library/collections.rst diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst index 65cdf34aa4e4f..8dcf9451d72bf 100644 --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -36,7 +36,7 @@ Python's general purpose built-in containers, :class:`dict`, :class:`list`, .. deprecated-removed:: 3.3 3.10 Moved :ref:`collections-abstract-base-classes` to the :mod:`collections.abc` module. For backwards compatibility, they continue to be visible in this module through - Python 3.8. + Python 3.9. :class:`ChainMap` objects From webhook-mailer at python.org Tue Mar 3 11:31:28 2020 From: webhook-mailer at python.org (Victor Stinner) Date: Tue, 03 Mar 2020 16:31:28 -0000 Subject: [Python-checkins] bpo-39674: Update collections ABC deprecation doc (GH-18748) Message-ID: https://github.com/python/cpython/commit/2aa694dd55202eb6d062fdf49c07cf95f8520f2d commit: 2aa694dd55202eb6d062fdf49c07cf95f8520f2d branch: 3.8 author: Victor Stinner committer: GitHub date: 2020-03-03T17:31:24+01:00 summary: bpo-39674: Update collections ABC deprecation doc (GH-18748) files: M Doc/library/collections.rst diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst index a5e8d04099b22..8dcf9451d72bf 100644 --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -33,10 +33,10 @@ Python's general purpose built-in containers, :class:`dict`, :class:`list`, :class:`UserString` wrapper around string objects for easier string subclassing ===================== ==================================================================== -.. deprecated-removed:: 3.3 3.9 +.. deprecated-removed:: 3.3 3.10 Moved :ref:`collections-abstract-base-classes` to the :mod:`collections.abc` module. For backwards compatibility, they continue to be visible in this module through - Python 3.8. + Python 3.9. :class:`ChainMap` objects From webhook-mailer at python.org Tue Mar 3 12:43:37 2020 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Tue, 03 Mar 2020 17:43:37 -0000 Subject: [Python-checkins] bpo-39831: Remove outdated comment. (GH-18764) Message-ID: https://github.com/python/cpython/commit/ae75a294352e9b9487f5dc8e88f068e7e6974dc2 commit: ae75a294352e9b9487f5dc8e88f068e7e6974dc2 branch: master author: Serhiy Storchaka committer: GitHub date: 2020-03-03T19:43:29+02:00 summary: bpo-39831: Remove outdated comment. (GH-18764) files: M Python/_warnings.c diff --git a/Python/_warnings.c b/Python/_warnings.c index 92378faa61f3e..39f8033cd906a 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -889,11 +889,9 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno, return 1; handle_error: - /* filename not XDECREF'ed here as there is no way to jump here with a - dangling reference. */ Py_XDECREF(*registry); Py_XDECREF(*module); - Py_XDECREF(*filename); + Py_DECREF(*filename); return 0; } From webhook-mailer at python.org Tue Mar 3 13:01:17 2020 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 03 Mar 2020 18:01:17 -0000 Subject: [Python-checkins] bpo-39831: Remove outdated comment. (GH-18764) Message-ID: https://github.com/python/cpython/commit/57fb29219f09ee705065e39ad488334a9c7e3d71 commit: 57fb29219f09ee705065e39ad488334a9c7e3d71 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2020-03-03T10:01:09-08:00 summary: bpo-39831: Remove outdated comment. (GH-18764) (cherry picked from commit ae75a294352e9b9487f5dc8e88f068e7e6974dc2) Co-authored-by: Serhiy Storchaka files: M Python/_warnings.c diff --git a/Python/_warnings.c b/Python/_warnings.c index 87269dd4dbc9e..52a13dfc62ccc 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -886,11 +886,9 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno, return 1; handle_error: - /* filename not XDECREF'ed here as there is no way to jump here with a - dangling reference. */ Py_XDECREF(*registry); Py_XDECREF(*module); - Py_XDECREF(*filename); + Py_DECREF(*filename); return 0; } From webhook-mailer at python.org Tue Mar 3 13:50:22 2020 From: webhook-mailer at python.org (MojoVampire) Date: Tue, 03 Mar 2020 18:50:22 -0000 Subject: [Python-checkins] bpo-35712: Make using NotImplemented in a boolean context issue a deprecation warning (GH-13195) Message-ID: https://github.com/python/cpython/commit/469325c30e147680543b2f5118b83fd95055a499 commit: 469325c30e147680543b2f5118b83fd95055a499 branch: master author: MojoVampire committer: GitHub date: 2020-03-03T20:50:17+02:00 summary: bpo-35712: Make using NotImplemented in a boolean context issue a deprecation warning (GH-13195) files: A Misc/NEWS.d/next/Core and Builtins/2019-05-08-11-11-45.bpo-35712.KJthus.rst M Doc/library/constants.rst M Doc/reference/datamodel.rst M Doc/whatsnew/3.9.rst M Lib/functools.py M Lib/ipaddress.py M Lib/test/test_buffer.py M Lib/test/test_builtin.py M Lib/test/test_descr.py M Objects/object.c diff --git a/Doc/library/constants.rst b/Doc/library/constants.rst index 501715980f957..f17e1a3787516 100644 --- a/Doc/library/constants.rst +++ b/Doc/library/constants.rst @@ -31,7 +31,7 @@ A small number of constants live in the built-in namespace. They are: etc.) to indicate that the operation is not implemented with respect to the other type; may be returned by the in-place binary special methods (e.g. :meth:`__imul__`, :meth:`__iand__`, etc.) for the same purpose. - Its truth value is true. + It should not be evaluated in a boolean context. .. note:: @@ -50,6 +50,11 @@ A small number of constants live in the built-in namespace. They are: even though they have similar names and purposes. See :exc:`NotImplementedError` for details on when to use it. + .. versionchanged:: 3.9 + Evaluating ``NotImplemented`` in a boolean context is deprecated. While + it currently evaluates as true, it will emit a :exc:`DeprecationWarning`. + It will raise a :exc:`TypeError` in a future version of Python. + .. index:: single: ...; ellipsis literal .. data:: Ellipsis diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 5b3b669c5eb91..8be432d465ba3 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -156,13 +156,18 @@ NotImplemented object is accessed through the built-in name ``NotImplemented``. Numeric methods and rich comparison methods should return this value if they do not implement the operation for the operands provided. (The interpreter will then try the - reflected operation, or some other fallback, depending on the operator.) Its - truth value is true. + reflected operation, or some other fallback, depending on the operator.) It + should not be evaluated in a boolean context. See :ref:`implementing-the-arithmetic-operations` for more details. + .. versionchanged:: 3.9 + Evaluating ``NotImplemented`` in a boolean context is deprecated. While + it currently evaluates as true, it will emit a :exc:`DeprecationWarning`. + It will raise a :exc:`TypeError` in a future version of Python. + Ellipsis .. index:: diff --git a/Doc/whatsnew/3.9.rst b/Doc/whatsnew/3.9.rst index f49575d89da67..9a8a484fc8f1b 100644 --- a/Doc/whatsnew/3.9.rst +++ b/Doc/whatsnew/3.9.rst @@ -452,6 +452,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. +* Using :data:`NotImplemented` in a boolean context has been deprecated, + as it is almost exclusively the result of incorrect rich comparator + implementations. It will be made a :exc:`TypeError` in a future version + of Python. + (Contributed by Josh Rosenberg in :issue:`35712`.) + * 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, diff --git a/Lib/functools.py b/Lib/functools.py index 535fa046c18a9..e230175e56ca0 100644 --- a/Lib/functools.py +++ b/Lib/functools.py @@ -96,6 +96,8 @@ def _gt_from_lt(self, other, NotImplemented=NotImplemented): def _le_from_lt(self, other, NotImplemented=NotImplemented): 'Return a <= b. Computed by @total_ordering from (a < b) or (a == b).' op_result = self.__lt__(other) + if op_result is NotImplemented: + return op_result return op_result or self == other def _ge_from_lt(self, other, NotImplemented=NotImplemented): @@ -136,6 +138,8 @@ def _lt_from_gt(self, other, NotImplemented=NotImplemented): def _ge_from_gt(self, other, NotImplemented=NotImplemented): 'Return a >= b. Computed by @total_ordering from (a > b) or (a == b).' op_result = self.__gt__(other) + if op_result is NotImplemented: + return op_result return op_result or self == other def _le_from_gt(self, other, NotImplemented=NotImplemented): diff --git a/Lib/ipaddress.py b/Lib/ipaddress.py index 9c47405ce8d8c..702433953a1e2 100644 --- a/Lib/ipaddress.py +++ b/Lib/ipaddress.py @@ -1398,7 +1398,7 @@ def __str__(self): def __eq__(self, other): address_equal = IPv4Address.__eq__(self, other) - if not address_equal or address_equal is NotImplemented: + if address_equal is NotImplemented or not address_equal: return address_equal try: return self.network == other.network @@ -2096,7 +2096,7 @@ def __str__(self): def __eq__(self, other): address_equal = IPv6Address.__eq__(self, other) - if not address_equal or address_equal is NotImplemented: + if address_equal is NotImplemented or not address_equal: return address_equal try: return self.network == other.network @@ -2109,7 +2109,7 @@ def __eq__(self, other): def __lt__(self, other): address_less = IPv6Address.__lt__(self, other) if address_less is NotImplemented: - return NotImplemented + return address_less try: return (self.network < other.network or self.network == other.network and address_less) diff --git a/Lib/test/test_buffer.py b/Lib/test/test_buffer.py index 6178ffde7a566..2ddca06b8b568 100644 --- a/Lib/test/test_buffer.py +++ b/Lib/test/test_buffer.py @@ -2528,7 +2528,7 @@ def f(): return 7 values = [INT(9), IDX(9), 2.2+3j, Decimal("-21.1"), 12.2, Fraction(5, 2), [1,2,3], {4,5,6}, {7:8}, (), (9,), - True, False, None, NotImplemented, + True, False, None, Ellipsis, b'a', b'abc', bytearray(b'a'), bytearray(b'abc'), 'a', 'abc', r'a', r'abc', f, lambda x: x] diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index 5c553a92b973c..e50c2735ec24d 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -1666,6 +1666,20 @@ def test_construct_singletons(self): self.assertRaises(TypeError, tp, 1, 2) self.assertRaises(TypeError, tp, a=1, b=2) + def test_warning_notimplemented(self): + # Issue #35712: NotImplemented is a sentinel value that should never + # be evaluated in a boolean context (virtually all such use cases + # are a result of accidental misuse implementing rich comparison + # operations in terms of one another). + # For the time being, it will continue to evaluate as truthy, but + # issue a deprecation warning (with the eventual intent to make it + # a TypeError). + self.assertWarns(DeprecationWarning, bool, NotImplemented) + with self.assertWarns(DeprecationWarning): + self.assertTrue(NotImplemented) + with self.assertWarns(DeprecationWarning): + self.assertFalse(not NotImplemented) + class TestBreakpoint(unittest.TestCase): def setUp(self): diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index d2e121820ea5f..96cc8de2d98fb 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -2526,9 +2526,9 @@ def getdict(self): except TypeError: pass - # Two essentially featureless objects, just inheriting stuff from - # object. - self.assertEqual(dir(NotImplemented), dir(Ellipsis)) + # Two essentially featureless objects, (Ellipsis just inherits stuff + # from object. + self.assertEqual(dir(object()), dir(Ellipsis)) # Nasty test case for proxied objects class Wrapper(object): diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-05-08-11-11-45.bpo-35712.KJthus.rst b/Misc/NEWS.d/next/Core and Builtins/2019-05-08-11-11-45.bpo-35712.KJthus.rst new file mode 100644 index 0000000000000..3a68632883fab --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-05-08-11-11-45.bpo-35712.KJthus.rst @@ -0,0 +1,2 @@ +Using :data:`NotImplemented` in a boolean context has been deprecated. Patch +contributed by Josh Rosenberg. diff --git a/Objects/object.c b/Objects/object.c index 81de3b8253040..9c74e07eddcb1 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -1673,6 +1673,22 @@ notimplemented_dealloc(PyObject* ignore) Py_FatalError("deallocating NotImplemented"); } +static int +notimplemented_bool(PyObject *v) +{ + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "NotImplemented should not be used in a boolean context", + 1) < 0) + { + return -1; + } + return 1; +} + +static PyNumberMethods notimplemented_as_number = { + .nb_bool = notimplemented_bool, +}; + PyTypeObject _PyNotImplemented_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "NotImplementedType", @@ -1683,8 +1699,8 @@ PyTypeObject _PyNotImplemented_Type = { 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_as_async*/ - NotImplemented_repr, /*tp_repr*/ - 0, /*tp_as_number*/ + NotImplemented_repr, /*tp_repr*/ + ¬implemented_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ From webhook-mailer at python.org Tue Mar 3 16:52:28 2020 From: webhook-mailer at python.org (Victor Stinner) Date: Tue, 03 Mar 2020 21:52:28 -0000 Subject: [Python-checkins] bpo-39674: Suggest to test with DeprecationWarning (GH-18552) Message-ID: https://github.com/python/cpython/commit/116fd4af7370706d0d99ac7c70541ef965672d4e commit: 116fd4af7370706d0d99ac7c70541ef965672d4e branch: master author: Victor Stinner committer: GitHub date: 2020-03-03T22:52:20+01:00 summary: bpo-39674: Suggest to test with DeprecationWarning (GH-18552) Add a section in What's New In Python 3.9 to strongly advice to check for DeprecationWarning in your Python projects. Co-authored-by: Hugo van Kemenade files: M Doc/whatsnew/3.9.rst diff --git a/Doc/whatsnew/3.9.rst b/Doc/whatsnew/3.9.rst index 9a8a484fc8f1b..6a4d07f62c69b 100644 --- a/Doc/whatsnew/3.9.rst +++ b/Doc/whatsnew/3.9.rst @@ -66,6 +66,34 @@ Summary -- Release highlights .. PEP-sized items next. +You should check for DeprecationWarning in your code +==================================================== + +When Python 2.7 was still supported, many functions were kept for backward +compatibility with Python 2.7. With the end of Python 2.7 support, these +backward compatibility layers have been removed, or will be removed soon. +Most of them emitted a :exc:`DeprecationWarning` warning for several years. For +example, using ``collections.Mapping`` instead of ``collections.abc.Mapping`` +emits a :exc:`DeprecationWarning` since Python 3.3, released in 2012. + +Test your application with the :option:`-W` ``default`` command-line option to see +:exc:`DeprecationWarning` and :exc:`PendingDeprecationWarning`, or even with +:option:`-W` ``error`` to treat them as errors. :ref:`Warnings Filter +` can be used to ignore warnings from third-party code. + +It has been decided to keep a few backward compatibility layers for one last +release, to give more time to Python projects maintainers to organize the +removal of the Python 2 support and add support for Python 3.9. + +Aliases to ref:`Abstract Base Classes ` in +the :mod:`collections` module, like ``collections.Mapping`` alias to +:class:`collections.abc.Mapping`, are kept for one last release for backward +compatibility. They will be removed from Python 3.10. + +More generally, try to run your tests in the :ref:`Python Development Mode +` which helps to prepare your code to make it compatible with the +next Python version. + New Features ============ From webhook-mailer at python.org Tue Mar 3 17:25:52 2020 From: webhook-mailer at python.org (Brandt Bucher) Date: Tue, 03 Mar 2020 22:25:52 -0000 Subject: [Python-checkins] bpo-39702: Relax grammar restrictions on decorators (PEP 614) (GH-18570) Message-ID: https://github.com/python/cpython/commit/be501ca2419a91546dea85ef4f36945545458589 commit: be501ca2419a91546dea85ef4f36945545458589 branch: master author: Brandt Bucher committer: GitHub date: 2020-03-03T14:25:44-08:00 summary: bpo-39702: Relax grammar restrictions on decorators (PEP 614) (GH-18570) files: A Misc/NEWS.d/next/Core and Builtins/2020-02-20-08-12-52.bpo-39702.4_AmyF.rst M Grammar/Grammar M Include/node.h M Lib/test/test_decorators.py M Lib/test/test_grammar.py M Lib/test/test_parser.py M Python/ast.c M Python/graminit.c diff --git a/Grammar/Grammar b/Grammar/Grammar index 21f7e1a89115b..170518af74e5a 100644 --- a/Grammar/Grammar +++ b/Grammar/Grammar @@ -14,7 +14,7 @@ single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE file_input: (NEWLINE | stmt)* ENDMARKER eval_input: testlist NEWLINE* ENDMARKER -decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE +decorator: '@' namedexpr_test NEWLINE decorators: decorator+ decorated: decorators (classdef | funcdef | async_funcdef) diff --git a/Include/node.h b/Include/node.h index 2b39074097387..ca24f28908592 100644 --- a/Include/node.h +++ b/Include/node.h @@ -31,7 +31,6 @@ PyAPI_FUNC(Py_ssize_t) _PyNode_SizeOf(node *n); #define NCH(n) ((n)->n_nchildren) #define CHILD(n, i) (&(n)->n_child[i]) -#define RCHILD(n, i) (CHILD(n, NCH(n) + i)) #define TYPE(n) ((n)->n_type) #define STR(n) ((n)->n_str) #define LINENO(n) ((n)->n_lineno) diff --git a/Lib/test/test_decorators.py b/Lib/test/test_decorators.py index 8953f64806122..298979e509f8d 100644 --- a/Lib/test/test_decorators.py +++ b/Lib/test/test_decorators.py @@ -151,21 +151,18 @@ def double(x): self.assertEqual(counts['double'], 4) def test_errors(self): - # Test syntax restrictions - these are all compile-time errors: - # - for expr in [ "1+2", "x[3]", "(1, 2)" ]: - # Sanity check: is expr is a valid expression by itself? - compile(expr, "testexpr", "exec") - - codestr = "@%s\ndef f(): pass" % expr - self.assertRaises(SyntaxError, compile, codestr, "test", "exec") - # You can't put multiple decorators on a single line: - # - self.assertRaises(SyntaxError, compile, - "@f1 @f2\ndef f(): pass", "test", "exec") + # Test SyntaxErrors: + for stmt in ("x,", "x, y", "x = y", "pass", "import sys"): + compile(stmt, "test", "exec") # Sanity check. + with self.assertRaises(SyntaxError): + compile(f"@{stmt}\ndef f(): pass", "test", "exec") - # Test runtime errors + # Test TypeErrors that used to be SyntaxErrors: + for expr in ("1.+2j", "[1, 2][-1]", "(1, 2)", "True", "...", "None"): + compile(expr, "test", "eval") # Sanity check. + with self.assertRaises(TypeError): + exec(f"@{expr}\ndef f(): pass") def unimp(func): raise NotImplementedError @@ -179,6 +176,13 @@ def unimp(func): code = compile(codestr, "test", "exec") self.assertRaises(exc, eval, code, context) + def test_expressions(self): + for expr in ( + "(x,)", "(x, y)", "x := y", "(x := y)", "x @y", "(x @ y)", "x[0]", + "w[x].y.z", "w + x - (y + z)", "x(y)()(z)", "[w, x, y][z]", "x.y", + ): + compile(f"@{expr}\ndef f(): pass", "test", "exec") + def test_double(self): class C(object): @funcattrs(abc=1, xyz="haha") diff --git a/Lib/test/test_grammar.py b/Lib/test/test_grammar.py index 2ed73e3ae8148..922a5166ec12f 100644 --- a/Lib/test/test_grammar.py +++ b/Lib/test/test_grammar.py @@ -460,7 +460,7 @@ def test_var_annot_rhs(self): def test_funcdef(self): ### [decorators] 'def' NAME parameters ['->' test] ':' suite - ### decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE + ### decorator: '@' namedexpr_test NEWLINE ### decorators: decorator+ ### parameters: '(' [typedargslist] ')' ### typedargslist: ((tfpdef ['=' test] ',')* @@ -666,6 +666,20 @@ def null(x): return x def f(x) -> list: pass self.assertEqual(f.__annotations__, {'return': list}) + # Test expressions as decorators (PEP 614): + @False or null + def f(x): pass + @d := null + def f(x): pass + @lambda f: null(f) + def f(x): pass + @[..., null, ...][1] + def f(x): pass + @null(null)(null) + def f(x): pass + @[null][0].__call__.__call__ + def f(x): pass + # test closures with a variety of opargs closure = 1 def f(): return closure @@ -1515,13 +1529,27 @@ def meth1(self): pass def meth2(self, arg): pass def meth3(self, a1, a2): pass - # decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE + # decorator: '@' namedexpr_test NEWLINE # decorators: decorator+ # decorated: decorators (classdef | funcdef) def class_decorator(x): return x @class_decorator class G: pass + # Test expressions as decorators (PEP 614): + @False or class_decorator + class H: pass + @d := class_decorator + class I: pass + @lambda c: class_decorator(c) + class J: pass + @[..., class_decorator, ...][1] + class K: pass + @class_decorator(class_decorator)(class_decorator) + class L: pass + @[class_decorator][0].__call__.__call__ + class M: pass + def test_dictcomps(self): # dictorsetmaker: ( (test ':' test (comp_for | # (',' test ':' test)* [','])) | diff --git a/Lib/test/test_parser.py b/Lib/test/test_parser.py index 7295f66d393a4..73178f3e7759b 100644 --- a/Lib/test/test_parser.py +++ b/Lib/test/test_parser.py @@ -226,6 +226,27 @@ def test_function_defs(self): self.check_suite("@funcattrs()\n" "def f(): pass") + self.check_suite("@False or x\n" + "def f(): pass") + self.check_suite("@d := x\n" + "def f(): pass") + self.check_suite("@lambda f: x(f)\n" + "def f(): pass") + self.check_suite("@[..., x, ...][1]\n" + "def f(): pass") + self.check_suite("@x(x)(x)\n" + "def f(): pass") + self.check_suite("@(x, x)\n" + "def f(): pass") + self.check_suite("@...\n" + "def f(): pass") + self.check_suite("@None\n" + "def f(): pass") + self.check_suite("@w @(x @y) @(z)\n" + "def f(): pass") + self.check_suite("@w[x].y.z\n" + "def f(): pass") + # keyword-only arguments self.check_suite("def f(*, a): pass") self.check_suite("def f(*, a = 5): pass") @@ -270,6 +291,27 @@ def test_class_defs(self): "@decorator2\n" "class foo():pass") + self.check_suite("@False or x\n" + "class C: pass") + self.check_suite("@d := x\n" + "class C: pass") + self.check_suite("@lambda f: x(f)\n" + "class C: pass") + self.check_suite("@[..., x, ...][1]\n" + "class C: pass") + self.check_suite("@x(x)(x)\n" + "class C: pass") + self.check_suite("@(x, x)\n" + "class C: pass") + self.check_suite("@...\n" + "class C: pass") + self.check_suite("@None\n" + "class C: pass") + self.check_suite("@w @(x @y) @(z)\n" + "class C: pass") + self.check_suite("@w[x].y.z\n" + "class C: pass") + def test_import_from_statement(self): self.check_suite("from sys.path import *") self.check_suite("from sys.path import dirname") diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-02-20-08-12-52.bpo-39702.4_AmyF.rst b/Misc/NEWS.d/next/Core and Builtins/2020-02-20-08-12-52.bpo-39702.4_AmyF.rst new file mode 100644 index 0000000000000..58bafa15714a2 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2020-02-20-08-12-52.bpo-39702.4_AmyF.rst @@ -0,0 +1,2 @@ +Relax :term:`decorator` grammar restrictions to allow any valid expression +(:pep:`614`). diff --git a/Python/ast.c b/Python/ast.c index ad25565b7c7f8..0aed54c8fe2ea 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -1691,80 +1691,16 @@ ast_for_arguments(struct compiling *c, const node *n) return arguments(posonlyargs, posargs, vararg, kwonlyargs, kwdefaults, kwarg, posdefaults, c->c_arena); } -static expr_ty -ast_for_dotted_name(struct compiling *c, const node *n) -{ - expr_ty e; - identifier id; - int lineno, col_offset; - int i; - node *ch; - - REQ(n, dotted_name); - - lineno = LINENO(n); - col_offset = n->n_col_offset; - - ch = CHILD(n, 0); - id = NEW_IDENTIFIER(ch); - if (!id) - return NULL; - e = Name(id, Load, lineno, col_offset, - ch->n_end_lineno, ch->n_end_col_offset, c->c_arena); - if (!e) - return NULL; - - for (i = 2; i < NCH(n); i+=2) { - const node *child = CHILD(n, i); - id = NEW_IDENTIFIER(child); - if (!id) - return NULL; - e = Attribute(e, id, Load, lineno, col_offset, - child->n_end_lineno, child->n_end_col_offset, c->c_arena); - if (!e) - return NULL; - } - - return e; -} - static expr_ty ast_for_decorator(struct compiling *c, const node *n) { - /* decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE */ - expr_ty d = NULL; - expr_ty name_expr; + /* decorator: '@' namedexpr_test NEWLINE */ REQ(n, decorator); REQ(CHILD(n, 0), AT); - REQ(RCHILD(n, -1), NEWLINE); - - name_expr = ast_for_dotted_name(c, CHILD(n, 1)); - if (!name_expr) - return NULL; - - if (NCH(n) == 3) { /* No arguments */ - d = name_expr; - name_expr = NULL; - } - else if (NCH(n) == 5) { /* Call with no arguments */ - d = Call(name_expr, NULL, NULL, - name_expr->lineno, name_expr->col_offset, - CHILD(n, 3)->n_end_lineno, CHILD(n, 3)->n_end_col_offset, - c->c_arena); - if (!d) - return NULL; - name_expr = NULL; - } - else { - d = ast_for_call(c, CHILD(n, 3), name_expr, - CHILD(n, 1), CHILD(n, 2), CHILD(n, 4)); - if (!d) - return NULL; - name_expr = NULL; - } - - return d; + REQ(CHILD(n, 2), NEWLINE); + + return ast_for_expr(c, CHILD(n, 1)); } static asdl_seq* diff --git a/Python/graminit.c b/Python/graminit.c index 62d9ae207f72f..b7aa52895f8ae 100644 --- a/Python/graminit.c +++ b/Python/graminit.c @@ -52,31 +52,17 @@ static const arc arcs_3_0[1] = { static const arc arcs_3_1[1] = { {49, 2}, }; -static const arc arcs_3_2[2] = { - {5, 3}, - {2, 4}, -}; -static const arc arcs_3_3[2] = { - {50, 5}, - {51, 6}, -}; -static const arc arcs_3_4[1] = { - {0, 4}, -}; -static const arc arcs_3_5[1] = { - {2, 4}, +static const arc arcs_3_2[1] = { + {2, 3}, }; -static const arc arcs_3_6[1] = { - {50, 5}, +static const arc arcs_3_3[1] = { + {0, 3}, }; -static state states_3[7] = { +static state states_3[4] = { {1, arcs_3_0}, {1, arcs_3_1}, - {2, arcs_3_2}, - {2, arcs_3_3}, - {1, arcs_3_4}, - {1, arcs_3_5}, - {1, arcs_3_6}, + {1, arcs_3_2}, + {1, arcs_3_3}, }; static const arc arcs_4_0[1] = { {48, 1}, @@ -90,12 +76,12 @@ static state states_4[2] = { {2, arcs_4_1}, }; static const arc arcs_5_0[1] = { - {52, 1}, + {50, 1}, }; static const arc arcs_5_1[3] = { + {52, 2}, + {53, 2}, {54, 2}, - {55, 2}, - {56, 2}, }; static const arc arcs_5_2[1] = { {0, 2}, @@ -109,7 +95,7 @@ static const arc arcs_6_0[1] = { {38, 1}, }; static const arc arcs_6_1[1] = { - {56, 2}, + {54, 2}, }; static const arc arcs_6_2[1] = { {0, 2}, @@ -126,24 +112,24 @@ static const arc arcs_7_1[1] = { {40, 2}, }; static const arc arcs_7_2[1] = { - {57, 3}, + {55, 3}, }; static const arc arcs_7_3[2] = { - {58, 4}, - {59, 5}, + {56, 4}, + {57, 5}, }; static const arc arcs_7_4[1] = { - {60, 6}, + {58, 6}, }; static const arc arcs_7_5[2] = { - {61, 7}, - {62, 8}, + {59, 7}, + {60, 8}, }; static const arc arcs_7_6[1] = { - {59, 5}, + {57, 5}, }; static const arc arcs_7_7[1] = { - {62, 8}, + {60, 8}, }; static const arc arcs_7_8[1] = { {0, 8}, @@ -163,14 +149,14 @@ static const arc arcs_8_0[1] = { {5, 1}, }; static const arc arcs_8_1[2] = { - {50, 2}, - {63, 3}, + {61, 2}, + {62, 3}, }; static const arc arcs_8_2[1] = { {0, 2}, }; static const arc arcs_8_3[1] = { - {50, 2}, + {61, 2}, }; static state states_8[4] = { {1, arcs_8_0}, @@ -180,217 +166,217 @@ static state states_8[4] = { }; static const arc arcs_9_0[3] = { {6, 1}, - {64, 2}, - {65, 3}, + {63, 2}, + {64, 3}, }; static const arc arcs_9_1[4] = { - {66, 4}, - {61, 5}, - {65, 6}, + {65, 4}, + {59, 5}, + {64, 6}, {0, 1}, }; static const arc arcs_9_2[1] = { - {65, 7}, + {64, 7}, }; static const arc arcs_9_3[4] = { - {66, 8}, - {67, 9}, - {61, 5}, + {65, 8}, + {66, 9}, + {59, 5}, {0, 3}, }; static const arc arcs_9_4[4] = { - {64, 2}, - {61, 10}, - {65, 11}, + {63, 2}, + {59, 10}, + {64, 11}, {0, 4}, }; static const arc arcs_9_5[1] = { {0, 5}, }; static const arc arcs_9_6[3] = { - {66, 4}, - {61, 5}, + {65, 4}, + {59, 5}, {0, 6}, }; static const arc arcs_9_7[3] = { - {66, 12}, - {61, 5}, + {65, 12}, + {59, 5}, {0, 7}, }; static const arc arcs_9_8[6] = { {6, 13}, - {64, 2}, - {68, 14}, - {61, 15}, - {65, 3}, + {63, 2}, + {67, 14}, + {59, 15}, + {64, 3}, {0, 8}, }; static const arc arcs_9_9[1] = { - {60, 16}, + {58, 16}, }; static const arc arcs_9_10[3] = { - {64, 2}, - {65, 11}, + {63, 2}, + {64, 11}, {0, 10}, }; static const arc arcs_9_11[4] = { - {66, 4}, - {67, 17}, - {61, 5}, + {65, 4}, + {66, 17}, + {59, 5}, {0, 11}, }; static const arc arcs_9_12[2] = { - {61, 5}, + {59, 5}, {0, 12}, }; static const arc arcs_9_13[4] = { - {66, 18}, - {61, 5}, - {65, 19}, + {65, 18}, + {59, 5}, + {64, 19}, {0, 13}, }; static const arc arcs_9_14[2] = { - {66, 20}, + {65, 20}, {0, 14}, }; static const arc arcs_9_15[5] = { {6, 13}, - {64, 2}, - {68, 14}, - {65, 3}, + {63, 2}, + {67, 14}, + {64, 3}, {0, 15}, }; static const arc arcs_9_16[3] = { - {66, 8}, - {61, 5}, + {65, 8}, + {59, 5}, {0, 16}, }; static const arc arcs_9_17[1] = { - {60, 6}, + {58, 6}, }; static const arc arcs_9_18[4] = { - {64, 2}, - {61, 21}, - {65, 22}, + {63, 2}, + {59, 21}, + {64, 22}, {0, 18}, }; static const arc arcs_9_19[3] = { - {66, 18}, - {61, 5}, + {65, 18}, + {59, 5}, {0, 19}, }; static const arc arcs_9_20[5] = { {6, 23}, - {64, 2}, - {61, 24}, - {65, 25}, + {63, 2}, + {59, 24}, + {64, 25}, {0, 20}, }; static const arc arcs_9_21[3] = { - {64, 2}, - {65, 22}, + {63, 2}, + {64, 22}, {0, 21}, }; static const arc arcs_9_22[4] = { - {66, 18}, - {67, 26}, - {61, 5}, + {65, 18}, + {66, 26}, + {59, 5}, {0, 22}, }; static const arc arcs_9_23[4] = { - {66, 27}, - {61, 5}, - {65, 28}, + {65, 27}, + {59, 5}, + {64, 28}, {0, 23}, }; static const arc arcs_9_24[1] = { - {65, 25}, + {64, 25}, }; static const arc arcs_9_25[4] = { - {66, 29}, - {67, 30}, - {61, 5}, + {65, 29}, + {66, 30}, + {59, 5}, {0, 25}, }; static const arc arcs_9_26[1] = { - {60, 19}, + {58, 19}, }; static const arc arcs_9_27[4] = { - {64, 2}, - {61, 31}, - {65, 32}, + {63, 2}, + {59, 31}, + {64, 32}, {0, 27}, }; static const arc arcs_9_28[3] = { - {66, 27}, - {61, 5}, + {65, 27}, + {59, 5}, {0, 28}, }; static const arc arcs_9_29[5] = { {6, 33}, - {64, 2}, - {61, 34}, - {65, 25}, + {63, 2}, + {59, 34}, + {64, 25}, {0, 29}, }; static const arc arcs_9_30[1] = { - {60, 35}, + {58, 35}, }; static const arc arcs_9_31[3] = { - {64, 2}, - {65, 32}, + {63, 2}, + {64, 32}, {0, 31}, }; static const arc arcs_9_32[4] = { - {66, 27}, - {67, 36}, - {61, 5}, + {65, 27}, + {66, 36}, + {59, 5}, {0, 32}, }; static const arc arcs_9_33[4] = { - {66, 37}, - {61, 5}, - {65, 38}, + {65, 37}, + {59, 5}, + {64, 38}, {0, 33}, }; static const arc arcs_9_34[4] = { {6, 33}, - {64, 2}, - {65, 25}, + {63, 2}, + {64, 25}, {0, 34}, }; static const arc arcs_9_35[3] = { - {66, 29}, - {61, 5}, + {65, 29}, + {59, 5}, {0, 35}, }; static const arc arcs_9_36[1] = { - {60, 28}, + {58, 28}, }; static const arc arcs_9_37[4] = { - {64, 2}, - {61, 39}, - {65, 40}, + {63, 2}, + {59, 39}, + {64, 40}, {0, 37}, }; static const arc arcs_9_38[3] = { - {66, 37}, - {61, 5}, + {65, 37}, + {59, 5}, {0, 38}, }; static const arc arcs_9_39[3] = { - {64, 2}, - {65, 40}, + {63, 2}, + {64, 40}, {0, 39}, }; static const arc arcs_9_40[4] = { - {66, 37}, - {67, 41}, - {61, 5}, + {65, 37}, + {66, 41}, + {59, 5}, {0, 40}, }; static const arc arcs_9_41[1] = { - {60, 38}, + {58, 38}, }; static state states_9[42] = { {3, arcs_9_0}, @@ -440,11 +426,11 @@ static const arc arcs_10_0[1] = { {40, 1}, }; static const arc arcs_10_1[2] = { - {59, 2}, + {57, 2}, {0, 1}, }; static const arc arcs_10_2[1] = { - {60, 3}, + {58, 3}, }; static const arc arcs_10_3[1] = { {0, 3}, @@ -457,153 +443,153 @@ static state states_10[4] = { }; static const arc arcs_11_0[3] = { {6, 1}, - {64, 2}, - {70, 3}, + {63, 2}, + {69, 3}, }; static const arc arcs_11_1[3] = { - {66, 4}, - {70, 5}, + {65, 4}, + {69, 5}, {0, 1}, }; static const arc arcs_11_2[1] = { - {70, 6}, + {69, 6}, }; static const arc arcs_11_3[3] = { - {66, 7}, - {67, 8}, + {65, 7}, + {66, 8}, {0, 3}, }; static const arc arcs_11_4[3] = { - {64, 2}, - {70, 9}, + {63, 2}, + {69, 9}, {0, 4}, }; static const arc arcs_11_5[2] = { - {66, 4}, + {65, 4}, {0, 5}, }; static const arc arcs_11_6[2] = { - {66, 10}, + {65, 10}, {0, 6}, }; static const arc arcs_11_7[5] = { {6, 11}, - {64, 2}, - {68, 12}, - {70, 3}, + {63, 2}, + {67, 12}, + {69, 3}, {0, 7}, }; static const arc arcs_11_8[1] = { - {60, 13}, + {58, 13}, }; static const arc arcs_11_9[3] = { - {66, 4}, - {67, 14}, + {65, 4}, + {66, 14}, {0, 9}, }; static const arc arcs_11_10[1] = { {0, 10}, }; static const arc arcs_11_11[3] = { - {66, 15}, - {70, 16}, + {65, 15}, + {69, 16}, {0, 11}, }; static const arc arcs_11_12[2] = { - {66, 17}, + {65, 17}, {0, 12}, }; static const arc arcs_11_13[2] = { - {66, 7}, + {65, 7}, {0, 13}, }; static const arc arcs_11_14[1] = { - {60, 5}, + {58, 5}, }; static const arc arcs_11_15[3] = { - {64, 2}, - {70, 18}, + {63, 2}, + {69, 18}, {0, 15}, }; static const arc arcs_11_16[2] = { - {66, 15}, + {65, 15}, {0, 16}, }; static const arc arcs_11_17[4] = { {6, 19}, - {64, 2}, - {70, 20}, + {63, 2}, + {69, 20}, {0, 17}, }; static const arc arcs_11_18[3] = { - {66, 15}, - {67, 21}, + {65, 15}, + {66, 21}, {0, 18}, }; static const arc arcs_11_19[3] = { - {66, 22}, - {70, 23}, + {65, 22}, + {69, 23}, {0, 19}, }; static const arc arcs_11_20[3] = { - {66, 24}, - {67, 25}, + {65, 24}, + {66, 25}, {0, 20}, }; static const arc arcs_11_21[1] = { - {60, 16}, + {58, 16}, }; static const arc arcs_11_22[3] = { - {64, 2}, - {70, 26}, + {63, 2}, + {69, 26}, {0, 22}, }; static const arc arcs_11_23[2] = { - {66, 22}, + {65, 22}, {0, 23}, }; static const arc arcs_11_24[4] = { {6, 27}, - {64, 2}, - {70, 20}, + {63, 2}, + {69, 20}, {0, 24}, }; static const arc arcs_11_25[1] = { - {60, 28}, + {58, 28}, }; static const arc arcs_11_26[3] = { - {66, 22}, - {67, 29}, + {65, 22}, + {66, 29}, {0, 26}, }; static const arc arcs_11_27[3] = { - {66, 30}, - {70, 31}, + {65, 30}, + {69, 31}, {0, 27}, }; static const arc arcs_11_28[2] = { - {66, 24}, + {65, 24}, {0, 28}, }; static const arc arcs_11_29[1] = { - {60, 23}, + {58, 23}, }; static const arc arcs_11_30[3] = { - {64, 2}, - {70, 32}, + {63, 2}, + {69, 32}, {0, 30}, }; static const arc arcs_11_31[2] = { - {66, 30}, + {65, 30}, {0, 31}, }; static const arc arcs_11_32[3] = { - {66, 30}, - {67, 33}, + {65, 30}, + {66, 33}, {0, 32}, }; static const arc arcs_11_33[1] = { - {60, 31}, + {58, 31}, }; static state states_11[34] = { {3, arcs_11_0}, @@ -663,15 +649,15 @@ static state states_13[2] = { {1, arcs_13_1}, }; static const arc arcs_14_0[1] = { - {71, 1}, + {70, 1}, }; static const arc arcs_14_1[2] = { - {72, 2}, + {71, 2}, {2, 3}, }; static const arc arcs_14_2[2] = { {2, 3}, - {71, 1}, + {70, 1}, }; static const arc arcs_14_3[1] = { {0, 3}, @@ -683,6 +669,7 @@ static state states_14[4] = { {1, arcs_14_3}, }; static const arc arcs_15_0[8] = { + {72, 1}, {73, 1}, {74, 1}, {75, 1}, @@ -690,7 +677,6 @@ static const arc arcs_15_0[8] = { {77, 1}, {78, 1}, {79, 1}, - {80, 1}, }; static const arc arcs_15_1[1] = { {0, 1}, @@ -700,28 +686,28 @@ static state states_15[2] = { {1, arcs_15_1}, }; static const arc arcs_16_0[1] = { - {81, 1}, + {80, 1}, }; static const arc arcs_16_1[4] = { - {67, 2}, - {82, 3}, - {83, 4}, + {66, 2}, + {81, 3}, + {82, 4}, {0, 1}, }; static const arc arcs_16_2[2] = { - {81, 5}, - {84, 5}, + {80, 5}, + {83, 5}, }; static const arc arcs_16_3[1] = { {0, 3}, }; static const arc arcs_16_4[2] = { {47, 3}, - {84, 3}, + {83, 3}, }; static const arc arcs_16_5[3] = { - {67, 2}, - {61, 3}, + {66, 2}, + {59, 3}, {0, 5}, }; static state states_16[6] = { @@ -733,18 +719,18 @@ static state states_16[6] = { {3, arcs_16_5}, }; static const arc arcs_17_0[1] = { - {59, 1}, + {57, 1}, }; static const arc arcs_17_1[1] = { - {60, 2}, + {58, 2}, }; static const arc arcs_17_2[2] = { - {67, 3}, + {66, 3}, {0, 2}, }; static const arc arcs_17_3[2] = { - {81, 4}, - {84, 4}, + {80, 4}, + {83, 4}, }; static const arc arcs_17_4[1] = { {0, 4}, @@ -757,16 +743,16 @@ static state states_17[5] = { {1, arcs_17_4}, }; static const arc arcs_18_0[2] = { - {85, 1}, - {60, 1}, + {84, 1}, + {58, 1}, }; static const arc arcs_18_1[2] = { - {66, 2}, + {65, 2}, {0, 1}, }; static const arc arcs_18_2[3] = { - {85, 1}, - {60, 1}, + {84, 1}, + {58, 1}, {0, 2}, }; static state states_18[3] = { @@ -775,6 +761,7 @@ static state states_18[3] = { {3, arcs_18_2}, }; static const arc arcs_19_0[13] = { + {85, 1}, {86, 1}, {87, 1}, {88, 1}, @@ -787,7 +774,6 @@ static const arc arcs_19_0[13] = { {95, 1}, {96, 1}, {97, 1}, - {98, 1}, }; static const arc arcs_19_1[1] = { {0, 1}, @@ -800,7 +786,7 @@ static const arc arcs_20_0[1] = { {20, 1}, }; static const arc arcs_20_1[1] = { - {99, 2}, + {98, 2}, }; static const arc arcs_20_2[1] = { {0, 2}, @@ -821,11 +807,11 @@ static state states_21[2] = { {1, arcs_21_1}, }; static const arc arcs_22_0[5] = { + {99, 1}, {100, 1}, {101, 1}, {102, 1}, {103, 1}, - {104, 1}, }; static const arc arcs_22_1[1] = { {0, 1}, @@ -858,7 +844,7 @@ static const arc arcs_25_0[1] = { {31, 1}, }; static const arc arcs_25_1[2] = { - {81, 2}, + {80, 2}, {0, 1}, }; static const arc arcs_25_2[1] = { @@ -870,7 +856,7 @@ static state states_25[3] = { {1, arcs_25_2}, }; static const arc arcs_26_0[1] = { - {84, 1}, + {83, 1}, }; static const arc arcs_26_1[1] = { {0, 1}, @@ -883,7 +869,7 @@ static const arc arcs_27_0[1] = { {30, 1}, }; static const arc arcs_27_1[2] = { - {60, 2}, + {58, 2}, {0, 1}, }; static const arc arcs_27_2[2] = { @@ -891,7 +877,7 @@ static const arc arcs_27_2[2] = { {0, 2}, }; static const arc arcs_27_3[1] = { - {60, 4}, + {58, 4}, }; static const arc arcs_27_4[1] = { {0, 4}, @@ -904,8 +890,8 @@ static state states_27[5] = { {1, arcs_27_4}, }; static const arc arcs_28_0[2] = { + {104, 1}, {105, 1}, - {106, 1}, }; static const arc arcs_28_1[1] = { {0, 1}, @@ -918,7 +904,7 @@ static const arc arcs_29_0[1] = { {25, 1}, }; static const arc arcs_29_1[1] = { - {107, 2}, + {106, 2}, }; static const arc arcs_29_2[1] = { {0, 2}, @@ -932,15 +918,15 @@ static const arc arcs_30_0[1] = { {22, 1}, }; static const arc arcs_30_1[3] = { - {108, 2}, + {107, 2}, {9, 2}, - {49, 3}, + {108, 3}, }; static const arc arcs_30_2[4] = { - {108, 2}, + {107, 2}, {9, 2}, {25, 4}, - {49, 3}, + {108, 3}, }; static const arc arcs_30_3[1] = { {25, 4}, @@ -957,7 +943,7 @@ static const arc arcs_30_6[1] = { {0, 6}, }; static const arc arcs_30_7[1] = { - {50, 6}, + {61, 6}, }; static state states_30[8] = { {1, arcs_30_0}, @@ -989,7 +975,7 @@ static state states_31[4] = { {1, arcs_31_3}, }; static const arc arcs_32_0[1] = { - {49, 1}, + {108, 1}, }; static const arc arcs_32_1[2] = { {111, 2}, @@ -1011,7 +997,7 @@ static const arc arcs_33_0[1] = { {110, 1}, }; static const arc arcs_33_1[2] = { - {66, 2}, + {65, 2}, {0, 1}, }; static const arc arcs_33_2[2] = { @@ -1027,7 +1013,7 @@ static const arc arcs_34_0[1] = { {112, 1}, }; static const arc arcs_34_1[2] = { - {66, 0}, + {65, 0}, {0, 1}, }; static state states_34[2] = { @@ -1038,7 +1024,7 @@ static const arc arcs_35_0[1] = { {40, 1}, }; static const arc arcs_35_1[2] = { - {108, 0}, + {107, 0}, {0, 1}, }; static state states_35[2] = { @@ -1052,7 +1038,7 @@ static const arc arcs_36_1[1] = { {40, 2}, }; static const arc arcs_36_2[2] = { - {66, 1}, + {65, 1}, {0, 2}, }; static state states_36[3] = { @@ -1067,7 +1053,7 @@ static const arc arcs_37_1[1] = { {40, 2}, }; static const arc arcs_37_2[2] = { - {66, 1}, + {65, 1}, {0, 2}, }; static state states_37[3] = { @@ -1079,14 +1065,14 @@ static const arc arcs_38_0[1] = { {15, 1}, }; static const arc arcs_38_1[1] = { - {60, 2}, + {58, 2}, }; static const arc arcs_38_2[2] = { - {66, 3}, + {65, 3}, {0, 2}, }; static const arc arcs_38_3[1] = { - {60, 4}, + {58, 4}, }; static const arc arcs_38_4[1] = { {0, 4}, @@ -1100,10 +1086,10 @@ static state states_38[5] = { }; static const arc arcs_39_0[9] = { {113, 1}, - {55, 1}, {53, 1}, + {51, 1}, {114, 1}, - {56, 1}, + {54, 1}, {115, 1}, {116, 1}, {117, 1}, @@ -1121,7 +1107,7 @@ static const arc arcs_40_0[1] = { }; static const arc arcs_40_1[3] = { {114, 2}, - {56, 2}, + {54, 2}, {118, 2}, }; static const arc arcs_40_2[1] = { @@ -1136,24 +1122,24 @@ static const arc arcs_41_0[1] = { {24, 1}, }; static const arc arcs_41_1[1] = { - {119, 2}, + {49, 2}, }; static const arc arcs_41_2[1] = { - {59, 3}, + {57, 3}, }; static const arc arcs_41_3[1] = { - {120, 4}, + {119, 4}, }; static const arc arcs_41_4[3] = { - {121, 1}, - {122, 5}, + {120, 1}, + {121, 5}, {0, 4}, }; static const arc arcs_41_5[1] = { - {59, 6}, + {57, 6}, }; static const arc arcs_41_6[1] = { - {120, 7}, + {119, 7}, }; static const arc arcs_41_7[1] = { {0, 7}, @@ -1172,23 +1158,23 @@ static const arc arcs_42_0[1] = { {33, 1}, }; static const arc arcs_42_1[1] = { - {119, 2}, + {49, 2}, }; static const arc arcs_42_2[1] = { - {59, 3}, + {57, 3}, }; static const arc arcs_42_3[1] = { - {120, 4}, + {119, 4}, }; static const arc arcs_42_4[2] = { - {122, 5}, + {121, 5}, {0, 4}, }; static const arc arcs_42_5[1] = { - {59, 6}, + {57, 6}, }; static const arc arcs_42_6[1] = { - {120, 7}, + {119, 7}, }; static const arc arcs_42_7[1] = { {0, 7}, @@ -1207,33 +1193,33 @@ static const arc arcs_43_0[1] = { {21, 1}, }; static const arc arcs_43_1[1] = { - {99, 2}, + {98, 2}, }; static const arc arcs_43_2[1] = { - {123, 3}, + {122, 3}, }; static const arc arcs_43_3[1] = { {47, 4}, }; static const arc arcs_43_4[1] = { - {59, 5}, + {57, 5}, }; static const arc arcs_43_5[2] = { - {61, 6}, - {120, 7}, + {59, 6}, + {119, 7}, }; static const arc arcs_43_6[1] = { - {120, 7}, + {119, 7}, }; static const arc arcs_43_7[2] = { - {122, 8}, + {121, 8}, {0, 7}, }; static const arc arcs_43_8[1] = { - {59, 9}, + {57, 9}, }; static const arc arcs_43_9[1] = { - {120, 10}, + {119, 10}, }; static const arc arcs_43_10[1] = { {0, 10}, @@ -1255,44 +1241,44 @@ static const arc arcs_44_0[1] = { {32, 1}, }; static const arc arcs_44_1[1] = { - {59, 2}, + {57, 2}, }; static const arc arcs_44_2[1] = { - {120, 3}, + {119, 3}, }; static const arc arcs_44_3[2] = { - {124, 4}, - {125, 5}, + {123, 4}, + {124, 5}, }; static const arc arcs_44_4[1] = { - {59, 6}, + {57, 6}, }; static const arc arcs_44_5[1] = { - {59, 7}, + {57, 7}, }; static const arc arcs_44_6[1] = { - {120, 8}, + {119, 8}, }; static const arc arcs_44_7[1] = { - {120, 9}, + {119, 9}, }; static const arc arcs_44_8[1] = { {0, 8}, }; static const arc arcs_44_9[4] = { - {122, 10}, - {124, 4}, - {125, 5}, + {121, 10}, + {123, 4}, + {124, 5}, {0, 9}, }; static const arc arcs_44_10[1] = { - {59, 11}, + {57, 11}, }; static const arc arcs_44_11[1] = { - {120, 12}, + {119, 12}, }; static const arc arcs_44_12[2] = { - {124, 4}, + {123, 4}, {0, 12}, }; static state states_44[13] = { @@ -1314,18 +1300,18 @@ static const arc arcs_45_0[1] = { {34, 1}, }; static const arc arcs_45_1[1] = { - {126, 2}, + {125, 2}, }; static const arc arcs_45_2[2] = { - {66, 1}, - {59, 3}, + {65, 1}, + {57, 3}, }; static const arc arcs_45_3[2] = { - {61, 4}, - {120, 5}, + {59, 4}, + {119, 5}, }; static const arc arcs_45_4[1] = { - {120, 5}, + {119, 5}, }; static const arc arcs_45_5[1] = { {0, 5}, @@ -1339,14 +1325,14 @@ static state states_45[6] = { {1, arcs_45_5}, }; static const arc arcs_46_0[1] = { - {60, 1}, + {58, 1}, }; static const arc arcs_46_1[2] = { {111, 2}, {0, 1}, }; static const arc arcs_46_2[1] = { - {127, 3}, + {126, 3}, }; static const arc arcs_46_3[1] = { {0, 3}, @@ -1358,10 +1344,10 @@ static state states_46[4] = { {1, arcs_46_3}, }; static const arc arcs_47_0[1] = { - {128, 1}, + {127, 1}, }; static const arc arcs_47_1[2] = { - {60, 2}, + {58, 2}, {0, 1}, }; static const arc arcs_47_2[2] = { @@ -1386,7 +1372,7 @@ static const arc arcs_48_0[2] = { {4, 2}, }; static const arc arcs_48_1[1] = { - {129, 3}, + {128, 3}, }; static const arc arcs_48_2[1] = { {0, 2}, @@ -1395,7 +1381,7 @@ static const arc arcs_48_3[1] = { {45, 4}, }; static const arc arcs_48_4[2] = { - {130, 2}, + {129, 2}, {45, 4}, }; static state states_48[5] = { @@ -1406,14 +1392,14 @@ static state states_48[5] = { {2, arcs_48_4}, }; static const arc arcs_49_0[1] = { - {60, 1}, + {58, 1}, }; static const arc arcs_49_1[2] = { - {131, 2}, + {130, 2}, {0, 1}, }; static const arc arcs_49_2[1] = { - {60, 3}, + {58, 3}, }; static const arc arcs_49_3[1] = { {0, 3}, @@ -1425,8 +1411,8 @@ static state states_49[4] = { {1, arcs_49_3}, }; static const arc arcs_50_0[2] = { - {132, 1}, - {133, 2}, + {131, 1}, + {132, 2}, }; static const arc arcs_50_1[1] = { {0, 1}, @@ -1436,13 +1422,13 @@ static const arc arcs_50_2[2] = { {0, 2}, }; static const arc arcs_50_3[1] = { - {133, 4}, + {132, 4}, }; static const arc arcs_50_4[1] = { - {122, 5}, + {121, 5}, }; static const arc arcs_50_5[1] = { - {60, 1}, + {58, 1}, }; static state states_50[6] = { {2, arcs_50_0}, @@ -1453,8 +1439,8 @@ static state states_50[6] = { {1, arcs_50_5}, }; static const arc arcs_51_0[2] = { - {135, 1}, - {133, 1}, + {134, 1}, + {132, 1}, }; static const arc arcs_51_1[1] = { {0, 1}, @@ -1467,14 +1453,14 @@ static const arc arcs_52_0[1] = { {26, 1}, }; static const arc arcs_52_1[2] = { - {59, 2}, - {69, 3}, + {57, 2}, + {68, 3}, }; static const arc arcs_52_2[1] = { - {60, 4}, + {58, 4}, }; static const arc arcs_52_3[1] = { - {59, 2}, + {57, 2}, }; static const arc arcs_52_4[1] = { {0, 4}, @@ -1490,14 +1476,14 @@ static const arc arcs_53_0[1] = { {26, 1}, }; static const arc arcs_53_1[2] = { - {59, 2}, - {69, 3}, + {57, 2}, + {68, 3}, }; static const arc arcs_53_2[1] = { - {134, 4}, + {133, 4}, }; static const arc arcs_53_3[1] = { - {59, 2}, + {57, 2}, }; static const arc arcs_53_4[1] = { {0, 4}, @@ -1510,10 +1496,10 @@ static state states_53[5] = { {1, arcs_53_4}, }; static const arc arcs_54_0[1] = { - {136, 1}, + {135, 1}, }; static const arc arcs_54_1[2] = { - {137, 0}, + {136, 0}, {0, 1}, }; static state states_54[2] = { @@ -1521,10 +1507,10 @@ static state states_54[2] = { {2, arcs_54_1}, }; static const arc arcs_55_0[1] = { - {138, 1}, + {137, 1}, }; static const arc arcs_55_1[2] = { - {139, 0}, + {138, 0}, {0, 1}, }; static state states_55[2] = { @@ -1533,10 +1519,10 @@ static state states_55[2] = { }; static const arc arcs_56_0[2] = { {28, 1}, - {140, 2}, + {139, 2}, }; static const arc arcs_56_1[1] = { - {138, 2}, + {137, 2}, }; static const arc arcs_56_2[1] = { {0, 2}, @@ -1547,10 +1533,10 @@ static state states_56[3] = { {1, arcs_56_2}, }; static const arc arcs_57_0[1] = { - {127, 1}, + {126, 1}, }; static const arc arcs_57_1[2] = { - {141, 0}, + {140, 0}, {0, 1}, }; static state states_57[2] = { @@ -1558,15 +1544,15 @@ static state states_57[2] = { {2, arcs_57_1}, }; static const arc arcs_58_0[10] = { + {141, 1}, {142, 1}, {143, 1}, + {141, 1}, {144, 1}, - {142, 1}, {145, 1}, {146, 1}, - {147, 1}, - {123, 1}, - {148, 2}, + {122, 1}, + {147, 2}, {28, 3}, }; static const arc arcs_58_1[1] = { @@ -1577,7 +1563,7 @@ static const arc arcs_58_2[2] = { {0, 2}, }; static const arc arcs_58_3[1] = { - {123, 1}, + {122, 1}, }; static state states_58[4] = { {10, arcs_58_0}, @@ -1589,7 +1575,7 @@ static const arc arcs_59_0[1] = { {6, 1}, }; static const arc arcs_59_1[1] = { - {127, 2}, + {126, 2}, }; static const arc arcs_59_2[1] = { {0, 2}, @@ -1600,10 +1586,10 @@ static state states_59[3] = { {1, arcs_59_2}, }; static const arc arcs_60_0[1] = { - {149, 1}, + {148, 1}, }; static const arc arcs_60_1[2] = { - {150, 0}, + {149, 0}, {0, 1}, }; static state states_60[2] = { @@ -1611,10 +1597,10 @@ static state states_60[2] = { {2, arcs_60_1}, }; static const arc arcs_61_0[1] = { - {151, 1}, + {150, 1}, }; static const arc arcs_61_1[2] = { - {152, 0}, + {151, 0}, {0, 1}, }; static state states_61[2] = { @@ -1622,10 +1608,10 @@ static state states_61[2] = { {2, arcs_61_1}, }; static const arc arcs_62_0[1] = { - {153, 1}, + {152, 1}, }; static const arc arcs_62_1[2] = { - {154, 0}, + {153, 0}, {0, 1}, }; static state states_62[2] = { @@ -1633,11 +1619,11 @@ static state states_62[2] = { {2, arcs_62_1}, }; static const arc arcs_63_0[1] = { - {155, 1}, + {154, 1}, }; static const arc arcs_63_1[3] = { + {155, 0}, {156, 0}, - {157, 0}, {0, 1}, }; static state states_63[2] = { @@ -1645,7 +1631,7 @@ static state states_63[2] = { {3, arcs_63_1}, }; static const arc arcs_64_0[1] = { - {158, 1}, + {157, 1}, }; static const arc arcs_64_1[3] = { {7, 0}, @@ -1657,13 +1643,13 @@ static state states_64[2] = { {3, arcs_64_1}, }; static const arc arcs_65_0[1] = { - {159, 1}, + {158, 1}, }; static const arc arcs_65_1[6] = { - {160, 0}, + {159, 0}, {6, 0}, - {68, 0}, - {161, 0}, + {67, 0}, + {160, 0}, {10, 0}, {0, 1}, }; @@ -1675,10 +1661,10 @@ static const arc arcs_66_0[4] = { {7, 1}, {8, 1}, {37, 1}, - {162, 2}, + {161, 2}, }; static const arc arcs_66_1[1] = { - {159, 2}, + {158, 2}, }; static const arc arcs_66_2[1] = { {0, 2}, @@ -1689,14 +1675,14 @@ static state states_66[3] = { {1, arcs_66_2}, }; static const arc arcs_67_0[1] = { - {163, 1}, + {162, 1}, }; static const arc arcs_67_1[2] = { - {64, 2}, + {63, 2}, {0, 1}, }; static const arc arcs_67_2[1] = { - {159, 3}, + {158, 3}, }; static const arc arcs_67_3[1] = { {0, 3}, @@ -1709,13 +1695,13 @@ static state states_67[4] = { }; static const arc arcs_68_0[2] = { {39, 1}, - {164, 2}, + {163, 2}, }; static const arc arcs_68_1[1] = { - {164, 2}, + {163, 2}, }; static const arc arcs_68_2[2] = { - {165, 2}, + {164, 2}, {0, 2}, }; static state states_68[3] = { @@ -1736,33 +1722,33 @@ static const arc arcs_69_0[10] = { {42, 5}, }; static const arc arcs_69_1[3] = { - {50, 2}, - {166, 6}, - {84, 6}, + {61, 2}, + {165, 6}, + {83, 6}, }; static const arc arcs_69_2[1] = { {0, 2}, }; static const arc arcs_69_3[2] = { - {167, 2}, - {166, 7}, + {166, 2}, + {165, 7}, }; static const arc arcs_69_4[2] = { - {168, 2}, - {169, 8}, + {167, 2}, + {168, 8}, }; static const arc arcs_69_5[2] = { {42, 5}, {0, 5}, }; static const arc arcs_69_6[1] = { - {50, 2}, + {61, 2}, }; static const arc arcs_69_7[1] = { - {167, 2}, + {166, 2}, }; static const arc arcs_69_8[1] = { - {168, 2}, + {167, 2}, }; static state states_69[9] = { {10, arcs_69_0}, @@ -1776,24 +1762,24 @@ static state states_69[9] = { {1, arcs_69_8}, }; static const arc arcs_70_0[2] = { - {119, 1}, - {85, 1}, + {49, 1}, + {84, 1}, }; static const arc arcs_70_1[3] = { - {66, 2}, - {170, 3}, + {65, 2}, + {169, 3}, {0, 1}, }; static const arc arcs_70_2[3] = { - {119, 4}, - {85, 4}, + {49, 4}, + {84, 4}, {0, 2}, }; static const arc arcs_70_3[1] = { {0, 3}, }; static const arc arcs_70_4[2] = { - {66, 2}, + {65, 2}, {0, 4}, }; static state states_70[5] = { @@ -1805,12 +1791,12 @@ static state states_70[5] = { }; static const arc arcs_71_0[3] = { {5, 1}, - {108, 2}, + {107, 2}, {14, 3}, }; static const arc arcs_71_1[2] = { - {50, 4}, - {51, 5}, + {61, 4}, + {170, 5}, }; static const arc arcs_71_2[1] = { {40, 4}, @@ -1822,10 +1808,10 @@ static const arc arcs_71_4[1] = { {0, 4}, }; static const arc arcs_71_5[1] = { - {50, 4}, + {61, 4}, }; static const arc arcs_71_6[1] = { - {167, 4}, + {166, 4}, }; static state states_71[7] = { {3, arcs_71_0}, @@ -1840,7 +1826,7 @@ static const arc arcs_72_0[1] = { {172, 1}, }; static const arc arcs_72_1[2] = { - {66, 2}, + {65, 2}, {0, 1}, }; static const arc arcs_72_2[2] = { @@ -1853,16 +1839,16 @@ static state states_72[3] = { {2, arcs_72_2}, }; static const arc arcs_73_0[2] = { - {59, 1}, - {60, 2}, + {57, 1}, + {58, 2}, }; static const arc arcs_73_1[3] = { {173, 3}, - {60, 4}, + {58, 4}, {0, 1}, }; static const arc arcs_73_2[2] = { - {59, 1}, + {57, 1}, {0, 2}, }; static const arc arcs_73_3[1] = { @@ -1880,10 +1866,10 @@ static state states_73[5] = { {2, arcs_73_4}, }; static const arc arcs_74_0[1] = { - {59, 1}, + {57, 1}, }; static const arc arcs_74_1[2] = { - {60, 2}, + {58, 2}, {0, 1}, }; static const arc arcs_74_2[1] = { @@ -1895,16 +1881,16 @@ static state states_74[3] = { {1, arcs_74_2}, }; static const arc arcs_75_0[2] = { - {127, 1}, - {85, 1}, + {126, 1}, + {84, 1}, }; static const arc arcs_75_1[2] = { - {66, 2}, + {65, 2}, {0, 1}, }; static const arc arcs_75_2[3] = { - {127, 1}, - {85, 1}, + {126, 1}, + {84, 1}, {0, 2}, }; static state states_75[3] = { @@ -1913,14 +1899,14 @@ static state states_75[3] = { {3, arcs_75_2}, }; static const arc arcs_76_0[1] = { - {60, 1}, + {58, 1}, }; static const arc arcs_76_1[2] = { - {66, 2}, + {65, 2}, {0, 1}, }; static const arc arcs_76_2[2] = { - {60, 1}, + {58, 1}, {0, 2}, }; static state states_76[3] = { @@ -1929,61 +1915,61 @@ static state states_76[3] = { {2, arcs_76_2}, }; static const arc arcs_77_0[3] = { - {64, 1}, - {85, 2}, - {60, 3}, + {63, 1}, + {84, 2}, + {58, 3}, }; static const arc arcs_77_1[1] = { - {127, 4}, + {126, 4}, }; static const arc arcs_77_2[3] = { - {66, 5}, - {170, 6}, + {65, 5}, + {169, 6}, {0, 2}, }; static const arc arcs_77_3[4] = { - {66, 5}, - {59, 7}, - {170, 6}, + {65, 5}, + {57, 7}, + {169, 6}, {0, 3}, }; static const arc arcs_77_4[3] = { - {66, 8}, - {170, 6}, + {65, 8}, + {169, 6}, {0, 4}, }; static const arc arcs_77_5[3] = { - {85, 9}, - {60, 9}, + {84, 9}, + {58, 9}, {0, 5}, }; static const arc arcs_77_6[1] = { {0, 6}, }; static const arc arcs_77_7[1] = { - {60, 4}, + {58, 4}, }; static const arc arcs_77_8[3] = { - {64, 10}, - {60, 11}, + {63, 10}, + {58, 11}, {0, 8}, }; static const arc arcs_77_9[2] = { - {66, 5}, + {65, 5}, {0, 9}, }; static const arc arcs_77_10[1] = { - {127, 12}, + {126, 12}, }; static const arc arcs_77_11[1] = { - {59, 13}, + {57, 13}, }; static const arc arcs_77_12[2] = { - {66, 8}, + {65, 8}, {0, 12}, }; static const arc arcs_77_13[1] = { - {60, 12}, + {58, 12}, }; static state states_77[14] = { {3, arcs_77_0}, @@ -2009,20 +1995,20 @@ static const arc arcs_78_1[1] = { }; static const arc arcs_78_2[2] = { {5, 3}, - {59, 4}, + {57, 4}, }; static const arc arcs_78_3[2] = { - {50, 5}, - {51, 6}, + {61, 5}, + {170, 6}, }; static const arc arcs_78_4[1] = { - {120, 7}, + {119, 7}, }; static const arc arcs_78_5[1] = { - {59, 4}, + {57, 4}, }; static const arc arcs_78_6[1] = { - {50, 5}, + {61, 5}, }; static const arc arcs_78_7[1] = { {0, 7}, @@ -2041,7 +2027,7 @@ static const arc arcs_79_0[1] = { {174, 1}, }; static const arc arcs_79_1[2] = { - {66, 2}, + {65, 2}, {0, 1}, }; static const arc arcs_79_2[2] = { @@ -2055,16 +2041,16 @@ static state states_79[3] = { }; static const arc arcs_80_0[3] = { {6, 1}, - {64, 1}, - {60, 2}, + {63, 1}, + {58, 2}, }; static const arc arcs_80_1[1] = { - {60, 3}, + {58, 3}, }; static const arc arcs_80_2[4] = { - {131, 1}, - {67, 1}, - {170, 3}, + {130, 1}, + {66, 1}, + {169, 3}, {0, 2}, }; static const arc arcs_80_3[1] = { @@ -2077,7 +2063,7 @@ static state states_80[4] = { {1, arcs_80_3}, }; static const arc arcs_81_0[2] = { - {170, 1}, + {169, 1}, {176, 1}, }; static const arc arcs_81_1[1] = { @@ -2091,13 +2077,13 @@ static const arc arcs_82_0[1] = { {21, 1}, }; static const arc arcs_82_1[1] = { - {99, 2}, + {98, 2}, }; static const arc arcs_82_2[1] = { - {123, 3}, + {122, 3}, }; static const arc arcs_82_3[1] = { - {133, 4}, + {132, 4}, }; static const arc arcs_82_4[2] = { {175, 5}, @@ -2133,7 +2119,7 @@ static const arc arcs_84_0[1] = { {24, 1}, }; static const arc arcs_84_1[1] = { - {134, 2}, + {133, 2}, }; static const arc arcs_84_2[2] = { {175, 3}, @@ -2175,10 +2161,10 @@ static state states_86[3] = { }; static const arc arcs_87_0[2] = { {22, 1}, - {81, 2}, + {80, 2}, }; static const arc arcs_87_1[1] = { - {60, 2}, + {58, 2}, }; static const arc arcs_87_2[1] = { {0, 2}, @@ -2193,8 +2179,8 @@ static const arc arcs_88_0[2] = { {4, 2}, }; static const arc arcs_88_1[2] = { - {129, 3}, - {61, 4}, + {128, 3}, + {59, 4}, }; static const arc arcs_88_2[1] = { {0, 2}, @@ -2206,11 +2192,11 @@ static const arc arcs_88_4[1] = { {2, 6}, }; static const arc arcs_88_5[2] = { - {130, 2}, + {129, 2}, {45, 5}, }; static const arc arcs_88_6[1] = { - {129, 3}, + {128, 3}, }; static state states_88[7] = { {2, arcs_88_0}, @@ -2240,17 +2226,17 @@ static const arc arcs_90_0[1] = { {5, 1}, }; static const arc arcs_90_1[2] = { - {50, 2}, + {61, 2}, {182, 3}, }; static const arc arcs_90_2[1] = { - {58, 4}, + {56, 4}, }; static const arc arcs_90_3[1] = { - {50, 2}, + {61, 2}, }; static const arc arcs_90_4[1] = { - {60, 5}, + {58, 5}, }; static const arc arcs_90_5[1] = { {0, 5}, @@ -2265,27 +2251,27 @@ static state states_90[6] = { }; static const arc arcs_91_0[3] = { {6, 1}, - {64, 2}, - {60, 3}, + {63, 2}, + {58, 3}, }; static const arc arcs_91_1[3] = { - {66, 4}, - {60, 5}, + {65, 4}, + {58, 5}, {0, 1}, }; static const arc arcs_91_2[1] = { - {60, 6}, + {58, 6}, }; static const arc arcs_91_3[2] = { - {66, 7}, + {65, 7}, {0, 3}, }; static const arc arcs_91_4[2] = { - {64, 2}, - {60, 5}, + {63, 2}, + {58, 5}, }; static const arc arcs_91_5[2] = { - {66, 4}, + {65, 4}, {0, 5}, }; static const arc arcs_91_6[1] = { @@ -2293,21 +2279,21 @@ static const arc arcs_91_6[1] = { }; static const arc arcs_91_7[4] = { {6, 8}, - {64, 2}, - {60, 3}, + {63, 2}, + {58, 3}, {0, 7}, }; static const arc arcs_91_8[3] = { - {66, 9}, - {60, 10}, + {65, 9}, + {58, 10}, {0, 8}, }; static const arc arcs_91_9[2] = { - {64, 2}, - {60, 10}, + {63, 2}, + {58, 10}, }; static const arc arcs_91_10[2] = { - {66, 9}, + {65, 9}, {0, 10}, }; static state states_91[11] = { @@ -2330,7 +2316,7 @@ static const dfa dfas[92] = { "\344\377\377\377\377\027\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {258, "eval_input", 3, states_2, "\240\173\000\024\260\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, - {259, "decorator", 7, states_3, + {259, "decorator", 4, states_3, "\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {260, "decorators", 2, states_4, "\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, @@ -2343,11 +2329,11 @@ static const dfa dfas[92] = { {264, "parameters", 4, states_8, "\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {265, "typedargslist", 42, states_9, - "\100\000\000\000\000\001\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + "\100\000\000\000\000\001\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {266, "tfpdef", 4, states_10, "\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {267, "varargslist", 34, states_11, - "\100\000\000\000\000\001\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + "\100\000\000\000\000\001\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {268, "vfpdef", 2, states_12, "\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {269, "stmt", 2, states_13, @@ -2359,11 +2345,11 @@ static const dfa dfas[92] = { {272, "expr_stmt", 6, states_16, "\340\173\000\024\260\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {273, "annassign", 5, states_17, - "\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {274, "testlist_star_expr", 3, states_18, "\340\173\000\024\260\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {275, "augassign", 2, states_19, - "\000\000\000\000\000\000\000\000\000\000\300\377\007\000\000\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\000\000\340\377\003\000\000\000\000\000\000\000\000\000\000"}, {276, "del_stmt", 3, states_20, "\000\000\020\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {277, "pass_stmt", 2, states_21, @@ -2419,7 +2405,7 @@ static const dfa dfas[92] = { {302, "with_item", 4, states_46, "\240\173\000\024\260\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {303, "except_clause", 5, states_47, - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\200\000\000\000\000\000\000\000"}, {304, "suite", 5, states_48, "\344\373\325\376\270\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {305, "namedexpr_test", 4, states_49, @@ -2441,7 +2427,7 @@ static const dfa dfas[92] = { {313, "comparison", 2, states_57, "\240\173\000\000\260\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {314, "comp_op", 4, states_58, - "\000\000\000\020\000\000\000\000\000\000\000\000\000\000\000\010\000\300\037\000\000\000\000"}, + "\000\000\000\020\000\000\000\000\000\000\000\000\000\000\000\004\000\340\017\000\000\000\000"}, {315, "star_expr", 3, states_59, "\100\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {316, "expr", 2, states_60, @@ -2467,25 +2453,25 @@ static const dfa dfas[92] = { {326, "testlist_comp", 5, states_70, "\340\173\000\024\260\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {327, "trailer", 7, states_71, - "\040\100\000\000\000\000\000\000\000\000\000\000\000\020\000\000\000\000\000\000\000\000\000"}, + "\040\100\000\000\000\000\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\000\000"}, {328, "subscriptlist", 3, states_72, - "\240\173\000\024\260\007\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + "\240\173\000\024\260\007\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {329, "subscript", 5, states_73, - "\240\173\000\024\260\007\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + "\240\173\000\024\260\007\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {330, "sliceop", 3, states_74, - "\000\000\000\000\000\000\000\010\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + "\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {331, "exprlist", 3, states_75, "\340\173\000\000\260\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {332, "testlist", 3, states_76, "\240\173\000\024\260\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {333, "dictorsetmaker", 14, states_77, - "\340\173\000\024\260\007\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + "\340\173\000\024\260\007\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {334, "classdef", 8, states_78, "\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {335, "arglist", 3, states_79, - "\340\173\000\024\260\007\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + "\340\173\000\024\260\007\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {336, "argument", 4, states_80, - "\340\173\000\024\260\007\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + "\340\173\000\024\260\007\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {337, "comp_iter", 2, states_81, "\000\000\040\001\100\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {338, "sync_comp_for", 6, states_82, @@ -2507,7 +2493,7 @@ static const dfa dfas[92] = { {346, "func_type", 6, states_90, "\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, {347, "typelist", 11, states_91, - "\340\173\000\024\260\007\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, + "\340\173\000\024\260\007\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"}, }; static const label labels[183] = { {0, "EMPTY"}, @@ -2559,9 +2545,7 @@ static const label labels[183] = { {258, 0}, {332, 0}, {259, 0}, - {291, 0}, - {8, 0}, - {335, 0}, + {305, 0}, {260, 0}, {261, 0}, {262, 0}, @@ -2573,6 +2557,7 @@ static const label labels[183] = { {306, 0}, {58, 0}, {344, 0}, + {8, 0}, {265, 0}, {35, 0}, {266, 0}, @@ -2619,6 +2604,7 @@ static const label labels[183] = { {285, 0}, {290, 0}, {23, 0}, + {291, 0}, {289, 0}, {287, 0}, {1, "as"}, @@ -2629,7 +2615,6 @@ static const label labels[183] = { {300, 0}, {298, 0}, {301, 0}, - {305, 0}, {304, 0}, {1, "elif"}, {1, "else"}, @@ -2681,6 +2666,7 @@ static const label labels[183] = { {26, 0}, {333, 0}, {339, 0}, + {335, 0}, {328, 0}, {329, 0}, {330, 0}, From webhook-mailer at python.org Tue Mar 3 17:29:45 2020 From: webhook-mailer at python.org (Ryan Rowe) Date: Tue, 03 Mar 2020 22:29:45 -0000 Subject: [Python-checkins] bpo-37953: Fix ForwardRef hash and equality checks (GH-15400) (GH-18751) Message-ID: https://github.com/python/cpython/commit/3eff46fc7d2e3c80c4dedba4177782f1fc8ad89b commit: 3eff46fc7d2e3c80c4dedba4177782f1fc8ad89b branch: 3.7 author: Ryan Rowe committer: GitHub date: 2020-03-03T17:29:40-05:00 summary: bpo-37953: Fix ForwardRef hash and equality checks (GH-15400) (GH-18751) Ideally if we stick a ForwardRef in a dictionary we would like to reliably be able to get it out again. https://bugs.python.org/issue37953 (cherry picked from commit e082e7c) Co-authored-by: plokmijnuhby <39633434+plokmijnuhby at users.noreply.github.com> files: A Misc/NEWS.d/next/Library/2019-09-06-17-40-34.bpo-37953.db5FQq.rst M Lib/test/test_typing.py M Lib/typing.py diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 087dc2a82f038..6e7e5a210a658 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -1505,6 +1505,65 @@ def test_forward_equality(self): self.assertEqual(fr, typing.ForwardRef('int')) self.assertNotEqual(List['int'], List[int]) + def test_forward_equality_gth(self): + c1 = typing.ForwardRef('C') + c1_gth = typing.ForwardRef('C') + c2 = typing.ForwardRef('C') + c2_gth = typing.ForwardRef('C') + + class C: + pass + def foo(a: c1_gth, b: c2_gth): + pass + + self.assertEqual(get_type_hints(foo, globals(), locals()), {'a': C, 'b': C}) + self.assertEqual(c1, c2) + self.assertEqual(c1, c1_gth) + self.assertEqual(c1_gth, c2_gth) + self.assertEqual(List[c1], List[c1_gth]) + self.assertNotEqual(List[c1], List[C]) + self.assertNotEqual(List[c1_gth], List[C]) + self.assertEquals(Union[c1, c1_gth], Union[c1]) + self.assertEquals(Union[c1, c1_gth, int], Union[c1, int]) + + def test_forward_equality_hash(self): + c1 = typing.ForwardRef('int') + c1_gth = typing.ForwardRef('int') + c2 = typing.ForwardRef('int') + c2_gth = typing.ForwardRef('int') + + def foo(a: c1_gth, b: c2_gth): + pass + get_type_hints(foo, globals(), locals()) + + self.assertEqual(hash(c1), hash(c2)) + self.assertEqual(hash(c1_gth), hash(c2_gth)) + self.assertEqual(hash(c1), hash(c1_gth)) + + def test_forward_equality_namespace(self): + class A: + pass + def namespace1(): + a = typing.ForwardRef('A') + def fun(x: a): + pass + get_type_hints(fun, globals(), locals()) + return a + + def namespace2(): + a = typing.ForwardRef('A') + + class A: + pass + def fun(x: a): + pass + + get_type_hints(fun, globals(), locals()) + return a + + self.assertEqual(namespace1(), namespace1()) + self.assertNotEqual(namespace1(), namespace2()) + def test_forward_repr(self): self.assertEqual(repr(List['int']), "typing.List[ForwardRef('int')]") @@ -1524,6 +1583,63 @@ def foo(a: Tuple['T']): self.assertEqual(get_type_hints(foo, globals(), locals()), {'a': Tuple[T]}) + def test_forward_recursion_actually(self): + def namespace1(): + a = typing.ForwardRef('A') + A = a + def fun(x: a): pass + + ret = get_type_hints(fun, globals(), locals()) + return a + + def namespace2(): + a = typing.ForwardRef('A') + A = a + def fun(x: a): pass + + ret = get_type_hints(fun, globals(), locals()) + return a + + def cmp(o1, o2): + return o1 == o2 + + r1 = namespace1() + r2 = namespace2() + self.assertIsNot(r1, r2) + self.assertRaises(RecursionError, cmp, r1, r2) + + def test_union_forward_recursion(self): + ValueList = List['Value'] + Value = Union[str, ValueList] + + class C: + foo: List[Value] + class D: + foo: Union[Value, ValueList] + class E: + foo: Union[List[Value], ValueList] + class F: + foo: Union[Value, List[Value], ValueList] + + self.assertEqual(get_type_hints(C, globals(), locals()), get_type_hints(C, globals(), locals())) + self.assertEqual(get_type_hints(C, globals(), locals()), + {'foo': List[Union[str, List[Union[str, List['Value']]]]]}) + self.assertEqual(get_type_hints(D, globals(), locals()), + {'foo': Union[str, List[Union[str, List['Value']]]]}) + self.assertEqual(get_type_hints(E, globals(), locals()), + {'foo': Union[ + List[Union[str, List[Union[str, List['Value']]]]], + List[Union[str, List['Value']]] + ] + }) + self.assertEqual(get_type_hints(F, globals(), locals()), + {'foo': Union[ + str, + List[Union[str, List['Value']]], + List[Union[str, List[Union[str, List['Value']]]]] + ] + }) + def test_callable_forward(self): def foo(a: Callable[['T'], 'T']): diff --git a/Lib/typing.py b/Lib/typing.py index 3b2e3720fff57..1749c2fd35cd1 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -473,11 +473,13 @@ def _evaluate(self, globalns, localns): def __eq__(self, other): if not isinstance(other, ForwardRef): return NotImplemented - return (self.__forward_arg__ == other.__forward_arg__ and - self.__forward_value__ == other.__forward_value__) + if self.__forward_evaluated__ and other.__forward_evaluated__: + return (self.__forward_arg__ == other.__forward_arg__ and + self.__forward_value__ == other.__forward_value__) + return self.__forward_arg__ == other.__forward_arg__ def __hash__(self): - return hash((self.__forward_arg__, self.__forward_value__)) + return hash(self.__forward_arg__) def __repr__(self): return f'ForwardRef({self.__forward_arg__!r})' diff --git a/Misc/NEWS.d/next/Library/2019-09-06-17-40-34.bpo-37953.db5FQq.rst b/Misc/NEWS.d/next/Library/2019-09-06-17-40-34.bpo-37953.db5FQq.rst new file mode 100644 index 0000000000000..4eff4f7479aad --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-09-06-17-40-34.bpo-37953.db5FQq.rst @@ -0,0 +1,2 @@ +In :mod:`typing`, improved the ``__hash__`` and ``__eq__`` methods for +:class:`ForwardReferences`. From webhook-mailer at python.org Wed Mar 4 02:06:24 2020 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 04 Mar 2020 07:06:24 -0000 Subject: [Python-checkins] [3.7] bpo-39389: gzip: fix compression level metadata (GH-18077) (GH-18101) Message-ID: https://github.com/python/cpython/commit/12c45efe828a90a2f2f58a1f95c85d792a0d9c0a commit: 12c45efe828a90a2f2f58a1f95c85d792a0d9c0a branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2020-03-04T02:06:19-05:00 summary: [3.7] bpo-39389: gzip: fix compression level metadata (GH-18077) (GH-18101) * bpo-39389: gzip: fix compression level metadata (GH-18077) As described in RFC 1952, section 2.3.1, the XFL (eXtra FLags) byte of a gzip member header should indicate whether the DEFLATE algorithm was tuned for speed or compression ratio. Prior to this patch, archives emitted by the `gzip` module always indicated maximum compression. (cherry picked from commit eab3b3f1c60afecfb4db3c3619109684cb04bd60) Co-authored-by: William Chargin files: A Misc/NEWS.d/next/Library/2020-01-20-00-56-01.bpo-39389.fEirIS.rst M Lib/gzip.py M Lib/test/test_gzip.py diff --git a/Lib/gzip.py b/Lib/gzip.py index ddc7bda1fecbb..e59b454814327 100644 --- a/Lib/gzip.py +++ b/Lib/gzip.py @@ -17,6 +17,11 @@ READ, WRITE = 1, 2 +_COMPRESS_LEVEL_FAST = 1 +_COMPRESS_LEVEL_TRADEOFF = 6 +_COMPRESS_LEVEL_BEST = 9 + + def open(filename, mode="rb", compresslevel=9, encoding=None, errors=None, newline=None): """Open a gzip-compressed file in binary or text mode. @@ -191,7 +196,7 @@ def __init__(self, filename=None, mode=None, self.fileobj = fileobj if self.mode == WRITE: - self._write_gzip_header() + self._write_gzip_header(compresslevel) @property def filename(self): @@ -218,7 +223,7 @@ def _init_write(self, filename): self.bufsize = 0 self.offset = 0 # Current file offset for seek(), tell(), etc - def _write_gzip_header(self): + def _write_gzip_header(self, compresslevel): self.fileobj.write(b'\037\213') # magic header self.fileobj.write(b'\010') # compression method try: @@ -239,7 +244,13 @@ def _write_gzip_header(self): if mtime is None: mtime = time.time() write32u(self.fileobj, int(mtime)) - self.fileobj.write(b'\002') + if compresslevel == _COMPRESS_LEVEL_BEST: + xfl = b'\002' + elif compresslevel == _COMPRESS_LEVEL_FAST: + xfl = b'\004' + else: + xfl = b'\000' + self.fileobj.write(xfl) self.fileobj.write(b'\377') if fname: self.fileobj.write(fname + b'\000') diff --git a/Lib/test/test_gzip.py b/Lib/test/test_gzip.py index 17ecda2089f25..0251914d8bcab 100644 --- a/Lib/test/test_gzip.py +++ b/Lib/test/test_gzip.py @@ -358,6 +358,26 @@ def test_metadata(self): isizeBytes = fRead.read(4) self.assertEqual(isizeBytes, struct.pack(' https://github.com/python/cpython/commit/93b7677f9cc44afb3269bd81cbd359c6f5798581 commit: 93b7677f9cc44afb3269bd81cbd359c6f5798581 branch: 3.7 author: Ned Deily committer: Ned Deily date: 2020-03-04T02:37:27-05:00 summary: 3.7.7rc1 files: A Misc/NEWS.d/3.7.7rc1.rst D Misc/NEWS.d/next/Build/2019-12-27-22-18-26.bpo-39144.dwHMlR.rst D Misc/NEWS.d/next/Core and Builtins/2019-10-31-14-30-39.bpo-38610.fHdVMS.rst D Misc/NEWS.d/next/Core and Builtins/2019-12-12-21-05-43.bpo-39031.imlCYZ.rst D Misc/NEWS.d/next/Core and Builtins/2019-12-29-19-13-54.bpo-38588.pgXnNS.rst D Misc/NEWS.d/next/Core and Builtins/2020-01-20-21-40-57.bpo-39386.ULqD8t.rst D Misc/NEWS.d/next/Core and Builtins/2020-01-22-15-53-37.bpo-39421.O3nG7u.rst D Misc/NEWS.d/next/Core and Builtins/2020-01-22-22-28-04.bpo-39427.LiO-Eo.rst D Misc/NEWS.d/next/Core and Builtins/2020-01-25-23-51-17.bpo-39453.xCOkYk.rst D Misc/NEWS.d/next/Core and Builtins/2020-02-04-10-27-41.bpo-39510.PMIh-f.rst D Misc/NEWS.d/next/Core and Builtins/2020-02-11-23-59-07.bpo-39606.a72Sxc.rst D Misc/NEWS.d/next/Core and Builtins/2020-02-18-01-40-13.bpo-39382.OLSJu9.rst D Misc/NEWS.d/next/Core and Builtins/2020-03-02-19-21-21.bpo-39778._YGLEc.rst D Misc/NEWS.d/next/Core and Builtins/2020-03-02-20-12-33.bpo-39776.fNaxi_.rst D Misc/NEWS.d/next/Documentation/2019-11-17-11-53-10.bpo-3530.8zFUMc.rst D Misc/NEWS.d/next/Documentation/2019-12-15-22-04-41.bpo-38918.8JnDTS.rst D Misc/NEWS.d/next/Documentation/2020-01-18-15-37-56.bpo-39381.wTWe8d.rst D Misc/NEWS.d/next/Documentation/2020-01-27-18-18-42.bpo-39392.oiqcLO.rst D Misc/NEWS.d/next/Documentation/2020-02-18-07-42-20.bpo-39654.MoT1jI.rst D Misc/NEWS.d/next/Documentation/2020-02-19-11-13-47.bpo-17422.g7_9zz.rst D Misc/NEWS.d/next/Documentation/2020-02-23-13-26-40.bpo-39530._bCvzQ.rst D Misc/NEWS.d/next/Documentation/2020-02-28-14-39-25.bpo-13790.hvLaRI.rst D Misc/NEWS.d/next/IDLE/2018-03-03-12-56-26.bpo-32989.FVhmhH.rst D Misc/NEWS.d/next/IDLE/2019-11-13-23-51-39.bpo-38792.xhTC5a.rst D Misc/NEWS.d/next/IDLE/2019-12-30-16-44-07.bpo-34118.FaNW0a.rst D Misc/NEWS.d/next/IDLE/2020-01-22-22-28-06.bpo-39050.zkn0FO.rst D Misc/NEWS.d/next/IDLE/2020-01-25-02-26-45.bpo-39388.x4TQNh.rst D Misc/NEWS.d/next/IDLE/2020-01-27-16-44-29.bpo-30780.nR80qu.rst D Misc/NEWS.d/next/IDLE/2020-02-10-17-09-48.bpo-39600.X6NsyM.rst D Misc/NEWS.d/next/IDLE/2020-02-17-21-09-03.bpo-39663.wexcsH.rst D Misc/NEWS.d/next/IDLE/2020-02-27-22-17-09.bpo-39781.bbYBeL.rst D Misc/NEWS.d/next/Library/2019-03-24-12-12-27.bpo-36406.mCEkOl.rst D Misc/NEWS.d/next/Library/2019-09-06-17-40-34.bpo-37953.db5FQq.rst D Misc/NEWS.d/next/Library/2019-09-29-08-17-03.bpo-38293.wls5s3.rst D Misc/NEWS.d/next/Library/2019-10-14-21-14-55.bpo-38473.uXpVld.rst D Misc/NEWS.d/next/Library/2019-10-31-19-23-25.bpo-35182.hzeNl9.rst D Misc/NEWS.d/next/Library/2019-11-22-12-08-52.bpo-38878.EJ0cFf.rst D Misc/NEWS.d/next/Library/2019-12-15-19-23-23.bpo-39055.FmN3un.rst D Misc/NEWS.d/next/Library/2019-12-15-21-05-16.bpo-39056.nEfUM9.rst D Misc/NEWS.d/next/Library/2019-12-15-21-47-54.bpo-39057.FOxn-w.rst D Misc/NEWS.d/next/Library/2019-12-20-16-06-28.bpo-38971.fKRYlF.rst D Misc/NEWS.d/next/Library/2019-12-31-19-27-23.bpo-39142.oqU5iD.rst D Misc/NEWS.d/next/Library/2020-01-01-18-44-52.bpo-38871.3EEOLg.rst D Misc/NEWS.d/next/Library/2020-01-02-17-28-03.bpo-39191.ur_scy.rst D Misc/NEWS.d/next/Library/2020-01-02-20-21-03.bpo-39198.nzwGyG.rst D Misc/NEWS.d/next/Library/2020-01-03-18-02-50.bpo-39152.JgPjCC.rst D Misc/NEWS.d/next/Library/2020-01-08-23-25-27.bpo-39242.bnL65N.rst D Misc/NEWS.d/next/Library/2020-01-15-23-13-03.bpo-39274.lpc0-n.rst D Misc/NEWS.d/next/Library/2020-01-20-00-56-01.bpo-39389.fEirIS.rst D Misc/NEWS.d/next/Library/2020-01-24-11-05-21.bpo-39430.I0UQzM.rst D Misc/NEWS.d/next/Library/2020-01-29-14-58-27.bpo-39485.Zy3ot6.rst D Misc/NEWS.d/next/Library/2020-01-30-01-13-19.bpo-39493.CbFRi7.rst D Misc/NEWS.d/next/Library/2020-02-02-14-46-34.bpo-39450.48R274.rst D Misc/NEWS.d/next/Library/2020-02-06-05-33-52.bpo-39548.DF4FFe.rst D Misc/NEWS.d/next/Library/2020-02-12-10-04-39.bpo-21016.bFXPH7.rst D Misc/NEWS.d/next/Library/2020-02-16-07-47-55.bpo-27657.9kZchc.rst D Misc/NEWS.d/next/Library/2020-02-23-21-27-10.bpo-39649.qiubSp.rst D Misc/NEWS.d/next/Library/2020-02-24-03-45-28.bpo-30566.qROxty.rst D Misc/NEWS.d/next/Library/2020-02-29-13-20-33.bpo-39769.hJmxu4.rst D Misc/NEWS.d/next/Library/2020-02-29-19-17-39.bpo-39794.7VjatS.rst D Misc/NEWS.d/next/Security/2020-01-28-20-54-09.bpo-39401.he7h_A.rst D Misc/NEWS.d/next/Tests/2019-12-18-14-52-08.bpo-38546.2kxNuM.rst D Misc/NEWS.d/next/Windows/2020-01-02-01-11-53.bpo-39185.T4herN.rst D Misc/NEWS.d/next/Windows/2020-01-24-03-07-14.bpo-39439.rwMWDR.rst D Misc/NEWS.d/next/Windows/2020-02-28-23-51-27.bpo-38380.TpOBCj.rst D Misc/NEWS.d/next/Windows/2020-03-01-15-04-54.bpo-38597.MnHdYl.rst D Misc/NEWS.d/next/macOS/2020-02-28-23-51-47.bpo-38380.u-ySyA.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 e912ff069b078..0006429ee7bcc 100644 --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -18,12 +18,12 @@ /*--start constants--*/ #define PY_MAJOR_VERSION 3 #define PY_MINOR_VERSION 7 -#define PY_MICRO_VERSION 6 -#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL -#define PY_RELEASE_SERIAL 0 +#define PY_MICRO_VERSION 7 +#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_GAMMA +#define PY_RELEASE_SERIAL 1 /* Version as a string */ -#define PY_VERSION "3.7.6+" +#define PY_VERSION "3.7.7rc1" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/Lib/pydoc_data/topics.py b/Lib/pydoc_data/topics.py index 0438309135f3b..7ca16fb4b2c6c 100644 --- a/Lib/pydoc_data/topics.py +++ b/Lib/pydoc_data/topics.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Autogenerated by Sphinx on Wed Dec 18 13:43:31 2019 +# Autogenerated by Sphinx on Wed Mar 4 02:29:35 2020 topics = {'assert': 'The "assert" statement\n' '**********************\n' '\n' @@ -5070,11 +5070,11 @@ 'only\n' 'supported by the numeric types.\n' '\n' - 'A general convention is that an empty format string ("""") ' + 'A general convention is that an empty format specification ' 'produces\n' 'the same result as if you had called "str()" on the value. ' 'A non-empty\n' - 'format string typically modifies the result.\n' + 'format specification typically modifies the result.\n' '\n' 'The general form of a *standard format specifier* is:\n' '\n' @@ -5227,9 +5227,12 @@ 'Changed in version 3.6: Added the "\'_\'" option (see also ' '**PEP 515**).\n' '\n' - '*width* is a decimal integer defining the minimum field ' - 'width. If not\n' - 'specified, then the field width will be determined by the ' + '*width* is a decimal integer defining the minimum total ' + 'field width,\n' + 'including any prefixes, separators, and other formatting ' + 'characters.\n' + 'If not specified, then the field width will be determined ' + 'by the\n' 'content.\n' '\n' 'When no explicit alignment is given, preceding the *width* ' @@ -6771,7 +6774,7 @@ 'object.__rfloordiv__(self, other)\n' 'object.__rmod__(self, other)\n' 'object.__rdivmod__(self, other)\n' - 'object.__rpow__(self, other)\n' + 'object.__rpow__(self, other[, modulo])\n' 'object.__rlshift__(self, other)\n' 'object.__rrshift__(self, other)\n' 'object.__rand__(self, other)\n' @@ -8907,11 +8910,17 @@ 'bases,\n' '**kwds)" (where the additional keyword arguments, if any, ' 'come from\n' - 'the class definition).\n' + 'the class definition). The "__prepare__" method should be ' + 'implemented\n' + 'as a "classmethod()". The namespace returned by ' + '"__prepare__" is\n' + 'passed in to "__new__", but when the final class object is ' + 'created the\n' + 'namespace is copied into a new "dict".\n' '\n' 'If the metaclass has no "__prepare__" attribute, then the ' 'class\n' - 'namespace is initialised as an empty ordered mapping.\n' + 'namespace is initialised as an empty "dict()".\n' '\n' 'See also:\n' '\n' @@ -9421,7 +9430,7 @@ 'object.__rfloordiv__(self, other)\n' 'object.__rmod__(self, other)\n' 'object.__rdivmod__(self, other)\n' - 'object.__rpow__(self, other)\n' + 'object.__rpow__(self, other[, modulo])\n' 'object.__rlshift__(self, other)\n' 'object.__rrshift__(self, other)\n' 'object.__rand__(self, other)\n' @@ -11847,10 +11856,9 @@ ' "co_lnotab" is a string encoding the mapping from bytecode\n' ' offsets to line numbers (for details see the source code of ' 'the\n' - ' interpreter); "co_stacksize" is the required stack size\n' - ' (including local variables); "co_flags" is an integer ' - 'encoding a\n' - ' number of flags for the interpreter.\n' + ' interpreter); "co_stacksize" is the required stack size;\n' + ' "co_flags" is an integer encoding a number of flags for the\n' + ' interpreter.\n' '\n' ' The following flag bits are defined for "co_flags": bit ' '"0x04"\n' diff --git a/Misc/NEWS.d/3.7.7rc1.rst b/Misc/NEWS.d/3.7.7rc1.rst new file mode 100644 index 0000000000000..27d05ab4f3e4b --- /dev/null +++ b/Misc/NEWS.d/3.7.7rc1.rst @@ -0,0 +1,668 @@ +.. bpo: 39401 +.. date: 2020-01-28-20-54-09 +.. nonce: he7h_A +.. release date: 2020-03-04 +.. section: Security + +Avoid unsafe load of ``api-ms-win-core-path-l1-1-0.dll`` at startup on +Windows 7. + +.. + +.. bpo: 39776 +.. date: 2020-03-02-20-12-33 +.. nonce: fNaxi_ +.. section: Core and Builtins + +Fix race condition where threads created by PyGILState_Ensure() could get a +duplicate id. + +This affects consumers of tstate->id like the contextvar caching machinery, +which could return invalid cached objects under heavy thread load (observed +in embedded scenarios). + +.. + +.. bpo: 39778 +.. date: 2020-03-02-19-21-21 +.. nonce: _YGLEc +.. section: Core and Builtins + +Fixed a crash due to incorrect handling of weak references in +``collections.OrderedDict`` classes. Patch by Pablo Galindo. + +.. + +.. bpo: 39382 +.. date: 2020-02-18-01-40-13 +.. nonce: OLSJu9 +.. section: Core and Builtins + +Fix a use-after-free in the single inheritance path of ``issubclass()``, +when the ``__bases__`` of an object has a single reference, and so does its +first item. Patch by Yonatan Goldschmidt. + +.. + +.. bpo: 39606 +.. date: 2020-02-11-23-59-07 +.. nonce: a72Sxc +.. section: Core and Builtins + +Fix regression caused by fix for bpo-39386, that prevented calling +``aclose`` on an async generator that had already been closed or exhausted. + +.. + +.. bpo: 39510 +.. date: 2020-02-04-10-27-41 +.. nonce: PMIh-f +.. section: Core and Builtins + +Fix segfault in ``readinto()`` method on closed BufferedReader. + +.. + +.. bpo: 39453 +.. date: 2020-01-25-23-51-17 +.. nonce: xCOkYk +.. section: Core and Builtins + +Fixed a possible crash in :meth:`list.__contains__` when a list is changed +during comparing items. Patch by Dong-hee Na. + +.. + +.. bpo: 39427 +.. date: 2020-01-22-22-28-04 +.. nonce: LiO-Eo +.. section: Core and Builtins + +Document all possibilities for the ``-X`` options in the command line help +section. Patch by Pablo Galindo. + +.. + +.. bpo: 39421 +.. date: 2020-01-22-15-53-37 +.. nonce: O3nG7u +.. section: Core and Builtins + +Fix possible crashes when operating with the functions in the :mod:`heapq` +module and custom comparison operators. + +.. + +.. bpo: 39386 +.. date: 2020-01-20-21-40-57 +.. nonce: ULqD8t +.. section: Core and Builtins + +Prevent double awaiting of async iterator. + +.. + +.. bpo: 38588 +.. date: 2019-12-29-19-13-54 +.. nonce: pgXnNS +.. section: Core and Builtins + +Fix possible crashes in dict and list when calling +:c:func:`PyObject_RichCompareBool`. + +.. + +.. bpo: 39031 +.. date: 2019-12-12-21-05-43 +.. nonce: imlCYZ +.. section: Core and Builtins + +When parsing an "elif" node, lineno and col_offset of the node now point to +the "elif" keyword and not to its condition, making it consistent with the +"if" node. Patch by Lysandros Nikolaou. + +.. + +.. bpo: 38610 +.. date: 2019-10-31-14-30-39 +.. nonce: fHdVMS +.. section: Core and Builtins + +Fix possible crashes in several list methods by holding strong references to +list elements when calling :c:func:`PyObject_RichCompareBool`. + +.. + +.. bpo: 39794 +.. date: 2020-02-29-19-17-39 +.. nonce: 7VjatS +.. section: Library + +Add --without-decimal-contextvar build option. This enables a thread-local +rather than a coroutine local context. + +.. + +.. bpo: 39769 +.. date: 2020-02-29-13-20-33 +.. nonce: hJmxu4 +.. section: Library + +The :func:`compileall.compile_dir` function's *ddir* parameter and the +compileall command line flag `-d` no longer write the wrong pathname to the +generated pyc file for submodules beneath the root of the directory tree +being compiled. This fixes a regression introduced with Python 3.5. + +.. + +.. bpo: 30566 +.. date: 2020-02-24-03-45-28 +.. nonce: qROxty +.. section: Library + +Fix :exc:`IndexError` when trying to decode an invalid string with punycode +codec. + +.. + +.. bpo: 39649 +.. date: 2020-02-23-21-27-10 +.. nonce: qiubSp +.. section: Library + +Remove obsolete check for `__args__` in bdb.Bdb.format_stack_entry. + +.. + +.. bpo: 27657 +.. date: 2020-02-16-07-47-55 +.. nonce: 9kZchc +.. section: Library + +The original fix for bpo-27657, "Fix urlparse() with numeric paths" +(GH-16839) included in 3.7.6, inadvertently introduced a behavior change +that broke several third-party packages relying on the original undefined +parsing behavior. The change is reverted in 3.7.7, restoring the behavior of +3.7.5 and earlier releases. + +.. + +.. bpo: 21016 +.. date: 2020-02-12-10-04-39 +.. nonce: bFXPH7 +.. section: Library + +The :mod:`pydoc` and :mod:`trace` modules now use the :mod:`sysconfig` +module to get the path to the Python standard library, to support uncommon +installation path like ``/usr/lib64/python3.9/`` on Fedora. Patch by Jan +Mat?jek. + +.. + +.. bpo: 39548 +.. date: 2020-02-06-05-33-52 +.. nonce: DF4FFe +.. section: Library + +Fix handling of header in :class:`urllib.request.AbstractDigestAuthHandler` +when the optional ``qop`` parameter is not present. + +.. + +.. bpo: 39450 +.. date: 2020-02-02-14-46-34 +.. nonce: 48R274 +.. section: Library + +Striped whitespace from docstring before returning it from +:func:`unittest.case.shortDescription`. + +.. + +.. bpo: 39493 +.. date: 2020-01-30-01-13-19 +.. nonce: CbFRi7 +.. section: Library + +Mark ``typing.IO.closed`` as a property + +.. + +.. bpo: 39485 +.. date: 2020-01-29-14-58-27 +.. nonce: Zy3ot6 +.. section: Library + +Fix a bug in :func:`unittest.mock.create_autospec` that would complain about +the wrong number of arguments for custom descriptors defined in an extension +module returning functions. + +.. + +.. bpo: 39430 +.. date: 2020-01-24-11-05-21 +.. nonce: I0UQzM +.. section: Library + +Fixed race condition in lazy imports in :mod:`tarfile`. + +.. + +.. bpo: 39389 +.. date: 2020-01-20-00-56-01 +.. nonce: fEirIS +.. section: Library + +Write accurate compression level metadata in :mod:`gzip` archives, rather +than always signaling maximum compression. + +.. + +.. bpo: 39274 +.. date: 2020-01-15-23-13-03 +.. nonce: lpc0-n +.. section: Library + +``bool(fraction.Fraction)`` now returns a boolean even if (numerator != 0) +does not return a boolean (ex: numpy number). + +.. + +.. bpo: 39242 +.. date: 2020-01-08-23-25-27 +.. nonce: bnL65N +.. section: Library + +Updated the Gmane domain from news.gmane.org to news.gmane.io which is used +for examples of :class:`~nntplib.NNTP` news reader server and nntplib tests. + +.. + +.. bpo: 39152 +.. date: 2020-01-03-18-02-50 +.. nonce: JgPjCC +.. section: Library + +Fix ttk.Scale.configure([name]) to return configuration tuple for name or +all options. Giovanni Lombardo contributed part of the patch. + +.. + +.. bpo: 39198 +.. date: 2020-01-02-20-21-03 +.. nonce: nzwGyG +.. section: Library + +If an exception were to be thrown in `Logger.isEnabledFor` (say, by asyncio +timeouts or stopit) , the `logging` global lock may not be released +appropriately, resulting in deadlock. This change wraps that block of code +with `try...finally` to ensure the lock is released. + +.. + +.. bpo: 39191 +.. date: 2020-01-02-17-28-03 +.. nonce: ur_scy +.. section: Library + +Perform a check for running loop before starting a new task in +``loop.run_until_complete()`` to fail fast; it prevents the side effect of +new task spawning before exception raising. + +.. + +.. bpo: 38871 +.. date: 2020-01-01-18-44-52 +.. nonce: 3EEOLg +.. section: Library + +Correctly parenthesize filter-based statements that contain lambda +expressions in mod:`lib2to3`. Patch by Dong-hee Na. + +.. + +.. bpo: 39142 +.. date: 2019-12-31-19-27-23 +.. nonce: oqU5iD +.. section: Library + +A change was made to logging.config.dictConfig to avoid converting instances +of named tuples to ConvertingTuple. It's assumed that named tuples are too +specialised to be treated like ordinary tuples; if a user of named tuples +requires ConvertingTuple functionality, they will have to implement that +themselves in their named tuple class. + +.. + +.. bpo: 38971 +.. date: 2019-12-20-16-06-28 +.. nonce: fKRYlF +.. section: Library + +Open issue in the BPO indicated a desire to make the implementation of +codecs.open() at parity with io.open(), which implements a try/except to +assure file stream gets closed before an exception is raised. + +.. + +.. bpo: 39057 +.. date: 2019-12-15-21-47-54 +.. nonce: FOxn-w +.. section: Library + +:func:`urllib.request.proxy_bypass_environment` now ignores leading dots and +no longer ignores a trailing newline. + +.. + +.. bpo: 39056 +.. date: 2019-12-15-21-05-16 +.. nonce: nEfUM9 +.. section: Library + +Fixed handling invalid warning category in the -W option. No longer import +the re module if it is not needed. + +.. + +.. bpo: 39055 +.. date: 2019-12-15-19-23-23 +.. nonce: FmN3un +.. section: Library + +:func:`base64.b64decode` with ``validate=True`` raises now a binascii.Error +if the input ends with a single ``\n``. + +.. + +.. bpo: 38878 +.. date: 2019-11-22-12-08-52 +.. nonce: EJ0cFf +.. section: Library + +Fixed __subclasshook__ of :class:`os.PathLike` to return a correct result +upon inheritence. Patch by Bar Harel. + +.. + +.. bpo: 35182 +.. date: 2019-10-31-19-23-25 +.. nonce: hzeNl9 +.. section: Library + +Fixed :func:`Popen.communicate` subsequent call crash when the child process +has already closed any piped standard stream, but still continues to be +running. Patch by Andriy Maletsky. + +.. + +.. bpo: 38473 +.. date: 2019-10-14-21-14-55 +.. nonce: uXpVld +.. section: Library + +Use signature from inner mock for autospecced methods attached with +:func:`unittest.mock.attach_mock`. Patch by Karthikeyan Singaravelan. + +.. + +.. bpo: 38293 +.. date: 2019-09-29-08-17-03 +.. nonce: wls5s3 +.. section: Library + +Add :func:`copy.copy` and :func:`copy.deepcopy` support to :func:`property` +objects. + +.. + +.. bpo: 37953 +.. date: 2019-09-06-17-40-34 +.. nonce: db5FQq +.. section: Library + +In :mod:`typing`, improved the ``__hash__`` and ``__eq__`` methods for +:class:`ForwardReferences`. + +.. + +.. bpo: 36406 +.. date: 2019-03-24-12-12-27 +.. nonce: mCEkOl +.. section: Library + +Handle namespace packages in :mod:`doctest`. Patch by Karthikeyan +Singaravelan. + +.. + +.. bpo: 13790 +.. date: 2020-02-28-14-39-25 +.. nonce: hvLaRI +.. section: Documentation + +Change 'string' to 'specification' in format doc. + +.. + +.. bpo: 39530 +.. date: 2020-02-23-13-26-40 +.. nonce: _bCvzQ +.. section: Documentation + +Fix misleading documentation about mixed-type numeric comparisons. + +.. + +.. bpo: 17422 +.. date: 2020-02-19-11-13-47 +.. nonce: g7_9zz +.. section: Documentation + +The language reference now specifies restrictions on class namespaces. +Adapted from a patch by Ethan Furman. + +.. + +.. bpo: 39654 +.. date: 2020-02-18-07-42-20 +.. nonce: MoT1jI +.. section: Documentation + +In pyclbr doc, update 'class' to 'module' where appropriate and add +readmodule comment. Patch by Hakan ?elik. + +.. + +.. bpo: 39392 +.. date: 2020-01-27-18-18-42 +.. nonce: oiqcLO +.. section: Documentation + +Explain that when filling with turtle, overlap regions may be left unfilled. + +.. + +.. bpo: 39381 +.. date: 2020-01-18-15-37-56 +.. nonce: wTWe8d +.. section: Documentation + +Mention in docs that :func:`asyncio.get_event_loop` implicitly creates new +event loop only if called from the main thread. + +.. + +.. bpo: 38918 +.. date: 2019-12-15-22-04-41 +.. nonce: 8JnDTS +.. section: Documentation + +Add an entry for ``__module__`` in the "function" & "method" sections of the +`inspect docs types and members table +`_ + +.. + +.. bpo: 3530 +.. date: 2019-11-17-11-53-10 +.. nonce: 8zFUMc +.. section: Documentation + +In the :mod:`ast` module documentation, fix a misleading ``NodeTransformer`` +example and add advice on when to use the ``fix_missing_locations`` +function. + +.. + +.. bpo: 38546 +.. date: 2019-12-18-14-52-08 +.. nonce: 2kxNuM +.. section: Tests + +Fix test_ressources_gced_in_workers() of test_concurrent_futures: explicitly +stop the manager to prevent leaking a child process running in the +background after the test completes. + +.. + +.. bpo: 39144 +.. date: 2019-12-27-22-18-26 +.. nonce: dwHMlR +.. section: Build + +The ctags and etags build targets both include Modules/_ctypes and Python +standard library source files. + +.. + +.. bpo: 38597 +.. date: 2020-03-01-15-04-54 +.. nonce: MnHdYl +.. section: Windows + +:mod:`distutils` will no longer statically link :file:`vcruntime140.dll` +when a redistributable version is unavailable. All future releases of +CPython will include a copy of this DLL to ensure distributed extensions can +continue to load. + +.. + +.. bpo: 38380 +.. date: 2020-02-28-23-51-27 +.. nonce: TpOBCj +.. section: Windows + +Update Windows builds to use SQLite 3.31.1 + +.. + +.. bpo: 39439 +.. date: 2020-01-24-03-07-14 +.. nonce: rwMWDR +.. section: Windows + +Reduce overhead when using multiprocessing in a Windows virtual environment + +.. + +.. bpo: 39185 +.. date: 2020-01-02-01-11-53 +.. nonce: T4herN +.. section: Windows + +The build.bat script has additional options for very-quiet output (-q) and +very-verbose output (-vv) + +.. + +.. bpo: 38380 +.. date: 2020-02-28-23-51-47 +.. nonce: u-ySyA +.. section: macOS + +Update macOS builds to use SQLite 3.31.1 + +.. + +.. bpo: 39781 +.. date: 2020-02-27-22-17-09 +.. nonce: bbYBeL +.. section: IDLE + +Selecting code context lines no longer causes a jump. + +.. + +.. bpo: 39663 +.. date: 2020-02-17-21-09-03 +.. nonce: wexcsH +.. section: IDLE + +Add tests for pyparse find_good_parse_start(). + +.. + +.. bpo: 39600 +.. date: 2020-02-10-17-09-48 +.. nonce: X6NsyM +.. section: IDLE + +In the font configuration window, remove duplicated font names. + +.. + +.. bpo: 30780 +.. date: 2020-01-27-16-44-29 +.. nonce: nR80qu +.. section: IDLE + +Add remaining configdialog tests for buttons and highlights and keys tabs. + +.. + +.. bpo: 39388 +.. date: 2020-01-25-02-26-45 +.. nonce: x4TQNh +.. section: IDLE + +IDLE Settings Cancel button now cancels pending changes + +.. + +.. bpo: 39050 +.. date: 2020-01-22-22-28-06 +.. nonce: zkn0FO +.. section: IDLE + +Make IDLE Settings dialog Help button work again. + +.. + +.. bpo: 34118 +.. date: 2019-12-30-16-44-07 +.. nonce: FaNW0a +.. section: IDLE + +Tag memoryview, range, and tuple as classes, the same as list, etcetera, in +the library manual built-in functions list. + +.. + +.. bpo: 38792 +.. date: 2019-11-13-23-51-39 +.. nonce: xhTC5a +.. section: IDLE + +Close an IDLE shell calltip if a :exc:`KeyboardInterrupt` or shell restart +occurs. Patch by Zackery Spytz. + +.. + +.. bpo: 32989 +.. date: 2018-03-03-12-56-26 +.. nonce: FVhmhH +.. section: IDLE + +Add tests for editor newline_and_indent_event method. Remove dead code from +pyparse find_good_parse_start method. diff --git a/Misc/NEWS.d/next/Build/2019-12-27-22-18-26.bpo-39144.dwHMlR.rst b/Misc/NEWS.d/next/Build/2019-12-27-22-18-26.bpo-39144.dwHMlR.rst deleted file mode 100644 index 8b90da19622e6..0000000000000 --- a/Misc/NEWS.d/next/Build/2019-12-27-22-18-26.bpo-39144.dwHMlR.rst +++ /dev/null @@ -1 +0,0 @@ -The ctags and etags build targets both include Modules/_ctypes and Python standard library source files. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-10-31-14-30-39.bpo-38610.fHdVMS.rst b/Misc/NEWS.d/next/Core and Builtins/2019-10-31-14-30-39.bpo-38610.fHdVMS.rst deleted file mode 100644 index 0ee63bbb40dc6..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2019-10-31-14-30-39.bpo-38610.fHdVMS.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix possible crashes in several list methods by holding strong references to -list elements when calling :c:func:`PyObject_RichCompareBool`. diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-12-12-21-05-43.bpo-39031.imlCYZ.rst b/Misc/NEWS.d/next/Core and Builtins/2019-12-12-21-05-43.bpo-39031.imlCYZ.rst deleted file mode 100644 index 738902ce907ad..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2019-12-12-21-05-43.bpo-39031.imlCYZ.rst +++ /dev/null @@ -1,2 +0,0 @@ -When parsing an "elif" node, lineno and col_offset of the node now point to the "elif" keyword and not to its condition, making it consistent with the "if" node. -Patch by Lysandros Nikolaou. diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-12-29-19-13-54.bpo-38588.pgXnNS.rst b/Misc/NEWS.d/next/Core and Builtins/2019-12-29-19-13-54.bpo-38588.pgXnNS.rst deleted file mode 100644 index 0b81085a89d25..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2019-12-29-19-13-54.bpo-38588.pgXnNS.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix possible crashes in dict and list when calling -:c:func:`PyObject_RichCompareBool`. diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-01-20-21-40-57.bpo-39386.ULqD8t.rst b/Misc/NEWS.d/next/Core and Builtins/2020-01-20-21-40-57.bpo-39386.ULqD8t.rst deleted file mode 100644 index f24e1f4e8a183..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2020-01-20-21-40-57.bpo-39386.ULqD8t.rst +++ /dev/null @@ -1 +0,0 @@ -Prevent double awaiting of async iterator. diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-01-22-15-53-37.bpo-39421.O3nG7u.rst b/Misc/NEWS.d/next/Core and Builtins/2020-01-22-15-53-37.bpo-39421.O3nG7u.rst deleted file mode 100644 index bae008150ee12..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2020-01-22-15-53-37.bpo-39421.O3nG7u.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix possible crashes when operating with the functions in the :mod:`heapq` -module and custom comparison operators. diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-01-22-22-28-04.bpo-39427.LiO-Eo.rst b/Misc/NEWS.d/next/Core and Builtins/2020-01-22-22-28-04.bpo-39427.LiO-Eo.rst deleted file mode 100644 index a3915a4d81c79..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2020-01-22-22-28-04.bpo-39427.LiO-Eo.rst +++ /dev/null @@ -1,2 +0,0 @@ -Document all possibilities for the ``-X`` options in the command line help -section. Patch by Pablo Galindo. diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-01-25-23-51-17.bpo-39453.xCOkYk.rst b/Misc/NEWS.d/next/Core and Builtins/2020-01-25-23-51-17.bpo-39453.xCOkYk.rst deleted file mode 100644 index 8c2e49f9474c4..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2020-01-25-23-51-17.bpo-39453.xCOkYk.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed a possible crash in :meth:`list.__contains__` when a list is changed -during comparing items. Patch by Dong-hee Na. diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-02-04-10-27-41.bpo-39510.PMIh-f.rst b/Misc/NEWS.d/next/Core and Builtins/2020-02-04-10-27-41.bpo-39510.PMIh-f.rst deleted file mode 100644 index 9a38e4ab76228..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2020-02-04-10-27-41.bpo-39510.PMIh-f.rst +++ /dev/null @@ -1 +0,0 @@ -Fix segfault in ``readinto()`` method on closed BufferedReader. diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-02-11-23-59-07.bpo-39606.a72Sxc.rst b/Misc/NEWS.d/next/Core and Builtins/2020-02-11-23-59-07.bpo-39606.a72Sxc.rst deleted file mode 100644 index b7cbe4e91f59c..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2020-02-11-23-59-07.bpo-39606.a72Sxc.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix regression caused by fix for bpo-39386, that prevented calling -``aclose`` on an async generator that had already been closed or exhausted. diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-02-18-01-40-13.bpo-39382.OLSJu9.rst b/Misc/NEWS.d/next/Core and Builtins/2020-02-18-01-40-13.bpo-39382.OLSJu9.rst deleted file mode 100644 index 605f4c8e5dfd1..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2020-02-18-01-40-13.bpo-39382.OLSJu9.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix a use-after-free in the single inheritance path of ``issubclass()``, when -the ``__bases__`` of an object has a single reference, and so does its first item. -Patch by Yonatan Goldschmidt. diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-03-02-19-21-21.bpo-39778._YGLEc.rst b/Misc/NEWS.d/next/Core and Builtins/2020-03-02-19-21-21.bpo-39778._YGLEc.rst deleted file mode 100644 index dc49512167365..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2020-03-02-19-21-21.bpo-39778._YGLEc.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed a crash due to incorrect handling of weak references in -``collections.OrderedDict`` classes. Patch by Pablo Galindo. diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-03-02-20-12-33.bpo-39776.fNaxi_.rst b/Misc/NEWS.d/next/Core and Builtins/2020-03-02-20-12-33.bpo-39776.fNaxi_.rst deleted file mode 100644 index e5a00bd96ae47..0000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2020-03-02-20-12-33.bpo-39776.fNaxi_.rst +++ /dev/null @@ -1,6 +0,0 @@ -Fix race condition where threads created by PyGILState_Ensure() could get a -duplicate id. - -This affects consumers of tstate->id like the contextvar caching machinery, -which could return invalid cached objects under heavy thread load (observed -in embedded scenarios). diff --git a/Misc/NEWS.d/next/Documentation/2019-11-17-11-53-10.bpo-3530.8zFUMc.rst b/Misc/NEWS.d/next/Documentation/2019-11-17-11-53-10.bpo-3530.8zFUMc.rst deleted file mode 100644 index 65f1a6d156a12..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2019-11-17-11-53-10.bpo-3530.8zFUMc.rst +++ /dev/null @@ -1,2 +0,0 @@ -In the :mod:`ast` module documentation, fix a misleading ``NodeTransformer`` example and add -advice on when to use the ``fix_missing_locations`` function. diff --git a/Misc/NEWS.d/next/Documentation/2019-12-15-22-04-41.bpo-38918.8JnDTS.rst b/Misc/NEWS.d/next/Documentation/2019-12-15-22-04-41.bpo-38918.8JnDTS.rst deleted file mode 100644 index 5747936dd64d5..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2019-12-15-22-04-41.bpo-38918.8JnDTS.rst +++ /dev/null @@ -1,3 +0,0 @@ -Add an entry for ``__module__`` in the "function" & "method" sections of the -`inspect docs types and members table -`_ diff --git a/Misc/NEWS.d/next/Documentation/2020-01-18-15-37-56.bpo-39381.wTWe8d.rst b/Misc/NEWS.d/next/Documentation/2020-01-18-15-37-56.bpo-39381.wTWe8d.rst deleted file mode 100644 index 37b66ad9dfd17..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2020-01-18-15-37-56.bpo-39381.wTWe8d.rst +++ /dev/null @@ -1,2 +0,0 @@ -Mention in docs that :func:`asyncio.get_event_loop` implicitly creates new -event loop only if called from the main thread. diff --git a/Misc/NEWS.d/next/Documentation/2020-01-27-18-18-42.bpo-39392.oiqcLO.rst b/Misc/NEWS.d/next/Documentation/2020-01-27-18-18-42.bpo-39392.oiqcLO.rst deleted file mode 100644 index 715874981f735..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2020-01-27-18-18-42.bpo-39392.oiqcLO.rst +++ /dev/null @@ -1 +0,0 @@ -Explain that when filling with turtle, overlap regions may be left unfilled. diff --git a/Misc/NEWS.d/next/Documentation/2020-02-18-07-42-20.bpo-39654.MoT1jI.rst b/Misc/NEWS.d/next/Documentation/2020-02-18-07-42-20.bpo-39654.MoT1jI.rst deleted file mode 100644 index cff201d812476..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2020-02-18-07-42-20.bpo-39654.MoT1jI.rst +++ /dev/null @@ -1,2 +0,0 @@ -In pyclbr doc, update 'class' to 'module' where appropriate and add readmodule comment. -Patch by Hakan ?elik. diff --git a/Misc/NEWS.d/next/Documentation/2020-02-19-11-13-47.bpo-17422.g7_9zz.rst b/Misc/NEWS.d/next/Documentation/2020-02-19-11-13-47.bpo-17422.g7_9zz.rst deleted file mode 100644 index f071d286176ae..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2020-02-19-11-13-47.bpo-17422.g7_9zz.rst +++ /dev/null @@ -1 +0,0 @@ -The language reference now specifies restrictions on class namespaces. Adapted from a patch by Ethan Furman. diff --git a/Misc/NEWS.d/next/Documentation/2020-02-23-13-26-40.bpo-39530._bCvzQ.rst b/Misc/NEWS.d/next/Documentation/2020-02-23-13-26-40.bpo-39530._bCvzQ.rst deleted file mode 100644 index b7a02522bbb1c..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2020-02-23-13-26-40.bpo-39530._bCvzQ.rst +++ /dev/null @@ -1 +0,0 @@ -Fix misleading documentation about mixed-type numeric comparisons. diff --git a/Misc/NEWS.d/next/Documentation/2020-02-28-14-39-25.bpo-13790.hvLaRI.rst b/Misc/NEWS.d/next/Documentation/2020-02-28-14-39-25.bpo-13790.hvLaRI.rst deleted file mode 100644 index 77db173168fc5..0000000000000 --- a/Misc/NEWS.d/next/Documentation/2020-02-28-14-39-25.bpo-13790.hvLaRI.rst +++ /dev/null @@ -1 +0,0 @@ -Change 'string' to 'specification' in format doc. diff --git a/Misc/NEWS.d/next/IDLE/2018-03-03-12-56-26.bpo-32989.FVhmhH.rst b/Misc/NEWS.d/next/IDLE/2018-03-03-12-56-26.bpo-32989.FVhmhH.rst deleted file mode 100644 index 38f0fb6e10452..0000000000000 --- a/Misc/NEWS.d/next/IDLE/2018-03-03-12-56-26.bpo-32989.FVhmhH.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add tests for editor newline_and_indent_event method. -Remove dead code from pyparse find_good_parse_start method. diff --git a/Misc/NEWS.d/next/IDLE/2019-11-13-23-51-39.bpo-38792.xhTC5a.rst b/Misc/NEWS.d/next/IDLE/2019-11-13-23-51-39.bpo-38792.xhTC5a.rst deleted file mode 100644 index 9aa2f0ffddfaf..0000000000000 --- a/Misc/NEWS.d/next/IDLE/2019-11-13-23-51-39.bpo-38792.xhTC5a.rst +++ /dev/null @@ -1,2 +0,0 @@ -Close an IDLE shell calltip if a :exc:`KeyboardInterrupt` -or shell restart occurs. Patch by Zackery Spytz. diff --git a/Misc/NEWS.d/next/IDLE/2019-12-30-16-44-07.bpo-34118.FaNW0a.rst b/Misc/NEWS.d/next/IDLE/2019-12-30-16-44-07.bpo-34118.FaNW0a.rst deleted file mode 100644 index ce95eb5482f2b..0000000000000 --- a/Misc/NEWS.d/next/IDLE/2019-12-30-16-44-07.bpo-34118.FaNW0a.rst +++ /dev/null @@ -1,2 +0,0 @@ -Tag memoryview, range, and tuple as classes, the same as list, etcetera, in -the library manual built-in functions list. diff --git a/Misc/NEWS.d/next/IDLE/2020-01-22-22-28-06.bpo-39050.zkn0FO.rst b/Misc/NEWS.d/next/IDLE/2020-01-22-22-28-06.bpo-39050.zkn0FO.rst deleted file mode 100644 index e71265cdf109b..0000000000000 --- a/Misc/NEWS.d/next/IDLE/2020-01-22-22-28-06.bpo-39050.zkn0FO.rst +++ /dev/null @@ -1 +0,0 @@ -Make IDLE Settings dialog Help button work again. diff --git a/Misc/NEWS.d/next/IDLE/2020-01-25-02-26-45.bpo-39388.x4TQNh.rst b/Misc/NEWS.d/next/IDLE/2020-01-25-02-26-45.bpo-39388.x4TQNh.rst deleted file mode 100644 index 42bbfb168c19d..0000000000000 --- a/Misc/NEWS.d/next/IDLE/2020-01-25-02-26-45.bpo-39388.x4TQNh.rst +++ /dev/null @@ -1 +0,0 @@ -IDLE Settings Cancel button now cancels pending changes diff --git a/Misc/NEWS.d/next/IDLE/2020-01-27-16-44-29.bpo-30780.nR80qu.rst b/Misc/NEWS.d/next/IDLE/2020-01-27-16-44-29.bpo-30780.nR80qu.rst deleted file mode 100644 index 2f65a00a5af3b..0000000000000 --- a/Misc/NEWS.d/next/IDLE/2020-01-27-16-44-29.bpo-30780.nR80qu.rst +++ /dev/null @@ -1 +0,0 @@ -Add remaining configdialog tests for buttons and highlights and keys tabs. diff --git a/Misc/NEWS.d/next/IDLE/2020-02-10-17-09-48.bpo-39600.X6NsyM.rst b/Misc/NEWS.d/next/IDLE/2020-02-10-17-09-48.bpo-39600.X6NsyM.rst deleted file mode 100644 index 102aa75f5813e..0000000000000 --- a/Misc/NEWS.d/next/IDLE/2020-02-10-17-09-48.bpo-39600.X6NsyM.rst +++ /dev/null @@ -1 +0,0 @@ -In the font configuration window, remove duplicated font names. diff --git a/Misc/NEWS.d/next/IDLE/2020-02-17-21-09-03.bpo-39663.wexcsH.rst b/Misc/NEWS.d/next/IDLE/2020-02-17-21-09-03.bpo-39663.wexcsH.rst deleted file mode 100644 index 19e16329ce0a0..0000000000000 --- a/Misc/NEWS.d/next/IDLE/2020-02-17-21-09-03.bpo-39663.wexcsH.rst +++ /dev/null @@ -1 +0,0 @@ -Add tests for pyparse find_good_parse_start(). diff --git a/Misc/NEWS.d/next/IDLE/2020-02-27-22-17-09.bpo-39781.bbYBeL.rst b/Misc/NEWS.d/next/IDLE/2020-02-27-22-17-09.bpo-39781.bbYBeL.rst deleted file mode 100644 index 4ae0defc2e217..0000000000000 --- a/Misc/NEWS.d/next/IDLE/2020-02-27-22-17-09.bpo-39781.bbYBeL.rst +++ /dev/null @@ -1 +0,0 @@ -Selecting code context lines no longer causes a jump. diff --git a/Misc/NEWS.d/next/Library/2019-03-24-12-12-27.bpo-36406.mCEkOl.rst b/Misc/NEWS.d/next/Library/2019-03-24-12-12-27.bpo-36406.mCEkOl.rst deleted file mode 100644 index 3d81eb50418b0..0000000000000 --- a/Misc/NEWS.d/next/Library/2019-03-24-12-12-27.bpo-36406.mCEkOl.rst +++ /dev/null @@ -1 +0,0 @@ -Handle namespace packages in :mod:`doctest`. Patch by Karthikeyan Singaravelan. diff --git a/Misc/NEWS.d/next/Library/2019-09-06-17-40-34.bpo-37953.db5FQq.rst b/Misc/NEWS.d/next/Library/2019-09-06-17-40-34.bpo-37953.db5FQq.rst deleted file mode 100644 index 4eff4f7479aad..0000000000000 --- a/Misc/NEWS.d/next/Library/2019-09-06-17-40-34.bpo-37953.db5FQq.rst +++ /dev/null @@ -1,2 +0,0 @@ -In :mod:`typing`, improved the ``__hash__`` and ``__eq__`` methods for -:class:`ForwardReferences`. diff --git a/Misc/NEWS.d/next/Library/2019-09-29-08-17-03.bpo-38293.wls5s3.rst b/Misc/NEWS.d/next/Library/2019-09-29-08-17-03.bpo-38293.wls5s3.rst deleted file mode 100644 index 0b19551970eb0..0000000000000 --- a/Misc/NEWS.d/next/Library/2019-09-29-08-17-03.bpo-38293.wls5s3.rst +++ /dev/null @@ -1 +0,0 @@ -Add :func:`copy.copy` and :func:`copy.deepcopy` support to :func:`property` objects. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2019-10-14-21-14-55.bpo-38473.uXpVld.rst b/Misc/NEWS.d/next/Library/2019-10-14-21-14-55.bpo-38473.uXpVld.rst deleted file mode 100644 index de80e89e00e2d..0000000000000 --- a/Misc/NEWS.d/next/Library/2019-10-14-21-14-55.bpo-38473.uXpVld.rst +++ /dev/null @@ -1,2 +0,0 @@ -Use signature from inner mock for autospecced methods attached with -:func:`unittest.mock.attach_mock`. Patch by Karthikeyan Singaravelan. diff --git a/Misc/NEWS.d/next/Library/2019-10-31-19-23-25.bpo-35182.hzeNl9.rst b/Misc/NEWS.d/next/Library/2019-10-31-19-23-25.bpo-35182.hzeNl9.rst deleted file mode 100644 index 9438cd8f9fd0b..0000000000000 --- a/Misc/NEWS.d/next/Library/2019-10-31-19-23-25.bpo-35182.hzeNl9.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fixed :func:`Popen.communicate` subsequent call crash when the child process -has already closed any piped standard stream, but still continues to be -running. Patch by Andriy Maletsky. diff --git a/Misc/NEWS.d/next/Library/2019-11-22-12-08-52.bpo-38878.EJ0cFf.rst b/Misc/NEWS.d/next/Library/2019-11-22-12-08-52.bpo-38878.EJ0cFf.rst deleted file mode 100644 index 9cbdf08dd53e3..0000000000000 --- a/Misc/NEWS.d/next/Library/2019-11-22-12-08-52.bpo-38878.EJ0cFf.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed __subclasshook__ of :class:`os.PathLike` to return a correct result -upon inheritence. Patch by Bar Harel. diff --git a/Misc/NEWS.d/next/Library/2019-12-15-19-23-23.bpo-39055.FmN3un.rst b/Misc/NEWS.d/next/Library/2019-12-15-19-23-23.bpo-39055.FmN3un.rst deleted file mode 100644 index 83b1431e92fcb..0000000000000 --- a/Misc/NEWS.d/next/Library/2019-12-15-19-23-23.bpo-39055.FmN3un.rst +++ /dev/null @@ -1,2 +0,0 @@ -:func:`base64.b64decode` with ``validate=True`` raises now a binascii.Error -if the input ends with a single ``\n``. diff --git a/Misc/NEWS.d/next/Library/2019-12-15-21-05-16.bpo-39056.nEfUM9.rst b/Misc/NEWS.d/next/Library/2019-12-15-21-05-16.bpo-39056.nEfUM9.rst deleted file mode 100644 index d5d2b98e9b0b3..0000000000000 --- a/Misc/NEWS.d/next/Library/2019-12-15-21-05-16.bpo-39056.nEfUM9.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed handling invalid warning category in the -W option. No longer import -the re module if it is not needed. diff --git a/Misc/NEWS.d/next/Library/2019-12-15-21-47-54.bpo-39057.FOxn-w.rst b/Misc/NEWS.d/next/Library/2019-12-15-21-47-54.bpo-39057.FOxn-w.rst deleted file mode 100644 index 24a17444b97da..0000000000000 --- a/Misc/NEWS.d/next/Library/2019-12-15-21-47-54.bpo-39057.FOxn-w.rst +++ /dev/null @@ -1,2 +0,0 @@ -:func:`urllib.request.proxy_bypass_environment` now ignores leading dots and -no longer ignores a trailing newline. diff --git a/Misc/NEWS.d/next/Library/2019-12-20-16-06-28.bpo-38971.fKRYlF.rst b/Misc/NEWS.d/next/Library/2019-12-20-16-06-28.bpo-38971.fKRYlF.rst deleted file mode 100644 index 9676d72b44abc..0000000000000 --- a/Misc/NEWS.d/next/Library/2019-12-20-16-06-28.bpo-38971.fKRYlF.rst +++ /dev/null @@ -1,3 +0,0 @@ -Open issue in the BPO indicated a desire to make the implementation of -codecs.open() at parity with io.open(), which implements a try/except to -assure file stream gets closed before an exception is raised. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2019-12-31-19-27-23.bpo-39142.oqU5iD.rst b/Misc/NEWS.d/next/Library/2019-12-31-19-27-23.bpo-39142.oqU5iD.rst deleted file mode 100644 index 508d1338d7c31..0000000000000 --- a/Misc/NEWS.d/next/Library/2019-12-31-19-27-23.bpo-39142.oqU5iD.rst +++ /dev/null @@ -1,5 +0,0 @@ -A change was made to logging.config.dictConfig to avoid converting instances -of named tuples to ConvertingTuple. It's assumed that named tuples are too -specialised to be treated like ordinary tuples; if a user of named tuples -requires ConvertingTuple functionality, they will have to implement that -themselves in their named tuple class. diff --git a/Misc/NEWS.d/next/Library/2020-01-01-18-44-52.bpo-38871.3EEOLg.rst b/Misc/NEWS.d/next/Library/2020-01-01-18-44-52.bpo-38871.3EEOLg.rst deleted file mode 100644 index fe970fd9e3fa1..0000000000000 --- a/Misc/NEWS.d/next/Library/2020-01-01-18-44-52.bpo-38871.3EEOLg.rst +++ /dev/null @@ -1,2 +0,0 @@ -Correctly parenthesize filter-based statements that contain lambda -expressions in mod:`lib2to3`. Patch by Dong-hee Na. diff --git a/Misc/NEWS.d/next/Library/2020-01-02-17-28-03.bpo-39191.ur_scy.rst b/Misc/NEWS.d/next/Library/2020-01-02-17-28-03.bpo-39191.ur_scy.rst deleted file mode 100644 index 138c93c2e4877..0000000000000 --- a/Misc/NEWS.d/next/Library/2020-01-02-17-28-03.bpo-39191.ur_scy.rst +++ /dev/null @@ -1,3 +0,0 @@ -Perform a check for running loop before starting a new task in -``loop.run_until_complete()`` to fail fast; it prevents the side effect of -new task spawning before exception raising. diff --git a/Misc/NEWS.d/next/Library/2020-01-02-20-21-03.bpo-39198.nzwGyG.rst b/Misc/NEWS.d/next/Library/2020-01-02-20-21-03.bpo-39198.nzwGyG.rst deleted file mode 100644 index ec4e81e2bbe4a..0000000000000 --- a/Misc/NEWS.d/next/Library/2020-01-02-20-21-03.bpo-39198.nzwGyG.rst +++ /dev/null @@ -1 +0,0 @@ -If an exception were to be thrown in `Logger.isEnabledFor` (say, by asyncio timeouts or stopit) , the `logging` global lock may not be released appropriately, resulting in deadlock. This change wraps that block of code with `try...finally` to ensure the lock is released. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2020-01-03-18-02-50.bpo-39152.JgPjCC.rst b/Misc/NEWS.d/next/Library/2020-01-03-18-02-50.bpo-39152.JgPjCC.rst deleted file mode 100644 index abb3df0da0fe4..0000000000000 --- a/Misc/NEWS.d/next/Library/2020-01-03-18-02-50.bpo-39152.JgPjCC.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix ttk.Scale.configure([name]) to return configuration tuple for name -or all options. Giovanni Lombardo contributed part of the patch. diff --git a/Misc/NEWS.d/next/Library/2020-01-08-23-25-27.bpo-39242.bnL65N.rst b/Misc/NEWS.d/next/Library/2020-01-08-23-25-27.bpo-39242.bnL65N.rst deleted file mode 100644 index a87dddf81dcd5..0000000000000 --- a/Misc/NEWS.d/next/Library/2020-01-08-23-25-27.bpo-39242.bnL65N.rst +++ /dev/null @@ -1,3 +0,0 @@ -Updated the Gmane domain from news.gmane.org to news.gmane.io -which is used for examples of :class:`~nntplib.NNTP` news reader server and -nntplib tests. diff --git a/Misc/NEWS.d/next/Library/2020-01-15-23-13-03.bpo-39274.lpc0-n.rst b/Misc/NEWS.d/next/Library/2020-01-15-23-13-03.bpo-39274.lpc0-n.rst deleted file mode 100644 index 4c398682b98ab..0000000000000 --- a/Misc/NEWS.d/next/Library/2020-01-15-23-13-03.bpo-39274.lpc0-n.rst +++ /dev/null @@ -1 +0,0 @@ -``bool(fraction.Fraction)`` now returns a boolean even if (numerator != 0) does not return a boolean (ex: numpy number). diff --git a/Misc/NEWS.d/next/Library/2020-01-20-00-56-01.bpo-39389.fEirIS.rst b/Misc/NEWS.d/next/Library/2020-01-20-00-56-01.bpo-39389.fEirIS.rst deleted file mode 100644 index d4c80506f7d6b..0000000000000 --- a/Misc/NEWS.d/next/Library/2020-01-20-00-56-01.bpo-39389.fEirIS.rst +++ /dev/null @@ -1,2 +0,0 @@ -Write accurate compression level metadata in :mod:`gzip` archives, rather -than always signaling maximum compression. diff --git a/Misc/NEWS.d/next/Library/2020-01-24-11-05-21.bpo-39430.I0UQzM.rst b/Misc/NEWS.d/next/Library/2020-01-24-11-05-21.bpo-39430.I0UQzM.rst deleted file mode 100644 index 712fc5d34bbe0..0000000000000 --- a/Misc/NEWS.d/next/Library/2020-01-24-11-05-21.bpo-39430.I0UQzM.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed race condition in lazy imports in :mod:`tarfile`. diff --git a/Misc/NEWS.d/next/Library/2020-01-29-14-58-27.bpo-39485.Zy3ot6.rst b/Misc/NEWS.d/next/Library/2020-01-29-14-58-27.bpo-39485.Zy3ot6.rst deleted file mode 100644 index f62c31fc686ad..0000000000000 --- a/Misc/NEWS.d/next/Library/2020-01-29-14-58-27.bpo-39485.Zy3ot6.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix a bug in :func:`unittest.mock.create_autospec` that would complain about -the wrong number of arguments for custom descriptors defined in an extension -module returning functions. diff --git a/Misc/NEWS.d/next/Library/2020-01-30-01-13-19.bpo-39493.CbFRi7.rst b/Misc/NEWS.d/next/Library/2020-01-30-01-13-19.bpo-39493.CbFRi7.rst deleted file mode 100644 index b676629a4414a..0000000000000 --- a/Misc/NEWS.d/next/Library/2020-01-30-01-13-19.bpo-39493.CbFRi7.rst +++ /dev/null @@ -1 +0,0 @@ -Mark ``typing.IO.closed`` as a property \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2020-02-02-14-46-34.bpo-39450.48R274.rst b/Misc/NEWS.d/next/Library/2020-02-02-14-46-34.bpo-39450.48R274.rst deleted file mode 100644 index 55fed519a2d80..0000000000000 --- a/Misc/NEWS.d/next/Library/2020-02-02-14-46-34.bpo-39450.48R274.rst +++ /dev/null @@ -1,2 +0,0 @@ -Striped whitespace from docstring before returning it from -:func:`unittest.case.shortDescription`. diff --git a/Misc/NEWS.d/next/Library/2020-02-06-05-33-52.bpo-39548.DF4FFe.rst b/Misc/NEWS.d/next/Library/2020-02-06-05-33-52.bpo-39548.DF4FFe.rst deleted file mode 100644 index 4cf32487b1f7a..0000000000000 --- a/Misc/NEWS.d/next/Library/2020-02-06-05-33-52.bpo-39548.DF4FFe.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix handling of header in :class:`urllib.request.AbstractDigestAuthHandler` when the optional ``qop`` parameter -is not present. diff --git a/Misc/NEWS.d/next/Library/2020-02-12-10-04-39.bpo-21016.bFXPH7.rst b/Misc/NEWS.d/next/Library/2020-02-12-10-04-39.bpo-21016.bFXPH7.rst deleted file mode 100644 index fb91bb3825555..0000000000000 --- a/Misc/NEWS.d/next/Library/2020-02-12-10-04-39.bpo-21016.bFXPH7.rst +++ /dev/null @@ -1,4 +0,0 @@ -The :mod:`pydoc` and :mod:`trace` modules now use the :mod:`sysconfig` -module to get the path to the Python standard library, to support uncommon -installation path like ``/usr/lib64/python3.9/`` on Fedora. -Patch by Jan Mat?jek. diff --git a/Misc/NEWS.d/next/Library/2020-02-16-07-47-55.bpo-27657.9kZchc.rst b/Misc/NEWS.d/next/Library/2020-02-16-07-47-55.bpo-27657.9kZchc.rst deleted file mode 100644 index 2a0aca855c2ba..0000000000000 --- a/Misc/NEWS.d/next/Library/2020-02-16-07-47-55.bpo-27657.9kZchc.rst +++ /dev/null @@ -1,5 +0,0 @@ -The original fix for bpo-27657, "Fix urlparse() with numeric paths" (GH-16839) -included in 3.7.6, inadvertently introduced a behavior change that broke -several third-party packages relying on the original undefined parsing -behavior. The change is reverted in 3.7.7, restoring the behavior of 3.7.5 and -earlier releases. diff --git a/Misc/NEWS.d/next/Library/2020-02-23-21-27-10.bpo-39649.qiubSp.rst b/Misc/NEWS.d/next/Library/2020-02-23-21-27-10.bpo-39649.qiubSp.rst deleted file mode 100644 index 5a88f79f05f0e..0000000000000 --- a/Misc/NEWS.d/next/Library/2020-02-23-21-27-10.bpo-39649.qiubSp.rst +++ /dev/null @@ -1 +0,0 @@ -Remove obsolete check for `__args__` in bdb.Bdb.format_stack_entry. diff --git a/Misc/NEWS.d/next/Library/2020-02-24-03-45-28.bpo-30566.qROxty.rst b/Misc/NEWS.d/next/Library/2020-02-24-03-45-28.bpo-30566.qROxty.rst deleted file mode 100644 index c780633030090..0000000000000 --- a/Misc/NEWS.d/next/Library/2020-02-24-03-45-28.bpo-30566.qROxty.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix :exc:`IndexError` when trying to decode an invalid string with punycode -codec. diff --git a/Misc/NEWS.d/next/Library/2020-02-29-13-20-33.bpo-39769.hJmxu4.rst b/Misc/NEWS.d/next/Library/2020-02-29-13-20-33.bpo-39769.hJmxu4.rst deleted file mode 100644 index 9b564bd10d3b3..0000000000000 --- a/Misc/NEWS.d/next/Library/2020-02-29-13-20-33.bpo-39769.hJmxu4.rst +++ /dev/null @@ -1,4 +0,0 @@ -The :func:`compileall.compile_dir` function's *ddir* parameter and the -compileall command line flag `-d` no longer write the wrong pathname to the -generated pyc file for submodules beneath the root of the directory tree -being compiled. This fixes a regression introduced with Python 3.5. diff --git a/Misc/NEWS.d/next/Library/2020-02-29-19-17-39.bpo-39794.7VjatS.rst b/Misc/NEWS.d/next/Library/2020-02-29-19-17-39.bpo-39794.7VjatS.rst deleted file mode 100644 index b2a4726068af9..0000000000000 --- a/Misc/NEWS.d/next/Library/2020-02-29-19-17-39.bpo-39794.7VjatS.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add --without-decimal-contextvar build option. This enables a thread-local -rather than a coroutine local context. diff --git a/Misc/NEWS.d/next/Security/2020-01-28-20-54-09.bpo-39401.he7h_A.rst b/Misc/NEWS.d/next/Security/2020-01-28-20-54-09.bpo-39401.he7h_A.rst deleted file mode 100644 index 5071e126b70d0..0000000000000 --- a/Misc/NEWS.d/next/Security/2020-01-28-20-54-09.bpo-39401.he7h_A.rst +++ /dev/null @@ -1 +0,0 @@ -Avoid unsafe load of ``api-ms-win-core-path-l1-1-0.dll`` at startup on Windows 7. diff --git a/Misc/NEWS.d/next/Tests/2019-12-18-14-52-08.bpo-38546.2kxNuM.rst b/Misc/NEWS.d/next/Tests/2019-12-18-14-52-08.bpo-38546.2kxNuM.rst deleted file mode 100644 index d8ec7cabbbab8..0000000000000 --- a/Misc/NEWS.d/next/Tests/2019-12-18-14-52-08.bpo-38546.2kxNuM.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix test_ressources_gced_in_workers() of test_concurrent_futures: explicitly -stop the manager to prevent leaking a child process running in the background -after the test completes. diff --git a/Misc/NEWS.d/next/Windows/2020-01-02-01-11-53.bpo-39185.T4herN.rst b/Misc/NEWS.d/next/Windows/2020-01-02-01-11-53.bpo-39185.T4herN.rst deleted file mode 100644 index 3b84bd5217264..0000000000000 --- a/Misc/NEWS.d/next/Windows/2020-01-02-01-11-53.bpo-39185.T4herN.rst +++ /dev/null @@ -1 +0,0 @@ -The build.bat script has additional options for very-quiet output (-q) and very-verbose output (-vv) \ No newline at end of file diff --git a/Misc/NEWS.d/next/Windows/2020-01-24-03-07-14.bpo-39439.rwMWDR.rst b/Misc/NEWS.d/next/Windows/2020-01-24-03-07-14.bpo-39439.rwMWDR.rst deleted file mode 100644 index d64e63757728a..0000000000000 --- a/Misc/NEWS.d/next/Windows/2020-01-24-03-07-14.bpo-39439.rwMWDR.rst +++ /dev/null @@ -1 +0,0 @@ -Reduce overhead when using multiprocessing in a Windows virtual environment \ No newline at end of file diff --git a/Misc/NEWS.d/next/Windows/2020-02-28-23-51-27.bpo-38380.TpOBCj.rst b/Misc/NEWS.d/next/Windows/2020-02-28-23-51-27.bpo-38380.TpOBCj.rst deleted file mode 100644 index 521075d628f42..0000000000000 --- a/Misc/NEWS.d/next/Windows/2020-02-28-23-51-27.bpo-38380.TpOBCj.rst +++ /dev/null @@ -1 +0,0 @@ -Update Windows builds to use SQLite 3.31.1 diff --git a/Misc/NEWS.d/next/Windows/2020-03-01-15-04-54.bpo-38597.MnHdYl.rst b/Misc/NEWS.d/next/Windows/2020-03-01-15-04-54.bpo-38597.MnHdYl.rst deleted file mode 100644 index 7f3a2e756c5a1..0000000000000 --- a/Misc/NEWS.d/next/Windows/2020-03-01-15-04-54.bpo-38597.MnHdYl.rst +++ /dev/null @@ -1,4 +0,0 @@ -:mod:`distutils` will no longer statically link :file:`vcruntime140.dll` -when a redistributable version is unavailable. All future releases of -CPython will include a copy of this DLL to ensure distributed extensions can -continue to load. diff --git a/Misc/NEWS.d/next/macOS/2020-02-28-23-51-47.bpo-38380.u-ySyA.rst b/Misc/NEWS.d/next/macOS/2020-02-28-23-51-47.bpo-38380.u-ySyA.rst deleted file mode 100644 index 908281b5d172f..0000000000000 --- a/Misc/NEWS.d/next/macOS/2020-02-28-23-51-47.bpo-38380.u-ySyA.rst +++ /dev/null @@ -1 +0,0 @@ -Update macOS builds to use SQLite 3.31.1 diff --git a/README.rst b/README.rst index 886b5829d92c1..28032cb6d4307 100644 --- a/README.rst +++ b/README.rst @@ -1,5 +1,5 @@ -This is Python version 3.7.6+ -============================= +This is Python version 3.7.7 candidate 1 +======================================== .. image:: https://travis-ci.org/python/cpython.svg?branch=3.7 :alt: CPython build status on Travis CI From webhook-mailer at python.org Wed Mar 4 05:49:56 2020 From: webhook-mailer at python.org (l0rb) Date: Wed, 04 Mar 2020 10:49:56 -0000 Subject: [Python-checkins] bpo-39826: add getConnection() hook to logging HTTPHandler (GH-18745) Message-ID: https://github.com/python/cpython/commit/22a9a546ff3bf2a63d77ca1e5494e758bc59132f commit: 22a9a546ff3bf2a63d77ca1e5494e758bc59132f branch: master author: l0rb committer: GitHub date: 2020-03-04T10:49:51Z summary: bpo-39826: add getConnection() hook to logging HTTPHandler (GH-18745) files: A Misc/NEWS.d/next/Library/2020-03-02-15-15-01.bpo-39826.DglHk7.rst M Lib/logging/handlers.py diff --git a/Lib/logging/handlers.py b/Lib/logging/handlers.py index 047798f6dc145..4a120e9f1ec48 100644 --- a/Lib/logging/handlers.py +++ b/Lib/logging/handlers.py @@ -1173,6 +1173,20 @@ def mapLogRecord(self, record): """ return record.__dict__ + def getConnection(self, host, secure): + """ + get a HTTP[S]Connection. + + Override when a custom connection is required, for example if + there is a proxy. + """ + import http.client + if secure: + connection = http.client.HTTPSConnection(host, context=self.context) + else: + connection = http.client.HTTPConnection(host) + return connection + def emit(self, record): """ Emit a record. @@ -1180,12 +1194,9 @@ def emit(self, record): Send the record to the Web server as a percent-encoded dictionary """ try: - import http.client, urllib.parse + import urllib.parse host = self.host - if self.secure: - h = http.client.HTTPSConnection(host, context=self.context) - else: - h = http.client.HTTPConnection(host) + h = self.getConnection(host, self.secure) url = self.url data = urllib.parse.urlencode(self.mapLogRecord(record)) if self.method == "GET": diff --git a/Misc/NEWS.d/next/Library/2020-03-02-15-15-01.bpo-39826.DglHk7.rst b/Misc/NEWS.d/next/Library/2020-03-02-15-15-01.bpo-39826.DglHk7.rst new file mode 100644 index 0000000000000..e425bbe2d5110 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-03-02-15-15-01.bpo-39826.DglHk7.rst @@ -0,0 +1 @@ +Add getConnection method to logging HTTPHandler to enable custom connections. \ No newline at end of file From webhook-mailer at python.org Wed Mar 4 06:53:01 2020 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 04 Mar 2020 11:53:01 -0000 Subject: [Python-checkins] Fix misleading statement about mixed-type numeric comparisons (GH-18615) (#18773) Message-ID: https://github.com/python/cpython/commit/6c8cc0dbfd69984a4e8381388704dc78261e1d59 commit: 6c8cc0dbfd69984a4e8381388704dc78261e1d59 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2020-03-04T11:52:56Z summary: Fix misleading statement about mixed-type numeric comparisons (GH-18615) (#18773) (cherry picked from commit 9f1cb1bb49476246de5d9ed5fe680301cf7f7571) Co-authored-by: Mark Dickinson Co-authored-by: Mark Dickinson files: A Misc/NEWS.d/next/Documentation/2020-02-23-13-26-40.bpo-39530._bCvzQ.rst M Doc/library/stdtypes.rst diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index d369b38b31bc9..8cc57c30c322c 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -261,8 +261,10 @@ and imaginary parts. Python fully supports mixed arithmetic: when a binary arithmetic operator has operands of different numeric types, the operand with the "narrower" type is widened to that of the other, where integer is narrower than floating point, -which is narrower than complex. Comparisons between numbers of mixed type use -the same rule. [2]_ The constructors :func:`int`, :func:`float`, and +which is narrower than complex. A comparison between numbers of different types +behaves as though the exact values of those numbers were being compared. [2]_ + +The constructors :func:`int`, :func:`float`, and :func:`complex` can be used to produce numbers of a specific type. All numeric types (except complex) support the following operations (for priorities of diff --git a/Misc/NEWS.d/next/Documentation/2020-02-23-13-26-40.bpo-39530._bCvzQ.rst b/Misc/NEWS.d/next/Documentation/2020-02-23-13-26-40.bpo-39530._bCvzQ.rst new file mode 100644 index 0000000000000..b7a02522bbb1c --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2020-02-23-13-26-40.bpo-39530._bCvzQ.rst @@ -0,0 +1 @@ +Fix misleading documentation about mixed-type numeric comparisons. From webhook-mailer at python.org Wed Mar 4 08:15:31 2020 From: webhook-mailer at python.org (Andy Lester) Date: Wed, 04 Mar 2020 13:15:31 -0000 Subject: [Python-checkins] bpo-39573: Finish converting to new Py_IS_TYPE() macro (GH-18601) Message-ID: https://github.com/python/cpython/commit/dffe4c07095e0c693e094d3c140e85a68bd8128e commit: dffe4c07095e0c693e094d3c140e85a68bd8128e branch: master author: Andy Lester committer: GitHub date: 2020-03-04T14:15:20+01:00 summary: bpo-39573: Finish converting to new Py_IS_TYPE() macro (GH-18601) files: M Include/py_curses.h M Modules/_asynciomodule.c M Modules/_collectionsmodule.c M Modules/_elementtree.c M Modules/_io/bufferedio.c M Modules/_io/stringio.c M Modules/_io/textio.c M Modules/_pickle.c M Modules/_threadmodule.c M Modules/cjkcodecs/multibytecodec.h M Modules/itertoolsmodule.c M Objects/abstract.c M Objects/descrobject.c M Objects/exceptions.c M Objects/genobject.c M Objects/listobject.c M Objects/namespaceobject.c M Objects/tupleobject.c M Objects/typeobject.c M Objects/unicodeobject.c M Python/ceval.c M Python/errors.c M Python/importdl.c diff --git a/Include/py_curses.h b/Include/py_curses.h index 2702b37ea7cfe..b70252d9d7605 100644 --- a/Include/py_curses.h +++ b/Include/py_curses.h @@ -64,7 +64,7 @@ typedef struct { char *encoding; } PyCursesWindowObject; -#define PyCursesWindow_Check(v) (Py_TYPE(v) == &PyCursesWindow_Type) +#define PyCursesWindow_Check(v) Py_IS_TYPE(v, &PyCursesWindow_Type) #define PyCurses_CAPSULE_NAME "_curses._C_API" @@ -97,4 +97,3 @@ static const char catchall_NULL[] = "curses function returned NULL"; #endif /* !defined(Py_CURSES_H) */ - diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 56743301d9eef..d394002c06579 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -572,7 +572,7 @@ future_set_exception(FutureObj *fut, PyObject *exc) PyErr_SetString(PyExc_TypeError, "invalid exception object"); return NULL; } - if ((PyObject*)Py_TYPE(exc_val) == PyExc_StopIteration) { + if (Py_IS_TYPE(exc_val, (PyTypeObject *)PyExc_StopIteration)) { Py_DECREF(exc_val); PyErr_SetString(PyExc_TypeError, "StopIteration interacts badly with generators " diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c index 057d40441835c..4d5d874b44da1 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -489,7 +489,7 @@ deque_copy(PyObject *deque, PyObject *Py_UNUSED(ignored)) { PyObject *result; dequeobject *old_deque = (dequeobject *)deque; - if (Py_TYPE(deque) == &deque_type) { + if (Py_IS_TYPE(deque, &deque_type)) { dequeobject *new_deque; PyObject *rv; diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c index c0f771f7d9305..cc06824571351 100644 --- a/Modules/_elementtree.c +++ b/Modules/_elementtree.c @@ -2366,7 +2366,7 @@ typedef struct { char insert_pis; } TreeBuilderObject; -#define TreeBuilder_CheckExact(op) (Py_TYPE(op) == &TreeBuilder_Type) +#define TreeBuilder_CheckExact(op) Py_IS_TYPE((op), &TreeBuilder_Type) /* -------------------------------------------------------------------- */ /* constructor and destructor */ diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index a09082c84f8a2..f2d0467a3f32d 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -1449,8 +1449,8 @@ _io_BufferedReader___init___impl(buffered *self, PyObject *raw, return -1; _bufferedreader_reset_buf(self); - self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedReader_Type && - Py_TYPE(raw) == &PyFileIO_Type); + self->fast_closed_checks = (Py_IS_TYPE(self, &PyBufferedReader_Type) && + Py_IS_TYPE(raw, &PyFileIO_Type)); self->ok = 1; return 0; @@ -1795,8 +1795,8 @@ _io_BufferedWriter___init___impl(buffered *self, PyObject *raw, _bufferedwriter_reset_buf(self); self->pos = 0; - self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedWriter_Type && - Py_TYPE(raw) == &PyFileIO_Type); + self->fast_closed_checks = (Py_IS_TYPE(self, &PyBufferedWriter_Type) && + Py_IS_TYPE(raw, &PyFileIO_Type)); self->ok = 1; return 0; @@ -2309,8 +2309,8 @@ _io_BufferedRandom___init___impl(buffered *self, PyObject *raw, _bufferedwriter_reset_buf(self); self->pos = 0; - self->fast_closed_checks = (Py_TYPE(self) == &PyBufferedRandom_Type && - Py_TYPE(raw) == &PyFileIO_Type); + self->fast_closed_checks = (Py_IS_TYPE(self, &PyBufferedRandom_Type) && + Py_IS_TYPE(raw, &PyFileIO_Type)); self->ok = 1; return 0; diff --git a/Modules/_io/stringio.c b/Modules/_io/stringio.c index 28d54e00d8a7b..9feb76e7ffaf4 100644 --- a/Modules/_io/stringio.c +++ b/Modules/_io/stringio.c @@ -402,7 +402,7 @@ stringio_iternext(stringio *self) CHECK_CLOSED(self); ENSURE_REALIZED(self); - if (Py_TYPE(self) == &PyStringIO_Type) { + if (Py_IS_TYPE(self, &PyStringIO_Type)) { /* Skip method call overhead for speed */ line = _stringio_readline(self, -1); } diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index 3a9ce93a5eb5e..dedbefe0079b8 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -897,7 +897,7 @@ _textiowrapper_decode(PyObject *decoder, PyObject *bytes, int eof) { PyObject *chars; - if (Py_TYPE(decoder) == &PyIncrementalNewlineDecoder_Type) + if (Py_IS_TYPE(decoder, &PyIncrementalNewlineDecoder_Type)) chars = _PyIncrementalNewlineDecoder_decode(decoder, bytes, eof); else chars = PyObject_CallMethodObjArgs(decoder, _PyIO_str_decode, bytes, @@ -1226,15 +1226,15 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer, /* Finished sorting out the codec details */ Py_CLEAR(codec_info); - if (Py_TYPE(buffer) == &PyBufferedReader_Type || - Py_TYPE(buffer) == &PyBufferedWriter_Type || - Py_TYPE(buffer) == &PyBufferedRandom_Type) + if (Py_IS_TYPE(buffer, &PyBufferedReader_Type) || + Py_IS_TYPE(buffer, &PyBufferedWriter_Type) || + Py_IS_TYPE(buffer, &PyBufferedRandom_Type)) { if (_PyObject_LookupAttrId(buffer, &PyId_raw, &raw) < 0) goto error; /* Cache the raw FileIO object to speed up 'closed' checks */ if (raw != NULL) { - if (Py_TYPE(raw) == &PyFileIO_Type) + if (Py_IS_TYPE(raw, &PyFileIO_Type)) self->raw = raw; else Py_DECREF(raw); @@ -1466,7 +1466,7 @@ textiowrapper_closed_get(textio *self, void *context); do { \ int r; \ PyObject *_res; \ - if (Py_TYPE(self) == &PyTextIOWrapper_Type) { \ + if (Py_IS_TYPE(self, &PyTextIOWrapper_Type)) { \ if (self->raw != NULL) \ r = _PyFileIO_closed(self->raw); \ else { \ @@ -1937,7 +1937,7 @@ _io_TextIOWrapper_read_impl(textio *self, Py_ssize_t n) if (bytes == NULL) goto fail; - if (Py_TYPE(self->decoder) == &PyIncrementalNewlineDecoder_Type) + if (Py_IS_TYPE(self->decoder, &PyIncrementalNewlineDecoder_Type)) decoded = _PyIncrementalNewlineDecoder_decode(self->decoder, bytes, 1); else @@ -3079,7 +3079,7 @@ textiowrapper_iternext(textio *self) CHECK_ATTACHED(self); self->telling = 0; - if (Py_TYPE(self) == &PyTextIOWrapper_Type) { + if (Py_IS_TYPE(self, &PyTextIOWrapper_Type)) { /* Skip method call overhead for speed */ line = _textiowrapper_readline(self, -1); } diff --git a/Modules/_pickle.c b/Modules/_pickle.c index bcbd3c0102965..6b903da8150d6 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -4974,7 +4974,7 @@ Pickler_set_memo(PicklerObject *self, PyObject *obj, void *Py_UNUSED(ignored)) return -1; } - if (Py_TYPE(obj) == &PicklerMemoProxyType) { + if (Py_IS_TYPE(obj, &PicklerMemoProxyType)) { PicklerObject *pickler = ((PicklerMemoProxyObject *)obj)->pickler; @@ -7519,7 +7519,7 @@ Unpickler_set_memo(UnpicklerObject *self, PyObject *obj, void *Py_UNUSED(ignored return -1; } - if (Py_TYPE(obj) == &UnpicklerMemoProxyType) { + if (Py_IS_TYPE(obj, &UnpicklerMemoProxyType)) { UnpicklerObject *unpickler = ((UnpicklerMemoProxyObject *)obj)->unpickler; diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c index 4a651cea6c7ff..da5fe7915a8e5 100644 --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -844,7 +844,7 @@ _ldict(localobject *self) } } else { - assert(Py_TYPE(dummy) == &localdummytype); + assert(Py_IS_TYPE(dummy, &localdummytype)); ldict = ((localdummyobject *) dummy)->localdict; } @@ -1209,7 +1209,7 @@ release_sentinel(void *wr_raw) PyObject *obj = PyWeakref_GET_OBJECT(wr); lockobject *lock; if (obj != Py_None) { - assert(Py_TYPE(obj) == &Locktype); + assert(Py_IS_TYPE(obj, &Locktype)); lock = (lockobject *) obj; if (lock->locked) { PyThread_release_lock(lock->lock_lock); diff --git a/Modules/cjkcodecs/multibytecodec.h b/Modules/cjkcodecs/multibytecodec.h index 94670ecafefd1..4d2b3558c936c 100644 --- a/Modules/cjkcodecs/multibytecodec.h +++ b/Modules/cjkcodecs/multibytecodec.h @@ -65,7 +65,7 @@ typedef struct { MultibyteCodec *codec; } MultibyteCodecObject; -#define MultibyteCodec_Check(op) (Py_TYPE(op) == &MultibyteCodec_Type) +#define MultibyteCodec_Check(op) Py_IS_TYPE((op), &MultibyteCodec_Type) #define _MultibyteStatefulCodec_HEAD \ PyObject_HEAD \ diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index c00c2745d3f0c..d545028901b4e 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -527,7 +527,7 @@ teedataobject_traverse(teedataobject *tdo, visitproc visit, void * arg) static void teedataobject_safe_decref(PyObject *obj) { - while (obj && Py_TYPE(obj) == &teedataobject_type && + while (obj && Py_IS_TYPE(obj, &teedataobject_type) && Py_REFCNT(obj) == 1) { PyObject *nextlink = ((teedataobject *)obj)->nextlink; ((teedataobject *)obj)->nextlink = NULL; diff --git a/Objects/abstract.c b/Objects/abstract.c index de5652f3e685f..454e0da71afbe 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2472,7 +2472,7 @@ object_recursive_isinstance(PyThreadState *tstate, PyObject *inst, PyObject *cls _Py_IDENTIFIER(__instancecheck__); /* Quick test for an exact match */ - if (Py_TYPE(inst) == (PyTypeObject *)cls) { + if (Py_IS_TYPE(inst, (PyTypeObject *)cls)) { return 1; } diff --git a/Objects/descrobject.c b/Objects/descrobject.c index aaaa4479e4b92..c96945bdb1f31 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -1178,7 +1178,7 @@ typedef struct { PyObject *self; } wrapperobject; -#define Wrapper_Check(v) (Py_TYPE(v) == &_PyMethodWrapper_Type) +#define Wrapper_Check(v) Py_IS_TYPE(v, &_PyMethodWrapper_Type) static void wrapper_dealloc(wrapperobject *wp) @@ -1628,7 +1628,7 @@ property_init_impl(propertyobject *self, PyObject *fget, PyObject *fset, if (rc <= 0) { return rc; } - if (Py_TYPE(self) == &PyProperty_Type) { + if (Py_IS_TYPE(self, &PyProperty_Type)) { Py_XSETREF(self->prop_doc, get_doc); } else { diff --git a/Objects/exceptions.c b/Objects/exceptions.c index 631f5375f7382..2baec5e3d5839 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -875,7 +875,7 @@ oserror_init(PyOSErrorObject *self, PyObject **p_args, /* self->filename will remain Py_None otherwise */ if (filename && filename != Py_None) { - if (Py_TYPE(self) == (PyTypeObject *) PyExc_BlockingIOError && + if (Py_IS_TYPE(self, (PyTypeObject *) PyExc_BlockingIOError) && PyNumber_Check(filename)) { /* BlockingIOError's 3rd argument can be the number of * characters written. @@ -1379,7 +1379,7 @@ SyntaxError_init(PySyntaxErrorObject *self, PyObject *args, PyObject *kwds) * Only applies to SyntaxError instances, not to subclasses such * as TabError or IndentationError (see issue #31161) */ - if ((PyObject*)Py_TYPE(self) == PyExc_SyntaxError && + if (Py_IS_TYPE(self, (PyTypeObject *)PyExc_SyntaxError) && self->text && PyUnicode_Check(self->text) && _report_missing_parentheses(self) < 0) { return -1; diff --git a/Objects/genobject.c b/Objects/genobject.c index ef892bb0366b8..6bb08aeaff76b 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -1216,10 +1216,10 @@ static PyAsyncGenASend *ag_asend_freelist[_PyAsyncGen_MAXFREELIST]; static int ag_asend_freelist_free = 0; #define _PyAsyncGenWrappedValue_CheckExact(o) \ - (Py_TYPE(o) == &_PyAsyncGenWrappedValue_Type) + Py_IS_TYPE(o, &_PyAsyncGenWrappedValue_Type) #define PyAsyncGenASend_CheckExact(o) \ - (Py_TYPE(o) == &_PyAsyncGenASend_Type) + Py_IS_TYPE(o, &_PyAsyncGenASend_Type) static int @@ -1442,7 +1442,7 @@ PyAsyncGen_ClearFreeLists(void) while (ag_asend_freelist_free) { PyAsyncGenASend *o; o = ag_asend_freelist[--ag_asend_freelist_free]; - assert(Py_TYPE(o) == &_PyAsyncGenASend_Type); + assert(Py_IS_TYPE(o, &_PyAsyncGenASend_Type)); PyObject_GC_Del(o); } diff --git a/Objects/listobject.c b/Objects/listobject.c index 3ac03b71d03ac..46bc7779218bc 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -2052,8 +2052,8 @@ unsafe_latin_compare(PyObject *v, PyObject *w, MergeState *ms) int res; /* Modified from Objects/unicodeobject.c:unicode_compare, assuming: */ - assert(Py_TYPE(v) == Py_TYPE(w)); - assert(Py_TYPE(v) == &PyUnicode_Type); + assert(Py_IS_TYPE(v, &PyUnicode_Type)); + assert(Py_IS_TYPE(w, &PyUnicode_Type)); assert(PyUnicode_KIND(v) == PyUnicode_KIND(w)); assert(PyUnicode_KIND(v) == PyUnicode_1BYTE_KIND); @@ -2075,8 +2075,8 @@ unsafe_long_compare(PyObject *v, PyObject *w, MergeState *ms) PyLongObject *vl, *wl; sdigit v0, w0; int res; /* Modified from Objects/longobject.c:long_compare, assuming: */ - assert(Py_TYPE(v) == Py_TYPE(w)); - assert(Py_TYPE(v) == &PyLong_Type); + assert(Py_IS_TYPE(v, &PyLong_Type)); + assert(Py_IS_TYPE(w, &PyLong_Type)); assert(Py_ABS(Py_SIZE(v)) <= 1); assert(Py_ABS(Py_SIZE(w)) <= 1); @@ -2103,8 +2103,8 @@ unsafe_float_compare(PyObject *v, PyObject *w, MergeState *ms) int res; /* Modified from Objects/floatobject.c:float_richcompare, assuming: */ - assert(Py_TYPE(v) == Py_TYPE(w)); - assert(Py_TYPE(v) == &PyFloat_Type); + assert(Py_IS_TYPE(v, &PyFloat_Type)); + assert(Py_IS_TYPE(w, &PyFloat_Type)); res = PyFloat_AS_DOUBLE(v) < PyFloat_AS_DOUBLE(w); assert(res == PyObject_RichCompareBool(v, w, Py_LT)); @@ -2125,8 +2125,8 @@ unsafe_tuple_compare(PyObject *v, PyObject *w, MergeState *ms) int k; /* Modified from Objects/tupleobject.c:tuplerichcompare, assuming: */ - assert(Py_TYPE(v) == Py_TYPE(w)); - assert(Py_TYPE(v) == &PyTuple_Type); + assert(Py_IS_TYPE(v, &PyTuple_Type)); + assert(Py_IS_TYPE(w, &PyTuple_Type)); assert(Py_SIZE(v) > 0); assert(Py_SIZE(w) > 0); @@ -2247,7 +2247,7 @@ list_sort_impl(PyListObject *self, PyObject *keyfunc, int reverse) * set ms appropriately. */ if (saved_ob_size > 1) { /* Assume the first element is representative of the whole list. */ - int keys_are_in_tuples = (Py_TYPE(lo.keys[0]) == &PyTuple_Type && + int keys_are_in_tuples = (Py_IS_TYPE(lo.keys[0], &PyTuple_Type) && Py_SIZE(lo.keys[0]) > 0); PyTypeObject* key_type = (keys_are_in_tuples ? @@ -2262,7 +2262,7 @@ list_sort_impl(PyListObject *self, PyObject *keyfunc, int reverse) for (i=0; i < saved_ob_size; i++) { if (keys_are_in_tuples && - !(Py_TYPE(lo.keys[i]) == &PyTuple_Type && Py_SIZE(lo.keys[i]) != 0)) { + !(Py_IS_TYPE(lo.keys[i], &PyTuple_Type) && Py_SIZE(lo.keys[i]) != 0)) { keys_are_in_tuples = 0; keys_are_all_same_type = 0; break; @@ -2275,7 +2275,7 @@ list_sort_impl(PyListObject *self, PyObject *keyfunc, int reverse) PyTuple_GET_ITEM(lo.keys[i], 0) : lo.keys[i]); - if (Py_TYPE(key) != key_type) { + if (!Py_IS_TYPE(key, key_type)) { keys_are_all_same_type = 0; /* If keys are in tuple we must loop over the whole list to make sure all items are tuples */ diff --git a/Objects/namespaceobject.c b/Objects/namespaceobject.c index 5c7163f36dc32..a28b9e509fcfb 100644 --- a/Objects/namespaceobject.c +++ b/Objects/namespaceobject.c @@ -72,7 +72,7 @@ namespace_repr(PyObject *ns) PyObject *separator, *pairsrepr, *repr = NULL; const char * name; - name = (Py_TYPE(ns) == &_PyNamespace_Type) ? "namespace" + name = Py_IS_TYPE(ns, &_PyNamespace_Type) ? "namespace" : Py_TYPE(ns)->tp_name; i = Py_ReprEnter(ns); diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index d114bd640964c..92374cc130d0c 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -237,7 +237,7 @@ tupledealloc(PyTupleObject *op) #if PyTuple_MAXSAVESIZE > 0 if (len < PyTuple_MAXSAVESIZE && numfree[len] < PyTuple_MAXFREELIST && - Py_TYPE(op) == &PyTuple_Type) + Py_IS_TYPE(op, &PyTuple_Type)) { op->ob_item[0] = (PyObject *) free_list[len]; numfree[len]++; diff --git a/Objects/typeobject.c b/Objects/typeobject.c index e51059b63267c..cf749eff58fe2 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -5335,7 +5335,7 @@ PyType_Ready(PyTypeObject *type) NULL when type is &PyBaseObject_Type, and we know its ob_type is not NULL (it's initialized to &PyType_Type). But coverity doesn't know that. */ - if (Py_TYPE(type) == NULL && base != NULL) { + if (Py_IS_TYPE(type, NULL) && base != NULL) { Py_SET_TYPE(type, Py_TYPE(base)); } @@ -6645,7 +6645,7 @@ slot_tp_getattr_hook(PyObject *self, PyObject *name) needed, with call_attribute. */ getattribute = _PyType_LookupId(tp, &PyId___getattribute__); if (getattribute == NULL || - (Py_TYPE(getattribute) == &PyWrapperDescr_Type && + (Py_IS_TYPE(getattribute, &PyWrapperDescr_Type) && ((PyWrapperDescrObject *)getattribute)->d_wrapped == (void *)PyObject_GenericGetAttr)) res = PyObject_GenericGetAttr(self, name); @@ -7352,7 +7352,7 @@ update_one_slot(PyTypeObject *type, slotdef *p) } continue; } - if (Py_TYPE(descr) == &PyWrapperDescr_Type && + if (Py_IS_TYPE(descr, &PyWrapperDescr_Type) && ((PyWrapperDescrObject *)descr)->d_base->name_strobj == p->name_strobj) { void **tptr = resolve_slotdups(type, p->name_strobj); if (tptr == NULL || tptr == ptr) @@ -7375,7 +7375,7 @@ update_one_slot(PyTypeObject *type, slotdef *p) use_generic = 1; } } - else if (Py_TYPE(descr) == &PyCFunction_Type && + else if (Py_IS_TYPE(descr, &PyCFunction_Type) && PyCFunction_GET_FUNCTION(descr) == (PyCFunction)(void(*)(void))tp_new_wrapper && ptr == (void**)&type->tp_new) diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index e0a666f70da36..3d99f11ecff6f 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -8484,7 +8484,7 @@ charmapencode_output(Py_UCS4 c, PyObject *mapping, char *outstart; Py_ssize_t outsize = PyBytes_GET_SIZE(*outobj); - if (Py_TYPE(mapping) == &EncodingMapType) { + if (Py_IS_TYPE(mapping, &EncodingMapType)) { int res = encoding_map_lookup(c, mapping); Py_ssize_t requiredsize = *outpos+1; if (res == -1) @@ -8563,7 +8563,7 @@ charmap_encoding_error( /* find all unencodable characters */ while (collendpos < size) { PyObject *rep; - if (Py_TYPE(mapping) == &EncodingMapType) { + if (Py_IS_TYPE(mapping, &EncodingMapType)) { ch = PyUnicode_READ_CHAR(unicode, collendpos); val = encoding_map_lookup(ch, mapping); if (val != -1) diff --git a/Python/ceval.c b/Python/ceval.c index 3f65820c25da9..ef4aac2f9abc8 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4851,7 +4851,7 @@ trace_call_function(PyThreadState *tstate, C_TRACE(x, PyObject_Vectorcall(func, args, nargs, kwnames)); return x; } - else if (Py_TYPE(func) == &PyMethodDescr_Type && nargs > 0) { + else if (Py_IS_TYPE(func, &PyMethodDescr_Type) && nargs > 0) { /* We need to create a temporary bound method as argument for profiling. @@ -4912,7 +4912,7 @@ do_call_core(PyThreadState *tstate, PyObject *func, PyObject *callargs, PyObject C_TRACE(result, PyObject_Call(func, callargs, kwdict)); return result; } - else if (Py_TYPE(func) == &PyMethodDescr_Type) { + else if (Py_IS_TYPE(func, &PyMethodDescr_Type)) { Py_ssize_t nargs = PyTuple_GET_SIZE(callargs); if (nargs > 0 && tstate->use_tracing) { /* We need to create a temporary bound method as argument diff --git a/Python/errors.c b/Python/errors.c index 61dc597916d72..6baa229ccc7ce 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -573,7 +573,7 @@ PyErr_BadArgument(void) PyObject * _PyErr_NoMemory(PyThreadState *tstate) { - if (Py_TYPE(PyExc_MemoryError) == NULL) { + if (Py_IS_TYPE(PyExc_MemoryError, NULL)) { /* PyErr_NoMemory() has been called before PyExc_MemoryError has been initialized by _PyExc_Init() */ Py_FatalError("Out of memory and PyExc_MemoryError is not " diff --git a/Python/importdl.c b/Python/importdl.c index 1d0d32a2371f8..fbeb9fb75403e 100644 --- a/Python/importdl.c +++ b/Python/importdl.c @@ -181,7 +181,7 @@ _PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *fp) m = NULL; goto error; } - if (Py_TYPE(m) == NULL) { + if (Py_IS_TYPE(m, NULL)) { /* This can happen when a PyModuleDef is returned without calling * PyModuleDef_Init on it */ From webhook-mailer at python.org Wed Mar 4 08:50:24 2020 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 04 Mar 2020 13:50:24 -0000 Subject: [Python-checkins] bpo-39763: distutils.spawn now uses subprocess (GH-18743) Message-ID: https://github.com/python/cpython/commit/1ec63b62035e73111e204a0e03b83503e1c58f2e commit: 1ec63b62035e73111e204a0e03b83503e1c58f2e branch: master author: Victor Stinner committer: GitHub date: 2020-03-04T14:50:19+01:00 summary: bpo-39763: distutils.spawn now uses subprocess (GH-18743) Reimplement distutils.spawn.spawn() function with the subprocess module. setup.py now uses a basic implementation of the subprocess module if the subprocess module is not available: before required C extension modules are built. files: A Misc/NEWS.d/next/Build/2020-03-02-14-44-09.bpo-39763.GGEwhH.rst A Misc/NEWS.d/next/Library/2020-03-02-14-43-19.bpo-39763.5a822c.rst M Lib/distutils/spawn.py M Lib/distutils/tests/test_spawn.py M setup.py diff --git a/Lib/distutils/spawn.py b/Lib/distutils/spawn.py index ceb94945dc8be..aad277b0ca776 100644 --- a/Lib/distutils/spawn.py +++ b/Lib/distutils/spawn.py @@ -8,11 +8,18 @@ import sys import os +import subprocess from distutils.errors import DistutilsPlatformError, DistutilsExecError from distutils.debug import DEBUG from distutils import log + +if sys.platform == 'darwin': + _cfg_target = None + _cfg_target_split = None + + def spawn(cmd, search_path=1, verbose=0, dry_run=0): """Run another program, specified as a command list 'cmd', in a new process. @@ -32,64 +39,16 @@ def spawn(cmd, search_path=1, verbose=0, dry_run=0): # cmd is documented as a list, but just in case some code passes a tuple # in, protect our %-formatting code against horrible death cmd = list(cmd) - if os.name == 'posix': - _spawn_posix(cmd, search_path, dry_run=dry_run) - elif os.name == 'nt': - _spawn_nt(cmd, search_path, dry_run=dry_run) - else: - raise DistutilsPlatformError( - "don't know how to spawn programs on platform '%s'" % os.name) - -def _nt_quote_args(args): - """Quote command-line arguments for DOS/Windows conventions. - - Just wraps every argument which contains blanks in double quotes, and - returns a new argument list. - """ - # XXX this doesn't seem very robust to me -- but if the Windows guys - # say it'll work, I guess I'll have to accept it. (What if an arg - # contains quotes? What other magic characters, other than spaces, - # have to be escaped? Is there an escaping mechanism other than - # quoting?) - for i, arg in enumerate(args): - if ' ' in arg: - args[i] = '"%s"' % arg - return args - -def _spawn_nt(cmd, search_path=1, verbose=0, dry_run=0): - executable = cmd[0] - cmd = _nt_quote_args(cmd) - if search_path: - # either we find one or it stays the same - executable = find_executable(executable) or executable - log.info(' '.join([executable] + cmd[1:])) - if not dry_run: - # spawn for NT requires a full path to the .exe - try: - rc = os.spawnv(os.P_WAIT, executable, cmd) - except OSError as exc: - # this seems to happen when the command isn't found - if not DEBUG: - cmd = executable - raise DistutilsExecError( - "command %r failed: %s" % (cmd, exc.args[-1])) - if rc != 0: - # and this reflects the command running but failing - if not DEBUG: - cmd = executable - raise DistutilsExecError( - "command %r failed with exit status %d" % (cmd, rc)) - -if sys.platform == 'darwin': - _cfg_target = None - _cfg_target_split = None -def _spawn_posix(cmd, search_path=1, verbose=0, dry_run=0): log.info(' '.join(cmd)) if dry_run: return - executable = cmd[0] - exec_fn = search_path and os.execvp or os.execv + + if search_path: + executable = find_executable(cmd[0]) + if executable is not None: + cmd[0] = executable + env = None if sys.platform == 'darwin': global _cfg_target, _cfg_target_split @@ -111,60 +70,17 @@ def _spawn_posix(cmd, search_path=1, verbose=0, dry_run=0): raise DistutilsPlatformError(my_msg) env = dict(os.environ, MACOSX_DEPLOYMENT_TARGET=cur_target) - exec_fn = search_path and os.execvpe or os.execve - pid = os.fork() - if pid == 0: # in the child - try: - if env is None: - exec_fn(executable, cmd) - else: - exec_fn(executable, cmd, env) - except OSError as e: - if not DEBUG: - cmd = executable - sys.stderr.write("unable to execute %r: %s\n" - % (cmd, e.strerror)) - os._exit(1) + proc = subprocess.Popen(cmd, env=env) + proc.wait() + exitcode = proc.returncode + + if exitcode: if not DEBUG: - cmd = executable - sys.stderr.write("unable to execute %r for unknown reasons" % cmd) - os._exit(1) - else: # in the parent - # Loop until the child either exits or is terminated by a signal - # (ie. keep waiting if it's merely stopped) - while True: - try: - pid, status = os.waitpid(pid, 0) - except OSError as exc: - if not DEBUG: - cmd = executable - raise DistutilsExecError( - "command %r failed: %s" % (cmd, exc.args[-1])) - if os.WIFSIGNALED(status): - if not DEBUG: - cmd = executable - raise DistutilsExecError( - "command %r terminated by signal %d" - % (cmd, os.WTERMSIG(status))) - elif os.WIFEXITED(status): - exit_status = os.WEXITSTATUS(status) - if exit_status == 0: - return # hey, it succeeded! - else: - if not DEBUG: - cmd = executable - raise DistutilsExecError( - "command %r failed with exit status %d" - % (cmd, exit_status)) - elif os.WIFSTOPPED(status): - continue - else: - if not DEBUG: - cmd = executable - raise DistutilsExecError( - "unknown error executing %r: termination status %d" - % (cmd, status)) + cmd = cmd[0] + raise DistutilsExecError( + "command %r failed with exit code %s" % (cmd, exitcode)) + def find_executable(executable, path=None): """Tries to find 'executable' in the directories listed in 'path'. diff --git a/Lib/distutils/tests/test_spawn.py b/Lib/distutils/tests/test_spawn.py index f9ae69ef86b3d..73b0f5cb7324c 100644 --- a/Lib/distutils/tests/test_spawn.py +++ b/Lib/distutils/tests/test_spawn.py @@ -8,7 +8,6 @@ from test import support as test_support from distutils.spawn import find_executable -from distutils.spawn import _nt_quote_args from distutils.spawn import spawn from distutils.errors import DistutilsExecError from distutils.tests import support @@ -17,16 +16,6 @@ class SpawnTestCase(support.TempdirManager, support.LoggingSilencer, unittest.TestCase): - def test_nt_quote_args(self): - - for (args, wanted) in ((['with space', 'nospace'], - ['"with space"', 'nospace']), - (['nochange', 'nospace'], - ['nochange', 'nospace'])): - res = _nt_quote_args(args) - self.assertEqual(res, wanted) - - @unittest.skipUnless(os.name in ('nt', 'posix'), 'Runs only under posix or nt') def test_spawn(self): diff --git a/Misc/NEWS.d/next/Build/2020-03-02-14-44-09.bpo-39763.GGEwhH.rst b/Misc/NEWS.d/next/Build/2020-03-02-14-44-09.bpo-39763.GGEwhH.rst new file mode 100644 index 0000000000000..e983b4f338a94 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2020-03-02-14-44-09.bpo-39763.GGEwhH.rst @@ -0,0 +1,3 @@ +setup.py now uses a basic implementation of the :mod:`subprocess` module if +the :mod:`subprocess` module is not available: before required C extension +modules are built. diff --git a/Misc/NEWS.d/next/Library/2020-03-02-14-43-19.bpo-39763.5a822c.rst b/Misc/NEWS.d/next/Library/2020-03-02-14-43-19.bpo-39763.5a822c.rst new file mode 100644 index 0000000000000..73ea8f9ab69a6 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-03-02-14-43-19.bpo-39763.5a822c.rst @@ -0,0 +1,2 @@ +Reimplement :func:`distutils.spawn.spawn` function with the +:mod:`subprocess` module. diff --git a/setup.py b/setup.py index 51e67fe4a558b..c9f3c97238c22 100644 --- a/setup.py +++ b/setup.py @@ -10,6 +10,61 @@ import sysconfig from glob import glob + +try: + import subprocess + del subprocess + SUBPROCESS_BOOTSTRAP = False +except ImportError: + SUBPROCESS_BOOTSTRAP = True + + # Bootstrap Python: distutils.spawn uses subprocess to build C extensions, + # subprocess requires C extensions built by setup.py like _posixsubprocess. + # + # Basic subprocess implementation for POSIX (setup.py is not used on + # Windows) which only uses os functions. Only implement features required + # by distutils.spawn. + # + # It is dropped from sys.modules as soon as all C extension modules + # are built. + class Popen: + def __init__(self, cmd, env=None): + self._cmd = cmd + self._env = env + self.returncode = None + + def wait(self): + pid = os.fork() + if pid == 0: + # Child process + try: + if self._env is not None: + os.execve(self._cmd[0], self._cmd, self._env) + else: + os.execv(self._cmd[0], self._cmd) + finally: + os._exit(1) + else: + # Parent process + pid, status = os.waitpid(pid, 0) + if os.WIFSIGNALED(status): + self.returncode = -os.WTERMSIG(status) + elif os.WIFEXITED(status): + self.returncode = os.WEXITSTATUS(status) + elif os.WIFSTOPPED(status): + self.returncode = -os.WSTOPSIG(sts) + else: + # Should never happen + raise Exception("Unknown child exit status!") + + return self.returncode + + mod = type(sys)('subprocess') + mod.Popen = Popen + sys.modules['subprocess'] = mod + del mod + + from distutils import log from distutils.command.build_ext import build_ext from distutils.command.build_scripts import build_scripts @@ -391,6 +446,11 @@ def build_extensions(self): build_ext.build_extensions(self) + if SUBPROCESS_BOOTSTRAP: + # Drop our custom subprocess module: + # use the newly built subprocess module + del sys.modules['subprocess'] + for ext in self.extensions: self.check_extension_import(ext) From webhook-mailer at python.org Wed Mar 4 09:11:48 2020 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 04 Mar 2020 14:11:48 -0000 Subject: [Python-checkins] bpo-39674: Fix typo in What's New In Python 3.9 (GH-18776) Message-ID: https://github.com/python/cpython/commit/a6d3546d003d9873de0f71b319ad79d203374bf0 commit: a6d3546d003d9873de0f71b319ad79d203374bf0 branch: master author: Victor Stinner committer: GitHub date: 2020-03-04T15:11:43+01:00 summary: bpo-39674: Fix typo in What's New In Python 3.9 (GH-18776) files: M Doc/whatsnew/3.9.rst diff --git a/Doc/whatsnew/3.9.rst b/Doc/whatsnew/3.9.rst index 6a4d07f62c69b..f15805c794ea8 100644 --- a/Doc/whatsnew/3.9.rst +++ b/Doc/whatsnew/3.9.rst @@ -85,7 +85,7 @@ It has been decided to keep a few backward compatibility layers for one last release, to give more time to Python projects maintainers to organize the removal of the Python 2 support and add support for Python 3.9. -Aliases to ref:`Abstract Base Classes ` in +Aliases to :ref:`Abstract Base Classes ` in the :mod:`collections` module, like ``collections.Mapping`` alias to :class:`collections.abc.Mapping`, are kept for one last release for backward compatibility. They will be removed from Python 3.10. From webhook-mailer at python.org Wed Mar 4 09:52:20 2020 From: webhook-mailer at python.org (Andy Lester) Date: Wed, 04 Mar 2020 14:52:20 -0000 Subject: [Python-checkins] bpo-39770, array module: Remove unnecessary descriptor counting (GH-18675) Message-ID: https://github.com/python/cpython/commit/702e09fd0ad72b248b5adfa0fcfdb58600be77f6 commit: 702e09fd0ad72b248b5adfa0fcfdb58600be77f6 branch: master author: Andy Lester committer: GitHub date: 2020-03-04T15:52:15+01:00 summary: bpo-39770, array module: Remove unnecessary descriptor counting (GH-18675) files: M Modules/arraymodule.c diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index b41ba0523b30b..95ee5f881cc35 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -2991,7 +2991,6 @@ array_modexec(PyObject *m) { char buffer[Py_ARRAY_LENGTH(descriptors)], *p; PyObject *typecodes; - Py_ssize_t size = 0; const struct arraydescr *descr; if (PyType_Ready(&Arraytype) < 0) @@ -3009,10 +3008,6 @@ array_modexec(PyObject *m) return -1; } - for (descr=descriptors; descr->typecode != '\0'; descr++) { - size++; - } - p = buffer; for (descr = descriptors; descr->typecode != '\0'; descr++) { *p++ = (char)descr->typecode; From webhook-mailer at python.org Wed Mar 4 12:32:17 2020 From: webhook-mailer at python.org (Ned Deily) Date: Wed, 04 Mar 2020 17:32:17 -0000 Subject: [Python-checkins] Update macOS installer ReadMe for 3.7.7. (GH-18775) Message-ID: https://github.com/python/cpython/commit/0814411ea6ba846b33a65c79ff235f6f35f46b70 commit: 0814411ea6ba846b33a65c79ff235f6f35f46b70 branch: 3.7 author: Ned Deily committer: GitHub date: 2020-03-04T12:32:09-05:00 summary: Update macOS installer ReadMe for 3.7.7. (GH-18775) files: M Mac/BuildScript/resources/ReadMe.rtf diff --git a/Mac/BuildScript/resources/ReadMe.rtf b/Mac/BuildScript/resources/ReadMe.rtf index b71bd642902a2..10e9b2d64ca56 100644 --- a/Mac/BuildScript/resources/ReadMe.rtf +++ b/Mac/BuildScript/resources/ReadMe.rtf @@ -1,5 +1,5 @@ -{\rtf1\ansi\ansicpg1252\cocoartf1671\cocoasubrtf600 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fswiss\fcharset0 Helvetica-Bold;\f2\fswiss\fcharset0 Helvetica-Oblique; +{\rtf1\ansi\ansicpg1252\cocoartf2511 +\cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fswiss\fcharset0 Helvetica-Bold;\f2\fswiss\fcharset0 Helvetica-Oblique; \f3\fmodern\fcharset0 CourierNewPSMT;} {\colortbl;\red255\green255\blue255;} {\*\expandedcolortbl;;} @@ -11,9 +11,10 @@ \cf0 \ \pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0 -\f1\b \cf0 \ul Certificate verification and OpenSSL\ +\f1\b \cf0 \ul \ulc0 Certificate verification and OpenSSL\ +\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0 -\f0\b0 \ulnone \ +\f0\b0 \cf0 \ulnone \ This package includes its own private copy of OpenSSL 1.1.1. The trust certificates in system and user keychains managed by the \f2\i Keychain Access \f0\i0 application and the @@ -32,36 +33,26 @@ The bundled \f3 pip \f0 has its own default certificate store for verifying download connections.\ \ +\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0 -\f1\b \ul Which installer variant should I use? +\f1\b \cf0 \ul \ulc0 Which installer variant should I use? \f0\b0 \ulnone \ \ \pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\partightenfactor0 -\cf0 In almost all cases, you should use the +\cf0 Use the \f1\b macOS 64-bit installer for OS X 10.9 and later -\f0\b0 .\ -\ -The legacy +\f0\b0 . As of 3.7.7, the deprecated \f1\b macOS 64-bit/32-bit installer for Mac OS X 10.6 and later -\f0\b0 variant is now deprecated. -\f1\b Python 3.8.0 -\f0\b0 will -\f1\b not -\f0\b0 include a binary installer for the 10.6+ variant and -\f1\b future bugfix releases of 3.7.x -\f0\b0 may not, either. macOS 10.6 Snow Leopard was released in 2009 and has not been supported by Apple for many years including lack of security updates. It is becoming increasingly difficult to ensure new Python features and bug fixes are compatible with such old systems. Note that, due to recent Apple installer packaging changes, the 10.6+ installer pkg we provide can no longer be opened by the Apple system installer application on 10.6; 10.7 and 10.8 are not affected. We believe that there is now very little usage of this installer variant and so we would like to focus our resources on supporting newer systems. We do not plan to intentionally break Python support on 10.6 through 10.8 and we will consider bug fixes for problems found when building from source on those systems. -\f1\b macOS 10.15 Catalina -\f0\b0 removes support for running 32-bit architecture programs; we do not recommend trying to use the 10.6+ variant on it and it may not install on 10.15 systems without intervention. \ +\f0\b0 variant is no longer provided. \ \pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0 -\f1\b \cf0 \ul \ +\f1\b \cf0 \ul \ulc0 \ Using IDLE or other Tk applications \f0\b0 \ulnone \ \ This package includes its own private version of Tcl/Tk 8.6. It does not use any system-supplied or third-party supplied versions of Tcl/Tk.\ \ -\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0 -\cf0 Due to new security checks on macOS 10.15 Catalina, when launching IDLE macOS may open a window with a message +Due to new security checks on macOS 10.15 Catalina, when launching IDLE macOS may open a window with a message \f1\b "Python" would like to access files in your Documents folder \f0\b0 . This is normal as IDLE uses your \f1\b Documents From webhook-mailer at python.org Wed Mar 4 12:44:57 2020 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 04 Mar 2020 17:44:57 -0000 Subject: [Python-checkins] bpo-39763: Refactor setup.py (GH-18778) Message-ID: https://github.com/python/cpython/commit/00c77ae55a82548a6b45af73cdf712ea34910645 commit: 00c77ae55a82548a6b45af73cdf712ea34910645 branch: master author: Victor Stinner committer: GitHub date: 2020-03-04T18:44:49+01:00 summary: bpo-39763: Refactor setup.py (GH-18778) Split long build_extensions() method into sub-methods. Fix also a typo in Popen.wait(): replace sts with status. files: M setup.py diff --git a/setup.py b/setup.py index c9f3c97238c22..a331315817950 100644 --- a/setup.py +++ b/setup.py @@ -52,7 +52,7 @@ def wait(self): elif os.WIFEXITED(status): self.returncode = os.WEXITSTATUS(status) elif os.WIFSTOPPED(status): - self.returncode = -os.WSTOPSIG(sts) + self.returncode = -os.WSTOPSIG(status) else: # Should never happen raise Exception("Unknown child exit status!") @@ -364,16 +364,14 @@ def __init__(self, dist): def add(self, ext): self.extensions.append(ext) - def build_extensions(self): + def set_srcdir(self): self.srcdir = sysconfig.get_config_var('srcdir') if not self.srcdir: # Maybe running on Windows but not using CYGWIN? raise ValueError("No source directory; cannot proceed.") self.srcdir = os.path.abspath(self.srcdir) - # Detect which modules should be compiled - self.detect_modules() - + def remove_disabled(self): # Remove modules that are present on the disabled list extensions = [ext for ext in self.extensions if ext.name not in DISABLED_MODULE_LIST] @@ -384,6 +382,7 @@ def build_extensions(self): extensions.append(ctypes) self.extensions = extensions + def update_sources_depends(self): # Fix up the autodetected modules, prefixing all the source files # with Modules/. moddirlist = [os.path.join(self.srcdir, 'Modules')] @@ -396,14 +395,6 @@ def build_extensions(self): headers = [sysconfig.get_config_h_filename()] headers += glob(os.path.join(sysconfig.get_path('include'), "*.h")) - # The sysconfig variables built by makesetup that list the already - # built modules and the disabled modules as configured by the Setup - # files. - sysconf_built = sysconfig.get_config_var('MODBUILT_NAMES').split() - sysconf_dis = sysconfig.get_config_var('MODDISABLED_NAMES').split() - - mods_built = [] - mods_disabled = [] for ext in self.extensions: ext.sources = [ find_module_file(filename, moddirlist) for filename in ext.sources ] @@ -415,6 +406,16 @@ def build_extensions(self): # re-compile extensions if a header file has been changed ext.depends.extend(headers) + def remove_configured_extensions(self): + # The sysconfig variables built by makesetup that list the already + # built modules and the disabled modules as configured by the Setup + # files. + sysconf_built = sysconfig.get_config_var('MODBUILT_NAMES').split() + sysconf_dis = sysconfig.get_config_var('MODDISABLED_NAMES').split() + + mods_built = [] + mods_disabled = [] + for ext in self.extensions: # If a module has already been built or has been disabled in the # Setup files, don't build it here. if ext.name in sysconf_built: @@ -432,6 +433,9 @@ def build_extensions(self): if os.path.exists(fullpath): os.unlink(fullpath) + return (mods_built, mods_disabled) + + def set_compiler_executables(self): # When you run "make CC=altcc" or something similar, you really want # those environment variables passed into the setup.py phase. Here's # a small set of useful ones. @@ -444,6 +448,18 @@ def build_extensions(self): args['compiler_so'] = compiler + ' ' + ccshared + ' ' + cflags self.compiler.set_executables(**args) + def build_extensions(self): + self.set_srcdir() + + # Detect which modules should be compiled + self.detect_modules() + + self.remove_disabled() + + self.update_sources_depends() + mods_built, mods_disabled = self.remove_configured_extensions() + self.set_compiler_executables() + build_ext.build_extensions(self) if SUBPROCESS_BOOTSTRAP: @@ -454,6 +470,9 @@ def build_extensions(self): for ext in self.extensions: self.check_extension_import(ext) + self.summary(mods_built, mods_disabled) + + def summary(self, mods_built, mods_disabled): longest = max([len(e.name) for e in self.extensions], default=0) if self.failed or self.failed_on_import: all_failed = self.failed + self.failed_on_import From webhook-mailer at python.org Wed Mar 4 12:50:26 2020 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 04 Mar 2020 17:50:26 -0000 Subject: [Python-checkins] bpo-39674: Revert "bpo-37330: open() no longer accept 'U' in file mode (GH-16959)" (GH-18767) Message-ID: https://github.com/python/cpython/commit/942f7a2dea2e95a0fa848329565c0d0288d92e47 commit: 942f7a2dea2e95a0fa848329565c0d0288d92e47 branch: master author: Victor Stinner committer: GitHub date: 2020-03-04T18:50:22+01:00 summary: bpo-39674: Revert "bpo-37330: open() no longer accept 'U' in file mode (GH-16959)" (GH-18767) This reverts commit e471e72977c83664f13d041c78549140c86c92de. The mode will be removed from Python 3.10. files: A Misc/NEWS.d/next/Library/2020-03-03-16-21-41.bpo-39674.HJVkD5.rst M Doc/library/codecs.rst M Doc/library/fileinput.rst M Doc/library/functions.rst M Doc/whatsnew/3.9.rst M Lib/_pyio.py M Lib/fileinput.py M Lib/imp.py M Lib/test/test_codecs.py M Lib/test/test_fileinput.py M Lib/test/test_io.py M Modules/_io/_iomodule.c M Modules/_io/clinic/_iomodule.c.h diff --git a/Doc/library/codecs.rst b/Doc/library/codecs.rst index ec6a0533033bd..f071057293eec 100644 --- a/Doc/library/codecs.rst +++ b/Doc/library/codecs.rst @@ -197,9 +197,6 @@ wider range of codecs when working with binary files: *buffering* has the same meaning as for the built-in :func:`open` function. It defaults to -1 which means that the default buffer size will be used. - .. versionchanged:: 3.9 - The ``'U'`` mode has been removed. - .. function:: EncodedFile(file, data_encoding, file_encoding=None, errors='strict') diff --git a/Doc/library/fileinput.rst b/Doc/library/fileinput.rst index 236f5d563833e..cc4039a30e38a 100644 --- a/Doc/library/fileinput.rst +++ b/Doc/library/fileinput.rst @@ -148,8 +148,8 @@ available for subclassing as well: The sequence must be accessed in strictly sequential order; random access and :meth:`~io.TextIOBase.readline` cannot be mixed. - With *mode* you can specify which file mode will be passed to :func:`open`. - It must be ``'r'`` or ``'rb'``. + With *mode* you can specify which file mode will be passed to :func:`open`. It + must be one of ``'r'``, ``'rU'``, ``'U'`` and ``'rb'``. The *openhook*, when given, must be a function that takes two arguments, *filename* and *mode*, and returns an accordingly opened file-like object. You @@ -166,14 +166,15 @@ available for subclassing as well: .. versionchanged:: 3.2 Can be used as a context manager. + .. deprecated:: 3.4 + The ``'rU'`` and ``'U'`` modes. + .. deprecated:: 3.8 Support for :meth:`__getitem__` method is deprecated. .. versionchanged:: 3.8 The keyword parameter *mode* and *openhook* are now keyword-only. - .. versionchanged:: 3.9 - The ``'rU'`` and ``'U'`` modes have been removed. **Optional in-place filtering:** if the keyword argument ``inplace=True`` is diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index cc48597ef91d5..ca09e6f33033d 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -1090,6 +1090,12 @@ are always available. They are listed here in alphabetical order. first decoded using a platform-dependent encoding or using the specified *encoding* if given. + There is an additional mode character permitted, ``'U'``, which no longer + has any effect, and is considered deprecated. It previously enabled + :term:`universal newlines` in text mode, which became the default behaviour + in Python 3.0. Refer to the documentation of the + :ref:`newline ` parameter for further details. + .. note:: Python doesn't depend on the underlying operating system's notion of text @@ -1246,6 +1252,10 @@ are always available. They are listed here in alphabetical order. * The file is now non-inheritable. + .. deprecated-removed:: 3.4 3.10 + + The ``'U'`` mode. + .. versionchanged:: 3.5 @@ -1261,10 +1271,6 @@ are always available. They are listed here in alphabetical order. * On Windows, opening a console buffer may return a subclass of :class:`io.RawIOBase` other than :class:`io.FileIO`. - .. versionchanged:: 3.9 - The ``'U'`` mode has been removed. - - .. function:: ord(c) Given a string representing one Unicode character, return an integer diff --git a/Doc/whatsnew/3.9.rst b/Doc/whatsnew/3.9.rst index d072b8db311cf..a59de485a95d3 100644 --- a/Doc/whatsnew/3.9.rst +++ b/Doc/whatsnew/3.9.rst @@ -625,14 +625,6 @@ that may require changes to your code. Changes in the Python API ------------------------- -* :func:`open`, :func:`io.open`, :func:`codecs.open` and - :class:`fileinput.FileInput` no longer accept ``'U'`` ("universal newline") - in the file mode. This flag was deprecated since Python 3.3. In Python 3, the - "universal newline" is used by default when a file is open in text mode. The - :ref:`newline parameter ` of :func:`open` controls - how universal newlines works. - (Contributed by Victor Stinner in :issue:`37330`.) - * :func:`__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 diff --git a/Lib/_pyio.py b/Lib/_pyio.py index 8eaa114c07c91..4804ed27cd14d 100644 --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -71,6 +71,7 @@ def open(file, mode="r", buffering=-1, encoding=None, errors=None, 'b' binary mode 't' text mode (default) '+' open a disk file for updating (reading and writing) + 'U' universal newline mode (deprecated) ========= =============================================================== The default mode is 'rt' (open for reading text). For binary random @@ -86,6 +87,10 @@ def open(file, mode="r", buffering=-1, encoding=None, errors=None, returned as strings, the bytes having been first decoded using a platform-dependent encoding or using the specified encoding if given. + 'U' mode is deprecated and will raise an exception in future versions + of Python. It has no effect in Python 3. Use newline to control + universal newlines mode. + buffering is an optional integer used to set the buffering policy. Pass 0 to switch buffering off (only allowed in binary mode), 1 to select line buffering (only usable in text mode), and an integer > 1 to indicate @@ -171,7 +176,7 @@ def open(file, mode="r", buffering=-1, encoding=None, errors=None, if errors is not None and not isinstance(errors, str): raise TypeError("invalid errors: %r" % errors) modes = set(mode) - if modes - set("axrwb+t") or len(mode) > len(modes): + if modes - set("axrwb+tU") or len(mode) > len(modes): raise ValueError("invalid mode: %r" % mode) creating = "x" in modes reading = "r" in modes @@ -180,6 +185,13 @@ def open(file, mode="r", buffering=-1, encoding=None, errors=None, updating = "+" in modes text = "t" in modes binary = "b" in modes + if "U" in modes: + if creating or writing or appending or updating: + raise ValueError("mode U cannot be combined with 'x', 'w', 'a', or '+'") + import warnings + warnings.warn("'U' mode is deprecated", + DeprecationWarning, 2) + reading = True if text and binary: raise ValueError("can't have text and binary mode at once") if creating + reading + writing + appending > 1: diff --git a/Lib/fileinput.py b/Lib/fileinput.py index 166c631689747..c1b0ec9a8ed08 100644 --- a/Lib/fileinput.py +++ b/Lib/fileinput.py @@ -209,10 +209,15 @@ def __init__(self, files=None, inplace=False, backup="", *, self._isstdin = False self._backupfilename = None # restrict mode argument to reading modes - if mode not in ('r', 'rb'): - raise ValueError("FileInput opening mode must be 'r' or 'rb'") + if mode not in ('r', 'rU', 'U', 'rb'): + raise ValueError("FileInput opening mode must be one of " + "'r', 'rU', 'U' and 'rb'") + if 'U' in mode: + import warnings + warnings.warn("'U' mode is deprecated", + DeprecationWarning, 2) self._mode = mode - self._write_mode = mode.replace('r', 'w') + self._write_mode = mode.replace('r', 'w') if 'U' not in mode else 'w' if openhook: if inplace: raise ValueError("FileInput cannot use an opening hook in inplace mode") diff --git a/Lib/imp.py b/Lib/imp.py index a6f6fc8434902..31f8c766381ad 100644 --- a/Lib/imp.py +++ b/Lib/imp.py @@ -225,7 +225,7 @@ def load_module(name, file, filename, details): """ suffix, mode, type_ = details - if mode and (not mode.startswith('r') or '+' in mode): + if mode and (not mode.startswith(('r', 'U')) or '+' in mode): raise ValueError('invalid file open mode {!r}'.format(mode)) elif file is None and type_ in {PY_SOURCE, PY_COMPILED}: msg = 'file object required for import (type code {})'.format(type_) diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py index dcdd574bc7f4d..54a3520802a4f 100644 --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -712,23 +712,11 @@ def test_bug691291(self): self.addCleanup(support.unlink, support.TESTFN) with open(support.TESTFN, 'wb') as fp: fp.write(s) - with codecs.open(support.TESTFN, 'r', - encoding=self.encoding) as reader: + with support.check_warnings(('', DeprecationWarning)): + reader = codecs.open(support.TESTFN, 'U', encoding=self.encoding) + with reader: self.assertEqual(reader.read(), s1) - def test_invalid_modes(self): - for mode in ('U', 'rU', 'r+U'): - with self.assertRaises(ValueError) as cm: - codecs.open(support.TESTFN, mode, encoding=self.encoding) - self.assertIn('invalid mode', str(cm.exception)) - - for mode in ('rt', 'wt', 'at', 'r+t'): - with self.assertRaises(ValueError) as cm: - codecs.open(support.TESTFN, mode, encoding=self.encoding) - self.assertIn("can't have text and binary mode at once", - str(cm.exception)) - - class UTF16LETest(ReadTest, unittest.TestCase): encoding = "utf-16-le" ill_formed_sequence = b"\x80\xdc" diff --git a/Lib/test/test_fileinput.py b/Lib/test/test_fileinput.py index 819557d5e8686..014f19e6cbdb1 100644 --- a/Lib/test/test_fileinput.py +++ b/Lib/test/test_fileinput.py @@ -226,11 +226,19 @@ def test_fileno(self): self.assertEqual(fi.fileno(), -1) def test_opening_mode(self): - # invalid modes - for mode in ('w', 'rU', 'U'): - with self.subTest(mode=mode): - with self.assertRaises(ValueError): - FileInput(mode=mode) + try: + # invalid mode, should raise ValueError + fi = FileInput(mode="w") + self.fail("FileInput should reject invalid mode argument") + except ValueError: + pass + # try opening in universal newline mode + t1 = self.writeTmp(b"A\nB\r\nC\rD", mode="wb") + with check_warnings(('', DeprecationWarning)): + fi = FileInput(files=t1, mode="U") + with check_warnings(('', DeprecationWarning)): + lines = list(fi) + self.assertEqual(lines, ["A\n", "B\n", "C\n", "D"]) def test_stdin_binary_mode(self): with mock.patch('sys.stdin') as m_stdin: @@ -977,6 +985,10 @@ def check(mode, expected_lines): self.assertEqual(lines, expected_lines) check('r', ['A\n', 'B\n', 'C\n', 'D\u20ac']) + with self.assertWarns(DeprecationWarning): + check('rU', ['A\n', 'B\n', 'C\n', 'D\u20ac']) + with self.assertWarns(DeprecationWarning): + check('U', ['A\n', 'B\n', 'C\n', 'D\u20ac']) with self.assertRaises(ValueError): check('rb', ['A\n', 'B\r\n', 'C\r', 'D\u20ac']) diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py index c27dfd96bc00d..4a7cbe538cf93 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -3900,6 +3900,16 @@ def test_attributes(self): self.assertEqual(f.mode, "wb") f.close() + with support.check_warnings(('', DeprecationWarning)): + f = self.open(support.TESTFN, "U") + self.assertEqual(f.name, support.TESTFN) + self.assertEqual(f.buffer.name, support.TESTFN) + self.assertEqual(f.buffer.raw.name, support.TESTFN) + self.assertEqual(f.mode, "U") + self.assertEqual(f.buffer.mode, "rb") + self.assertEqual(f.buffer.raw.mode, "rb") + f.close() + f = self.open(support.TESTFN, "w+") self.assertEqual(f.mode, "w+") self.assertEqual(f.buffer.mode, "rb+") # Does it really matter? @@ -3913,13 +3923,6 @@ def test_attributes(self): f.close() g.close() - def test_removed_u_mode(self): - # "U" mode has been removed in Python 3.9 - for mode in ("U", "rU", "r+U"): - with self.assertRaises(ValueError) as cm: - self.open(support.TESTFN, mode) - self.assertIn('invalid mode', str(cm.exception)) - def test_open_pipe_with_append(self): # bpo-27805: Ignore ESPIPE from lseek() in open(). r, w = os.pipe() diff --git a/Misc/NEWS.d/next/Library/2020-03-03-16-21-41.bpo-39674.HJVkD5.rst b/Misc/NEWS.d/next/Library/2020-03-03-16-21-41.bpo-39674.HJVkD5.rst new file mode 100644 index 0000000000000..40f9c29d5d2de --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-03-03-16-21-41.bpo-39674.HJVkD5.rst @@ -0,0 +1,3 @@ +Revert "bpo-37330: open() no longer accept 'U' in file mode". The "U" mode of +open() is kept in Python 3.9 to ease transition from Python 2.7, but will be +removed in Python 3.10. diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index d609fa4afec61..534d7de103ed5 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -138,6 +138,7 @@ Character Meaning 'b' binary mode 't' text mode (default) '+' open a disk file for updating (reading and writing) +'U' universal newline mode (deprecated) ========= =============================================================== The default mode is 'rt' (open for reading text). For binary random @@ -153,6 +154,10 @@ bytes objects without any decoding. In text mode (the default, or when returned as strings, the bytes having been first decoded using a platform-dependent encoding or using the specified encoding if given. +'U' mode is deprecated and will raise an exception in future versions +of Python. It has no effect in Python 3. Use newline to control +universal newlines mode. + buffering is an optional integer used to set the buffering policy. Pass 0 to switch buffering off (only allowed in binary mode), 1 to select line buffering (only usable in text mode), and an integer > 1 to indicate @@ -228,12 +233,12 @@ static PyObject * _io_open_impl(PyObject *module, PyObject *file, const char *mode, int buffering, const char *encoding, const char *errors, const char *newline, int closefd, PyObject *opener) -/*[clinic end generated code: output=aefafc4ce2b46dc0 input=1543f4511d2356a5]*/ +/*[clinic end generated code: output=aefafc4ce2b46dc0 input=7295902222e6b311]*/ { unsigned i; int creating = 0, reading = 0, writing = 0, appending = 0, updating = 0; - int text = 0, binary = 0; + int text = 0, binary = 0, universal = 0; char rawmode[6], *m; int line_buffering, is_number; @@ -291,6 +296,10 @@ _io_open_impl(PyObject *module, PyObject *file, const char *mode, case 'b': binary = 1; break; + case 'U': + universal = 1; + reading = 1; + break; default: goto invalid_mode; } @@ -313,6 +322,18 @@ _io_open_impl(PyObject *module, PyObject *file, const char *mode, *m = '\0'; /* Parameters validation */ + if (universal) { + if (creating || writing || appending || updating) { + PyErr_SetString(PyExc_ValueError, + "mode U cannot be combined with 'x', 'w', 'a', or '+'"); + goto error; + } + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "'U' mode is deprecated", 1) < 0) + goto error; + reading = 1; + } + if (text && binary) { PyErr_SetString(PyExc_ValueError, "can't have text and binary mode at once"); diff --git a/Modules/_io/clinic/_iomodule.c.h b/Modules/_io/clinic/_iomodule.c.h index c1f518ff60273..1a9651d340813 100644 --- a/Modules/_io/clinic/_iomodule.c.h +++ b/Modules/_io/clinic/_iomodule.c.h @@ -36,6 +36,7 @@ PyDoc_STRVAR(_io_open__doc__, "\'b\' binary mode\n" "\'t\' text mode (default)\n" "\'+\' open a disk file for updating (reading and writing)\n" +"\'U\' universal newline mode (deprecated)\n" "========= ===============================================================\n" "\n" "The default mode is \'rt\' (open for reading text). For binary random\n" @@ -51,6 +52,10 @@ PyDoc_STRVAR(_io_open__doc__, "returned as strings, the bytes having been first decoded using a\n" "platform-dependent encoding or using the specified encoding if given.\n" "\n" +"\'U\' mode is deprecated and will raise an exception in future versions\n" +"of Python. It has no effect in Python 3. Use newline to control\n" +"universal newlines mode.\n" +"\n" "buffering is an optional integer used to set the buffering policy.\n" "Pass 0 to switch buffering off (only allowed in binary mode), 1 to select\n" "line buffering (only usable in text mode), and an integer > 1 to indicate\n" @@ -318,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=680e4b488c7da8a1 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=3df6bc6d91697545 input=a9049054013a1b77]*/ From webhook-mailer at python.org Wed Mar 4 14:46:57 2020 From: webhook-mailer at python.org (Steve Dower) Date: Wed, 04 Mar 2020 19:46:57 -0000 Subject: [Python-checkins] Allow python_uwp.vcxproj to build with toolset v142 if present (GH-18777) Message-ID: https://github.com/python/cpython/commit/a39353efc10df6b2ca13714222c4e610555bfb01 commit: a39353efc10df6b2ca13714222c4e610555bfb01 branch: 3.7 author: Steve Dower committer: GitHub date: 2020-03-04T19:46:50Z summary: Allow python_uwp.vcxproj to build with toolset v142 if present (GH-18777) files: M PCbuild/python_uwp.vcxproj M PCbuild/pythonw_uwp.vcxproj diff --git a/PCbuild/python_uwp.vcxproj b/PCbuild/python_uwp.vcxproj index 14e138cbed3e0..5d94a321d40db 100644 --- a/PCbuild/python_uwp.vcxproj +++ b/PCbuild/python_uwp.vcxproj @@ -36,6 +36,7 @@ {9DE9E23D-C8D4-4817-92A9-920A8B1FE5FF} + v142 diff --git a/PCbuild/pythonw_uwp.vcxproj b/PCbuild/pythonw_uwp.vcxproj index 79e105877fbeb..3da05e351d483 100644 --- a/PCbuild/pythonw_uwp.vcxproj +++ b/PCbuild/pythonw_uwp.vcxproj @@ -36,6 +36,7 @@ {AB603547-1E2A-45B3-9E09-B04596006393} + v142 From webhook-mailer at python.org Wed Mar 4 17:51:58 2020 From: webhook-mailer at python.org (Brett Cannon) Date: Wed, 04 Mar 2020 22:51:58 -0000 Subject: [Python-checkins] bpo-39808: Improve docs for pathlib.Path.stat() (GH-18719) Message-ID: https://github.com/python/cpython/commit/67152d0ed670227b61b5df683655b196ab04ca1a commit: 67152d0ed670227b61b5df683655b196ab04ca1a branch: master author: Brett Cannon <54418+brettcannon at users.noreply.github.com> committer: GitHub date: 2020-03-04T14:51:50-08:00 summary: bpo-39808: Improve docs for pathlib.Path.stat() (GH-18719) files: M Doc/library/pathlib.rst diff --git a/Doc/library/pathlib.rst b/Doc/library/pathlib.rst index 5906a33bdea11..7c0ffd50e2c79 100644 --- a/Doc/library/pathlib.rst +++ b/Doc/library/pathlib.rst @@ -685,7 +685,7 @@ call fails (for example because the path doesn't exist). .. method:: Path.stat() - Return information about this path (similarly to :func:`os.stat`). + Return a :class:`os.stat_result` object containing information about this path, like :func:`os.stat`. The result is looked up at each call to this method. :: From webhook-mailer at python.org Wed Mar 4 18:17:47 2020 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 04 Mar 2020 23:17:47 -0000 Subject: [Python-checkins] [3.7] bpo-39808: Improve docs for pathlib.Path.stat() (GH-18719) (GH-18782) Message-ID: https://github.com/python/cpython/commit/6bb67452d4f21e2d948dafce7644b1d66e5efcb8 commit: 6bb67452d4f21e2d948dafce7644b1d66e5efcb8 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2020-03-04T15:17:39-08:00 summary: [3.7] bpo-39808: Improve docs for pathlib.Path.stat() (GH-18719) (GH-18782) (cherry picked from commit 67152d0ed670227b61b5df683655b196ab04ca1a) Co-authored-by: Brett Cannon <54418+brettcannon at users.noreply.github.com> Automerge-Triggered-By: @brettcannon files: M Doc/library/pathlib.rst diff --git a/Doc/library/pathlib.rst b/Doc/library/pathlib.rst index 5b2df3feb7084..9ed5d9da55a21 100644 --- a/Doc/library/pathlib.rst +++ b/Doc/library/pathlib.rst @@ -662,7 +662,7 @@ call fails (for example because the path doesn't exist): .. method:: Path.stat() - Return information about this path (similarly to :func:`os.stat`). + Return a :class:`os.stat_result` object containing information about this path, like :func:`os.stat`. The result is looked up at each call to this method. :: From webhook-mailer at python.org Wed Mar 4 19:12:32 2020 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 05 Mar 2020 00:12:32 -0000 Subject: [Python-checkins] Add a missing space after a period in 'typing.TypedDict' documentation (GH-18784) Message-ID: https://github.com/python/cpython/commit/d4a09c13ddd91a9bc1b4ba76ff4e8a153334a1e2 commit: d4a09c13ddd91a9bc1b4ba76ff4e8a153334a1e2 branch: master author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2020-03-04T16:12:28-08:00 summary: Add a missing space after a period in 'typing.TypedDict' documentation (GH-18784) files: M Doc/library/typing.rst diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index eac75ee8654f5..58ae184578616 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -1004,7 +1004,7 @@ The module defines the following classes, functions and decorators: x: int y: int - This means that a point2D TypedDict can have any of the keys omitted.A type + This means that a point2D TypedDict can have any of the keys omitted. A type checker is only expected to support a literal False or True as the value of the total argument. True is the default, and makes all items defined in the class body be required. From webhook-mailer at python.org Wed Mar 4 19:18:27 2020 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 05 Mar 2020 00:18:27 -0000 Subject: [Python-checkins] Add a missing space after a period in 'typing.TypedDict' documentation (GH-18784) Message-ID: https://github.com/python/cpython/commit/5a3926d55922bf62faaeab664844dd69df04ab42 commit: 5a3926d55922bf62faaeab664844dd69df04ab42 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2020-03-04T16:18:22-08:00 summary: Add a missing space after a period in 'typing.TypedDict' documentation (GH-18784) (cherry picked from commit d4a09c13ddd91a9bc1b4ba76ff4e8a153334a1e2) Co-authored-by: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> files: M Doc/library/typing.rst diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index a9c7c4756dd0d..beb00fc8b61c2 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -1004,7 +1004,7 @@ The module defines the following classes, functions and decorators: x: int y: int - This means that a point2D TypedDict can have any of the keys omitted.A type + This means that a point2D TypedDict can have any of the keys omitted. A type checker is only expected to support a literal False or True as the value of the total argument. True is the default, and makes all items defined in the class body be required. From webhook-mailer at python.org Wed Mar 4 19:45:36 2020 From: webhook-mailer at python.org (Gregory P. Smith) Date: Thu, 05 Mar 2020 00:45:36 -0000 Subject: [Python-checkins] bpo-13487: Use sys.modules.copy() in inspect.getmodule() for thread safety. (GH-18786) Message-ID: https://github.com/python/cpython/commit/85cf1d514b84dc9a4bcb40e20a12e1d82ff19f20 commit: 85cf1d514b84dc9a4bcb40e20a12e1d82ff19f20 branch: master author: Gregory P. Smith committer: GitHub date: 2020-03-04T16:45:22-08:00 summary: bpo-13487: Use sys.modules.copy() in inspect.getmodule() for thread safety. (GH-18786) `list(sys.modules.items())` was apparently not immune to "dictionary changed size during iteration" errors. Tested internally using an integration test that has run into this a couple of times in the past two years. With this patch applied, the test is no longer flaky. files: A Misc/NEWS.d/next/Library/2020-03-04-16-10-59.bpo-13487.gqe4Fb.rst M Lib/inspect.py diff --git a/Lib/inspect.py b/Lib/inspect.py index bb82f96fdf374..125bd456a1c46 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -741,7 +741,7 @@ def getmodule(object, _filename=None): return sys.modules.get(modulesbyfile[file]) # Update the filename to module name cache and check yet again # Copy sys.modules in order to cope with changes while iterating - for modname, module in list(sys.modules.items()): + for modname, module in sys.modules.copy().items(): if ismodule(module) and hasattr(module, '__file__'): f = module.__file__ if f == _filesbymodname.get(modname, None): diff --git a/Misc/NEWS.d/next/Library/2020-03-04-16-10-59.bpo-13487.gqe4Fb.rst b/Misc/NEWS.d/next/Library/2020-03-04-16-10-59.bpo-13487.gqe4Fb.rst new file mode 100644 index 0000000000000..5a1f02a7bdf37 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-03-04-16-10-59.bpo-13487.gqe4Fb.rst @@ -0,0 +1,3 @@ +Avoid a possible *"RuntimeError: dictionary changed size during iteration"* +from :func:`inspect.getmodule` when it tried to loop through +:attr:`sys.modules`. From webhook-mailer at python.org Wed Mar 4 20:03:36 2020 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 05 Mar 2020 01:03:36 -0000 Subject: [Python-checkins] bpo-13487: Use sys.modules.copy() in inspect.getmodule() for thread safety. (GH-18786) Message-ID: https://github.com/python/cpython/commit/a12381233a243ba7d5151ebf060feb57dd540bef commit: a12381233a243ba7d5151ebf060feb57dd540bef branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2020-03-04T17:03:29-08:00 summary: bpo-13487: Use sys.modules.copy() in inspect.getmodule() for thread safety. (GH-18786) `list(sys.modules.items())` was apparently not immune to "dictionary changed size during iteration" errors. Tested internally using an integration test that has run into this a couple of times in the past two years. With this patch applied, the test is no longer flaky. (cherry picked from commit 85cf1d514b84dc9a4bcb40e20a12e1d82ff19f20) Co-authored-by: Gregory P. Smith files: A Misc/NEWS.d/next/Library/2020-03-04-16-10-59.bpo-13487.gqe4Fb.rst M Lib/inspect.py diff --git a/Lib/inspect.py b/Lib/inspect.py index bbecd98f94abd..9848ca4c50775 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -729,7 +729,7 @@ def getmodule(object, _filename=None): return sys.modules.get(modulesbyfile[file]) # Update the filename to module name cache and check yet again # Copy sys.modules in order to cope with changes while iterating - for modname, module in list(sys.modules.items()): + for modname, module in sys.modules.copy().items(): if ismodule(module) and hasattr(module, '__file__'): f = module.__file__ if f == _filesbymodname.get(modname, None): diff --git a/Misc/NEWS.d/next/Library/2020-03-04-16-10-59.bpo-13487.gqe4Fb.rst b/Misc/NEWS.d/next/Library/2020-03-04-16-10-59.bpo-13487.gqe4Fb.rst new file mode 100644 index 0000000000000..5a1f02a7bdf37 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-03-04-16-10-59.bpo-13487.gqe4Fb.rst @@ -0,0 +1,3 @@ +Avoid a possible *"RuntimeError: dictionary changed size during iteration"* +from :func:`inspect.getmodule` when it tried to loop through +:attr:`sys.modules`. From webhook-mailer at python.org Wed Mar 4 20:04:43 2020 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 05 Mar 2020 01:04:43 -0000 Subject: [Python-checkins] bpo-13487: Use sys.modules.copy() in inspect.getmodule() for thread safety. (GH-18786) Message-ID: https://github.com/python/cpython/commit/6b452ff97f70eca79ab956987cc04b6586feca00 commit: 6b452ff97f70eca79ab956987cc04b6586feca00 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2020-03-04T17:04:38-08:00 summary: bpo-13487: Use sys.modules.copy() in inspect.getmodule() for thread safety. (GH-18786) `list(sys.modules.items())` was apparently not immune to "dictionary changed size during iteration" errors. Tested internally using an integration test that has run into this a couple of times in the past two years. With this patch applied, the test is no longer flaky. (cherry picked from commit 85cf1d514b84dc9a4bcb40e20a12e1d82ff19f20) Co-authored-by: Gregory P. Smith files: A Misc/NEWS.d/next/Library/2020-03-04-16-10-59.bpo-13487.gqe4Fb.rst M Lib/inspect.py diff --git a/Lib/inspect.py b/Lib/inspect.py index 3ff395ca33377..e8ea8c221f828 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -741,7 +741,7 @@ def getmodule(object, _filename=None): return sys.modules.get(modulesbyfile[file]) # Update the filename to module name cache and check yet again # Copy sys.modules in order to cope with changes while iterating - for modname, module in list(sys.modules.items()): + for modname, module in sys.modules.copy().items(): if ismodule(module) and hasattr(module, '__file__'): f = module.__file__ if f == _filesbymodname.get(modname, None): diff --git a/Misc/NEWS.d/next/Library/2020-03-04-16-10-59.bpo-13487.gqe4Fb.rst b/Misc/NEWS.d/next/Library/2020-03-04-16-10-59.bpo-13487.gqe4Fb.rst new file mode 100644 index 0000000000000..5a1f02a7bdf37 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-03-04-16-10-59.bpo-13487.gqe4Fb.rst @@ -0,0 +1,3 @@ +Avoid a possible *"RuntimeError: dictionary changed size during iteration"* +from :func:`inspect.getmodule` when it tried to loop through +:attr:`sys.modules`. From webhook-mailer at python.org Thu Mar 5 08:29:03 2020 From: webhook-mailer at python.org (Victor Stinner) Date: Thu, 05 Mar 2020 13:29:03 -0000 Subject: [Python-checkins] bpo-39855: Fix test_subprocess if nobody user doesn't exist (GH-18781) Message-ID: https://github.com/python/cpython/commit/f7b5d419bf871d9cc898982c7b6b4c043f7d5e9d commit: f7b5d419bf871d9cc898982c7b6b4c043f7d5e9d branch: master author: Victor Stinner committer: GitHub date: 2020-03-05T14:28:40+01:00 summary: bpo-39855: Fix test_subprocess if nobody user doesn't exist (GH-18781) test_subprocess.test_user() now skips the test on an user name if the user name doesn't exist. For example, skip the test if the user "nobody" doesn't exist on Linux. files: A Misc/NEWS.d/next/Tests/2020-03-04-23-03-01.bpo-39855.Ql5xv8.rst M Lib/test/test_subprocess.py diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index 2bbdbaef84e99..1cebf6b24a69e 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -1791,7 +1791,12 @@ def test_user(self): name_uid = "nobody" if sys.platform != 'darwin' else "unknown" if pwd is not None: - test_users.append(name_uid) + try: + pwd.getpwnam(name_uid) + test_users.append(name_uid) + except KeyError: + # unknown user name + name_uid = None for user in test_users: # posix_spawn() may be used with close_fds=False @@ -1819,7 +1824,7 @@ def test_user(self): with self.assertRaises(ValueError): subprocess.check_call(ZERO_RETURN_CMD, user=-1) - if pwd is None: + if pwd is None and name_uid is not None: with self.assertRaises(ValueError): subprocess.check_call(ZERO_RETURN_CMD, user=name_uid) diff --git a/Misc/NEWS.d/next/Tests/2020-03-04-23-03-01.bpo-39855.Ql5xv8.rst b/Misc/NEWS.d/next/Tests/2020-03-04-23-03-01.bpo-39855.Ql5xv8.rst new file mode 100644 index 0000000000000..060124129042d --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2020-03-04-23-03-01.bpo-39855.Ql5xv8.rst @@ -0,0 +1,3 @@ +test_subprocess.test_user() now skips the test on an user name if the user +name doesn't exist. For example, skip the test if the user "nobody" doesn't +exist on Linux. From webhook-mailer at python.org Thu Mar 5 12:14:03 2020 From: webhook-mailer at python.org (Victor Stinner) Date: Thu, 05 Mar 2020 17:14:03 -0000 Subject: [Python-checkins] Add a comment to _Py_RestoreSignals() (GH-18792) Message-ID: https://github.com/python/cpython/commit/efc28bbbeee07867669dfbf49385d6a2147fe631 commit: efc28bbbeee07867669dfbf49385d6a2147fe631 branch: master author: Victor Stinner committer: GitHub date: 2020-03-05T18:13:56+01:00 summary: Add a comment to _Py_RestoreSignals() (GH-18792) subprocess _posix_spawn() should stay in sync with _Py_RestoreSignals(). files: M Python/pylifecycle.c diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 7fa165b736869..84ced424499de 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -2374,6 +2374,8 @@ init_signals(PyThreadState *tstate) * All of the code in this function must only use async-signal-safe functions, * listed at `man 7 signal` or * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html. + * + * If this function is updated, update also _posix_spawn() of subprocess.py. */ void _Py_RestoreSignals(void) From webhook-mailer at python.org Thu Mar 5 13:37:02 2020 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 05 Mar 2020 18:37:02 -0000 Subject: [Python-checkins] [3.8] bpo-39808: Improve docs for pathlib.Path.stat() (GH-18719) (GH-18783) Message-ID: https://github.com/python/cpython/commit/7b39c474e4ce7057a9e16b06d40261ff563b1e9d commit: 7b39c474e4ce7057a9e16b06d40261ff563b1e9d branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2020-03-05T10:36:54-08:00 summary: [3.8] bpo-39808: Improve docs for pathlib.Path.stat() (GH-18719) (GH-18783) (cherry picked from commit 67152d0ed670227b61b5df683655b196ab04ca1a) Co-authored-by: Brett Cannon <54418+brettcannon at users.noreply.github.com> Automerge-Triggered-By: @brettcannon files: M Doc/library/pathlib.rst diff --git a/Doc/library/pathlib.rst b/Doc/library/pathlib.rst index 326bb2e933cdb..03408145cf572 100644 --- a/Doc/library/pathlib.rst +++ b/Doc/library/pathlib.rst @@ -672,7 +672,7 @@ call fails (for example because the path doesn't exist). .. method:: Path.stat() - Return information about this path (similarly to :func:`os.stat`). + Return a :class:`os.stat_result` object containing information about this path, like :func:`os.stat`. The result is looked up at each call to this method. :: From webhook-mailer at python.org Thu Mar 5 20:28:21 2020 From: webhook-mailer at python.org (Jules Lasne (jlasne)) Date: Fri, 06 Mar 2020 01:28:21 -0000 Subject: [Python-checkins] IDLE doc: improve Startup failure subsection. (#18771) Message-ID: https://github.com/python/cpython/commit/ce305d641074931e4e790f7a83e28f74910644e5 commit: ce305d641074931e4e790f7a83e28f74910644e5 branch: master author: Jules Lasne (jlasne) committer: GitHub date: 2020-03-05T20:28:14-05:00 summary: IDLE doc: improve Startup failure subsection. (#18771) Eliminate repeat of 'Options', reported by Jules Lasne, and improve wording elsewhere. Co-authored-by: Terry Jan Reedy files: M Doc/library/idle.rst diff --git a/Doc/library/idle.rst b/Doc/library/idle.rst index f15f46b788b36..fd6e309567de3 100644 --- a/Doc/library/idle.rst +++ b/Doc/library/idle.rst @@ -681,19 +681,22 @@ clash, or cannot or does not want to run as admin, it might be easiest to completely remove Python and start over. A zombie pythonw.exe process could be a problem. On Windows, use Task -Manager to detect and stop one. Sometimes a restart initiated by a program -crash or Keyboard Interrupt (control-C) may fail to connect. Dismissing -the error box or Restart Shell on the Shell menu may fix a temporary problem. +Manager to check for one and stop it if there is. Sometimes a restart +initiated by a program crash or Keyboard Interrupt (control-C) may fail +to connect. Dismissing the error box or using Restart Shell on the Shell +menu may fix a temporary problem. When IDLE first starts, it attempts to read user configuration files in ``~/.idlerc/`` (~ is one's home directory). If there is a problem, an error message should be displayed. Leaving aside random disk glitches, this can -be prevented by never editing the files by hand, using the configuration -dialog, under Options, instead Options. Once it happens, the solution may -be to delete one or more of the configuration files. +be prevented by never editing the files by hand. Instead, use the +configuration dialog, under Options. Once there is an error in a user +configuration file, the best solution may be to delete it and start over +with the settings dialog. If IDLE quits with no message, and it was not started from a console, try -starting from a console (``python -m idlelib``) and see if a message appears. +starting it from a console or terminal (``python -m idlelib``) and see if +this results in an error message. Running user code ^^^^^^^^^^^^^^^^^ From webhook-mailer at python.org Thu Mar 5 20:33:52 2020 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 06 Mar 2020 01:33:52 -0000 Subject: [Python-checkins] IDLE doc: improve Startup failure subsection. (GH-18771) Message-ID: https://github.com/python/cpython/commit/3c9cec0b2ecd34d81c28c08ba0566794724194b6 commit: 3c9cec0b2ecd34d81c28c08ba0566794724194b6 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2020-03-05T17:33:48-08:00 summary: IDLE doc: improve Startup failure subsection. (GH-18771) Eliminate repeat of 'Options', reported by Jules Lasne, and improve wording elsewhere. Co-authored-by: Terry Jan Reedy (cherry picked from commit ce305d641074931e4e790f7a83e28f74910644e5) Co-authored-by: Jules Lasne (jlasne) files: M Doc/library/idle.rst diff --git a/Doc/library/idle.rst b/Doc/library/idle.rst index f15f46b788b36..fd6e309567de3 100644 --- a/Doc/library/idle.rst +++ b/Doc/library/idle.rst @@ -681,19 +681,22 @@ clash, or cannot or does not want to run as admin, it might be easiest to completely remove Python and start over. A zombie pythonw.exe process could be a problem. On Windows, use Task -Manager to detect and stop one. Sometimes a restart initiated by a program -crash or Keyboard Interrupt (control-C) may fail to connect. Dismissing -the error box or Restart Shell on the Shell menu may fix a temporary problem. +Manager to check for one and stop it if there is. Sometimes a restart +initiated by a program crash or Keyboard Interrupt (control-C) may fail +to connect. Dismissing the error box or using Restart Shell on the Shell +menu may fix a temporary problem. When IDLE first starts, it attempts to read user configuration files in ``~/.idlerc/`` (~ is one's home directory). If there is a problem, an error message should be displayed. Leaving aside random disk glitches, this can -be prevented by never editing the files by hand, using the configuration -dialog, under Options, instead Options. Once it happens, the solution may -be to delete one or more of the configuration files. +be prevented by never editing the files by hand. Instead, use the +configuration dialog, under Options. Once there is an error in a user +configuration file, the best solution may be to delete it and start over +with the settings dialog. If IDLE quits with no message, and it was not started from a console, try -starting from a console (``python -m idlelib``) and see if a message appears. +starting it from a console or terminal (``python -m idlelib``) and see if +this results in an error message. Running user code ^^^^^^^^^^^^^^^^^ From webhook-mailer at python.org Thu Mar 5 20:35:47 2020 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 06 Mar 2020 01:35:47 -0000 Subject: [Python-checkins] IDLE doc: improve Startup failure subsection. (GH-18771) Message-ID: https://github.com/python/cpython/commit/da9ee00ffea9120bea4b5f0cbed20f9fb584d2a2 commit: da9ee00ffea9120bea4b5f0cbed20f9fb584d2a2 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2020-03-05T17:35:43-08:00 summary: IDLE doc: improve Startup failure subsection. (GH-18771) Eliminate repeat of 'Options', reported by Jules Lasne, and improve wording elsewhere. Co-authored-by: Terry Jan Reedy (cherry picked from commit ce305d641074931e4e790f7a83e28f74910644e5) Co-authored-by: Jules Lasne (jlasne) files: M Doc/library/idle.rst diff --git a/Doc/library/idle.rst b/Doc/library/idle.rst index f15f46b788b36..fd6e309567de3 100644 --- a/Doc/library/idle.rst +++ b/Doc/library/idle.rst @@ -681,19 +681,22 @@ clash, or cannot or does not want to run as admin, it might be easiest to completely remove Python and start over. A zombie pythonw.exe process could be a problem. On Windows, use Task -Manager to detect and stop one. Sometimes a restart initiated by a program -crash or Keyboard Interrupt (control-C) may fail to connect. Dismissing -the error box or Restart Shell on the Shell menu may fix a temporary problem. +Manager to check for one and stop it if there is. Sometimes a restart +initiated by a program crash or Keyboard Interrupt (control-C) may fail +to connect. Dismissing the error box or using Restart Shell on the Shell +menu may fix a temporary problem. When IDLE first starts, it attempts to read user configuration files in ``~/.idlerc/`` (~ is one's home directory). If there is a problem, an error message should be displayed. Leaving aside random disk glitches, this can -be prevented by never editing the files by hand, using the configuration -dialog, under Options, instead Options. Once it happens, the solution may -be to delete one or more of the configuration files. +be prevented by never editing the files by hand. Instead, use the +configuration dialog, under Options. Once there is an error in a user +configuration file, the best solution may be to delete it and start over +with the settings dialog. If IDLE quits with no message, and it was not started from a console, try -starting from a console (``python -m idlelib``) and see if a message appears. +starting it from a console or terminal (``python -m idlelib``) and see if +this results in an error message. Running user code ^^^^^^^^^^^^^^^^^ From webhook-mailer at python.org Thu Mar 5 23:34:43 2020 From: webhook-mailer at python.org (Andy Lester) Date: Fri, 06 Mar 2020 04:34:43 -0000 Subject: [Python-checkins] closes bpo-39870: Remove unused arg from sys_displayhook_unencodable. (GH-18796) Message-ID: https://github.com/python/cpython/commit/da4d656e951b00580d135ae6345656ecedf9d8d4 commit: da4d656e951b00580d135ae6345656ecedf9d8d4 branch: master author: Andy Lester committer: GitHub date: 2020-03-05T20:34:36-08:00 summary: closes bpo-39870: Remove unused arg from sys_displayhook_unencodable. (GH-18796) Also move int err to its innermost scope. files: M Python/sysmodule.c diff --git a/Python/sysmodule.c b/Python/sysmodule.c index cacff529758c6..bfacf314dfc9e 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -551,7 +551,7 @@ PyDoc_STRVAR(breakpointhook_doc, Helper function for sys_displayhook(). */ static int -sys_displayhook_unencodable(PyThreadState *tstate, PyObject *outf, PyObject *o) +sys_displayhook_unencodable(PyObject *outf, PyObject *o) { PyObject *stdout_encoding = NULL; PyObject *encoded, *escaped_str, *repr_str, *buffer, *result; @@ -624,7 +624,6 @@ sys_displayhook(PyObject *module, PyObject *o) PyObject *outf; PyObject *builtins; static PyObject *newline = NULL; - int err; PyThreadState *tstate = _PyThreadState_GET(); builtins = _PyImport_GetModuleId(&PyId_builtins); @@ -652,10 +651,11 @@ sys_displayhook(PyObject *module, PyObject *o) } if (PyFile_WriteObject(o, outf, 0) != 0) { if (_PyErr_ExceptionMatches(tstate, PyExc_UnicodeEncodeError)) { + int err; /* repr(o) is not encodable to sys.stdout.encoding with * sys.stdout.errors error handler (which is probably 'strict') */ _PyErr_Clear(tstate); - err = sys_displayhook_unencodable(tstate, outf, o); + err = sys_displayhook_unencodable(outf, o); if (err) { return NULL; } From webhook-mailer at python.org Thu Mar 5 23:43:43 2020 From: webhook-mailer at python.org (Andy Lester) Date: Fri, 06 Mar 2020 04:43:43 -0000 Subject: [Python-checkins] closes bpo-39859: Do not downcast result of hstrerror (GH-18790) Message-ID: https://github.com/python/cpython/commit/e63117a84ef11083be86db7afb2ac2789491ca09 commit: e63117a84ef11083be86db7afb2ac2789491ca09 branch: master author: Andy Lester committer: GitHub date: 2020-03-05T20:43:36-08:00 summary: closes bpo-39859: Do not downcast result of hstrerror (GH-18790) set_herror builds a string by calling hstrerror but downcasts its return value to char *. It should be const char *. Automerge-Triggered-By: @benjaminp files: M Modules/socketmodule.c diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 37b312396f944..2818ac7f20570 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -658,7 +658,7 @@ set_herror(int h_error) PyObject *v; #ifdef HAVE_HSTRERROR - v = Py_BuildValue("(is)", h_error, (char *)hstrerror(h_error)); + v = Py_BuildValue("(is)", h_error, hstrerror(h_error)); #else v = Py_BuildValue("(is)", h_error, "host not found"); #endif From webhook-mailer at python.org Fri Mar 6 00:19:26 2020 From: webhook-mailer at python.org (Brandt Bucher) Date: Fri, 06 Mar 2020 05:19:26 -0000 Subject: [Python-checkins] bpo-39868: Update Language Reference for PEP 572. (#18793) Message-ID: https://github.com/python/cpython/commit/8bae21962bab2fac7630982abd73676b89930902 commit: 8bae21962bab2fac7630982abd73676b89930902 branch: master author: Brandt Bucher committer: GitHub date: 2020-03-05T21:19:22-08:00 summary: bpo-39868: Update Language Reference for PEP 572. (#18793) files: A Misc/NEWS.d/next/Documentation/2020-03-05-16-29-03.bpo-39868.JQoHhO.rst M Doc/reference/compound_stmts.rst M Doc/reference/expressions.rst diff --git a/Doc/reference/compound_stmts.rst b/Doc/reference/compound_stmts.rst index e2f44a55b180b..ac2065b4cff9b 100644 --- a/Doc/reference/compound_stmts.rst +++ b/Doc/reference/compound_stmts.rst @@ -90,8 +90,8 @@ The :keyword:`!if` statement The :keyword:`if` statement is used for conditional execution: .. productionlist:: - if_stmt: "if" `expression` ":" `suite` - : ("elif" `expression` ":" `suite`)* + if_stmt: "if" `assignment_expression` ":" `suite` + : ("elif" `assignment_expression` ":" `suite`)* : ["else" ":" `suite`] It selects exactly one of the suites by evaluating the expressions one by one @@ -116,7 +116,7 @@ The :keyword:`while` statement is used for repeated execution as long as an expression is true: .. productionlist:: - while_stmt: "while" `expression` ":" `suite` + while_stmt: "while" `assignment_expression` ":" `suite` : ["else" ":" `suite`] This repeatedly tests the expression and, if it is true, executes the first diff --git a/Doc/reference/expressions.rst b/Doc/reference/expressions.rst index d9db33a78568e..3fcc5e17d9a7c 100644 --- a/Doc/reference/expressions.rst +++ b/Doc/reference/expressions.rst @@ -178,7 +178,7 @@ called "displays", each of them in two flavors: Common syntax elements for comprehensions are: .. productionlist:: - comprehension: `expression` `comp_for` + comprehension: `assignment_expression` `comp_for` comp_for: ["async"] "for" `target_list` "in" `or_test` [`comp_iter`] comp_iter: `comp_for` | `comp_if` comp_if: "if" `expression_nocond` [`comp_iter`] @@ -911,7 +911,8 @@ series of :term:`arguments `: : ["," `keywords_arguments`] : | `starred_and_keywords` ["," `keywords_arguments`] : | `keywords_arguments` - positional_arguments: ["*"] `expression` ("," ["*"] `expression`)* + positional_arguments: positional_item ("," positional_item)* + positional_item: `assignment_expression` | "*" `expression` starred_and_keywords: ("*" `expression` | `keyword_item`) : ("," "*" `expression` | "," `keyword_item`)* keywords_arguments: (`keyword_item` | "**" `expression`) @@ -1642,6 +1643,17 @@ returns a boolean value regardless of the type of its argument (for example, ``not 'foo'`` produces ``False`` rather than ``''``.) +Assignment expressions +====================== + +.. productionlist:: + assignment_expression: [`identifier` ":="] `expression` + +.. TODO: BPO-39868 + +See :pep:`572` for more details about assignment expressions. + + .. _if_expr: Conditional expressions @@ -1711,7 +1723,7 @@ Expression lists expression_list: `expression` ("," `expression`)* [","] starred_list: `starred_item` ("," `starred_item`)* [","] starred_expression: `expression` | (`starred_item` ",")* [`starred_item`] - starred_item: `expression` | "*" `or_expr` + starred_item: `assignment_expression` | "*" `or_expr` .. index:: object: tuple diff --git a/Misc/NEWS.d/next/Documentation/2020-03-05-16-29-03.bpo-39868.JQoHhO.rst b/Misc/NEWS.d/next/Documentation/2020-03-05-16-29-03.bpo-39868.JQoHhO.rst new file mode 100644 index 0000000000000..9fa8bfd04f7db --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2020-03-05-16-29-03.bpo-39868.JQoHhO.rst @@ -0,0 +1 @@ +Updated the Language Reference for :pep:`572`. From webhook-mailer at python.org Fri Mar 6 00:25:19 2020 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 06 Mar 2020 05:25:19 -0000 Subject: [Python-checkins] bpo-39868: Update Language Reference for PEP 572. (GH-18793) Message-ID: https://github.com/python/cpython/commit/0c71770eeee9c1b19b6f146b56db5f10bab3f09c commit: 0c71770eeee9c1b19b6f146b56db5f10bab3f09c branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2020-03-05T21:25:15-08:00 summary: bpo-39868: Update Language Reference for PEP 572. (GH-18793) (cherry picked from commit 8bae21962bab2fac7630982abd73676b89930902) Co-authored-by: Brandt Bucher files: A Misc/NEWS.d/next/Documentation/2020-03-05-16-29-03.bpo-39868.JQoHhO.rst M Doc/reference/compound_stmts.rst M Doc/reference/expressions.rst diff --git a/Doc/reference/compound_stmts.rst b/Doc/reference/compound_stmts.rst index 564d6cc42136d..feaf3109d5a24 100644 --- a/Doc/reference/compound_stmts.rst +++ b/Doc/reference/compound_stmts.rst @@ -90,8 +90,8 @@ The :keyword:`!if` statement The :keyword:`if` statement is used for conditional execution: .. productionlist:: - if_stmt: "if" `expression` ":" `suite` - : ("elif" `expression` ":" `suite`)* + if_stmt: "if" `assignment_expression` ":" `suite` + : ("elif" `assignment_expression` ":" `suite`)* : ["else" ":" `suite`] It selects exactly one of the suites by evaluating the expressions one by one @@ -116,7 +116,7 @@ The :keyword:`while` statement is used for repeated execution as long as an expression is true: .. productionlist:: - while_stmt: "while" `expression` ":" `suite` + while_stmt: "while" `assignment_expression` ":" `suite` : ["else" ":" `suite`] This repeatedly tests the expression and, if it is true, executes the first diff --git a/Doc/reference/expressions.rst b/Doc/reference/expressions.rst index d9db33a78568e..3fcc5e17d9a7c 100644 --- a/Doc/reference/expressions.rst +++ b/Doc/reference/expressions.rst @@ -178,7 +178,7 @@ called "displays", each of them in two flavors: Common syntax elements for comprehensions are: .. productionlist:: - comprehension: `expression` `comp_for` + comprehension: `assignment_expression` `comp_for` comp_for: ["async"] "for" `target_list` "in" `or_test` [`comp_iter`] comp_iter: `comp_for` | `comp_if` comp_if: "if" `expression_nocond` [`comp_iter`] @@ -911,7 +911,8 @@ series of :term:`arguments `: : ["," `keywords_arguments`] : | `starred_and_keywords` ["," `keywords_arguments`] : | `keywords_arguments` - positional_arguments: ["*"] `expression` ("," ["*"] `expression`)* + positional_arguments: positional_item ("," positional_item)* + positional_item: `assignment_expression` | "*" `expression` starred_and_keywords: ("*" `expression` | `keyword_item`) : ("," "*" `expression` | "," `keyword_item`)* keywords_arguments: (`keyword_item` | "**" `expression`) @@ -1642,6 +1643,17 @@ returns a boolean value regardless of the type of its argument (for example, ``not 'foo'`` produces ``False`` rather than ``''``.) +Assignment expressions +====================== + +.. productionlist:: + assignment_expression: [`identifier` ":="] `expression` + +.. TODO: BPO-39868 + +See :pep:`572` for more details about assignment expressions. + + .. _if_expr: Conditional expressions @@ -1711,7 +1723,7 @@ Expression lists expression_list: `expression` ("," `expression`)* [","] starred_list: `starred_item` ("," `starred_item`)* [","] starred_expression: `expression` | (`starred_item` ",")* [`starred_item`] - starred_item: `expression` | "*" `or_expr` + starred_item: `assignment_expression` | "*" `or_expr` .. index:: object: tuple diff --git a/Misc/NEWS.d/next/Documentation/2020-03-05-16-29-03.bpo-39868.JQoHhO.rst b/Misc/NEWS.d/next/Documentation/2020-03-05-16-29-03.bpo-39868.JQoHhO.rst new file mode 100644 index 0000000000000..9fa8bfd04f7db --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2020-03-05-16-29-03.bpo-39868.JQoHhO.rst @@ -0,0 +1 @@ +Updated the Language Reference for :pep:`572`. From webhook-mailer at python.org Fri Mar 6 03:04:05 2020 From: webhook-mailer at python.org (Andy Lester) Date: Fri, 06 Mar 2020 08:04:05 -0000 Subject: [Python-checkins] bpo-39573: Make Py_IS_TYPE() take constant parameters (GH-18799) Message-ID: https://github.com/python/cpython/commit/8767ce92d24d3687405848442e6c67cf0af1c657 commit: 8767ce92d24d3687405848442e6c67cf0af1c657 branch: master author: Andy Lester committer: GitHub date: 2020-03-06T09:03:58+01:00 summary: bpo-39573: Make Py_IS_TYPE() take constant parameters (GH-18799) Add _PyObject_CAST_CONST() macro: cast a pointer to (const PyObject *). files: M Include/object.h diff --git a/Include/object.h b/Include/object.h index 3d0da52c2b6b1..6b6c66a52a6b0 100644 --- a/Include/object.h +++ b/Include/object.h @@ -110,6 +110,7 @@ typedef struct _object { /* Cast argument to PyObject* type. */ #define _PyObject_CAST(op) ((PyObject*)(op)) +#define _PyObject_CAST_CONST(op) ((const PyObject*)(op)) typedef struct { PyObject ob_base; @@ -123,10 +124,10 @@ typedef struct { #define Py_TYPE(ob) (_PyObject_CAST(ob)->ob_type) #define Py_SIZE(ob) (_PyVarObject_CAST(ob)->ob_size) -static inline int _Py_IS_TYPE(PyObject *ob, PyTypeObject *type) { +static inline int _Py_IS_TYPE(const PyObject *ob, const PyTypeObject *type) { return ob->ob_type == type; } -#define Py_IS_TYPE(ob, type) _Py_IS_TYPE(_PyObject_CAST(ob), type) +#define Py_IS_TYPE(ob, type) _Py_IS_TYPE(_PyObject_CAST_CONST(ob), type) static inline void _Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) { ob->ob_refcnt = refcnt; From webhook-mailer at python.org Fri Mar 6 06:08:24 2020 From: webhook-mailer at python.org (Slam) Date: Fri, 06 Mar 2020 11:08:24 -0000 Subject: [Python-checkins] PyPy already supports Python 3 (GH-18774) Message-ID: https://github.com/python/cpython/commit/7598a93139a8d76a331d5f30121277031044d35b commit: 7598a93139a8d76a331d5f30121277031044d35b branch: master author: Slam <3lnc.slam at gmail.com> committer: GitHub date: 2020-03-06T11:08:17Z summary: PyPy already supports Python 3 (GH-18774) files: M Doc/howto/logging.rst diff --git a/Doc/howto/logging.rst b/Doc/howto/logging.rst index fbe5a118d1868..6316e086ef43b 100644 --- a/Doc/howto/logging.rst +++ b/Doc/howto/logging.rst @@ -1086,8 +1086,7 @@ need: | | :func:`sys._getframe`, which may help | | | to speed up your code in environments | | | like PyPy (which can't speed up code | -| | that uses :func:`sys._getframe`), if | -| | and when PyPy supports Python 3.x. | +| | that uses :func:`sys._getframe`). | +-----------------------------------------------+----------------------------------------+ | Threading information. | Set ``logging.logThreads`` to ``0``. | +-----------------------------------------------+----------------------------------------+ From webhook-mailer at python.org Fri Mar 6 09:55:36 2020 From: webhook-mailer at python.org (Victor Stinner) Date: Fri, 06 Mar 2020 14:55:36 -0000 Subject: [Python-checkins] bpo-39873: PyObject_Init() uses PyObject_INIT() (GH-18804) Message-ID: https://github.com/python/cpython/commit/1fb5a9f394a6fdf62e21b96080c3257c959cf8c9 commit: 1fb5a9f394a6fdf62e21b96080c3257c959cf8c9 branch: master author: Victor Stinner committer: GitHub date: 2020-03-06T15:55:14+01:00 summary: bpo-39873: PyObject_Init() uses PyObject_INIT() (GH-18804) Avoid duplicated code: * PyObject_Init() uses PyObject_INIT() * PyObject_InitVar() uses PyObject_INIT_VAR() files: M Objects/object.c diff --git a/Objects/object.c b/Objects/object.c index 9c74e07eddcb1..707424c98fe7d 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -144,12 +144,7 @@ PyObject_Init(PyObject *op, PyTypeObject *tp) return PyErr_NoMemory(); } - Py_SET_TYPE(op, tp); - if (PyType_GetFlags(tp) & Py_TPFLAGS_HEAPTYPE) { - Py_INCREF(tp); - } - _Py_NewReference(op); - return op; + return PyObject_INIT(op, tp); } PyVarObject * @@ -160,9 +155,7 @@ PyObject_InitVar(PyVarObject *op, PyTypeObject *tp, Py_ssize_t size) return (PyVarObject *) PyErr_NoMemory(); } - Py_SET_SIZE(op, size); - PyObject_Init((PyObject *)op, tp); - return op; + return PyObject_INIT_VAR(op, tp, size); } PyObject * From webhook-mailer at python.org Fri Mar 6 10:46:11 2020 From: webhook-mailer at python.org (Andy Lester) Date: Fri, 06 Mar 2020 15:46:11 -0000 Subject: [Python-checkins] closes bpo-39872: Remove unused args from symtable_exit_block and symtable_visit_annotations. (GH-18800) Message-ID: https://github.com/python/cpython/commit/9566842e892c1f600e1dcfadaab4643be8f32901 commit: 9566842e892c1f600e1dcfadaab4643be8f32901 branch: master author: Andy Lester committer: GitHub date: 2020-03-06T07:46:04-08:00 summary: closes bpo-39872: Remove unused args from symtable_exit_block and symtable_visit_annotations. (GH-18800) files: M Python/symtable.c diff --git a/Python/symtable.c b/Python/symtable.c index a98a0fa6092cc..290e41b64acea 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -190,7 +190,7 @@ static int symtable_analyze(struct symtable *st); static int symtable_enter_block(struct symtable *st, identifier name, _Py_block_ty block, void *ast, int lineno, int col_offset); -static int symtable_exit_block(struct symtable *st, void *ast); +static int symtable_exit_block(struct symtable *st); static int symtable_visit_stmt(struct symtable *st, stmt_ty s); static int symtable_visit_expr(struct symtable *st, expr_ty s); static int symtable_visit_genexp(struct symtable *st, expr_ty s); @@ -206,7 +206,7 @@ static int symtable_visit_slice(struct symtable *st, slice_ty); static int symtable_visit_params(struct symtable *st, asdl_seq *args); static int symtable_visit_argannotations(struct symtable *st, asdl_seq *args); static int symtable_implicit_arg(struct symtable *st, int pos); -static int symtable_visit_annotations(struct symtable *st, stmt_ty s, arguments_ty, expr_ty); +static int symtable_visit_annotations(struct symtable *st, arguments_ty, expr_ty); static int symtable_visit_withitem(struct symtable *st, withitem_ty item); @@ -323,7 +323,7 @@ PySymtable_BuildObject(mod_ty mod, PyObject *filename, PyFutureFeatures *future) "this compiler does not handle FunctionTypes"); goto error; } - if (!symtable_exit_block(st, (void *)mod)) { + if (!symtable_exit_block(st)) { PySymtable_Free(st); return NULL; } @@ -341,7 +341,7 @@ PySymtable_BuildObject(mod_ty mod, PyObject *filename, PyFutureFeatures *future) PySymtable_Free(st); return NULL; error: - (void) symtable_exit_block(st, (void *)mod); + (void) symtable_exit_block(st); PySymtable_Free(st); return NULL; } @@ -950,7 +950,7 @@ symtable_analyze(struct symtable *st) */ static int -symtable_exit_block(struct symtable *st, void *ast) +symtable_exit_block(struct symtable *st) { Py_ssize_t size; @@ -1184,7 +1184,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) VISIT_SEQ(st, expr, s->v.FunctionDef.args->defaults); if (s->v.FunctionDef.args->kw_defaults) VISIT_SEQ_WITH_NULL(st, expr, s->v.FunctionDef.args->kw_defaults); - if (!symtable_visit_annotations(st, s, s->v.FunctionDef.args, + if (!symtable_visit_annotations(st, s->v.FunctionDef.args, s->v.FunctionDef.returns)) VISIT_QUIT(st, 0); if (s->v.FunctionDef.decorator_list) @@ -1195,7 +1195,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) VISIT_QUIT(st, 0); VISIT(st, arguments, s->v.FunctionDef.args); VISIT_SEQ(st, stmt, s->v.FunctionDef.body); - if (!symtable_exit_block(st, s)) + if (!symtable_exit_block(st)) VISIT_QUIT(st, 0); break; case ClassDef_kind: { @@ -1213,7 +1213,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) st->st_private = s->v.ClassDef.name; VISIT_SEQ(st, stmt, s->v.ClassDef.body); st->st_private = tmp; - if (!symtable_exit_block(st, s)) + if (!symtable_exit_block(st)) VISIT_QUIT(st, 0); break; } @@ -1402,7 +1402,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) if (s->v.AsyncFunctionDef.args->kw_defaults) VISIT_SEQ_WITH_NULL(st, expr, s->v.AsyncFunctionDef.args->kw_defaults); - if (!symtable_visit_annotations(st, s, s->v.AsyncFunctionDef.args, + if (!symtable_visit_annotations(st, s->v.AsyncFunctionDef.args, s->v.AsyncFunctionDef.returns)) VISIT_QUIT(st, 0); if (s->v.AsyncFunctionDef.decorator_list) @@ -1414,7 +1414,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) st->st_cur->ste_coroutine = 1; VISIT(st, arguments, s->v.AsyncFunctionDef.args); VISIT_SEQ(st, stmt, s->v.AsyncFunctionDef.body); - if (!symtable_exit_block(st, s)) + if (!symtable_exit_block(st)) VISIT_QUIT(st, 0); break; case AsyncWith_kind: @@ -1561,7 +1561,7 @@ symtable_visit_expr(struct symtable *st, expr_ty e) VISIT_QUIT(st, 0); VISIT(st, arguments, e->v.Lambda.args); VISIT(st, expr, e->v.Lambda.body); - if (!symtable_exit_block(st, (void *)e)) + if (!symtable_exit_block(st)) VISIT_QUIT(st, 0); break; } @@ -1710,8 +1710,7 @@ symtable_visit_argannotations(struct symtable *st, asdl_seq *args) } static int -symtable_visit_annotations(struct symtable *st, stmt_ty s, - arguments_ty a, expr_ty returns) +symtable_visit_annotations(struct symtable *st, arguments_ty a, expr_ty returns) { if (a->posonlyargs && !symtable_visit_argannotations(st, a->posonlyargs)) return 0; @@ -1889,7 +1888,7 @@ symtable_handle_comprehension(struct symtable *st, expr_ty e, /* Outermost iter is received as an argument */ if (!symtable_implicit_arg(st, 0)) { - symtable_exit_block(st, (void *)e); + symtable_exit_block(st); return 0; } /* Visit iteration variable target, and mark them as such */ @@ -1911,11 +1910,11 @@ symtable_handle_comprehension(struct symtable *st, expr_ty e, PyErr_SyntaxLocationObject(st->st_filename, st->st_cur->ste_lineno, st->st_cur->ste_col_offset + 1); - symtable_exit_block(st, (void *)e); + symtable_exit_block(st); return 0; } st->st_cur->ste_generator = is_generator; - return symtable_exit_block(st, (void *)e); + return symtable_exit_block(st); } static int From webhook-mailer at python.org Fri Mar 6 12:24:15 2020 From: webhook-mailer at python.org (Brandt Bucher) Date: Fri, 06 Mar 2020 17:24:15 -0000 Subject: [Python-checkins] bpo-36144: Implement defaultdict union (GH-18729) Message-ID: https://github.com/python/cpython/commit/57c9d1725689dde068a7fccaa7500772ecd16d2e commit: 57c9d1725689dde068a7fccaa7500772ecd16d2e branch: master author: Brandt Bucher committer: GitHub date: 2020-03-06T09:24:08-08:00 summary: bpo-36144: Implement defaultdict union (GH-18729) For PEP 585 (this isn't in the PEP but is an obvious follow-up). files: A Misc/NEWS.d/next/Library/2020-02-29-15-54-08.bpo-36144.4GgTZs.rst M Doc/library/collections.rst M Lib/test/test_defaultdict.py M Modules/_collectionsmodule.c diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst index 8dcf9451d72bf..f4a383c8ea57d 100644 --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -729,6 +729,10 @@ stack manipulations such as ``dup``, ``drop``, ``swap``, ``over``, ``pick``, initialized from the first argument to the constructor, if present, or to ``None``, if absent. + .. versionchanged:: 3.9 + Added merge (``|``) and update (``|=``) operators, specified in + :pep:`584`. + :class:`defaultdict` Examples ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/Lib/test/test_defaultdict.py b/Lib/test/test_defaultdict.py index b9f1fb9f23d39..b48c649fce6ba 100644 --- a/Lib/test/test_defaultdict.py +++ b/Lib/test/test_defaultdict.py @@ -183,5 +183,43 @@ def test_pickling(self): o = pickle.loads(s) self.assertEqual(d, o) + def test_union(self): + i = defaultdict(int, {1: 1, 2: 2}) + s = defaultdict(str, {0: "zero", 1: "one"}) + + i_s = i | s + self.assertIs(i_s.default_factory, int) + self.assertDictEqual(i_s, {1: "one", 2: 2, 0: "zero"}) + self.assertEqual(list(i_s), [1, 2, 0]) + + s_i = s | i + self.assertIs(s_i.default_factory, str) + self.assertDictEqual(s_i, {0: "zero", 1: 1, 2: 2}) + self.assertEqual(list(s_i), [0, 1, 2]) + + i_ds = i | dict(s) + self.assertIs(i_ds.default_factory, int) + self.assertDictEqual(i_ds, {1: "one", 2: 2, 0: "zero"}) + self.assertEqual(list(i_ds), [1, 2, 0]) + + ds_i = dict(s) | i + self.assertIs(ds_i.default_factory, int) + self.assertDictEqual(ds_i, {0: "zero", 1: 1, 2: 2}) + self.assertEqual(list(ds_i), [0, 1, 2]) + + with self.assertRaises(TypeError): + i | list(s.items()) + with self.assertRaises(TypeError): + list(s.items()) | i + + # We inherit a fine |= from dict, so just a few sanity checks here: + i |= list(s.items()) + self.assertIs(i.default_factory, int) + self.assertDictEqual(i, {1: "one", 2: 2, 0: "zero"}) + self.assertEqual(list(i), [1, 2, 0]) + + with self.assertRaises(TypeError): + i |= None + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Library/2020-02-29-15-54-08.bpo-36144.4GgTZs.rst b/Misc/NEWS.d/next/Library/2020-02-29-15-54-08.bpo-36144.4GgTZs.rst new file mode 100644 index 0000000000000..416d5ac3a2717 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-02-29-15-54-08.bpo-36144.4GgTZs.rst @@ -0,0 +1 @@ +:class:`collections.defaultdict` now implements ``|`` (:pep:`584`). diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c index 4d5d874b44da1..d0a381deabf5d 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -1990,6 +1990,13 @@ defdict_missing(defdictobject *dd, PyObject *key) return value; } +static inline PyObject* +new_defdict(defdictobject *dd, PyObject *arg) +{ + return PyObject_CallFunctionObjArgs((PyObject*)Py_TYPE(dd), + dd->default_factory ? dd->default_factory : Py_None, arg, NULL); +} + PyDoc_STRVAR(defdict_copy_doc, "D.copy() -> a shallow copy of D."); static PyObject * @@ -1999,11 +2006,7 @@ defdict_copy(defdictobject *dd, PyObject *Py_UNUSED(ignored)) whose class constructor has the same signature. Subclasses that define a different constructor signature must override copy(). */ - - if (dd->default_factory == NULL) - return PyObject_CallFunctionObjArgs((PyObject*)Py_TYPE(dd), Py_None, dd, NULL); - return PyObject_CallFunctionObjArgs((PyObject*)Py_TYPE(dd), - dd->default_factory, dd, NULL); + return new_defdict(dd, (PyObject*)dd); } static PyObject * @@ -2127,6 +2130,42 @@ defdict_repr(defdictobject *dd) return result; } +static PyObject* +defdict_or(PyObject* left, PyObject* right) +{ + int left_is_self = PyObject_IsInstance(left, (PyObject*)&defdict_type); + if (left_is_self < 0) { + return NULL; + } + PyObject *self, *other; + if (left_is_self) { + self = left; + other = right; + } + else { + self = right; + other = left; + } + if (!PyDict_Check(other)) { + Py_RETURN_NOTIMPLEMENTED; + } + // Like copy(), this calls the object's class. + // Override __or__/__ror__ for subclasses with different constructors. + PyObject *new = new_defdict((defdictobject*)self, left); + if (!new) { + return NULL; + } + if (PyDict_Update(new, right)) { + Py_DECREF(new); + return NULL; + } + return new; +} + +static PyNumberMethods defdict_as_number = { + .nb_or = defdict_or, +}; + static int defdict_traverse(PyObject *self, visitproc visit, void *arg) { @@ -2198,7 +2237,7 @@ static PyTypeObject defdict_type = { 0, /* tp_setattr */ 0, /* tp_as_async */ (reprfunc)defdict_repr, /* tp_repr */ - 0, /* tp_as_number */ + &defdict_as_number, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ From webhook-mailer at python.org Fri Mar 6 12:57:53 2020 From: webhook-mailer at python.org (Victor Stinner) Date: Fri, 06 Mar 2020 17:57:53 -0000 Subject: [Python-checkins] bpo-39873: Cleanup _PyObject_CheckConsistency() (GH-18807) Message-ID: https://github.com/python/cpython/commit/9a73705a1d0cb8b89d0a20add2ffa2c4d32950ed commit: 9a73705a1d0cb8b89d0a20add2ffa2c4d32950ed branch: master author: Victor Stinner committer: GitHub date: 2020-03-06T18:57:48+01:00 summary: bpo-39873: Cleanup _PyObject_CheckConsistency() (GH-18807) Remove redundant check on Py_TYPE() value: it's already checked inside _PyType_CheckConsistency(). files: M Objects/object.c diff --git a/Objects/object.c b/Objects/object.c index 707424c98fe7d..8314a08150e2d 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -33,7 +33,6 @@ _PyObject_CheckConsistency(PyObject *op, int check_content) CHECK(!_PyObject_IsFreed(op)); CHECK(Py_REFCNT(op) >= 1); - CHECK(Py_TYPE(op) != NULL); _PyType_CheckConsistency(Py_TYPE(op)); if (PyUnicode_Check(op)) { From webhook-mailer at python.org Fri Mar 6 13:20:53 2020 From: webhook-mailer at python.org (Caleb Donovick) Date: Fri, 06 Mar 2020 18:20:53 -0000 Subject: [Python-checkins] bpo-17422: slightly more precise language (GH-18682) Message-ID: https://github.com/python/cpython/commit/e59334ebc9308b0f3ad048ef293c6b49e6456d1a commit: e59334ebc9308b0f3ad048ef293c6b49e6456d1a branch: master author: Caleb Donovick committer: GitHub date: 2020-03-06T10:20:48-08:00 summary: bpo-17422: slightly more precise language (GH-18682) files: A Misc/NEWS.d/next/Documentation/2020-02-27-17-35-27.bpo-17422.eS1hVh.rst M Doc/reference/datamodel.rst diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 8be432d465ba3..c683d9991eb5a 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1956,7 +1956,7 @@ namespace returned by ``__prepare__`` is passed in to ``__new__``, but when the final class object is created the namespace is copied into a new ``dict``. If the metaclass has no ``__prepare__`` attribute, then the class namespace -is initialised as an empty :func:`dict`. +is initialised as an empty ordered mapping. .. seealso:: diff --git a/Misc/NEWS.d/next/Documentation/2020-02-27-17-35-27.bpo-17422.eS1hVh.rst b/Misc/NEWS.d/next/Documentation/2020-02-27-17-35-27.bpo-17422.eS1hVh.rst new file mode 100644 index 0000000000000..bbec5ec0eee65 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2020-02-27-17-35-27.bpo-17422.eS1hVh.rst @@ -0,0 +1,2 @@ +The language reference no longer restricts default class namespaces to dicts +only. From webhook-mailer at python.org Fri Mar 6 13:25:55 2020 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 06 Mar 2020 18:25:55 -0000 Subject: [Python-checkins] bpo-17422: slightly more precise language (GH-18682) Message-ID: https://github.com/python/cpython/commit/f1b79645cf18b2c212cd26d547cd1762fd534d4b commit: f1b79645cf18b2c212cd26d547cd1762fd534d4b branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2020-03-06T10:25:51-08:00 summary: bpo-17422: slightly more precise language (GH-18682) (cherry picked from commit e59334ebc9308b0f3ad048ef293c6b49e6456d1a) Co-authored-by: Caleb Donovick files: A Misc/NEWS.d/next/Documentation/2020-02-27-17-35-27.bpo-17422.eS1hVh.rst M Doc/reference/datamodel.rst diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index b682465d3ddc8..1212dc61f2d24 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1937,7 +1937,7 @@ namespace returned by ``__prepare__`` is passed in to ``__new__``, but when the final class object is created the namespace is copied into a new ``dict``. If the metaclass has no ``__prepare__`` attribute, then the class namespace -is initialised as an empty :func:`dict`. +is initialised as an empty ordered mapping. .. seealso:: diff --git a/Misc/NEWS.d/next/Documentation/2020-02-27-17-35-27.bpo-17422.eS1hVh.rst b/Misc/NEWS.d/next/Documentation/2020-02-27-17-35-27.bpo-17422.eS1hVh.rst new file mode 100644 index 0000000000000..bbec5ec0eee65 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2020-02-27-17-35-27.bpo-17422.eS1hVh.rst @@ -0,0 +1,2 @@ +The language reference no longer restricts default class namespaces to dicts +only. From webhook-mailer at python.org Fri Mar 6 13:26:57 2020 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 06 Mar 2020 18:26:57 -0000 Subject: [Python-checkins] bpo-17422: slightly more precise language (GH-18682) Message-ID: https://github.com/python/cpython/commit/6df0c47669031c6a8e9b1a07ec2c5813e4c10ee0 commit: 6df0c47669031c6a8e9b1a07ec2c5813e4c10ee0 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2020-03-06T10:26:52-08:00 summary: bpo-17422: slightly more precise language (GH-18682) (cherry picked from commit e59334ebc9308b0f3ad048ef293c6b49e6456d1a) Co-authored-by: Caleb Donovick files: A Misc/NEWS.d/next/Documentation/2020-02-27-17-35-27.bpo-17422.eS1hVh.rst M Doc/reference/datamodel.rst diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 06f4992cf544a..1530775839bb6 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1951,7 +1951,7 @@ namespace returned by ``__prepare__`` is passed in to ``__new__``, but when the final class object is created the namespace is copied into a new ``dict``. If the metaclass has no ``__prepare__`` attribute, then the class namespace -is initialised as an empty :func:`dict`. +is initialised as an empty ordered mapping. .. seealso:: diff --git a/Misc/NEWS.d/next/Documentation/2020-02-27-17-35-27.bpo-17422.eS1hVh.rst b/Misc/NEWS.d/next/Documentation/2020-02-27-17-35-27.bpo-17422.eS1hVh.rst new file mode 100644 index 0000000000000..bbec5ec0eee65 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2020-02-27-17-35-27.bpo-17422.eS1hVh.rst @@ -0,0 +1,2 @@ +The language reference no longer restricts default class namespaces to dicts +only. From webhook-mailer at python.org Fri Mar 6 17:53:22 2020 From: webhook-mailer at python.org (Andy Lester) Date: Fri, 06 Mar 2020 22:53:22 -0000 Subject: [Python-checkins] bpo-39573: Use Py_IS_TYPE() macro to check for types (GH-18809) Message-ID: https://github.com/python/cpython/commit/557287075c264d2458cd3e1b45e9b8ee5341e0a1 commit: 557287075c264d2458cd3e1b45e9b8ee5341e0a1 branch: master author: Andy Lester committer: GitHub date: 2020-03-06T23:53:17+01:00 summary: bpo-39573: Use Py_IS_TYPE() macro to check for types (GH-18809) Co-authored-by: Victor Stinner files: M Modules/_functoolsmodule.c M Modules/_threadmodule.c M Modules/itertoolsmodule.c M Modules/posixmodule.c M Objects/abstract.c M Objects/object.c M Objects/setobject.c M Objects/tupleobject.c M Objects/typeobject.c M Python/errors.c diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c index ab0839cdc7473..0c0fae1a979a4 100644 --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -573,7 +573,7 @@ keyobject_richcompare(PyObject *ko, PyObject *other, int op) PyObject *answer; PyObject* stack[2]; - if (Py_TYPE(other) != &keyobject_type){ + if (!Py_IS_TYPE(other, &keyobject_type)) { PyErr_Format(PyExc_TypeError, "other argument must be K instance"); return NULL; } diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c index da5fe7915a8e5..11bc16f4b3111 100644 --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -938,7 +938,7 @@ local_getattro(localobject *self, PyObject *name) if (r == -1) return NULL; - if (Py_TYPE(self) != &localtype) + if (!Py_IS_TYPE(self, &localtype)) /* use generic lookup for subtypes */ return _PyObject_GenericGetAttrWithDict( (PyObject *)self, name, ldict, 0); @@ -1400,7 +1400,7 @@ static PyStructSequence_Desc ExceptHookArgs_desc = { static PyObject * thread_excepthook(PyObject *self, PyObject *args) { - if (Py_TYPE(args) != &ExceptHookArgsType) { + if (!Py_IS_TYPE(args, &ExceptHookArgsType)) { PyErr_SetString(PyExc_TypeError, "_thread.excepthook argument type " "must be ExceptHookArgs"); diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index d545028901b4e..9505fd454b42e 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -614,7 +614,7 @@ itertools_teedataobject_impl(PyTypeObject *type, PyObject *it, if (len == LINKCELLS) { if (next != Py_None) { - if (Py_TYPE(next) != &teedataobject_type) + if (!Py_IS_TYPE(next, &teedataobject_type)) goto err; assert(tdo->nextlink == NULL); Py_INCREF(next); diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 4d6d255b3469b..29aeca4169dd1 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -6380,8 +6380,7 @@ convert_sched_param(PyObject *param, struct sched_param *res) { long priority; - PyObject *SchedParamType = _posixstate_global->SchedParamType; - if (Py_TYPE(param) != (PyTypeObject *)SchedParamType) { + if (!Py_IS_TYPE(param, (PyTypeObject *)_posixstate_global->SchedParamType)) { PyErr_SetString(PyExc_TypeError, "must have a sched_param object"); return 0; } diff --git a/Objects/abstract.c b/Objects/abstract.c index 454e0da71afbe..accd72d5f28e5 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -834,7 +834,7 @@ binary_op1(PyObject *v, PyObject *w, const int op_slot) if (Py_TYPE(v)->tp_as_number != NULL) slotv = NB_BINOP(Py_TYPE(v)->tp_as_number, op_slot); - if (Py_TYPE(w) != Py_TYPE(v) && + if (!Py_IS_TYPE(w, Py_TYPE(v)) && Py_TYPE(w)->tp_as_number != NULL) { slotw = NB_BINOP(Py_TYPE(w)->tp_as_number, op_slot); if (slotw == slotv) @@ -925,8 +925,7 @@ ternary_op(PyObject *v, mw = Py_TYPE(w)->tp_as_number; if (mv != NULL) slotv = NB_TERNOP(mv, op_slot); - if (Py_TYPE(w) != Py_TYPE(v) && - mw != NULL) { + if (!Py_IS_TYPE(w, Py_TYPE(v)) && mw != NULL) { slotw = NB_TERNOP(mw, op_slot); if (slotw == slotv) slotw = NULL; diff --git a/Objects/object.c b/Objects/object.c index 8314a08150e2d..bb47cfa8585f7 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -657,7 +657,7 @@ do_richcompare(PyThreadState *tstate, PyObject *v, PyObject *w, int op) PyObject *res; int checked_reverse_op = 0; - if (Py_TYPE(v) != Py_TYPE(w) && + if (!Py_IS_TYPE(v, Py_TYPE(w)) && PyType_IsSubtype(Py_TYPE(w), Py_TYPE(v)) && (f = Py_TYPE(w)->tp_richcompare) != NULL) { checked_reverse_op = 1; @@ -1907,7 +1907,7 @@ _Py_GetObjects(PyObject *self, PyObject *args) return NULL; for (i = 0; (n == 0 || i < n) && op != &refchain; i++) { while (op == self || op == args || op == res || op == t || - (t != NULL && Py_TYPE(op) != (PyTypeObject *) t)) { + (t != NULL && !Py_IS_TYPE(op, (PyTypeObject *) t))) { op = op->_ob_next; if (op == &refchain) return res; diff --git a/Objects/setobject.c b/Objects/setobject.c index bb7c0b8f0456b..43fa5d17fd2e7 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -608,7 +608,7 @@ set_repr(PySetObject *so) goto done; listrepr = tmp; - if (Py_TYPE(so) != &PySet_Type) + if (!Py_IS_TYPE(so, &PySet_Type)) result = PyUnicode_FromFormat("%s({%U})", Py_TYPE(so)->tp_name, listrepr); diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index 92374cc130d0c..52ecb5446fe8f 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -881,7 +881,7 @@ _PyTuple_Resize(PyObject **pv, Py_ssize_t newsize) Py_ssize_t oldsize; v = (PyTupleObject *) *pv; - if (v == NULL || Py_TYPE(v) != &PyTuple_Type || + if (v == NULL || !Py_IS_TYPE(v, &PyTuple_Type) || (Py_SIZE(v) != 0 && Py_REFCNT(v) != 1)) { *pv = 0; Py_XDECREF(v); diff --git a/Objects/typeobject.c b/Objects/typeobject.c index cf749eff58fe2..ec8dc19da9998 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -1889,7 +1889,7 @@ mro_invoke(PyTypeObject *type) { PyObject *mro_result; PyObject *new_mro; - int custom = (Py_TYPE(type) != &PyType_Type); + const int custom = !Py_IS_TYPE(type, &PyType_Type); if (custom) { int unbound; @@ -6191,7 +6191,7 @@ FUNCNAME(PyObject *self, PyObject *other) \ PyThreadState *tstate = _PyThreadState_GET(); \ _Py_static_string(op_id, OPSTR); \ _Py_static_string(rop_id, ROPSTR); \ - int do_other = Py_TYPE(self) != Py_TYPE(other) && \ + int do_other = !Py_IS_TYPE(self, Py_TYPE(other)) && \ Py_TYPE(other)->tp_as_number != NULL && \ Py_TYPE(other)->tp_as_number->SLOTNAME == TESTFUNC; \ if (Py_TYPE(self)->tp_as_number != NULL && \ @@ -7901,7 +7901,7 @@ super_descr_get(PyObject *self, PyObject *obj, PyObject *type) Py_INCREF(self); return self; } - if (Py_TYPE(su) != &PySuper_Type) + if (!Py_IS_TYPE(su, &PySuper_Type)) /* If su is an instance of a (strict) subclass of super, call its type */ return PyObject_CallFunctionObjArgs((PyObject *)Py_TYPE(su), diff --git a/Python/errors.c b/Python/errors.c index 6baa229ccc7ce..4656fb2a33670 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -1321,7 +1321,7 @@ _PyErr_WriteUnraisableDefaultHook(PyObject *args) { PyThreadState *tstate = _PyThreadState_GET(); - if (Py_TYPE(args) != &UnraisableHookArgsType) { + if (!Py_IS_TYPE(args, &UnraisableHookArgsType)) { _PyErr_SetString(tstate, PyExc_TypeError, "sys.unraisablehook argument type " "must be UnraisableHookArgs"); From webhook-mailer at python.org Fri Mar 6 18:24:27 2020 From: webhook-mailer at python.org (Victor Stinner) Date: Fri, 06 Mar 2020 23:24:27 -0000 Subject: [Python-checkins] bpo-39877: _PyRuntimeState.finalizing becomes atomic (GH-18816) Message-ID: https://github.com/python/cpython/commit/7b3c252dc7f44d4bdc4c7c82d225ebd09c78f520 commit: 7b3c252dc7f44d4bdc4c7c82d225ebd09c78f520 branch: master author: Victor Stinner committer: GitHub date: 2020-03-07T00:24:23+01:00 summary: bpo-39877: _PyRuntimeState.finalizing becomes atomic (GH-18816) Convert _PyRuntimeState.finalizing field to an atomic variable: * Rename it to _finalizing * Change its type to _Py_atomic_address * Add _PyRuntimeState_GetFinalizing() and _PyRuntimeState_SetFinalizing() functions * Remove _Py_CURRENTLY_FINALIZING() function: replace it with testing directly _PyRuntimeState_GetFinalizing() value Convert _PyRuntimeState_GetThreadState() to static inline function. files: M Include/internal/pycore_pystate.h M Python/ceval.c M Python/pylifecycle.c M Python/pystate.c M Python/sysmodule.c diff --git a/Include/internal/pycore_pystate.h b/Include/internal/pycore_pystate.h index 405efb9f46060..b5f509547207d 100644 --- a/Include/internal/pycore_pystate.h +++ b/Include/internal/pycore_pystate.h @@ -223,8 +223,11 @@ typedef struct pyruntimestate { int initialized; /* Set by Py_FinalizeEx(). Only reset to NULL if Py_Initialize() - is called again. */ - PyThreadState *finalizing; + is called again. + + Use _PyRuntimeState_GetFinalizing() and _PyRuntimeState_SetFinalizing() + to access it, don't access it directly. */ + _Py_atomic_address _finalizing; struct pyinterpreters { PyThread_type_lock mutex; @@ -279,8 +282,15 @@ PyAPI_FUNC(PyStatus) _PyRuntime_Initialize(void); PyAPI_FUNC(void) _PyRuntime_Finalize(void); -#define _Py_CURRENTLY_FINALIZING(runtime, tstate) \ - (runtime->finalizing == tstate) +static inline PyThreadState* +_PyRuntimeState_GetFinalizing(_PyRuntimeState *runtime) { + return (PyThreadState*)_Py_atomic_load_relaxed(&runtime->_finalizing); +} + +static inline void +_PyRuntimeState_SetFinalizing(_PyRuntimeState *runtime, PyThreadState *tstate) { + _Py_atomic_store_relaxed(&runtime->_finalizing, (uintptr_t)tstate); +} PyAPI_FUNC(int) _Py_IsMainInterpreter(PyThreadState* tstate); @@ -288,8 +298,9 @@ PyAPI_FUNC(int) _Py_IsMainInterpreter(PyThreadState* tstate); /* Variable and macro for in-line access to current thread and interpreter state */ -#define _PyRuntimeState_GetThreadState(runtime) \ - ((PyThreadState*)_Py_atomic_load_relaxed(&(runtime)->gilstate.tstate_current)) +static inline PyThreadState* _PyRuntimeState_GetThreadState(_PyRuntimeState *runtime) { + return (PyThreadState*)_Py_atomic_load_relaxed(&runtime->gilstate.tstate_current); +} /* Get the current Python thread state. diff --git a/Python/ceval.c b/Python/ceval.c index ef4aac2f9abc8..20e32e224e7d4 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -240,7 +240,8 @@ exit_thread_if_finalizing(PyThreadState *tstate) { _PyRuntimeState *runtime = tstate->interp->runtime; /* _Py_Finalizing is protected by the GIL */ - if (runtime->finalizing != NULL && !_Py_CURRENTLY_FINALIZING(runtime, tstate)) { + PyThreadState *finalizing = _PyRuntimeState_GetFinalizing(runtime); + if (finalizing != NULL && finalizing != tstate) { drop_gil(&runtime->ceval, tstate); PyThread_exit_thread(); } diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 84ced424499de..23d74ee9503aa 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -103,7 +103,7 @@ _PyRuntime_Finalize(void) int _Py_IsFinalizing(void) { - return _PyRuntime.finalizing != NULL; + return _PyRuntimeState_GetFinalizing(&_PyRuntime) != NULL; } /* Hack to force loading of object files */ @@ -507,7 +507,7 @@ pycore_init_runtime(_PyRuntimeState *runtime, * threads still hanging around from a previous Py_Initialize/Finalize * pair :( */ - runtime->finalizing = NULL; + _PyRuntimeState_SetFinalizing(runtime, NULL); PyStatus status = _Py_HashRandomization_Init(config); if (_PyStatus_EXCEPTION(status)) { @@ -1366,7 +1366,7 @@ Py_FinalizeEx(void) /* Remaining threads (e.g. daemon threads) will automatically exit after taking the GIL (in PyEval_RestoreThread()). */ - runtime->finalizing = tstate; + _PyRuntimeState_SetFinalizing(runtime, tstate); runtime->initialized = 0; runtime->core_initialized = 0; @@ -2131,8 +2131,9 @@ static void fatal_error_dump_runtime(FILE *stream, _PyRuntimeState *runtime) { fprintf(stream, "Python runtime state: "); - if (runtime->finalizing) { - fprintf(stream, "finalizing (tstate=%p)", runtime->finalizing); + PyThreadState *finalizing = _PyRuntimeState_GetFinalizing(runtime); + if (finalizing) { + fprintf(stream, "finalizing (tstate=%p)", finalizing); } else if (runtime->initialized) { fprintf(stream, "initialized"); diff --git a/Python/pystate.c b/Python/pystate.c index 4001c63ff25ee..900266919dfc4 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -292,7 +292,7 @@ PyInterpreterState_Clear(PyInterpreterState *interp) Py_CLEAR(interp->after_forkers_parent); Py_CLEAR(interp->after_forkers_child); #endif - if (runtime->finalizing == NULL) { + if (_PyRuntimeState_GetFinalizing(runtime) == NULL) { _PyWarnings_Fini(interp); } // XXX Once we have one allocator per interpreter (i.e. diff --git a/Python/sysmodule.c b/Python/sysmodule.c index bfacf314dfc9e..f086514a03243 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -289,8 +289,9 @@ _PySys_ClearAuditHooks(void) /* Must be finalizing to clear hooks */ _PyRuntimeState *runtime = &_PyRuntime; PyThreadState *ts = _PyRuntimeState_GetThreadState(runtime); - assert(!ts || _Py_CURRENTLY_FINALIZING(runtime, ts)); - if (!ts || !_Py_CURRENTLY_FINALIZING(runtime, ts)) { + PyThreadState *finalizing = _PyRuntimeState_GetFinalizing(runtime); + assert(!ts || finalizing == ts); + if (!ts || finalizing != ts) { return; } From webhook-mailer at python.org Fri Mar 6 18:54:25 2020 From: webhook-mailer at python.org (Victor Stinner) Date: Fri, 06 Mar 2020 23:54:25 -0000 Subject: [Python-checkins] bpo-39882: Py_FatalError() logs the function name (GH-18819) Message-ID: https://github.com/python/cpython/commit/9e5d30cc99e34f4c3e7b2cd851de20816c9d1927 commit: 9e5d30cc99e34f4c3e7b2cd851de20816c9d1927 branch: master author: Victor Stinner committer: GitHub date: 2020-03-07T00:54:20+01:00 summary: bpo-39882: Py_FatalError() logs the function name (GH-18819) The Py_FatalError() function is replaced with a macro which logs automatically the name of the current function, unless the Py_LIMITED_API macro is defined. Changes: * Add _Py_FatalErrorFunc() function. * Remove the function name from the message of Py_FatalError() calls which included the function name. * Update tests. files: A Misc/NEWS.d/next/C API/2020-03-06-23-56-04.bpo-39882.Iqhcqm.rst M Doc/c-api/sys.rst M Include/cpython/pyerrors.h M Include/pyerrors.h M Lib/test/test_capi.py M Lib/test/test_exceptions.py M Lib/test/test_faulthandler.py M Lib/test/test_io.py M Lib/test/test_sys.py M Objects/obmalloc.c M Parser/parser.c M Parser/tokenizer.c M Python/ceval.c M Python/import.c M Python/pathconfig.c M Python/pylifecycle.c M Python/pystate.c diff --git a/Doc/c-api/sys.rst b/Doc/c-api/sys.rst index c851ff66487d5..9ac9179097892 100644 --- a/Doc/c-api/sys.rst +++ b/Doc/c-api/sys.rst @@ -388,6 +388,13 @@ Process Control function :c:func:`abort` is called which will attempt to produce a :file:`core` file. + The ``Py_FatalError()`` function is replaced with a macro which logs + automatically the name of the current function, unless the + ``Py_LIMITED_API`` macro is defined. + + .. versionchanged:: 3.9 + Log the function name automatically. + .. c:function:: void Py_Exit(int status) diff --git a/Include/cpython/pyerrors.h b/Include/cpython/pyerrors.h index f8480fb79e557..ab2e74018b40e 100644 --- a/Include/cpython/pyerrors.h +++ b/Include/cpython/pyerrors.h @@ -178,6 +178,12 @@ PyAPI_FUNC(void) _PyErr_WriteUnraisableMsg( const char *err_msg, PyObject *obj); +PyAPI_FUNC(void) _Py_NO_RETURN _Py_FatalErrorFunc( + const char *func, + const char *message); + +#define Py_FatalError(message) _Py_FatalErrorFunc(__func__, message) + #ifdef __cplusplus } #endif diff --git a/Include/pyerrors.h b/Include/pyerrors.h index 3fd133c57de30..399bb7c3a6fac 100644 --- a/Include/pyerrors.h +++ b/Include/pyerrors.h @@ -21,7 +21,11 @@ PyAPI_FUNC(void) PyErr_GetExcInfo(PyObject **, PyObject **, PyObject **); PyAPI_FUNC(void) PyErr_SetExcInfo(PyObject *, PyObject *, PyObject *); #endif -/* Defined in Python/pylifecycle.c */ +/* Defined in Python/pylifecycle.c + + The Py_FatalError() function is replaced with a macro which logs + automatically the name of the current function, unless the Py_LIMITED_API + macro is defined. */ PyAPI_FUNC(void) _Py_NO_RETURN Py_FatalError(const char *message); #if defined(Py_DEBUG) || defined(Py_LIMITED_API) diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py index e65973c4646b1..ff18a211f8bbf 100644 --- a/Lib/test/test_capi.py +++ b/Lib/test/test_capi.py @@ -61,8 +61,8 @@ def test_no_FatalError_infinite_loop(self): self.assertEqual(out, b'') # This used to cause an infinite loop. self.assertTrue(err.rstrip().startswith( - b'Fatal Python error:' - b' PyThreadState_Get: no current thread')) + b'Fatal Python error: ' + b'PyThreadState_Get: no current thread')) def test_memoryview_from_NULL_pointer(self): self.assertRaises(ValueError, _testcapi.make_memoryview_from_NULL_pointer) @@ -197,7 +197,8 @@ def test_return_null_without_error(self): """) rc, out, err = assert_python_failure('-c', code) self.assertRegex(err.replace(b'\r', b''), - br'Fatal Python error: a function returned NULL ' + br'Fatal Python error: _Py_CheckFunctionResult: ' + br'a function returned NULL ' br'without setting an error\n' br'Python runtime state: initialized\n' br'SystemError: " r"at interpreter shutdown, possibly due to " r"daemon threads".format_map(locals())) diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index c5bd8a4b1ff96..027f87e0d4ca2 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -269,6 +269,8 @@ def set_recursion_limit_at_depth(depth, limit): finally: sys.setrecursionlimit(oldlimit) + # The error message is specific to CPython + @test.support.cpython_only def test_recursionlimit_fatalerror(self): # A fatal error occurs if a second recursion limit is hit when recovering # from a first one. @@ -290,7 +292,8 @@ def f(): err = sub.communicate()[1] self.assertTrue(sub.returncode, sub.returncode) self.assertIn( - b"Fatal Python error: Cannot recover from stack overflow", + b"Fatal Python error: _Py_CheckRecursiveCall: " + b"Cannot recover from stack overflow", err) def test_getwindowsversion(self): diff --git a/Misc/NEWS.d/next/C API/2020-03-06-23-56-04.bpo-39882.Iqhcqm.rst b/Misc/NEWS.d/next/C API/2020-03-06-23-56-04.bpo-39882.Iqhcqm.rst new file mode 100644 index 0000000000000..b5eae7af72155 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2020-03-06-23-56-04.bpo-39882.Iqhcqm.rst @@ -0,0 +1,3 @@ +The :c:func:`Py_FatalError` function is replaced with a macro which logs +automatically the name of the current function, unless the ``Py_LIMITED_API`` +macro is defined. diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c index 3881ff17e0642..3b574bffd829d 100644 --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -25,7 +25,7 @@ static void* _PyMem_DebugRealloc(void *ctx, void *ptr, size_t size); static void _PyMem_DebugFree(void *ctx, void *p); static void _PyObject_DebugDumpAddress(const void *p); -static void _PyMem_DebugCheckAddress(char api_id, const void *p); +static void _PyMem_DebugCheckAddress(const char *func, char api_id, const void *p); static void _PyMem_SetupDebugHooksDomain(PyMemAllocatorDomain domain); @@ -2205,7 +2205,7 @@ _PyMem_DebugRawFree(void *ctx, void *p) uint8_t *q = (uint8_t *)p - 2*SST; /* address returned from malloc */ size_t nbytes; - _PyMem_DebugCheckAddress(api->api_id, p); + _PyMem_DebugCheckAddress(__func__, api->api_id, p); nbytes = read_size_t(q); nbytes += PYMEM_DEBUG_EXTRA_BYTES; memset(q, PYMEM_DEADBYTE, nbytes); @@ -2230,7 +2230,7 @@ _PyMem_DebugRawRealloc(void *ctx, void *p, size_t nbytes) #define ERASED_SIZE 64 uint8_t save[2*ERASED_SIZE]; /* A copy of erased bytes. */ - _PyMem_DebugCheckAddress(api->api_id, p); + _PyMem_DebugCheckAddress(__func__, api->api_id, p); data = (uint8_t *)p; head = data - 2*SST; @@ -2314,25 +2314,26 @@ _PyMem_DebugRawRealloc(void *ctx, void *p, size_t nbytes) } static inline void -_PyMem_DebugCheckGIL(void) +_PyMem_DebugCheckGIL(const char *func) { if (!PyGILState_Check()) { - Py_FatalError("Python memory allocator called " - "without holding the GIL"); + _Py_FatalErrorFunc(func, + "Python memory allocator called " + "without holding the GIL"); } } static void * _PyMem_DebugMalloc(void *ctx, size_t nbytes) { - _PyMem_DebugCheckGIL(); + _PyMem_DebugCheckGIL(__func__); return _PyMem_DebugRawMalloc(ctx, nbytes); } static void * _PyMem_DebugCalloc(void *ctx, size_t nelem, size_t elsize) { - _PyMem_DebugCheckGIL(); + _PyMem_DebugCheckGIL(__func__); return _PyMem_DebugRawCalloc(ctx, nelem, elsize); } @@ -2340,7 +2341,7 @@ _PyMem_DebugCalloc(void *ctx, size_t nelem, size_t elsize) static void _PyMem_DebugFree(void *ctx, void *ptr) { - _PyMem_DebugCheckGIL(); + _PyMem_DebugCheckGIL(__func__); _PyMem_DebugRawFree(ctx, ptr); } @@ -2348,7 +2349,7 @@ _PyMem_DebugFree(void *ctx, void *ptr) static void * _PyMem_DebugRealloc(void *ctx, void *ptr, size_t nbytes) { - _PyMem_DebugCheckGIL(); + _PyMem_DebugCheckGIL(__func__); return _PyMem_DebugRawRealloc(ctx, ptr, nbytes); } @@ -2358,7 +2359,7 @@ _PyMem_DebugRealloc(void *ctx, void *ptr, size_t nbytes) * The API id, is also checked. */ static void -_PyMem_DebugCheckAddress(char api, const void *p) +_PyMem_DebugCheckAddress(const char *func, char api, const void *p) { const uint8_t *q = (const uint8_t *)p; char msgbuf[64]; @@ -2406,7 +2407,7 @@ _PyMem_DebugCheckAddress(char api, const void *p) error: _PyObject_DebugDumpAddress(p); - Py_FatalError(msg); + _Py_FatalErrorFunc(func, msg); } /* Display info to stderr about the memory block at p. */ diff --git a/Parser/parser.c b/Parser/parser.c index 227b9184f471d..a61b2f5ebf7a1 100644 --- a/Parser/parser.c +++ b/Parser/parser.c @@ -54,8 +54,9 @@ s_push(stack *s, const dfa *d, node *parent) static void s_pop(stack *s) { - if (s_empty(s)) - Py_FatalError("s_pop: parser stack underflow -- FATAL"); + if (s_empty(s)) { + Py_FatalError("parser stack underflow"); + } s->s_top++; } diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c index f82b102998171..75e8da4362218 100644 --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -1031,10 +1031,12 @@ static void tok_backup(struct tok_state *tok, int c) { if (c != EOF) { - if (--tok->cur < tok->buf) - Py_FatalError("tok_backup: beginning of buffer"); - if (*tok->cur != c) + if (--tok->cur < tok->buf) { + Py_FatalError("beginning of buffer"); + } + if (*tok->cur != c) { *tok->cur = c; + } } } diff --git a/Python/ceval.c b/Python/ceval.c index 20e32e224e7d4..04e0824727e6e 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -283,7 +283,7 @@ PyEval_AcquireLock(void) struct _ceval_runtime_state *ceval = &runtime->ceval; PyThreadState *tstate = _PyRuntimeState_GetThreadState(runtime); if (tstate == NULL) { - Py_FatalError("PyEval_AcquireLock: current thread state is NULL"); + Py_FatalError("current thread state is NULL"); } take_gil(ceval, tstate); exit_thread_if_finalizing(tstate); @@ -314,7 +314,7 @@ PyEval_AcquireThread(PyThreadState *tstate) take_gil(ceval, tstate); exit_thread_if_finalizing(tstate); if (_PyThreadState_Swap(&runtime->gilstate, tstate) != NULL) { - Py_FatalError("PyEval_AcquireThread: non-NULL old thread state"); + Py_FatalError("non-NULL old thread state"); } } @@ -326,7 +326,7 @@ PyEval_ReleaseThread(PyThreadState *tstate) _PyRuntimeState *runtime = tstate->interp->runtime; PyThreadState *new_tstate = _PyThreadState_Swap(&runtime->gilstate, NULL); if (new_tstate != tstate) { - Py_FatalError("PyEval_ReleaseThread: wrong thread state"); + Py_FatalError("wrong thread state"); } drop_gil(&runtime->ceval, tstate); } @@ -373,7 +373,7 @@ PyEval_SaveThread(void) struct _ceval_runtime_state *ceval = &runtime->ceval; PyThreadState *tstate = _PyThreadState_Swap(&runtime->gilstate, NULL); if (tstate == NULL) { - Py_FatalError("PyEval_SaveThread: NULL tstate"); + Py_FatalError("NULL tstate"); } assert(gil_created(&ceval->gil)); drop_gil(ceval, tstate); @@ -1236,7 +1236,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) if (_Py_atomic_load_relaxed(&ceval->gil_drop_request)) { /* Give another thread a chance */ if (_PyThreadState_Swap(&runtime->gilstate, NULL) != tstate) { - Py_FatalError("ceval: tstate mix-up"); + Py_FatalError("tstate mix-up"); } drop_gil(ceval, tstate); @@ -1248,7 +1248,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) exit_thread_if_finalizing(tstate); if (_PyThreadState_Swap(&runtime->gilstate, tstate) != NULL) { - Py_FatalError("ceval: orphan tstate"); + Py_FatalError("orphan tstate"); } } /* Check for asynchronous exceptions. */ diff --git a/Python/import.c b/Python/import.c index 392d711299e0e..c4a19bc229e55 100644 --- a/Python/import.c +++ b/Python/import.c @@ -310,7 +310,7 @@ PyImport_GetModuleDict(void) { PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE(); if (interp->modules == NULL) { - Py_FatalError("PyImport_GetModuleDict: no module dictionary!"); + Py_FatalError("no module dictionary"); } return interp->modules; } @@ -982,8 +982,7 @@ PyImport_ExecCodeModuleWithPathnames(const char *name, PyObject *co, _Py_IDENTIFIER(_get_sourcefile); if (interp == NULL) { - Py_FatalError("PyImport_ExecCodeModuleWithPathnames: " - "no interpreter!"); + Py_FatalError("no interpreter!"); } external= PyObject_GetAttrString(interp->importlib, diff --git a/Python/pathconfig.c b/Python/pathconfig.c index e37b5612366e4..3756e3a9b83ff 100644 --- a/Python/pathconfig.c +++ b/Python/pathconfig.c @@ -515,7 +515,7 @@ Py_SetPath(const wchar_t *path) || _Py_path_config.exec_prefix == NULL || _Py_path_config.module_search_path == NULL) { - Py_FatalError("Py_SetPath() failed: out of memory"); + Py_FatalError("out of memory"); } } @@ -536,7 +536,7 @@ Py_SetPythonHome(const wchar_t *home) PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); if (_Py_path_config.home == NULL) { - Py_FatalError("Py_SetPythonHome() failed: out of memory"); + Py_FatalError("out of memory"); } } @@ -557,7 +557,7 @@ Py_SetProgramName(const wchar_t *program_name) PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); if (_Py_path_config.program_name == NULL) { - Py_FatalError("Py_SetProgramName() failed: out of memory"); + Py_FatalError("out of memory"); } } @@ -577,7 +577,7 @@ _Py_SetProgramFullPath(const wchar_t *program_full_path) PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); if (_Py_path_config.program_full_path == NULL) { - Py_FatalError("_Py_SetProgramFullPath() failed: out of memory"); + Py_FatalError("out of memory"); } } diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 23d74ee9503aa..9e3b25727945a 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -1611,10 +1611,10 @@ Py_EndInterpreter(PyThreadState *tstate) PyInterpreterState *interp = tstate->interp; if (tstate != _PyThreadState_GET()) { - Py_FatalError("Py_EndInterpreter: thread is not current"); + Py_FatalError("thread is not current"); } if (tstate->frame != NULL) { - Py_FatalError("Py_EndInterpreter: thread still has a frame"); + Py_FatalError("thread still has a frame"); } interp->finalizing = 1; @@ -1624,7 +1624,7 @@ Py_EndInterpreter(PyThreadState *tstate) call_py_exitfuncs(tstate); if (tstate != interp->tstate_head || tstate->next != NULL) { - Py_FatalError("Py_EndInterpreter: not the last thread"); + Py_FatalError("not the last thread"); } _PyImport_Cleanup(tstate); @@ -2241,12 +2241,20 @@ fatal_error(const char *prefix, const char *msg, int status) } } +#undef Py_FatalError + void _Py_NO_RETURN Py_FatalError(const char *msg) { fatal_error(NULL, msg, -1); } +void _Py_NO_RETURN +_Py_FatalErrorFunc(const char *func, const char *msg) +{ + fatal_error(func, msg, -1); +} + void _Py_NO_RETURN Py_ExitStatusException(PyStatus status) { diff --git a/Python/pystate.c b/Python/pystate.c index 900266919dfc4..a1eb5239f7f30 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -327,20 +327,20 @@ PyInterpreterState_Delete(PyInterpreterState *interp) PyInterpreterState **p; for (p = &interpreters->head; ; p = &(*p)->next) { if (*p == NULL) { - Py_FatalError("PyInterpreterState_Delete: invalid interp"); + Py_FatalError("invalid interp"); } if (*p == interp) { break; } } if (interp->tstate_head != NULL) { - Py_FatalError("PyInterpreterState_Delete: remaining threads"); + Py_FatalError("remaining threads"); } *p = interp->next; if (interpreters->main == interp) { interpreters->main = NULL; if (interpreters->head != NULL) { - Py_FatalError("PyInterpreterState_Delete: remaining subinterpreters"); + Py_FatalError("remaining subinterpreters"); } } HEAD_UNLOCK(runtime); @@ -363,7 +363,7 @@ _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime) PyThreadState *tstate = _PyThreadState_Swap(gilstate, NULL); if (tstate != NULL && tstate->interp != interpreters->main) { - Py_FatalError("PyInterpreterState_DeleteExceptMain: not main interpreter"); + Py_FatalError("not main interpreter"); } HEAD_LOCK(runtime); @@ -389,7 +389,7 @@ _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime) HEAD_UNLOCK(runtime); if (interpreters->head == NULL) { - Py_FatalError("PyInterpreterState_DeleteExceptMain: missing main"); + Py_FatalError("missing main"); } _PyThreadState_Swap(gilstate, tstate); } @@ -400,11 +400,11 @@ _PyInterpreterState_Get(void) { PyThreadState *tstate = _PyThreadState_GET(); if (tstate == NULL) { - Py_FatalError("_PyInterpreterState_Get(): no current thread state"); + Py_FatalError("no current thread state"); } PyInterpreterState *interp = tstate->interp; if (interp == NULL) { - Py_FatalError("_PyInterpreterState_Get(): no current interpreter"); + Py_FatalError("no current interpreter"); } return interp; } @@ -695,7 +695,7 @@ int PyState_AddModule(PyObject* module, struct PyModuleDef* def) { if (!def) { - Py_FatalError("PyState_AddModule: Module Definition is NULL"); + Py_FatalError("Module Definition is NULL"); return -1; } @@ -706,7 +706,7 @@ PyState_AddModule(PyObject* module, struct PyModuleDef* def) index < PyList_GET_SIZE(interp->modules_by_index) && module == PyList_GET_ITEM(interp->modules_by_index, index)) { - Py_FatalError("PyState_AddModule: Module already added!"); + Py_FatalError("Module already added"); return -1; } return _PyState_AddModule(tstate, module, def); @@ -724,15 +724,15 @@ PyState_RemoveModule(struct PyModuleDef* def) } state = _PyInterpreterState_GET_UNSAFE(); if (index == 0) { - Py_FatalError("PyState_RemoveModule: Module index invalid."); + Py_FatalError("Module index invalid"); return -1; } if (state->modules_by_index == NULL) { - Py_FatalError("PyState_RemoveModule: Interpreters module-list not accessible."); + Py_FatalError("Interpreters module-list not accessible."); return -1; } if (index > PyList_GET_SIZE(state->modules_by_index)) { - Py_FatalError("PyState_RemoveModule: Module index out of bounds."); + Py_FatalError("Module index out of bounds."); return -1; } Py_INCREF(Py_None); @@ -819,11 +819,11 @@ tstate_delete_common(PyThreadState *tstate, { _PyRuntimeState *runtime = tstate->interp->runtime; if (tstate == NULL) { - Py_FatalError("PyThreadState_Delete: NULL tstate"); + Py_FatalError("NULL tstate"); } PyInterpreterState *interp = tstate->interp; if (interp == NULL) { - Py_FatalError("PyThreadState_Delete: NULL interp"); + Py_FatalError("NULL interp"); } HEAD_LOCK(runtime); if (tstate->prev) @@ -850,7 +850,7 @@ _PyThreadState_Delete(PyThreadState *tstate, int check_current) struct _gilstate_runtime_state *gilstate = &tstate->interp->runtime->gilstate; if (check_current) { if (tstate == _PyRuntimeGILState_GetThreadState(gilstate)) { - Py_FatalError("PyThreadState_Delete: tstate is still current"); + Py_FatalError("tstate is still current"); } } tstate_delete_common(tstate, gilstate); @@ -869,9 +869,9 @@ _PyThreadState_DeleteCurrent(_PyRuntimeState *runtime) { struct _gilstate_runtime_state *gilstate = &runtime->gilstate; PyThreadState *tstate = _PyRuntimeGILState_GetThreadState(gilstate); - if (tstate == NULL) - Py_FatalError( - "PyThreadState_DeleteCurrent: no current tstate"); + if (tstate == NULL) { + Py_FatalError("no current tstate"); + } tstate_delete_common(tstate, gilstate); _PyRuntimeGILState_SetThreadState(gilstate, NULL); PyEval_ReleaseLock(); @@ -932,9 +932,9 @@ PyThreadState * PyThreadState_Get(void) { PyThreadState *tstate = _PyThreadState_GET(); - if (tstate == NULL) - Py_FatalError("PyThreadState_Get: no current thread"); - + if (tstate == NULL) { + Py_FatalError("no current thread"); + } return tstate; } From webhook-mailer at python.org Fri Mar 6 19:11:51 2020 From: webhook-mailer at python.org (Steve Dower) Date: Sat, 07 Mar 2020 00:11:51 -0000 Subject: [Python-checkins] bpo-39837: Disable macOS tests on Azure Pipelines (GH-18818) Message-ID: https://github.com/python/cpython/commit/31350f9af09dcff7cf6ff4b0a0a7ea595942372e commit: 31350f9af09dcff7cf6ff4b0a0a7ea595942372e branch: master author: Steve Dower committer: GitHub date: 2020-03-07T00:11:47Z summary: bpo-39837: Disable macOS tests on Azure Pipelines (GH-18818) files: M .azure-pipelines/ci.yml M .azure-pipelines/pr.yml diff --git a/.azure-pipelines/ci.yml b/.azure-pipelines/ci.yml index 4c2f115cd9b60..6c2c1acc286c0 100644 --- a/.azure-pipelines/ci.yml +++ b/.azure-pipelines/ci.yml @@ -35,7 +35,9 @@ jobs: - job: macOS_CI_Tests displayName: macOS CI Tests dependsOn: Prebuild - condition: and(succeeded(), eq(dependencies.Prebuild.outputs['tests.run'], 'true')) + #condition: and(succeeded(), eq(dependencies.Prebuild.outputs['tests.run'], 'true')) + # bpo-39837: macOS tests on Azure Pipelines are disabled + condition: false variables: testRunTitle: '$(build.sourceBranchName)-macos' diff --git a/.azure-pipelines/pr.yml b/.azure-pipelines/pr.yml index 73d4f55b86450..0cc764d025f40 100644 --- a/.azure-pipelines/pr.yml +++ b/.azure-pipelines/pr.yml @@ -33,7 +33,9 @@ jobs: - job: macOS_PR_Tests displayName: macOS PR Tests dependsOn: Prebuild - condition: and(succeeded(), eq(dependencies.Prebuild.outputs['tests.run'], 'true')) + #condition: and(succeeded(), eq(dependencies.Prebuild.outputs['tests.run'], 'true')) + # bpo-39837: macOS tests on Azure Pipelines are disabled + condition: false variables: testRunTitle: '$(system.pullRequest.TargetBranch)-macos' From webhook-mailer at python.org Fri Mar 6 19:29:56 2020 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 07 Mar 2020 00:29:56 -0000 Subject: [Python-checkins] bpo-39837: Disable macOS tests on Azure Pipelines (GH-18818) Message-ID: https://github.com/python/cpython/commit/47b7c227048f2cb019cc3ec2fef7e867f1b232f3 commit: 47b7c227048f2cb019cc3ec2fef7e867f1b232f3 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2020-03-06T16:29:49-08:00 summary: bpo-39837: Disable macOS tests on Azure Pipelines (GH-18818) (cherry picked from commit 31350f9af09dcff7cf6ff4b0a0a7ea595942372e) Co-authored-by: Steve Dower files: M .azure-pipelines/ci.yml M .azure-pipelines/pr.yml diff --git a/.azure-pipelines/ci.yml b/.azure-pipelines/ci.yml index 38d0cc3e47dd5..7b3af5dc480b2 100644 --- a/.azure-pipelines/ci.yml +++ b/.azure-pipelines/ci.yml @@ -35,7 +35,9 @@ jobs: - job: macOS_CI_Tests displayName: macOS CI Tests dependsOn: Prebuild - condition: and(succeeded(), eq(dependencies.Prebuild.outputs['tests.run'], 'true')) + #condition: and(succeeded(), eq(dependencies.Prebuild.outputs['tests.run'], 'true')) + # bpo-39837: macOS tests on Azure Pipelines are disabled + condition: false variables: testRunTitle: '$(build.sourceBranchName)-macos' diff --git a/.azure-pipelines/pr.yml b/.azure-pipelines/pr.yml index 8661da93d7e78..73f4b96a9bf6e 100644 --- a/.azure-pipelines/pr.yml +++ b/.azure-pipelines/pr.yml @@ -33,7 +33,9 @@ jobs: - job: macOS_PR_Tests displayName: macOS PR Tests dependsOn: Prebuild - condition: and(succeeded(), eq(dependencies.Prebuild.outputs['tests.run'], 'true')) + #condition: and(succeeded(), eq(dependencies.Prebuild.outputs['tests.run'], 'true')) + # bpo-39837: macOS tests on Azure Pipelines are disabled + condition: false variables: testRunTitle: '$(system.pullRequest.TargetBranch)-macos' From webhook-mailer at python.org Fri Mar 6 19:30:14 2020 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 07 Mar 2020 00:30:14 -0000 Subject: [Python-checkins] bpo-39837: Disable macOS tests on Azure Pipelines (GH-18818) Message-ID: https://github.com/python/cpython/commit/d692d52f4aaeb6feaabb18f18d49907dd578fbeb commit: d692d52f4aaeb6feaabb18f18d49907dd578fbeb branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2020-03-06T16:30:09-08:00 summary: bpo-39837: Disable macOS tests on Azure Pipelines (GH-18818) (cherry picked from commit 31350f9af09dcff7cf6ff4b0a0a7ea595942372e) Co-authored-by: Steve Dower files: M .azure-pipelines/ci.yml M .azure-pipelines/pr.yml diff --git a/.azure-pipelines/ci.yml b/.azure-pipelines/ci.yml index 4c2f115cd9b60..6c2c1acc286c0 100644 --- a/.azure-pipelines/ci.yml +++ b/.azure-pipelines/ci.yml @@ -35,7 +35,9 @@ jobs: - job: macOS_CI_Tests displayName: macOS CI Tests dependsOn: Prebuild - condition: and(succeeded(), eq(dependencies.Prebuild.outputs['tests.run'], 'true')) + #condition: and(succeeded(), eq(dependencies.Prebuild.outputs['tests.run'], 'true')) + # bpo-39837: macOS tests on Azure Pipelines are disabled + condition: false variables: testRunTitle: '$(build.sourceBranchName)-macos' diff --git a/.azure-pipelines/pr.yml b/.azure-pipelines/pr.yml index 73d4f55b86450..0cc764d025f40 100644 --- a/.azure-pipelines/pr.yml +++ b/.azure-pipelines/pr.yml @@ -33,7 +33,9 @@ jobs: - job: macOS_PR_Tests displayName: macOS PR Tests dependsOn: Prebuild - condition: and(succeeded(), eq(dependencies.Prebuild.outputs['tests.run'], 'true')) + #condition: and(succeeded(), eq(dependencies.Prebuild.outputs['tests.run'], 'true')) + # bpo-39837: macOS tests on Azure Pipelines are disabled + condition: false variables: testRunTitle: '$(system.pullRequest.TargetBranch)-macos' From webhook-mailer at python.org Sat Mar 7 10:25:39 2020 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sat, 07 Mar 2020 15:25:39 -0000 Subject: [Python-checkins] bpo-39889: Fix ast.unparse() for subscript. (GH-18824) Message-ID: https://github.com/python/cpython/commit/c4928fc1a853f3f84e2b4ec1253d0349137745e5 commit: c4928fc1a853f3f84e2b4ec1253d0349137745e5 branch: master author: Serhiy Storchaka committer: GitHub date: 2020-03-07T17:25:32+02:00 summary: bpo-39889: Fix ast.unparse() for subscript. (GH-18824) files: A Misc/NEWS.d/next/Library/2020-03-07-16-44-51.bpo-39889.3RYqeX.rst M Lib/ast.py M Lib/test/test_unparse.py diff --git a/Lib/ast.py b/Lib/ast.py index 93ffa1edc84d5..2719f6ff7ac59 100644 --- a/Lib/ast.py +++ b/Lib/ast.py @@ -1261,7 +1261,17 @@ def visit_Subscript(self, node): self.set_precedence(_Precedence.ATOM, node.value) self.traverse(node.value) with self.delimit("[", "]"): - self.traverse(node.slice) + if (isinstance(node.slice, Index) + and isinstance(node.slice.value, Tuple) + and node.slice.value.elts): + if len(node.slice.value.elts) == 1: + elt = node.slice.value.elts[0] + self.traverse(elt) + self.write(",") + else: + self.interleave(lambda: self.write(", "), self.traverse, node.slice.value.elts) + else: + self.traverse(node.slice) def visit_Starred(self, node): self.write("*") @@ -1286,7 +1296,12 @@ def visit_Slice(self, node): self.traverse(node.step) def visit_ExtSlice(self, node): - self.interleave(lambda: self.write(", "), self.traverse, node.dims) + if len(node.dims) == 1: + elt = node.dims[0] + self.traverse(elt) + self.write(",") + else: + self.interleave(lambda: self.write(", "), self.traverse, node.dims) def visit_arg(self, node): self.write(node.arg) diff --git a/Lib/test/test_unparse.py b/Lib/test/test_unparse.py index d04db4d5f46e1..d33f32e2a7fe9 100644 --- a/Lib/test/test_unparse.py +++ b/Lib/test/test_unparse.py @@ -344,6 +344,20 @@ def test_simple_expressions_parens(self): self.check_src_roundtrip("call((yield x))") self.check_src_roundtrip("return x + (yield x)") + def test_subscript(self): + self.check_src_roundtrip("a[i]") + self.check_src_roundtrip("a[i,]") + self.check_src_roundtrip("a[i, j]") + self.check_src_roundtrip("a[()]") + self.check_src_roundtrip("a[i:j]") + self.check_src_roundtrip("a[:j]") + self.check_src_roundtrip("a[i:]") + self.check_src_roundtrip("a[i:j:k]") + self.check_src_roundtrip("a[:j:k]") + self.check_src_roundtrip("a[i::k]") + self.check_src_roundtrip("a[i:j,]") + self.check_src_roundtrip("a[i:j, k]") + def test_docstrings(self): docstrings = ( '"""simple doc string"""', diff --git a/Misc/NEWS.d/next/Library/2020-03-07-16-44-51.bpo-39889.3RYqeX.rst b/Misc/NEWS.d/next/Library/2020-03-07-16-44-51.bpo-39889.3RYqeX.rst new file mode 100644 index 0000000000000..62f1d8998d4e5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-03-07-16-44-51.bpo-39889.3RYqeX.rst @@ -0,0 +1,3 @@ +Fixed :func:`ast.unparse` for extended slices containing a single element +(e.g. ``a[i:j,]``). Remove redundant tuples when index with a tuple (e.g. +``a[i, j]``). From webhook-mailer at python.org Sat Mar 7 11:55:36 2020 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sat, 07 Mar 2020 16:55:36 -0000 Subject: [Python-checkins] [3.8] bpo-39889: Fix unparse.py for subscript. (GH-18824). (GH-18826) Message-ID: https://github.com/python/cpython/commit/92b72788ecf2ee5dfac780c7dfb5ee5350fc641d commit: 92b72788ecf2ee5dfac780c7dfb5ee5350fc641d branch: 3.8 author: Serhiy Storchaka committer: GitHub date: 2020-03-07T18:55:32+02:00 summary: [3.8] bpo-39889: Fix unparse.py for subscript. (GH-18824). (GH-18826) (cherry picked from commit c4928fc1a853f3f84e2b4ec1253d0349137745e5) files: A Misc/NEWS.d/next/Tools-Demos/2020-03-07-18-01-30.bpo-39889.l1czT6.rst M Lib/test/test_tools/test_unparse.py M Tools/parser/unparse.py diff --git a/Lib/test/test_tools/test_unparse.py b/Lib/test/test_tools/test_unparse.py index a958ebb51cc3d..d89cb09776756 100644 --- a/Lib/test/test_tools/test_unparse.py +++ b/Lib/test/test_tools/test_unparse.py @@ -265,6 +265,20 @@ def test_dict_unpacking_in_dict(self): self.check_roundtrip(r"""{**{'y': 2}, 'x': 1}""") self.check_roundtrip(r"""{**{'y': 2}, **{'x': 1}}""") + def test_subscript(self): + self.check_roundtrip("a[i]") + self.check_roundtrip("a[i,]") + self.check_roundtrip("a[i, j]") + self.check_roundtrip("a[()]") + self.check_roundtrip("a[i:j]") + self.check_roundtrip("a[:j]") + self.check_roundtrip("a[i:]") + self.check_roundtrip("a[i:j:k]") + self.check_roundtrip("a[:j:k]") + self.check_roundtrip("a[i::k]") + self.check_roundtrip("a[i:j,]") + self.check_roundtrip("a[i:j, k]") + class DirectoryTestCase(ASTTestCase): """Test roundtrip behaviour on all files in Lib and Lib/test.""" diff --git a/Misc/NEWS.d/next/Tools-Demos/2020-03-07-18-01-30.bpo-39889.l1czT6.rst b/Misc/NEWS.d/next/Tools-Demos/2020-03-07-18-01-30.bpo-39889.l1czT6.rst new file mode 100644 index 0000000000000..1202cb5fa064b --- /dev/null +++ b/Misc/NEWS.d/next/Tools-Demos/2020-03-07-18-01-30.bpo-39889.l1czT6.rst @@ -0,0 +1,3 @@ +Fixed ``unparse.py`` for extended slices containing a single element (e.g. +``a[i:j,]``). Remove redundant tuples when index with a tuple (e.g. ``a[i, +j]``). diff --git a/Tools/parser/unparse.py b/Tools/parser/unparse.py index a5cc000676b02..0642b84dcfc82 100644 --- a/Tools/parser/unparse.py +++ b/Tools/parser/unparse.py @@ -556,7 +556,17 @@ def _Call(self, t): def _Subscript(self, t): self.dispatch(t.value) self.write("[") - self.dispatch(t.slice) + if (isinstance(t.slice, ast.Index) + and isinstance(t.slice.value, ast.Tuple) + and t.slice.value.elts): + if len(t.slice.value.elts) == 1: + elt = t.slice.value.elts[0] + self.dispatch(elt) + self.write(",") + else: + interleave(lambda: self.write(", "), self.dispatch, t.slice.value.elts) + else: + self.dispatch(t.slice) self.write("]") def _Starred(self, t): @@ -581,7 +591,12 @@ def _Slice(self, t): self.dispatch(t.step) def _ExtSlice(self, t): - interleave(lambda: self.write(', '), self.dispatch, t.dims) + if len(t.dims) == 1: + elt = t.dims[0] + self.dispatch(elt) + self.write(",") + else: + interleave(lambda: self.write(', '), self.dispatch, t.dims) # argument def _arg(self, t): From webhook-mailer at python.org Sat Mar 7 12:13:36 2020 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 07 Mar 2020 17:13:36 -0000 Subject: [Python-checkins] [3.8] bpo-39889: Fix unparse.py for subscript. (GH-18824). (GH-18826) Message-ID: https://github.com/python/cpython/commit/65b031090161331470827ec809732008b15030d5 commit: 65b031090161331470827ec809732008b15030d5 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2020-03-07T09:13:31-08:00 summary: [3.8] bpo-39889: Fix unparse.py for subscript. (GH-18824). (GH-18826) (cherry picked from commit c4928fc1a853f3f84e2b4ec1253d0349137745e5) (cherry picked from commit 92b72788ecf2ee5dfac780c7dfb5ee5350fc641d) Co-authored-by: Serhiy Storchaka files: A Misc/NEWS.d/next/Tools-Demos/2020-03-07-18-01-30.bpo-39889.l1czT6.rst M Lib/test/test_tools/test_unparse.py M Tools/parser/unparse.py diff --git a/Lib/test/test_tools/test_unparse.py b/Lib/test/test_tools/test_unparse.py index f3386f5e31a2d..12a41c756cdde 100644 --- a/Lib/test/test_tools/test_unparse.py +++ b/Lib/test/test_tools/test_unparse.py @@ -260,6 +260,20 @@ def test_dict_unpacking_in_dict(self): self.check_roundtrip(r"""{**{'y': 2}, 'x': 1}""") self.check_roundtrip(r"""{**{'y': 2}, **{'x': 1}}""") + def test_subscript(self): + self.check_roundtrip("a[i]") + self.check_roundtrip("a[i,]") + self.check_roundtrip("a[i, j]") + self.check_roundtrip("a[()]") + self.check_roundtrip("a[i:j]") + self.check_roundtrip("a[:j]") + self.check_roundtrip("a[i:]") + self.check_roundtrip("a[i:j:k]") + self.check_roundtrip("a[:j:k]") + self.check_roundtrip("a[i::k]") + self.check_roundtrip("a[i:j,]") + self.check_roundtrip("a[i:j, k]") + class DirectoryTestCase(ASTTestCase): """Test roundtrip behaviour on all files in Lib and Lib/test.""" diff --git a/Misc/NEWS.d/next/Tools-Demos/2020-03-07-18-01-30.bpo-39889.l1czT6.rst b/Misc/NEWS.d/next/Tools-Demos/2020-03-07-18-01-30.bpo-39889.l1czT6.rst new file mode 100644 index 0000000000000..1202cb5fa064b --- /dev/null +++ b/Misc/NEWS.d/next/Tools-Demos/2020-03-07-18-01-30.bpo-39889.l1czT6.rst @@ -0,0 +1,3 @@ +Fixed ``unparse.py`` for extended slices containing a single element (e.g. +``a[i:j,]``). Remove redundant tuples when index with a tuple (e.g. ``a[i, +j]``). diff --git a/Tools/parser/unparse.py b/Tools/parser/unparse.py index 7e1cc4ea5db95..721ac3c6483d9 100644 --- a/Tools/parser/unparse.py +++ b/Tools/parser/unparse.py @@ -562,7 +562,17 @@ def _Call(self, t): def _Subscript(self, t): self.dispatch(t.value) self.write("[") - self.dispatch(t.slice) + if (isinstance(t.slice, ast.Index) + and isinstance(t.slice.value, ast.Tuple) + and t.slice.value.elts): + if len(t.slice.value.elts) == 1: + elt = t.slice.value.elts[0] + self.dispatch(elt) + self.write(",") + else: + interleave(lambda: self.write(", "), self.dispatch, t.slice.value.elts) + else: + self.dispatch(t.slice) self.write("]") def _Starred(self, t): @@ -587,7 +597,12 @@ def _Slice(self, t): self.dispatch(t.step) def _ExtSlice(self, t): - interleave(lambda: self.write(', '), self.dispatch, t.dims) + if len(t.dims) == 1: + elt = t.dims[0] + self.dispatch(elt) + self.write(",") + else: + interleave(lambda: self.write(', '), self.dispatch, t.dims) # argument def _arg(self, t): From webhook-mailer at python.org Sat Mar 7 12:29:15 2020 From: webhook-mailer at python.org (Andy Lester) Date: Sat, 07 Mar 2020 17:29:15 -0000 Subject: [Python-checkins] closes bpo-39878: Remove unused arguments from static functions. (GH-18822) Message-ID: https://github.com/python/cpython/commit/ad0c775ea24bb827410f01ece9f191309292bb95 commit: ad0c775ea24bb827410f01ece9f191309292bb95 branch: master author: Andy Lester committer: GitHub date: 2020-03-07T09:29:10-08:00 summary: closes bpo-39878: Remove unused arguments from static functions. (GH-18822) calc_number_widths -> PyObject *number fill_number -> Py_ssize_t d_end files: M Python/formatter_unicode.c diff --git a/Python/formatter_unicode.c b/Python/formatter_unicode.c index 705e12dd446da..55ed59d36898d 100644 --- a/Python/formatter_unicode.c +++ b/Python/formatter_unicode.c @@ -466,7 +466,7 @@ parse_number(PyObject *s, Py_ssize_t pos, Py_ssize_t end, Return -1 on error. */ static Py_ssize_t calc_number_widths(NumberFieldWidths *spec, Py_ssize_t n_prefix, - Py_UCS4 sign_char, PyObject *number, Py_ssize_t n_start, + Py_UCS4 sign_char, Py_ssize_t n_start, Py_ssize_t n_end, Py_ssize_t n_remainder, int has_decimal, const LocaleInfo *locale, const InternalFormatSpec *format, Py_UCS4 *maxchar) @@ -595,7 +595,7 @@ calc_number_widths(NumberFieldWidths *spec, Py_ssize_t n_prefix, Return -1 on error, or 0 on success. */ static int fill_number(_PyUnicodeWriter *writer, const NumberFieldWidths *spec, - PyObject *digits, Py_ssize_t d_start, Py_ssize_t d_end, + PyObject *digits, Py_ssize_t d_start, PyObject *prefix, Py_ssize_t p_start, Py_UCS4 fill_char, LocaleInfo *locale, int toupper) @@ -983,7 +983,7 @@ format_long_internal(PyObject *value, const InternalFormatSpec *format, goto done; /* Calculate how much memory we'll need. */ - n_total = calc_number_widths(&spec, n_prefix, sign_char, tmp, inumeric_chars, + n_total = calc_number_widths(&spec, n_prefix, sign_char, inumeric_chars, inumeric_chars + n_digits, n_remainder, 0, &locale, format, &maxchar); if (n_total == -1) { @@ -996,7 +996,7 @@ format_long_internal(PyObject *value, const InternalFormatSpec *format, /* Populate the memory. */ result = fill_number(writer, &spec, - tmp, inumeric_chars, inumeric_chars + n_digits, + tmp, inumeric_chars, tmp, prefix, format->fill_char, &locale, format->type == 'X'); @@ -1131,7 +1131,7 @@ format_float_internal(PyObject *value, goto done; /* Calculate how much memory we'll need. */ - n_total = calc_number_widths(&spec, 0, sign_char, unicode_tmp, index, + n_total = calc_number_widths(&spec, 0, sign_char, index, index + n_digits, n_remainder, has_decimal, &locale, format, &maxchar); if (n_total == -1) { @@ -1144,7 +1144,7 @@ format_float_internal(PyObject *value, /* Populate the memory. */ result = fill_number(writer, &spec, - unicode_tmp, index, index + n_digits, + unicode_tmp, index, NULL, 0, format->fill_char, &locale, 0); @@ -1316,7 +1316,7 @@ format_complex_internal(PyObject *value, tmp_format.width = -1; /* Calculate how much memory we'll need. */ - n_re_total = calc_number_widths(&re_spec, 0, re_sign_char, re_unicode_tmp, + n_re_total = calc_number_widths(&re_spec, 0, re_sign_char, i_re, i_re + n_re_digits, n_re_remainder, re_has_decimal, &locale, &tmp_format, &maxchar); @@ -1329,7 +1329,7 @@ format_complex_internal(PyObject *value, * requested by the original format. */ if (!skip_re) tmp_format.sign = '+'; - n_im_total = calc_number_widths(&im_spec, 0, im_sign_char, im_unicode_tmp, + n_im_total = calc_number_widths(&im_spec, 0, im_sign_char, i_im, i_im + n_im_digits, n_im_remainder, im_has_decimal, &locale, &tmp_format, &maxchar); @@ -1366,7 +1366,7 @@ format_complex_internal(PyObject *value, if (!skip_re) { result = fill_number(writer, &re_spec, - re_unicode_tmp, i_re, i_re + n_re_digits, + re_unicode_tmp, i_re, NULL, 0, 0, &locale, 0); @@ -1374,7 +1374,7 @@ format_complex_internal(PyObject *value, goto done; } result = fill_number(writer, &im_spec, - im_unicode_tmp, i_im, i_im + n_im_digits, + im_unicode_tmp, i_im, NULL, 0, 0, &locale, 0); From webhook-mailer at python.org Sat Mar 7 12:36:09 2020 From: webhook-mailer at python.org (Andy Lester) Date: Sat, 07 Mar 2020 17:36:09 -0000 Subject: [Python-checkins] closes bpo-39886: Remove unused arg from config_get_stdio_errors. (GH-18823) Message-ID: https://github.com/python/cpython/commit/aa450a0364b6160be7dd61ec2d378abb0652f014 commit: aa450a0364b6160be7dd61ec2d378abb0652f014 branch: master author: Andy Lester committer: GitHub date: 2020-03-07T09:36:04-08:00 summary: closes bpo-39886: Remove unused arg from config_get_stdio_errors. (GH-18823) files: M Python/initconfig.c diff --git a/Python/initconfig.c b/Python/initconfig.c index 493b4bb440656..22232ad28c7c7 100644 --- a/Python/initconfig.c +++ b/Python/initconfig.c @@ -1434,7 +1434,7 @@ config_read_complex_options(PyConfig *config) static const wchar_t * -config_get_stdio_errors(const PyConfig *config) +config_get_stdio_errors(void) { #ifndef MS_WINDOWS const char *loc = setlocale(LC_CTYPE, NULL); @@ -1590,7 +1590,7 @@ config_init_stdio_encoding(PyConfig *config, } } if (config->stdio_errors == NULL) { - const wchar_t *errors = config_get_stdio_errors(config); + const wchar_t *errors = config_get_stdio_errors(); assert(errors != NULL); status = PyConfig_SetString(config, &config->stdio_errors, errors); From webhook-mailer at python.org Sat Mar 7 12:53:24 2020 From: webhook-mailer at python.org (Pablo Galindo) Date: Sat, 07 Mar 2020 17:53:24 -0000 Subject: [Python-checkins] bpo-38894: Fix pathlib.Path.glob in the presence of symlinks and insufficient permissions (GH-18815) Message-ID: https://github.com/python/cpython/commit/eb7560a73d46800e4ade4a8869139b48e6c92811 commit: eb7560a73d46800e4ade4a8869139b48e6c92811 branch: master author: Pablo Galindo committer: GitHub date: 2020-03-07T17:53:20Z summary: bpo-38894: Fix pathlib.Path.glob in the presence of symlinks and insufficient permissions (GH-18815) Co-authored-by: Matt Wozniski files: A Misc/NEWS.d/next/Core and Builtins/2020-03-06-21-04-39.bpo-38894.nfcGKv.rst M Lib/pathlib.py M Lib/test/test_pathlib.py diff --git a/Lib/pathlib.py b/Lib/pathlib.py index cfa574af6e8ba..851aabd479725 100644 --- a/Lib/pathlib.py +++ b/Lib/pathlib.py @@ -529,23 +529,26 @@ def _select_from(self, parent_path, is_dir, exists, scandir): try: entries = list(scandir(parent_path)) for entry in entries: - entry_is_dir = False - try: - entry_is_dir = entry.is_dir() - except OSError as e: - if not _ignore_error(e): - raise - if not self.dironly or entry_is_dir: - name = entry.name - if self.match(name): - path = parent_path._make_child_relpath(name) - for p in self.successor._select_from(path, is_dir, exists, scandir): - yield p + if self.dironly: + try: + # "entry.is_dir()" can raise PermissionError + # in some cases (see bpo-38894), which is not + # among the errors ignored by _ignore_error() + if not entry.is_dir(): + continue + except OSError as e: + if not _ignore_error(e): + raise + continue + name = entry.name + if self.match(name): + path = parent_path._make_child_relpath(name) + for p in self.successor._select_from(path, is_dir, exists, scandir): + yield p except PermissionError: return - class _RecursiveWildcardSelector(_Selector): def __init__(self, pat, child_parts, flavour): diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index a50dce0171808..5b362a0ff3d9b 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -1595,6 +1595,42 @@ def test_glob_dotdot(self): self.assertEqual(set(p.glob("dirA/../file*")), { P(BASE, "dirA/../fileA") }) self.assertEqual(set(p.glob("../xyzzy")), set()) + @support.skip_unless_symlink + def test_glob_permissions(self): + # See bpo-38894 + P = self.cls + base = P(BASE) / 'permissions' + base.mkdir() + + file1 = base / "file1" + file1.touch() + file2 = base / "file2" + file2.touch() + + subdir = base / "subdir" + + file3 = base / "file3" + file3.symlink_to(subdir / "other") + + # Patching is needed to avoid relying on the filesystem + # to return the order of the files as the error will not + # happen if the symlink is the last item. + + with mock.patch("os.scandir") as scandir: + scandir.return_value = sorted(os.scandir(base)) + self.assertEqual(len(set(base.glob("*"))), 3) + + subdir.mkdir() + + with mock.patch("os.scandir") as scandir: + scandir.return_value = sorted(os.scandir(base)) + self.assertEqual(len(set(base.glob("*"))), 4) + + subdir.chmod(000) + + with mock.patch("os.scandir") as scandir: + scandir.return_value = sorted(os.scandir(base)) + self.assertEqual(len(set(base.glob("*"))), 4) def _check_resolve(self, p, expected, strict=True): q = p.resolve(strict) diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-03-06-21-04-39.bpo-38894.nfcGKv.rst b/Misc/NEWS.d/next/Core and Builtins/2020-03-06-21-04-39.bpo-38894.nfcGKv.rst new file mode 100644 index 0000000000000..a937b8ecc626f --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2020-03-06-21-04-39.bpo-38894.nfcGKv.rst @@ -0,0 +1,4 @@ +Fix a bug that was causing incomplete results when calling +``pathlib.Path.glob`` in the presence of symlinks that point +to files where the user does not have read access. Patch by Pablo +Galindo and Matt Wozniski. From webhook-mailer at python.org Sat Mar 7 13:10:16 2020 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 07 Mar 2020 18:10:16 -0000 Subject: [Python-checkins] bpo-38894: Fix pathlib.Path.glob in the presence of symlinks and insufficient permissions (GH-18815) Message-ID: https://github.com/python/cpython/commit/cca0b31fb8ed7d25ede68f314d4a85bb07d6ca6f commit: cca0b31fb8ed7d25ede68f314d4a85bb07d6ca6f branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2020-03-07T10:10:10-08:00 summary: bpo-38894: Fix pathlib.Path.glob in the presence of symlinks and insufficient permissions (GH-18815) Co-authored-by: Matt Wozniski (cherry picked from commit eb7560a73d46800e4ade4a8869139b48e6c92811) Co-authored-by: Pablo Galindo files: A Misc/NEWS.d/next/Core and Builtins/2020-03-06-21-04-39.bpo-38894.nfcGKv.rst M Lib/pathlib.py M Lib/test/test_pathlib.py diff --git a/Lib/pathlib.py b/Lib/pathlib.py index d868254bc5512..b2cc39857a577 100644 --- a/Lib/pathlib.py +++ b/Lib/pathlib.py @@ -524,23 +524,26 @@ def _select_from(self, parent_path, is_dir, exists, scandir): try: entries = list(scandir(parent_path)) for entry in entries: - entry_is_dir = False - try: - entry_is_dir = entry.is_dir() - except OSError as e: - if not _ignore_error(e): - raise - if not self.dironly or entry_is_dir: - name = entry.name - if self.match(name): - path = parent_path._make_child_relpath(name) - for p in self.successor._select_from(path, is_dir, exists, scandir): - yield p + if self.dironly: + try: + # "entry.is_dir()" can raise PermissionError + # in some cases (see bpo-38894), which is not + # among the errors ignored by _ignore_error() + if not entry.is_dir(): + continue + except OSError as e: + if not _ignore_error(e): + raise + continue + name = entry.name + if self.match(name): + path = parent_path._make_child_relpath(name) + for p in self.successor._select_from(path, is_dir, exists, scandir): + yield p except PermissionError: return - class _RecursiveWildcardSelector(_Selector): def __init__(self, pat, child_parts, flavour): diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index e1d699a0d5246..83181b4322e92 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -1478,6 +1478,42 @@ def test_glob_dotdot(self): self.assertEqual(set(p.glob("dirA/../file*")), { P(BASE, "dirA/../fileA") }) self.assertEqual(set(p.glob("../xyzzy")), set()) + @support.skip_unless_symlink + def test_glob_permissions(self): + # See bpo-38894 + P = self.cls + base = P(BASE) / 'permissions' + base.mkdir() + + file1 = base / "file1" + file1.touch() + file2 = base / "file2" + file2.touch() + + subdir = base / "subdir" + + file3 = base / "file3" + file3.symlink_to(subdir / "other") + + # Patching is needed to avoid relying on the filesystem + # to return the order of the files as the error will not + # happen if the symlink is the last item. + + with mock.patch("os.scandir") as scandir: + scandir.return_value = sorted(os.scandir(base)) + self.assertEqual(len(set(base.glob("*"))), 3) + + subdir.mkdir() + + with mock.patch("os.scandir") as scandir: + scandir.return_value = sorted(os.scandir(base)) + self.assertEqual(len(set(base.glob("*"))), 4) + + subdir.chmod(000) + + with mock.patch("os.scandir") as scandir: + scandir.return_value = sorted(os.scandir(base)) + self.assertEqual(len(set(base.glob("*"))), 4) def _check_resolve(self, p, expected, strict=True): q = p.resolve(strict) diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-03-06-21-04-39.bpo-38894.nfcGKv.rst b/Misc/NEWS.d/next/Core and Builtins/2020-03-06-21-04-39.bpo-38894.nfcGKv.rst new file mode 100644 index 0000000000000..a937b8ecc626f --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2020-03-06-21-04-39.bpo-38894.nfcGKv.rst @@ -0,0 +1,4 @@ +Fix a bug that was causing incomplete results when calling +``pathlib.Path.glob`` in the presence of symlinks that point +to files where the user does not have read access. Patch by Pablo +Galindo and Matt Wozniski. From webhook-mailer at python.org Sat Mar 7 13:11:29 2020 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 07 Mar 2020 18:11:29 -0000 Subject: [Python-checkins] bpo-38894: Fix pathlib.Path.glob in the presence of symlinks and insufficient permissions (GH-18815) Message-ID: https://github.com/python/cpython/commit/928b4dd0edf0022190a8a296c8ea65e7ef55c694 commit: 928b4dd0edf0022190a8a296c8ea65e7ef55c694 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2020-03-07T10:11:24-08:00 summary: bpo-38894: Fix pathlib.Path.glob in the presence of symlinks and insufficient permissions (GH-18815) Co-authored-by: Matt Wozniski (cherry picked from commit eb7560a73d46800e4ade4a8869139b48e6c92811) Co-authored-by: Pablo Galindo files: A Misc/NEWS.d/next/Core and Builtins/2020-03-06-21-04-39.bpo-38894.nfcGKv.rst M Lib/pathlib.py M Lib/test/test_pathlib.py diff --git a/Lib/pathlib.py b/Lib/pathlib.py index 015370a860e65..d188026bcde84 100644 --- a/Lib/pathlib.py +++ b/Lib/pathlib.py @@ -529,23 +529,26 @@ def _select_from(self, parent_path, is_dir, exists, scandir): try: entries = list(scandir(parent_path)) for entry in entries: - entry_is_dir = False - try: - entry_is_dir = entry.is_dir() - except OSError as e: - if not _ignore_error(e): - raise - if not self.dironly or entry_is_dir: - name = entry.name - if self.match(name): - path = parent_path._make_child_relpath(name) - for p in self.successor._select_from(path, is_dir, exists, scandir): - yield p + if self.dironly: + try: + # "entry.is_dir()" can raise PermissionError + # in some cases (see bpo-38894), which is not + # among the errors ignored by _ignore_error() + if not entry.is_dir(): + continue + except OSError as e: + if not _ignore_error(e): + raise + continue + name = entry.name + if self.match(name): + path = parent_path._make_child_relpath(name) + for p in self.successor._select_from(path, is_dir, exists, scandir): + yield p except PermissionError: return - class _RecursiveWildcardSelector(_Selector): def __init__(self, pat, child_parts, flavour): diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index 97fc5d8ad7838..36226948222d6 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -1508,6 +1508,42 @@ def test_glob_dotdot(self): self.assertEqual(set(p.glob("dirA/../file*")), { P(BASE, "dirA/../fileA") }) self.assertEqual(set(p.glob("../xyzzy")), set()) + @support.skip_unless_symlink + def test_glob_permissions(self): + # See bpo-38894 + P = self.cls + base = P(BASE) / 'permissions' + base.mkdir() + + file1 = base / "file1" + file1.touch() + file2 = base / "file2" + file2.touch() + + subdir = base / "subdir" + + file3 = base / "file3" + file3.symlink_to(subdir / "other") + + # Patching is needed to avoid relying on the filesystem + # to return the order of the files as the error will not + # happen if the symlink is the last item. + + with mock.patch("os.scandir") as scandir: + scandir.return_value = sorted(os.scandir(base)) + self.assertEqual(len(set(base.glob("*"))), 3) + + subdir.mkdir() + + with mock.patch("os.scandir") as scandir: + scandir.return_value = sorted(os.scandir(base)) + self.assertEqual(len(set(base.glob("*"))), 4) + + subdir.chmod(000) + + with mock.patch("os.scandir") as scandir: + scandir.return_value = sorted(os.scandir(base)) + self.assertEqual(len(set(base.glob("*"))), 4) def _check_resolve(self, p, expected, strict=True): q = p.resolve(strict) diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-03-06-21-04-39.bpo-38894.nfcGKv.rst b/Misc/NEWS.d/next/Core and Builtins/2020-03-06-21-04-39.bpo-38894.nfcGKv.rst new file mode 100644 index 0000000000000..a937b8ecc626f --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2020-03-06-21-04-39.bpo-38894.nfcGKv.rst @@ -0,0 +1,4 @@ +Fix a bug that was causing incomplete results when calling +``pathlib.Path.glob`` in the presence of symlinks that point +to files where the user does not have read access. Patch by Pablo +Galindo and Matt Wozniski. From webhook-mailer at python.org Sat Mar 7 13:23:04 2020 From: webhook-mailer at python.org (Pablo Galindo) Date: Sat, 07 Mar 2020 18:23:04 -0000 Subject: [Python-checkins] bpo-39199: Use 'eval' mode for the examples with expression nodes (GH-18828) Message-ID: https://github.com/python/cpython/commit/02f64cb79175902705b40e3eaa8ea6c7038754ef commit: 02f64cb79175902705b40e3eaa8ea6c7038754ef branch: master author: Pablo Galindo committer: GitHub date: 2020-03-07T18:22:58Z summary: bpo-39199: Use 'eval' mode for the examples with expression nodes (GH-18828) Co-Authored-By: Serhiy Storchaka files: M Doc/library/ast.rst diff --git a/Doc/library/ast.rst b/Doc/library/ast.rst index ea3057867b0f0..01735643dbb9b 100644 --- a/Doc/library/ast.rst +++ b/Doc/library/ast.rst @@ -139,12 +139,9 @@ Literals .. doctest:: - >>> print(ast.dump(ast.parse("123"), indent=4)) - Module( - body=[ - Expr( - value=Constant(value=123, kind=None))], - type_ignores=[]) + >>> print(ast.dump(ast.parse('123', mode='eval'), indent=4)) + Expression( + body=Constant(value=123, kind=None)) .. class:: FormattedValue(value, conversion, format_spec) @@ -174,29 +171,26 @@ Literals .. doctest:: - >>> print(ast.dump(ast.parse('f"sin({a}) is {sin(a):.3}"'), indent=4)) - Module( - body=[ - Expr( - value=JoinedStr( - values=[ - Constant(value='sin(', kind=None), - FormattedValue( - value=Name(id='a', ctx=Load()), - conversion=-1, - format_spec=None), - Constant(value=') is ', kind=None), - FormattedValue( - value=Call( - func=Name(id='sin', ctx=Load()), - args=[ - Name(id='a', ctx=Load())], - keywords=[]), - conversion=-1, - format_spec=JoinedStr( - values=[ - Constant(value='.3', kind=None)]))]))], - type_ignores=[]) + >>> print(ast.dump(ast.parse('f"sin({a}) is {sin(a):.3}"', mode='eval'), indent=4)) + Expression( + body=JoinedStr( + values=[ + Constant(value='sin(', kind=None), + FormattedValue( + value=Name(id='a', ctx=Load()), + conversion=-1, + format_spec=None), + Constant(value=') is ', kind=None), + FormattedValue( + value=Call( + func=Name(id='sin', ctx=Load()), + args=[ + Name(id='a', ctx=Load())], + keywords=[]), + conversion=-1, + format_spec=JoinedStr( + values=[ + Constant(value='.3', kind=None)]))])) .. class:: List(elts, ctx) @@ -208,29 +202,22 @@ Literals .. doctest:: - >>> print(ast.dump(ast.parse("[1, 2, 3]"), indent=4)) - Module( - body=[ - Expr( - value=List( - elts=[ - Constant(value=1, kind=None), - Constant(value=2, kind=None), - Constant(value=3, kind=None)], - ctx=Load()))], - type_ignores=[]) - - >>> print(ast.dump(ast.parse("(1, 2, 3)"), indent=4)) - Module( - body=[ - Expr( - value=Tuple( - elts=[ - Constant(value=1, kind=None), - Constant(value=2, kind=None), - Constant(value=3, kind=None)], - ctx=Load()))], - type_ignores=[]) + >>> print(ast.dump(ast.parse('[1, 2, 3]', mode='eval'), indent=4)) + Expression( + body=List( + elts=[ + Constant(value=1, kind=None), + Constant(value=2, kind=None), + Constant(value=3, kind=None)], + ctx=Load())) + >>> print(ast.dump(ast.parse('(1, 2, 3)', mode='eval'), indent=4)) + Expression( + body=Tuple( + elts=[ + Constant(value=1, kind=None), + Constant(value=2, kind=None), + Constant(value=3, kind=None)], + ctx=Load())) .. class:: Set(elts) @@ -239,16 +226,13 @@ Literals .. doctest:: - >>> print(ast.dump(ast.parse("{1, 2, 3}"), indent=4)) - Module( - body=[ - Expr( - value=Set( - elts=[ - Constant(value=1, kind=None), - Constant(value=2, kind=None), - Constant(value=3, kind=None)]))], - type_ignores=[]) + >>> print(ast.dump(ast.parse('{1, 2, 3}', mode='eval'), indent=4)) + Expression( + body=Set( + elts=[ + Constant(value=1, kind=None), + Constant(value=2, kind=None), + Constant(value=3, kind=None)])) .. class:: Dict(keys, values) @@ -263,18 +247,15 @@ Literals .. doctest:: - >>> print(ast.dump(ast.parse("{'a':1, **d}"), indent=4)) - Module( - body=[ - Expr( - value=Dict( - keys=[ - Constant(value='a', kind=None), - None], - values=[ - Constant(value=1, kind=None), - Name(id='d', ctx=Load())]))], - type_ignores=[]) + >>> print(ast.dump(ast.parse('{"a":1, **d}', mode='eval'), indent=4)) + Expression( + body=Dict( + keys=[ + Constant(value='a', kind=None), + None], + values=[ + Constant(value=1, kind=None), + Name(id='d', ctx=Load())])) Variables @@ -385,14 +366,11 @@ Expressions .. doctest:: - >>> print(ast.dump(ast.parse("not x"), indent=4)) - Module( - body=[ - Expr( - value=UnaryOp( - op=Not(), - operand=Name(id='x', ctx=Load())))], - type_ignores=[]) + >>> print(ast.dump(ast.parse('not x', mode='eval'), indent=4)) + Expression( + body=UnaryOp( + op=Not(), + operand=Name(id='x', ctx=Load()))) .. class:: BinOp(left, op, right) @@ -402,15 +380,12 @@ Expressions .. doctest:: - >>> print(ast.dump(ast.parse("x + y"), indent=4)) - Module( - body=[ - Expr( - value=BinOp( - left=Name(id='x', ctx=Load()), - op=Add(), - right=Name(id='y', ctx=Load())))], - type_ignores=[]) + >>> print(ast.dump(ast.parse('x + y', mode='eval'), indent=4)) + Expression( + body=BinOp( + left=Name(id='x', ctx=Load()), + op=Add(), + right=Name(id='y', ctx=Load()))) .. class:: Add @@ -441,16 +416,13 @@ Expressions .. doctest:: - >>> print(ast.dump(ast.parse("x or y"), indent=4)) - Module( - body=[ - Expr( - value=BoolOp( - op=Or(), - values=[ - Name(id='x', ctx=Load()), - Name(id='y', ctx=Load())]))], - type_ignores=[]) + >>> print(ast.dump(ast.parse('x or y', mode='eval'), indent=4)) + Expression( + body=BoolOp( + op=Or(), + values=[ + Name(id='x', ctx=Load()), + Name(id='y', ctx=Load())])) .. class:: And @@ -467,19 +439,16 @@ Expressions .. doctest:: - >>> print(ast.dump(ast.parse("1 < a < 10"), indent=4)) - Module( - body=[ - Expr( - value=Compare( - left=Constant(value=1, kind=None), - ops=[ - Lt(), - Lt()], - comparators=[ - Name(id='a', ctx=Load()), - Constant(value=10, kind=None)]))], - type_ignores=[]) + >>> print(ast.dump(ast.parse('1 <= a < 10', mode='eval'), indent=4)) + Expression( + body=Compare( + left=Constant(value=1, kind=None), + ops=[ + LtE(), + Lt()], + comparators=[ + Name(id='a', ctx=Load()), + Constant(value=10, kind=None)])) .. class:: Eq @@ -510,25 +479,22 @@ Expressions .. doctest:: - >>> print(ast.dump(ast.parse('func(a, b=c, *d, **e)'), indent=4)) - Module( - body=[ - Expr( - value=Call( - func=Name(id='func', ctx=Load()), - args=[ - Name(id='a', ctx=Load()), - Starred( - value=Name(id='d', ctx=Load()), - ctx=Load())], - keywords=[ - keyword( - arg='b', - value=Name(id='c', ctx=Load())), - keyword( - arg=None, - value=Name(id='e', ctx=Load()))]))], - type_ignores=[]) + >>> print(ast.dump(ast.parse('func(a, b=c, *d, **e)', mode='eval'), indent=4)) + Expression( + body=Call( + func=Name(id='func', ctx=Load()), + args=[ + Name(id='a', ctx=Load()), + Starred( + value=Name(id='d', ctx=Load()), + ctx=Load())], + keywords=[ + keyword( + arg='b', + value=Name(id='c', ctx=Load())), + keyword( + arg=None, + value=Name(id='e', ctx=Load()))])) .. class:: keyword(arg, value) @@ -544,15 +510,12 @@ Expressions .. doctest:: - >>> print(ast.dump(ast.parse("a if b else c"), indent=4)) - Module( - body=[ - Expr( - value=IfExp( - test=Name(id='b', ctx=Load()), - body=Name(id='a', ctx=Load()), - orelse=Name(id='c', ctx=Load())))], - type_ignores=[]) + >>> print(ast.dump(ast.parse('a if b else c', mode='eval'), indent=4)) + Expression( + body=IfExp( + test=Name(id='b', ctx=Load()), + body=Name(id='a', ctx=Load()), + orelse=Name(id='c', ctx=Load()))) .. class:: Attribute(value, attr, ctx) @@ -564,15 +527,12 @@ Expressions .. doctest:: - >>> print(ast.dump(ast.parse('snake.colour'), indent=4)) - Module( - body=[ - Expr( - value=Attribute( - value=Name(id='snake', ctx=Load()), - attr='colour', - ctx=Load()))], - type_ignores=[]) + >>> print(ast.dump(ast.parse('snake.colour', mode='eval'), indent=4)) + Expression( + body=Attribute( + value=Name(id='snake', ctx=Load()), + attr='colour', + ctx=Load())) .. class:: NamedExpr(target, value) @@ -584,14 +544,11 @@ Expressions .. doctest:: - >>> print(ast.dump(ast.parse("(x := 4)"), indent=4)) - Module( - body=[ - Expr( - value=NamedExpr( - target=Name(id='x', ctx=Store()), - value=Constant(value=4, kind=None)))], - type_ignores=[]) + >>> print(ast.dump(ast.parse('(x := 4)', mode='eval'), indent=4)) + Expression( + body=NamedExpr( + target=Name(id='x', ctx=Store()), + value=Constant(value=4, kind=None))) Subscripting @@ -611,16 +568,13 @@ Subscripting .. doctest:: - >>> print(ast.dump(ast.parse('l[1]'), indent=4)) - Module( - body=[ - Expr( - value=Subscript( - value=Name(id='l', ctx=Load()), - slice=Index( - value=Constant(value=1, kind=None)), - ctx=Load()))], - type_ignores=[]) + >>> print(ast.dump(ast.parse('l[1]', mode='eval'), indent=4)) + Expression( + body=Subscript( + value=Name(id='l', ctx=Load()), + slice=Index( + value=Constant(value=1, kind=None)), + ctx=Load())) .. class:: Slice(lower, upper, step) @@ -629,18 +583,15 @@ Subscripting .. doctest:: - >>> print(ast.dump(ast.parse('l[1:2]'), indent=4)) - Module( - body=[ - Expr( - value=Subscript( - value=Name(id='l', ctx=Load()), - slice=Slice( - lower=Constant(value=1, kind=None), - upper=Constant(value=2, kind=None), - step=None), - ctx=Load()))], - type_ignores=[]) + >>> print(ast.dump(ast.parse('l[1:2]', mode='eval'), indent=4)) + Expression( + body=Subscript( + value=Name(id='l', ctx=Load()), + slice=Slice( + lower=Constant(value=1, kind=None), + upper=Constant(value=2, kind=None), + step=None), + ctx=Load())) .. class:: ExtSlice(dims) @@ -650,22 +601,19 @@ Subscripting .. doctest:: - >>> print(ast.dump(ast.parse('l[1:2, 3]'), indent=4)) - Module( - body=[ - Expr( - value=Subscript( - value=Name(id='l', ctx=Load()), - slice=ExtSlice( - dims=[ - Slice( - lower=Constant(value=1, kind=None), - upper=Constant(value=2, kind=None), - step=None), - Index( - value=Constant(value=3, kind=None))]), - ctx=Load()))], - type_ignores=[]) + >>> print(ast.dump(ast.parse('l[1:2, 3]', mode='eval'), indent=4)) + Expression( + body=Subscript( + value=Name(id='l', ctx=Load()), + slice=ExtSlice( + dims=[ + Slice( + lower=Constant(value=1, kind=None), + upper=Constant(value=2, kind=None), + step=None), + Index( + value=Constant(value=3, kind=None))]), + ctx=Load())) Comprehensions @@ -684,51 +632,40 @@ Comprehensions .. doctest:: - >>> print(ast.dump(ast.parse("[x for x in numbers]"), indent=4)) - Module( - body=[ - Expr( - value=ListComp( - elt=Name(id='x', ctx=Load()), - generators=[ - comprehension( - target=Name(id='x', ctx=Store()), - iter=Name(id='numbers', ctx=Load()), - ifs=[], - is_async=0)]))], - type_ignores=[]) - - >>> print(ast.dump(ast.parse("{x: x**2 for x in numbers}"), indent=4)) - Module( - body=[ - Expr( - value=DictComp( - key=Name(id='x', ctx=Load()), - value=BinOp( - left=Name(id='x', ctx=Load()), - op=Pow(), - right=Constant(value=2, kind=None)), - generators=[ - comprehension( - target=Name(id='x', ctx=Store()), - iter=Name(id='numbers', ctx=Load()), - ifs=[], - is_async=0)]))], - type_ignores=[]) - - >>> print(ast.dump(ast.parse("{x for x in numbers}"), indent=4)) - Module( - body=[ - Expr( - value=SetComp( - elt=Name(id='x', ctx=Load()), - generators=[ - comprehension( - target=Name(id='x', ctx=Store()), - iter=Name(id='numbers', ctx=Load()), - ifs=[], - is_async=0)]))], - type_ignores=[]) + >>> print(ast.dump(ast.parse('[x for x in numbers]', mode='eval'), indent=4)) + Expression( + body=ListComp( + elt=Name(id='x', ctx=Load()), + generators=[ + comprehension( + target=Name(id='x', ctx=Store()), + iter=Name(id='numbers', ctx=Load()), + ifs=[], + is_async=0)])) + >>> print(ast.dump(ast.parse('{x: x**2 for x in numbers}', mode='eval'), indent=4)) + Expression( + body=DictComp( + key=Name(id='x', ctx=Load()), + value=BinOp( + left=Name(id='x', ctx=Load()), + op=Pow(), + right=Constant(value=2, kind=None)), + generators=[ + comprehension( + target=Name(id='x', ctx=Store()), + iter=Name(id='numbers', ctx=Load()), + ifs=[], + is_async=0)])) + >>> print(ast.dump(ast.parse('{x for x in numbers}', mode='eval'), indent=4)) + Expression( + body=SetComp( + elt=Name(id='x', ctx=Load()), + generators=[ + comprehension( + target=Name(id='x', ctx=Store()), + iter=Name(id='numbers', ctx=Load()), + ifs=[], + is_async=0)])) .. class:: comprehension(target, iter, ifs, is_async) @@ -743,7 +680,7 @@ Comprehensions .. doctest:: - >>> print(ast.dump(ast.parse("[ord(c) for line in file for c in line]", mode='eval'), + >>> print(ast.dump(ast.parse('[ord(c) for line in file for c in line]', mode='eval'), ... indent=4)) # Multiple comprehensions in one. Expression( body=ListComp( @@ -764,7 +701,7 @@ Comprehensions ifs=[], is_async=0)])) - >>> print(ast.dump(ast.parse("(n**2 for n in it if n>5 if n<10)", mode='eval'), + >>> print(ast.dump(ast.parse('(n**2 for n in it if n>5 if n<10)', mode='eval'), ... indent=4)) # generator comprehension Expression( body=GeneratorExp( @@ -791,35 +728,17 @@ Comprehensions Constant(value=10, kind=None)])], is_async=0)])) - >>> print(ast.dump(ast.parse("async def f():" - ... " return [i async for i in soc]"), + >>> print(ast.dump(ast.parse('[i async for i in soc]', mode='eval'), ... indent=4)) # Async comprehension - Module( - body=[ - AsyncFunctionDef( - name='f', - args=arguments( - posonlyargs=[], - args=[], - vararg=None, - kwonlyargs=[], - kw_defaults=[], - kwarg=None, - defaults=[]), - body=[ - Return( - value=ListComp( - elt=Name(id='i', ctx=Load()), - generators=[ - comprehension( - target=Name(id='i', ctx=Store()), - iter=Name(id='soc', ctx=Load()), - ifs=[], - is_async=1)]))], - decorator_list=[], - returns=None, - type_comment=None)], - type_ignores=[]) + Expression( + body=ListComp( + elt=Name(id='i', ctx=Load()), + generators=[ + comprehension( + target=Name(id='i', ctx=Store()), + iter=Name(id='soc', ctx=Load()), + ifs=[], + is_async=1)])) Statements ^^^^^^^^^^ @@ -838,7 +757,7 @@ Statements .. doctest:: - >>> print(ast.dump(ast.parse("a = b = 1"), indent=4)) # Multiple assignment + >>> print(ast.dump(ast.parse('a = b = 1'), indent=4)) # Multiple assignment Module( body=[ Assign( @@ -849,7 +768,7 @@ Statements type_comment=None)], type_ignores=[]) - >>> print(ast.dump(ast.parse("a,b = c"), indent=4)) # Unpacking + >>> print(ast.dump(ast.parse('a,b = c'), indent=4)) # Unpacking Module( body=[ Assign( @@ -875,7 +794,7 @@ Statements .. doctest:: - >>> print(ast.dump(ast.parse("c: int"), indent=4)) + >>> print(ast.dump(ast.parse('c: int'), indent=4)) Module( body=[ AnnAssign( @@ -885,7 +804,7 @@ Statements simple=1)], type_ignores=[]) - >>> print(ast.dump(ast.parse("(a): int = 1"), indent=4)) # Annotation with parenthesis + >>> print(ast.dump(ast.parse('(a): int = 1'), indent=4)) # Annotation with parenthesis Module( body=[ AnnAssign( @@ -895,7 +814,7 @@ Statements simple=0)], type_ignores=[]) - >>> print(ast.dump(ast.parse("a.b: int"), indent=4)) # Attribute annotation + >>> print(ast.dump(ast.parse('a.b: int'), indent=4)) # Attribute annotation Module( body=[ AnnAssign( @@ -908,7 +827,7 @@ Statements simple=0)], type_ignores=[]) - >>> print(ast.dump(ast.parse("a[1]: int"), indent=4)) # Subscript annotation + >>> print(ast.dump(ast.parse('a[1]: int'), indent=4)) # Subscript annotation Module( body=[ AnnAssign( @@ -935,7 +854,7 @@ Statements .. doctest:: - >>> print(ast.dump(ast.parse("x += 2"), indent=4)) + >>> print(ast.dump(ast.parse('x += 2'), indent=4)) Module( body=[ AugAssign( @@ -953,7 +872,7 @@ Statements .. doctest:: - >>> print(ast.dump(ast.parse("raise x from y"), indent=4)) + >>> print(ast.dump(ast.parse('raise x from y'), indent=4)) Module( body=[ Raise( @@ -969,7 +888,7 @@ Statements .. doctest:: - >>> print(ast.dump(ast.parse("assert x,y"), indent=4)) + >>> print(ast.dump(ast.parse('assert x,y'), indent=4)) Module( body=[ Assert( @@ -985,7 +904,7 @@ Statements .. doctest:: - >>> print(ast.dump(ast.parse("del x,y,z"), indent=4)) + >>> print(ast.dump(ast.parse('del x,y,z'), indent=4)) Module( body=[ Delete( @@ -1002,7 +921,7 @@ Statements .. doctest:: - >>> print(ast.dump(ast.parse("pass"), indent=4)) + >>> print(ast.dump(ast.parse('pass'), indent=4)) Module( body=[ Pass()], @@ -1021,7 +940,7 @@ Imports .. doctest:: - >>> print(ast.dump(ast.parse("import x,y,z"), indent=4)) + >>> print(ast.dump(ast.parse('import x,y,z'), indent=4)) Module( body=[ Import( @@ -1041,7 +960,7 @@ Imports .. doctest:: - >>> print(ast.dump(ast.parse("from y import x,y,z"), indent=4)) + >>> print(ast.dump(ast.parse('from y import x,y,z'), indent=4)) Module( body=[ ImportFrom( @@ -1061,7 +980,7 @@ Imports .. doctest:: - >>> print(ast.dump(ast.parse("from ..foo.bar import a as b, c"), indent=4)) + >>> print(ast.dump(ast.parse('from ..foo.bar import a as b, c'), indent=4)) Module( body=[ ImportFrom( @@ -1368,7 +1287,7 @@ Function and class definitions .. doctest:: - >>> print(ast.dump(ast.parse("lambda x,y: ..."), indent=4)) + >>> print(ast.dump(ast.parse('lambda x,y: ...'), indent=4)) Module( body=[ Expr( @@ -1459,7 +1378,7 @@ Function and class definitions .. doctest:: - >>> print(ast.dump(ast.parse("return 4"), indent=4)) + >>> print(ast.dump(ast.parse('return 4'), indent=4)) Module( body=[ Return( @@ -1475,7 +1394,7 @@ Function and class definitions .. doctest:: - >>> print(ast.dump(ast.parse("yield x"), indent=4)) + >>> print(ast.dump(ast.parse('yield x'), indent=4)) Module( body=[ Expr( @@ -1483,7 +1402,7 @@ Function and class definitions value=Name(id='x', ctx=Load())))], type_ignores=[]) - >>> print(ast.dump(ast.parse("yield from x"), indent=4)) + >>> print(ast.dump(ast.parse('yield from x'), indent=4)) Module( body=[ Expr( @@ -1499,7 +1418,7 @@ Function and class definitions .. doctest:: - >>> print(ast.dump(ast.parse("global x,y,z"), indent=4)) + >>> print(ast.dump(ast.parse('global x,y,z'), indent=4)) Module( body=[ Global( @@ -1509,7 +1428,7 @@ Function and class definitions 'z'])], type_ignores=[]) - >>> print(ast.dump(ast.parse("nonlocal x,y,z"), indent=4)) + >>> print(ast.dump(ast.parse('nonlocal x,y,z'), indent=4)) Module( body=[ Nonlocal( From webhook-mailer at python.org Sat Mar 7 13:23:54 2020 From: webhook-mailer at python.org (Brandt Bucher) Date: Sat, 07 Mar 2020 18:23:54 -0000 Subject: [Python-checkins] bpo-39702: Update the Language Reference (PEP 614) (GH-18802) Message-ID: https://github.com/python/cpython/commit/8f130536926a30237b5297780d61ef4232e88577 commit: 8f130536926a30237b5297780d61ef4232e88577 branch: master author: Brandt Bucher committer: GitHub date: 2020-03-07T10:23:49-08:00 summary: bpo-39702: Update the Language Reference (PEP 614) (GH-18802) files: M Doc/reference/compound_stmts.rst M Doc/whatsnew/3.9.rst diff --git a/Doc/reference/compound_stmts.rst b/Doc/reference/compound_stmts.rst index ac2065b4cff9b..c14e7c79fe14c 100644 --- a/Doc/reference/compound_stmts.rst +++ b/Doc/reference/compound_stmts.rst @@ -507,7 +507,7 @@ A function definition defines a user-defined function object (see section funcdef: [`decorators`] "def" `funcname` "(" [`parameter_list`] ")" : ["->" `expression`] ":" `suite` decorators: `decorator`+ - decorator: "@" `dotted_name` ["(" [`argument_list` [","]] ")"] NEWLINE + decorator: "@" `assignment_expression` NEWLINE dotted_name: `identifier` ("." `identifier`)* parameter_list: `defparameter` ("," `defparameter`)* "," "/" ["," [`parameter_list_no_posonly`]] : | `parameter_list_no_posonly` @@ -550,6 +550,11 @@ is roughly equivalent to :: except that the original function is not temporarily bound to the name ``func``. +.. versionchanged:: 3.9 + Functions may be decorated with any valid :token:`assignment_expression`. + Previously, the grammar was much more restrictive; see :pep:`614` for + details. + .. index:: triple: default; parameter; value single: argument; function definition @@ -717,6 +722,11 @@ is roughly equivalent to :: The evaluation rules for the decorator expressions are the same as for function decorators. The result is then bound to the class name. +.. versionchanged:: 3.9 + Classes may be decorated with any valid :token:`assignment_expression`. + Previously, the grammar was much more restrictive; see :pep:`614` for + details. + **Programmer's note:** Variables defined in the class definition are class attributes; they are shared by instances. Instance attributes can be set in a method with ``self.name = value``. Both class and instance attributes are diff --git a/Doc/whatsnew/3.9.rst b/Doc/whatsnew/3.9.rst index a59de485a95d3..befd6d0d940ab 100644 --- a/Doc/whatsnew/3.9.rst +++ b/Doc/whatsnew/3.9.rst @@ -138,6 +138,10 @@ Other Language Changes There are similar changes for :class:`bytes` and :class:`bytearray` objects. (Contributed by Serhiy Storchaka in :issue:`28029`.) +* Any valid expression can now be used as a :term:`decorator`. Previously, the + grammar was much more restrictive. See :pep:`614` for details. + (Contributed by Brandt Bucher in :issue:`39702`.) + New Modules =========== From webhook-mailer at python.org Sat Mar 7 14:03:14 2020 From: webhook-mailer at python.org (Brandt Bucher) Date: Sat, 07 Mar 2020 19:03:14 -0000 Subject: [Python-checkins] bpo-36144: Update MappingProxyType with PEP 584's operators (#18814) Message-ID: https://github.com/python/cpython/commit/4663f66f3554dd8e2ec130e40f6abb3c6a514775 commit: 4663f66f3554dd8e2ec130e40f6abb3c6a514775 branch: master author: Brandt Bucher committer: GitHub date: 2020-03-07T11:03:09-08:00 summary: bpo-36144: Update MappingProxyType with PEP 584's operators (#18814) We make `|=` raise TypeError, since it would be surprising if `C.__dict__ |= {'x': 0}` silently did nothing, while `C.__dict__.update({'x': 0})` is an error. files: A Misc/NEWS.d/next/Library/2020-02-25-09-28-06.bpo-36144.Rbvvi7.rst M Doc/library/types.rst M Lib/test/test_types.py M Objects/descrobject.c diff --git a/Doc/library/types.rst b/Doc/library/types.rst index 3529c2b0edb89..4cb91c1a90bcf 100644 --- a/Doc/library/types.rst +++ b/Doc/library/types.rst @@ -282,6 +282,11 @@ Standard names are defined for the following types: .. versionadded:: 3.3 + .. versionchanged:: 3.9 + + Updated to support the new union (``|``) operator from :pep:`584`, which + simply delegates to the underlying mapping. + .. describe:: key in proxy Return ``True`` if the underlying mapping has a key *key*, else diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py index 7b45b7a589503..544c91bc36a2a 100644 --- a/Lib/test/test_types.py +++ b/Lib/test/test_types.py @@ -622,8 +622,11 @@ def test_methods(self): self.assertEqual(attrs, { '__contains__', '__getitem__', + '__ior__', '__iter__', '__len__', + '__or__', + '__ror__', 'copy', 'get', 'items', @@ -774,6 +777,22 @@ def test_copy(self): self.assertEqual(view['key1'], 70) self.assertEqual(copy['key1'], 27) + def test_union(self): + mapping = {'a': 0, 'b': 1, 'c': 2} + view = self.mappingproxy(mapping) + with self.assertRaises(TypeError): + view | [('r', 2), ('d', 2)] + with self.assertRaises(TypeError): + [('r', 2), ('d', 2)] | view + with self.assertRaises(TypeError): + view |= [('r', 2), ('d', 2)] + other = {'c': 3, 'p': 0} + self.assertDictEqual(view | other, {'a': 0, 'b': 1, 'c': 3, 'p': 0}) + self.assertDictEqual(other | view, {'c': 2, 'p': 0, 'a': 0, 'b': 1}) + self.assertEqual(view, {'a': 0, 'b': 1, 'c': 2}) + self.assertDictEqual(mapping, {'a': 0, 'b': 1, 'c': 2}) + self.assertDictEqual(other, {'c': 3, 'p': 0}) + class ClassCreationTests(unittest.TestCase): diff --git a/Misc/NEWS.d/next/Library/2020-02-25-09-28-06.bpo-36144.Rbvvi7.rst b/Misc/NEWS.d/next/Library/2020-02-25-09-28-06.bpo-36144.Rbvvi7.rst new file mode 100644 index 0000000000000..da0ff9d9ff894 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-02-25-09-28-06.bpo-36144.Rbvvi7.rst @@ -0,0 +1,2 @@ +:class:`types.MappingProxyType` objects now support the merge (``|``) operator +from :pep:`584`. diff --git a/Objects/descrobject.c b/Objects/descrobject.c index c96945bdb1f31..4ebbb74151a23 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -982,6 +982,30 @@ static PyMappingMethods mappingproxy_as_mapping = { 0, /* mp_ass_subscript */ }; +static PyObject * +mappingproxy_or(PyObject *left, PyObject *right) +{ + if (PyObject_TypeCheck(left, &PyDictProxy_Type)) { + left = ((mappingproxyobject*)left)->mapping; + } + if (PyObject_TypeCheck(right, &PyDictProxy_Type)) { + right = ((mappingproxyobject*)right)->mapping; + } + return PyNumber_Or(left, right); +} + +static PyObject * +mappingproxy_ior(PyObject *self, PyObject *Py_UNUSED(other)) +{ + return PyErr_Format(PyExc_TypeError, + "'|=' is not supported by %s; use '|' instead", Py_TYPE(self)->tp_name); +} + +static PyNumberMethods mappingproxy_as_number = { + .nb_or = mappingproxy_or, + .nb_inplace_or = mappingproxy_ior, +}; + static int mappingproxy_contains(mappingproxyobject *pp, PyObject *key) { @@ -1717,7 +1741,7 @@ PyTypeObject PyDictProxy_Type = { 0, /* tp_setattr */ 0, /* tp_as_async */ (reprfunc)mappingproxy_repr, /* tp_repr */ - 0, /* tp_as_number */ + &mappingproxy_as_number, /* tp_as_number */ &mappingproxy_as_sequence, /* tp_as_sequence */ &mappingproxy_as_mapping, /* tp_as_mapping */ 0, /* tp_hash */ From webhook-mailer at python.org Sat Mar 7 22:44:26 2020 From: webhook-mailer at python.org (Brandt Bucher) Date: Sun, 08 Mar 2020 03:44:26 -0000 Subject: [Python-checkins] bpo-39890: Don't mutate the AST when compiling starred assignments (GH-18833) Message-ID: https://github.com/python/cpython/commit/d5aa2e941ccc44412b95d0e3f0a1789fbcccf403 commit: d5aa2e941ccc44412b95d0e3f0a1789fbcccf403 branch: master author: Brandt Bucher committer: GitHub date: 2020-03-08T03:44:18Z summary: bpo-39890: Don't mutate the AST when compiling starred assignments (GH-18833) files: M Python/compile.c diff --git a/Python/compile.c b/Python/compile.c index f603e3d29e539..f228e16079b28 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -3765,7 +3765,6 @@ assignment_helper(struct compiler *c, asdl_seq *elts) "star-unpacking assignment"); ADDOP_I(c, UNPACK_EX, (i + ((n-i-1) << 8))); seen_star = 1; - asdl_seq_SET(elts, i, elt->v.Starred.value); } else if (elt->kind == Starred_kind) { return compiler_error(c, @@ -3775,7 +3774,10 @@ assignment_helper(struct compiler *c, asdl_seq *elts) if (!seen_star) { ADDOP_I(c, UNPACK_SEQUENCE, n); } - VISIT_SEQ(c, expr, elts); + for (i = 0; i < n; i++) { + expr_ty elt = asdl_seq_GET(elts, i); + VISIT(c, expr, elt->kind != Starred_kind ? elt : elt->v.Starred.value); + } return 1; } From webhook-mailer at python.org Sun Mar 8 06:57:50 2020 From: webhook-mailer at python.org (Victor Stinner) Date: Sun, 08 Mar 2020 10:57:50 -0000 Subject: [Python-checkins] bpo-39877: Fix PyEval_RestoreThread() for daemon threads (GH-18811) Message-ID: https://github.com/python/cpython/commit/eb4e2ae2b8486e8ee4249218b95d94a9f0cc513e commit: eb4e2ae2b8486e8ee4249218b95d94a9f0cc513e branch: master author: Victor Stinner committer: GitHub date: 2020-03-08T11:57:45+01:00 summary: bpo-39877: Fix PyEval_RestoreThread() for daemon threads (GH-18811) * exit_thread_if_finalizing() does now access directly _PyRuntime variable, rather than using tstate->interp->runtime since tstate can be a dangling pointer after Py_Finalize() has been called. * exit_thread_if_finalizing() is now called *before* calling take_gil(). _PyRuntime.finalizing is an atomic variable, we don't need to hold the GIL to access it. * Add ensure_tstate_not_null() function to check that tstate is not NULL at runtime. Check tstate earlier. take_gil() does not longer check if tstate is NULL. Cleanup: * PyEval_RestoreThread() no longer saves/restores errno: it's already done inside take_gil(). * PyEval_AcquireLock(), PyEval_AcquireThread(), PyEval_RestoreThread() and _PyEval_EvalFrameDefault() now check if tstate is valid with the new is_tstate_valid() function which uses _PyMem_IsPtrFreed(). files: A Misc/NEWS.d/next/Core and Builtins/2020-03-06-18-30-00.bpo-39877.bzd1y0.rst M Python/ceval.c M Python/ceval_gil.h M Python/pylifecycle.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-03-06-18-30-00.bpo-39877.bzd1y0.rst b/Misc/NEWS.d/next/Core and Builtins/2020-03-06-18-30-00.bpo-39877.bzd1y0.rst new file mode 100644 index 0000000000000..d545813c1075d --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2020-03-06-18-30-00.bpo-39877.bzd1y0.rst @@ -0,0 +1,5 @@ +Fix :c:func:`PyEval_RestoreThread` random crash at exit with daemon threads. +It now accesses the ``_PyRuntime`` variable directly instead of using +``tstate->interp->runtime``, since ``tstate`` can be a dangling pointer after +:c:func:`Py_Finalize` has been called. Moreover, the daemon thread now exits +before trying to take the GIL. diff --git a/Python/ceval.c b/Python/ceval.c index 04e0824727e6e..42f08c4534c64 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -188,6 +188,25 @@ static size_t opcache_global_misses = 0; #include "pythread.h" #include "ceval_gil.h" +static void +ensure_tstate_not_null(const char *func, PyThreadState *tstate) +{ + if (tstate == NULL) { + _Py_FatalErrorFunc(func, "current thread state is NULL"); + } +} + + +#ifndef NDEBUG +static int is_tstate_valid(PyThreadState *tstate) +{ + assert(!_PyMem_IsPtrFreed(tstate)); + assert(!_PyMem_IsPtrFreed(tstate->interp)); + return 1; +} +#endif + + int PyEval_ThreadsInitialized(void) { @@ -208,6 +227,7 @@ PyEval_InitThreads(void) PyThread_init_thread(); create_gil(gil); PyThreadState *tstate = _PyRuntimeState_GetThreadState(runtime); + ensure_tstate_not_null(__func__, tstate); take_gil(ceval, tstate); struct _pending_calls *pending = &ceval->pending; @@ -235,14 +255,26 @@ _PyEval_FiniThreads(struct _ceval_runtime_state *ceval) } } +/* This function is designed to exit daemon threads immediately rather than + taking the GIL if Py_Finalize() has been called. + + The caller must *not* hold the GIL, since this function does not release + the GIL before exiting the thread. + + When this function is called by a daemon thread after Py_Finalize() has been + called, the GIL does no longer exist. + + tstate must be non-NULL. */ static inline void exit_thread_if_finalizing(PyThreadState *tstate) { - _PyRuntimeState *runtime = tstate->interp->runtime; - /* _Py_Finalizing is protected by the GIL */ + /* bpo-39877: Access _PyRuntime directly rather than using + tstate->interp->runtime to support calls from Python daemon threads. + After Py_Finalize() has been called, tstate can be a dangling pointer: + point to PyThreadState freed memory. */ + _PyRuntimeState *runtime = &_PyRuntime; PyThreadState *finalizing = _PyRuntimeState_GetFinalizing(runtime); if (finalizing != NULL && finalizing != tstate) { - drop_gil(&runtime->ceval, tstate); PyThread_exit_thread(); } } @@ -280,13 +312,14 @@ void PyEval_AcquireLock(void) { _PyRuntimeState *runtime = &_PyRuntime; - struct _ceval_runtime_state *ceval = &runtime->ceval; PyThreadState *tstate = _PyRuntimeState_GetThreadState(runtime); - if (tstate == NULL) { - Py_FatalError("current thread state is NULL"); - } - take_gil(ceval, tstate); + ensure_tstate_not_null(__func__, tstate); + exit_thread_if_finalizing(tstate); + assert(is_tstate_valid(tstate)); + + struct _ceval_runtime_state *ceval = &runtime->ceval; + take_gil(ceval, tstate); } void @@ -304,15 +337,18 @@ PyEval_ReleaseLock(void) void PyEval_AcquireThread(PyThreadState *tstate) { - assert(tstate != NULL); + ensure_tstate_not_null(__func__, tstate); + + exit_thread_if_finalizing(tstate); + assert(is_tstate_valid(tstate)); _PyRuntimeState *runtime = tstate->interp->runtime; struct _ceval_runtime_state *ceval = &runtime->ceval; /* Check someone has called PyEval_InitThreads() to create the lock */ assert(gil_created(&ceval->gil)); + take_gil(ceval, tstate); - exit_thread_if_finalizing(tstate); if (_PyThreadState_Swap(&runtime->gilstate, tstate) != NULL) { Py_FatalError("non-NULL old thread state"); } @@ -344,8 +380,9 @@ _PyEval_ReInitThreads(_PyRuntimeState *runtime) return; } recreate_gil(&ceval->gil); - PyThreadState *current_tstate = _PyRuntimeState_GetThreadState(runtime); - take_gil(ceval, current_tstate); + PyThreadState *tstate = _PyRuntimeState_GetThreadState(runtime); + ensure_tstate_not_null(__func__, tstate); + take_gil(ceval, tstate); struct _pending_calls *pending = &ceval->pending; pending->lock = PyThread_allocate_lock(); @@ -354,7 +391,7 @@ _PyEval_ReInitThreads(_PyRuntimeState *runtime) } /* Destroy all threads except the current one */ - _PyThreadState_DeleteExcept(runtime, current_tstate); + _PyThreadState_DeleteExcept(runtime, tstate); } /* This function is used to signal that async exceptions are waiting to be @@ -383,16 +420,16 @@ PyEval_SaveThread(void) void PyEval_RestoreThread(PyThreadState *tstate) { - assert(tstate != NULL); + ensure_tstate_not_null(__func__, tstate); + + exit_thread_if_finalizing(tstate); + assert(is_tstate_valid(tstate)); _PyRuntimeState *runtime = tstate->interp->runtime; struct _ceval_runtime_state *ceval = &runtime->ceval; assert(gil_created(&ceval->gil)); - int err = errno; take_gil(ceval, tstate); - exit_thread_if_finalizing(tstate); - errno = err; _PyThreadState_Swap(&runtime->gilstate, tstate); } @@ -750,11 +787,14 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) PyObject **fastlocals, **freevars; PyObject *retval = NULL; /* Return value */ _PyRuntimeState * const runtime = &_PyRuntime; - PyThreadState * const tstate = _PyRuntimeState_GetThreadState(runtime); struct _ceval_runtime_state * const ceval = &runtime->ceval; _Py_atomic_int * const eval_breaker = &ceval->eval_breaker; PyCodeObject *co; + PyThreadState * const tstate = _PyRuntimeState_GetThreadState(runtime); + ensure_tstate_not_null(__func__, tstate); + assert(is_tstate_valid(tstate)); + /* when tracing we set things up so that not (instr_lb <= current_bytecode_offset < instr_ub) @@ -1242,11 +1282,11 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) /* Other threads may run now */ - take_gil(ceval, tstate); - /* Check if we should make a quick exit. */ exit_thread_if_finalizing(tstate); + take_gil(ceval, tstate); + if (_PyThreadState_Swap(&runtime->gilstate, tstate) != NULL) { Py_FatalError("orphan tstate"); } diff --git a/Python/ceval_gil.h b/Python/ceval_gil.h index 34d48c990c447..99d576d561517 100644 --- a/Python/ceval_gil.h +++ b/Python/ceval_gil.h @@ -180,15 +180,17 @@ drop_gil(struct _ceval_runtime_state *ceval, PyThreadState *tstate) #endif } +/* Take the GIL. + + The function saves errno at entry and restores its value at exit. + + tstate must be non-NULL. */ static void take_gil(struct _ceval_runtime_state *ceval, PyThreadState *tstate) { - if (tstate == NULL) { - Py_FatalError("take_gil: NULL tstate"); - } + int err = errno; struct _gil_runtime_state *gil = &ceval->gil; - int err = errno; MUTEX_LOCK(gil->mutex); if (!_Py_atomic_load_relaxed(&gil->locked)) { @@ -240,6 +242,7 @@ take_gil(struct _ceval_runtime_state *ceval, PyThreadState *tstate) } MUTEX_UNLOCK(gil->mutex); + errno = err; } diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 9e3b25727945a..eaae5fdbb6692 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -1364,8 +1364,8 @@ Py_FinalizeEx(void) int malloc_stats = interp->config.malloc_stats; #endif - /* Remaining threads (e.g. daemon threads) will automatically exit - after taking the GIL (in PyEval_RestoreThread()). */ + /* Remaining daemon threads will automatically exit + when they attempt to take the GIL (ex: PyEval_RestoreThread()). */ _PyRuntimeState_SetFinalizing(runtime, tstate); runtime->initialized = 0; runtime->core_initialized = 0; From webhook-mailer at python.org Sun Mar 8 08:31:51 2020 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sun, 08 Mar 2020 12:31:51 -0000 Subject: [Python-checkins] bpo-39567: Document audit for os.walk, os.fwalk, Path.glob and Path.rglob. (GH-18499) Message-ID: https://github.com/python/cpython/commit/db283b32e7580741a8b6b7f27f616cc656634750 commit: db283b32e7580741a8b6b7f27f616cc656634750 branch: master author: Serhiy Storchaka committer: GitHub date: 2020-03-08T14:31:47+02:00 summary: bpo-39567: Document audit for os.walk, os.fwalk, Path.glob and Path.rglob. (GH-18499) files: M Doc/library/os.rst M Doc/library/pathlib.rst diff --git a/Doc/library/os.rst b/Doc/library/os.rst index af02a373f33dc..c9d6fb232c0a8 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -3053,6 +3053,8 @@ features: for name in dirs: os.rmdir(os.path.join(root, name)) + .. audit-event:: os.walk top,topdown,onerror,followlinks os.walk + .. versionchanged:: 3.5 This function now calls :func:`os.scandir` instead of :func:`os.listdir`, making it faster by reducing the number of calls to :func:`os.stat`. @@ -3112,6 +3114,8 @@ features: for name in dirs: os.rmdir(name, dir_fd=rootfd) + .. audit-event:: os.fwalk top,topdown,onerror,follow_symlinks,dir_fd os.fwalk + .. availability:: Unix. .. versionadded:: 3.3 diff --git a/Doc/library/pathlib.rst b/Doc/library/pathlib.rst index 7c0ffd50e2c79..004c156e11885 100644 --- a/Doc/library/pathlib.rst +++ b/Doc/library/pathlib.rst @@ -763,6 +763,8 @@ call fails (for example because the path doesn't exist). Using the "``**``" pattern in large directory trees may consume an inordinate amount of time. + .. audit-event:: pathlib.Path.glob self,pattern pathlib.Path.glob + .. method:: Path.group() @@ -1025,6 +1027,8 @@ call fails (for example because the path doesn't exist). PosixPath('setup.py'), PosixPath('test_pathlib.py')] + .. audit-event:: pathlib.Path.rglob self,pattern pathlib.Path.rglob + .. method:: Path.rmdir() From webhook-mailer at python.org Sun Mar 8 12:08:13 2020 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sun, 08 Mar 2020 16:08:13 -0000 Subject: [Python-checkins] [3.7] bpo-39831: Fix a reference leak in PyErr_WarnEx(). (GH-18750). (GH-18765) Message-ID: https://github.com/python/cpython/commit/89fabe51af27a16ae71733334ad94921e3980e28 commit: 89fabe51af27a16ae71733334ad94921e3980e28 branch: 3.7 author: Serhiy Storchaka committer: GitHub date: 2020-03-08T18:07:58+02:00 summary: [3.7] bpo-39831: Fix a reference leak in PyErr_WarnEx(). (GH-18750). (GH-18765) (cherry picked from commit 2d2f85517f8216146a2f888d1ad4d765b3be2339) files: M Python/_warnings.c diff --git a/Python/_warnings.c b/Python/_warnings.c index 1a2035eb250d5..e86a582a01cf4 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -710,7 +710,7 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno, *registry = PyDict_New(); if (*registry == NULL) - goto handle_error; + return 0; rc = PyDict_SetItemString(globals, "__warningregistry__", *registry); if (rc < 0) @@ -802,7 +802,6 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno, dangling reference. */ Py_XDECREF(*registry); Py_XDECREF(*module); - Py_XDECREF(*filename); return 0; } From webhook-mailer at python.org Sun Mar 8 12:54:06 2020 From: webhook-mailer at python.org (Andy Lester) Date: Sun, 08 Mar 2020 16:54:06 -0000 Subject: [Python-checkins] closes bpo-39898: Remove unused arg from append_formattedvalue. (GH-18840) Message-ID: https://github.com/python/cpython/commit/28ca43b7e30e2eaa2997c3becd8b1a837484ae5c commit: 28ca43b7e30e2eaa2997c3becd8b1a837484ae5c branch: master author: Andy Lester committer: GitHub date: 2020-03-08T09:53:59-07:00 summary: closes bpo-39898: Remove unused arg from append_formattedvalue. (GH-18840) files: M Python/ast_unparse.c diff --git a/Python/ast_unparse.c b/Python/ast_unparse.c index 1a7cd236aafa1..bd9c1396c07e5 100644 --- a/Python/ast_unparse.c +++ b/Python/ast_unparse.c @@ -15,7 +15,7 @@ append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, int level); static int append_joinedstr(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec); static int -append_formattedvalue(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec); +append_formattedvalue(_PyUnicodeWriter *writer, expr_ty e); static int append_ast_slice(_PyUnicodeWriter *writer, slice_ty slice); @@ -583,7 +583,7 @@ append_fstring_element(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec) case JoinedStr_kind: return append_joinedstr(writer, e, is_format_spec); case FormattedValue_kind: - return append_formattedvalue(writer, e, is_format_spec); + return append_formattedvalue(writer, e); default: PyErr_SetString(PyExc_SystemError, "unknown expression kind inside f-string"); @@ -640,7 +640,7 @@ append_joinedstr(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec) } static int -append_formattedvalue(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec) +append_formattedvalue(_PyUnicodeWriter *writer, expr_ty e) { const char *conversion; const char *outer_brace = "{"; @@ -870,7 +870,7 @@ append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, int level) case JoinedStr_kind: return append_joinedstr(writer, e, false); case FormattedValue_kind: - return append_formattedvalue(writer, e, false); + return append_formattedvalue(writer, e); /* The following exprs can be assignment targets. */ case Attribute_kind: return append_ast_attribute(writer, e); From webhook-mailer at python.org Sun Mar 8 13:52:24 2020 From: webhook-mailer at python.org (Julin S) Date: Sun, 08 Mar 2020 17:52:24 -0000 Subject: [Python-checkins] fix typo: add space (GH-18853) Message-ID: https://github.com/python/cpython/commit/c580981ba01c4d9f721dbdd88208ba37704e0217 commit: c580981ba01c4d9f721dbdd88208ba37704e0217 branch: master author: Julin S <48789920+ju-sh at users.noreply.github.com> committer: GitHub date: 2020-03-08T10:52:15-07:00 summary: fix typo: add space (GH-18853) Fix typo in cmdline.rst Add space between the `-m` option and the module name (`timeit`). files: M Doc/using/cmdline.rst diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst index 2206e5065be1f..9b30c288211ed 100644 --- a/Doc/using/cmdline.rst +++ b/Doc/using/cmdline.rst @@ -109,8 +109,8 @@ source. Many standard library modules contain code that is invoked on their execution as a script. An example is the :mod:`timeit` module:: - python -mtimeit -s 'setup here' 'benchmarked code here' - python -mtimeit -h # for details + python -m timeit -s 'setup here' 'benchmarked code here' + python -m timeit -h # for details .. audit-event:: cpython.run_module module-name cmdoption-m From webhook-mailer at python.org Sun Mar 8 13:57:18 2020 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sun, 08 Mar 2020 17:57:18 -0000 Subject: [Python-checkins] fix typo: add space (GH-18853) Message-ID: https://github.com/python/cpython/commit/516e6735b4e1dd94fc0c8eca35c19ca534c39a38 commit: 516e6735b4e1dd94fc0c8eca35c19ca534c39a38 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2020-03-08T10:57:11-07:00 summary: fix typo: add space (GH-18853) Fix typo in cmdline.rst Add space between the `-m` option and the module name (`timeit`). (cherry picked from commit c580981ba01c4d9f721dbdd88208ba37704e0217) Co-authored-by: Julin S <48789920+ju-sh at users.noreply.github.com> files: M Doc/using/cmdline.rst diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst index 6a1d7aa00d082..be92642e2fa31 100644 --- a/Doc/using/cmdline.rst +++ b/Doc/using/cmdline.rst @@ -108,8 +108,8 @@ source. Many standard library modules contain code that is invoked on their execution as a script. An example is the :mod:`timeit` module:: - python -mtimeit -s 'setup here' 'benchmarked code here' - python -mtimeit -h # for details + python -m timeit -s 'setup here' 'benchmarked code here' + python -m timeit -h # for details .. seealso:: :func:`runpy.run_module` From webhook-mailer at python.org Sun Mar 8 13:58:24 2020 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sun, 08 Mar 2020 17:58:24 -0000 Subject: [Python-checkins] fix typo: add space (GH-18853) Message-ID: https://github.com/python/cpython/commit/765117dc161d7bd8317e9df7fb3f3b5caca281c2 commit: 765117dc161d7bd8317e9df7fb3f3b5caca281c2 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2020-03-08T10:58:19-07:00 summary: fix typo: add space (GH-18853) Fix typo in cmdline.rst Add space between the `-m` option and the module name (`timeit`). (cherry picked from commit c580981ba01c4d9f721dbdd88208ba37704e0217) Co-authored-by: Julin S <48789920+ju-sh at users.noreply.github.com> files: M Doc/using/cmdline.rst diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst index 53206c7b54649..d3f04004efc75 100644 --- a/Doc/using/cmdline.rst +++ b/Doc/using/cmdline.rst @@ -109,8 +109,8 @@ source. Many standard library modules contain code that is invoked on their execution as a script. An example is the :mod:`timeit` module:: - python -mtimeit -s 'setup here' 'benchmarked code here' - python -mtimeit -h # for details + python -m timeit -s 'setup here' 'benchmarked code here' + python -m timeit -h # for details .. audit-event:: cpython.run_module module-name cmdoption-m From webhook-mailer at python.org Sun Mar 8 14:32:48 2020 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Sun, 08 Mar 2020 18:32:48 -0000 Subject: [Python-checkins] bpo-39852: IDLE 'Go to line' deletes selection, updates status (GH-18801) Message-ID: https://github.com/python/cpython/commit/2522db11df102be3baf25ce9e816ebe8ffdb7fcc commit: 2522db11df102be3baf25ce9e816ebe8ffdb7fcc branch: master author: Terry Jan Reedy committer: GitHub date: 2020-03-08T14:32:42-04:00 summary: bpo-39852: IDLE 'Go to line' deletes selection, updates status (GH-18801) It appears standard that moving the text insert cursor away from a selection clears the selection. Clearing prevents accidental deletion of a possibly off-screen bit of text. The update is for Ln and Col on the status bar. files: A Misc/NEWS.d/next/IDLE/2020-03-06-01-55-14.bpo-39852.QjA1qF.rst M Doc/library/idle.rst M Lib/idlelib/NEWS.txt M Lib/idlelib/editor.py M Lib/idlelib/help.html diff --git a/Doc/library/idle.rst b/Doc/library/idle.rst index fd6e309567de3..b1192e7bb4655 100644 --- a/Doc/library/idle.rst +++ b/Doc/library/idle.rst @@ -142,7 +142,9 @@ Replace... Open a search-and-replace dialog. Go to Line - Move cursor to the line number requested and make that line visible. + Move the cursor to the beginning of the line requested and make that + line visible. A request past the end of the file goes to the end. + Clear any selection and update the line and column status. Show Completions Open a scrollable list allowing selection of keywords and attributes. See diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index 0651b3d68dc8b..1e6cd4580ea7b 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -3,6 +3,9 @@ Released on 2020-10-05? ====================================== +bpo-39852: Edit "Go to line" now clears any selection, preventing +accidental deletion. It also updates Ln and Col on the status bar. + bpo-39781: Selecting code context lines no longer causes a jump. bpo-39663: Add tests for pyparse find_good_parse_start(). diff --git a/Lib/idlelib/editor.py b/Lib/idlelib/editor.py index 04c786dc5234c..5b81b52f9196c 100644 --- a/Lib/idlelib/editor.py +++ b/Lib/idlelib/editor.py @@ -678,8 +678,11 @@ def goto_line_event(self, event): if lineno <= 0: text.bell() return "break" - text.mark_set("insert", "%d.0" % lineno) + + text.tag_remove("sel", "1.0", "end") + text.mark_set("insert", f'{lineno}.0') text.see("insert") + self.set_line_and_column() return "break" def open_module(self): diff --git a/Lib/idlelib/help.html b/Lib/idlelib/help.html index 0b2bdd2e174cc..424c6b50f339e 100644 --- a/Lib/idlelib/help.html +++ b/Lib/idlelib/help.html @@ -4,7 +4,7 @@ - IDLE — Python 3.9.0a1 documentation + IDLE — Python 3.9.0a4 documentation @@ -17,7 +17,7 @@ @@ -71,7 +71,7 @@

Navigation

  • - 3.9.0a1 Documentation » + 3.9.0a4 Documentation »
  • @@ -197,7 +197,9 @@

    Edit menu (Shell and Editor)Completions in the Editing and navigation section below.

    @@ -635,17 +637,20 @@

    Startup failure~/.idlerc/ (~ is one?s home directory). If there is a problem, an error message should be displayed. Leaving aside random disk glitches, this can -be prevented by never editing the files by hand, using the configuration -dialog, under Options, instead Options. Once it happens, the solution may -be to delete one or more of the configuration files.

    +be prevented by never editing the files by hand. Instead, use the +configuration dialog, under Options. Once there is an error in a user +configuration file, the best solution may be to delete it and start over +with the settings dialog.

    If IDLE quits with no message, and it was not started from a console, try -starting from a console (python -m idlelib) and see if a message appears.

    +starting it from a console or terminal (python -m idlelib) and see if +this results in an error message.

    Running user code?

    @@ -930,7 +935,7 @@

    Navigation

  • - 3.9.0a1 Documentation » + 3.9.0a4 Documentation »
  • @@ -953,7 +958,7 @@

    Navigation

    Running user code?

    @@ -930,7 +935,7 @@

    Navigation

  • - 3.9.0a1 Documentation » + 3.9.0a4 Documentation »
  • @@ -953,7 +958,7 @@

    Navigation

    Running user code?

    @@ -930,7 +935,7 @@

    Navigation

  • - 3.9.0a1 Documentation » + 3.9.0a4 Documentation »
  • @@ -953,7 +958,7 @@

    Navigation