From webhook-mailer at python.org Tue May 1 00:06:03 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 01 May 2018 04:06:03 -0000 Subject: [Python-checkins] bpo-31908: Fix output of cover files for trace module command-line tool. (GH-4205) Message-ID: https://github.com/python/cpython/commit/e4eeb6eff12947a55df5eabee36e537cadefbbac commit: e4eeb6eff12947a55df5eabee36e537cadefbbac branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-04-30T21:06:00-07:00 summary: bpo-31908: Fix output of cover files for trace module command-line tool. (GH-4205) Previously emitted cover files only when --missing option was used. (cherry picked from commit 47ab15470d72367694d7758004067313ae022f0e) Co-authored-by: Michael Selik files: A Misc/NEWS.d/next/Library/2017-10-31.bpo-31908.g4xh8x.rst M Lib/test/test_trace.py M Lib/trace.py diff --git a/Lib/test/test_trace.py b/Lib/test/test_trace.py index e04ca01c4299..55a8bcea3e54 100644 --- a/Lib/test/test_trace.py +++ b/Lib/test/test_trace.py @@ -2,6 +2,7 @@ import sys from test.support import TESTFN, rmtree, unlink, captured_stdout from test.support.script_helper import assert_python_ok, assert_python_failure +import textwrap import unittest import trace @@ -365,6 +366,46 @@ def test_ignored(self): # Matched before. self.assertTrue(ignore.names(jn('bar', 'baz.py'), 'baz')) +# Created for Issue 31908 -- CLI utility not writing cover files +class TestCoverageCommandLineOutput(unittest.TestCase): + + codefile = 'tmp.py' + coverfile = 'tmp.cover' + + def setUp(self): + with open(self.codefile, 'w') as f: + f.write(textwrap.dedent('''\ + x = 42 + if []: + print('unreachable') + ''')) + + def tearDown(self): + unlink(self.codefile) + unlink(self.coverfile) + + def test_cover_files_written_no_highlight(self): + argv = '-m trace --count'.split() + [self.codefile] + status, stdout, stderr = assert_python_ok(*argv) + self.assertTrue(os.path.exists(self.coverfile)) + with open(self.coverfile) as f: + self.assertEqual(f.read(), + " 1: x = 42\n" + " 1: if []:\n" + " print('unreachable')\n" + ) + + def test_cover_files_written_with_highlight(self): + argv = '-m trace --count --missing'.split() + [self.codefile] + status, stdout, stderr = assert_python_ok(*argv) + self.assertTrue(os.path.exists(self.coverfile)) + with open(self.coverfile) as f: + self.assertEqual(f.read(), textwrap.dedent('''\ + 1: x = 42 + 1: if []: + >>>>>> print('unreachable') + ''')) + class TestCommandLine(unittest.TestCase): def test_failures(self): diff --git a/Lib/trace.py b/Lib/trace.py index ade76166bdd2..16c3494689dd 100755 --- a/Lib/trace.py +++ b/Lib/trace.py @@ -73,9 +73,6 @@ def _unsettrace(): PRAGMA_NOCOVER = "#pragma NO COVER" -# Simple rx to find lines with no code. -rx_blank = re.compile(r'^\s*(#.*)?$') - class _Ignore: def __init__(self, modules=None, dirs=None): self._mods = set() if not modules else set(modules) @@ -278,16 +275,15 @@ def write_results(self, show_missing=True, summary=False, coverdir=None): lnotab = _find_executable_linenos(filename) else: lnotab = {} - if lnotab: - source = linecache.getlines(filename) - coverpath = os.path.join(dir, modulename + ".cover") - with open(filename, 'rb') as fp: - encoding, _ = tokenize.detect_encoding(fp.readline) - n_hits, n_lines = self.write_results_file(coverpath, source, - lnotab, count, encoding) - if summary and n_lines: - percent = int(100 * n_hits / n_lines) - sums[modulename] = n_lines, percent, modulename, filename + source = linecache.getlines(filename) + coverpath = os.path.join(dir, modulename + ".cover") + with open(filename, 'rb') as fp: + encoding, _ = tokenize.detect_encoding(fp.readline) + n_hits, n_lines = self.write_results_file(coverpath, source, + lnotab, count, encoding) + if summary and n_lines: + percent = int(100 * n_hits / n_lines) + sums[modulename] = n_lines, percent, modulename, filename if summary and sums: @@ -306,6 +302,7 @@ def write_results(self, show_missing=True, summary=False, coverdir=None): def write_results_file(self, path, lines, lnotab, lines_hit, encoding=None): """Return a coverage results file in path.""" + # ``lnotab`` is a dict of executable lines, or a line number "table" try: outfile = open(path, "w", encoding=encoding) @@ -324,17 +321,13 @@ def write_results_file(self, path, lines, lnotab, lines_hit, encoding=None): outfile.write("%5d: " % lines_hit[lineno]) n_hits += 1 n_lines += 1 - elif rx_blank.match(line): - outfile.write(" ") - else: - # lines preceded by no marks weren't hit - # Highlight them if so indicated, unless the line contains + elif lineno in lnotab and not PRAGMA_NOCOVER in line: + # Highlight never-executed lines, unless the line contains # #pragma: NO COVER - if lineno in lnotab and not PRAGMA_NOCOVER in line: - outfile.write(">>>>>> ") - n_lines += 1 - else: - outfile.write(" ") + outfile.write(">>>>>> ") + n_lines += 1 + else: + outfile.write(" ") outfile.write(line.expandtabs(8)) return n_hits, n_lines diff --git a/Misc/NEWS.d/next/Library/2017-10-31.bpo-31908.g4xh8x.rst b/Misc/NEWS.d/next/Library/2017-10-31.bpo-31908.g4xh8x.rst new file mode 100644 index 000000000000..700bc690764f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-10-31.bpo-31908.g4xh8x.rst @@ -0,0 +1,3 @@ +Fix output of cover files for ``trace`` module command-line tool. +Previously emitted cover files only when ``--missing`` option was used. +Patch by Michael Selik. \ No newline at end of file From webhook-mailer at python.org Tue May 1 01:03:32 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 01 May 2018 05:03:32 -0000 Subject: [Python-checkins] bpo-31908: Fix output of cover files for trace module command-line tool. (GH-4205) Message-ID: https://github.com/python/cpython/commit/a607f8b9982ac95bb59f8f61e0a50fc5ae29dc14 commit: a607f8b9982ac95bb59f8f61e0a50fc5ae29dc14 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-04-30T22:03:29-07:00 summary: bpo-31908: Fix output of cover files for trace module command-line tool. (GH-4205) Previously emitted cover files only when --missing option was used. (cherry picked from commit 47ab15470d72367694d7758004067313ae022f0e) Co-authored-by: Michael Selik files: A Misc/NEWS.d/next/Library/2017-10-31.bpo-31908.g4xh8x.rst M Lib/test/test_trace.py M Lib/trace.py diff --git a/Lib/test/test_trace.py b/Lib/test/test_trace.py index e04ca01c4299..55a8bcea3e54 100644 --- a/Lib/test/test_trace.py +++ b/Lib/test/test_trace.py @@ -2,6 +2,7 @@ import sys from test.support import TESTFN, rmtree, unlink, captured_stdout from test.support.script_helper import assert_python_ok, assert_python_failure +import textwrap import unittest import trace @@ -365,6 +366,46 @@ def test_ignored(self): # Matched before. self.assertTrue(ignore.names(jn('bar', 'baz.py'), 'baz')) +# Created for Issue 31908 -- CLI utility not writing cover files +class TestCoverageCommandLineOutput(unittest.TestCase): + + codefile = 'tmp.py' + coverfile = 'tmp.cover' + + def setUp(self): + with open(self.codefile, 'w') as f: + f.write(textwrap.dedent('''\ + x = 42 + if []: + print('unreachable') + ''')) + + def tearDown(self): + unlink(self.codefile) + unlink(self.coverfile) + + def test_cover_files_written_no_highlight(self): + argv = '-m trace --count'.split() + [self.codefile] + status, stdout, stderr = assert_python_ok(*argv) + self.assertTrue(os.path.exists(self.coverfile)) + with open(self.coverfile) as f: + self.assertEqual(f.read(), + " 1: x = 42\n" + " 1: if []:\n" + " print('unreachable')\n" + ) + + def test_cover_files_written_with_highlight(self): + argv = '-m trace --count --missing'.split() + [self.codefile] + status, stdout, stderr = assert_python_ok(*argv) + self.assertTrue(os.path.exists(self.coverfile)) + with open(self.coverfile) as f: + self.assertEqual(f.read(), textwrap.dedent('''\ + 1: x = 42 + 1: if []: + >>>>>> print('unreachable') + ''')) + class TestCommandLine(unittest.TestCase): def test_failures(self): diff --git a/Lib/trace.py b/Lib/trace.py index 9ba9486bd024..d171577e3991 100755 --- a/Lib/trace.py +++ b/Lib/trace.py @@ -79,9 +79,6 @@ def _unsettrace(): PRAGMA_NOCOVER = "#pragma NO COVER" -# Simple rx to find lines with no code. -rx_blank = re.compile(r'^\s*(#.*)?$') - class _Ignore: def __init__(self, modules=None, dirs=None): self._mods = set() if not modules else set(modules) @@ -284,16 +281,15 @@ def write_results(self, show_missing=True, summary=False, coverdir=None): lnotab = _find_executable_linenos(filename) else: lnotab = {} - if lnotab: - source = linecache.getlines(filename) - coverpath = os.path.join(dir, modulename + ".cover") - with open(filename, 'rb') as fp: - encoding, _ = tokenize.detect_encoding(fp.readline) - n_hits, n_lines = self.write_results_file(coverpath, source, - lnotab, count, encoding) - if summary and n_lines: - percent = int(100 * n_hits / n_lines) - sums[modulename] = n_lines, percent, modulename, filename + source = linecache.getlines(filename) + coverpath = os.path.join(dir, modulename + ".cover") + with open(filename, 'rb') as fp: + encoding, _ = tokenize.detect_encoding(fp.readline) + n_hits, n_lines = self.write_results_file(coverpath, source, + lnotab, count, encoding) + if summary and n_lines: + percent = int(100 * n_hits / n_lines) + sums[modulename] = n_lines, percent, modulename, filename if summary and sums: @@ -312,6 +308,7 @@ def write_results(self, show_missing=True, summary=False, coverdir=None): def write_results_file(self, path, lines, lnotab, lines_hit, encoding=None): """Return a coverage results file in path.""" + # ``lnotab`` is a dict of executable lines, or a line number "table" try: outfile = open(path, "w", encoding=encoding) @@ -330,17 +327,13 @@ def write_results_file(self, path, lines, lnotab, lines_hit, encoding=None): outfile.write("%5d: " % lines_hit[lineno]) n_hits += 1 n_lines += 1 - elif rx_blank.match(line): - outfile.write(" ") - else: - # lines preceded by no marks weren't hit - # Highlight them if so indicated, unless the line contains + elif lineno in lnotab and not PRAGMA_NOCOVER in line: + # Highlight never-executed lines, unless the line contains # #pragma: NO COVER - if lineno in lnotab and not PRAGMA_NOCOVER in line: - outfile.write(">>>>>> ") - n_lines += 1 - else: - outfile.write(" ") + outfile.write(">>>>>> ") + n_lines += 1 + else: + outfile.write(" ") outfile.write(line.expandtabs(8)) return n_hits, n_lines diff --git a/Misc/NEWS.d/next/Library/2017-10-31.bpo-31908.g4xh8x.rst b/Misc/NEWS.d/next/Library/2017-10-31.bpo-31908.g4xh8x.rst new file mode 100644 index 000000000000..700bc690764f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-10-31.bpo-31908.g4xh8x.rst @@ -0,0 +1,3 @@ +Fix output of cover files for ``trace`` module command-line tool. +Previously emitted cover files only when ``--missing`` option was used. +Patch by Michael Selik. \ No newline at end of file From solipsis at pitrou.net Tue May 1 05:18:51 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Tue, 01 May 2018 09:18:51 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=6 Message-ID: <20180501091851.1.86CD088A051D1AC8@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_fork leaked [2, 0, 0] memory blocks, sum=2 test_multiprocessing_forkserver leaked [-1, 2, -1] memory blocks, sum=0 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogL8_3jG', '--timeout', '7200'] From webhook-mailer at python.org Tue May 1 05:46:46 2018 From: webhook-mailer at python.org (Julien Palard) Date: Tue, 01 May 2018 09:46:46 -0000 Subject: [Python-checkins] Add What's New for Korean documentation translation. (GH-6645) Message-ID: https://github.com/python/cpython/commit/335a602666d3b94352c194fe002430dda3c0ab2b commit: 335a602666d3b94352c194fe002430dda3c0ab2b branch: master author: Julien Palard committer: GitHub date: 2018-05-01T11:46:43+02:00 summary: Add What's New for Korean documentation translation. (GH-6645) files: M Doc/whatsnew/3.7.rst diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 3ce20fafd376..408fed4572fa 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -1354,7 +1354,7 @@ PEP 545: Python Documentation Translations ------------------------------------------ :pep:`545` describes the process to translate Python documentation, -and two translations have been added: +and three translations have been added: - Japanese: https://docs.python.org/ja/ and associated GitHub repository: https://github.com/python/python-docs-ja @@ -1362,5 +1362,8 @@ and two translations have been added: - French: https://docs.python.org/fr/ and associated GitHub repository: https://github.com/python/python-docs-fr +- Korean: https://docs.python.org/ko/ and associated GitHub + repository: https://github.com/python/python-docs-ko + (Contributed by Julien Palard, Inada Naoki, and Victor Stinner in :issue:`26546`.) From webhook-mailer at python.org Tue May 1 05:47:20 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 01 May 2018 09:47:20 -0000 Subject: [Python-checkins] bpo-33378: Add Korean to the language switcher. (GH-6627) Message-ID: https://github.com/python/cpython/commit/dc5c92fcb2aafd7f133f9f6986d8d05ac6e5160f commit: dc5c92fcb2aafd7f133f9f6986d8d05ac6e5160f branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-05-01T02:47:17-07:00 summary: bpo-33378: Add Korean to the language switcher. (GH-6627) (cherry picked from commit 577948329976985ea9bef23d9a6c3dd7108211bf) Co-authored-by: Dong-hee Na files: A Misc/NEWS.d/next/Documentation/2018-04-29-04-02-18.bpo-33378.-anAHN.rst M Doc/tools/static/switchers.js diff --git a/Doc/tools/static/switchers.js b/Doc/tools/static/switchers.js index 8e0c5ea0092a..3dea08e523bf 100644 --- a/Doc/tools/static/switchers.js +++ b/Doc/tools/static/switchers.js @@ -21,6 +21,7 @@ 'en': 'English', 'fr': 'French', 'ja': 'Japanese', + 'ko': 'Korean', }; function build_version_select(current_version, current_release) { diff --git a/Misc/NEWS.d/next/Documentation/2018-04-29-04-02-18.bpo-33378.-anAHN.rst b/Misc/NEWS.d/next/Documentation/2018-04-29-04-02-18.bpo-33378.-anAHN.rst new file mode 100644 index 000000000000..43214d10b7c5 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2018-04-29-04-02-18.bpo-33378.-anAHN.rst @@ -0,0 +1 @@ +Add Korean language switcher for https://docs.python.org/3/ From webhook-mailer at python.org Tue May 1 06:02:29 2018 From: webhook-mailer at python.org (Julien Palard) Date: Tue, 01 May 2018 10:02:29 -0000 Subject: [Python-checkins] bpo-20709: os.utime(path_to_directory): wrong documentation for Windows. (GH-5469) Message-ID: https://github.com/python/cpython/commit/7508a54c77e85235e07e344cf9440e5b4695e9cc commit: 7508a54c77e85235e07e344cf9440e5b4695e9cc branch: master author: St?phane Wirtel committer: Julien Palard date: 2018-05-01T12:02:26+02:00 summary: bpo-20709: os.utime(path_to_directory): wrong documentation for Windows. (GH-5469) Remove the paragraph where we explain that os.utime() does not support a directory as path under Windows. Patch by Jan-Philip Gehrcke Co-authored-by: Jan-Philip Gehrcke files: A Misc/NEWS.d/next/Documentation/2018-02-01-10-57-24.bpo-20709.1flcnc.rst M Doc/library/os.rst diff --git a/Doc/library/os.rst b/Doc/library/os.rst index 2f3b31edd5d7..2e81459a2504 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -2768,14 +2768,12 @@ features: It is an error to specify tuples for both *times* and *ns*. - Whether a directory can be given for *path* - depends on whether the operating system implements directories as files - (for example, Windows does not). Note that the exact times you set here may - not be returned by a subsequent :func:`~os.stat` call, depending on the - resolution with which your operating system records access and modification - times; see :func:`~os.stat`. The best way to preserve exact times is to - use the *st_atime_ns* and *st_mtime_ns* fields from the :func:`os.stat` - result object with the *ns* parameter to `utime`. + Note that the exact times you set here may not be returned by a subsequent + :func:`~os.stat` call, depending on the resolution with which your operating + system records access and modification times; see :func:`~os.stat`. The best + way to preserve exact times is to use the *st_atime_ns* and *st_mtime_ns* + fields from the :func:`os.stat` result object with the *ns* parameter to + `utime`. This function can support :ref:`specifying a file descriptor `, :ref:`paths relative to directory descriptors ` and :ref:`not diff --git a/Misc/NEWS.d/next/Documentation/2018-02-01-10-57-24.bpo-20709.1flcnc.rst b/Misc/NEWS.d/next/Documentation/2018-02-01-10-57-24.bpo-20709.1flcnc.rst new file mode 100644 index 000000000000..b14c0f54eb3b --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2018-02-01-10-57-24.bpo-20709.1flcnc.rst @@ -0,0 +1,2 @@ +Remove the paragraph where we explain that os.utime() does not support a +directory as path under Windows. Patch by Jan-Philip Gehrcke From webhook-mailer at python.org Tue May 1 09:45:07 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Tue, 01 May 2018 13:45:07 -0000 Subject: [Python-checkins] bpo-20104: Improve error handling and fix a reference leak in os.posix_spawn(). (#6332) Message-ID: https://github.com/python/cpython/commit/ef347535f289baad22c0601e12a36b2dcd155c3a commit: ef347535f289baad22c0601e12a36b2dcd155c3a branch: master author: Serhiy Storchaka committer: GitHub date: 2018-05-01T16:45:04+03:00 summary: bpo-20104: Improve error handling and fix a reference leak in os.posix_spawn(). (#6332) files: A Misc/NEWS.d/next/Library/2018-04-01-19-21-04.bpo-20104.-AKcGa.rst M Doc/library/os.rst M Lib/test/test_posix.py M Modules/clinic/posixmodule.c.h M Modules/posixmodule.c diff --git a/Doc/library/os.rst b/Doc/library/os.rst index 2e81459a2504..4b4e93106692 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -3365,25 +3365,41 @@ written in Python, such as a mail server's external command delivery program. .. function:: posix_spawn(path, argv, env, file_actions=None) - Wraps the posix_spawn() C library API for use from Python. + Wraps the :c:func:`posix_spawn` C library API for use from Python. - Most users should use :class:`subprocess.run` instead of posix_spawn. + Most users should use :func:`subprocess.run` instead of :func:`posix_spawn`. The *path*, *args*, and *env* arguments are similar to :func:`execve`. The *file_actions* argument may be a sequence of tuples describing actions to take on specific file descriptors in the child process between the C - library implementation's fork and exec steps. The first item in each tuple - must be one of the three type indicator listed below describing the - remaining tuple elements: + library implementation's :c:func:`fork` and :c:func:`exec` steps. + The first item in each tuple must be one of the three type indicator + listed below describing the remaining tuple elements: - (os.POSIX_SPAWN_OPEN, fd, path, open flags, mode) - (os.POSIX_SPAWN_CLOSE, fd) - (os.POSIX_SPAWN_DUP2, fd, new_fd) + .. data:: POSIX_SPAWN_OPEN - These tuples correspond to the C library posix_spawn_file_actions_addopen, - posix_spawn_file_actions_addclose, and posix_spawn_file_actions_adddup2 API - calls used to prepare for the posix_spawn call itself. + (``os.POSIX_SPAWN_OPEN``, *fd*, *path*, *flags*, *mode*) + + Performs ``os.dup2(os.open(path, flags, mode), fd)``. + + .. data:: POSIX_SPAWN_CLOSE + + (``os.POSIX_SPAWN_CLOSE``, *fd*) + + Performs ``os.close(fd)``. + + .. data:: POSIX_SPAWN_DUP2 + + (``os.POSIX_SPAWN_DUP2``, *fd*, *new_fd*) + + Performs ``os.dup2(fd, new_fd)``. + + These tuples correspond to the C library + :c:func:`posix_spawn_file_actions_addopen`, + :c:func:`posix_spawn_file_actions_addclose`, and + :c:func:`posix_spawn_file_actions_adddup2` API calls used to prepare + for the :c:func:`posix_spawn` call itself. .. versionadded:: 3.7 diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py index 8ada0e3ab3c7..b94da3f45a2c 100644 --- a/Lib/test/test_posix.py +++ b/Lib/test/test_posix.py @@ -177,22 +177,6 @@ def test_fexecve(self): os.close(fp) - @unittest.skipUnless(hasattr(os, 'posix_spawn'), "test needs os.posix_spawn") - def test_posix_spawn(self): - pid = posix.posix_spawn(sys.executable, [sys.executable, "-c", "pass"], os.environ,[]) - self.assertEqual(os.waitpid(pid,0),(pid,0)) - - - @unittest.skipUnless(hasattr(os, 'posix_spawn'), "test needs os.posix_spawn") - def test_posix_spawn_file_actions(self): - file_actions = [] - file_actions.append((0,3,os.path.realpath(__file__),0,0)) - file_actions.append((os.POSIX_SPAWN_CLOSE,2)) - file_actions.append((os.POSIX_SPAWN_DUP2,1,4)) - pid = posix.posix_spawn(sys.executable, [sys.executable, "-c", "pass"], os.environ, file_actions) - self.assertEqual(os.waitpid(pid,0),(pid,0)) - - @unittest.skipUnless(hasattr(posix, 'waitid'), "test needs posix.waitid()") @unittest.skipUnless(hasattr(os, 'fork'), "test needs os.fork()") def test_waitid(self): @@ -1437,9 +1421,168 @@ def test_setgroups(self): posix.setgroups(groups) self.assertListEqual(groups, posix.getgroups()) + + at unittest.skipUnless(hasattr(os, 'posix_spawn'), "test needs os.posix_spawn") +class TestPosixSpawn(unittest.TestCase): + def test_returns_pid(self): + pidfile = support.TESTFN + self.addCleanup(support.unlink, pidfile) + script = f"""if 1: + import os + with open({pidfile!r}, "w") as pidfile: + pidfile.write(str(os.getpid())) + """ + pid = posix.posix_spawn(sys.executable, + [sys.executable, '-c', script], + os.environ) + self.assertEqual(os.waitpid(pid, 0), (pid, 0)) + with open(pidfile) as f: + self.assertEqual(f.read(), str(pid)) + + def test_no_such_executable(self): + no_such_executable = 'no_such_executable' + try: + pid = posix.posix_spawn(no_such_executable, + [no_such_executable], + os.environ) + except FileNotFoundError as exc: + self.assertEqual(exc.filename, no_such_executable) + else: + pid2, status = os.waitpid(pid, 0) + self.assertEqual(pid2, pid) + self.assertNotEqual(status, 0) + + def test_specify_environment(self): + envfile = support.TESTFN + self.addCleanup(support.unlink, envfile) + script = f"""if 1: + import os + with open({envfile!r}, "w") as envfile: + envfile.write(os.environ['foo']) + """ + pid = posix.posix_spawn(sys.executable, + [sys.executable, '-c', script], + {'foo': 'bar'}) + self.assertEqual(os.waitpid(pid, 0), (pid, 0)) + with open(envfile) as f: + self.assertEqual(f.read(), 'bar') + + def test_empty_file_actions(self): + pid = posix.posix_spawn( + sys.executable, + [sys.executable, '-c', 'pass'], + os.environ, + [] + ) + self.assertEqual(os.waitpid(pid, 0), (pid, 0)) + + def test_multiple_file_actions(self): + file_actions = [ + (os.POSIX_SPAWN_OPEN, 3, os.path.realpath(__file__), os.O_RDONLY, 0), + (os.POSIX_SPAWN_CLOSE, 0), + (os.POSIX_SPAWN_DUP2, 1, 4), + ] + pid = posix.posix_spawn(sys.executable, + [sys.executable, "-c", "pass"], + os.environ, file_actions) + self.assertEqual(os.waitpid(pid, 0), (pid, 0)) + + def test_bad_file_actions(self): + with self.assertRaises(TypeError): + posix.posix_spawn(sys.executable, + [sys.executable, "-c", "pass"], + os.environ, [None]) + with self.assertRaises(TypeError): + posix.posix_spawn(sys.executable, + [sys.executable, "-c", "pass"], + os.environ, [()]) + with self.assertRaises(TypeError): + posix.posix_spawn(sys.executable, + [sys.executable, "-c", "pass"], + os.environ, [(None,)]) + with self.assertRaises(TypeError): + posix.posix_spawn(sys.executable, + [sys.executable, "-c", "pass"], + os.environ, [(12345,)]) + with self.assertRaises(TypeError): + posix.posix_spawn(sys.executable, + [sys.executable, "-c", "pass"], + os.environ, [(os.POSIX_SPAWN_CLOSE,)]) + with self.assertRaises(TypeError): + posix.posix_spawn(sys.executable, + [sys.executable, "-c", "pass"], + os.environ, [(os.POSIX_SPAWN_CLOSE, 1, 2)]) + with self.assertRaises(TypeError): + posix.posix_spawn(sys.executable, + [sys.executable, "-c", "pass"], + os.environ, [(os.POSIX_SPAWN_CLOSE, None)]) + with self.assertRaises(ValueError): + posix.posix_spawn(sys.executable, + [sys.executable, "-c", "pass"], + os.environ, + [(os.POSIX_SPAWN_OPEN, 3, __file__ + '\0', + os.O_RDONLY, 0)]) + + def test_open_file(self): + outfile = support.TESTFN + self.addCleanup(support.unlink, outfile) + script = """if 1: + import sys + sys.stdout.write("hello") + """ + file_actions = [ + (os.POSIX_SPAWN_OPEN, 1, outfile, + os.O_WRONLY | os.O_CREAT | os.O_TRUNC, + stat.S_IRUSR | stat.S_IWUSR), + ] + pid = posix.posix_spawn(sys.executable, + [sys.executable, '-c', script], + os.environ, file_actions) + self.assertEqual(os.waitpid(pid, 0), (pid, 0)) + with open(outfile) as f: + self.assertEqual(f.read(), 'hello') + + def test_close_file(self): + closefile = support.TESTFN + self.addCleanup(support.unlink, closefile) + script = f"""if 1: + import os + try: + os.fstat(0) + except OSError as e: + with open({closefile!r}, 'w') as closefile: + closefile.write('is closed %d' % e.errno) + """ + pid = posix.posix_spawn(sys.executable, + [sys.executable, '-c', script], + os.environ, + [(os.POSIX_SPAWN_CLOSE, 0),]) + self.assertEqual(os.waitpid(pid, 0), (pid, 0)) + with open(closefile) as f: + self.assertEqual(f.read(), 'is closed %d' % errno.EBADF) + + def test_dup2(self): + dupfile = support.TESTFN + self.addCleanup(support.unlink, dupfile) + script = """if 1: + import sys + sys.stdout.write("hello") + """ + with open(dupfile, "wb") as childfile: + file_actions = [ + (os.POSIX_SPAWN_DUP2, childfile.fileno(), 1), + ] + pid = posix.posix_spawn(sys.executable, + [sys.executable, '-c', script], + os.environ, file_actions) + self.assertEqual(os.waitpid(pid, 0), (pid, 0)) + with open(dupfile) as f: + self.assertEqual(f.read(), 'hello') + + def test_main(): try: - support.run_unittest(PosixTester, PosixGroupsTester) + support.run_unittest(PosixTester, PosixGroupsTester, TestPosixSpawn) finally: support.reap_children() diff --git a/Misc/NEWS.d/next/Library/2018-04-01-19-21-04.bpo-20104.-AKcGa.rst b/Misc/NEWS.d/next/Library/2018-04-01-19-21-04.bpo-20104.-AKcGa.rst new file mode 100644 index 000000000000..150401dc7412 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-04-01-19-21-04.bpo-20104.-AKcGa.rst @@ -0,0 +1 @@ +Improved error handling and fixed a reference leak in :func:`os.posix_spawn()`. diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h index 4054389d15f3..e4bbd082450b 100644 --- a/Modules/clinic/posixmodule.c.h +++ b/Modules/clinic/posixmodule.c.h @@ -1742,7 +1742,7 @@ PyDoc_STRVAR(os_posix_spawn__doc__, " env\n" " Dictionary of strings mapping to strings.\n" " file_actions\n" -" FileActions object."); +" A sequence of file action tuples."); #define OS_POSIX_SPAWN_METHODDEF \ {"posix_spawn", (PyCFunction)os_posix_spawn, METH_FASTCALL, os_posix_spawn__doc__}, @@ -6589,4 +6589,4 @@ os_getrandom(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject #ifndef OS_GETRANDOM_METHODDEF #define OS_GETRANDOM_METHODDEF #endif /* !defined(OS_GETRANDOM_METHODDEF) */ -/*[clinic end generated code: output=fc603214822bdda6 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=8d3d9dddf254c3c2 input=a9049054013a1b77]*/ diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index e6721032f211..4ac6e7658999 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -5114,6 +5114,111 @@ enum posix_spawn_file_actions_identifier { POSIX_SPAWN_DUP2 }; +static int +parse_file_actions(PyObject *file_actions, + posix_spawn_file_actions_t *file_actionsp) +{ + PyObject *seq; + PyObject *file_action = NULL; + PyObject *tag_obj; + + seq = PySequence_Fast(file_actions, + "file_actions must be a sequence or None"); + if (seq == NULL) { + return -1; + } + + errno = posix_spawn_file_actions_init(file_actionsp); + if (errno) { + posix_error(); + Py_DECREF(seq); + return -1; + } + + for (int i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) { + file_action = PySequence_Fast_GET_ITEM(seq, i); + Py_INCREF(file_action); + if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) { + PyErr_SetString(PyExc_TypeError, + "Each file_actions element must be a non-empty tuple"); + goto fail; + } + long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0)); + if (tag == -1 && PyErr_Occurred()) { + goto fail; + } + + /* Populate the file_actions object */ + switch (tag) { + case POSIX_SPAWN_OPEN: { + int fd, oflag; + PyObject *path; + unsigned long mode; + if (!PyArg_ParseTuple(file_action, "OiO&ik" + ";A open file_action tuple must have 5 elements", + &tag_obj, &fd, PyUnicode_FSConverter, &path, + &oflag, &mode)) + { + goto fail; + } + errno = posix_spawn_file_actions_addopen(file_actionsp, + fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode); + Py_DECREF(path); /* addopen copied it. */ + if (errno) { + posix_error(); + goto fail; + } + break; + } + case POSIX_SPAWN_CLOSE: { + int fd; + if (!PyArg_ParseTuple(file_action, "Oi" + ";A close file_action tuple must have 2 elements", + &tag_obj, &fd)) + { + goto fail; + } + errno = posix_spawn_file_actions_addclose(file_actionsp, fd); + if (errno) { + posix_error(); + goto fail; + } + break; + } + case POSIX_SPAWN_DUP2: { + int fd1, fd2; + if (!PyArg_ParseTuple(file_action, "Oii" + ";A dup2 file_action tuple must have 3 elements", + &tag_obj, &fd1, &fd2)) + { + goto fail; + } + errno = posix_spawn_file_actions_adddup2(file_actionsp, + fd1, fd2); + if (errno) { + posix_error(); + goto fail; + } + break; + } + default: { + PyErr_SetString(PyExc_TypeError, + "Unknown file_actions identifier"); + goto fail; + } + } + Py_DECREF(file_action); + } + Py_DECREF(seq); + return 0; + +fail: + Py_DECREF(seq); + Py_DECREF(file_action); + (void)posix_spawn_file_actions_destroy(file_actionsp); + return -1; +} + /*[clinic input] os.posix_spawn @@ -5124,7 +5229,7 @@ os.posix_spawn env: object Dictionary of strings mapping to strings. file_actions: object = None - FileActions object. + A sequence of file action tuples. / Execute the program specified by path in a new process. @@ -5133,22 +5238,22 @@ Execute the program specified by path in a new process. static PyObject * os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env, PyObject *file_actions) -/*[clinic end generated code: output=d023521f541c709c input=0ec9f1cfdc890be5]*/ +/*[clinic end generated code: output=d023521f541c709c input=a3db1021d33230dc]*/ { EXECV_CHAR **argvlist = NULL; EXECV_CHAR **envlist = NULL; - posix_spawn_file_actions_t _file_actions; + posix_spawn_file_actions_t file_actions_buf; posix_spawn_file_actions_t *file_actionsp = NULL; Py_ssize_t argc, envc; - PyObject* result = NULL; - PyObject* seq = NULL; - + PyObject *result = NULL; + pid_t pid; + int err_code; /* posix_spawn has three arguments: (path, argv, env), where - argv is a list or tuple of strings and env is a dictionary + argv is a list or tuple of strings and env is a dictionary like posix.environ. */ - if (!PySequence_Check(argv)) { + if (!PyList_Check(argv) && !PyTuple_Check(argv)) { PyErr_SetString(PyExc_TypeError, "posix_spawn: argv must be a tuple or list"); goto exit; @@ -5180,139 +5285,35 @@ os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv, goto exit; } - pid_t pid; - if (file_actions != NULL && file_actions != Py_None) { - if(posix_spawn_file_actions_init(&_file_actions) != 0){ - PyErr_SetString(PyExc_OSError, - "Error initializing file actions"); - goto exit; - } - - file_actionsp = &_file_actions; - - seq = PySequence_Fast(file_actions, "file_actions must be a sequence"); - if(seq == NULL) { + if (file_actions != Py_None) { + if (parse_file_actions(file_actions, &file_actions_buf)) { goto exit; } - PyObject* file_actions_obj; - PyObject* mode_obj; - - for (int i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) { - file_actions_obj = PySequence_Fast_GET_ITEM(seq, i); - - if(!PySequence_Check(file_actions_obj) | !PySequence_Size(file_actions_obj)) { - PyErr_SetString(PyExc_TypeError,"Each file_action element must be a non empty sequence"); - goto exit; - } - - - mode_obj = PySequence_Fast_GET_ITEM(file_actions_obj, 0); - int mode = PyLong_AsLong(mode_obj); - - /* Populate the file_actions object */ - - switch(mode) { - - case POSIX_SPAWN_OPEN: - if(PySequence_Size(file_actions_obj) != 5) { - PyErr_SetString(PyExc_TypeError,"A open file_action object must have 5 elements"); - goto exit; - } - - long open_fd = PyLong_AsLong(PySequence_GetItem(file_actions_obj, 1)); - if(PyErr_Occurred()) { - goto exit; - } - const char* open_path = PyUnicode_AsUTF8(PySequence_GetItem(file_actions_obj, 2)); - if(open_path == NULL) { - goto exit; - } - long open_oflag = PyLong_AsLong(PySequence_GetItem(file_actions_obj, 3)); - if(PyErr_Occurred()) { - goto exit; - } - long open_mode = PyLong_AsLong(PySequence_GetItem(file_actions_obj, 4)); - if(PyErr_Occurred()) { - goto exit; - } - if(posix_spawn_file_actions_addopen(file_actionsp, open_fd, open_path, open_oflag, open_mode)) { - PyErr_SetString(PyExc_OSError,"Failed to add open file action"); - goto exit; - } - - break; - - case POSIX_SPAWN_CLOSE: - if(PySequence_Size(file_actions_obj) != 2){ - PyErr_SetString(PyExc_TypeError,"A close file_action object must have 2 elements"); - goto exit; - } - - long close_fd = PyLong_AsLong(PySequence_GetItem(file_actions_obj, 1)); - if(PyErr_Occurred()) { - goto exit; - } - if(posix_spawn_file_actions_addclose(file_actionsp, close_fd)) { - PyErr_SetString(PyExc_OSError,"Failed to add close file action"); - goto exit; - } - break; - - case POSIX_SPAWN_DUP2: - if(PySequence_Size(file_actions_obj) != 3){ - PyErr_SetString(PyExc_TypeError,"A dup2 file_action object must have 3 elements"); - goto exit; - } - - long fd1 = PyLong_AsLong(PySequence_GetItem(file_actions_obj, 1)); - if(PyErr_Occurred()) { - goto exit; - } - long fd2 = PyLong_AsLong(PySequence_GetItem(file_actions_obj, 2)); - if(PyErr_Occurred()) { - goto exit; - } - if(posix_spawn_file_actions_adddup2(file_actionsp, fd1, fd2)) { - PyErr_SetString(PyExc_OSError,"Failed to add dup2 file action"); - goto exit; - } - break; - - default: - PyErr_SetString(PyExc_TypeError,"Unknown file_actions identifier"); - goto exit; - } - } + file_actionsp = &file_actions_buf; } _Py_BEGIN_SUPPRESS_IPH - int err_code = posix_spawn(&pid, path->narrow, file_actionsp, NULL, argvlist, envlist); + err_code = posix_spawn(&pid, path->narrow, + file_actionsp, NULL, argvlist, envlist); _Py_END_SUPPRESS_IPH - if(err_code) { - PyErr_SetString(PyExc_OSError,"posix_spawn call failed"); + if (err_code) { + errno = err_code; + PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object); goto exit; } result = PyLong_FromPid(pid); exit: - - Py_XDECREF(seq); - - if(file_actionsp) { - posix_spawn_file_actions_destroy(file_actionsp); + if (file_actionsp) { + (void)posix_spawn_file_actions_destroy(file_actionsp); } - if (envlist) { free_string_array(envlist, envc); } - if (argvlist) { free_string_array(argvlist, argc); } - return result; - - } #endif /* HAVE_POSIX_SPAWN */ From webhook-mailer at python.org Tue May 1 10:18:48 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 01 May 2018 14:18:48 -0000 Subject: [Python-checkins] bpo-20104: Improve error handling and fix a reference leak in os.posix_spawn(). (GH-6332) Message-ID: https://github.com/python/cpython/commit/77fa7835da0cb49d30ac5d4c32bf6eb71eae0742 commit: 77fa7835da0cb49d30ac5d4c32bf6eb71eae0742 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-05-01T07:18:44-07:00 summary: bpo-20104: Improve error handling and fix a reference leak in os.posix_spawn(). (GH-6332) (cherry picked from commit ef347535f289baad22c0601e12a36b2dcd155c3a) Co-authored-by: Serhiy Storchaka files: A Misc/NEWS.d/next/Library/2018-04-01-19-21-04.bpo-20104.-AKcGa.rst M Doc/library/os.rst M Lib/test/test_posix.py M Modules/clinic/posixmodule.c.h M Modules/posixmodule.c diff --git a/Doc/library/os.rst b/Doc/library/os.rst index 2f3b31edd5d7..5699d50a2034 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -3367,25 +3367,41 @@ written in Python, such as a mail server's external command delivery program. .. function:: posix_spawn(path, argv, env, file_actions=None) - Wraps the posix_spawn() C library API for use from Python. + Wraps the :c:func:`posix_spawn` C library API for use from Python. - Most users should use :class:`subprocess.run` instead of posix_spawn. + Most users should use :func:`subprocess.run` instead of :func:`posix_spawn`. The *path*, *args*, and *env* arguments are similar to :func:`execve`. The *file_actions* argument may be a sequence of tuples describing actions to take on specific file descriptors in the child process between the C - library implementation's fork and exec steps. The first item in each tuple - must be one of the three type indicator listed below describing the - remaining tuple elements: + library implementation's :c:func:`fork` and :c:func:`exec` steps. + The first item in each tuple must be one of the three type indicator + listed below describing the remaining tuple elements: - (os.POSIX_SPAWN_OPEN, fd, path, open flags, mode) - (os.POSIX_SPAWN_CLOSE, fd) - (os.POSIX_SPAWN_DUP2, fd, new_fd) + .. data:: POSIX_SPAWN_OPEN - These tuples correspond to the C library posix_spawn_file_actions_addopen, - posix_spawn_file_actions_addclose, and posix_spawn_file_actions_adddup2 API - calls used to prepare for the posix_spawn call itself. + (``os.POSIX_SPAWN_OPEN``, *fd*, *path*, *flags*, *mode*) + + Performs ``os.dup2(os.open(path, flags, mode), fd)``. + + .. data:: POSIX_SPAWN_CLOSE + + (``os.POSIX_SPAWN_CLOSE``, *fd*) + + Performs ``os.close(fd)``. + + .. data:: POSIX_SPAWN_DUP2 + + (``os.POSIX_SPAWN_DUP2``, *fd*, *new_fd*) + + Performs ``os.dup2(fd, new_fd)``. + + These tuples correspond to the C library + :c:func:`posix_spawn_file_actions_addopen`, + :c:func:`posix_spawn_file_actions_addclose`, and + :c:func:`posix_spawn_file_actions_adddup2` API calls used to prepare + for the :c:func:`posix_spawn` call itself. .. versionadded:: 3.7 diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py index 8ada0e3ab3c7..b94da3f45a2c 100644 --- a/Lib/test/test_posix.py +++ b/Lib/test/test_posix.py @@ -177,22 +177,6 @@ def test_fexecve(self): os.close(fp) - @unittest.skipUnless(hasattr(os, 'posix_spawn'), "test needs os.posix_spawn") - def test_posix_spawn(self): - pid = posix.posix_spawn(sys.executable, [sys.executable, "-c", "pass"], os.environ,[]) - self.assertEqual(os.waitpid(pid,0),(pid,0)) - - - @unittest.skipUnless(hasattr(os, 'posix_spawn'), "test needs os.posix_spawn") - def test_posix_spawn_file_actions(self): - file_actions = [] - file_actions.append((0,3,os.path.realpath(__file__),0,0)) - file_actions.append((os.POSIX_SPAWN_CLOSE,2)) - file_actions.append((os.POSIX_SPAWN_DUP2,1,4)) - pid = posix.posix_spawn(sys.executable, [sys.executable, "-c", "pass"], os.environ, file_actions) - self.assertEqual(os.waitpid(pid,0),(pid,0)) - - @unittest.skipUnless(hasattr(posix, 'waitid'), "test needs posix.waitid()") @unittest.skipUnless(hasattr(os, 'fork'), "test needs os.fork()") def test_waitid(self): @@ -1437,9 +1421,168 @@ def test_setgroups(self): posix.setgroups(groups) self.assertListEqual(groups, posix.getgroups()) + + at unittest.skipUnless(hasattr(os, 'posix_spawn'), "test needs os.posix_spawn") +class TestPosixSpawn(unittest.TestCase): + def test_returns_pid(self): + pidfile = support.TESTFN + self.addCleanup(support.unlink, pidfile) + script = f"""if 1: + import os + with open({pidfile!r}, "w") as pidfile: + pidfile.write(str(os.getpid())) + """ + pid = posix.posix_spawn(sys.executable, + [sys.executable, '-c', script], + os.environ) + self.assertEqual(os.waitpid(pid, 0), (pid, 0)) + with open(pidfile) as f: + self.assertEqual(f.read(), str(pid)) + + def test_no_such_executable(self): + no_such_executable = 'no_such_executable' + try: + pid = posix.posix_spawn(no_such_executable, + [no_such_executable], + os.environ) + except FileNotFoundError as exc: + self.assertEqual(exc.filename, no_such_executable) + else: + pid2, status = os.waitpid(pid, 0) + self.assertEqual(pid2, pid) + self.assertNotEqual(status, 0) + + def test_specify_environment(self): + envfile = support.TESTFN + self.addCleanup(support.unlink, envfile) + script = f"""if 1: + import os + with open({envfile!r}, "w") as envfile: + envfile.write(os.environ['foo']) + """ + pid = posix.posix_spawn(sys.executable, + [sys.executable, '-c', script], + {'foo': 'bar'}) + self.assertEqual(os.waitpid(pid, 0), (pid, 0)) + with open(envfile) as f: + self.assertEqual(f.read(), 'bar') + + def test_empty_file_actions(self): + pid = posix.posix_spawn( + sys.executable, + [sys.executable, '-c', 'pass'], + os.environ, + [] + ) + self.assertEqual(os.waitpid(pid, 0), (pid, 0)) + + def test_multiple_file_actions(self): + file_actions = [ + (os.POSIX_SPAWN_OPEN, 3, os.path.realpath(__file__), os.O_RDONLY, 0), + (os.POSIX_SPAWN_CLOSE, 0), + (os.POSIX_SPAWN_DUP2, 1, 4), + ] + pid = posix.posix_spawn(sys.executable, + [sys.executable, "-c", "pass"], + os.environ, file_actions) + self.assertEqual(os.waitpid(pid, 0), (pid, 0)) + + def test_bad_file_actions(self): + with self.assertRaises(TypeError): + posix.posix_spawn(sys.executable, + [sys.executable, "-c", "pass"], + os.environ, [None]) + with self.assertRaises(TypeError): + posix.posix_spawn(sys.executable, + [sys.executable, "-c", "pass"], + os.environ, [()]) + with self.assertRaises(TypeError): + posix.posix_spawn(sys.executable, + [sys.executable, "-c", "pass"], + os.environ, [(None,)]) + with self.assertRaises(TypeError): + posix.posix_spawn(sys.executable, + [sys.executable, "-c", "pass"], + os.environ, [(12345,)]) + with self.assertRaises(TypeError): + posix.posix_spawn(sys.executable, + [sys.executable, "-c", "pass"], + os.environ, [(os.POSIX_SPAWN_CLOSE,)]) + with self.assertRaises(TypeError): + posix.posix_spawn(sys.executable, + [sys.executable, "-c", "pass"], + os.environ, [(os.POSIX_SPAWN_CLOSE, 1, 2)]) + with self.assertRaises(TypeError): + posix.posix_spawn(sys.executable, + [sys.executable, "-c", "pass"], + os.environ, [(os.POSIX_SPAWN_CLOSE, None)]) + with self.assertRaises(ValueError): + posix.posix_spawn(sys.executable, + [sys.executable, "-c", "pass"], + os.environ, + [(os.POSIX_SPAWN_OPEN, 3, __file__ + '\0', + os.O_RDONLY, 0)]) + + def test_open_file(self): + outfile = support.TESTFN + self.addCleanup(support.unlink, outfile) + script = """if 1: + import sys + sys.stdout.write("hello") + """ + file_actions = [ + (os.POSIX_SPAWN_OPEN, 1, outfile, + os.O_WRONLY | os.O_CREAT | os.O_TRUNC, + stat.S_IRUSR | stat.S_IWUSR), + ] + pid = posix.posix_spawn(sys.executable, + [sys.executable, '-c', script], + os.environ, file_actions) + self.assertEqual(os.waitpid(pid, 0), (pid, 0)) + with open(outfile) as f: + self.assertEqual(f.read(), 'hello') + + def test_close_file(self): + closefile = support.TESTFN + self.addCleanup(support.unlink, closefile) + script = f"""if 1: + import os + try: + os.fstat(0) + except OSError as e: + with open({closefile!r}, 'w') as closefile: + closefile.write('is closed %d' % e.errno) + """ + pid = posix.posix_spawn(sys.executable, + [sys.executable, '-c', script], + os.environ, + [(os.POSIX_SPAWN_CLOSE, 0),]) + self.assertEqual(os.waitpid(pid, 0), (pid, 0)) + with open(closefile) as f: + self.assertEqual(f.read(), 'is closed %d' % errno.EBADF) + + def test_dup2(self): + dupfile = support.TESTFN + self.addCleanup(support.unlink, dupfile) + script = """if 1: + import sys + sys.stdout.write("hello") + """ + with open(dupfile, "wb") as childfile: + file_actions = [ + (os.POSIX_SPAWN_DUP2, childfile.fileno(), 1), + ] + pid = posix.posix_spawn(sys.executable, + [sys.executable, '-c', script], + os.environ, file_actions) + self.assertEqual(os.waitpid(pid, 0), (pid, 0)) + with open(dupfile) as f: + self.assertEqual(f.read(), 'hello') + + def test_main(): try: - support.run_unittest(PosixTester, PosixGroupsTester) + support.run_unittest(PosixTester, PosixGroupsTester, TestPosixSpawn) finally: support.reap_children() diff --git a/Misc/NEWS.d/next/Library/2018-04-01-19-21-04.bpo-20104.-AKcGa.rst b/Misc/NEWS.d/next/Library/2018-04-01-19-21-04.bpo-20104.-AKcGa.rst new file mode 100644 index 000000000000..150401dc7412 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-04-01-19-21-04.bpo-20104.-AKcGa.rst @@ -0,0 +1 @@ +Improved error handling and fixed a reference leak in :func:`os.posix_spawn()`. diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h index 4054389d15f3..e4bbd082450b 100644 --- a/Modules/clinic/posixmodule.c.h +++ b/Modules/clinic/posixmodule.c.h @@ -1742,7 +1742,7 @@ PyDoc_STRVAR(os_posix_spawn__doc__, " env\n" " Dictionary of strings mapping to strings.\n" " file_actions\n" -" FileActions object."); +" A sequence of file action tuples."); #define OS_POSIX_SPAWN_METHODDEF \ {"posix_spawn", (PyCFunction)os_posix_spawn, METH_FASTCALL, os_posix_spawn__doc__}, @@ -6589,4 +6589,4 @@ os_getrandom(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject #ifndef OS_GETRANDOM_METHODDEF #define OS_GETRANDOM_METHODDEF #endif /* !defined(OS_GETRANDOM_METHODDEF) */ -/*[clinic end generated code: output=fc603214822bdda6 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=8d3d9dddf254c3c2 input=a9049054013a1b77]*/ diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index e8964ce33901..a81580db0a3b 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -5114,6 +5114,111 @@ enum posix_spawn_file_actions_identifier { POSIX_SPAWN_DUP2 }; +static int +parse_file_actions(PyObject *file_actions, + posix_spawn_file_actions_t *file_actionsp) +{ + PyObject *seq; + PyObject *file_action = NULL; + PyObject *tag_obj; + + seq = PySequence_Fast(file_actions, + "file_actions must be a sequence or None"); + if (seq == NULL) { + return -1; + } + + errno = posix_spawn_file_actions_init(file_actionsp); + if (errno) { + posix_error(); + Py_DECREF(seq); + return -1; + } + + for (int i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) { + file_action = PySequence_Fast_GET_ITEM(seq, i); + Py_INCREF(file_action); + if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) { + PyErr_SetString(PyExc_TypeError, + "Each file_actions element must be a non-empty tuple"); + goto fail; + } + long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0)); + if (tag == -1 && PyErr_Occurred()) { + goto fail; + } + + /* Populate the file_actions object */ + switch (tag) { + case POSIX_SPAWN_OPEN: { + int fd, oflag; + PyObject *path; + unsigned long mode; + if (!PyArg_ParseTuple(file_action, "OiO&ik" + ";A open file_action tuple must have 5 elements", + &tag_obj, &fd, PyUnicode_FSConverter, &path, + &oflag, &mode)) + { + goto fail; + } + errno = posix_spawn_file_actions_addopen(file_actionsp, + fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode); + Py_DECREF(path); /* addopen copied it. */ + if (errno) { + posix_error(); + goto fail; + } + break; + } + case POSIX_SPAWN_CLOSE: { + int fd; + if (!PyArg_ParseTuple(file_action, "Oi" + ";A close file_action tuple must have 2 elements", + &tag_obj, &fd)) + { + goto fail; + } + errno = posix_spawn_file_actions_addclose(file_actionsp, fd); + if (errno) { + posix_error(); + goto fail; + } + break; + } + case POSIX_SPAWN_DUP2: { + int fd1, fd2; + if (!PyArg_ParseTuple(file_action, "Oii" + ";A dup2 file_action tuple must have 3 elements", + &tag_obj, &fd1, &fd2)) + { + goto fail; + } + errno = posix_spawn_file_actions_adddup2(file_actionsp, + fd1, fd2); + if (errno) { + posix_error(); + goto fail; + } + break; + } + default: { + PyErr_SetString(PyExc_TypeError, + "Unknown file_actions identifier"); + goto fail; + } + } + Py_DECREF(file_action); + } + Py_DECREF(seq); + return 0; + +fail: + Py_DECREF(seq); + Py_DECREF(file_action); + (void)posix_spawn_file_actions_destroy(file_actionsp); + return -1; +} + /*[clinic input] os.posix_spawn @@ -5124,7 +5229,7 @@ os.posix_spawn env: object Dictionary of strings mapping to strings. file_actions: object = None - FileActions object. + A sequence of file action tuples. / Execute the program specified by path in a new process. @@ -5133,22 +5238,22 @@ Execute the program specified by path in a new process. static PyObject * os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env, PyObject *file_actions) -/*[clinic end generated code: output=d023521f541c709c input=0ec9f1cfdc890be5]*/ +/*[clinic end generated code: output=d023521f541c709c input=a3db1021d33230dc]*/ { EXECV_CHAR **argvlist = NULL; EXECV_CHAR **envlist = NULL; - posix_spawn_file_actions_t _file_actions; + posix_spawn_file_actions_t file_actions_buf; posix_spawn_file_actions_t *file_actionsp = NULL; Py_ssize_t argc, envc; - PyObject* result = NULL; - PyObject* seq = NULL; - + PyObject *result = NULL; + pid_t pid; + int err_code; /* posix_spawn has three arguments: (path, argv, env), where - argv is a list or tuple of strings and env is a dictionary + argv is a list or tuple of strings and env is a dictionary like posix.environ. */ - if (!PySequence_Check(argv)) { + if (!PyList_Check(argv) && !PyTuple_Check(argv)) { PyErr_SetString(PyExc_TypeError, "posix_spawn: argv must be a tuple or list"); goto exit; @@ -5180,139 +5285,35 @@ os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv, goto exit; } - pid_t pid; - if (file_actions != NULL && file_actions != Py_None) { - if(posix_spawn_file_actions_init(&_file_actions) != 0){ - PyErr_SetString(PyExc_OSError, - "Error initializing file actions"); - goto exit; - } - - file_actionsp = &_file_actions; - - seq = PySequence_Fast(file_actions, "file_actions must be a sequence"); - if(seq == NULL) { + if (file_actions != Py_None) { + if (parse_file_actions(file_actions, &file_actions_buf)) { goto exit; } - PyObject* file_actions_obj; - PyObject* mode_obj; - - for (int i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) { - file_actions_obj = PySequence_Fast_GET_ITEM(seq, i); - - if(!PySequence_Check(file_actions_obj) | !PySequence_Size(file_actions_obj)) { - PyErr_SetString(PyExc_TypeError,"Each file_action element must be a non empty sequence"); - goto exit; - } - - - mode_obj = PySequence_Fast_GET_ITEM(file_actions_obj, 0); - int mode = PyLong_AsLong(mode_obj); - - /* Populate the file_actions object */ - - switch(mode) { - - case POSIX_SPAWN_OPEN: - if(PySequence_Size(file_actions_obj) != 5) { - PyErr_SetString(PyExc_TypeError,"A open file_action object must have 5 elements"); - goto exit; - } - - long open_fd = PyLong_AsLong(PySequence_GetItem(file_actions_obj, 1)); - if(PyErr_Occurred()) { - goto exit; - } - const char* open_path = PyUnicode_AsUTF8(PySequence_GetItem(file_actions_obj, 2)); - if(open_path == NULL) { - goto exit; - } - long open_oflag = PyLong_AsLong(PySequence_GetItem(file_actions_obj, 3)); - if(PyErr_Occurred()) { - goto exit; - } - long open_mode = PyLong_AsLong(PySequence_GetItem(file_actions_obj, 4)); - if(PyErr_Occurred()) { - goto exit; - } - if(posix_spawn_file_actions_addopen(file_actionsp, open_fd, open_path, open_oflag, open_mode)) { - PyErr_SetString(PyExc_OSError,"Failed to add open file action"); - goto exit; - } - - break; - - case POSIX_SPAWN_CLOSE: - if(PySequence_Size(file_actions_obj) != 2){ - PyErr_SetString(PyExc_TypeError,"A close file_action object must have 2 elements"); - goto exit; - } - - long close_fd = PyLong_AsLong(PySequence_GetItem(file_actions_obj, 1)); - if(PyErr_Occurred()) { - goto exit; - } - if(posix_spawn_file_actions_addclose(file_actionsp, close_fd)) { - PyErr_SetString(PyExc_OSError,"Failed to add close file action"); - goto exit; - } - break; - - case POSIX_SPAWN_DUP2: - if(PySequence_Size(file_actions_obj) != 3){ - PyErr_SetString(PyExc_TypeError,"A dup2 file_action object must have 3 elements"); - goto exit; - } - - long fd1 = PyLong_AsLong(PySequence_GetItem(file_actions_obj, 1)); - if(PyErr_Occurred()) { - goto exit; - } - long fd2 = PyLong_AsLong(PySequence_GetItem(file_actions_obj, 2)); - if(PyErr_Occurred()) { - goto exit; - } - if(posix_spawn_file_actions_adddup2(file_actionsp, fd1, fd2)) { - PyErr_SetString(PyExc_OSError,"Failed to add dup2 file action"); - goto exit; - } - break; - - default: - PyErr_SetString(PyExc_TypeError,"Unknown file_actions identifier"); - goto exit; - } - } + file_actionsp = &file_actions_buf; } _Py_BEGIN_SUPPRESS_IPH - int err_code = posix_spawn(&pid, path->narrow, file_actionsp, NULL, argvlist, envlist); + err_code = posix_spawn(&pid, path->narrow, + file_actionsp, NULL, argvlist, envlist); _Py_END_SUPPRESS_IPH - if(err_code) { - PyErr_SetString(PyExc_OSError,"posix_spawn call failed"); + if (err_code) { + errno = err_code; + PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object); goto exit; } result = PyLong_FromPid(pid); exit: - - Py_XDECREF(seq); - - if(file_actionsp) { - posix_spawn_file_actions_destroy(file_actionsp); + if (file_actionsp) { + (void)posix_spawn_file_actions_destroy(file_actionsp); } - if (envlist) { free_string_array(envlist, envc); } - if (argvlist) { free_string_array(argvlist, argc); } - return result; - - } #endif /* HAVE_POSIX_SPAWN */ From webhook-mailer at python.org Tue May 1 10:40:21 2018 From: webhook-mailer at python.org (Ned Deily) Date: Tue, 01 May 2018 14:40:21 -0000 Subject: [Python-checkins] bpo-33377: add triplets for mips-r6 and riscv (GH-6655) (GH-6660) Message-ID: https://github.com/python/cpython/commit/0596f319020ad34010cbf98608021080ba2a1d4b commit: 0596f319020ad34010cbf98608021080ba2a1d4b branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Ned Deily date: 2018-05-01T10:40:17-04:00 summary: bpo-33377: add triplets for mips-r6 and riscv (GH-6655) (GH-6660) (cherry picked from commit ddbe976964933cb943c6383a776e800cc7e0f47d) Co-authored-by: Matthias Klose files: A Misc/NEWS.d/next/Build/2018-04-30-16-53-00.bpo-33377.QBh6vP.rst M configure M configure.ac diff --git a/Misc/NEWS.d/next/Build/2018-04-30-16-53-00.bpo-33377.QBh6vP.rst b/Misc/NEWS.d/next/Build/2018-04-30-16-53-00.bpo-33377.QBh6vP.rst new file mode 100644 index 000000000000..f5dbd23c7c35 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2018-04-30-16-53-00.bpo-33377.QBh6vP.rst @@ -0,0 +1,2 @@ +Add new triplets for mips r6 and riscv variants (used in extension +suffixes). diff --git a/configure b/configure index f75acf68ce2c..2ab9bc8eff2a 100755 --- a/configure +++ b/configure @@ -781,6 +781,7 @@ infodir docdir oldincludedir includedir +runstatedir localstatedir sharedstatedir sysconfdir @@ -893,6 +894,7 @@ datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' +runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' @@ -1145,6 +1147,15 @@ do | -silent | --silent | --silen | --sile | --sil) silent=yes ;; + -runstatedir | --runstatedir | --runstatedi | --runstated \ + | --runstate | --runstat | --runsta | --runst | --runs \ + | --run | --ru | --r) + ac_prev=runstatedir ;; + -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ + | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ + | --run=* | --ru=* | --r=*) + runstatedir=$ac_optarg ;; + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ @@ -1282,7 +1293,7 @@ fi for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir + libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. @@ -1435,6 +1446,7 @@ Fine tuning of the installation directories: --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] @@ -5238,6 +5250,26 @@ cat >> conftest.c <=6) && defined(_MIPSEL) +# if _MIPS_SIM == _ABIO32 + mipsisa32r6el-linux-gnu +# elif _MIPS_SIM == _ABIN32 + mipsisa64r6el-linux-gnuabin32 +# elif _MIPS_SIM == _ABI64 + mipsisa64r6el-linux-gnuabi64 +# else +# error unknown platform triplet +# endif +# elif defined(__mips_hard_float) && defined(__mips_isa_rev) && (__mips_isa_rev >=6) +# if _MIPS_SIM == _ABIO32 + mipsisa32r6-linux-gnu +# elif _MIPS_SIM == _ABIN32 + mipsisa64r6-linux-gnuabin32 +# elif _MIPS_SIM == _ABI64 + mipsisa64r6-linux-gnuabi64 +# else +# error unknown platform triplet +# endif # elif defined(__mips_hard_float) && defined(_MIPSEL) # if _MIPS_SIM == _ABIO32 mipsel-linux-gnu @@ -5280,6 +5312,14 @@ cat >> conftest.c <> conftest.c <=6) && defined(_MIPSEL) +# if _MIPS_SIM == _ABIO32 + mipsisa32r6el-linux-gnu +# elif _MIPS_SIM == _ABIN32 + mipsisa64r6el-linux-gnuabin32 +# elif _MIPS_SIM == _ABI64 + mipsisa64r6el-linux-gnuabi64 +# else +# error unknown platform triplet +# endif +# elif defined(__mips_hard_float) && defined(__mips_isa_rev) && (__mips_isa_rev >=6) +# if _MIPS_SIM == _ABIO32 + mipsisa32r6-linux-gnu +# elif _MIPS_SIM == _ABIN32 + mipsisa64r6-linux-gnuabin32 +# elif _MIPS_SIM == _ABI64 + mipsisa64r6-linux-gnuabi64 +# else +# error unknown platform triplet +# endif # elif defined(__mips_hard_float) && defined(_MIPSEL) # if _MIPS_SIM == _ABIO32 mipsel-linux-gnu @@ -823,6 +843,14 @@ cat >> conftest.c < https://github.com/python/cpython/commit/d06d345f04b3f7e5b318df69b1d179328a64ca9c commit: d06d345f04b3f7e5b318df69b1d179328a64ca9c branch: master author: Ray Donnelly committer: Ned Deily date: 2018-05-01T22:31:36-04:00 summary: bpo-33281: Fix ctypes.util.find_library regression on macOS (GH-6625) files: M Lib/ctypes/util.py diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py index 5e8b31a8546a..97973bce001d 100644 --- a/Lib/ctypes/util.py +++ b/Lib/ctypes/util.py @@ -67,7 +67,7 @@ def find_library(name): return fname return None -if os.name == "posix" and sys.platform == "darwin": +elif os.name == "posix" and sys.platform == "darwin": from ctypes.macholib.dyld import dyld_find as _dyld_find def find_library(name): possible = ['lib%s.dylib' % name, @@ -80,7 +80,7 @@ def find_library(name): continue return None -if sys.platform.startswith("aix"): +elif sys.platform.startswith("aix"): # AIX has two styles of storing shared libraries # GNU auto_tools refer to these as svr4 and aix # svr4 (System V Release 4) is a regular file, often with .so as suffix From webhook-mailer at python.org Tue May 1 22:41:46 2018 From: webhook-mailer at python.org (Ned Deily) Date: Wed, 02 May 2018 02:41:46 -0000 Subject: [Python-checkins] bpo-33281: NEWS and ACK (GH-6681) Message-ID: https://github.com/python/cpython/commit/69a013ec189f93a0dea97cfdbb3adc348648a666 commit: 69a013ec189f93a0dea97cfdbb3adc348648a666 branch: master author: Ned Deily committer: GitHub date: 2018-05-01T22:41:43-04:00 summary: bpo-33281: NEWS and ACK (GH-6681) files: A Misc/NEWS.d/next/Library/2018-05-01-22-35-50.bpo-33281.d4jOt4.rst M Misc/ACKS diff --git a/Misc/ACKS b/Misc/ACKS index 3b6774219f6c..587bbecbc36a 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -393,6 +393,7 @@ Jaromir Dolecek Zsolt Dollenstein Brendan Donegan Ismail Donmez +Ray Donnelly Robert Donohue Marcos Donolo Dima Dorfman diff --git a/Misc/NEWS.d/next/Library/2018-05-01-22-35-50.bpo-33281.d4jOt4.rst b/Misc/NEWS.d/next/Library/2018-05-01-22-35-50.bpo-33281.d4jOt4.rst new file mode 100644 index 000000000000..ad08caa70b63 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-01-22-35-50.bpo-33281.d4jOt4.rst @@ -0,0 +1 @@ +Fix ctypes.util.find_library regression on macOS. From webhook-mailer at python.org Tue May 1 22:51:34 2018 From: webhook-mailer at python.org (Ned Deily) Date: Wed, 02 May 2018 02:51:34 -0000 Subject: [Python-checkins] bpo-33281: Fix ctypes.util.find_library regression on macOS (GH-6625) (GH-6680) Message-ID: https://github.com/python/cpython/commit/c74ca5396aa7740d4fc90617e6b2315e849fa71f commit: c74ca5396aa7740d4fc90617e6b2315e849fa71f branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Ned Deily date: 2018-05-01T22:51:31-04:00 summary: bpo-33281: Fix ctypes.util.find_library regression on macOS (GH-6625) (GH-6680) (cherry picked from commit d06d345f04b3f7e5b318df69b1d179328a64ca9c) Co-authored-by: Ray Donnelly files: M Lib/ctypes/util.py diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py index 5e8b31a8546a..97973bce001d 100644 --- a/Lib/ctypes/util.py +++ b/Lib/ctypes/util.py @@ -67,7 +67,7 @@ def find_library(name): return fname return None -if os.name == "posix" and sys.platform == "darwin": +elif os.name == "posix" and sys.platform == "darwin": from ctypes.macholib.dyld import dyld_find as _dyld_find def find_library(name): possible = ['lib%s.dylib' % name, @@ -80,7 +80,7 @@ def find_library(name): continue return None -if sys.platform.startswith("aix"): +elif sys.platform.startswith("aix"): # AIX has two styles of storing shared libraries # GNU auto_tools refer to these as svr4 and aix # svr4 (System V Release 4) is a regular file, often with .so as suffix From webhook-mailer at python.org Tue May 1 22:52:45 2018 From: webhook-mailer at python.org (Ned Deily) Date: Wed, 02 May 2018 02:52:45 -0000 Subject: [Python-checkins] bpo-33281: NEWS and ACK (GH-6681) (GH-6682) Message-ID: https://github.com/python/cpython/commit/d74f35331f176e0679f0614b6cccf0dc0422e31a commit: d74f35331f176e0679f0614b6cccf0dc0422e31a branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Ned Deily date: 2018-05-01T22:52:42-04:00 summary: bpo-33281: NEWS and ACK (GH-6681) (GH-6682) (cherry picked from commit 69a013ec189f93a0dea97cfdbb3adc348648a666) Co-authored-by: Ned Deily files: A Misc/NEWS.d/next/Library/2018-05-01-22-35-50.bpo-33281.d4jOt4.rst M Misc/ACKS diff --git a/Misc/ACKS b/Misc/ACKS index 64262c490c66..0bb3f35d4915 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -392,6 +392,7 @@ Jaromir Dolecek Zsolt Dollenstein Brendan Donegan Ismail Donmez +Ray Donnelly Robert Donohue Marcos Donolo Dima Dorfman diff --git a/Misc/NEWS.d/next/Library/2018-05-01-22-35-50.bpo-33281.d4jOt4.rst b/Misc/NEWS.d/next/Library/2018-05-01-22-35-50.bpo-33281.d4jOt4.rst new file mode 100644 index 000000000000..ad08caa70b63 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-01-22-35-50.bpo-33281.d4jOt4.rst @@ -0,0 +1 @@ +Fix ctypes.util.find_library regression on macOS. From webhook-mailer at python.org Wed May 2 01:30:39 2018 From: webhook-mailer at python.org (Ned Deily) Date: Wed, 02 May 2018 05:30:39 -0000 Subject: [Python-checkins] bpo-33290: Have macOS installer remove "pip" alias (GH-6683) Message-ID: https://github.com/python/cpython/commit/0dd80709b5dc03756e7f4510761ae60236bb9f6d commit: 0dd80709b5dc03756e7f4510761ae60236bb9f6d branch: master author: Ned Deily committer: GitHub date: 2018-05-02T01:30:33-04:00 summary: bpo-33290: Have macOS installer remove "pip" alias (GH-6683) Currently, "pip3 install --upgrade pip" unconditionally installs a "pip" alias even for Python 3. If a user has an existing Python 3.x installed from a python.org macOS installer and then subsequently manually updates to a new version of pip, there may now be a stray "pip" alias in the Python 3.x framework bin directory which can cause confusion if the user has both a Python 2.7 and 3.x installed; if the Python 3.x fw bin directory appears early on $PATH, "pip" might invoke the pip3 for the Python 3.x rather than the pip for Python 2.7. To try to mitigate this, the macOS installer script for the ensurepip option will unconditionally remove "pip" from the 3.x framework bin directory being updated / installed. (The ambiguity can be avoided by using "pythonx.y -m pip".) files: M Mac/BuildScript/scripts/postflight.ensurepip diff --git a/Mac/BuildScript/scripts/postflight.ensurepip b/Mac/BuildScript/scripts/postflight.ensurepip index 3074fa36fc0b..36d05945b6fd 100755 --- a/Mac/BuildScript/scripts/postflight.ensurepip +++ b/Mac/BuildScript/scripts/postflight.ensurepip @@ -12,6 +12,11 @@ umask 022 "${FWK}/bin/python${PYVER}" -E -s -m ensurepip --upgrade +# bpo-33290: An earlier "pip3 install --upgrade pip" may have installed +# a "pip" in the fw bin directory. For a py3 install, remove it. + +rm -f "${FWK}/bin/pip" + "${FWK}/bin/python${PYVER}" -E -s -Wi \ "${FWK}/lib/python${PYVER}/compileall.py" -q -j0 \ -f -x badsyntax \ From webhook-mailer at python.org Wed May 2 01:41:18 2018 From: webhook-mailer at python.org (Ned Deily) Date: Wed, 02 May 2018 05:41:18 -0000 Subject: [Python-checkins] Mitigate macOS race condition in installer build (GH-6686) Message-ID: https://github.com/python/cpython/commit/fc6aa28bfd0502d994cec30bd3679b7def3be2af commit: fc6aa28bfd0502d994cec30bd3679b7def3be2af branch: master author: Ned Deily committer: GitHub date: 2018-05-02T01:41:15-04:00 summary: Mitigate macOS race condition in installer build (GH-6686) files: M Mac/BuildScript/build-installer.py diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index 68868d97a65c..d2b04d163ab4 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -1524,6 +1524,10 @@ def buildDMG(): shellQuote(os.path.join(WORKDIR, 'installer')), shellQuote(imagepath + ".tmp.dmg" ))) + # Try to mitigate race condition in certain versions of macOS, e.g. 10.9, + # when hdiutil fails with "Resource busy" + + time.sleep(10) if not os.path.exists(os.path.join(WORKDIR, "mnt")): os.mkdir(os.path.join(WORKDIR, "mnt")) From webhook-mailer at python.org Wed May 2 01:44:02 2018 From: webhook-mailer at python.org (Ned Deily) Date: Wed, 02 May 2018 05:44:02 -0000 Subject: [Python-checkins] bpo-33290: Have macOS installer remove "pip" alias (GH-6683) (GH-6684) Message-ID: https://github.com/python/cpython/commit/1470e43076559d22518f2e8d704fa9426d2659dd commit: 1470e43076559d22518f2e8d704fa9426d2659dd branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Ned Deily date: 2018-05-02T01:43:59-04:00 summary: bpo-33290: Have macOS installer remove "pip" alias (GH-6683) (GH-6684) Currently, "pip3 install --upgrade pip" unconditionally installs a "pip" alias even for Python 3. If a user has an existing Python 3.x installed from a python.org macOS installer and then subsequently manually updates to a new version of pip, there may now be a stray "pip" alias in the Python 3.x framework bin directory which can cause confusion if the user has both a Python 2.7 and 3.x installed; if the Python 3.x fw bin directory appears early on $PATH, "pip" might invoke the pip3 for the Python 3.x rather than the pip for Python 2.7. To try to mitigate this, the macOS installer script for the ensurepip option will unconditionally remove "pip" from the 3.x framework bin directory being updated / installed. (The ambiguity can be avoided by using "pythonx.y -m pip".) (cherry picked from commit 0dd80709b5dc03756e7f4510761ae60236bb9f6d) Co-authored-by: Ned Deily files: M Mac/BuildScript/scripts/postflight.ensurepip diff --git a/Mac/BuildScript/scripts/postflight.ensurepip b/Mac/BuildScript/scripts/postflight.ensurepip index 3074fa36fc0b..36d05945b6fd 100755 --- a/Mac/BuildScript/scripts/postflight.ensurepip +++ b/Mac/BuildScript/scripts/postflight.ensurepip @@ -12,6 +12,11 @@ umask 022 "${FWK}/bin/python${PYVER}" -E -s -m ensurepip --upgrade +# bpo-33290: An earlier "pip3 install --upgrade pip" may have installed +# a "pip" in the fw bin directory. For a py3 install, remove it. + +rm -f "${FWK}/bin/pip" + "${FWK}/bin/python${PYVER}" -E -s -Wi \ "${FWK}/lib/python${PYVER}/compileall.py" -q -j0 \ -f -x badsyntax \ From webhook-mailer at python.org Wed May 2 01:46:02 2018 From: webhook-mailer at python.org (Ned Deily) Date: Wed, 02 May 2018 05:46:02 -0000 Subject: [Python-checkins] Mitigate macOS race condition in installer build (GH-6686) (GH-6687) Message-ID: https://github.com/python/cpython/commit/50903bf011d8d3841c1874628f9ac20515256872 commit: 50903bf011d8d3841c1874628f9ac20515256872 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Ned Deily date: 2018-05-02T01:45:59-04:00 summary: Mitigate macOS race condition in installer build (GH-6686) (GH-6687) (cherry picked from commit fc6aa28bfd0502d994cec30bd3679b7def3be2af) Co-authored-by: Ned Deily files: M Mac/BuildScript/build-installer.py diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index 68868d97a65c..d2b04d163ab4 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -1524,6 +1524,10 @@ def buildDMG(): shellQuote(os.path.join(WORKDIR, 'installer')), shellQuote(imagepath + ".tmp.dmg" ))) + # Try to mitigate race condition in certain versions of macOS, e.g. 10.9, + # when hdiutil fails with "Resource busy" + + time.sleep(10) if not os.path.exists(os.path.join(WORKDIR, "mnt")): os.mkdir(os.path.join(WORKDIR, "mnt")) From webhook-mailer at python.org Wed May 2 01:48:13 2018 From: webhook-mailer at python.org (Ned Deily) Date: Wed, 02 May 2018 05:48:13 -0000 Subject: [Python-checkins] bpo-33290: Have macOS installer remove "pip" alias (GH-6683) (GH-6685) Message-ID: https://github.com/python/cpython/commit/8ac441876418a217c31fe429733d7fa4704f0e3c commit: 8ac441876418a217c31fe429733d7fa4704f0e3c branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Ned Deily date: 2018-05-02T01:48:11-04:00 summary: bpo-33290: Have macOS installer remove "pip" alias (GH-6683) (GH-6685) Currently, "pip3 install --upgrade pip" unconditionally installs a "pip" alias even for Python 3. If a user has an existing Python 3.x installed from a python.org macOS installer and then subsequently manually updates to a new version of pip, there may now be a stray "pip" alias in the Python 3.x framework bin directory which can cause confusion if the user has both a Python 2.7 and 3.x installed; if the Python 3.x fw bin directory appears early on $PATH, "pip" might invoke the pip3 for the Python 3.x rather than the pip for Python 2.7. To try to mitigate this, the macOS installer script for the ensurepip option will unconditionally remove "pip" from the 3.x framework bin directory being updated / installed. (The ambiguity can be avoided by using "pythonx.y -m pip".) (cherry picked from commit 0dd80709b5dc03756e7f4510761ae60236bb9f6d) Co-authored-by: Ned Deily files: M Mac/BuildScript/scripts/postflight.ensurepip diff --git a/Mac/BuildScript/scripts/postflight.ensurepip b/Mac/BuildScript/scripts/postflight.ensurepip index 3074fa36fc0b..36d05945b6fd 100755 --- a/Mac/BuildScript/scripts/postflight.ensurepip +++ b/Mac/BuildScript/scripts/postflight.ensurepip @@ -12,6 +12,11 @@ umask 022 "${FWK}/bin/python${PYVER}" -E -s -m ensurepip --upgrade +# bpo-33290: An earlier "pip3 install --upgrade pip" may have installed +# a "pip" in the fw bin directory. For a py3 install, remove it. + +rm -f "${FWK}/bin/pip" + "${FWK}/bin/python${PYVER}" -E -s -Wi \ "${FWK}/lib/python${PYVER}/compileall.py" -q -j0 \ -f -x badsyntax \ From webhook-mailer at python.org Wed May 2 01:49:06 2018 From: webhook-mailer at python.org (Ned Deily) Date: Wed, 02 May 2018 05:49:06 -0000 Subject: [Python-checkins] Mitigate macOS race condition in installer build (GH-6686) (GH-6688) Message-ID: https://github.com/python/cpython/commit/fb646219e9ec673d267d264b34c25fe96dc12844 commit: fb646219e9ec673d267d264b34c25fe96dc12844 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Ned Deily date: 2018-05-02T01:49:03-04:00 summary: Mitigate macOS race condition in installer build (GH-6686) (GH-6688) (cherry picked from commit fc6aa28bfd0502d994cec30bd3679b7def3be2af) Co-authored-by: Ned Deily files: M Mac/BuildScript/build-installer.py diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index ef81bc147e21..d76b2c096764 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -1523,6 +1523,10 @@ def buildDMG(): shellQuote(os.path.join(WORKDIR, 'installer')), shellQuote(imagepath + ".tmp.dmg" ))) + # Try to mitigate race condition in certain versions of macOS, e.g. 10.9, + # when hdiutil fails with "Resource busy" + + time.sleep(10) if not os.path.exists(os.path.join(WORKDIR, "mnt")): os.mkdir(os.path.join(WORKDIR, "mnt")) From webhook-mailer at python.org Wed May 2 01:50:15 2018 From: webhook-mailer at python.org (Ned Deily) Date: Wed, 02 May 2018 05:50:15 -0000 Subject: [Python-checkins] Mitigate macOS race condition in installer build (GH-6686) (#6689) Message-ID: https://github.com/python/cpython/commit/5818f0896257c51654ce3efce9abad63e12db037 commit: 5818f0896257c51654ce3efce9abad63e12db037 branch: 2.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Ned Deily date: 2018-05-02T01:50:12-04:00 summary: Mitigate macOS race condition in installer build (GH-6686) (#6689) (cherry picked from commit fc6aa28bfd0502d994cec30bd3679b7def3be2af) Co-authored-by: Ned Deily files: M Mac/BuildScript/build-installer.py diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index 7875bc8ef419..038e1917c4e1 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -1530,6 +1530,10 @@ def buildDMG(): shellQuote(os.path.join(WORKDIR, 'installer')), shellQuote(imagepath + ".tmp.dmg" ))) + # Try to mitigate race condition in certain versions of macOS, e.g. 10.9, + # when hdiutil fails with "Resource busy" + + time.sleep(10) if not os.path.exists(os.path.join(WORKDIR, "mnt")): os.mkdir(os.path.join(WORKDIR, "mnt")) From webhook-mailer at python.org Wed May 2 02:54:54 2018 From: webhook-mailer at python.org (Matthias Klose) Date: Wed, 02 May 2018 06:54:54 -0000 Subject: [Python-checkins] bpo-33393: Update config.guess and config.sub files (GH-6658) (#6661) Message-ID: https://github.com/python/cpython/commit/9da7ee40037fa30d0d28fd8d7c652cde14e5a834 commit: 9da7ee40037fa30d0d28fd8d7c652cde14e5a834 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Matthias Klose date: 2018-05-02T08:54:51+02:00 summary: bpo-33393: Update config.guess and config.sub files (GH-6658) (#6661) (cherry picked from commit 7e3545c70cdecd86ffa8fcbffd79b4f78560679f) Co-authored-by: Matthias Klose files: A Misc/NEWS.d/next/Build/2018-04-30-17-19-37.bpo-33393.HkVCqI.rst M config.guess M config.sub diff --git a/Misc/NEWS.d/next/Build/2018-04-30-17-19-37.bpo-33393.HkVCqI.rst b/Misc/NEWS.d/next/Build/2018-04-30-17-19-37.bpo-33393.HkVCqI.rst new file mode 100644 index 000000000000..f3317e7e68f3 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2018-04-30-17-19-37.bpo-33393.HkVCqI.rst @@ -0,0 +1 @@ +Update config.guess and config.sub files. diff --git a/config.guess b/config.guess index 2193702b12af..256083a70d35 100755 --- a/config.guess +++ b/config.guess @@ -1,8 +1,8 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright 1992-2017 Free Software Foundation, Inc. +# Copyright 1992-2018 Free Software Foundation, Inc. -timestamp='2017-05-27' +timestamp='2018-03-08' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -15,7 +15,7 @@ timestamp='2017-05-27' # General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, see . +# along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -27,7 +27,7 @@ timestamp='2017-05-27' # Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess # # Please send patches to . @@ -39,7 +39,7 @@ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. -Operation modes: +Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit @@ -50,7 +50,7 @@ version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright 1992-2017 Free Software Foundation, Inc. +Copyright 1992-2018 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -107,9 +107,9 @@ trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int x;" > $dummy.c ; + ,,) echo "int x;" > "$dummy.c" ; for c in cc gcc c89 c99 ; do - if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + if ($c -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; @@ -132,14 +132,14 @@ UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown -case "${UNAME_SYSTEM}" in +case "$UNAME_SYSTEM" in Linux|GNU|GNU/*) # If the system lacks a compiler, then just pick glibc. # We could probably try harder. LIBC=gnu - eval $set_cc_for_build - cat <<-EOF > $dummy.c + eval "$set_cc_for_build" + cat <<-EOF > "$dummy.c" #include #if defined(__UCLIBC__) LIBC=uclibc @@ -149,13 +149,20 @@ Linux|GNU|GNU/*) LIBC=gnu #endif EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`" + + # If ldd exists, use it to detect musl libc. + if command -v ldd >/dev/null && \ + ldd --version 2>&1 | grep -q ^musl + then + LIBC=musl + fi ;; esac # Note: order is significant - the case branches are not exclusive. -case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in +case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, @@ -169,30 +176,30 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ - /sbin/$sysctl 2>/dev/null || \ - /usr/sbin/$sysctl 2>/dev/null || \ + "/sbin/$sysctl" 2>/dev/null || \ + "/usr/sbin/$sysctl" 2>/dev/null || \ echo unknown)` - case "${UNAME_MACHINE_ARCH}" in + case "$UNAME_MACHINE_ARCH" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; earmv*) - arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'` - endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'` - machine=${arch}${endian}-unknown + arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'` + endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'` + machine="${arch}${endian}"-unknown ;; - *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + *) machine="$UNAME_MACHINE_ARCH"-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently (or will in the future) and ABI. - case "${UNAME_MACHINE_ARCH}" in + case "$UNAME_MACHINE_ARCH" in earm*) os=netbsdelf ;; arm*|i386|m68k|ns32k|sh3*|sparc|vax) - eval $set_cc_for_build + eval "$set_cc_for_build" if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then @@ -208,10 +215,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in ;; esac # Determine ABI tags. - case "${UNAME_MACHINE_ARCH}" in + case "$UNAME_MACHINE_ARCH" in earm*) expr='s/^earmv[0-9]/-eabi/;s/eb$//' - abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"` + abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"` ;; esac # The OS release @@ -219,46 +226,55 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. - case "${UNAME_VERSION}" in + case "$UNAME_VERSION" in Debian*) release='-gnu' ;; *) - release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2` + release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}${abi}" + echo "$machine-${os}${release}${abi}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} + echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE" exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE" exit ;; *:LibertyBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE} + echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE" + exit ;; + *:MidnightBSD:*:*) + echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE" exit ;; *:ekkoBSD:*:*) - echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE" exit ;; *:SolidBSD:*:*) - echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE" exit ;; macppc:MirBSD:*:*) - echo powerpc-unknown-mirbsd${UNAME_RELEASE} + echo powerpc-unknown-mirbsd"$UNAME_RELEASE" exit ;; *:MirBSD:*:*) - echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE" exit ;; *:Sortix:*:*) - echo ${UNAME_MACHINE}-unknown-sortix + echo "$UNAME_MACHINE"-unknown-sortix + exit ;; + *:Redox:*:*) + echo "$UNAME_MACHINE"-unknown-redox exit ;; + mips:OSF1:*.*) + echo mips-dec-osf1 + exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) @@ -310,28 +326,19 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`" # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; - Alpha\ *:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # Should we change UNAME_MACHINE based on the output of uname instead - # of the specific Alpha model? - echo alpha-pc-interix - exit ;; - 21064:Windows_NT:50:3) - echo alpha-dec-winnt3.5 - exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-amigaos + echo "$UNAME_MACHINE"-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-morphos + echo "$UNAME_MACHINE"-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition @@ -343,7 +350,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix${UNAME_RELEASE} + echo arm-acorn-riscix"$UNAME_RELEASE" exit ;; arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos @@ -370,19 +377,19 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) - echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" exit ;; sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) - echo i386-pc-auroraux${UNAME_RELEASE} + echo i386-pc-auroraux"$UNAME_RELEASE" exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) - eval $set_cc_for_build + eval "$set_cc_for_build" SUN_ARCH=i386 # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. @@ -395,13 +402,13 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in SUN_ARCH=x86_64 fi fi - echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in @@ -410,25 +417,25 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`" exit ;; sun3*:SunOS:*:*) - echo m68k-sun-sunos${UNAME_RELEASE} + echo m68k-sun-sunos"$UNAME_RELEASE" exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = x && UNAME_RELEASE=3 + test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) - echo m68k-sun-sunos${UNAME_RELEASE} + echo m68k-sun-sunos"$UNAME_RELEASE" ;; sun4) - echo sparc-sun-sunos${UNAME_RELEASE} + echo sparc-sun-sunos"$UNAME_RELEASE" ;; esac exit ;; aushp:SunOS:*:*) - echo sparc-auspex-sunos${UNAME_RELEASE} + echo sparc-auspex-sunos"$UNAME_RELEASE" exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not @@ -439,44 +446,44 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} + echo m68k-atari-mint"$UNAME_RELEASE" exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} + echo m68k-atari-mint"$UNAME_RELEASE" exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} + echo m68k-atari-mint"$UNAME_RELEASE" exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} + echo m68k-milan-mint"$UNAME_RELEASE" exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} + echo m68k-hades-mint"$UNAME_RELEASE" exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} + echo m68k-unknown-mint"$UNAME_RELEASE" exit ;; m68k:machten:*:*) - echo m68k-apple-machten${UNAME_RELEASE} + echo m68k-apple-machten"$UNAME_RELEASE" exit ;; powerpc:machten:*:*) - echo powerpc-apple-machten${UNAME_RELEASE} + echo powerpc-apple-machten"$UNAME_RELEASE" exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) - echo mips-dec-ultrix${UNAME_RELEASE} + echo mips-dec-ultrix"$UNAME_RELEASE" exit ;; VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix${UNAME_RELEASE} + echo vax-dec-ultrix"$UNAME_RELEASE" exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix${UNAME_RELEASE} + echo clipper-intergraph-clix"$UNAME_RELEASE" exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { @@ -485,23 +492,23 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF - $CC_FOR_BUILD -o $dummy $dummy.c && - dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && - SYSTEM_NAME=`$dummy $dummyarg` && + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && + dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`"$dummy" "$dummyarg"` && { echo "$SYSTEM_NAME"; exit; } - echo mips-mips-riscos${UNAME_RELEASE} + echo mips-mips-riscos"$UNAME_RELEASE" exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax @@ -527,17 +534,17 @@ EOF AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + if [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ] then - if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ - [ ${TARGET_BINARY_INTERFACE}x = x ] + if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \ + [ "$TARGET_BINARY_INTERFACE"x = x ] then - echo m88k-dg-dgux${UNAME_RELEASE} + echo m88k-dg-dgux"$UNAME_RELEASE" else - echo m88k-dg-dguxbcs${UNAME_RELEASE} + echo m88k-dg-dguxbcs"$UNAME_RELEASE" fi else - echo i586-dg-dgux${UNAME_RELEASE} + echo i586-dg-dgux"$UNAME_RELEASE" fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) @@ -554,7 +561,7 @@ EOF echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) - echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`" exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id @@ -566,14 +573,14 @@ EOF if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" fi - echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV" exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" #include main() @@ -584,7 +591,7 @@ EOF exit(0); } EOF - if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` then echo "$SYSTEM_NAME" else @@ -598,7 +605,7 @@ EOF exit ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` - if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc @@ -607,18 +614,18 @@ EOF IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" fi - echo ${IBM_ARCH}-ibm-aix${IBM_REV} + echo "$IBM_ARCH"-ibm-aix"$IBM_REV" exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; - ibmrt:4.4BSD:*|romp-ibm:BSD:*) + ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + echo romp-ibm-bsd"$UNAME_RELEASE" # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx @@ -633,28 +640,28 @@ EOF echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; + HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` + case "$UNAME_MACHINE" in + 9000/31?) HP_ARCH=m68000 ;; + 9000/[34]??) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in + case "$sc_cpu_version" in 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in + case "$sc_kernel_bits" in 32) HP_ARCH=hppa2.0n ;; 64) HP_ARCH=hppa2.0w ;; '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 esac ;; esac fi - if [ "${HP_ARCH}" = "" ]; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + if [ "$HP_ARCH" = "" ]; then + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" #define _HPUX_SOURCE #include @@ -687,13 +694,13 @@ EOF exit (0); } EOF - (CCOPTS="" $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac - if [ ${HP_ARCH} = hppa2.0w ] + if [ "$HP_ARCH" = hppa2.0w ] then - eval $set_cc_for_build + eval "$set_cc_for_build" # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler @@ -712,15 +719,15 @@ EOF HP_ARCH=hppa64 fi fi - echo ${HP_ARCH}-hp-hpux${HPUX_REV} + echo "$HP_ARCH"-hp-hpux"$HPUX_REV" exit ;; ia64:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - echo ia64-hp-hpux${HPUX_REV} + HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux"$HPUX_REV" exit ;; 3050*:HI-UX:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" #include int main () @@ -745,11 +752,11 @@ EOF exit (0); } EOF - $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) @@ -758,7 +765,7 @@ EOF *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) @@ -766,9 +773,9 @@ EOF exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then - echo ${UNAME_MACHINE}-unknown-osf1mk + echo "$UNAME_MACHINE"-unknown-osf1mk else - echo ${UNAME_MACHINE}-unknown-osf1 + echo "$UNAME_MACHINE"-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) @@ -793,128 +800,109 @@ EOF echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) - echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) - echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) - echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) - echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE" exit ;; sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi${UNAME_RELEASE} + echo sparc-unknown-bsdi"$UNAME_RELEASE" exit ;; *:BSD/OS:*:*) - echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE" exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` - case ${UNAME_PROCESSOR} in + case "$UNAME_PROCESSOR" in amd64) UNAME_PROCESSOR=x86_64 ;; i386) UNAME_PROCESSOR=i586 ;; esac - echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" exit ;; i*:CYGWIN*:*) - echo ${UNAME_MACHINE}-pc-cygwin + echo "$UNAME_MACHINE"-pc-cygwin exit ;; *:MINGW64*:*) - echo ${UNAME_MACHINE}-pc-mingw64 + echo "$UNAME_MACHINE"-pc-mingw64 exit ;; *:MINGW*:*) - echo ${UNAME_MACHINE}-pc-mingw32 + echo "$UNAME_MACHINE"-pc-mingw32 exit ;; *:MSYS*:*) - echo ${UNAME_MACHINE}-pc-msys - exit ;; - i*:windows32*:*) - # uname -m includes "-pc" on this system. - echo ${UNAME_MACHINE}-mingw32 + echo "$UNAME_MACHINE"-pc-msys exit ;; i*:PW*:*) - echo ${UNAME_MACHINE}-pc-pw32 + echo "$UNAME_MACHINE"-pc-pw32 exit ;; *:Interix*:*) - case ${UNAME_MACHINE} in + case "$UNAME_MACHINE" in x86) - echo i586-pc-interix${UNAME_RELEASE} + echo i586-pc-interix"$UNAME_RELEASE" exit ;; authenticamd | genuineintel | EM64T) - echo x86_64-unknown-interix${UNAME_RELEASE} + echo x86_64-unknown-interix"$UNAME_RELEASE" exit ;; IA64) - echo ia64-unknown-interix${UNAME_RELEASE} + echo ia64-unknown-interix"$UNAME_RELEASE" exit ;; esac ;; - [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) - echo i${UNAME_MACHINE}-pc-mks - exit ;; - 8664:Windows_NT:*) - echo x86_64-pc-mks - exit ;; - i*:Windows_NT*:* | Pentium*:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we - # UNAME_MACHINE based on the output of uname instead of i386? - echo i586-pc-interix - exit ;; i*:UWIN*:*) - echo ${UNAME_MACHINE}-pc-uwin + echo "$UNAME_MACHINE"-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; - p*:CYGWIN*:*) - echo powerpcle-unknown-cygwin - exit ;; prep*:SunOS:5.*:*) - echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; *:GNU:*:*) # the GNU system - echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + echo "`echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,'`-unknown-$LIBC`echo "$UNAME_RELEASE"|sed -e 's,/.*$,,'`" exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland - echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} + echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC" exit ;; i*86:Minix:*:*) - echo ${UNAME_MACHINE}-pc-minix + echo "$UNAME_MACHINE"-pc-minix exit ;; aarch64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in @@ -928,63 +916,63 @@ EOF esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC=gnulibc1 ; fi - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; arc:Linux:*:* | arceb:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; arm*:Linux:*:*) - eval $set_cc_for_build + eval "$set_cc_for_build" if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then - echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi else - echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf fi fi exit ;; avr32*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; cris:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-${LIBC} + echo "$UNAME_MACHINE"-axis-linux-"$LIBC" exit ;; crisv32:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-${LIBC} + echo "$UNAME_MACHINE"-axis-linux-"$LIBC" exit ;; e2k:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; frv:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; hexagon:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; i*86:Linux:*:*) - echo ${UNAME_MACHINE}-pc-linux-${LIBC} + echo "$UNAME_MACHINE"-pc-linux-"$LIBC" exit ;; ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; k1om:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; m32r*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; m68*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; mips:Linux:*:* | mips64:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" #undef CPU #undef ${UNAME_MACHINE} #undef ${UNAME_MACHINE}el @@ -998,70 +986,70 @@ EOF #endif #endif EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` - test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU'`" + test "x$CPU" != x && { echo "$CPU-unknown-linux-$LIBC"; exit; } ;; mips64el:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; openrisc*:Linux:*:*) - echo or1k-unknown-linux-${LIBC} + echo or1k-unknown-linux-"$LIBC" exit ;; or32:Linux:*:* | or1k*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; padre:Linux:*:*) - echo sparc-unknown-linux-${LIBC} + echo sparc-unknown-linux-"$LIBC" exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-${LIBC} + echo hppa64-unknown-linux-"$LIBC" exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; - PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; - *) echo hppa-unknown-linux-${LIBC} ;; + PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;; + PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;; + *) echo hppa-unknown-linux-"$LIBC" ;; esac exit ;; ppc64:Linux:*:*) - echo powerpc64-unknown-linux-${LIBC} + echo powerpc64-unknown-linux-"$LIBC" exit ;; ppc:Linux:*:*) - echo powerpc-unknown-linux-${LIBC} + echo powerpc-unknown-linux-"$LIBC" exit ;; ppc64le:Linux:*:*) - echo powerpc64le-unknown-linux-${LIBC} + echo powerpc64le-unknown-linux-"$LIBC" exit ;; ppcle:Linux:*:*) - echo powerpcle-unknown-linux-${LIBC} + echo powerpcle-unknown-linux-"$LIBC" exit ;; riscv32:Linux:*:* | riscv64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; s390:Linux:*:* | s390x:Linux:*:*) - echo ${UNAME_MACHINE}-ibm-linux-${LIBC} + echo "$UNAME_MACHINE"-ibm-linux-"$LIBC" exit ;; sh64*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; sh*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; tile*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; vax:Linux:*:*) - echo ${UNAME_MACHINE}-dec-linux-${LIBC} + echo "$UNAME_MACHINE"-dec-linux-"$LIBC" exit ;; x86_64:Linux:*:*) - echo ${UNAME_MACHINE}-pc-linux-${LIBC} + echo "$UNAME_MACHINE"-pc-linux-"$LIBC" exit ;; xtensa*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. @@ -1075,34 +1063,34 @@ EOF # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. - echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION" exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx + echo "$UNAME_MACHINE"-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) - echo ${UNAME_MACHINE}-unknown-stop + echo "$UNAME_MACHINE"-unknown-stop exit ;; i*86:atheos:*:*) - echo ${UNAME_MACHINE}-unknown-atheos + echo "$UNAME_MACHINE"-unknown-atheos exit ;; i*86:syllable:*:*) - echo ${UNAME_MACHINE}-pc-syllable + echo "$UNAME_MACHINE"-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} + echo i386-unknown-lynxos"$UNAME_RELEASE" exit ;; i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp + echo "$UNAME_MACHINE"-pc-msdosdjgpp exit ;; - i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) - UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + i*86:*:4.*:*) + UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL" else - echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL" fi exit ;; i*86:*:5:[678]*) @@ -1112,12 +1100,12 @@ EOF *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac - echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}{$UNAME_VERSION}" exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 @@ -1127,9 +1115,9 @@ EOF && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 - echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL" else - echo ${UNAME_MACHINE}-pc-sysv32 + echo "$UNAME_MACHINE"-pc-sysv32 fi exit ;; pc:*:*:*) @@ -1149,9 +1137,9 @@ EOF exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + echo i860-unknown-sysv"$UNAME_RELEASE" # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) @@ -1171,9 +1159,9 @@ EOF test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; @@ -1182,28 +1170,28 @@ EOF test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-unknown-lynxos${UNAME_RELEASE} + echo m68k-unknown-lynxos"$UNAME_RELEASE" exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos${UNAME_RELEASE} + echo sparc-unknown-lynxos"$UNAME_RELEASE" exit ;; rs6000:LynxOS:2.*:*) - echo rs6000-unknown-lynxos${UNAME_RELEASE} + echo rs6000-unknown-lynxos"$UNAME_RELEASE" exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) - echo powerpc-unknown-lynxos${UNAME_RELEASE} + echo powerpc-unknown-lynxos"$UNAME_RELEASE" exit ;; SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv${UNAME_RELEASE} + echo mips-dde-sysv"$UNAME_RELEASE" exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 @@ -1214,7 +1202,7 @@ EOF *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo ${UNAME_MACHINE}-sni-sysv4 + echo "$UNAME_MACHINE"-sni-sysv4 else echo ns32k-sni-sysv fi @@ -1234,23 +1222,23 @@ EOF exit ;; i*86:VOS:*:*) # From Paul.Green at stratus.com. - echo ${UNAME_MACHINE}-stratus-vos + echo "$UNAME_MACHINE"-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green at stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) - echo m68k-apple-aux${UNAME_RELEASE} + echo m68k-apple-aux"$UNAME_RELEASE" exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} + echo mips-nec-sysv"$UNAME_RELEASE" else - echo mips-unknown-sysv${UNAME_RELEASE} + echo mips-unknown-sysv"$UNAME_RELEASE" fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. @@ -1269,39 +1257,39 @@ EOF echo x86_64-unknown-haiku exit ;; SX-4:SUPER-UX:*:*) - echo sx4-nec-superux${UNAME_RELEASE} + echo sx4-nec-superux"$UNAME_RELEASE" exit ;; SX-5:SUPER-UX:*:*) - echo sx5-nec-superux${UNAME_RELEASE} + echo sx5-nec-superux"$UNAME_RELEASE" exit ;; SX-6:SUPER-UX:*:*) - echo sx6-nec-superux${UNAME_RELEASE} + echo sx6-nec-superux"$UNAME_RELEASE" exit ;; SX-7:SUPER-UX:*:*) - echo sx7-nec-superux${UNAME_RELEASE} + echo sx7-nec-superux"$UNAME_RELEASE" exit ;; SX-8:SUPER-UX:*:*) - echo sx8-nec-superux${UNAME_RELEASE} + echo sx8-nec-superux"$UNAME_RELEASE" exit ;; SX-8R:SUPER-UX:*:*) - echo sx8r-nec-superux${UNAME_RELEASE} + echo sx8r-nec-superux"$UNAME_RELEASE" exit ;; SX-ACE:SUPER-UX:*:*) - echo sxace-nec-superux${UNAME_RELEASE} + echo sxace-nec-superux"$UNAME_RELEASE" exit ;; Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody${UNAME_RELEASE} + echo powerpc-apple-rhapsody"$UNAME_RELEASE" exit ;; *:Rhapsody:*:*) - echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE" exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown - eval $set_cc_for_build + eval "$set_cc_for_build" if test "$UNAME_PROCESSOR" = unknown ; then UNAME_PROCESSOR=powerpc fi - if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then + if test "`echo "$UNAME_RELEASE" | sed -e 's/\..*//'`" -le 10 ; then if [ "$CC_FOR_BUILD" != no_compiler_found ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ @@ -1329,7 +1317,7 @@ EOF # that Apple uses in portable devices. UNAME_PROCESSOR=x86_64 fi - echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE" exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` @@ -1337,22 +1325,25 @@ EOF UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi - echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE" exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NEO-*:NONSTOP_KERNEL:*:*) - echo neo-tandem-nsk${UNAME_RELEASE} + echo neo-tandem-nsk"$UNAME_RELEASE" exit ;; NSE-*:NONSTOP_KERNEL:*:*) - echo nse-tandem-nsk${UNAME_RELEASE} + echo nse-tandem-nsk"$UNAME_RELEASE" exit ;; NSR-*:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk${UNAME_RELEASE} + echo nsr-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSV-*:NONSTOP_KERNEL:*:*) + echo nsv-tandem-nsk"$UNAME_RELEASE" exit ;; NSX-*:NONSTOP_KERNEL:*:*) - echo nsx-tandem-nsk${UNAME_RELEASE} + echo nsx-tandem-nsk"$UNAME_RELEASE" exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux @@ -1361,7 +1352,7 @@ EOF echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) - echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE" exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 @@ -1372,7 +1363,7 @@ EOF else UNAME_MACHINE="$cputype" fi - echo ${UNAME_MACHINE}-unknown-plan9 + echo "$UNAME_MACHINE"-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 @@ -1393,14 +1384,14 @@ EOF echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) - echo mips-sei-seiux${UNAME_RELEASE} + echo mips-sei-seiux"$UNAME_RELEASE" exit ;; *:DragonFly:*:*) - echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` - case "${UNAME_MACHINE}" in + case "$UNAME_MACHINE" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; @@ -1409,32 +1400,44 @@ EOF echo i386-pc-xenix exit ;; i*86:skyos:*:*) - echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'` + echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`" exit ;; i*86:rdos:*:*) - echo ${UNAME_MACHINE}-pc-rdos + echo "$UNAME_MACHINE"-pc-rdos exit ;; i*86:AROS:*:*) - echo ${UNAME_MACHINE}-pc-aros + echo "$UNAME_MACHINE"-pc-aros exit ;; x86_64:VMkernel:*:*) - echo ${UNAME_MACHINE}-unknown-esx + echo "$UNAME_MACHINE"-unknown-esx exit ;; amd64:Isilon\ OneFS:*:*) echo x86_64-unknown-onefs exit ;; esac +echo "$0: unable to guess system type" >&2 + +case "$UNAME_MACHINE:$UNAME_SYSTEM" in + mips:Linux | mips64:Linux) + # If we got here on MIPS GNU/Linux, output extra information. + cat >&2 <&2 </dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` -UNAME_MACHINE = ${UNAME_MACHINE} -UNAME_RELEASE = ${UNAME_RELEASE} -UNAME_SYSTEM = ${UNAME_SYSTEM} -UNAME_VERSION = ${UNAME_VERSION} +UNAME_MACHINE = "$UNAME_MACHINE" +UNAME_RELEASE = "$UNAME_RELEASE" +UNAME_SYSTEM = "$UNAME_SYSTEM" +UNAME_VERSION = "$UNAME_VERSION" EOF exit 1 # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" diff --git a/config.sub b/config.sub index 40ea5dfe1152..ba37cf99e26b 100755 --- a/config.sub +++ b/config.sub @@ -1,8 +1,8 @@ #! /bin/sh # Configuration validation subroutine script. -# Copyright 1992-2017 Free Software Foundation, Inc. +# Copyright 1992-2018 Free Software Foundation, Inc. -timestamp='2017-04-02' +timestamp='2018-04-24' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -15,7 +15,7 @@ timestamp='2017-04-02' # General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, see . +# along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -33,7 +33,7 @@ timestamp='2017-04-02' # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases @@ -57,7 +57,7 @@ Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS Canonicalize a configuration name. -Operation modes: +Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit @@ -67,7 +67,7 @@ Report bugs and patches to ." version="\ GNU config.sub ($timestamp) -Copyright 1992-2017 Free Software Foundation, Inc. +Copyright 1992-2018 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -94,7 +94,7 @@ while test $# -gt 0 ; do *local*) # First pass through any local machine types. - echo $1 + echo "$1" exit ;; * ) @@ -112,7 +112,7 @@ esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +maybe_os=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ @@ -120,16 +120,16 @@ case $maybe_os in kopensolaris*-gnu* | cloudabi*-eabi* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; android-linux) os=-linux-android - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` + basic_machine=`echo "$1" | sed 's/-[^-]*$//'` + if [ "$basic_machine" != "$1" ] + then os=`echo "$1" | sed 's/.*-/-/'` else os=; fi ;; esac @@ -178,44 +178,44 @@ case $os in ;; -sco6) os=-sco5v6 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -udk*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -lynx*178) os=-lynxos178 @@ -227,10 +227,7 @@ case $os in os=-lynxos ;; -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` - ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-sequent/'` ;; -psos*) os=-psos @@ -252,12 +249,12 @@ case $basic_machine in | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arceb \ - | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ + | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv6m | armv[78][arm] \ | avr | avr32 \ | ba \ | be32 | be64 \ | bfin \ - | c4x | c8051 | clipper \ + | c4x | c8051 | clipper | csky \ | d10v | d30v | dlx | dsp16xx \ | e2k | epiphany \ | fido | fr30 | frv | ft32 \ @@ -299,7 +296,7 @@ case $basic_machine in | nios | nios2 | nios2eb | nios2el \ | ns16k | ns32k \ | open8 | or1k | or1knd | or32 \ - | pdp10 | pdp11 | pj | pjl \ + | pdp10 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pru \ | pyramid \ @@ -316,7 +313,6 @@ case $basic_machine in | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | visium \ | wasm32 \ - | we32k \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown @@ -337,7 +333,11 @@ case $basic_machine in basic_machine=$basic_machine-unknown os=-none ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65) + ;; + m9s12z | m68hcs12z | hcs12z | s12z) + basic_machine=s12z-unknown + os=-none ;; ms1) basic_machine=mt-unknown @@ -366,7 +366,7 @@ case $basic_machine in ;; # Object if more than one company name word. *-*-*) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. @@ -382,7 +382,7 @@ case $basic_machine in | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ - | c8051-* | clipper-* | craynv-* | cydra-* \ + | c8051-* | clipper-* | craynv-* | csky-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | e2k-* | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ @@ -461,7 +461,7 @@ case $basic_machine in # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) - basic_machine=i386-unknown + basic_machine=i386-pc os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) @@ -495,7 +495,7 @@ case $basic_machine in basic_machine=x86_64-pc ;; amd64-*) - basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=x86_64-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl @@ -540,7 +540,7 @@ case $basic_machine in os=-linux ;; blackfin-*) - basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=bfin-`echo "$basic_machine" | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) @@ -548,13 +548,13 @@ case $basic_machine in os=-cnk ;; c54x-*) - basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=tic54x-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; c55x-*) - basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=tic55x-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; c6x-*) - basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=tic6x-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; c90) basic_machine=c90-cray @@ -643,7 +643,7 @@ case $basic_machine in basic_machine=rs6000-bull os=-bosx ;; - dpx2* | dpx2*-bull) + dpx2*) basic_machine=m68k-bull os=-sysv3 ;; @@ -652,7 +652,7 @@ case $basic_machine in os=$os"spe" ;; e500v[12]-*) - basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` os=$os"spe" ;; ebmon29k) @@ -744,9 +744,6 @@ case $basic_machine in hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; - hppa-next) - os=-nextstep3 - ;; hppaosf) basic_machine=hppa1.1-hp os=-osf @@ -759,26 +756,26 @@ case $basic_machine in basic_machine=i370-ibm ;; i*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; - i386-vsta | vsta) + vsta) basic_machine=i386-unknown os=-vsta ;; @@ -797,19 +794,16 @@ case $basic_machine in os=-sysv ;; leon-*|leon[3-9]-*) - basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'` + basic_machine=sparc-`echo "$basic_machine" | sed 's/-.*//'` ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) - basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=m68k-`echo "$basic_machine" | sed 's/^[^-]*-//'` os=-linux ;; - m88k-omron*) - basic_machine=m88k-omron - ;; magnum | m3230) basic_machine=mips-mips os=-sysv @@ -841,10 +835,10 @@ case $basic_machine in os=-mint ;; mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'` ;; mips3*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k @@ -863,7 +857,7 @@ case $basic_machine in os=-msdos ;; ms1-*) - basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + basic_machine=`echo "$basic_machine" | sed -e 's/ms1-/mt-/'` ;; msys) basic_machine=i686-pc @@ -905,7 +899,7 @@ case $basic_machine in basic_machine=v70-nec os=-sysv ;; - next | m*-next ) + next | m*-next) basic_machine=m68k-next case $os in -nextstep* ) @@ -950,6 +944,9 @@ case $basic_machine in nsr-tandem) basic_machine=nsr-tandem ;; + nsv-tandem) + basic_machine=nsv-tandem + ;; nsx-tandem) basic_machine=nsx-tandem ;; @@ -985,7 +982,7 @@ case $basic_machine in os=-linux ;; parisc-*) - basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=hppa-`echo "$basic_machine" | sed 's/^[^-]*-//'` os=-linux ;; pbd) @@ -1001,7 +998,7 @@ case $basic_machine in basic_machine=i386-pc ;; pc98-*) - basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i386-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc @@ -1016,16 +1013,16 @@ case $basic_machine in basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i586-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentium4-*) - basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i786-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould @@ -1035,23 +1032,23 @@ case $basic_machine in ppc | ppcbe) basic_machine=powerpc-unknown ;; ppc-* | ppcbe-*) - basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=powerpcle-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; - ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ppc64-*) basic_machine=powerpc64-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=powerpc64le-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm @@ -1105,17 +1102,10 @@ case $basic_machine in sequent) basic_machine=i386-sequent ;; - sh) - basic_machine=sh-hitachi - os=-hms - ;; sh5el) basic_machine=sh5le-unknown ;; - sh64) - basic_machine=sh64-unknown - ;; - sparclite-wrs | simso-wrs) + simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; @@ -1134,7 +1124,7 @@ case $basic_machine in os=-sysv4 ;; strongarm-* | thumb-*) - basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=arm-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; sun2) basic_machine=m68000-sun @@ -1248,9 +1238,6 @@ case $basic_machine in basic_machine=a29k-wrs os=-vxworks ;; - wasm32) - basic_machine=wasm32-unknown - ;; w65*) basic_machine=w65-wdc os=-none @@ -1259,6 +1246,9 @@ case $basic_machine in basic_machine=hppa1.1-winbond os=-proelf ;; + x64) + basic_machine=x86_64-pc + ;; xbox) basic_machine=i686-pc os=-mingw32 @@ -1267,20 +1257,12 @@ case $basic_machine in basic_machine=xps100-honeywell ;; xscale-* | xscalee[bl]-*) - basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + basic_machine=`echo "$basic_machine" | sed 's/^xscale/arm/'` ;; ymp) basic_machine=ymp-cray os=-unicos ;; - z8k-*-coff) - basic_machine=z8k-unknown - os=-sim - ;; - z80-*-coff) - basic_machine=z80-unknown - os=-sim - ;; none) basic_machine=none-none os=-none @@ -1309,10 +1291,6 @@ case $basic_machine in vax) basic_machine=vax-dec ;; - pdp10) - # there are many clones, so DEC is not a safe bet - basic_machine=pdp10-unknown - ;; pdp11) basic_machine=pdp11-dec ;; @@ -1322,9 +1300,6 @@ case $basic_machine in sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; - sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) - basic_machine=sparc-sun - ;; cydra) basic_machine=cydra-cydrome ;; @@ -1344,7 +1319,7 @@ case $basic_machine in # Make sure to match an already-canonicalized machine name. ;; *) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2 exit 1 ;; esac @@ -1352,10 +1327,10 @@ esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + basic_machine=`echo "$basic_machine" | sed 's/digital.*/dec/'` ;; *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + basic_machine=`echo "$basic_machine" | sed 's/commodore.*/cbm/'` ;; *) ;; @@ -1366,8 +1341,8 @@ esac if [ x"$os" != x"" ] then case $os in - # First match some system type aliases - # that might get confused with valid system types. + # First match some system type aliases that might get confused + # with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux @@ -1378,18 +1353,19 @@ case $os in -solaris) os=-solaris2 ;; - -svr4*) - os=-sysv4 - ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; - # First accept the basic system types. + # es1800 is here to avoid being matched by es* (a different OS) + -es1800*) + os=-ose + ;; + # Now accept the basic system types. # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. + # Each alternative MUST end in a * to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ @@ -1399,25 +1375,26 @@ case $os in | -aos* | -aros* | -cloudabi* | -sortix* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -hiux* | -knetbsd* | -mirbsd* | -netbsd* \ | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ - | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* | -hcos* \ | -chorusos* | -chorusrdb* | -cegcc* | -glidix* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ - | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -morphos* | -superux* | -rtmk* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ - | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox*) + | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox* | -bme* \ + | -midnightbsd*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) @@ -1434,12 +1411,12 @@ case $os in -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; - -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + -sim | -xray | -os68k* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) - os=`echo $os | sed -e 's|mac|macos|'` + os=`echo "$os" | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc @@ -1448,10 +1425,10 @@ case $os in os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) - os=`echo $os | sed -e 's|sunos5|solaris2|'` + os=`echo "$os" | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) - os=`echo $os | sed -e 's|sunos6|solaris3|'` + os=`echo "$os" | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition @@ -1462,12 +1439,6 @@ case $os in -wince*) os=-wince ;; - -osfrose*) - os=-osfrose - ;; - -osf*) - os=-osf - ;; -utek*) os=-bsd ;; @@ -1492,7 +1463,7 @@ case $os in -nova*) os=-rtmk-nova ;; - -ns2 ) + -ns2) os=-nextstep2 ;; -nsk*) @@ -1514,7 +1485,7 @@ case $os in -oss*) os=-sysv3 ;; - -svr4) + -svr4*) os=-sysv4 ;; -svr3) @@ -1529,24 +1500,28 @@ case $os in -ose*) os=-ose ;; - -es1800*) - os=-ose - ;; - -xenix) - os=-xenix - ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; - -aros*) - os=-aros - ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; + -pikeos*) + # Until real need of OS specific support for + # particular features comes up, bare metal + # configurations are quite functional. + case $basic_machine in + arm*) + os=-eabi + ;; + *) + os=-elf + ;; + esac + ;; -nacl*) ;; -ios) @@ -1556,7 +1531,7 @@ case $os in *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` - echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + echo Invalid configuration \`"$1"\': system \`"$os"\' not recognized 1>&2 exit 1 ;; esac @@ -1652,9 +1627,6 @@ case $basic_machine in *-be) os=-beos ;; - *-haiku) - os=-haiku - ;; *-ibm) os=-aix ;; @@ -1694,7 +1666,7 @@ case $basic_machine in m88k-omron*) os=-luna ;; - *-next ) + *-next) os=-nextstep ;; *-sequent) @@ -1709,9 +1681,6 @@ case $basic_machine in i370-*) os=-mvs ;; - *-next) - os=-nextstep3 - ;; *-gould) os=-sysv ;; @@ -1821,15 +1790,15 @@ case $basic_machine in vendor=stratus ;; esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + basic_machine=`echo "$basic_machine" | sed "s/unknown/$vendor/"` ;; esac -echo $basic_machine$os +echo "$basic_machine$os" exit # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" From webhook-mailer at python.org Wed May 2 02:57:27 2018 From: webhook-mailer at python.org (Matthias Klose) Date: Wed, 02 May 2018 06:57:27 -0000 Subject: [Python-checkins] Enable the verbose build for extension modules with GNU make (GH-6659) (#6662) Message-ID: https://github.com/python/cpython/commit/3c5d3f519d092ea845fa6673df1222fdd668430b commit: 3c5d3f519d092ea845fa6673df1222fdd668430b branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Matthias Klose date: 2018-05-02T08:57:24+02:00 summary: Enable the verbose build for extension modules with GNU make (GH-6659) (#6662) (cherry picked from commit 10f715d71218ece737f990fa55027b8e1120cc3a) Co-authored-by: Matthias Klose files: A Misc/NEWS.d/next/Build/2018-04-30-17-36-46.bpo-33394._Vdi4t.rst M Makefile.pre.in diff --git a/Makefile.pre.in b/Makefile.pre.in index 3a7324f50963..4c23c0e4114a 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -601,11 +601,15 @@ $(srcdir)/Modules/_blake2/blake2s_impl.c: $(srcdir)/Modules/_blake2/blake2b_impl # Under GNU make, MAKEFLAGS are sorted and normalized; the 's' for # -s, --silent or --quiet is always the first char. # Under BSD make, MAKEFLAGS might be " -s -v x=y". +# Ignore macros passed by GNU make, passed after -- sharedmods: $(BUILDPYTHON) pybuilddir.txt Modules/_math.o - @case "$$MAKEFLAGS" in \ + @case "`echo X $$MAKEFLAGS | sed 's/^X //;s/ -- .*//'`" in \ *\ -s*|s*) quiet="-q";; \ *) quiet="";; \ esac; \ + echo "$(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \ + _TCLTK_INCLUDES='$(TCLTK_INCLUDES)' _TCLTK_LIBS='$(TCLTK_LIBS)' \ + $(PYTHON_FOR_BUILD) $(srcdir)/setup.py $$quiet build"; \ $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \ _TCLTK_INCLUDES='$(TCLTK_INCLUDES)' _TCLTK_LIBS='$(TCLTK_LIBS)' \ $(PYTHON_FOR_BUILD) $(srcdir)/setup.py $$quiet build diff --git a/Misc/NEWS.d/next/Build/2018-04-30-17-36-46.bpo-33394._Vdi4t.rst b/Misc/NEWS.d/next/Build/2018-04-30-17-36-46.bpo-33394._Vdi4t.rst new file mode 100644 index 000000000000..b25fbb02c406 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2018-04-30-17-36-46.bpo-33394._Vdi4t.rst @@ -0,0 +1,2 @@ +Enable the verbose build for extension modules, when GNU make is passed +macros on the command line. From webhook-mailer at python.org Wed May 2 04:54:56 2018 From: webhook-mailer at python.org (Ned Deily) Date: Wed, 02 May 2018 08:54:56 -0000 Subject: [Python-checkins] 3.7.0b4 Message-ID: https://github.com/python/cpython/commit/eb96c376994cb7c6c2e8a4967782d1c0e2a96135 commit: eb96c376994cb7c6c2e8a4967782d1c0e2a96135 branch: 3.7 author: Ned Deily committer: Ned Deily date: 2018-05-02T03:41:45-04:00 summary: 3.7.0b4 files: A Misc/NEWS.d/3.7.0b4.rst D Misc/NEWS.d/next/Build/2018-03-30-14-55-48.bpo-33182.CePczb.rst D Misc/NEWS.d/next/Build/2018-04-17-00-38-19.bpo-32232.o7G_UO.rst D Misc/NEWS.d/next/Build/2018-04-30-16-53-00.bpo-33377.QBh6vP.rst D Misc/NEWS.d/next/Build/2018-04-30-17-19-37.bpo-33393.HkVCqI.rst D Misc/NEWS.d/next/Build/2018-04-30-17-36-46.bpo-33394._Vdi4t.rst D Misc/NEWS.d/next/Core and Builtins/2018-04-02-09-32-40.bpo-33199.TPnxQu.rst D Misc/NEWS.d/next/Core and Builtins/2018-04-03-00-30-25.bpo-29922.CdLuMl.rst D Misc/NEWS.d/next/Core and Builtins/2018-04-03-00-58-41.bpo-33205.lk2F3r.rst D Misc/NEWS.d/next/Core and Builtins/2018-04-05-22-20-44.bpo-33231.3Jmo0q.rst D Misc/NEWS.d/next/Core and Builtins/2018-04-19-08-30-07.bpo-33312.mDe2iL.rst D Misc/NEWS.d/next/Core and Builtins/2018-04-24-22-31-04.bpo-33128.g2yLuf.rst D Misc/NEWS.d/next/Core and Builtins/2018-04-26-22-48-28.bpo-33363.8RCnN2.rst D Misc/NEWS.d/next/Documentation/2017-12-22-17-29-37.bpo-32337.eZe-ID.rst D Misc/NEWS.d/next/Documentation/2018-01-13-20-30-53.bpo-8243.s98r28.rst D Misc/NEWS.d/next/Documentation/2018-04-01-14-30-36.bpo-33195.dRS-XX.rst D Misc/NEWS.d/next/Documentation/2018-04-01-21-03-41.bpo-33201.aa8Lkl.rst D Misc/NEWS.d/next/Documentation/2018-04-20-14-09-36.bpo-33276.rA1z_3.rst D Misc/NEWS.d/next/Documentation/2018-04-29-04-02-18.bpo-33378.-anAHN.rst D Misc/NEWS.d/next/IDLE/2018-04-02-00-28-13.bpo-33204.NBsuIv.rst D Misc/NEWS.d/next/IDLE/2018-04-29-16-13-02.bpo-21474.bglg-F.rst D Misc/NEWS.d/next/Library/2017-10-31.bpo-31908.g4xh8x.rst D Misc/NEWS.d/next/Library/2018-03-18-16-48-23.bpo-33097.Yl4gI2.rst D Misc/NEWS.d/next/Library/2018-03-29-04-32-25.bpo-33175._zs1yM.rst D Misc/NEWS.d/next/Library/2018-04-01-19-21-04.bpo-20104.-AKcGa.rst D Misc/NEWS.d/next/Library/2018-04-03-10-37-13.bpo-33209.9sGWE_.rst D Misc/NEWS.d/next/Library/2018-04-04-23-41-30.bpo-33224.pyR0jB.rst D Misc/NEWS.d/next/Library/2018-04-05-11-09-45.bpo-33203.Hje9Py.rst D Misc/NEWS.d/next/Library/2018-04-05-13-36-09.bpo-33217.FfOKDI.rst D Misc/NEWS.d/next/Library/2018-04-06-14-56-26.bpo-33169.ByhDqb.rst D Misc/NEWS.d/next/Library/2018-04-08-22-54-07.bpo-33185.Id-Ba9.rst D Misc/NEWS.d/next/Library/2018-04-10-20-57-14.bpo-33256.ndHkqu.rst D Misc/NEWS.d/next/Library/2018-04-13-15-14-47.bpo-33254.DS4KFK.rst D Misc/NEWS.d/next/Library/2018-04-16-08-42-03.bpo-11594.QLo4vv.rst D Misc/NEWS.d/next/Library/2018-04-16-15-59-21.bpo-33266.w2PAm-.rst D Misc/NEWS.d/next/Library/2018-04-18-19-12-25.bpo-33308.fW75xi.rst D Misc/NEWS.d/next/Library/2018-04-20-10-43-17.bpo-33131.L2E977.rst D Misc/NEWS.d/next/Library/2018-04-21-00-24-08.bpo-991266.h93TP_.rst D Misc/NEWS.d/next/Library/2018-04-23-13-21-39.bpo-33329.lQ-Eod.rst D Misc/NEWS.d/next/Library/2018-04-29-11-15-38.bpo-33383.g32YWn.rst D Misc/NEWS.d/next/Library/2018-05-01-22-35-50.bpo-33281.d4jOt4.rst D Misc/NEWS.d/next/Tests/2018-04-27-11-46-35.bpo-33358._OcR59.rst D Misc/NEWS.d/next/Tools-Demos/2017-09-26-10-11-21.bpo-31583.TM90_H.rst D Misc/NEWS.d/next/Tools-Demos/2018-03-16-17-25-05.bpo-29673.m8QtaW.rst D Misc/NEWS.d/next/Tools-Demos/2018-03-26-18-54-24.bpo-31920.u_WKsT.rst D Misc/NEWS.d/next/Tools-Demos/2018-04-03-18-10-00.bpo-33189.QrXR00.rst D Misc/NEWS.d/next/Windows/2018-04-13-11-28-55.bpo-33184.7YhqQE.rst D Misc/NEWS.d/next/macOS/2018-04-07-00-51-34.bpo-33184.3j208P.rst M Include/patchlevel.h M Lib/pydoc_data/topics.py M README.rst M configure diff --git a/Include/patchlevel.h b/Include/patchlevel.h index 70d86c9f8529..c01b8f98fe51 100644 --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -20,10 +20,10 @@ #define PY_MINOR_VERSION 7 #define PY_MICRO_VERSION 0 #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_BETA -#define PY_RELEASE_SERIAL 3 +#define PY_RELEASE_SERIAL 4 /* Version as a string */ -#define PY_VERSION "3.7.0b3+" +#define PY_VERSION "3.7.0b4" /*--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 abface57b092..e138d49821aa 100644 --- a/Lib/pydoc_data/topics.py +++ b/Lib/pydoc_data/topics.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Autogenerated by Sphinx on Thu Mar 29 07:53:04 2018 +# Autogenerated by Sphinx on Wed May 2 03:29:32 2018 topics = {'assert': 'The "assert" statement\n' '**********************\n' '\n' @@ -106,7 +106,7 @@ ' corresponding targets.\n' '\n' ' * If the target list contains one target prefixed with an\n' - ' asterisk, called a "starred" target: The object must be ' + ' asterisk, called a ?starred? target: The object must be ' 'an\n' ' iterable with at least as many items as there are targets ' 'in the\n' @@ -203,10 +203,10 @@ ' If the primary is a mutable sequence object (such as a ' 'list), the\n' ' subscript must yield an integer. If it is negative, the ' - "sequence's\n" + 'sequence?s\n' ' length is added to it. The resulting value must be a ' 'nonnegative\n' - " integer less than the sequence's length, and the sequence is " + ' integer less than the sequence?s length, and the sequence is ' 'asked\n' ' to assign the assigned object to its item with that index. ' 'If the\n' @@ -216,7 +216,7 @@ '\n' ' If the primary is a mapping object (such as a dictionary), ' 'the\n' - " subscript must have a type compatible with the mapping's key " + ' subscript must have a type compatible with the mapping?s key ' 'type,\n' ' and the mapping is then asked to create a key/datum pair ' 'which maps\n' @@ -239,12 +239,12 @@ 'expressions are\n' ' evaluated, insofar they are present; defaults are zero and ' 'the\n' - " sequence's length. The bounds should evaluate to integers. " + ' sequence?s length. The bounds should evaluate to integers. ' 'If\n' - " either bound is negative, the sequence's length is added to " + ' either bound is negative, the sequence?s length is added to ' 'it. The\n' ' resulting bounds are clipped to lie between zero and the ' - "sequence's\n" + 'sequence?s\n' ' length, inclusive. Finally, the sequence object is asked to ' 'replace\n' ' the slice with the items of the assigned sequence. The ' @@ -265,7 +265,7 @@ '\n' 'Although the definition of assignment implies that overlaps ' 'between\n' - "the left-hand side and the right-hand side are 'simultaneous' " + 'the left-hand side and the right-hand side are ?simultaneous? ' '(for\n' 'example "a, b = b, a" swaps two variables), overlaps *within* ' 'the\n' @@ -464,7 +464,7 @@ '\n' 'All literals correspond to immutable data types, and hence ' 'the\n' - "object's identity is less important than its value. " + 'object?s identity is less important than its value. ' 'Multiple\n' 'evaluations of literals with the same value (either the ' 'same\n' @@ -626,10 +626,10 @@ 'Note: Defining module "__getattr__" and setting module ' '"__class__"\n' ' only affect lookups made using the attribute access ' - 'syntax --\n' + 'syntax ?\n' ' directly accessing the module globals (whether by code ' 'within the\n' - " module, or via a reference to the module's globals " + ' module, or via a reference to the module?s globals ' 'dictionary) is\n' ' unaffected.\n' '\n' @@ -654,13 +654,12 @@ 'containing the method (a so-called *descriptor* class) ' 'appears in an\n' '*owner* class (the descriptor must be in either the ' - "owner's class\n" + 'owner?s class\n' 'dictionary or in the class dictionary for one of its ' 'parents). In the\n' - 'examples below, "the attribute" refers to the attribute ' + 'examples below, ?the attribute? refers to the attribute ' 'whose name is\n' - "the key of the property in the owner class' " - '"__dict__".\n' + 'the key of the property in the owner class? "__dict__".\n' '\n' 'object.__get__(self, instance, owner)\n' '\n' @@ -717,8 +716,8 @@ '====================\n' '\n' 'In general, a descriptor is an object attribute with ' - '"binding\n' - 'behavior", one whose attribute access has been ' + '?binding\n' + 'behavior?, one whose attribute access has been ' 'overridden by methods\n' 'in the descriptor protocol: "__get__()", "__set__()", ' 'and\n' @@ -728,7 +727,7 @@ '\n' 'The default behavior for attribute access is to get, ' 'set, or delete\n' - "the attribute from an object's dictionary. For instance, " + 'the attribute from an object?s dictionary. For instance, ' '"a.x" has a\n' 'lookup chain starting with "a.__dict__[\'x\']", then\n' '"type(a).__dict__[\'x\']", and continuing through the ' @@ -783,7 +782,7 @@ 'does not define "__get__()", then accessing the ' 'attribute will return\n' 'the descriptor object itself unless there is a value in ' - "the object's\n" + 'the object?s\n' 'instance dictionary. If the descriptor defines ' '"__set__()" and/or\n' '"__delete__()", it is a data descriptor; if it defines ' @@ -904,7 +903,7 @@ '\n' '* Nonempty *__slots__* does not work for classes derived ' 'from\n' - ' "variable-length" built-in types such as "int", ' + ' ?variable-length? built-in types such as "int", ' '"bytes" and "tuple".\n' '\n' '* Any non-string iterable may be assigned to ' @@ -1056,7 +1055,7 @@ 'while\n' 'floor division of integers results in an integer; the result is ' 'that\n' - "of mathematical division with the 'floor' function applied to the\n" + 'of mathematical division with the ?floor? function applied to the\n' 'result. Division by zero raises the "ZeroDivisionError" ' 'exception.\n' '\n' @@ -1132,10 +1131,10 @@ '************\n' '\n' 'Code objects are used by the implementation to ' - 'represent "pseudo-\n' - 'compiled" executable Python code such as a function ' + 'represent ?pseudo-\n' + 'compiled? executable Python code such as a function ' 'body. They differ\n' - "from function objects because they don't contain a " + 'from function objects because they don?t contain a ' 'reference to their\n' 'global execution environment. Code objects are ' 'returned by the built-\n' @@ -1166,7 +1165,7 @@ 'bltin-null-object': 'The Null Object\n' '***************\n' '\n' - "This object is returned by functions that don't " + 'This object is returned by functions that don?t ' 'explicitly return a\n' 'value. It supports no special operations. There is ' 'exactly one null\n' @@ -1179,7 +1178,7 @@ '************\n' '\n' 'Type objects represent the various object types. An ' - "object's type is\n" + 'object?s type is\n' 'accessed by the built-in function "type()". There are ' 'no special\n' 'operations on types. The standard module "types" ' @@ -1262,7 +1261,7 @@ '\n' 'object.__call__(self[, args...])\n' '\n' - ' Called when the instance is "called" as a function; if ' + ' Called when the instance is ?called? as a function; if ' 'this method\n' ' is defined, "x(arg1, arg2, ...)" is a shorthand for\n' ' "x.__call__(arg1, arg2, ...)".\n', @@ -1322,7 +1321,7 @@ 'values are calculated, once, when the function is defined; thus, a\n' 'mutable object such as a list or dictionary used as default value ' 'will\n' - "be shared by all calls that don't specify an argument value for " + 'be shared by all calls that don?t specify an argument value for ' 'the\n' 'corresponding slot; this should usually be avoided.) If there are ' 'any\n' @@ -1335,7 +1334,7 @@ '**CPython implementation detail:** An implementation may provide\n' 'built-in functions whose positional parameters do not have names, ' 'even\n' - "if they are 'named' for the purpose of documentation, and which\n" + 'if they are ?named? for the purpose of documentation, and which\n' 'therefore cannot be supplied by keyword. In CPython, this is the ' 'case\n' 'for functions implemented in C that use "PyArg_ParseTuple()" to ' @@ -1367,16 +1366,17 @@ 'must evaluate to an *iterable*. Elements from these iterables are\n' 'treated as if they were additional positional arguments. For the ' 'call\n' - '"f(x1, x2, *y, x3, x4)", if *y* evaluates to a sequence *y1*, ...,\n' - '*yM*, this is equivalent to a call with M+4 positional arguments ' - '*x1*,\n' - '*x2*, *y1*, ..., *yM*, *x3*, *x4*.\n' + '"f(x1, x2, *y, x3, x4)", if *y* evaluates to a sequence *y1*, ?, ' + '*yM*,\n' + 'this is equivalent to a call with M+4 positional arguments *x1*, ' + '*x2*,\n' + '*y1*, ?, *yM*, *x3*, *x4*.\n' '\n' 'A consequence of this is that although the "*expression" syntax ' 'may\n' 'appear *after* explicit keyword arguments, it is processed ' '*before*\n' - 'the keyword arguments (and any "**expression" arguments -- see ' + 'the keyword arguments (and any "**expression" arguments ? see ' 'below).\n' 'So:\n' '\n' @@ -1423,7 +1423,7 @@ 'exception. How this value is computed depends on the type of the\n' 'callable object.\n' '\n' - 'If it is---\n' + 'If it is?\n' '\n' 'a user-defined function:\n' ' The code block for the function is executed, passing it the\n' @@ -1482,10 +1482,10 @@ ' class Foo(object):\n' ' pass\n' '\n' - "The class's suite is then executed in a new execution frame (see\n" + 'The class?s suite is then executed in a new execution frame (see\n' 'Naming and binding), using a newly created local namespace and the\n' 'original global namespace. (Usually, the suite contains mostly\n' - "function definitions.) When the class's suite finishes execution, " + 'function definitions.) When the class?s suite finishes execution, ' 'its\n' 'execution frame is discarded but its local namespace is saved. [4] ' 'A\n' @@ -1497,7 +1497,7 @@ 'namespace.\n' '\n' 'The order in which attributes are defined in the class body is\n' - 'preserved in the new class\'s "__dict__". Note that this is ' + 'preserved in the new class?s "__dict__". Note that this is ' 'reliable\n' 'only right after the class is created and only for classes that ' 'were\n' @@ -1521,13 +1521,13 @@ 'for\n' 'function decorators. The result is then bound to the class name.\n' '\n' - "**Programmer's note:** Variables defined in the class definition " + '**Programmer?s note:** Variables defined in the class definition ' 'are\n' 'class attributes; they are shared by instances. Instance ' 'attributes\n' 'can be set in a method with "self.name = value". Both class and\n' 'instance attributes are accessible through the notation ' - '""self.name"",\n' + '?"self.name"?,\n' 'and an instance attribute hides a class attribute with the same ' 'name\n' 'when accessed in this way. Class attributes can be used as ' @@ -1564,15 +1564,15 @@ 'y" is\n' 'found to be false).\n' '\n' - 'Formally, if *a*, *b*, *c*, ..., *y*, *z* are expressions and ' + 'Formally, if *a*, *b*, *c*, ?, *y*, *z* are expressions and ' '*op1*,\n' - '*op2*, ..., *opN* are comparison operators, then "a op1 b op2 ' - 'c ... y\n' + '*op2*, ?, *opN* are comparison operators, then "a op1 b op2 c ' + '... y\n' 'opN z" is equivalent to "a op1 b and b op2 c and ... y opN ' 'z", except\n' 'that each expression is evaluated at most once.\n' '\n' - 'Note that "a op1 b op2 c" doesn\'t imply any kind of ' + 'Note that "a op1 b op2 c" doesn?t imply any kind of ' 'comparison between\n' '*a* and *c*, so that, e.g., "x < y > z" is perfectly legal ' '(though\n' @@ -1593,7 +1593,7 @@ 'rather\n' 'abstract notion in Python: For example, there is no canonical ' 'access\n' - "method for an object's value. Also, there is no requirement " + 'method for an object?s value. Also, there is no requirement ' 'that the\n' 'value of an object should be constructed in a particular way, ' 'e.g.\n' @@ -1647,7 +1647,7 @@ 'most\n' 'important built-in types.\n' '\n' - '* Numbers of built-in numeric types (Numeric Types --- int, ' + '* Numbers of built-in numeric types (Numeric Types ? int, ' 'float,\n' ' complex) and of the standard library types ' '"fractions.Fraction" and\n' @@ -1934,9 +1934,9 @@ 'compound\n' 'statements.\n' '\n' - "A compound statement consists of one or more 'clauses.' A " + 'A compound statement consists of one or more ?clauses.? A ' 'clause\n' - "consists of a header and a 'suite.' The clause headers of a\n" + 'consists of a header and a ?suite.? The clause headers of a\n' 'particular compound statement are all at the same indentation ' 'level.\n' 'Each clause header begins with a uniquely identifying keyword ' @@ -1944,12 +1944,12 @@ 'with a colon. A suite is a group of statements controlled by a\n' 'clause. A suite can be one or more semicolon-separated simple\n' 'statements on the same line as the header, following the ' - "header's\n" + 'header?s\n' 'colon, or it can be one or more indented statements on ' 'subsequent\n' 'lines. Only the latter form of a suite can contain nested ' 'compound\n' - "statements; the following is illegal, mostly because it wouldn't " + 'statements; the following is illegal, mostly because it wouldn?t ' 'be\n' 'clear to which "if" clause a following "else" clause would ' 'belong:\n' @@ -1986,7 +1986,7 @@ '"DEDENT". Also note that optional continuation clauses always ' 'begin\n' 'with a keyword that cannot start a statement, thus there are no\n' - 'ambiguities (the \'dangling "else"\' problem is solved in Python ' + 'ambiguities (the ?dangling "else"? problem is solved in Python ' 'by\n' 'requiring nested "if" statements to be indented).\n' '\n' @@ -2037,7 +2037,7 @@ '\n' 'A "break" statement executed in the first suite terminates the ' 'loop\n' - 'without executing the "else" clause\'s suite. A "continue" ' + 'without executing the "else" clause?s suite. A "continue" ' 'statement\n' 'executed in the first suite skips the rest of the suite and goes ' 'back\n' @@ -2076,7 +2076,7 @@ '\n' 'A "break" statement executed in the first suite terminates the ' 'loop\n' - 'without executing the "else" clause\'s suite. A "continue" ' + 'without executing the "else" clause?s suite. A "continue" ' 'statement\n' 'executed in the first suite skips the rest of the suite and ' 'continues\n' @@ -2103,7 +2103,7 @@ 'to at\n' 'all by the loop. Hint: the built-in function "range()" returns ' 'an\n' - "iterator of integers suitable to emulate the effect of Pascal's " + 'iterator of integers suitable to emulate the effect of Pascal?s ' '"for i\n' ':= a to b do"; e.g., "list(range(3))" returns the list "[0, 1, ' '2]".\n' @@ -2165,7 +2165,7 @@ 'expression\n' 'is evaluated, and the clause matches the exception if the ' 'resulting\n' - 'object is "compatible" with the exception. An object is ' + 'object is ?compatible? with the exception. An object is ' 'compatible\n' 'with an exception if it is the class or a base class of the ' 'exception\n' @@ -2192,7 +2192,7 @@ 'assigned to\n' 'the target specified after the "as" keyword in that except ' 'clause, if\n' - "present, and the except clause's suite is executed. All except\n" + 'present, and the except clause?s suite is executed. All except\n' 'clauses must have an executable block. When the end of this ' 'block is\n' 'reached, execution continues normally after the entire try ' @@ -2228,7 +2228,7 @@ 'alive\n' 'until the next garbage collection occurs.\n' '\n' - "Before an except clause's suite is executed, details about the\n" + 'Before an except clause?s suite is executed, details about the\n' 'exception are stored in the "sys" module and can be accessed ' 'via\n' '"sys.exc_info()". "sys.exc_info()" returns a 3-tuple consisting ' @@ -2249,8 +2249,8 @@ 'are\n' 'not handled by the preceding "except" clauses.\n' '\n' - 'If "finally" is present, it specifies a \'cleanup\' handler. ' - 'The "try"\n' + 'If "finally" is present, it specifies a ?cleanup? handler. The ' + '"try"\n' 'clause is executed, including any "except" and "else" clauses. ' 'If an\n' 'exception occurs in any of the clauses and is not handled, the\n' @@ -2281,13 +2281,12 @@ '\n' 'When a "return", "break" or "continue" statement is executed in ' 'the\n' - '"try" suite of a "try"..."finally" statement, the "finally" ' - 'clause is\n' - 'also executed \'on the way out.\' A "continue" statement is ' + '"try" suite of a "try"?"finally" statement, the "finally" clause ' + 'is\n' + 'also executed ?on the way out.? A "continue" statement is ' 'illegal in\n' 'the "finally" clause. (The reason is a problem with the current\n' - 'implementation --- this restriction may be lifted in the ' - 'future).\n' + 'implementation ? this restriction may be lifted in the future).\n' '\n' 'The return value of a function is determined by the last ' '"return"\n' @@ -2319,14 +2318,14 @@ 'with\n' 'methods defined by a context manager (see section With ' 'Statement\n' - 'Context Managers). This allows common ' - '"try"..."except"..."finally"\n' - 'usage patterns to be encapsulated for convenient reuse.\n' + 'Context Managers). This allows common "try"?"except"?"finally" ' + 'usage\n' + 'patterns to be encapsulated for convenient reuse.\n' '\n' ' with_stmt ::= "with" with_item ("," with_item)* ":" suite\n' ' with_item ::= expression ["as" target]\n' '\n' - 'The execution of the "with" statement with one "item" proceeds ' + 'The execution of the "with" statement with one ?item? proceeds ' 'as\n' 'follows:\n' '\n' @@ -2334,9 +2333,9 @@ '"with_item")\n' ' is evaluated to obtain a context manager.\n' '\n' - '2. The context manager\'s "__exit__()" is loaded for later use.\n' + '2. The context manager?s "__exit__()" is loaded for later use.\n' '\n' - '3. The context manager\'s "__enter__()" method is invoked.\n' + '3. The context manager?s "__enter__()" method is invoked.\n' '\n' '4. If a target was included in the "with" statement, the return\n' ' value from "__enter__()" is assigned to it.\n' @@ -2353,8 +2352,7 @@ '\n' '5. The suite is executed.\n' '\n' - '6. The context manager\'s "__exit__()" method is invoked. If ' - 'an\n' + '6. The context manager?s "__exit__()" method is invoked. If an\n' ' exception caused the suite to be exited, its type, value, ' 'and\n' ' traceback are passed as arguments to "__exit__()". Otherwise, ' @@ -2394,7 +2392,7 @@ '\n' 'See also:\n' '\n' - ' **PEP 343** - The "with" statement\n' + ' **PEP 343** - The ?with? statement\n' ' The specification, background, and examples for the Python ' '"with"\n' ' statement.\n' @@ -2463,25 +2461,24 @@ '"func".\n' '\n' 'When one or more *parameters* have the form *parameter* "="\n' - '*expression*, the function is said to have "default parameter ' - 'values."\n' + '*expression*, the function is said to have ?default parameter ' + 'values.?\n' 'For a parameter with a default value, the corresponding ' '*argument* may\n' - "be omitted from a call, in which case the parameter's default " + 'be omitted from a call, in which case the parameter?s default ' 'value is\n' 'substituted. If a parameter has a default value, all following\n' - 'parameters up until the ""*"" must also have a default value --- ' - 'this\n' - 'is a syntactic restriction that is not expressed by the ' - 'grammar.\n' + 'parameters up until the ?"*"? must also have a default value ? ' + 'this is\n' + 'a syntactic restriction that is not expressed by the grammar.\n' '\n' '**Default parameter values are evaluated from left to right when ' 'the\n' 'function definition is executed.** This means that the ' 'expression is\n' 'evaluated once, when the function is defined, and that the same ' - '"pre-\n' - 'computed" value is used for each call. This is especially ' + '?pre-\n' + 'computed? value is used for each call. This is especially ' 'important\n' 'to understand when a default parameter is a mutable object, such ' 'as a\n' @@ -2507,26 +2504,26 @@ 'mentioned in\n' 'the parameter list, either from position arguments, from ' 'keyword\n' - 'arguments, or from default values. If the form ""*identifier"" ' + 'arguments, or from default values. If the form ?"*identifier"? ' 'is\n' 'present, it is initialized to a tuple receiving any excess ' 'positional\n' 'parameters, defaulting to the empty tuple. If the form\n' - '""**identifier"" is present, it is initialized to a new ordered\n' + '?"**identifier"? is present, it is initialized to a new ordered\n' 'mapping receiving any excess keyword arguments, defaulting to a ' 'new\n' - 'empty mapping of the same type. Parameters after ""*"" or\n' - '""*identifier"" are keyword-only parameters and may only be ' + 'empty mapping of the same type. Parameters after ?"*"? or\n' + '?"*identifier"? are keyword-only parameters and may only be ' 'passed\n' 'used keyword arguments.\n' '\n' - 'Parameters may have annotations of the form "": expression"" ' + 'Parameters may have annotations of the form ?": expression"? ' 'following\n' 'the parameter name. Any parameter may have an annotation even ' 'those\n' 'of the form "*identifier" or "**identifier". Functions may ' 'have\n' - '"return" annotation of the form ""-> expression"" after the ' + '?return? annotation of the form ?"-> expression"? after the ' 'parameter\n' 'list. These annotations can be any valid Python expression. ' 'The\n' @@ -2534,8 +2531,7 @@ 'function.\n' 'The annotation values are available as values of a dictionary ' 'keyed by\n' - 'the parameters\' names in the "__annotations__" attribute of ' - 'the\n' + 'the parameters? names in the "__annotations__" attribute of the\n' 'function object. If the "annotations" import from "__future__" ' 'is\n' 'used, annotations are preserved as strings at runtime which ' @@ -2553,16 +2549,16 @@ 'lambda\n' 'expression is merely a shorthand for a simplified function ' 'definition;\n' - 'a function defined in a ""def"" statement can be passed around ' + 'a function defined in a ?"def"? statement can be passed around ' 'or\n' 'assigned to another name just like a function defined by a ' 'lambda\n' - 'expression. The ""def"" form is actually more powerful since ' + 'expression. The ?"def"? form is actually more powerful since ' 'it\n' 'allows the execution of multiple statements and annotations.\n' '\n' - "**Programmer's note:** Functions are first-class objects. A " - '""def""\n' + '**Programmer?s note:** Functions are first-class objects. A ' + '?"def"?\n' 'statement executed inside a function definition defines a local\n' 'function that can be returned or passed around. Free variables ' 'used\n' @@ -2621,12 +2617,12 @@ ' class Foo(object):\n' ' pass\n' '\n' - "The class's suite is then executed in a new execution frame " + 'The class?s suite is then executed in a new execution frame ' '(see\n' 'Naming and binding), using a newly created local namespace and ' 'the\n' 'original global namespace. (Usually, the suite contains mostly\n' - "function definitions.) When the class's suite finishes " + 'function definitions.) When the class?s suite finishes ' 'execution, its\n' 'execution frame is discarded but its local namespace is saved. ' '[4] A\n' @@ -2639,7 +2635,7 @@ 'namespace.\n' '\n' 'The order in which attributes are defined in the class body is\n' - 'preserved in the new class\'s "__dict__". Note that this is ' + 'preserved in the new class?s "__dict__". Note that this is ' 'reliable\n' 'only right after the class is created and only for classes that ' 'were\n' @@ -2664,14 +2660,14 @@ 'function decorators. The result is then bound to the class ' 'name.\n' '\n' - "**Programmer's note:** Variables defined in the class definition " + '**Programmer?s note:** Variables defined in the class definition ' 'are\n' 'class attributes; they are shared by instances. Instance ' 'attributes\n' 'can be set in a method with "self.name = value". Both class ' 'and\n' 'instance attributes are accessible through the notation ' - '""self.name"",\n' + '?"self.name"?,\n' 'and an instance attribute hides a class attribute with the same ' 'name\n' 'when accessed in this way. Class attributes can be used as ' @@ -2807,20 +2803,19 @@ ' exception. That new exception causes the old one to be ' 'lost.\n' '\n' - '[2] Currently, control "flows off the end" except in the case ' + '[2] Currently, control ?flows off the end? except in the case ' 'of\n' ' an exception or the execution of a "return", "continue", or\n' ' "break" statement.\n' '\n' '[3] A string literal appearing as the first statement in the\n' - ' function body is transformed into the function\'s "__doc__"\n' - " attribute and therefore the function's *docstring*.\n" + ' function body is transformed into the function?s "__doc__"\n' + ' attribute and therefore the function?s *docstring*.\n' '\n' '[4] A string literal appearing as the first statement in the ' 'class\n' - ' body is transformed into the namespace\'s "__doc__" item ' - 'and\n' - " therefore the class's *docstring*.\n", + ' body is transformed into the namespace?s "__doc__" item and\n' + ' therefore the class?s *docstring*.\n', 'context-managers': 'With Statement Context Managers\n' '*******************************\n' '\n' @@ -2850,7 +2845,7 @@ '\n' ' Enter the runtime context related to this object. The ' '"with"\n' - " statement will bind this method's return value to the " + ' statement will bind this method?s return value to the ' 'target(s)\n' ' specified in the "as" clause of the statement, if ' 'any.\n' @@ -2875,11 +2870,11 @@ '\n' ' Note that "__exit__()" methods should not reraise the ' 'passed-in\n' - " exception; this is the caller's responsibility.\n" + ' exception; this is the caller?s responsibility.\n' '\n' 'See also:\n' '\n' - ' **PEP 343** - The "with" statement\n' + ' **PEP 343** - The ?with? statement\n' ' The specification, background, and examples for the ' 'Python "with"\n' ' statement.\n', @@ -2905,7 +2900,7 @@ '\n' 'When a description of an arithmetic operator below uses the ' 'phrase\n' - '"the numeric arguments are converted to a common type," this ' + '?the numeric arguments are converted to a common type,? this ' 'means\n' 'that the operator implementation for built-in types works as ' 'follows:\n' @@ -2923,7 +2918,7 @@ '\n' 'Some additional rules apply for certain operators (e.g., a ' 'string as a\n' - "left argument to the '%' operator). Extensions must define " + 'left argument to the ?%? operator). Extensions must define ' 'their own\n' 'conversion behavior.\n', 'customization': 'Basic customization\n' @@ -2947,7 +2942,7 @@ '\n' ' Typical implementations create a new instance of the ' 'class by\n' - ' invoking the superclass\'s "__new__()" method using\n' + ' invoking the superclass?s "__new__()" method using\n' ' "super().__new__(cls[, ...])" with appropriate arguments ' 'and then\n' ' modifying the newly-created instance as necessary before ' @@ -2956,7 +2951,7 @@ '\n' ' If "__new__()" returns an instance of *cls*, then the ' 'new\n' - ' instance\'s "__init__()" method will be invoked like\n' + ' instance?s "__init__()" method will be invoked like\n' ' "__init__(self[, ...])", where *self* is the new ' 'instance and the\n' ' remaining arguments are the same as were passed to ' @@ -2964,7 +2959,7 @@ '\n' ' If "__new__()" does not return an instance of *cls*, ' 'then the new\n' - ' instance\'s "__init__()" method will not be invoked.\n' + ' instance?s "__init__()" method will not be invoked.\n' '\n' ' "__new__()" is intended mainly to allow subclasses of ' 'immutable\n' @@ -2982,7 +2977,7 @@ 'those\n' ' passed to the class constructor expression. If a base ' 'class has an\n' - ' "__init__()" method, the derived class\'s "__init__()" ' + ' "__init__()" method, the derived class?s "__init__()" ' 'method, if\n' ' any, must explicitly call it to ensure proper ' 'initialization of the\n' @@ -3003,7 +2998,7 @@ 'is also\n' ' called a finalizer or (improperly) a destructor. If a ' 'base class\n' - ' has a "__del__()" method, the derived class\'s ' + ' has a "__del__()" method, the derived class?s ' '"__del__()" method,\n' ' if any, must explicitly call it to ensure proper ' 'deletion of the\n' @@ -3024,11 +3019,11 @@ 'for\n' ' objects that still exist when the interpreter exits.\n' '\n' - ' Note: "del x" doesn\'t directly call "x.__del__()" --- ' - 'the former\n' + ' Note: "del x" doesn?t directly call "x.__del__()" ? the ' + 'former\n' ' decrements the reference count for "x" by one, and the ' 'latter is\n' - ' only called when "x"\'s reference count reaches zero.\n' + ' only called when "x"?s reference count reaches zero.\n' '\n' ' **CPython implementation detail:** It is possible for a ' 'reference\n' @@ -3040,7 +3035,7 @@ 'reference\n' ' cycles is when an exception has been caught in a local ' 'variable.\n' - " The frame's locals then reference the exception, which " + ' The frame?s locals then reference the exception, which ' 'references\n' ' its own traceback, which references the locals of all ' 'frames caught\n' @@ -3087,7 +3082,7 @@ 'object.__repr__(self)\n' '\n' ' Called by the "repr()" built-in function to compute the ' - '"official"\n' + '?official?\n' ' string representation of an object. If at all possible, ' 'this\n' ' should look like a valid Python expression that could be ' @@ -3101,7 +3096,7 @@ ' value must be a string object. If a class defines ' '"__repr__()" but\n' ' not "__str__()", then "__repr__()" is also used when an ' - '"informal"\n' + '?informal?\n' ' string representation of instances of that class is ' 'required.\n' '\n' @@ -3113,7 +3108,7 @@ '\n' ' Called by "str(object)" and the built-in functions ' '"format()" and\n' - ' "print()" to compute the "informal" or nicely printable ' + ' "print()" to compute the ?informal? or nicely printable ' 'string\n' ' representation of an object. The return value must be a ' 'string\n' @@ -3141,7 +3136,7 @@ 'extension,\n' ' evaluation of formatted string literals and the ' '"str.format()"\n' - ' method, to produce a "formatted" string representation ' + ' method, to produce a ?formatted? string representation ' 'of an\n' ' object. The "format_spec" argument is a string that ' 'contains a\n' @@ -3177,7 +3172,7 @@ 'object.__gt__(self, other)\n' 'object.__ge__(self, other)\n' '\n' - ' These are the so-called "rich comparison" methods. The\n' + ' These are the so-called ?rich comparison? methods. The\n' ' correspondence between operator symbols and method names ' 'is as\n' ' follows: "x>> import pdb\n' @@ -3427,11 +3422,11 @@ 'post-\n' 'mortem debugging (or after normal exit of the program), pdb ' 'will\n' - "restart the program. Automatic restarting preserves pdb's state " + 'restart the program. Automatic restarting preserves pdb?s state ' '(such\n' 'as breakpoints) and in most cases is more useful than quitting ' 'the\n' - "debugger upon program's exit.\n" + 'debugger upon program?s exit.\n' '\n' 'New in version 3.2: "pdb.py" now accepts a "-c" option that ' 'executes\n' @@ -3621,7 +3616,7 @@ 'the last command was a "list" command, the next 11 lines are ' 'listed.\n' '\n' - "Commands that the debugger doesn't recognize are assumed to be " + 'Commands that the debugger doesn?t recognize are assumed to be ' 'Python\n' 'statements and are executed in the context of the program being\n' 'debugged. Python statements can also be prefixed with an ' @@ -3632,7 +3627,7 @@ 'function.\n' 'When an exception occurs in such a statement, the exception name ' 'is\n' - "printed but the debugger's state is not changed.\n" + 'printed but the debugger?s state is not changed.\n' '\n' 'The debugger supports aliases. Aliases can have parameters ' 'which\n' @@ -3649,7 +3644,7 @@ 'first\n' '";;" pair, even if it is in the middle of a quoted string.\n' '\n' - 'If a file ".pdbrc" exists in the user\'s home directory or in ' + 'If a file ".pdbrc" exists in the user?s home directory or in ' 'the\n' 'current directory, it is read in and executed as if it had been ' 'typed\n' @@ -3705,7 +3700,7 @@ 'prefixed\n' ' with a filename and a colon, to specify a breakpoint in ' 'another\n' - " file (probably one that hasn't been loaded yet). The file " + ' file (probably one that hasn?t been loaded yet). The file ' 'is\n' ' searched on "sys.path". Note that each breakpoint is ' 'assigned a\n' @@ -3810,7 +3805,7 @@ ' breakpoint?which could have its own command list, leading to\n' ' ambiguities about which list to execute.\n' '\n' - " If you use the 'silent' command in the command list, the " + ' If you use the ?silent? command in the command list, the ' 'usual\n' ' message about stopping at a breakpoint is not printed. This ' 'may be\n' @@ -3869,13 +3864,13 @@ 'the\n' ' bottom-most frame. This lets you jump back and execute code ' 'again,\n' - " or jump forward to skip code that you don't want to run.\n" + ' or jump forward to skip code that you don?t want to run.\n' '\n' - ' It should be noted that not all jumps are allowed -- for ' - 'instance\n' - ' it is not possible to jump into the middle of a "for" loop or ' - 'out\n' - ' of a "finally" clause.\n' + ' It should be noted that not all jumps are allowed ? for ' + 'instance it\n' + ' is not possible to jump into the middle of a "for" loop or ' + 'out of a\n' + ' "finally" clause.\n' '\n' 'l(ist) [first[, last]]\n' '\n' @@ -3918,8 +3913,8 @@ ' value.\n' '\n' ' Note: "print()" can also be used, but is not a debugger ' - 'command\n' - ' --- this executes the Python "print()" function.\n' + 'command ?\n' + ' this executes the Python "print()" function.\n' '\n' 'pp expression\n' '\n' @@ -4089,7 +4084,7 @@ 'dictionary:\n' 'each key object is used as a key into the dictionary to store the\n' 'corresponding datum. This means that you can specify the same key\n' - "multiple times in the key/datum list, and the final dictionary's " + 'multiple times in the key/datum list, and the final dictionary?s ' 'value\n' 'for that key will be the last one given.\n' '\n' @@ -4103,7 +4098,7 @@ '\n' 'A dict comprehension, in contrast to list and set comprehensions,\n' 'needs two expressions separated with a colon followed by the usual\n' - '"for" and "if" clauses. When the comprehension is run, the ' + '?for? and ?if? clauses. When the comprehension is run, the ' 'resulting\n' 'key and value elements are inserted in the new dictionary in the ' 'order\n' @@ -4177,7 +4172,7 @@ 'error (such as division by zero). A Python program can also\n' 'explicitly raise an exception with the "raise" statement. ' 'Exception\n' - 'handlers are specified with the "try" ... "except" statement. ' + 'handlers are specified with the "try" ? "except" statement. ' 'The\n' '"finally" clause of such a statement can be used to specify ' 'cleanup\n' @@ -4185,7 +4180,7 @@ 'whether an\n' 'exception occurred or not in the preceding code.\n' '\n' - 'Python uses the "termination" model of error handling: an ' + 'Python uses the ?termination? model of error handling: an ' 'exception\n' 'handler can find out what happened and continue execution at ' 'an outer\n' @@ -4253,7 +4248,7 @@ 'argument to the interpreter) is a code block. A script command ' '(a\n' 'command specified on the interpreter command line with the ' - "'**-c**'\n" + '?**-c**?\n' 'option) is a code block. The string argument passed to the ' 'built-in\n' 'functions "eval()" and "exec()" is a code block.\n' @@ -4262,7 +4257,7 @@ 'contains\n' 'some administrative information (used for debugging) and ' 'determines\n' - "where and how execution continues after the code block's " + 'where and how execution continues after the code block?s ' 'execution has\n' 'completed.\n' '\n' @@ -4337,7 +4332,7 @@ 'nearest\n' 'enclosing scope. The set of all such scopes visible to a code ' 'block\n' - "is called the block's *environment*.\n" + 'is called the block?s *environment*.\n' '\n' 'When a name is not found at all, a "NameError" exception is ' 'raised. If\n' @@ -4415,7 +4410,7 @@ 'the class. The scope of names defined in a class block is ' 'limited to\n' 'the class block; it does not extend to the code blocks of ' - 'methods --\n' + 'methods ?\n' 'this includes comprehensions and generator expressions since ' 'they are\n' 'implemented using a function scope. This means that the ' @@ -4443,7 +4438,7 @@ 'global\n' 'namespace; this should be a dictionary or a module (in the ' 'latter case\n' - "the module's dictionary is used). By default, when in the " + 'the module?s dictionary is used). By default, when in the ' '"__main__"\n' 'module, "__builtins__" is the built-in module "builtins"; when ' 'in any\n' @@ -4498,7 +4493,7 @@ 'error (such as division by zero). A Python program can also\n' 'explicitly raise an exception with the "raise" statement. ' 'Exception\n' - 'handlers are specified with the "try" ... "except" statement. ' + 'handlers are specified with the "try" ? "except" statement. ' 'The\n' '"finally" clause of such a statement can be used to specify ' 'cleanup\n' @@ -4506,7 +4501,7 @@ 'whether an\n' 'exception occurred or not in the preceding code.\n' '\n' - 'Python uses the "termination" model of error handling: an ' + 'Python uses the ?termination? model of error handling: an ' 'exception\n' 'handler can find out what happened and continue execution at an ' 'outer\n' @@ -4586,7 +4581,7 @@ '(a.k.a. a\n' '*singleton*); it is optional in all other cases. A single ' 'expression\n' - "without a trailing comma doesn't create a tuple, but rather " + 'without a trailing comma doesn?t create a tuple, but rather ' 'yields the\n' 'value of that expression. (To create an empty tuple, use an ' 'empty pair\n' @@ -4647,8 +4642,7 @@ 'terminates.\n' '\n' 'A "break" statement executed in the first suite terminates the loop\n' - 'without executing the "else" clause\'s suite. A "continue" ' - 'statement\n' + 'without executing the "else" clause?s suite. A "continue" statement\n' 'executed in the first suite skips the rest of the suite and ' 'continues\n' 'with the next item, or with the "else" clause if there is no next\n' @@ -4670,7 +4664,7 @@ 'Names in the target list are not deleted when the loop is finished,\n' 'but if the sequence is empty, they will not have been assigned to at\n' 'all by the loop. Hint: the built-in function "range()" returns an\n' - 'iterator of integers suitable to emulate the effect of Pascal\'s "for ' + 'iterator of integers suitable to emulate the effect of Pascal?s "for ' 'i\n' ':= a to b do"; e.g., "list(range(3))" returns the list "[0, 1, 2]".\n' '\n' @@ -4706,7 +4700,7 @@ 'are\n' 'differences.\n' '\n' - 'Format strings contain "replacement fields" surrounded by ' + 'Format strings contain ?replacement fields? surrounded by ' 'curly braces\n' '"{}". Anything that is not contained in braces is ' 'considered literal\n' @@ -4749,29 +4743,27 @@ '\n' 'The *field_name* itself begins with an *arg_name* that is ' 'either a\n' - "number or a keyword. If it's a number, it refers to a " + 'number or a keyword. If it?s a number, it refers to a ' 'positional\n' - "argument, and if it's a keyword, it refers to a named " + 'argument, and if it?s a keyword, it refers to a named ' 'keyword\n' 'argument. If the numerical arg_names in a format string ' 'are 0, 1, 2,\n' - '... in sequence, they can all be omitted (not just some) ' - 'and the\n' - 'numbers 0, 1, 2, ... will be automatically inserted in that ' - 'order.\n' - 'Because *arg_name* is not quote-delimited, it is not ' - 'possible to\n' - 'specify arbitrary dictionary keys (e.g., the strings ' - '"\'10\'" or\n' - '"\':-]\'") within a format string. The *arg_name* can be ' - 'followed by any\n' - 'number of index or attribute expressions. An expression of ' - 'the form\n' - '"\'.name\'" selects the named attribute using "getattr()", ' - 'while an\n' - 'expression of the form "\'[index]\'" does an index lookup ' - 'using\n' - '"__getitem__()".\n' + '? in sequence, they can all be omitted (not just some) and ' + 'the numbers\n' + '0, 1, 2, ? will be automatically inserted in that order. ' + 'Because\n' + '*arg_name* is not quote-delimited, it is not possible to ' + 'specify\n' + 'arbitrary dictionary keys (e.g., the strings "\'10\'" or ' + '"\':-]\'") within\n' + 'a format string. The *arg_name* can be followed by any ' + 'number of index\n' + 'or attribute expressions. An expression of the form ' + '"\'.name\'" selects\n' + 'the named attribute using "getattr()", while an expression ' + 'of the form\n' + '"\'[index]\'" does an index lookup using "__getitem__()".\n' '\n' 'Changed in version 3.1: The positional argument specifiers ' 'can be\n' @@ -4826,7 +4818,7 @@ 'alignment,\n' 'padding, decimal precision and so on. Each value type can ' 'define its\n' - 'own "formatting mini-language" or interpretation of the ' + 'own ?formatting mini-language? or interpretation of the ' '*format_spec*.\n' '\n' 'Most built-in types support a common formatting ' @@ -4852,7 +4844,7 @@ 'Format Specification Mini-Language\n' '==================================\n' '\n' - '"Format specifications" are used within replacement fields ' + '?Format specifications? are used within replacement fields ' 'contained\n' 'within a format string to define how individual values are ' 'presented\n' @@ -4894,13 +4886,13 @@ 'character that can be any character and defaults to a space ' 'if\n' 'omitted. It is not possible to use a literal curly brace ' - '(""{"" or\n' - '""}"") as the *fill* character in a formatted string ' + '(?"{"? or\n' + '?"}"?) as the *fill* character in a formatted string ' 'literal or when\n' 'using the "str.format()" method. However, it is possible ' 'to insert a\n' 'curly brace with a nested replacement field. This ' - "limitation doesn't\n" + 'limitation doesn?t\n' 'affect the "format()" function.\n' '\n' 'The meaning of the various alignment options is as ' @@ -4929,10 +4921,10 @@ 'the sign (if any) |\n' ' | | but before the digits. This is used for ' 'printing fields |\n' - " | | in the form '+000000120'. This alignment " + ' | | in the form ?+000000120?. This alignment ' 'option is only |\n' ' | | valid for numeric types. It becomes the ' - "default when '0' |\n" + 'default when ?0? |\n' ' | | immediately precedes the field ' 'width. |\n' ' ' @@ -4981,7 +4973,7 @@ ' ' '+-----------+------------------------------------------------------------+\n' '\n' - 'The "\'#\'" option causes the "alternate form" to be used ' + 'The "\'#\'" option causes the ?alternate form? to be used ' 'for the\n' 'conversion. The alternate form is defined differently for ' 'different\n' @@ -5150,7 +5142,7 @@ '+===========+============================================================+\n' ' | "\'e\'" | Exponent notation. Prints the number in ' 'scientific |\n' - " | | notation using the letter 'e' to indicate " + ' | | notation using the letter ?e? to indicate ' 'the exponent. |\n' ' | | The default precision is ' '"6". |\n' @@ -5158,7 +5150,7 @@ '+-----------+------------------------------------------------------------+\n' ' | "\'E\'" | Exponent notation. Same as "\'e\'" ' 'except it uses an upper |\n' - " | | case 'E' as the separator " + ' | | case ?E? as the separator ' 'character. |\n' ' ' '+-----------+------------------------------------------------------------+\n' @@ -5295,7 +5287,7 @@ "{longitude}'.format(**coord)\n" " 'Coordinates: 37.24N, -115.81W'\n" '\n' - "Accessing arguments' attributes:\n" + 'Accessing arguments? attributes:\n' '\n' ' >>> c = 3-5j\n' " >>> ('The complex number {0} is formed from the real " @@ -5313,7 +5305,7 @@ ' >>> str(Point(4, 2))\n' " 'Point(4, 2)'\n" '\n' - "Accessing arguments' items:\n" + 'Accessing arguments? items:\n' '\n' ' >>> coord = (3, 5)\n' " >>> 'X: {0[0]}; Y: {0[1]}'.format(coord)\n" @@ -5475,25 +5467,24 @@ '"func".\n' '\n' 'When one or more *parameters* have the form *parameter* "="\n' - '*expression*, the function is said to have "default parameter ' - 'values."\n' + '*expression*, the function is said to have ?default parameter ' + 'values.?\n' 'For a parameter with a default value, the corresponding ' '*argument* may\n' - "be omitted from a call, in which case the parameter's default " + 'be omitted from a call, in which case the parameter?s default ' 'value is\n' 'substituted. If a parameter has a default value, all following\n' - 'parameters up until the ""*"" must also have a default value --- ' - 'this\n' - 'is a syntactic restriction that is not expressed by the ' - 'grammar.\n' + 'parameters up until the ?"*"? must also have a default value ? ' + 'this is\n' + 'a syntactic restriction that is not expressed by the grammar.\n' '\n' '**Default parameter values are evaluated from left to right when ' 'the\n' 'function definition is executed.** This means that the ' 'expression is\n' 'evaluated once, when the function is defined, and that the same ' - '"pre-\n' - 'computed" value is used for each call. This is especially ' + '?pre-\n' + 'computed? value is used for each call. This is especially ' 'important\n' 'to understand when a default parameter is a mutable object, such ' 'as a\n' @@ -5519,26 +5510,26 @@ 'mentioned in\n' 'the parameter list, either from position arguments, from ' 'keyword\n' - 'arguments, or from default values. If the form ""*identifier"" ' + 'arguments, or from default values. If the form ?"*identifier"? ' 'is\n' 'present, it is initialized to a tuple receiving any excess ' 'positional\n' 'parameters, defaulting to the empty tuple. If the form\n' - '""**identifier"" is present, it is initialized to a new ordered\n' + '?"**identifier"? is present, it is initialized to a new ordered\n' 'mapping receiving any excess keyword arguments, defaulting to a ' 'new\n' - 'empty mapping of the same type. Parameters after ""*"" or\n' - '""*identifier"" are keyword-only parameters and may only be ' + 'empty mapping of the same type. Parameters after ?"*"? or\n' + '?"*identifier"? are keyword-only parameters and may only be ' 'passed\n' 'used keyword arguments.\n' '\n' - 'Parameters may have annotations of the form "": expression"" ' + 'Parameters may have annotations of the form ?": expression"? ' 'following\n' 'the parameter name. Any parameter may have an annotation even ' 'those\n' 'of the form "*identifier" or "**identifier". Functions may ' 'have\n' - '"return" annotation of the form ""-> expression"" after the ' + '?return? annotation of the form ?"-> expression"? after the ' 'parameter\n' 'list. These annotations can be any valid Python expression. ' 'The\n' @@ -5546,8 +5537,7 @@ 'function.\n' 'The annotation values are available as values of a dictionary ' 'keyed by\n' - 'the parameters\' names in the "__annotations__" attribute of ' - 'the\n' + 'the parameters? names in the "__annotations__" attribute of the\n' 'function object. If the "annotations" import from "__future__" ' 'is\n' 'used, annotations are preserved as strings at runtime which ' @@ -5565,16 +5555,16 @@ 'lambda\n' 'expression is merely a shorthand for a simplified function ' 'definition;\n' - 'a function defined in a ""def"" statement can be passed around ' + 'a function defined in a ?"def"? statement can be passed around ' 'or\n' 'assigned to another name just like a function defined by a ' 'lambda\n' - 'expression. The ""def"" form is actually more powerful since ' + 'expression. The ?"def"? form is actually more powerful since ' 'it\n' 'allows the execution of multiple statements and annotations.\n' '\n' - "**Programmer's note:** Functions are first-class objects. A " - '""def""\n' + '**Programmer?s note:** Functions are first-class objects. A ' + '?"def"?\n' 'statement executed inside a function definition defines a local\n' 'function that can be returned or passed around. Free variables ' 'used\n' @@ -5633,8 +5623,7 @@ 'change\n' 'the meaning of the program.\n' '\n' - '**Programmer\'s note:** "global" is a directive to the parser. ' - 'It\n' + '**Programmer?s note:** "global" is a directive to the parser. It\n' 'applies only to code parsed at the same time as the "global"\n' 'statement. In particular, a "global" statement contained in a ' 'string\n' @@ -5691,7 +5680,7 @@ 'within the\n' ' context of a class definition, are re-written to use a ' 'mangled form\n' - ' to help avoid name clashes between "private" attributes of ' + ' to help avoid name clashes between ?private? attributes of ' 'base and\n' ' derived classes. See section Identifiers (Names).\n', 'identifiers': 'Identifiers and keywords\n' @@ -5839,7 +5828,7 @@ 'within the\n' ' context of a class definition, are re-written to use a ' 'mangled form\n' - ' to help avoid name clashes between "private" attributes of ' + ' to help avoid name clashes between ?private? attributes of ' 'base and\n' ' derived classes. See section Identifiers (Names).\n', 'if': 'The "if" statement\n' @@ -5920,7 +5909,7 @@ 'either\n' 'that the module could not be located, *or* that an error occurred\n' 'while initializing the module, which includes execution of the\n' - "module's code.\n" + 'module?s code.\n' '\n' 'If the requested module is retrieved successfully, it will be ' 'made\n' @@ -5931,7 +5920,7 @@ '\n' '* If no other name is specified, and the module being imported is ' 'a\n' - " top level module, the module's name is bound in the local " + ' top level module, the module?s name is bound in the local ' 'namespace\n' ' as a reference to the imported module\n' '\n' @@ -5984,7 +5973,7 @@ '\n' 'The *public names* defined by a module are determined by checking ' 'the\n' - 'module\'s namespace for a variable named "__all__"; if defined, it ' + 'module?s namespace for a variable named "__all__"; if defined, it ' 'must\n' 'be a sequence of strings which are names defined or imported by ' 'that\n' @@ -5992,7 +5981,7 @@ 'and\n' 'are required to exist. If "__all__" is not defined, the set of ' 'public\n' - "names includes all names found in the module's namespace which do " + 'names includes all names found in the module?s namespace which do ' 'not\n' 'begin with an underscore character ("\'_\'"). "__all__" should ' 'contain\n' @@ -6002,8 +5991,7 @@ 'were\n' 'imported and used within the module).\n' '\n' - 'The wild card form of import --- "from module import *" --- is ' - 'only\n' + 'The wild card form of import ? "from module import *" ? is only\n' 'allowed at the module level. Attempting to use it in class or\n' 'function definitions will raise a "SyntaxError".\n' '\n' @@ -6116,7 +6104,7 @@ '\n' ' import __future__ [as name]\n' '\n' - "That is not a future statement; it's an ordinary import statement " + 'That is not a future statement; it?s an ordinary import statement ' 'with\n' 'no special semantics or syntax restrictions.\n' '\n' @@ -6127,8 +6115,7 @@ 'the\n' 'future statement. This can be controlled by optional arguments ' 'to\n' - '"compile()" --- see the documentation of that function for ' - 'details.\n' + '"compile()" ? see the documentation of that function for details.\n' '\n' 'A future statement typed at an interactive interpreter prompt ' 'will\n' @@ -6334,7 +6321,7 @@ 'nearest\n' 'enclosing scope. The set of all such scopes visible to a code ' 'block\n' - "is called the block's *environment*.\n" + 'is called the block?s *environment*.\n' '\n' 'When a name is not found at all, a "NameError" exception is ' 'raised. If\n' @@ -6408,7 +6395,7 @@ 'the class. The scope of names defined in a class block is limited ' 'to\n' 'the class block; it does not extend to the code blocks of methods ' - '--\n' + '?\n' 'this includes comprehensions and generator expressions since they ' 'are\n' 'implemented using a function scope. This means that the ' @@ -6435,7 +6422,7 @@ 'global\n' 'namespace; this should be a dictionary or a module (in the latter ' 'case\n' - "the module's dictionary is used). By default, when in the " + 'the module?s dictionary is used). By default, when in the ' '"__main__"\n' 'module, "__builtins__" is the built-in module "builtins"; when in ' 'any\n' @@ -6511,7 +6498,7 @@ '\n' 'Note that numeric literals do not include a sign; a phrase like ' '"-1"\n' - 'is actually an expression composed of the unary operator \'"-"\' ' + 'is actually an expression composed of the unary operator ?"-"? ' 'and the\n' 'literal "1".\n', 'numeric-types': 'Emulating numeric types\n' @@ -6601,15 +6588,15 @@ '"__rpow__()" (the\n' ' coercion rules would become too complicated).\n' '\n' - " Note: If the right operand's type is a subclass of the " + ' Note: If the right operand?s type is a subclass of the ' 'left\n' - " operand's type and that subclass provides the " + ' operand?s type and that subclass provides the ' 'reflected method\n' ' for the operation, this method will be called before ' 'the left\n' - " operand's non-reflected method. This behavior allows " + ' operand?s non-reflected method. This behavior allows ' 'subclasses\n' - " to override their ancestors' operations.\n" + ' to override their ancestors? operations.\n' '\n' 'object.__iadd__(self, other)\n' 'object.__isub__(self, other)\n' @@ -6647,7 +6634,7 @@ 'certain\n' ' situations, augmented assignment can result in ' 'unexpected errors\n' - " (see Why does a_tuple[i] += ['item'] raise an exception " + ' (see Why does a_tuple[i] += [?item?] raise an exception ' 'when the\n' ' addition works?), but this behavior is in fact part of ' 'the data\n' @@ -6709,18 +6696,18 @@ 'objects': 'Objects, values and types\n' '*************************\n' '\n' - "*Objects* are Python's abstraction for data. All data in a " + '*Objects* are Python?s abstraction for data. All data in a ' 'Python\n' 'program is represented by objects or by relations between ' 'objects. (In\n' - 'a sense, and in conformance to Von Neumann\'s model of a "stored\n' - 'program computer," code is also represented by objects.)\n' + 'a sense, and in conformance to Von Neumann?s model of a ?stored\n' + 'program computer,? code is also represented by objects.)\n' '\n' - "Every object has an identity, a type and a value. An object's\n" + 'Every object has an identity, a type and a value. An object?s\n' '*identity* never changes once it has been created; you may think ' 'of it\n' - 'as the object\'s address in memory. The \'"is"\' operator ' - 'compares the\n' + 'as the object?s address in memory. The ?"is"? operator compares ' + 'the\n' 'identity of two objects; the "id()" function returns an integer\n' 'representing its identity.\n' '\n' @@ -6728,14 +6715,14 @@ 'memory\n' 'address where "x" is stored.\n' '\n' - "An object's type determines the operations that the object " + 'An object?s type determines the operations that the object ' 'supports\n' - '(e.g., "does it have a length?") and also defines the possible ' + '(e.g., ?does it have a length??) and also defines the possible ' 'values\n' 'for objects of that type. The "type()" function returns an ' - "object's\n" + 'object?s\n' 'type (which is an object itself). Like its identity, an ' - "object's\n" + 'object?s\n' '*type* is also unchangeable. [1]\n' '\n' 'The *value* of some objects can change. Objects whose value can\n' @@ -6744,14 +6731,14 @@ 'once they are created are called *immutable*. (The value of an\n' 'immutable container object that contains a reference to a ' 'mutable\n' - "object can change when the latter's value is changed; however " + 'object can change when the latter?s value is changed; however ' 'the\n' 'container is still considered immutable, because the collection ' 'of\n' 'objects it contains cannot be changed. So, immutability is not\n' 'strictly the same as having an unchangeable value, it is more ' 'subtle.)\n' - "An object's mutability is determined by its type; for instance,\n" + 'An object?s mutability is determined by its type; for instance,\n' 'numbers, strings and tuples are immutable, while dictionaries ' 'and\n' 'lists are mutable.\n' @@ -6759,9 +6746,9 @@ 'Objects are never explicitly destroyed; however, when they ' 'become\n' 'unreachable they may be garbage-collected. An implementation is\n' - 'allowed to postpone garbage collection or omit it altogether --- ' - 'it is\n' - 'a matter of implementation quality how garbage collection is\n' + 'allowed to postpone garbage collection or omit it altogether ? it ' + 'is a\n' + 'matter of implementation quality how garbage collection is\n' 'implemented, as long as no objects are collected that are still\n' 'reachable.\n' '\n' @@ -6781,13 +6768,14 @@ '(so\n' 'you should always close files explicitly).\n' '\n' - "Note that the use of the implementation's tracing or debugging\n" + 'Note that the use of the implementation?s tracing or debugging\n' 'facilities may keep objects alive that would normally be ' 'collectable.\n' - 'Also note that catching an exception with a \'"try"..."except"\'\n' - 'statement may keep objects alive.\n' + 'Also note that catching an exception with a ?"try"?"except"? ' + 'statement\n' + 'may keep objects alive.\n' '\n' - 'Some objects contain references to "external" resources such as ' + 'Some objects contain references to ?external? resources such as ' 'open\n' 'files or windows. It is understood that these resources are ' 'freed\n' @@ -6798,14 +6786,13 @@ 'release the external resource, usually a "close()" method. ' 'Programs\n' 'are strongly recommended to explicitly close such objects. The\n' - '\'"try"..."finally"\' statement and the \'"with"\' statement ' - 'provide\n' + '?"try"?"finally"? statement and the ?"with"? statement provide\n' 'convenient ways to do this.\n' '\n' 'Some objects contain references to other objects; these are ' 'called\n' '*containers*. Examples of containers are tuples, lists and\n' - "dictionaries. The references are part of a container's value. " + 'dictionaries. The references are part of a container?s value. ' 'In\n' 'most cases, when we talk about the value of a container, we imply ' 'the\n' @@ -6862,7 +6849,7 @@ '| "lambda" | ' 'Lambda expression |\n' '+-------------------------------------------------+---------------------------------------+\n' - '| "if" -- "else" | ' + '| "if" ? "else" | ' 'Conditional expression |\n' '+-------------------------------------------------+---------------------------------------+\n' '| "or" | ' @@ -6945,7 +6932,7 @@ 'application.\n' '\n' '[2] If x is very close to an exact integer multiple of ' - "y, it's\n" + 'y, it?s\n' ' possible for "x//y" to be one larger than ' '"(x-x%y)//y" due to\n' ' rounding. In such cases, Python returns the latter ' @@ -6956,8 +6943,8 @@ '\n' '[3] The Unicode standard distinguishes between *code ' 'points* (e.g.\n' - ' U+0041) and *abstract characters* (e.g. "LATIN ' - 'CAPITAL LETTER A").\n' + ' U+0041) and *abstract characters* (e.g. ?LATIN ' + 'CAPITAL LETTER A?).\n' ' While most abstract characters in Unicode are only ' 'represented\n' ' using one code point, there is a number of abstract ' @@ -6965,8 +6952,8 @@ ' that can in addition be represented using a sequence ' 'of more than\n' ' one code point. For example, the abstract character ' - '"LATIN\n' - ' CAPITAL LETTER C WITH CEDILLA" can be represented as ' + '?LATIN\n' + ' CAPITAL LETTER C WITH CEDILLA? can be represented as ' 'a single\n' ' *precomposed character* at code position U+00C7, or ' 'as a sequence\n' @@ -6982,9 +6969,9 @@ 'to humans. For\n' ' example, ""\\u00C7" == "\\u0043\\u0327"" is "False", ' 'even though both\n' - ' strings represent the same abstract character "LATIN ' + ' strings represent the same abstract character ?LATIN ' 'CAPITAL\n' - ' LETTER C WITH CEDILLA".\n' + ' LETTER C WITH CEDILLA?.\n' '\n' ' To compare strings at the level of abstract ' 'characters (that is,\n' @@ -7014,10 +7001,11 @@ '\n' ' pass_stmt ::= "pass"\n' '\n' - '"pass" is a null operation --- when it is executed, nothing ' - 'happens.\n' - 'It is useful as a placeholder when a statement is required\n' - 'syntactically, but no code needs to be executed, for example:\n' + '"pass" is a null operation ? when it is executed, nothing happens. ' + 'It\n' + 'is useful as a placeholder when a statement is required ' + 'syntactically,\n' + 'but no code needs to be executed, for example:\n' '\n' ' def f(arg): pass # a function that does nothing (yet)\n' '\n' @@ -7073,7 +7061,7 @@ '"BaseException". If it is a class, the exception instance will be\n' 'obtained when needed by instantiating the class with no arguments.\n' '\n' - "The *type* of the exception is the exception instance's class, the\n" + 'The *type* of the exception is the exception instance?s class, the\n' '*value* is the instance itself.\n' '\n' 'A traceback object is normally created automatically when an ' @@ -7119,7 +7107,7 @@ 'inside\n' 'an exception handler or a "finally" clause: the previous exception ' 'is\n' - 'then attached as the new exception\'s "__context__" attribute:\n' + 'then attached as the new exception?s "__context__" attribute:\n' '\n' ' >>> try:\n' ' ... print(1 / 0)\n' @@ -7219,7 +7207,7 @@ '"clear()",\n' '"setdefault()", "pop()", "popitem()", "copy()", and ' '"update()"\n' - "behaving similar to those for Python's standard dictionary " + 'behaving similar to those for Python?s standard dictionary ' 'objects.\n' 'The "collections.abc" module provides a "MutableMapping" ' 'abstract base\n' @@ -7245,7 +7233,7 @@ 'the\n' '"__contains__()" method to allow efficient use of the "in" ' 'operator;\n' - 'for mappings, "in" should search the mapping\'s keys; for ' + 'for mappings, "in" should search the mapping?s keys; for ' 'sequences, it\n' 'should search through the values. It is further ' 'recommended that both\n' @@ -7263,7 +7251,7 @@ 'Should return\n' ' the length of the object, an integer ">=" 0. Also, an ' 'object that\n' - ' doesn\'t define a "__bool__()" method and whose ' + ' doesn?t define a "__bool__()" method and whose ' '"__len__()" method\n' ' returns zero is considered to be false in a Boolean ' 'context.\n' @@ -7420,7 +7408,7 @@ 'values or\n' ' the key-item pairs.\n' '\n' - ' For objects that don\'t define "__contains__()", the ' + ' For objects that don?t define "__contains__()", the ' 'membership test\n' ' first tries iteration via "__iter__()", then the old ' 'sequence\n' @@ -7508,7 +7496,7 @@ 'object.__dict__\n' '\n' ' A dictionary or other mapping object used to store an ' - "object's\n" + 'object?s\n' ' (writable) attributes.\n' '\n' 'instance.__class__\n' @@ -7568,15 +7556,15 @@ 'to\n' ' "[1.0, 2.0]", and similarly for tuples.\n' '\n' - "[3] They must have since the parser can't tell the type of " + '[3] They must have since the parser can?t tell the type of ' 'the\n' ' operands.\n' '\n' '[4] Cased characters are those with general category ' 'property\n' - ' being one of "Lu" (Letter, uppercase), "Ll" (Letter, ' + ' being one of ?Lu? (Letter, uppercase), ?Ll? (Letter, ' 'lowercase),\n' - ' or "Lt" (Letter, titlecase).\n' + ' or ?Lt? (Letter, titlecase).\n' '\n' '[5] To format only a tuple you should therefore provide a\n' ' singleton tuple whose only element is the tuple to be ' @@ -7588,7 +7576,7 @@ 'special\n' 'syntax (such as arithmetic operations or subscripting and ' 'slicing) by\n' - "defining methods with special names. This is Python's " + 'defining methods with special names. This is Python?s ' 'approach to\n' '*operator overloading*, allowing classes to define their own ' 'behavior\n' @@ -7622,7 +7610,7 @@ 'elements, but\n' 'extracting a slice may not make sense. (One example of this ' 'is the\n' - '"NodeList" interface in the W3C\'s Document Object Model.)\n' + '"NodeList" interface in the W3C?s Document Object Model.)\n' '\n' '\n' 'Basic customization\n' @@ -7646,7 +7634,7 @@ '\n' ' Typical implementations create a new instance of the ' 'class by\n' - ' invoking the superclass\'s "__new__()" method using\n' + ' invoking the superclass?s "__new__()" method using\n' ' "super().__new__(cls[, ...])" with appropriate arguments ' 'and then\n' ' modifying the newly-created instance as necessary before ' @@ -7655,7 +7643,7 @@ '\n' ' If "__new__()" returns an instance of *cls*, then the ' 'new\n' - ' instance\'s "__init__()" method will be invoked like\n' + ' instance?s "__init__()" method will be invoked like\n' ' "__init__(self[, ...])", where *self* is the new instance ' 'and the\n' ' remaining arguments are the same as were passed to ' @@ -7663,7 +7651,7 @@ '\n' ' If "__new__()" does not return an instance of *cls*, then ' 'the new\n' - ' instance\'s "__init__()" method will not be invoked.\n' + ' instance?s "__init__()" method will not be invoked.\n' '\n' ' "__new__()" is intended mainly to allow subclasses of ' 'immutable\n' @@ -7681,7 +7669,7 @@ 'those\n' ' passed to the class constructor expression. If a base ' 'class has an\n' - ' "__init__()" method, the derived class\'s "__init__()" ' + ' "__init__()" method, the derived class?s "__init__()" ' 'method, if\n' ' any, must explicitly call it to ensure proper ' 'initialization of the\n' @@ -7702,8 +7690,8 @@ 'is also\n' ' called a finalizer or (improperly) a destructor. If a ' 'base class\n' - ' has a "__del__()" method, the derived class\'s ' - '"__del__()" method,\n' + ' has a "__del__()" method, the derived class?s "__del__()" ' + 'method,\n' ' if any, must explicitly call it to ensure proper deletion ' 'of the\n' ' base class part of the instance.\n' @@ -7723,11 +7711,11 @@ 'for\n' ' objects that still exist when the interpreter exits.\n' '\n' - ' Note: "del x" doesn\'t directly call "x.__del__()" --- ' - 'the former\n' + ' Note: "del x" doesn?t directly call "x.__del__()" ? the ' + 'former\n' ' decrements the reference count for "x" by one, and the ' 'latter is\n' - ' only called when "x"\'s reference count reaches zero.\n' + ' only called when "x"?s reference count reaches zero.\n' '\n' ' **CPython implementation detail:** It is possible for a ' 'reference\n' @@ -7739,7 +7727,7 @@ 'reference\n' ' cycles is when an exception has been caught in a local ' 'variable.\n' - " The frame's locals then reference the exception, which " + ' The frame?s locals then reference the exception, which ' 'references\n' ' its own traceback, which references the locals of all ' 'frames caught\n' @@ -7785,7 +7773,7 @@ 'object.__repr__(self)\n' '\n' ' Called by the "repr()" built-in function to compute the ' - '"official"\n' + '?official?\n' ' string representation of an object. If at all possible, ' 'this\n' ' should look like a valid Python expression that could be ' @@ -7799,7 +7787,7 @@ ' value must be a string object. If a class defines ' '"__repr__()" but\n' ' not "__str__()", then "__repr__()" is also used when an ' - '"informal"\n' + '?informal?\n' ' string representation of instances of that class is ' 'required.\n' '\n' @@ -7811,7 +7799,7 @@ '\n' ' Called by "str(object)" and the built-in functions ' '"format()" and\n' - ' "print()" to compute the "informal" or nicely printable ' + ' "print()" to compute the ?informal? or nicely printable ' 'string\n' ' representation of an object. The return value must be a ' 'string\n' @@ -7839,7 +7827,7 @@ 'extension,\n' ' evaluation of formatted string literals and the ' '"str.format()"\n' - ' method, to produce a "formatted" string representation of ' + ' method, to produce a ?formatted? string representation of ' 'an\n' ' object. The "format_spec" argument is a string that ' 'contains a\n' @@ -7875,7 +7863,7 @@ 'object.__gt__(self, other)\n' 'object.__ge__(self, other)\n' '\n' - ' These are the so-called "rich comparison" methods. The\n' + ' These are the so-called ?rich comparison? methods. The\n' ' correspondence between operator symbols and method names ' 'is as\n' ' follows: "x=" 0. Also, an ' 'object that\n' - ' doesn\'t define a "__bool__()" method and whose ' + ' doesn?t define a "__bool__()" method and whose ' '"__len__()" method\n' ' returns zero is considered to be false in a Boolean ' 'context.\n' @@ -9117,7 +9105,7 @@ 'values or\n' ' the key-item pairs.\n' '\n' - ' For objects that don\'t define "__contains__()", the ' + ' For objects that don?t define "__contains__()", the ' 'membership test\n' ' first tries iteration via "__iter__()", then the old ' 'sequence\n' @@ -9213,15 +9201,15 @@ '"__rpow__()" (the\n' ' coercion rules would become too complicated).\n' '\n' - " Note: If the right operand's type is a subclass of the " + ' Note: If the right operand?s type is a subclass of the ' 'left\n' - " operand's type and that subclass provides the reflected " + ' operand?s type and that subclass provides the reflected ' 'method\n' ' for the operation, this method will be called before ' 'the left\n' - " operand's non-reflected method. This behavior allows " + ' operand?s non-reflected method. This behavior allows ' 'subclasses\n' - " to override their ancestors' operations.\n" + ' to override their ancestors? operations.\n' '\n' 'object.__iadd__(self, other)\n' 'object.__isub__(self, other)\n' @@ -9259,7 +9247,7 @@ 'certain\n' ' situations, augmented assignment can result in unexpected ' 'errors\n' - " (see Why does a_tuple[i] += ['item'] raise an exception " + ' (see Why does a_tuple[i] += [?item?] raise an exception ' 'when the\n' ' addition works?), but this behavior is in fact part of ' 'the data\n' @@ -9349,7 +9337,7 @@ '\n' ' Enter the runtime context related to this object. The ' '"with"\n' - " statement will bind this method's return value to the " + ' statement will bind this method?s return value to the ' 'target(s)\n' ' specified in the "as" clause of the statement, if any.\n' '\n' @@ -9373,11 +9361,11 @@ '\n' ' Note that "__exit__()" methods should not reraise the ' 'passed-in\n' - " exception; this is the caller's responsibility.\n" + ' exception; this is the caller?s responsibility.\n' '\n' 'See also:\n' '\n' - ' **PEP 343** - The "with" statement\n' + ' **PEP 343** - The ?with? statement\n' ' The specification, background, and examples for the ' 'Python "with"\n' ' statement.\n' @@ -9388,9 +9376,9 @@ '\n' 'For custom classes, implicit invocations of special methods ' 'are only\n' - "guaranteed to work correctly if defined on an object's type, " + 'guaranteed to work correctly if defined on an object?s type, ' 'not in\n' - "the object's instance dictionary. That behaviour is the " + 'the object?s instance dictionary. That behaviour is the ' 'reason why\n' 'the following code raises an exception:\n' '\n' @@ -9424,7 +9412,7 @@ '\n' 'Incorrectly attempting to invoke an unbound method of a ' 'class in this\n' - "way is sometimes referred to as 'metaclass confusion', and " + 'way is sometimes referred to as ?metaclass confusion?, and ' 'is avoided\n' 'by bypassing the instance when looking up special methods:\n' '\n' @@ -9437,7 +9425,7 @@ 'interest of\n' 'correctness, implicit special method lookup generally also ' 'bypasses\n' - 'the "__getattribute__()" method even of the object\'s ' + 'the "__getattribute__()" method even of the object?s ' 'metaclass:\n' '\n' ' >>> class Meta(type):\n' @@ -9717,11 +9705,11 @@ 'Alphabetic\n' ' characters are those characters defined in the Unicode ' 'character\n' - ' database as "Letter", i.e., those with general category ' + ' database as ?Letter?, i.e., those with general category ' 'property\n' - ' being one of "Lm", "Lt", "Lu", "Ll", or "Lo". Note ' + ' being one of ?Lm?, ?Lt?, ?Lu?, ?Ll?, or ?Lo?. Note ' 'that this is\n' - ' different from the "Alphabetic" property defined in the ' + ' different from the ?Alphabetic? property defined in the ' 'Unicode\n' ' Standard.\n' '\n' @@ -9745,7 +9733,7 @@ 'in base 10,\n' ' e.g. U+0660, ARABIC-INDIC DIGIT ZERO. Formally a ' 'decimal character\n' - ' is a character in the Unicode General Category "Nd".\n' + ' is a character in the Unicode General Category ?Nd?.\n' '\n' 'str.isdigit()\n' '\n' @@ -9804,7 +9792,7 @@ 'characters are\n' ' those characters defined in the Unicode character ' 'database as\n' - ' "Other" or "Separator", excepting the ASCII space ' + ' ?Other? or ?Separator?, excepting the ASCII space ' '(0x20) which is\n' ' considered printable. (Note that printable characters ' 'in this\n' @@ -9822,9 +9810,9 @@ 'Whitespace\n' ' characters are those characters defined in the Unicode ' 'character\n' - ' database as "Other" or "Separator" and those with ' + ' database as ?Other? or ?Separator? and those with ' 'bidirectional\n' - ' property being one of "WS", "B", or "S".\n' + ' property being one of ?WS?, ?B?, or ?S?.\n' '\n' 'str.istitle()\n' '\n' @@ -10282,9 +10270,9 @@ '"str.upper().isupper()" might be\n' ' "False" if "s" contains uncased characters or if the ' 'Unicode\n' - ' category of the resulting character(s) is not "Lu" ' + ' category of the resulting character(s) is not ?Lu? ' '(Letter,\n' - ' uppercase), but e.g. "Lt" (Letter, titlecase).\n' + ' uppercase), but e.g. ?Lt? (Letter, titlecase).\n' '\n' ' The uppercasing algorithm used is described in section ' '3.13 of the\n' @@ -10379,9 +10367,9 @@ 'literals,\n' '"\'\\U\'" and "\'\\u\'" escapes in raw strings are not treated ' 'specially.\n' - "Given that Python 2.x's raw unicode literals behave differently " + 'Given that Python 2.x?s raw unicode literals behave differently ' 'than\n' - 'Python 3.x\'s the "\'ur\'" syntax is not supported.\n' + 'Python 3.x?s the "\'ur\'" syntax is not supported.\n' '\n' 'New in version 3.3: The "\'rb\'" prefix of raw bytes literals has ' 'been\n' @@ -10405,7 +10393,7 @@ 'In triple-quoted literals, unescaped newlines and quotes are ' 'allowed\n' '(and are retained), except that three unescaped quotes in a row\n' - 'terminate the literal. (A "quote" is the character used to open ' + 'terminate the literal. (A ?quote? is the character used to open ' 'the\n' 'literal, i.e. either "\'" or """.)\n' '\n' @@ -10584,13 +10572,13 @@ 'item whose\n' 'index is that value (counting from zero). Since the support ' 'for\n' - "negative indices and slicing occurs in the object's " + 'negative indices and slicing occurs in the object?s ' '"__getitem__()"\n' 'method, subclasses overriding this method will need to ' 'explicitly add\n' 'that support.\n' '\n' - "A string's items are characters. A character is not a " + 'A string?s items are characters. A character is not a ' 'separate data\n' 'type but a string of exactly one character.\n', 'truth': 'Truth Value Testing\n' @@ -10647,7 +10635,7 @@ 'less except clause, if present, must be last; it matches any\n' 'exception. For an except clause with an expression, that expression\n' 'is evaluated, and the clause matches the exception if the resulting\n' - 'object is "compatible" with the exception. An object is compatible\n' + 'object is ?compatible? with the exception. An object is compatible\n' 'with an exception if it is the class or a base class of the ' 'exception\n' 'object or a tuple containing an item compatible with the exception.\n' @@ -10669,7 +10657,7 @@ 'When a matching except clause is found, the exception is assigned to\n' 'the target specified after the "as" keyword in that except clause, ' 'if\n' - "present, and the except clause's suite is executed. All except\n" + 'present, and the except clause?s suite is executed. All except\n' 'clauses must have an executable block. When the end of this block ' 'is\n' 'reached, execution continues normally after the entire try ' @@ -10699,7 +10687,7 @@ 'cycle with the stack frame, keeping all locals in that frame alive\n' 'until the next garbage collection occurs.\n' '\n' - "Before an except clause's suite is executed, details about the\n" + 'Before an except clause?s suite is executed, details about the\n' 'exception are stored in the "sys" module and can be accessed via\n' '"sys.exc_info()". "sys.exc_info()" returns a 3-tuple consisting of ' 'the\n' @@ -10713,7 +10701,7 @@ 'the end of the "try" clause. [2] Exceptions in the "else" clause are\n' 'not handled by the preceding "except" clauses.\n' '\n' - 'If "finally" is present, it specifies a \'cleanup\' handler. The ' + 'If "finally" is present, it specifies a ?cleanup? handler. The ' '"try"\n' 'clause is executed, including any "except" and "else" clauses. If ' 'an\n' @@ -10741,12 +10729,10 @@ 'execution of the "finally" clause.\n' '\n' 'When a "return", "break" or "continue" statement is executed in the\n' - '"try" suite of a "try"..."finally" statement, the "finally" clause ' - 'is\n' - 'also executed \'on the way out.\' A "continue" statement is illegal ' - 'in\n' + '"try" suite of a "try"?"finally" statement, the "finally" clause is\n' + 'also executed ?on the way out.? A "continue" statement is illegal in\n' 'the "finally" clause. (The reason is a problem with the current\n' - 'implementation --- this restriction may be lifted in the future).\n' + 'implementation ? this restriction may be lifted in the future).\n' '\n' 'The return value of a function is determined by the last "return"\n' 'statement executed. Since the "finally" clause always executes, a\n' @@ -10781,7 +10767,7 @@ 'will often be provided via the standard library instead.\n' '\n' 'Some of the type descriptions below contain a paragraph listing\n' - "'special attributes.' These are attributes that provide access to " + '?special attributes.? These are attributes that provide access to ' 'the\n' 'implementation and are not intended for general use. Their ' 'definition\n' @@ -10794,7 +10780,7 @@ 'It\n' ' is used to signify the absence of a value in many situations, ' 'e.g.,\n' - " it is returned from functions that don't explicitly return\n" + ' it is returned from functions that don?t explicitly return\n' ' anything. Its truth value is false.\n' '\n' 'NotImplemented\n' @@ -10845,7 +10831,7 @@ 'shift\n' ' and mask operations, a binary representation is assumed, ' 'and\n' - " negative numbers are represented in a variant of 2's\n" + ' negative numbers are represented in a variant of 2?s\n' ' complement which gives the illusion of an infinite string ' 'of\n' ' sign bits extending to the left.\n' @@ -10899,7 +10885,7 @@ 'items\n' ' of a sequence. When the length of a sequence is *n*, the index ' 'set\n' - ' contains the numbers 0, 1, ..., *n*-1. Item *i* of sequence *a* ' + ' contains the numbers 0, 1, ?, *n*-1. Item *i* of sequence *a* ' 'is\n' ' selected by "a[i]".\n' '\n' @@ -10909,8 +10895,8 @@ 'implies\n' ' that the index set is renumbered so that it starts at 0.\n' '\n' - ' Some sequences also support "extended slicing" with a third ' - '"step"\n' + ' Some sequences also support ?extended slicing? with a third ' + '?step?\n' ' parameter: "a[i:j:k]" selects all items of *a* with index *x* ' 'where\n' ' "x = i + n*k", *n* ">=" "0" and *i* "<=" *x* "<" *j*.\n' @@ -10935,7 +10921,7 @@ 'code\n' ' points. All the code points in the range "U+0000 - ' 'U+10FFFF"\n' - " can be represented in a string. Python doesn't have a " + ' can be represented in a string. Python doesn?t have a ' '"char"\n' ' type; instead, every code point in the string is ' 'represented\n' @@ -10954,7 +10940,7 @@ ' The items of a tuple are arbitrary Python objects. Tuples ' 'of\n' ' two or more items are formed by comma-separated lists of\n' - " expressions. A tuple of one item (a 'singleton') can be\n" + ' expressions. A tuple of one item (a ?singleton?) can be\n' ' formed by affixing a comma to an expression (an expression ' 'by\n' ' itself does not create a tuple, since parentheses must be\n' @@ -11060,7 +11046,7 @@ 'object\n' ' identity, the reason being that the efficient implementation ' 'of\n' - " dictionaries requires a key's hash value to remain constant.\n" + ' dictionaries requires a key?s hash value to remain constant.\n' ' Numeric types used for keys obey the normal rules for ' 'numeric\n' ' comparison: if two numbers compare equal (e.g., "1" and ' @@ -11085,7 +11071,7 @@ ' definition (see section Function definitions). It should be\n' ' called with an argument list containing the same number of ' 'items\n' - " as the function's formal parameter list.\n" + ' as the function?s formal parameter list.\n' '\n' ' Special attributes:\n' '\n' @@ -11095,8 +11081,8 @@ '| |\n' ' ' '+===========================+=================================+=============+\n' - ' | "__doc__" | The function\'s ' - 'documentation | Writable |\n' + ' | "__doc__" | The function?s documentation ' + '| Writable |\n' ' | | string, or "None" if ' '| |\n' ' | | unavailable; not inherited by ' @@ -11105,12 +11091,12 @@ '| |\n' ' ' '+---------------------------+---------------------------------+-------------+\n' - ' | "__name__" | The function\'s ' - 'name | Writable |\n' + ' | "__name__" | The function?s name ' + '| Writable |\n' ' ' '+---------------------------+---------------------------------+-------------+\n' - ' | "__qualname__" | The function\'s *qualified ' - 'name* | Writable |\n' + ' | "__qualname__" | The function?s *qualified name* ' + '| Writable |\n' ' | | New in version 3.3. ' '| |\n' ' ' @@ -11143,9 +11129,9 @@ '+---------------------------+---------------------------------+-------------+\n' ' | "__globals__" | A reference to the dictionary ' '| Read-only |\n' - " | | that holds the function's " + ' | | that holds the function?s ' '| |\n' - ' | | global variables --- the global ' + ' | | global variables ? the global ' '| |\n' ' | | namespace of the module in ' '| |\n' @@ -11163,7 +11149,7 @@ '| Read-only |\n' ' | | contain bindings for the ' '| |\n' - " | | function's free variables. See " + ' | | function?s free variables. See ' '| |\n' ' | | below for information on the ' '| |\n' @@ -11190,7 +11176,7 @@ ' ' '+---------------------------+---------------------------------+-------------+\n' '\n' - ' Most of the attributes labelled "Writable" check the type of ' + ' Most of the attributes labelled ?Writable? check the type of ' 'the\n' ' assigned value.\n' '\n' @@ -11209,7 +11195,7 @@ ' A cell object has the attribute "cell_contents". This can be\n' ' used to get the value of the cell, as well as set the value.\n' '\n' - " Additional information about a function's definition can be\n" + ' Additional information about a function?s definition can be\n' ' retrieved from its code object; see the description of ' 'internal\n' ' types below.\n' @@ -11222,7 +11208,7 @@ ' Special read-only attributes: "__self__" is the class ' 'instance\n' ' object, "__func__" is the function object; "__doc__" is the\n' - ' method\'s documentation (same as "__func__.__doc__"); ' + ' method?s documentation (same as "__func__.__doc__"); ' '"__name__"\n' ' is the method name (same as "__func__.__name__"); ' '"__module__"\n' @@ -11246,7 +11232,7 @@ 'instances,\n' ' its "__self__" attribute is the instance, and the method ' 'object\n' - ' is said to be bound. The new method\'s "__func__" attribute ' + ' is said to be bound. The new method?s "__func__" attribute ' 'is\n' ' the original function object.\n' '\n' @@ -11279,7 +11265,7 @@ '\n' ' When an instance method object is derived from a class ' 'method\n' - ' object, the "class instance" stored in "__self__" will ' + ' object, the ?class instance? stored in "__self__" will ' 'actually\n' ' be the class itself, so that calling either "x.f(1)" or ' '"C.f(1)"\n' @@ -11312,7 +11298,7 @@ 'object\n' ' which can be used to execute the body of the function: ' 'calling\n' - ' the iterator\'s "iterator.__next__()" method will cause the\n' + ' the iterator?s "iterator.__next__()" method will cause the\n' ' function to execute until it provides a value using the ' '"yield"\n' ' statement. When the function executes a "return" statement ' @@ -11341,7 +11327,7 @@ 'for"\n' ' statement to execute the body of the function.\n' '\n' - ' Calling the asynchronous iterator\'s "aiterator.__anext__()"\n' + ' Calling the asynchronous iterator?s "aiterator.__anext__()"\n' ' method will return an *awaitable* which when awaited will\n' ' execute until it provides a value using the "yield" ' 'expression.\n' @@ -11360,9 +11346,9 @@ 'of\n' ' the arguments are determined by the C function. Special ' 'read-\n' - ' only attributes: "__doc__" is the function\'s documentation\n' + ' only attributes: "__doc__" is the function?s documentation\n' ' string, or "None" if unavailable; "__name__" is the ' - "function's\n" + 'function?s\n' ' name; "__self__" is set to "None" (but see the next item);\n' ' "__module__" is the name of the module the function was ' 'defined\n' @@ -11405,16 +11391,16 @@ ' translated to lookups in this dictionary, e.g., "m.x" is ' 'equivalent\n' ' to "m.__dict__["x"]". A module object does not contain the code\n' - " object used to initialize the module (since it isn't needed " + ' object used to initialize the module (since it isn?t needed ' 'once\n' ' the initialization is done).\n' '\n' - " Attribute assignment updates the module's namespace dictionary,\n" + ' Attribute assignment updates the module?s namespace dictionary,\n' ' e.g., "m.x = 1" is equivalent to "m.__dict__["x"] = 1".\n' '\n' - ' Predefined (writable) attributes: "__name__" is the module\'s ' + ' Predefined (writable) attributes: "__name__" is the module?s ' 'name;\n' - ' "__doc__" is the module\'s documentation string, or "None" if\n' + ' "__doc__" is the module?s documentation string, or "None" if\n' ' unavailable; "__annotations__" (optional) is a dictionary\n' ' containing *variable annotations* collected during module body\n' ' execution; "__file__" is the pathname of the file from which ' @@ -11427,7 +11413,7 @@ 'is\n' ' the pathname of the shared library file.\n' '\n' - ' Special read-only attribute: "__dict__" is the module\'s ' + ' Special read-only attribute: "__dict__" is the module?s ' 'namespace\n' ' as a dictionary object.\n' '\n' @@ -11456,7 +11442,7 @@ ' classes. This search of the base classes uses the C3 method\n' ' resolution order which behaves correctly even in the presence ' 'of\n' - " 'diamond' inheritance structures where there are multiple\n" + ' ?diamond? inheritance structures where there are multiple\n' ' inheritance paths leading back to a common ancestor. Additional\n' ' details on the C3 MRO used by Python can be found in the\n' ' documentation accompanying the 2.3 release at\n' @@ -11475,7 +11461,7 @@ 'differ\n' ' from those actually contained in its "__dict__".\n' '\n' - " Class attribute assignments update the class's dictionary, " + ' Class attribute assignments update the class?s dictionary, ' 'never\n' ' the dictionary of a base class.\n' '\n' @@ -11487,11 +11473,11 @@ 'is\n' ' the module name in which the class was defined; "__dict__" is ' 'the\n' - ' dictionary containing the class\'s namespace; "__bases__" is a ' + ' dictionary containing the class?s namespace; "__bases__" is a ' 'tuple\n' ' containing the base classes, in the order of their occurrence ' 'in\n' - ' the base class list; "__doc__" is the class\'s documentation ' + ' the base class list; "__doc__" is the class?s documentation ' 'string,\n' ' or "None" if undefined; "__annotations__" (optional) is a\n' ' dictionary containing *variable annotations* collected during ' @@ -11504,7 +11490,7 @@ ' A class instance has a namespace implemented as a dictionary ' 'which\n' ' is the first place in which attribute references are searched.\n' - " When an attribute is not found there, and the instance's class " + ' When an attribute is not found there, and the instance?s class ' 'has\n' ' an attribute by that name, the search continues with the class\n' ' attributes. If a class attribute is found that is a ' @@ -11513,17 +11499,17 @@ 'object\n' ' whose "__self__" attribute is the instance. Static method and\n' ' class method objects are also transformed; see above under\n' - ' "Classes". See section Implementing Descriptors for another way ' + ' ?Classes?. See section Implementing Descriptors for another way ' 'in\n' ' which attributes of a class retrieved via its instances may ' 'differ\n' - ' from the objects actually stored in the class\'s "__dict__". If ' + ' from the objects actually stored in the class?s "__dict__". If ' 'no\n' - " class attribute is found, and the object's class has a\n" + ' class attribute is found, and the object?s class has a\n' ' "__getattr__()" method, that is called to satisfy the lookup.\n' '\n' - " Attribute assignments and deletions update the instance's\n" - " dictionary, never a class's dictionary. If the class has a\n" + ' Attribute assignments and deletions update the instance?s\n' + ' dictionary, never a class?s dictionary. If the class has a\n' ' "__setattr__()" or "__delattr__()" method, this is called ' 'instead\n' ' of updating the instance dictionary directly.\n' @@ -11534,7 +11520,7 @@ ' Special method names.\n' '\n' ' Special attributes: "__dict__" is the attribute dictionary;\n' - ' "__class__" is the instance\'s class.\n' + ' "__class__" is the instance?s class.\n' '\n' 'I/O objects (also known as file objects)\n' ' A *file object* represents an open file. Various shortcuts are\n' @@ -11546,7 +11532,7 @@ ' provided by extension modules).\n' '\n' ' The objects "sys.stdin", "sys.stdout" and "sys.stderr" are\n' - " initialized to file objects corresponding to the interpreter's\n" + ' initialized to file objects corresponding to the interpreter?s\n' ' standard input, output and error streams; they are all open in ' 'text\n' ' mode and therefore follow the interface defined by the\n' @@ -11564,7 +11550,7 @@ ' or *bytecode*. The difference between a code object and a\n' ' function object is that the function object contains an ' 'explicit\n' - " reference to the function's globals (the module in which it " + ' reference to the function?s globals (the module in which it ' 'was\n' ' defined), while a code object contains no context; also the\n' ' default argument values are stored in the function object, ' @@ -11667,13 +11653,12 @@ ' undefined interpreter behaviour if exceptions raised by the\n' ' trace function escape to the function being traced.\n' '\n' - ' "f_lineno" is the current line number of the frame --- ' - 'writing\n' - ' to this from within a trace function jumps to the given line\n' - ' (only for the bottom-most frame). A debugger can implement ' - 'a\n' - ' Jump command (aka Set Next Statement) by writing to ' - 'f_lineno.\n' + ' "f_lineno" is the current line number of the frame ? writing ' + 'to\n' + ' this from within a trace function jumps to the given line ' + '(only\n' + ' for the bottom-most frame). A debugger can implement a Jump\n' + ' command (aka Set Next Statement) by writing to f_lineno.\n' '\n' ' Frame objects support one method:\n' '\n' @@ -11799,7 +11784,7 @@ ' is retrieved from classes and class instances. The behaviour ' 'of\n' ' class method objects upon such retrieval is described above,\n' - ' under "User-defined methods". Class method objects are ' + ' under ?User-defined methods?. Class method objects are ' 'created\n' ' by the built-in "classmethod()" constructor.\n', 'typesfunctions': 'Functions\n' @@ -11819,8 +11804,8 @@ 'different object types.\n' '\n' 'See Function definitions for more information.\n', - 'typesmapping': 'Mapping Types --- "dict"\n' - '************************\n' + 'typesmapping': 'Mapping Types ? "dict"\n' + '**********************\n' '\n' 'A *mapping* object maps *hashable* values to arbitrary ' 'objects.\n' @@ -11831,7 +11816,7 @@ 'in "list", "set", and "tuple" classes, and the "collections" ' 'module.)\n' '\n' - "A dictionary's keys are *almost* arbitrary values. Values " + 'A dictionary?s keys are *almost* arbitrary values. Values ' 'that are\n' 'not *hashable*, that is, values containing lists, ' 'dictionaries or\n' @@ -12007,13 +11992,13 @@ '\n' ' items()\n' '\n' - ' Return a new view of the dictionary\'s items ("(key, ' + ' Return a new view of the dictionary?s items ("(key, ' 'value)"\n' ' pairs). See the documentation of view objects.\n' '\n' ' keys()\n' '\n' - " Return a new view of the dictionary's keys. See the\n" + ' Return a new view of the dictionary?s keys. See the\n' ' documentation of view objects.\n' '\n' ' pop(key[, default])\n' @@ -12061,14 +12046,14 @@ '\n' ' values()\n' '\n' - " Return a new view of the dictionary's values. See " + ' Return a new view of the dictionary?s values. See ' 'the\n' ' documentation of view objects.\n' '\n' ' Dictionaries compare equal if and only if they have the ' 'same "(key,\n' - ' value)" pairs. Order comparisons (\'<\', \'<=\', \'>=\', ' - "'>') raise\n" + ' value)" pairs. Order comparisons (?=?, ?>?) ' + 'raise\n' ' "TypeError".\n' '\n' 'See also: "types.MappingProxyType" can be used to create a ' @@ -12082,7 +12067,7 @@ 'The objects returned by "dict.keys()", "dict.values()" and\n' '"dict.items()" are *view objects*. They provide a dynamic ' 'view on the\n' - "dictionary's entries, which means that when the dictionary " + 'dictionary?s entries, which means that when the dictionary ' 'changes,\n' 'the view reflects these changes.\n' '\n' @@ -12100,31 +12085,26 @@ '(represented as\n' ' tuples of "(key, value)") in the dictionary.\n' '\n' - ' Keys and values are iterated over in an arbitrary order ' - 'which is\n' - ' non-random, varies across Python implementations, and ' - 'depends on\n' - " the dictionary's history of insertions and deletions. If " - 'keys,\n' - ' values and items views are iterated over with no ' - 'intervening\n' - ' modifications to the dictionary, the order of items will ' - 'directly\n' - ' correspond. This allows the creation of "(value, key)" ' - 'pairs using\n' - ' "zip()": "pairs = zip(d.values(), d.keys())". Another ' - 'way to\n' - ' create the same list is "pairs = [(v, k) for (k, v) in ' - 'd.items()]".\n' + ' Keys and values are iterated over in insertion order. ' + 'This allows\n' + ' the creation of "(value, key)" pairs using "zip()": ' + '"pairs =\n' + ' zip(d.values(), d.keys())". Another way to create the ' + 'same list is\n' + ' "pairs = [(v, k) for (k, v) in d.items()]".\n' '\n' ' Iterating views while adding or deleting entries in the ' 'dictionary\n' ' may raise a "RuntimeError" or fail to iterate over all ' 'entries.\n' '\n' + ' Changed in version 3.7: Dict order is guaranteed to be ' + 'insertion\n' + ' order.\n' + '\n' 'x in dictview\n' '\n' - ' Return "True" if *x* is in the underlying dictionary\'s ' + ' Return "True" if *x* is in the underlying dictionary?s ' 'keys, values\n' ' or items (in the latter case, *x* should be a "(key, ' 'value)"\n' @@ -12158,10 +12138,10 @@ ' >>> print(n)\n' ' 504\n' '\n' - ' >>> # keys and values are iterated over in the same ' - 'order\n' + ' >>> # keys and values are iterated over in the same order ' + '(insertion order)\n' ' >>> list(keys)\n' - " ['eggs', 'bacon', 'sausage', 'spam']\n" + " ['eggs', 'sausage', 'bacon', 'spam']\n" ' >>> list(values)\n' ' [2, 1, 1, 500]\n' '\n' @@ -12169,7 +12149,7 @@ " >>> del dishes['eggs']\n" " >>> del dishes['sausage']\n" ' >>> list(keys)\n' - " ['spam', 'bacon']\n" + " ['bacon', 'spam']\n" '\n' ' >>> # set operations\n' " >>> keys & {'eggs', 'bacon', 'salad'}\n" @@ -12239,7 +12219,7 @@ 'The only special operation on a module is attribute access: ' '"m.name",\n' 'where *m* is a module and *name* accesses a name defined in ' - "*m*'s\n" + '*m*?s\n' 'symbol table. Module attributes can be assigned to. (Note ' 'that the\n' '"import" statement is not, strictly speaking, an operation ' @@ -12252,14 +12232,14 @@ '\n' 'A special attribute of every module is "__dict__". This is ' 'the\n' - "dictionary containing the module's symbol table. Modifying " + 'dictionary containing the module?s symbol table. Modifying ' 'this\n' - "dictionary will actually change the module's symbol table, " + 'dictionary will actually change the module?s symbol table, ' 'but direct\n' 'assignment to the "__dict__" attribute is not possible (you ' 'can write\n' '"m.__dict__[\'a\'] = 1", which defines "m.a" to be "1", but ' - "you can't\n" + 'you can?t\n' 'write "m.__dict__ = {}"). Modifying "__dict__" directly is ' 'not\n' 'recommended.\n' @@ -12270,8 +12250,8 @@ 'written as\n' '"".\n', - 'typesseq': 'Sequence Types --- "list", "tuple", "range"\n' - '*******************************************\n' + 'typesseq': 'Sequence Types ? "list", "tuple", "range"\n' + '*****************************************\n' '\n' 'There are three basic sequence types: lists, tuples, and range\n' 'objects. Additional sequence types tailored for processing of ' @@ -12445,7 +12425,7 @@ '*j* are\n' ' reduced to "len(s) - 1" if they are greater. If *i* or *j* ' 'are\n' - ' omitted or "None", they become "end" values (which end ' + ' omitted or "None", they become ?end? values (which end ' 'depends on\n' ' the sign of *k*). Note, *k* cannot be zero. If *k* is ' '"None", it\n' @@ -12476,7 +12456,7 @@ 'documentation\n' '\n' '7. Some sequence types (such as "range") only support item\n' - " sequences that follow specific patterns, and hence don't " + ' sequences that follow specific patterns, and hence don?t ' 'support\n' ' sequence concatenation or repetition.\n' '\n' @@ -12633,7 +12613,7 @@ ' sequence.\n' '\n' '5. "clear()" and "copy()" are included for consistency with the\n' - " interfaces of mutable containers that don't support slicing\n" + ' interfaces of mutable containers that don?t support slicing\n' ' operations (such as "dict" and "set")\n' '\n' ' New in version 3.3: "clear()" and "copy()" methods.\n' @@ -12673,7 +12653,7 @@ '\n' ' The constructor builds a list whose items are the same and in ' 'the\n' - " same order as *iterable*'s items. *iterable* may be either " + ' same order as *iterable*?s items. *iterable* may be either ' 'a\n' ' sequence, a container that supports iteration, or an ' 'iterator\n' @@ -12740,8 +12720,8 @@ 'is\n' ' stable if it guarantees not to change the relative order ' 'of\n' - ' elements that compare equal --- this is helpful for ' - 'sorting in\n' + ' elements that compare equal ? this is helpful for sorting ' + 'in\n' ' multiple passes (for example, sort by department, then by ' 'salary\n' ' grade).\n' @@ -12787,7 +12767,7 @@ '\n' ' The constructor builds a tuple whose items are the same and ' 'in the\n' - " same order as *iterable*'s items. *iterable* may be either " + ' same order as *iterable*?s items. *iterable* may be either ' 'a\n' ' sequence, a container that supports iteration, or an ' 'iterator\n' @@ -12916,7 +12896,7 @@ 'Range objects implement the "collections.abc.Sequence" ABC, and\n' 'provide features such as containment tests, element index ' 'lookup,\n' - 'slicing and support for negative indices (see Sequence Types --- ' + 'slicing and support for negative indices (see Sequence Types ? ' 'list,\n' 'tuple, range):\n' '\n' @@ -12954,7 +12934,7 @@ 'constant\n' 'time instead of iterating through all items.\n' '\n' - "Changed in version 3.3: Define '==' and '!=' to compare range " + 'Changed in version 3.3: Define ?==? and ?!=? to compare range ' 'objects\n' 'based on the sequence of values they define (instead of ' 'comparing\n' @@ -13093,7 +13073,7 @@ '\n' '5. "clear()" and "copy()" are included for consistency ' 'with the\n' - " interfaces of mutable containers that don't support " + ' interfaces of mutable containers that don?t support ' 'slicing\n' ' operations (such as "dict" and "set")\n' '\n' @@ -13148,7 +13128,7 @@ '\n' 'A "break" statement executed in the first suite terminates the ' 'loop\n' - 'without executing the "else" clause\'s suite. A "continue" ' + 'without executing the "else" clause?s suite. A "continue" ' 'statement\n' 'executed in the first suite skips the rest of the suite and goes ' 'back\n' @@ -13158,21 +13138,22 @@ '\n' 'The "with" statement is used to wrap the execution of a block with\n' 'methods defined by a context manager (see section With Statement\n' - 'Context Managers). This allows common "try"..."except"..."finally"\n' - 'usage patterns to be encapsulated for convenient reuse.\n' + 'Context Managers). This allows common "try"?"except"?"finally" ' + 'usage\n' + 'patterns to be encapsulated for convenient reuse.\n' '\n' ' with_stmt ::= "with" with_item ("," with_item)* ":" suite\n' ' with_item ::= expression ["as" target]\n' '\n' - 'The execution of the "with" statement with one "item" proceeds as\n' + 'The execution of the "with" statement with one ?item? proceeds as\n' 'follows:\n' '\n' '1. The context expression (the expression given in the "with_item")\n' ' is evaluated to obtain a context manager.\n' '\n' - '2. The context manager\'s "__exit__()" is loaded for later use.\n' + '2. The context manager?s "__exit__()" is loaded for later use.\n' '\n' - '3. The context manager\'s "__enter__()" method is invoked.\n' + '3. The context manager?s "__enter__()" method is invoked.\n' '\n' '4. If a target was included in the "with" statement, the return\n' ' value from "__enter__()" is assigned to it.\n' @@ -13186,7 +13167,7 @@ '\n' '5. The suite is executed.\n' '\n' - '6. The context manager\'s "__exit__()" method is invoked. If an\n' + '6. The context manager?s "__exit__()" method is invoked. If an\n' ' exception caused the suite to be exited, its type, value, and\n' ' traceback are passed as arguments to "__exit__()". Otherwise, ' 'three\n' @@ -13222,7 +13203,7 @@ '\n' 'See also:\n' '\n' - ' **PEP 343** - The "with" statement\n' + ' **PEP 343** - The ?with? statement\n' ' The specification, background, and examples for the Python ' '"with"\n' ' statement.\n', diff --git a/Misc/NEWS.d/3.7.0b4.rst b/Misc/NEWS.d/3.7.0b4.rst new file mode 100644 index 000000000000..a6cae2819182 --- /dev/null +++ b/Misc/NEWS.d/3.7.0b4.rst @@ -0,0 +1,466 @@ +.. bpo: 33363 +.. date: 2018-04-26-22-48-28 +.. nonce: 8RCnN2 +.. release date: 2018-05-02 +.. section: Core and Builtins + +Raise a SyntaxError for ``async with`` and ``async for`` statements outside +of async functions. + +.. + +.. bpo: 33128 +.. date: 2018-04-24-22-31-04 +.. nonce: g2yLuf +.. section: Core and Builtins + +Fix a bug that causes PathFinder to appear twice on sys.meta_path. Patch by +Pablo Galindo Salgado. + +.. + +.. bpo: 33312 +.. date: 2018-04-19-08-30-07 +.. nonce: mDe2iL +.. section: Core and Builtins + +Fixed clang ubsan (undefined behavior sanitizer) warnings in dictobject.c by +adjusting how the internal struct _dictkeysobject shared keys structure is +declared. + +.. + +.. bpo: 33231 +.. date: 2018-04-05-22-20-44 +.. nonce: 3Jmo0q +.. section: Core and Builtins + +Fix potential memory leak in ``normalizestring()``. + +.. + +.. bpo: 33205 +.. date: 2018-04-03-00-58-41 +.. nonce: lk2F3r +.. section: Core and Builtins + +Change dict growth function from +``round_up_to_power_2(used*2+hashtable_size/2)`` to +``round_up_to_power_2(used*3)``. Previously, dict is shrinked only when +``used == 0``. Now dict has more chance to be shrinked. + +.. + +.. bpo: 29922 +.. date: 2018-04-03-00-30-25 +.. nonce: CdLuMl +.. section: Core and Builtins + +Improved error messages in 'async with' when ``__aenter__()`` or +``__aexit__()`` return non-awaitable object. + +.. + +.. bpo: 33199 +.. date: 2018-04-02-09-32-40 +.. nonce: TPnxQu +.. section: Core and Builtins + +Fix ``ma_version_tag`` in dict implementation is uninitialized when copying +from key-sharing dict. + +.. + +.. bpo: 33281 +.. date: 2018-05-01-22-35-50 +.. nonce: d4jOt4 +.. section: Library + +Fix ctypes.util.find_library regression on macOS. + +.. + +.. bpo: 33383 +.. date: 2018-04-29-11-15-38 +.. nonce: g32YWn +.. section: Library + +Fixed crash in the get() method of the :mod:`dbm.ndbm` database object when +it is called with a single argument. + +.. + +.. bpo: 33329 +.. date: 2018-04-23-13-21-39 +.. nonce: lQ-Eod +.. section: Library + +Fix multiprocessing regression on newer glibcs + +.. + +.. bpo: 991266 +.. date: 2018-04-21-00-24-08 +.. nonce: h93TP_ +.. section: Library + +Fix quoting of the ``Comment`` attribute of +:class:`http.cookies.SimpleCookie`. + +.. + +.. bpo: 33131 +.. date: 2018-04-20-10-43-17 +.. nonce: L2E977 +.. section: Library + +Upgrade bundled version of pip to 10.0.1. + +.. + +.. bpo: 33308 +.. date: 2018-04-18-19-12-25 +.. nonce: fW75xi +.. section: Library + +Fixed a crash in the :mod:`parser` module when converting an ST object to a +tree of tuples or lists with ``line_info=False`` and ``col_info=True``. + +.. + +.. bpo: 33266 +.. date: 2018-04-16-15-59-21 +.. nonce: w2PAm- +.. section: Library + +lib2to3 now recognizes ``rf'...'`` strings. + +.. + +.. bpo: 11594 +.. date: 2018-04-16-08-42-03 +.. nonce: QLo4vv +.. section: Library + +Ensure line-endings are respected when using lib2to3. + +.. + +.. bpo: 33254 +.. date: 2018-04-13-15-14-47 +.. nonce: DS4KFK +.. section: Library + +Have :func:`importlib.resources.contents` and +:meth:`importlib.abc.ResourceReader.contents` return an :term:`iterable` +instead of an :term:`iterator`. + +.. + +.. bpo: 33256 +.. date: 2018-04-10-20-57-14 +.. nonce: ndHkqu +.. section: Library + +Fix display of ```` call in the html produced by ``cgitb.html()``. +Patch by St?phane Blondon. + +.. + +.. bpo: 33185 +.. date: 2018-04-08-22-54-07 +.. nonce: Id-Ba9 +.. section: Library + +Fixed regression when running pydoc with the :option:`-m` switch. (The +regression was introduced in 3.7.0b3 by the resolution of :issue:`33053`) + +This fix also changed pydoc to add ``os.getcwd()`` to :data:`sys.path` when +necessary, rather than adding ``"."``. + +.. + +.. bpo: 33169 +.. date: 2018-04-06-14-56-26 +.. nonce: ByhDqb +.. section: Library + +Delete entries of ``None`` in :data:`sys.path_importer_cache` when +:meth:`importlib.machinery.invalidate_caches` is called. + +.. + +.. bpo: 33217 +.. date: 2018-04-05-13-36-09 +.. nonce: FfOKDI +.. section: Library + +Deprecate looking up non-Enum objects in Enum classes and Enum members (will +raise :exc:`TypeError` in 3.8+). + +.. + +.. bpo: 33203 +.. date: 2018-04-05-11-09-45 +.. nonce: Hje9Py +.. section: Library + +``random.Random.choice()`` now raises ``IndexError`` for empty sequences +consistently even when called from subclasses without a ``getrandbits()`` +implementation. + +.. + +.. bpo: 33224 +.. date: 2018-04-04-23-41-30 +.. nonce: pyR0jB +.. section: Library + +Update difflib.mdiff() for PEP 479. Convert an uncaught StopIteration in a +generator into a return-statement. + +.. + +.. bpo: 33209 +.. date: 2018-04-03-10-37-13 +.. nonce: 9sGWE_ +.. section: Library + +End framing at the end of C implementation of :func:`pickle.Pickler.dump`. + +.. + +.. bpo: 20104 +.. date: 2018-04-01-19-21-04 +.. nonce: -AKcGa +.. section: Library + +Improved error handling and fixed a reference leak in +:func:`os.posix_spawn()`. + +.. + +.. bpo: 33175 +.. date: 2018-03-29-04-32-25 +.. nonce: _zs1yM +.. section: Library + +In dataclasses, Field.__set_name__ now looks up the __set_name__ special +method on the class, not the instance, of the default value. + +.. + +.. bpo: 33097 +.. date: 2018-03-18-16-48-23 +.. nonce: Yl4gI2 +.. section: Library + +Raise RuntimeError when ``executor.submit`` is called during interpreter +shutdown. + +.. + +.. bpo: 31908 +.. date: 2017-10-31 +.. nonce: g4xh8x +.. section: Library + +Fix output of cover files for ``trace`` module command-line tool. Previously +emitted cover files only when ``--missing`` option was used. Patch by +Michael Selik. + +.. + +.. bpo: 33378 +.. date: 2018-04-29-04-02-18 +.. nonce: -anAHN +.. section: Documentation + +Add Korean language switcher for https://docs.python.org/3/ + +.. + +.. bpo: 33276 +.. date: 2018-04-20-14-09-36 +.. nonce: rA1z_3 +.. section: Documentation + +Clarify that the ``__path__`` attribute on modules cannot be just any value. + +.. + +.. bpo: 33201 +.. date: 2018-04-01-21-03-41 +.. nonce: aa8Lkl +.. section: Documentation + +Modernize documentation for writing C extension types. + +.. + +.. bpo: 33195 +.. date: 2018-04-01-14-30-36 +.. nonce: dRS-XX +.. section: Documentation + +Deprecate ``Py_UNICODE`` usage in ``c-api/arg`` document. ``Py_UNICODE`` +related APIs are deprecated since Python 3.3, but it is missed in the +document. + +.. + +.. bpo: 8243 +.. date: 2018-01-13-20-30-53 +.. nonce: s98r28 +.. section: Documentation + +Add a note about curses.addch and curses.addstr exception behavior when +writing outside a window, or pad. + +.. + +.. bpo: 32337 +.. date: 2017-12-22-17-29-37 +.. nonce: eZe-ID +.. section: Documentation + +Update documentation related with ``dict`` order. + +.. + +.. bpo: 33358 +.. date: 2018-04-27-11-46-35 +.. nonce: _OcR59 +.. section: Tests + +Fix ``test_embed.test_pre_initialization_sys_options()`` when the +interpreter is built with ``--enable-shared``. + +.. + +.. bpo: 33394 +.. date: 2018-04-30-17-36-46 +.. nonce: _Vdi4t +.. section: Build + +Enable the verbose build for extension modules, when GNU make is passed +macros on the command line. + +.. + +.. bpo: 33393 +.. date: 2018-04-30-17-19-37 +.. nonce: HkVCqI +.. section: Build + +Update config.guess and config.sub files. + +.. + +.. bpo: 33377 +.. date: 2018-04-30-16-53-00 +.. nonce: QBh6vP +.. section: Build + +Add new triplets for mips r6 and riscv variants (used in extension +suffixes). + +.. + +.. bpo: 32232 +.. date: 2018-04-17-00-38-19 +.. nonce: o7G_UO +.. section: Build + +By default, modules configured in `Modules/Setup` are no longer built with +`-DPy_BUILD_CORE`. Instead, modules that specifically need that preprocessor +definition include it in their individual entries. + +.. + +.. bpo: 33182 +.. date: 2018-03-30-14-55-48 +.. nonce: CePczb +.. section: Build + +The embedding tests can once again be built with clang 6.0 + +.. + +.. bpo: 33184 +.. date: 2018-04-13-11-28-55 +.. nonce: 7YhqQE +.. section: Windows + +Update Windows installer to use OpenSSL 1.1.0h. + +.. + +.. bpo: 33184 +.. date: 2018-04-07-00-51-34 +.. nonce: 3j208P +.. section: macOS + +Update macOS installer build to use OpenSSL 1.1.0h. + +.. + +.. bpo: 21474 +.. date: 2018-04-29-16-13-02 +.. nonce: bglg-F +.. section: IDLE + +Update word/identifier definition from ascii to unicode. In text and entry +boxes, this affects selection by double-click, movement left/right by +control-left/right, and deletion left/right by control-BACKSPACE/DEL. + +.. + +.. bpo: 33204 +.. date: 2018-04-02-00-28-13 +.. nonce: NBsuIv +.. section: IDLE + +IDLE: consistently color invalid string prefixes. A 'u' string prefix cannot +be paired with either 'r' or 'f'. Consistently color as much of the prefix, +starting at the right, as is valid. Revise and extend colorizer test. + +.. + +.. bpo: 33189 +.. date: 2018-04-03-18-10-00 +.. nonce: QrXR00 +.. section: Tools/Demos + +:program:`pygettext.py` now recognizes only literal strings as docstrings +and translatable strings, and rejects bytes literals and f-string +expressions. + +.. + +.. bpo: 31920 +.. date: 2018-03-26-18-54-24 +.. nonce: u_WKsT +.. section: Tools/Demos + +Fixed handling directories as arguments in the ``pygettext`` script. Based +on patch by Oleg Krasnikov. + +.. + +.. bpo: 29673 +.. date: 2018-03-16-17-25-05 +.. nonce: m8QtaW +.. section: Tools/Demos + +Fix pystackv and pystack gdbinit macros. + +.. + +.. bpo: 31583 +.. date: 2017-09-26-10-11-21 +.. nonce: TM90_H +.. section: Tools/Demos + +Fix 2to3 for using with --add-suffix option but without --output-dir option +for relative path to files in current directory. diff --git a/Misc/NEWS.d/next/Build/2018-03-30-14-55-48.bpo-33182.CePczb.rst b/Misc/NEWS.d/next/Build/2018-03-30-14-55-48.bpo-33182.CePczb.rst deleted file mode 100644 index 6310e5d5b557..000000000000 --- a/Misc/NEWS.d/next/Build/2018-03-30-14-55-48.bpo-33182.CePczb.rst +++ /dev/null @@ -1 +0,0 @@ -The embedding tests can once again be built with clang 6.0 diff --git a/Misc/NEWS.d/next/Build/2018-04-17-00-38-19.bpo-32232.o7G_UO.rst b/Misc/NEWS.d/next/Build/2018-04-17-00-38-19.bpo-32232.o7G_UO.rst deleted file mode 100644 index fea0b60fcedd..000000000000 --- a/Misc/NEWS.d/next/Build/2018-04-17-00-38-19.bpo-32232.o7G_UO.rst +++ /dev/null @@ -1,3 +0,0 @@ -By default, modules configured in `Modules/Setup` are no longer built with -`-DPy_BUILD_CORE`. Instead, modules that specifically need that preprocessor -definition include it in their individual entries. diff --git a/Misc/NEWS.d/next/Build/2018-04-30-16-53-00.bpo-33377.QBh6vP.rst b/Misc/NEWS.d/next/Build/2018-04-30-16-53-00.bpo-33377.QBh6vP.rst deleted file mode 100644 index f5dbd23c7c35..000000000000 --- a/Misc/NEWS.d/next/Build/2018-04-30-16-53-00.bpo-33377.QBh6vP.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add new triplets for mips r6 and riscv variants (used in extension -suffixes). diff --git a/Misc/NEWS.d/next/Build/2018-04-30-17-19-37.bpo-33393.HkVCqI.rst b/Misc/NEWS.d/next/Build/2018-04-30-17-19-37.bpo-33393.HkVCqI.rst deleted file mode 100644 index f3317e7e68f3..000000000000 --- a/Misc/NEWS.d/next/Build/2018-04-30-17-19-37.bpo-33393.HkVCqI.rst +++ /dev/null @@ -1 +0,0 @@ -Update config.guess and config.sub files. diff --git a/Misc/NEWS.d/next/Build/2018-04-30-17-36-46.bpo-33394._Vdi4t.rst b/Misc/NEWS.d/next/Build/2018-04-30-17-36-46.bpo-33394._Vdi4t.rst deleted file mode 100644 index b25fbb02c406..000000000000 --- a/Misc/NEWS.d/next/Build/2018-04-30-17-36-46.bpo-33394._Vdi4t.rst +++ /dev/null @@ -1,2 +0,0 @@ -Enable the verbose build for extension modules, when GNU make is passed -macros on the command line. diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-04-02-09-32-40.bpo-33199.TPnxQu.rst b/Misc/NEWS.d/next/Core and Builtins/2018-04-02-09-32-40.bpo-33199.TPnxQu.rst deleted file mode 100644 index 22abf8d00011..000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2018-04-02-09-32-40.bpo-33199.TPnxQu.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix ``ma_version_tag`` in dict implementation is uninitialized when copying -from key-sharing dict. diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-04-03-00-30-25.bpo-29922.CdLuMl.rst b/Misc/NEWS.d/next/Core and Builtins/2018-04-03-00-30-25.bpo-29922.CdLuMl.rst deleted file mode 100644 index d8c144e59d6c..000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2018-04-03-00-30-25.bpo-29922.CdLuMl.rst +++ /dev/null @@ -1,2 +0,0 @@ -Improved error messages in 'async with' when ``__aenter__()`` or -``__aexit__()`` return non-awaitable object. diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-04-03-00-58-41.bpo-33205.lk2F3r.rst b/Misc/NEWS.d/next/Core and Builtins/2018-04-03-00-58-41.bpo-33205.lk2F3r.rst deleted file mode 100644 index 44511865abfa..000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2018-04-03-00-58-41.bpo-33205.lk2F3r.rst +++ /dev/null @@ -1,3 +0,0 @@ -Change dict growth function from ``round_up_to_power_2(used*2+hashtable_size/2)`` to -``round_up_to_power_2(used*3)``. Previously, dict is shrinked only when ``used == 0``. -Now dict has more chance to be shrinked. diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-04-05-22-20-44.bpo-33231.3Jmo0q.rst b/Misc/NEWS.d/next/Core and Builtins/2018-04-05-22-20-44.bpo-33231.3Jmo0q.rst deleted file mode 100644 index de54fbb52671..000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2018-04-05-22-20-44.bpo-33231.3Jmo0q.rst +++ /dev/null @@ -1 +0,0 @@ -Fix potential memory leak in ``normalizestring()``. diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-04-19-08-30-07.bpo-33312.mDe2iL.rst b/Misc/NEWS.d/next/Core and Builtins/2018-04-19-08-30-07.bpo-33312.mDe2iL.rst deleted file mode 100644 index 40b51b902c9f..000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2018-04-19-08-30-07.bpo-33312.mDe2iL.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fixed clang ubsan (undefined behavior sanitizer) warnings in dictobject.c by -adjusting how the internal struct _dictkeysobject shared keys structure is -declared. diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-04-24-22-31-04.bpo-33128.g2yLuf.rst b/Misc/NEWS.d/next/Core and Builtins/2018-04-24-22-31-04.bpo-33128.g2yLuf.rst deleted file mode 100644 index 66b98cdf51cf..000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2018-04-24-22-31-04.bpo-33128.g2yLuf.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix a bug that causes PathFinder to appear twice on sys.meta_path. Patch by -Pablo Galindo Salgado. diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-04-26-22-48-28.bpo-33363.8RCnN2.rst b/Misc/NEWS.d/next/Core and Builtins/2018-04-26-22-48-28.bpo-33363.8RCnN2.rst deleted file mode 100644 index ad8d24895343..000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2018-04-26-22-48-28.bpo-33363.8RCnN2.rst +++ /dev/null @@ -1,2 +0,0 @@ -Raise a SyntaxError for ``async with`` and ``async for`` statements outside -of async functions. diff --git a/Misc/NEWS.d/next/Documentation/2017-12-22-17-29-37.bpo-32337.eZe-ID.rst b/Misc/NEWS.d/next/Documentation/2017-12-22-17-29-37.bpo-32337.eZe-ID.rst deleted file mode 100644 index a905467cd59f..000000000000 --- a/Misc/NEWS.d/next/Documentation/2017-12-22-17-29-37.bpo-32337.eZe-ID.rst +++ /dev/null @@ -1 +0,0 @@ -Update documentation related with ``dict`` order. diff --git a/Misc/NEWS.d/next/Documentation/2018-01-13-20-30-53.bpo-8243.s98r28.rst b/Misc/NEWS.d/next/Documentation/2018-01-13-20-30-53.bpo-8243.s98r28.rst deleted file mode 100644 index a3520d05c095..000000000000 --- a/Misc/NEWS.d/next/Documentation/2018-01-13-20-30-53.bpo-8243.s98r28.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add a note about curses.addch and curses.addstr exception behavior when -writing outside a window, or pad. diff --git a/Misc/NEWS.d/next/Documentation/2018-04-01-14-30-36.bpo-33195.dRS-XX.rst b/Misc/NEWS.d/next/Documentation/2018-04-01-14-30-36.bpo-33195.dRS-XX.rst deleted file mode 100644 index 6884640325b0..000000000000 --- a/Misc/NEWS.d/next/Documentation/2018-04-01-14-30-36.bpo-33195.dRS-XX.rst +++ /dev/null @@ -1,3 +0,0 @@ -Deprecate ``Py_UNICODE`` usage in ``c-api/arg`` document. ``Py_UNICODE`` -related APIs are deprecated since Python 3.3, but it is missed in the -document. diff --git a/Misc/NEWS.d/next/Documentation/2018-04-01-21-03-41.bpo-33201.aa8Lkl.rst b/Misc/NEWS.d/next/Documentation/2018-04-01-21-03-41.bpo-33201.aa8Lkl.rst deleted file mode 100644 index bdee48ba0314..000000000000 --- a/Misc/NEWS.d/next/Documentation/2018-04-01-21-03-41.bpo-33201.aa8Lkl.rst +++ /dev/null @@ -1 +0,0 @@ -Modernize documentation for writing C extension types. diff --git a/Misc/NEWS.d/next/Documentation/2018-04-20-14-09-36.bpo-33276.rA1z_3.rst b/Misc/NEWS.d/next/Documentation/2018-04-20-14-09-36.bpo-33276.rA1z_3.rst deleted file mode 100644 index 0da58a0ce4c8..000000000000 --- a/Misc/NEWS.d/next/Documentation/2018-04-20-14-09-36.bpo-33276.rA1z_3.rst +++ /dev/null @@ -1 +0,0 @@ -Clarify that the ``__path__`` attribute on modules cannot be just any value. diff --git a/Misc/NEWS.d/next/Documentation/2018-04-29-04-02-18.bpo-33378.-anAHN.rst b/Misc/NEWS.d/next/Documentation/2018-04-29-04-02-18.bpo-33378.-anAHN.rst deleted file mode 100644 index 43214d10b7c5..000000000000 --- a/Misc/NEWS.d/next/Documentation/2018-04-29-04-02-18.bpo-33378.-anAHN.rst +++ /dev/null @@ -1 +0,0 @@ -Add Korean language switcher for https://docs.python.org/3/ diff --git a/Misc/NEWS.d/next/IDLE/2018-04-02-00-28-13.bpo-33204.NBsuIv.rst b/Misc/NEWS.d/next/IDLE/2018-04-02-00-28-13.bpo-33204.NBsuIv.rst deleted file mode 100644 index 3ae937bab930..000000000000 --- a/Misc/NEWS.d/next/IDLE/2018-04-02-00-28-13.bpo-33204.NBsuIv.rst +++ /dev/null @@ -1,3 +0,0 @@ -IDLE: consistently color invalid string prefixes. A 'u' string prefix cannot -be paired with either 'r' or 'f'. Consistently color as much of the prefix, -starting at the right, as is valid. Revise and extend colorizer test. diff --git a/Misc/NEWS.d/next/IDLE/2018-04-29-16-13-02.bpo-21474.bglg-F.rst b/Misc/NEWS.d/next/IDLE/2018-04-29-16-13-02.bpo-21474.bglg-F.rst deleted file mode 100644 index caf640b73b29..000000000000 --- a/Misc/NEWS.d/next/IDLE/2018-04-29-16-13-02.bpo-21474.bglg-F.rst +++ /dev/null @@ -1,3 +0,0 @@ -Update word/identifier definition from ascii to unicode. In text and entry -boxes, this affects selection by double-click, movement left/right by -control-left/right, and deletion left/right by control-BACKSPACE/DEL. diff --git a/Misc/NEWS.d/next/Library/2017-10-31.bpo-31908.g4xh8x.rst b/Misc/NEWS.d/next/Library/2017-10-31.bpo-31908.g4xh8x.rst deleted file mode 100644 index 700bc690764f..000000000000 --- a/Misc/NEWS.d/next/Library/2017-10-31.bpo-31908.g4xh8x.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix output of cover files for ``trace`` module command-line tool. -Previously emitted cover files only when ``--missing`` option was used. -Patch by Michael Selik. \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2018-03-18-16-48-23.bpo-33097.Yl4gI2.rst b/Misc/NEWS.d/next/Library/2018-03-18-16-48-23.bpo-33097.Yl4gI2.rst deleted file mode 100644 index d9411eb51623..000000000000 --- a/Misc/NEWS.d/next/Library/2018-03-18-16-48-23.bpo-33097.Yl4gI2.rst +++ /dev/null @@ -1,2 +0,0 @@ -Raise RuntimeError when ``executor.submit`` is called during interpreter -shutdown. diff --git a/Misc/NEWS.d/next/Library/2018-03-29-04-32-25.bpo-33175._zs1yM.rst b/Misc/NEWS.d/next/Library/2018-03-29-04-32-25.bpo-33175._zs1yM.rst deleted file mode 100644 index c872499cd679..000000000000 --- a/Misc/NEWS.d/next/Library/2018-03-29-04-32-25.bpo-33175._zs1yM.rst +++ /dev/null @@ -1,2 +0,0 @@ -In dataclasses, Field.__set_name__ now looks up the __set_name__ special -method on the class, not the instance, of the default value. diff --git a/Misc/NEWS.d/next/Library/2018-04-01-19-21-04.bpo-20104.-AKcGa.rst b/Misc/NEWS.d/next/Library/2018-04-01-19-21-04.bpo-20104.-AKcGa.rst deleted file mode 100644 index 150401dc7412..000000000000 --- a/Misc/NEWS.d/next/Library/2018-04-01-19-21-04.bpo-20104.-AKcGa.rst +++ /dev/null @@ -1 +0,0 @@ -Improved error handling and fixed a reference leak in :func:`os.posix_spawn()`. diff --git a/Misc/NEWS.d/next/Library/2018-04-03-10-37-13.bpo-33209.9sGWE_.rst b/Misc/NEWS.d/next/Library/2018-04-03-10-37-13.bpo-33209.9sGWE_.rst deleted file mode 100644 index d98b1e174e55..000000000000 --- a/Misc/NEWS.d/next/Library/2018-04-03-10-37-13.bpo-33209.9sGWE_.rst +++ /dev/null @@ -1 +0,0 @@ -End framing at the end of C implementation of :func:`pickle.Pickler.dump`. diff --git a/Misc/NEWS.d/next/Library/2018-04-04-23-41-30.bpo-33224.pyR0jB.rst b/Misc/NEWS.d/next/Library/2018-04-04-23-41-30.bpo-33224.pyR0jB.rst deleted file mode 100644 index 87ff100da4b6..000000000000 --- a/Misc/NEWS.d/next/Library/2018-04-04-23-41-30.bpo-33224.pyR0jB.rst +++ /dev/null @@ -1,2 +0,0 @@ -Update difflib.mdiff() for PEP 479. Convert an uncaught StopIteration in a -generator into a return-statement. diff --git a/Misc/NEWS.d/next/Library/2018-04-05-11-09-45.bpo-33203.Hje9Py.rst b/Misc/NEWS.d/next/Library/2018-04-05-11-09-45.bpo-33203.Hje9Py.rst deleted file mode 100644 index ab6d17b5d1ba..000000000000 --- a/Misc/NEWS.d/next/Library/2018-04-05-11-09-45.bpo-33203.Hje9Py.rst +++ /dev/null @@ -1,3 +0,0 @@ -``random.Random.choice()`` now raises ``IndexError`` for empty sequences -consistently even when called from subclasses without a ``getrandbits()`` -implementation. diff --git a/Misc/NEWS.d/next/Library/2018-04-05-13-36-09.bpo-33217.FfOKDI.rst b/Misc/NEWS.d/next/Library/2018-04-05-13-36-09.bpo-33217.FfOKDI.rst deleted file mode 100644 index 8dfc9e5a15c0..000000000000 --- a/Misc/NEWS.d/next/Library/2018-04-05-13-36-09.bpo-33217.FfOKDI.rst +++ /dev/null @@ -1,2 +0,0 @@ -Deprecate looking up non-Enum objects in Enum classes and Enum members (will -raise :exc:`TypeError` in 3.8+). diff --git a/Misc/NEWS.d/next/Library/2018-04-06-14-56-26.bpo-33169.ByhDqb.rst b/Misc/NEWS.d/next/Library/2018-04-06-14-56-26.bpo-33169.ByhDqb.rst deleted file mode 100644 index b5bacfcb5732..000000000000 --- a/Misc/NEWS.d/next/Library/2018-04-06-14-56-26.bpo-33169.ByhDqb.rst +++ /dev/null @@ -1,2 +0,0 @@ -Delete entries of ``None`` in :data:`sys.path_importer_cache` when -:meth:`importlib.machinery.invalidate_caches` is called. diff --git a/Misc/NEWS.d/next/Library/2018-04-08-22-54-07.bpo-33185.Id-Ba9.rst b/Misc/NEWS.d/next/Library/2018-04-08-22-54-07.bpo-33185.Id-Ba9.rst deleted file mode 100644 index 1f51d7e5120d..000000000000 --- a/Misc/NEWS.d/next/Library/2018-04-08-22-54-07.bpo-33185.Id-Ba9.rst +++ /dev/null @@ -1,5 +0,0 @@ -Fixed regression when running pydoc with the :option:`-m` switch. (The regression -was introduced in 3.7.0b3 by the resolution of :issue:`33053`) - -This fix also changed pydoc to add ``os.getcwd()`` to :data:`sys.path` when -necessary, rather than adding ``"."``. diff --git a/Misc/NEWS.d/next/Library/2018-04-10-20-57-14.bpo-33256.ndHkqu.rst b/Misc/NEWS.d/next/Library/2018-04-10-20-57-14.bpo-33256.ndHkqu.rst deleted file mode 100644 index a0605c04b4de..000000000000 --- a/Misc/NEWS.d/next/Library/2018-04-10-20-57-14.bpo-33256.ndHkqu.rst +++ /dev/null @@ -1 +0,0 @@ -Fix display of ```` call in the html produced by ``cgitb.html()``. Patch by St?phane Blondon. diff --git a/Misc/NEWS.d/next/Library/2018-04-13-15-14-47.bpo-33254.DS4KFK.rst b/Misc/NEWS.d/next/Library/2018-04-13-15-14-47.bpo-33254.DS4KFK.rst deleted file mode 100644 index c77a902524b8..000000000000 --- a/Misc/NEWS.d/next/Library/2018-04-13-15-14-47.bpo-33254.DS4KFK.rst +++ /dev/null @@ -1,3 +0,0 @@ -Have :func:`importlib.resources.contents` and -:meth:`importlib.abc.ResourceReader.contents` return an :term:`iterable` instead -of an :term:`iterator`. diff --git a/Misc/NEWS.d/next/Library/2018-04-16-08-42-03.bpo-11594.QLo4vv.rst b/Misc/NEWS.d/next/Library/2018-04-16-08-42-03.bpo-11594.QLo4vv.rst deleted file mode 100644 index be2abf6c34dd..000000000000 --- a/Misc/NEWS.d/next/Library/2018-04-16-08-42-03.bpo-11594.QLo4vv.rst +++ /dev/null @@ -1 +0,0 @@ -Ensure line-endings are respected when using lib2to3. diff --git a/Misc/NEWS.d/next/Library/2018-04-16-15-59-21.bpo-33266.w2PAm-.rst b/Misc/NEWS.d/next/Library/2018-04-16-15-59-21.bpo-33266.w2PAm-.rst deleted file mode 100644 index 6c93c48b8886..000000000000 --- a/Misc/NEWS.d/next/Library/2018-04-16-15-59-21.bpo-33266.w2PAm-.rst +++ /dev/null @@ -1 +0,0 @@ -lib2to3 now recognizes ``rf'...'`` strings. diff --git a/Misc/NEWS.d/next/Library/2018-04-18-19-12-25.bpo-33308.fW75xi.rst b/Misc/NEWS.d/next/Library/2018-04-18-19-12-25.bpo-33308.fW75xi.rst deleted file mode 100644 index 586004a3c6c9..000000000000 --- a/Misc/NEWS.d/next/Library/2018-04-18-19-12-25.bpo-33308.fW75xi.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed a crash in the :mod:`parser` module when converting an ST object to a -tree of tuples or lists with ``line_info=False`` and ``col_info=True``. diff --git a/Misc/NEWS.d/next/Library/2018-04-20-10-43-17.bpo-33131.L2E977.rst b/Misc/NEWS.d/next/Library/2018-04-20-10-43-17.bpo-33131.L2E977.rst deleted file mode 100644 index 875c6ac5f742..000000000000 --- a/Misc/NEWS.d/next/Library/2018-04-20-10-43-17.bpo-33131.L2E977.rst +++ /dev/null @@ -1 +0,0 @@ -Upgrade bundled version of pip to 10.0.1. diff --git a/Misc/NEWS.d/next/Library/2018-04-21-00-24-08.bpo-991266.h93TP_.rst b/Misc/NEWS.d/next/Library/2018-04-21-00-24-08.bpo-991266.h93TP_.rst deleted file mode 100644 index 3af6c27cf21d..000000000000 --- a/Misc/NEWS.d/next/Library/2018-04-21-00-24-08.bpo-991266.h93TP_.rst +++ /dev/null @@ -1 +0,0 @@ -Fix quoting of the ``Comment`` attribute of :class:`http.cookies.SimpleCookie`. diff --git a/Misc/NEWS.d/next/Library/2018-04-23-13-21-39.bpo-33329.lQ-Eod.rst b/Misc/NEWS.d/next/Library/2018-04-23-13-21-39.bpo-33329.lQ-Eod.rst deleted file mode 100644 index d1a4e56d04b9..000000000000 --- a/Misc/NEWS.d/next/Library/2018-04-23-13-21-39.bpo-33329.lQ-Eod.rst +++ /dev/null @@ -1 +0,0 @@ -Fix multiprocessing regression on newer glibcs diff --git a/Misc/NEWS.d/next/Library/2018-04-29-11-15-38.bpo-33383.g32YWn.rst b/Misc/NEWS.d/next/Library/2018-04-29-11-15-38.bpo-33383.g32YWn.rst deleted file mode 100644 index 7b65baac97bf..000000000000 --- a/Misc/NEWS.d/next/Library/2018-04-29-11-15-38.bpo-33383.g32YWn.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed crash in the get() method of the :mod:`dbm.ndbm` database object when -it is called with a single argument. diff --git a/Misc/NEWS.d/next/Library/2018-05-01-22-35-50.bpo-33281.d4jOt4.rst b/Misc/NEWS.d/next/Library/2018-05-01-22-35-50.bpo-33281.d4jOt4.rst deleted file mode 100644 index ad08caa70b63..000000000000 --- a/Misc/NEWS.d/next/Library/2018-05-01-22-35-50.bpo-33281.d4jOt4.rst +++ /dev/null @@ -1 +0,0 @@ -Fix ctypes.util.find_library regression on macOS. diff --git a/Misc/NEWS.d/next/Tests/2018-04-27-11-46-35.bpo-33358._OcR59.rst b/Misc/NEWS.d/next/Tests/2018-04-27-11-46-35.bpo-33358._OcR59.rst deleted file mode 100644 index 89406e994a91..000000000000 --- a/Misc/NEWS.d/next/Tests/2018-04-27-11-46-35.bpo-33358._OcR59.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix ``test_embed.test_pre_initialization_sys_options()`` when the interpreter -is built with ``--enable-shared``. diff --git a/Misc/NEWS.d/next/Tools-Demos/2017-09-26-10-11-21.bpo-31583.TM90_H.rst b/Misc/NEWS.d/next/Tools-Demos/2017-09-26-10-11-21.bpo-31583.TM90_H.rst deleted file mode 100644 index 472f61c5129e..000000000000 --- a/Misc/NEWS.d/next/Tools-Demos/2017-09-26-10-11-21.bpo-31583.TM90_H.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix 2to3 for using with --add-suffix option but without --output-dir -option for relative path to files in current directory. diff --git a/Misc/NEWS.d/next/Tools-Demos/2018-03-16-17-25-05.bpo-29673.m8QtaW.rst b/Misc/NEWS.d/next/Tools-Demos/2018-03-16-17-25-05.bpo-29673.m8QtaW.rst deleted file mode 100644 index 3d515b3ee4db..000000000000 --- a/Misc/NEWS.d/next/Tools-Demos/2018-03-16-17-25-05.bpo-29673.m8QtaW.rst +++ /dev/null @@ -1 +0,0 @@ -Fix pystackv and pystack gdbinit macros. diff --git a/Misc/NEWS.d/next/Tools-Demos/2018-03-26-18-54-24.bpo-31920.u_WKsT.rst b/Misc/NEWS.d/next/Tools-Demos/2018-03-26-18-54-24.bpo-31920.u_WKsT.rst deleted file mode 100644 index 39c694b0728d..000000000000 --- a/Misc/NEWS.d/next/Tools-Demos/2018-03-26-18-54-24.bpo-31920.u_WKsT.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed handling directories as arguments in the ``pygettext`` script. Based -on patch by Oleg Krasnikov. diff --git a/Misc/NEWS.d/next/Tools-Demos/2018-04-03-18-10-00.bpo-33189.QrXR00.rst b/Misc/NEWS.d/next/Tools-Demos/2018-04-03-18-10-00.bpo-33189.QrXR00.rst deleted file mode 100644 index 4d4137240e61..000000000000 --- a/Misc/NEWS.d/next/Tools-Demos/2018-04-03-18-10-00.bpo-33189.QrXR00.rst +++ /dev/null @@ -1,2 +0,0 @@ -:program:`pygettext.py` now recognizes only literal strings as docstrings -and translatable strings, and rejects bytes literals and f-string expressions. diff --git a/Misc/NEWS.d/next/Windows/2018-04-13-11-28-55.bpo-33184.7YhqQE.rst b/Misc/NEWS.d/next/Windows/2018-04-13-11-28-55.bpo-33184.7YhqQE.rst deleted file mode 100644 index ca47a9811088..000000000000 --- a/Misc/NEWS.d/next/Windows/2018-04-13-11-28-55.bpo-33184.7YhqQE.rst +++ /dev/null @@ -1 +0,0 @@ -Update Windows installer to use OpenSSL 1.1.0h. diff --git a/Misc/NEWS.d/next/macOS/2018-04-07-00-51-34.bpo-33184.3j208P.rst b/Misc/NEWS.d/next/macOS/2018-04-07-00-51-34.bpo-33184.3j208P.rst deleted file mode 100644 index 03308ed6a72b..000000000000 --- a/Misc/NEWS.d/next/macOS/2018-04-07-00-51-34.bpo-33184.3j208P.rst +++ /dev/null @@ -1 +0,0 @@ -Update macOS installer build to use OpenSSL 1.1.0h. diff --git a/README.rst b/README.rst index fcd23442d766..68bc5712d4c3 100644 --- a/README.rst +++ b/README.rst @@ -1,5 +1,5 @@ -This is Python version 3.7.0 beta 3+ -==================================== +This is Python version 3.7.0 beta 4 +=================================== .. image:: https://travis-ci.org/python/cpython.svg?branch=master :alt: CPython build status on Travis CI diff --git a/configure b/configure index 2ab9bc8eff2a..f1f01df4a80e 100755 --- a/configure +++ b/configure @@ -781,7 +781,6 @@ infodir docdir oldincludedir includedir -runstatedir localstatedir sharedstatedir sysconfdir @@ -894,7 +893,6 @@ datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' -runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' @@ -1147,15 +1145,6 @@ do | -silent | --silent | --silen | --sile | --sil) silent=yes ;; - -runstatedir | --runstatedir | --runstatedi | --runstated \ - | --runstate | --runstat | --runsta | --runst | --runs \ - | --run | --ru | --r) - ac_prev=runstatedir ;; - -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ - | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ - | --run=* | --ru=* | --r=*) - runstatedir=$ac_optarg ;; - -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ @@ -1293,7 +1282,7 @@ fi for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir runstatedir + libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. @@ -1446,7 +1435,6 @@ Fine tuning of the installation directories: --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] - --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] From webhook-mailer at python.org Wed May 2 05:01:57 2018 From: webhook-mailer at python.org (Ned Deily) Date: Wed, 02 May 2018 09:01:57 -0000 Subject: [Python-checkins] bump to 3.7.0b4+ Message-ID: https://github.com/python/cpython/commit/01e19f8fedb1e02476c4e42d387829135c9e76a1 commit: 01e19f8fedb1e02476c4e42d387829135c9e76a1 branch: 3.7 author: Ned Deily committer: Ned Deily date: 2018-05-02T05:01:31-04:00 summary: bump to 3.7.0b4+ files: M Include/patchlevel.h M README.rst diff --git a/Include/patchlevel.h b/Include/patchlevel.h index c01b8f98fe51..d7bd1d394454 100644 --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -23,7 +23,7 @@ #define PY_RELEASE_SERIAL 4 /* Version as a string */ -#define PY_VERSION "3.7.0b4" +#define PY_VERSION "3.7.0b4+" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/README.rst b/README.rst index 68bc5712d4c3..ffa9631b0287 100644 --- a/README.rst +++ b/README.rst @@ -1,5 +1,5 @@ -This is Python version 3.7.0 beta 4 -=================================== +This is Python version 3.7.0 beta 4+ +==================================== .. image:: https://travis-ci.org/python/cpython.svg?branch=master :alt: CPython build status on Travis CI From solipsis at pitrou.net Wed May 2 05:18:16 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 02 May 2018 09:18:16 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=2 Message-ID: <20180502091816.1.B3151F097246F63D@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_collections leaked [0, -7, 8] memory blocks, sum=1 test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_fork leaked [0, 0, -2] memory blocks, sum=-2 test_multiprocessing_forkserver leaked [1, 0, -2] memory blocks, sum=-1 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogY5Ysth', '--timeout', '7200'] From webhook-mailer at python.org Wed May 2 05:29:20 2018 From: webhook-mailer at python.org (INADA Naoki) Date: Wed, 02 May 2018 09:29:20 -0000 Subject: [Python-checkins] bpo-33391: Fix refleak in set_symmetric_difference (GH-6670) Message-ID: https://github.com/python/cpython/commit/491bbedc209fea314a04cb3015da68fb0aa63238 commit: 491bbedc209fea314a04cb3015da68fb0aa63238 branch: master author: lekma committer: INADA Naoki date: 2018-05-02T18:29:10+09:00 summary: bpo-33391: Fix refleak in set_symmetric_difference (GH-6670) files: A Misc/NEWS.d/next/Core and Builtins/2018-05-02-08-36-03.bpo-33391.z4a7rb.rst M Objects/setobject.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-05-02-08-36-03.bpo-33391.z4a7rb.rst b/Misc/NEWS.d/next/Core and Builtins/2018-05-02-08-36-03.bpo-33391.z4a7rb.rst new file mode 100644 index 000000000000..ab17aa408c06 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-05-02-08-36-03.bpo-33391.z4a7rb.rst @@ -0,0 +1 @@ +Fix a leak in set_symmetric_difference(). diff --git a/Objects/setobject.c b/Objects/setobject.c index 80101dda9bee..82b583820816 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -1744,8 +1744,10 @@ set_symmetric_difference(PySetObject *so, PyObject *other) if (otherset == NULL) return NULL; rv = set_symmetric_difference_update(otherset, (PyObject *)so); - if (rv == NULL) + if (rv == NULL) { + Py_DECREF(otherset); return NULL; + } Py_DECREF(rv); return (PyObject *)otherset; } From webhook-mailer at python.org Wed May 2 05:50:51 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 02 May 2018 09:50:51 -0000 Subject: [Python-checkins] bpo-33391: Fix refleak in set_symmetric_difference (GH-6670) Message-ID: https://github.com/python/cpython/commit/6a56790e0b50846f1f968e48c3a321c148b5e6cd commit: 6a56790e0b50846f1f968e48c3a321c148b5e6cd branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-05-02T02:50:48-07:00 summary: bpo-33391: Fix refleak in set_symmetric_difference (GH-6670) (cherry picked from commit 491bbedc209fea314a04cb3015da68fb0aa63238) Co-authored-by: lekma files: A Misc/NEWS.d/next/Core and Builtins/2018-05-02-08-36-03.bpo-33391.z4a7rb.rst M Objects/setobject.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-05-02-08-36-03.bpo-33391.z4a7rb.rst b/Misc/NEWS.d/next/Core and Builtins/2018-05-02-08-36-03.bpo-33391.z4a7rb.rst new file mode 100644 index 000000000000..ab17aa408c06 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-05-02-08-36-03.bpo-33391.z4a7rb.rst @@ -0,0 +1 @@ +Fix a leak in set_symmetric_difference(). diff --git a/Objects/setobject.c b/Objects/setobject.c index 47db6b245ca6..ce35aa2a0cdb 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -1744,8 +1744,10 @@ set_symmetric_difference(PySetObject *so, PyObject *other) if (otherset == NULL) return NULL; rv = set_symmetric_difference_update(otherset, (PyObject *)so); - if (rv == NULL) + if (rv == NULL) { + Py_DECREF(otherset); return NULL; + } Py_DECREF(rv); return (PyObject *)otherset; } From webhook-mailer at python.org Wed May 2 06:12:23 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 02 May 2018 10:12:23 -0000 Subject: [Python-checkins] bpo-33391: Fix refleak in set_symmetric_difference (GH-6670) Message-ID: https://github.com/python/cpython/commit/d5546991a2123b6ec84f7c4ecf37b62bedd78ea4 commit: d5546991a2123b6ec84f7c4ecf37b62bedd78ea4 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-05-02T03:12:18-07:00 summary: bpo-33391: Fix refleak in set_symmetric_difference (GH-6670) (cherry picked from commit 491bbedc209fea314a04cb3015da68fb0aa63238) Co-authored-by: lekma files: A Misc/NEWS.d/next/Core and Builtins/2018-05-02-08-36-03.bpo-33391.z4a7rb.rst M Objects/setobject.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-05-02-08-36-03.bpo-33391.z4a7rb.rst b/Misc/NEWS.d/next/Core and Builtins/2018-05-02-08-36-03.bpo-33391.z4a7rb.rst new file mode 100644 index 000000000000..ab17aa408c06 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-05-02-08-36-03.bpo-33391.z4a7rb.rst @@ -0,0 +1 @@ +Fix a leak in set_symmetric_difference(). diff --git a/Objects/setobject.c b/Objects/setobject.c index c742041b16de..96485f83ecb6 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -1740,8 +1740,10 @@ set_symmetric_difference(PySetObject *so, PyObject *other) if (otherset == NULL) return NULL; rv = set_symmetric_difference_update(otherset, (PyObject *)so); - if (rv == NULL) + if (rv == NULL) { + Py_DECREF(otherset); return NULL; + } Py_DECREF(rv); return (PyObject *)otherset; } From webhook-mailer at python.org Wed May 2 06:23:44 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 02 May 2018 10:23:44 -0000 Subject: [Python-checkins] bpo-33391: Fix refleak in set_symmetric_difference (GH-6670) Message-ID: https://github.com/python/cpython/commit/6d3d02c69a65abcd64eb6d83baac5675f9208318 commit: 6d3d02c69a65abcd64eb6d83baac5675f9208318 branch: 2.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-05-02T03:23:41-07:00 summary: bpo-33391: Fix refleak in set_symmetric_difference (GH-6670) (cherry picked from commit 491bbedc209fea314a04cb3015da68fb0aa63238) Co-authored-by: lekma files: A Misc/NEWS.d/next/Core and Builtins/2018-05-02-08-36-03.bpo-33391.z4a7rb.rst M Objects/setobject.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-05-02-08-36-03.bpo-33391.z4a7rb.rst b/Misc/NEWS.d/next/Core and Builtins/2018-05-02-08-36-03.bpo-33391.z4a7rb.rst new file mode 100644 index 000000000000..ab17aa408c06 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-05-02-08-36-03.bpo-33391.z4a7rb.rst @@ -0,0 +1 @@ +Fix a leak in set_symmetric_difference(). diff --git a/Objects/setobject.c b/Objects/setobject.c index 154be43564dd..31da3dbfecb1 100644 --- a/Objects/setobject.c +++ b/Objects/setobject.c @@ -1710,8 +1710,10 @@ set_symmetric_difference(PySetObject *so, PyObject *other) if (otherset == NULL) return NULL; rv = set_symmetric_difference_update(otherset, (PyObject *)so); - if (rv == NULL) + if (rv == NULL) { + Py_DECREF(otherset); return NULL; + } Py_DECREF(rv); return (PyObject *)otherset; } From solipsis at pitrou.net Thu May 3 05:14:13 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 03 May 2018 09:14:13 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=3 Message-ID: <20180503091413.1.1CA64F40A943263E@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_collections leaked [0, 7, -7] memory blocks, sum=0 test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_fork leaked [1, 0, -2] memory blocks, sum=-1 test_multiprocessing_forkserver leaked [-2, 2, 0] memory blocks, sum=0 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogIS9exp', '--timeout', '7200'] From lp_benchmark_robot at intel.com Thu May 3 22:03:47 2018 From: lp_benchmark_robot at intel.com (lp_benchmark_robot at intel.com) Date: Thu, 3 May 2018 19:03:47 -0700 Subject: [Python-checkins] [4 down, 2 up, 59 flat] Results for Python (master branch) 2018-05-03 Message-ID: <919d6a19-1b58-4168-91cf-f496304e4ef3@orsmsx110.amr.corp.intel.com> Results for project python/master, build date: 2018-05-03 09:54:21-07:00. - commit: 491bbed - previous commit: ffa2c3e - revision date: 2018-05-02 18:29:10+09:00 - environment: Broadwell-EP - cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores, stepping 1, LLC 55 MB - mem: 128 GB - os: Ubuntu 16.04.2 LTS - kernel: 4.4.0-62-generic x86_64 GNU/Linux Baseline results were generated using release v3.6.0, with hash 5c4568a from 2016-12-22 23:38:47+00:00. +-----+------------------------+--------+------------+------------+------------+ | | |relative|change since|change since|current rev | | | benchmark|std_dev*| last run | baseline |run with PGO| +-----+------------------------+--------+------------+------------+------------+ | :-| | 2to3| 0.604% | +0.323% | +8.224% | +7.450% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method| 1.990% | -0.957% | +23.763% | +11.188% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_slots| 0.784% | -0.574% | +25.540% | +10.648% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_unknown| 0.931% | +0.317% | +23.691% | +9.424% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_simple| 3.217% | +0.093% | +9.806% | +13.235% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chameleon| 1.792% | -0.744% | +11.770% | +10.896% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chaos| 0.658% | +1.501% | +8.875% | +10.071% | +-----+------------------------+--------+------------+------------+------------+ | :-| | crypto_pyaes| 0.540% | -0.289% | -1.804% | +8.906% | +-----+------------------------+--------+------------+------------+------------+ | :-| | deltablue| 1.963% | +1.328% | +12.382% | +16.495% | +-----+------------------------+--------+------------+------------+------------+ | :-| | django_template| 2.860% | -1.348% | +20.707% | +14.374% | +-----+------------------------+--------+------------+------------+------------+ | :-| | dulwich_log| 1.267% | -0.245% | +5.167% | +7.040% | +-----+------------------------+--------+------------+------------+------------+ | :-| | fannkuch| 1.889% | +0.219% | +6.296% | +6.243% | +-----+------------------------+--------+------------+------------+------------+ | :-| | float| 1.116% | +0.362% | +2.862% | +7.049% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_text| 1.353% | -1.002% | +13.589% | +10.084% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_xml| 1.634% | +0.305% | +10.918% | +9.895% | +-----+------------------------+--------+------------+------------+------------+ | :-| | go| 6.492% | -1.296% | +3.931% | +12.477% | +-----+------------------------+--------+------------+------------+------------+ | :-| | hexiom| 1.047% | -0.189% | +11.161% | +11.903% | +-----+------------------------+--------+------------+------------+------------+ | :-| | html5lib| 2.981% | -2.272% | +10.624% | +10.552% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_dumps| 1.987% | +1.024% | +2.411% | +10.113% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_loads| 3.707% | -2.412% | -5.860% | +17.526% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_format| 1.455% | -2.209% | +17.476% | +12.552% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_silent| 2.245% | +0.662% | +48.179% | +11.925% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_simple| 1.882% | -2.724% | +11.692% | +13.947% | +-----+------------------------+--------+------------+------------+------------+ | :-( | mako| 0.497% | -2.383% | +15.412% | +16.005% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mdp| 7.469% | -5.390% | +4.360% | +14.952% | +-----+------------------------+--------+------------+------------+------------+ | :-| | meteor_contest| 1.821% | -0.966% | +4.551% | +5.788% | +-----+------------------------+--------+------------+------------+------------+ | :-( | nbody| 0.630% | -2.392% | -2.148% | +3.096% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nqueens| 1.181% | -1.248% | +4.652% | +7.971% | +-----+------------------------+--------+------------+------------+------------+ | :-( | pathlib| 1.344% | -4.060% | -1.311% | +12.306% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle| 1.273% | -1.459% | +0.289% | +23.186% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_dict| 0.265% | +1.442% | +4.349% | +22.412% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_list| 0.738% | +2.135% | +5.651% | +19.920% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_pure_python| 8.390% | -4.324% | +8.311% | +14.957% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pidigits| 0.119% | +0.032% | +0.209% | +10.132% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup| 0.114% | +0.324% | +18.340% | +5.728% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup_no_site| 0.081% | +0.326% | +5.343% | +5.687% | +-----+------------------------+--------+------------+------------+------------+ | :-| | raytrace| 0.900% | -0.313% | +10.484% | +13.883% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_compile| 5.336% | -4.503% | +1.318% | +13.095% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_dna| 0.207% | +0.236% | -2.013% | +13.177% | +-----+------------------------+--------+------------+------------+------------+ | :-) | regex_effbot| 2.351% | +6.075% | -2.699% | +4.460% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_v8| 1.068% | -0.498% | +3.409% | +6.371% | +-----+------------------------+--------+------------+------------+------------+ | :-| | richards| 0.926% | -0.703% | +9.817% | +15.323% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_fft| 2.089% | -0.409% | -3.160% | +5.168% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_lu| 3.020% | -0.825% | +22.611% | +11.885% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_monte_carlo| 2.239% | -0.393% | +4.395% | +4.353% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sor| 2.219% | -1.129% | +13.447% | +11.238% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sparse_mat_mult| 0.671% | +1.221% | -5.803% | -0.931% | +-----+------------------------+--------+------------+------------+------------+ | :-| | spectral_norm| 0.835% | +0.663% | +3.568% | +6.081% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_declarative| 1.340% | -0.236% | +6.721% | +6.072% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_imperative| 3.812% | -0.690% | +7.800% | +5.342% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlite_synth| 3.436% | -0.258% | +0.797% | +9.067% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_expand| 3.573% | -0.775% | +16.839% | +7.393% | +-----+------------------------+--------+------------+------------+------------+ | :-) | sympy_integrate| 1.439% | +5.631% | +17.668% | +6.658% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_str| 4.970% | -0.299% | +17.931% | +7.933% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_sum| 6.487% | -1.295% | +15.089% | +10.686% | +-----+------------------------+--------+------------+------------+------------+ | :-| | telco| 5.019% | -3.672% | +18.772% | +9.009% | +-----+------------------------+--------+------------+------------+------------+ | :-| | tornado_http| 1.395% | -0.813% | +7.006% | +6.692% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpack_sequence| 1.875% | +0.143% | +2.206% | -0.451% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle| 4.430% | -0.522% | +8.467% | +22.050% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_list| 2.107% | -2.513% | -3.916% | +15.242% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_pure_python| 2.266% | -3.098% | +5.647% | +9.247% | +-----+------------------------+--------+------------+------------+------------+ | :-( | xml_etree_generate| 0.969% | -3.292% | +2.015% | +12.701% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_iterparse| 2.438% | -0.385% | +2.578% | +8.268% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_parse| 3.199% | -2.171% | -9.094% | +10.813% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_process| 1.170% | -2.347% | +3.953% | +11.540% | +-----+------------------------+--------+------------+------------+------------+ * Relative Standard Deviation (Standard Deviation/Average) If this is not displayed properly please visit our results page here: http://languagesperformance.intel.com/4-down-2-up-59-flat-results-for-python-master-branch-2018-05-03 Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. From solipsis at pitrou.net Fri May 4 05:08:58 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 04 May 2018 09:08:58 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=3 Message-ID: <20180504090858.1.3A40D3CEBAEBD918@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_forkserver leaked [-2, 2, -1] memory blocks, sum=-1 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogqyCwLI', '--timeout', '7200'] From webhook-mailer at python.org Fri May 4 07:01:03 2018 From: webhook-mailer at python.org (Antoine Pitrou) Date: Fri, 04 May 2018 11:01:03 -0000 Subject: [Python-checkins] bpo-33332: Add signal.valid_signals() (GH-6581) Message-ID: https://github.com/python/cpython/commit/9d3627e311211a1b4abcda29c36fe4afe2c46532 commit: 9d3627e311211a1b4abcda29c36fe4afe2c46532 branch: master author: Antoine Pitrou committer: GitHub date: 2018-05-04T13:00:50+02:00 summary: bpo-33332: Add signal.valid_signals() (GH-6581) files: A Misc/NEWS.d/next/Library/2018-04-23-21-41-30.bpo-33332.Y6OZ8Z.rst M Doc/library/signal.rst M Lib/asyncio/unix_events.py M Lib/multiprocessing/resource_sharer.py M Lib/signal.py M Lib/test/support/__init__.py M Lib/test/test_asyncio/test_unix_events.py M Lib/test/test_signal.py M Modules/clinic/signalmodule.c.h M Modules/signalmodule.c M aclocal.m4 M configure M configure.ac M pyconfig.h.in diff --git a/Doc/library/signal.rst b/Doc/library/signal.rst index 3f17e08f0f95..67ee979dc0e0 100644 --- a/Doc/library/signal.rst +++ b/Doc/library/signal.rst @@ -216,6 +216,15 @@ The :mod:`signal` module defines the following functions: .. versionadded:: 3.8 +.. function:: valid_signals() + + Return the set of valid signal numbers on this platform. This can be + less than ``range(1, NSIG)`` if some signals are reserved by the system + for internal use. + + .. versionadded:: 3.8 + + .. function:: pause() Cause the process to sleep until a signal is received; the appropriate handler @@ -268,8 +277,8 @@ The :mod:`signal` module defines the following functions: argument. *mask* is a set of signal numbers (e.g. {:const:`signal.SIGINT`, - :const:`signal.SIGTERM`}). Use ``range(1, signal.NSIG)`` for a full mask - including all signals. + :const:`signal.SIGTERM`}). Use :func:`~signal.valid_signals` for a full + mask including all signals. For example, ``signal.pthread_sigmask(signal.SIG_BLOCK, [])`` reads the signal mask of the calling thread. diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py index 6cac137cacb3..f64037a25c67 100644 --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -167,8 +167,8 @@ def _check_signal(self, sig): if not isinstance(sig, int): raise TypeError(f'sig must be an int, not {sig!r}') - if not (1 <= sig < signal.NSIG): - raise ValueError(f'sig {sig} out of range(1, {signal.NSIG})') + if sig not in signal.valid_signals(): + raise ValueError(f'invalid signal number {sig}') def _make_read_pipe_transport(self, pipe, protocol, waiter=None, extra=None): diff --git a/Lib/multiprocessing/resource_sharer.py b/Lib/multiprocessing/resource_sharer.py index 6d99da102ffc..730b2aa17bdf 100644 --- a/Lib/multiprocessing/resource_sharer.py +++ b/Lib/multiprocessing/resource_sharer.py @@ -136,7 +136,7 @@ def _start(self): def _serve(self): if hasattr(signal, 'pthread_sigmask'): - signal.pthread_sigmask(signal.SIG_BLOCK, range(1, signal.NSIG)) + signal.pthread_sigmask(signal.SIG_BLOCK, signal.valid_signals()) while 1: try: with self._listener.accept() as conn: diff --git a/Lib/signal.py b/Lib/signal.py index 9f05c9198df7..826b62cf596c 100644 --- a/Lib/signal.py +++ b/Lib/signal.py @@ -65,8 +65,7 @@ def pthread_sigmask(how, mask): if 'sigpending' in _globals: @_wraps(_signal.sigpending) def sigpending(): - sigs = _signal.sigpending() - return set(_int_to_enum(x, Signals) for x in sigs) + return {_int_to_enum(x, Signals) for x in _signal.sigpending()} if 'sigwait' in _globals: @@ -76,4 +75,11 @@ def sigwait(sigset): return _int_to_enum(retsig, Signals) sigwait.__doc__ = _signal.sigwait + +if 'valid_signals' in _globals: + @_wraps(_signal.valid_signals) + def valid_signals(): + return {_int_to_enum(x, Signals) for x in _signal.valid_signals()} + + del _globals, _wraps diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index a5f86d4c4176..f1c4c952eff3 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -2810,7 +2810,7 @@ class SaveSignals: def __init__(self): import signal self.signal = signal - self.signals = list(range(1, signal.NSIG)) + self.signals = signal.valid_signals() # SIGKILL and SIGSTOP signals cannot be ignored nor caught for signame in ('SIGKILL', 'SIGSTOP'): try: diff --git a/Lib/test/test_asyncio/test_unix_events.py b/Lib/test/test_asyncio/test_unix_events.py index 104f99593797..a01efedf66d9 100644 --- a/Lib/test/test_asyncio/test_unix_events.py +++ b/Lib/test/test_asyncio/test_unix_events.py @@ -69,6 +69,7 @@ def test_handle_signal_cancelled_handler(self): @mock.patch('asyncio.unix_events.signal') def test_add_signal_handler_setup_error(self, m_signal): m_signal.NSIG = signal.NSIG + m_signal.valid_signals = signal.valid_signals m_signal.set_wakeup_fd.side_effect = ValueError self.assertRaises( @@ -96,6 +97,7 @@ def test_add_signal_handler_coroutine_error(self, m_signal): @mock.patch('asyncio.unix_events.signal') def test_add_signal_handler(self, m_signal): m_signal.NSIG = signal.NSIG + m_signal.valid_signals = signal.valid_signals cb = lambda: True self.loop.add_signal_handler(signal.SIGHUP, cb) @@ -106,6 +108,7 @@ def test_add_signal_handler(self, m_signal): @mock.patch('asyncio.unix_events.signal') def test_add_signal_handler_install_error(self, m_signal): m_signal.NSIG = signal.NSIG + m_signal.valid_signals = signal.valid_signals def set_wakeup_fd(fd): if fd == -1: @@ -125,6 +128,7 @@ class Err(OSError): @mock.patch('asyncio.base_events.logger') def test_add_signal_handler_install_error2(self, m_logging, m_signal): m_signal.NSIG = signal.NSIG + m_signal.valid_signals = signal.valid_signals class Err(OSError): errno = errno.EINVAL @@ -145,6 +149,7 @@ class Err(OSError): errno = errno.EINVAL m_signal.signal.side_effect = Err m_signal.NSIG = signal.NSIG + m_signal.valid_signals = signal.valid_signals self.assertRaises( RuntimeError, @@ -156,6 +161,7 @@ class Err(OSError): @mock.patch('asyncio.unix_events.signal') def test_remove_signal_handler(self, m_signal): m_signal.NSIG = signal.NSIG + m_signal.valid_signals = signal.valid_signals self.loop.add_signal_handler(signal.SIGHUP, lambda: True) @@ -170,6 +176,7 @@ def test_remove_signal_handler(self, m_signal): def test_remove_signal_handler_2(self, m_signal): m_signal.NSIG = signal.NSIG m_signal.SIGINT = signal.SIGINT + m_signal.valid_signals = signal.valid_signals self.loop.add_signal_handler(signal.SIGINT, lambda: True) self.loop._signal_handlers[signal.SIGHUP] = object() @@ -187,6 +194,7 @@ def test_remove_signal_handler_2(self, m_signal): @mock.patch('asyncio.base_events.logger') def test_remove_signal_handler_cleanup_error(self, m_logging, m_signal): m_signal.NSIG = signal.NSIG + m_signal.valid_signals = signal.valid_signals self.loop.add_signal_handler(signal.SIGHUP, lambda: True) m_signal.set_wakeup_fd.side_effect = ValueError @@ -197,6 +205,7 @@ def test_remove_signal_handler_cleanup_error(self, m_logging, m_signal): @mock.patch('asyncio.unix_events.signal') def test_remove_signal_handler_error(self, m_signal): m_signal.NSIG = signal.NSIG + m_signal.valid_signals = signal.valid_signals self.loop.add_signal_handler(signal.SIGHUP, lambda: True) m_signal.signal.side_effect = OSError @@ -207,6 +216,7 @@ def test_remove_signal_handler_error(self, m_signal): @mock.patch('asyncio.unix_events.signal') def test_remove_signal_handler_error2(self, m_signal): m_signal.NSIG = signal.NSIG + m_signal.valid_signals = signal.valid_signals self.loop.add_signal_handler(signal.SIGHUP, lambda: True) class Err(OSError): @@ -219,6 +229,7 @@ class Err(OSError): @mock.patch('asyncio.unix_events.signal') def test_close(self, m_signal): m_signal.NSIG = signal.NSIG + m_signal.valid_signals = signal.valid_signals self.loop.add_signal_handler(signal.SIGHUP, lambda: True) self.loop.add_signal_handler(signal.SIGCHLD, lambda: True) @@ -236,6 +247,7 @@ def test_close(self, m_signal): @mock.patch('asyncio.unix_events.signal') def test_close_on_finalizing(self, m_signal, m_sys): m_signal.NSIG = signal.NSIG + m_signal.valid_signals = signal.valid_signals self.loop.add_signal_handler(signal.SIGHUP, lambda: True) self.assertEqual(len(self.loop._signal_handlers), 1) diff --git a/Lib/test/test_signal.py b/Lib/test/test_signal.py index 7635eec148d8..7ce89f61ab3e 100644 --- a/Lib/test/test_signal.py +++ b/Lib/test/test_signal.py @@ -67,9 +67,28 @@ def test_interprocess_signal(self): script = os.path.join(dirname, 'signalinterproctester.py') assert_python_ok(script) + def test_valid_signals(self): + s = signal.valid_signals() + self.assertIsInstance(s, set) + self.assertIn(signal.Signals.SIGINT, s) + self.assertIn(signal.Signals.SIGALRM, s) + self.assertNotIn(0, s) + self.assertNotIn(signal.NSIG, s) + self.assertLess(len(s), signal.NSIG) + @unittest.skipUnless(sys.platform == "win32", "Windows specific") class WindowsSignalTests(unittest.TestCase): + + def test_valid_signals(self): + s = signal.valid_signals() + self.assertIsInstance(s, set) + self.assertGreaterEqual(len(s), 6) + self.assertIn(signal.Signals.SIGINT, s) + self.assertNotIn(0, s) + self.assertNotIn(signal.NSIG, s) + self.assertLess(len(s), signal.NSIG) + def test_issue9324(self): # Updated for issue #10003, adding SIGBREAK handler = lambda x, y: None @@ -922,6 +941,17 @@ def test_pthread_sigmask_arguments(self): self.assertRaises(TypeError, signal.pthread_sigmask, 1) self.assertRaises(TypeError, signal.pthread_sigmask, 1, 2, 3) self.assertRaises(OSError, signal.pthread_sigmask, 1700, []) + with self.assertRaises(ValueError): + signal.pthread_sigmask(signal.SIG_BLOCK, [signal.NSIG]) + + @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'), + 'need signal.pthread_sigmask()') + def test_pthread_sigmask_valid_signals(self): + s = signal.pthread_sigmask(signal.SIG_BLOCK, signal.valid_signals()) + self.addCleanup(signal.pthread_sigmask, signal.SIG_SETMASK, s) + # Get current blocked set + s = signal.pthread_sigmask(signal.SIG_UNBLOCK, signal.valid_signals()) + self.assertLessEqual(s, signal.valid_signals()) @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'), 'need signal.pthread_sigmask()') diff --git a/Misc/NEWS.d/next/Library/2018-04-23-21-41-30.bpo-33332.Y6OZ8Z.rst b/Misc/NEWS.d/next/Library/2018-04-23-21-41-30.bpo-33332.Y6OZ8Z.rst new file mode 100644 index 000000000000..05dca54d5776 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-04-23-21-41-30.bpo-33332.Y6OZ8Z.rst @@ -0,0 +1,2 @@ +Add ``signal.valid_signals()`` to expose the POSIX sigfillset() +functionality. diff --git a/Modules/clinic/signalmodule.c.h b/Modules/clinic/signalmodule.c.h index 1c439716c498..eca2da10ad33 100644 --- a/Modules/clinic/signalmodule.c.h +++ b/Modules/clinic/signalmodule.c.h @@ -341,6 +341,31 @@ PyDoc_STRVAR(signal_sigwait__doc__, #endif /* defined(HAVE_SIGWAIT) */ +#if (defined(HAVE_SIGFILLSET) || defined(MS_WINDOWS)) + +PyDoc_STRVAR(signal_valid_signals__doc__, +"valid_signals($module, /)\n" +"--\n" +"\n" +"Return a set of valid signal numbers on this platform.\n" +"\n" +"The signal numbers returned by this function can be safely passed to\n" +"functions like `pthread_sigmask`."); + +#define SIGNAL_VALID_SIGNALS_METHODDEF \ + {"valid_signals", (PyCFunction)signal_valid_signals, METH_NOARGS, signal_valid_signals__doc__}, + +static PyObject * +signal_valid_signals_impl(PyObject *module); + +static PyObject * +signal_valid_signals(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return signal_valid_signals_impl(module); +} + +#endif /* (defined(HAVE_SIGFILLSET) || defined(MS_WINDOWS)) */ + #if defined(HAVE_SIGWAITINFO) PyDoc_STRVAR(signal_sigwaitinfo__doc__, @@ -459,6 +484,10 @@ signal_pthread_kill(PyObject *module, PyObject *const *args, Py_ssize_t nargs) #define SIGNAL_SIGWAIT_METHODDEF #endif /* !defined(SIGNAL_SIGWAIT_METHODDEF) */ +#ifndef SIGNAL_VALID_SIGNALS_METHODDEF + #define SIGNAL_VALID_SIGNALS_METHODDEF +#endif /* !defined(SIGNAL_VALID_SIGNALS_METHODDEF) */ + #ifndef SIGNAL_SIGWAITINFO_METHODDEF #define SIGNAL_SIGWAITINFO_METHODDEF #endif /* !defined(SIGNAL_SIGWAITINFO_METHODDEF) */ @@ -470,4 +499,4 @@ signal_pthread_kill(PyObject *module, PyObject *const *args, Py_ssize_t nargs) #ifndef SIGNAL_PTHREAD_KILL_METHODDEF #define SIGNAL_PTHREAD_KILL_METHODDEF #endif /* !defined(SIGNAL_PTHREAD_KILL_METHODDEF) */ -/*[clinic end generated code: output=7b41486acf93aa8e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=f35d79e0cfee3f1b input=a9049054013a1b77]*/ diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c index 35fd87e2d1e7..003bbb60e387 100644 --- a/Modules/signalmodule.c +++ b/Modules/signalmodule.c @@ -841,11 +841,21 @@ iterable_to_sigset(PyObject *iterable, sigset_t *mask) if (signum == -1 && PyErr_Occurred()) goto error; if (0 < signum && signum < NSIG) { - /* bpo-33329: ignore sigaddset() return value as it can fail - * for some reserved signals, but we want the `range(1, NSIG)` - * idiom to allow selecting all valid signals. - */ - (void) sigaddset(mask, (int)signum); + if (sigaddset(mask, (int)signum)) { + if (errno != EINVAL) { + /* Probably impossible */ + PyErr_SetFromErrno(PyExc_OSError); + goto error; + } + /* For backwards compatibility, allow idioms such as + * `range(1, NSIG)` but warn about invalid signal numbers + */ + const char *msg = + "invalid signal number %ld, please use valid_signals()"; + if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1, msg, signum)) { + goto error; + } + } } else { PyErr_Format(PyExc_ValueError, @@ -1001,6 +1011,47 @@ signal_sigwait(PyObject *module, PyObject *sigset) #endif /* #ifdef HAVE_SIGWAIT */ +#if defined(HAVE_SIGFILLSET) || defined(MS_WINDOWS) + +/*[clinic input] +signal.valid_signals + +Return a set of valid signal numbers on this platform. + +The signal numbers returned by this function can be safely passed to +functions like `pthread_sigmask`. +[clinic start generated code]*/ + +static PyObject * +signal_valid_signals_impl(PyObject *module) +/*[clinic end generated code: output=1609cffbcfcf1314 input=86a3717ff25288f2]*/ +{ +#ifdef MS_WINDOWS +#ifdef SIGBREAK + PyObject *tup = Py_BuildValue("(iiiiiii)", SIGABRT, SIGBREAK, SIGFPE, + SIGILL, SIGINT, SIGSEGV, SIGTERM); +#else + PyObject *tup = Py_BuildValue("(iiiiii)", SIGABRT, SIGFPE, SIGILL, + SIGINT, SIGSEGV, SIGTERM); +#endif + if (tup == NULL) { + return NULL; + } + PyObject *set = PySet_New(tup); + Py_DECREF(tup); + return set; +#else + sigset_t mask; + if (sigemptyset(&mask) || sigfillset(&mask)) { + return PyErr_SetFromErrno(PyExc_OSError); + } + return sigset_to_set(mask); +#endif +} + +#endif /* #if defined(HAVE_SIGFILLSET) || defined(MS_WINDOWS) */ + + #if defined(HAVE_SIGWAITINFO) || defined(HAVE_SIGTIMEDWAIT) static int initialized; static PyStructSequence_Field struct_siginfo_fields[] = { @@ -1225,6 +1276,9 @@ static PyMethodDef signal_methods[] = { SIGNAL_SIGWAIT_METHODDEF SIGNAL_SIGWAITINFO_METHODDEF SIGNAL_SIGTIMEDWAIT_METHODDEF +#if defined(HAVE_SIGFILLSET) || defined(MS_WINDOWS) + SIGNAL_VALID_SIGNALS_METHODDEF +#endif {NULL, NULL} /* sentinel */ }; diff --git a/aclocal.m4 b/aclocal.m4 index 8ed232fb515f..69205776ed4c 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -1,6 +1,6 @@ -# generated automatically by aclocal 1.15.1 -*- Autoconf -*- +# generated automatically by aclocal 1.15 -*- Autoconf -*- -# Copyright (C) 1996-2017 Free Software Foundation, Inc. +# Copyright (C) 1996-2014 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -12,9 +12,9 @@ # PARTICULAR PURPOSE. m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) -# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- -# serial 12 (pkg-config-0.29.2) - +dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +dnl serial 11 (pkg-config-0.29.1) +dnl dnl Copyright ? 2004 Scott James Remnant . dnl Copyright ? 2012-2015 Dan Nicholson dnl @@ -55,7 +55,7 @@ dnl dnl See the "Since" comment for each macro you use to see what version dnl of the macros you require. m4_defun([PKG_PREREQ], -[m4_define([PKG_MACROS_VERSION], [0.29.2]) +[m4_define([PKG_MACROS_VERSION], [0.29.1]) m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) ])dnl PKG_PREREQ @@ -156,7 +156,7 @@ AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no -AC_MSG_CHECKING([for $2]) +AC_MSG_CHECKING([for $1]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) @@ -166,11 +166,11 @@ and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then - AC_MSG_RESULT([no]) + AC_MSG_RESULT([no]) _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` - else + else $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` fi # Put the nasty error message in config.log where it belongs @@ -187,7 +187,7 @@ installed software in a non-standard prefix. _PKG_TEXT])[]dnl ]) elif test $pkg_failed = untried; then - AC_MSG_RESULT([no]) + AC_MSG_RESULT([no]) m4_default([$4], [AC_MSG_FAILURE( [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full diff --git a/configure b/configure index 673cfbd3cf62..adf8cf3ab9c1 100755 --- a/configure +++ b/configure @@ -11259,7 +11259,7 @@ for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \ setlocale setregid setreuid setresuid setresgid setsid setpgid setpgrp setpriority setuid setvbuf \ sched_get_priority_max sched_setaffinity sched_setscheduler sched_setparam \ sched_rr_get_interval \ - sigaction sigaltstack siginterrupt sigpending sigrelse \ + sigaction sigaltstack sigfillset siginterrupt sigpending sigrelse \ sigtimedwait sigwait sigwaitinfo snprintf strftime strlcpy symlinkat sync \ sysconf tcgetpgrp tcsetpgrp tempnam timegm times tmpfile tmpnam tmpnam_r \ truncate uname unlinkat unsetenv utimensat utimes waitid waitpid wait3 wait4 \ diff --git a/configure.ac b/configure.ac index 419bc34eab76..b52247356d75 100644 --- a/configure.ac +++ b/configure.ac @@ -3474,7 +3474,7 @@ AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \ setlocale setregid setreuid setresuid setresgid setsid setpgid setpgrp setpriority setuid setvbuf \ sched_get_priority_max sched_setaffinity sched_setscheduler sched_setparam \ sched_rr_get_interval \ - sigaction sigaltstack siginterrupt sigpending sigrelse \ + sigaction sigaltstack sigfillset siginterrupt sigpending sigrelse \ sigtimedwait sigwait sigwaitinfo snprintf strftime strlcpy symlinkat sync \ sysconf tcgetpgrp tcsetpgrp tempnam timegm times tmpfile tmpnam tmpnam_r \ truncate uname unlinkat unsetenv utimensat utimes waitid waitpid wait3 wait4 \ diff --git a/pyconfig.h.in b/pyconfig.h.in index a0efff9777d2..848872a7dca3 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -896,6 +896,9 @@ /* Define to 1 if you have the `sigaltstack' function. */ #undef HAVE_SIGALTSTACK +/* Define to 1 if you have the `sigfillset' function. */ +#undef HAVE_SIGFILLSET + /* Define to 1 if `si_band' is a member of `siginfo_t'. */ #undef HAVE_SIGINFO_T_SI_BAND From webhook-mailer at python.org Fri May 4 17:21:04 2018 From: webhook-mailer at python.org (Vinay Sajip) Date: Fri, 04 May 2018 21:21:04 -0000 Subject: [Python-checkins] bpo-33400: Clarified documentation to indicate no strict adherence to ISO 8601. (GH-6702) Message-ID: https://github.com/python/cpython/commit/c4994dc00d9828a99510f3851da93b0e1c18361d commit: c4994dc00d9828a99510f3851da93b0e1c18361d branch: master author: Vinay Sajip committer: GitHub date: 2018-05-04T22:20:54+01:00 summary: bpo-33400: Clarified documentation to indicate no strict adherence to ISO 8601. (GH-6702) files: M Doc/howto/logging.rst M Doc/library/logging.config.rst M Doc/library/logging.rst M Lib/logging/__init__.py diff --git a/Doc/howto/logging.rst b/Doc/howto/logging.rst index f8b78b618569..e9e5580df969 100644 --- a/Doc/howto/logging.rst +++ b/Doc/howto/logging.rst @@ -296,9 +296,9 @@ which should print something like this: 2010-12-12 11:41:42,612 is when this event was logged. -The default format for date/time display (shown above) is ISO8601. If you need -more control over the formatting of the date/time, provide a *datefmt* -argument to ``basicConfig``, as in this example:: +The default format for date/time display (shown above) is like ISO8601 or +RFC 3339. If you need more control over the formatting of the date/time, provide +a *datefmt* argument to ``basicConfig``, as in this example:: import logging logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p') diff --git a/Doc/library/logging.config.rst b/Doc/library/logging.config.rst index 1f9d7c7f220b..b5007610c40f 100644 --- a/Doc/library/logging.config.rst +++ b/Doc/library/logging.config.rst @@ -790,10 +790,10 @@ Sections which specify formatter configuration are typified by the following. The ``format`` entry is the overall format string, and the ``datefmt`` entry is the :func:`strftime`\ -compatible date/time format string. If empty, the -package substitutes ISO8601 format date/times, which is almost equivalent to -specifying the date format string ``'%Y-%m-%d %H:%M:%S'``. The ISO8601 format -also specifies milliseconds, which are appended to the result of using the above -format string, with a comma separator. An example time in ISO8601 format is +package substitutes ISO8601-style format date/times, which is almost equivalent to +specifying the date format string ``'%Y-%m-%d %H:%M:%S'``. This format also +specifies milliseconds, which are appended to the result of using the above +format string, with a comma separator. An example time in this format is ``2003-01-23 00:29:50,411``. The ``class`` entry is optional. It indicates the name of the formatter's class diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst index f9eda173ad0d..9a54bf9325a0 100644 --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -515,8 +515,9 @@ The useful mapping keys in a :class:`LogRecord` are given in the section on Returns a new instance of the :class:`Formatter` class. The instance is initialized with a format string for the message as a whole, as well as a format string for the date/time portion of a message. If no *fmt* is - specified, ``'%(message)s'`` is used. If no *datefmt* is specified, the - ISO8601 date format is used. + specified, ``'%(message)s'`` is used. If no *datefmt* is specified, an + ISO8601-like (or RFC3339-like) date format is used. See the + :meth:`formatTime` documentation for more details. The *style* parameter can be one of '%', '{' or '$' and determines how the format string will be merged with its data: using one of %-formatting, @@ -556,8 +557,8 @@ The useful mapping keys in a :class:`LogRecord` are given in the section on formatters to provide for any specific requirement, but the basic behavior is as follows: if *datefmt* (a string) is specified, it is used with :func:`time.strftime` to format the creation time of the - record. Otherwise, the ISO8601 format is used. The resulting string is - returned. + record. Otherwise, an ISO8601-like (or RDC 3339-like) format is used. The + resulting string is returned. This function uses a user-configurable function to convert the creation time to a tuple. By default, :func:`time.localtime` is used; to change @@ -568,7 +569,7 @@ The useful mapping keys in a :class:`LogRecord` are given in the section on attribute in the ``Formatter`` class. .. versionchanged:: 3.3 - Previously, the default ISO 8601 format was hard-coded as in this + Previously, the default ISO8601-like format was hard-coded as in this example: ``2010-09-06 22:38:15,292`` where the part before the comma is handled by a strptime format string (``'%Y-%m-%d %H:%M:%S'``), and the part after the comma is a millisecond value. Because strptime does not diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py index 9f2c0f0c58a3..46c590687c7d 100644 --- a/Lib/logging/__init__.py +++ b/Lib/logging/__init__.py @@ -466,7 +466,8 @@ def __init__(self, fmt=None, datefmt=None, style='%'): Initialize the formatter either with the specified format string, or a default as described above. Allow for specialized date formatting with - the optional datefmt argument (if omitted, you get the ISO8601 format). + the optional datefmt argument. If datefmt is omitted, you get an + ISO8601-like (or RFC 3339-like) format. Use a style parameter of '%', '{' or '$' to specify that you want to use one of %-formatting, :meth:`str.format` (``{}``) formatting or @@ -494,13 +495,13 @@ def formatTime(self, record, datefmt=None): in formatters to provide for any specific requirement, but the basic behaviour is as follows: if datefmt (a string) is specified, it is used with time.strftime() to format the creation time of the - record. Otherwise, the ISO8601 format is used. The resulting - string is returned. This function uses a user-configurable function - to convert the creation time to a tuple. By default, time.localtime() - is used; to change this for a particular formatter instance, set the - 'converter' attribute to a function with the same signature as - time.localtime() or time.gmtime(). To change it for all formatters, - for example if you want all logging times to be shown in GMT, + record. Otherwise, an ISO8601-like (or RFC 3339-like) format is used. + The resulting string is returned. This function uses a user-configurable + function to convert the creation time to a tuple. By default, + time.localtime() is used; to change this for a particular formatter + instance, set the 'converter' attribute to a function with the same + signature as time.localtime() or time.gmtime(). To change it for all + formatters, for example if you want all logging times to be shown in GMT, set the 'converter' attribute in the Formatter class. """ ct = self.converter(record.created) From webhook-mailer at python.org Fri May 4 18:02:52 2018 From: webhook-mailer at python.org (Vinay Sajip) Date: Fri, 04 May 2018 22:02:52 -0000 Subject: [Python-checkins] bpo-33400: Clarified documentation to indicate no strict adherence to ISO 8601. (GH-6703) Message-ID: https://github.com/python/cpython/commit/eb5abdc70815c4207829551ede4a7dc302d56c19 commit: eb5abdc70815c4207829551ede4a7dc302d56c19 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Vinay Sajip date: 2018-05-04T23:02:48+01:00 summary: bpo-33400: Clarified documentation to indicate no strict adherence to ISO 8601. (GH-6703) (cherry picked from commit c4994dc00d9828a99510f3851da93b0e1c18361d) Co-authored-by: Vinay Sajip files: M Doc/howto/logging.rst M Doc/library/logging.config.rst M Doc/library/logging.rst M Lib/logging/__init__.py diff --git a/Doc/howto/logging.rst b/Doc/howto/logging.rst index cc230e1897ba..5976c32d93b0 100644 --- a/Doc/howto/logging.rst +++ b/Doc/howto/logging.rst @@ -296,9 +296,9 @@ which should print something like this: 2010-12-12 11:41:42,612 is when this event was logged. -The default format for date/time display (shown above) is ISO8601. If you need -more control over the formatting of the date/time, provide a *datefmt* -argument to ``basicConfig``, as in this example:: +The default format for date/time display (shown above) is like ISO8601 or +RFC 3339. If you need more control over the formatting of the date/time, provide +a *datefmt* argument to ``basicConfig``, as in this example:: import logging logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p') diff --git a/Doc/library/logging.config.rst b/Doc/library/logging.config.rst index 9a75a3c81d83..5f5ea03362ea 100644 --- a/Doc/library/logging.config.rst +++ b/Doc/library/logging.config.rst @@ -783,10 +783,10 @@ Sections which specify formatter configuration are typified by the following. The ``format`` entry is the overall format string, and the ``datefmt`` entry is the :func:`strftime`\ -compatible date/time format string. If empty, the -package substitutes ISO8601 format date/times, which is almost equivalent to -specifying the date format string ``'%Y-%m-%d %H:%M:%S'``. The ISO8601 format -also specifies milliseconds, which are appended to the result of using the above -format string, with a comma separator. An example time in ISO8601 format is +package substitutes ISO8601-style format date/times, which is almost equivalent to +specifying the date format string ``'%Y-%m-%d %H:%M:%S'``. This format also +specifies milliseconds, which are appended to the result of using the above +format string, with a comma separator. An example time in this format is ``2003-01-23 00:29:50,411``. The ``class`` entry is optional. It indicates the name of the formatter's class diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst index 55b8dda0df47..d0a6e613d8ee 100644 --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -515,8 +515,9 @@ The useful mapping keys in a :class:`LogRecord` are given in the section on Returns a new instance of the :class:`Formatter` class. The instance is initialized with a format string for the message as a whole, as well as a format string for the date/time portion of a message. If no *fmt* is - specified, ``'%(message)s'`` is used. If no *datefmt* is specified, the - ISO8601 date format is used. + specified, ``'%(message)s'`` is used. If no *datefmt* is specified, an + ISO8601-like (or RFC3339-like) date format is used. See the + :meth:`formatTime` documentation for more details. The *style* parameter can be one of '%', '{' or '$' and determines how the format string will be merged with its data: using one of %-formatting, @@ -556,8 +557,8 @@ The useful mapping keys in a :class:`LogRecord` are given in the section on formatters to provide for any specific requirement, but the basic behavior is as follows: if *datefmt* (a string) is specified, it is used with :func:`time.strftime` to format the creation time of the - record. Otherwise, the ISO8601 format is used. The resulting string is - returned. + record. Otherwise, an ISO8601-like (or RDC 3339-like) format is used. The + resulting string is returned. This function uses a user-configurable function to convert the creation time to a tuple. By default, :func:`time.localtime` is used; to change @@ -568,7 +569,7 @@ The useful mapping keys in a :class:`LogRecord` are given in the section on attribute in the ``Formatter`` class. .. versionchanged:: 3.3 - Previously, the default ISO 8601 format was hard-coded as in this + Previously, the default ISO8601-like format was hard-coded as in this example: ``2010-09-06 22:38:15,292`` where the part before the comma is handled by a strptime format string (``'%Y-%m-%d %H:%M:%S'``), and the part after the comma is a millisecond value. Because strptime does not diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py index 3617dbb6d996..e2084f550508 100644 --- a/Lib/logging/__init__.py +++ b/Lib/logging/__init__.py @@ -473,7 +473,8 @@ def __init__(self, fmt=None, datefmt=None, style='%'): Initialize the formatter either with the specified format string, or a default as described above. Allow for specialized date formatting with - the optional datefmt argument (if omitted, you get the ISO8601 format). + the optional datefmt argument. If datefmt is omitted, you get an + ISO8601-like (or RFC 3339-like) format. Use a style parameter of '%', '{' or '$' to specify that you want to use one of %-formatting, :meth:`str.format` (``{}``) formatting or @@ -501,13 +502,13 @@ def formatTime(self, record, datefmt=None): in formatters to provide for any specific requirement, but the basic behaviour is as follows: if datefmt (a string) is specified, it is used with time.strftime() to format the creation time of the - record. Otherwise, the ISO8601 format is used. The resulting - string is returned. This function uses a user-configurable function - to convert the creation time to a tuple. By default, time.localtime() - is used; to change this for a particular formatter instance, set the - 'converter' attribute to a function with the same signature as - time.localtime() or time.gmtime(). To change it for all formatters, - for example if you want all logging times to be shown in GMT, + record. Otherwise, an ISO8601-like (or RFC 3339-like) format is used. + The resulting string is returned. This function uses a user-configurable + function to convert the creation time to a tuple. By default, + time.localtime() is used; to change this for a particular formatter + instance, set the 'converter' attribute to a function with the same + signature as time.localtime() or time.gmtime(). To change it for all + formatters, for example if you want all logging times to be shown in GMT, set the 'converter' attribute in the Formatter class. """ ct = self.converter(record.created) From lp_benchmark_robot at intel.com Fri May 4 19:50:54 2018 From: lp_benchmark_robot at intel.com (lp_benchmark_robot at intel.com) Date: Fri, 4 May 2018 16:50:54 -0700 Subject: [Python-checkins] [65 flat] Results for Python (master branch) 2018-05-04 Message-ID: Results for project python/master, build date: 2018-05-04 09:43:37-07:00. - commit: 9d3627e - previous commit: 491bbed - revision date: 2018-05-04 13:00:50+02:00 - environment: Broadwell-EP - cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores, stepping 1, LLC 55 MB - mem: 128 GB - os: Ubuntu 16.04.2 LTS - kernel: 4.4.0-62-generic x86_64 GNU/Linux Baseline results were generated using release v3.6.0, with hash 5c4568a from 2016-12-22 23:38:47+00:00. +-----+------------------------+--------+------------+------------+------------+ | | |relative|change since|change since|current rev | | | benchmark|std_dev*| last run | baseline |run with PGO| +-----+------------------------+--------+------------+------------+------------+ | :-| | 2to3| 0.614% | +0.093% | +8.310% | +7.737% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method| 1.722% | -0.036% | +23.735% | +12.833% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_slots| 0.988% | +0.056% | +25.581% | +12.083% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_unknown| 1.298% | +0.009% | +23.698% | +9.526% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_simple| 3.171% | -0.005% | +9.801% | +14.490% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chameleon| 1.489% | +0.434% | +12.153% | +10.749% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chaos| 0.778% | +0.606% | +9.427% | +9.797% | +-----+------------------------+--------+------------+------------+------------+ | :-| | crypto_pyaes| 0.525% | +0.412% | -1.385% | +9.957% | +-----+------------------------+--------+------------+------------+------------+ | :-| | deltablue| 3.294% | -1.359% | +11.190% | +17.046% | +-----+------------------------+--------+------------+------------+------------+ | :-| | django_template| 1.410% | +1.362% | +21.787% | +13.023% | +-----+------------------------+--------+------------+------------+------------+ | :-| | dulwich_log| 1.249% | +0.122% | +5.282% | +6.809% | +-----+------------------------+--------+------------+------------+------------+ | :-| | fannkuch| 0.278% | +0.894% | +7.134% | +6.340% | +-----+------------------------+--------+------------+------------+------------+ | :-| | float| 1.086% | -0.302% | +2.569% | +7.353% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_text| 1.134% | +0.080% | +13.658% | +10.642% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_xml| 1.164% | +2.091% | +12.781% | +9.025% | +-----+------------------------+--------+------------+------------+------------+ | :-| | go| 6.831% | -0.029% | +3.903% | +12.791% | +-----+------------------------+--------+------------+------------+------------+ | :-| | hexiom| 0.425% | +0.246% | +11.380% | +11.462% | +-----+------------------------+--------+------------+------------+------------+ | :-| | html5lib| 2.547% | +0.873% | +11.404% | +11.672% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_dumps| 0.945% | -0.150% | +2.265% | +9.853% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_loads| 1.922% | +0.705% | -5.113% | +16.410% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_format| 1.415% | +0.904% | +18.222% | +13.536% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_silent| 3.004% | -1.257% | +47.528% | +12.984% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_simple| 1.365% | +0.651% | +12.267% | +14.545% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mako| 0.459% | +0.265% | +15.636% | +15.910% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mdp| 8.215% | -1.690% | +2.743% | +15.598% | +-----+------------------------+--------+------------+------------+------------+ | :-| | meteor_contest| 1.303% | -0.187% | +4.373% | +7.381% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nbody| 0.682% | +1.343% | -0.776% | +2.308% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nqueens| 2.020% | +1.110% | +5.710% | +6.967% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pathlib| 1.127% | +0.200% | -1.109% | +11.880% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle| 1.651% | +0.060% | +0.349% | +22.356% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_dict| 0.213% | -0.025% | +4.325% | +20.808% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_list| 0.713% | +0.430% | +6.057% | +19.828% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_pure_python| 4.567% | +3.309% | +11.345% | +11.373% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pidigits| 0.159% | +0.029% | +0.238% | +10.511% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup| 0.125% | +0.112% | +18.431% | +6.403% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup_no_site| 0.083% | +0.125% | +5.462% | +6.361% | +-----+------------------------+--------+------------+------------+------------+ | :-| | raytrace| 0.942% | -0.084% | +10.408% | +13.571% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_compile| 4.911% | +1.368% | +2.668% | +11.831% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_dna| 0.533% | -0.125% | -2.141% | +13.985% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_effbot| 2.459% | -1.411% | -4.147% | +8.126% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_v8| 0.887% | -0.219% | +3.198% | +9.745% | +-----+------------------------+--------+------------+------------+------------+ | :-| | richards| 1.946% | -0.321% | +9.527% | +14.992% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_fft| 0.602% | +1.760% | -1.344% | +5.101% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_lu| 2.932% | -1.584% | +21.385% | +13.065% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_monte_carlo| 1.791% | +0.719% | +5.082% | +4.695% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sor| 1.508% | +0.728% | +14.077% | +9.759% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sparse_mat_mult| 1.872% | +1.067% | -4.674% | +2.545% | +-----+------------------------+--------+------------+------------+------------+ | :-| | spectral_norm| 0.732% | -0.015% | +3.554% | +9.241% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_declarative| 1.072% | -0.073% | +6.652% | +6.720% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_imperative| 3.842% | -0.405% | +7.427% | +4.914% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlite_synth| 3.491% | -0.328% | +0.472% | +9.252% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_expand| 2.926% | +0.595% | +17.333% | +7.469% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_integrate| 1.383% | +0.517% | +18.094% | +6.808% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_str| 3.862% | +1.158% | +18.881% | +8.409% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_sum| 6.650% | +0.213% | +15.270% | +10.964% | +-----+------------------------+--------+------------+------------+------------+ | :-| | telco| 3.158% | -0.675% | +18.223% | +10.708% | +-----+------------------------+--------+------------+------------+------------+ | :-| | tornado_http| 0.974% | +0.105% | +7.103% | +6.983% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpack_sequence| 1.227% | +0.067% | +2.272% | +0.464% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle| 7.002% | -2.631% | +6.059% | +22.559% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_list| 0.782% | +1.973% | -1.865% | +14.516% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_pure_python| 2.570% | +0.648% | +6.258% | +9.334% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_generate| 0.876% | +0.945% | +2.941% | +12.582% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_iterparse| 2.312% | -0.433% | +2.156% | +9.710% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_parse| 4.461% | -0.217% | -9.330% | +12.050% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_process| 1.144% | +0.417% | +4.354% | +12.002% | +-----+------------------------+--------+------------+------------+------------+ * Relative Standard Deviation (Standard Deviation/Average) If this is not displayed properly please visit our results page here: http://languagesperformance.intel.com/65-flat-results-for-python-master-branch-2018-05-04 Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. From solipsis at pitrou.net Sat May 5 05:10:04 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 05 May 2018 09:10:04 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=14 Message-ID: <20180505091004.1.48AF689AF135DDCB@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_asyncio leaked [0, 0, 3] memory blocks, sum=3 test_collections leaked [0, 7, 0] memory blocks, sum=7 test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_forkserver leaked [-1, -1, 2] memory blocks, sum=0 test_multiprocessing_spawn leaked [-1, -1, 2] memory blocks, sum=0 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogzdIIhr', '--timeout', '7200'] From webhook-mailer at python.org Sat May 5 07:09:51 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sat, 05 May 2018 11:09:51 -0000 Subject: [Python-checkins] [2.7] bpo-32362: Fix references to non-existent multiprocessing.Connection() (GH-6223) (GH-6646) Message-ID: https://github.com/python/cpython/commit/4a1bc26832048325aecc01a4783a4984496d52d2 commit: 4a1bc26832048325aecc01a4783a4984496d52d2 branch: 2.7 author: Bo Bayles committer: Serhiy Storchaka date: 2018-05-05T14:09:46+03:00 summary: [2.7] bpo-32362: Fix references to non-existent multiprocessing.Connection() (GH-6223) (GH-6646) (cherry picked from commit 9f3535c9cde8813ce631d6ebe4d790682f594828) Co-authored-by: Bo Bayles files: M Doc/library/multiprocessing.rst diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst index 81c46c0b637b..2d8660aba9c8 100644 --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -803,10 +803,13 @@ Miscellaneous Connection Objects ~~~~~~~~~~~~~~~~~~ +.. currentmodule:: None + Connection objects allow the sending and receiving of picklable objects or strings. They can be thought of as message oriented connected sockets. -Connection objects are usually created using :func:`Pipe` -- see also +Connection objects are usually created using +:func:`Pipe ` -- see also :ref:`multiprocessing-listeners-clients`. .. class:: Connection @@ -926,6 +929,8 @@ For example: Synchronization primitives ~~~~~~~~~~~~~~~~~~~~~~~~~~ +.. currentmodule:: multiprocessing + Generally synchronization primitives are not as necessary in a multiprocess program as they are in a multithreaded program. See the documentation for :mod:`threading` module. @@ -1943,8 +1948,7 @@ Listeners and Clients :synopsis: API for dealing with sockets. Usually message passing between processes is done using queues or by using -:class:`~multiprocessing.Connection` objects returned by -:func:`~multiprocessing.Pipe`. +:class:`Connection` objects returned by :func:`~multiprocessing.Pipe`. However, the :mod:`multiprocessing.connection` module allows some extra flexibility. It basically gives a high level message oriented API for dealing @@ -1972,7 +1976,7 @@ authentication* using the :mod:`hmac` module. .. function:: Client(address[, family[, authenticate[, authkey]]]) Attempt to set up a connection to the listener which is using address - *address*, returning a :class:`~multiprocessing.Connection`. + *address*, returning a :class:`Connection`. The type of the connection is determined by *family* argument, but this can generally be omitted since it can usually be inferred from the format of @@ -2028,8 +2032,8 @@ authentication* using the :mod:`hmac` module. .. method:: accept() Accept a connection on the bound socket or named pipe of the listener - object and return a :class:`~multiprocessing.Connection` object. If - authentication is attempted and fails, then + object and return a :class:`Connection` object. + If authentication is attempted and fails, then :exc:`~multiprocessing.AuthenticationError` is raised. .. method:: close() @@ -2139,7 +2143,7 @@ an ``'AF_PIPE'`` address rather than an ``'AF_UNIX'`` address. Authentication keys ~~~~~~~~~~~~~~~~~~~ -When one uses :meth:`Connection.recv `, the +When one uses :meth:`Connection.recv`, the data received is automatically unpickled. Unfortunately unpickling data from an untrusted source is a security risk. Therefore :class:`Listener` and :func:`Client` use the :mod:`hmac` module From webhook-mailer at python.org Sat May 5 09:10:51 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sat, 05 May 2018 13:10:51 -0000 Subject: [Python-checkins] bpo-32857: Raise error when tkinter after_cancel() is called with None. (GH-5701) (GH-6620) Message-ID: https://github.com/python/cpython/commit/3a04598f63960e72025a91c682aec51b6b460413 commit: 3a04598f63960e72025a91c682aec51b6b460413 branch: 2.7 author: Cheryl Sabella committer: Serhiy Storchaka date: 2018-05-05T16:10:48+03:00 summary: bpo-32857: Raise error when tkinter after_cancel() is called with None. (GH-5701) (GH-6620) (cherry picked from commit 74382a3f175ac285cc924a73fd758e8dc3cc41bb) files: A Lib/lib-tk/test/test_tkinter/test_misc.py A Misc/NEWS.d/next/Library/2018-02-16-14-37-14.bpo-32857.-XljAx.rst M Lib/lib-tk/Tkinter.py diff --git a/Lib/lib-tk/Tkinter.py b/Lib/lib-tk/Tkinter.py index b226fd5f3529..f46642f5bb99 100644 --- a/Lib/lib-tk/Tkinter.py +++ b/Lib/lib-tk/Tkinter.py @@ -586,6 +586,7 @@ def after(self, ms, func=None, *args): if not func: # I'd rather use time.sleep(ms*0.001) self.tk.call('after', ms) + return None else: def callit(): try: @@ -609,11 +610,13 @@ def after_cancel(self, id): """Cancel scheduling of function identified with ID. Identifier returned by after or after_idle must be - given as first parameter.""" + given as first parameter. + """ + if not id: + raise ValueError('id must be a valid identifier returned from ' + 'after or after_idle') try: data = self.tk.call('after', 'info', id) - # In Tk 8.3, splitlist returns: (script, type) - # In Tk 8.4, splitlist may return (script, type) or (script,) script = self.tk.splitlist(data)[0] self.deletecommand(script) except TclError: diff --git a/Lib/lib-tk/test/test_tkinter/test_misc.py b/Lib/lib-tk/test/test_tkinter/test_misc.py new file mode 100644 index 000000000000..796269ede409 --- /dev/null +++ b/Lib/lib-tk/test/test_tkinter/test_misc.py @@ -0,0 +1,122 @@ +import unittest +import Tkinter as tkinter +from test.test_support import requires, run_unittest +from test_ttk.support import AbstractTkTest + +requires('gui') + +class MiscTest(AbstractTkTest, unittest.TestCase): + + def test_after(self): + root = self.root + cbcount = {'count': 0} + + def callback(start=0, step=1): + cbcount['count'] = start + step + + # Without function, sleeps for ms. + self.assertIsNone(root.after(1)) + + # Set up with callback with no args. + cbcount['count'] = 0 + timer1 = root.after(0, callback) + self.assertIn(timer1, root.tk.call('after', 'info')) + (script, _) = root.tk.splitlist(root.tk.call('after', 'info', timer1)) + root.update() # Process all pending events. + self.assertEqual(cbcount['count'], 1) + with self.assertRaises(tkinter.TclError): + root.tk.call(script) + + # Set up with callback with args. + cbcount['count'] = 0 + timer1 = root.after(0, callback, 42, 11) + root.update() # Process all pending events. + self.assertEqual(cbcount['count'], 53) + + # Cancel before called. + timer1 = root.after(1000, callback) + self.assertIn(timer1, root.tk.call('after', 'info')) + (script, _) = root.tk.splitlist(root.tk.call('after', 'info', timer1)) + root.after_cancel(timer1) # Cancel this event. + self.assertEqual(cbcount['count'], 53) + with self.assertRaises(tkinter.TclError): + root.tk.call(script) + + def test_after_idle(self): + root = self.root + cbcount = {'count': 0} + + def callback(start=0, step=1): + cbcount['count'] = start + step + + # Set up with callback with no args. + cbcount['count'] = 0 + idle1 = root.after_idle(callback) + self.assertIn(idle1, root.tk.call('after', 'info')) + (script, _) = root.tk.splitlist(root.tk.call('after', 'info', idle1)) + root.update_idletasks() # Process all pending events. + self.assertEqual(cbcount['count'], 1) + with self.assertRaises(tkinter.TclError): + root.tk.call(script) + + # Set up with callback with args. + cbcount['count'] = 0 + idle1 = root.after_idle(callback, 42, 11) + root.update_idletasks() # Process all pending events. + self.assertEqual(cbcount['count'], 53) + + # Cancel before called. + idle1 = root.after_idle(callback) + self.assertIn(idle1, root.tk.call('after', 'info')) + (script, _) = root.tk.splitlist(root.tk.call('after', 'info', idle1)) + root.after_cancel(idle1) # Cancel this event. + self.assertEqual(cbcount['count'], 53) + with self.assertRaises(tkinter.TclError): + root.tk.call(script) + + def test_after_cancel(self): + root = self.root + cbcount = {'count': 0} + + def callback(): + cbcount['count'] += 1 + + timer1 = root.after(5000, callback) + idle1 = root.after_idle(callback) + + # No value for id raises a ValueError. + with self.assertRaises(ValueError): + root.after_cancel(None) + + # Cancel timer event. + cbcount['count'] = 0 + (script, _) = root.tk.splitlist(root.tk.call('after', 'info', timer1)) + root.tk.call(script) + self.assertEqual(cbcount['count'], 1) + root.after_cancel(timer1) + with self.assertRaises(tkinter.TclError): + root.tk.call(script) + self.assertEqual(cbcount['count'], 1) + with self.assertRaises(tkinter.TclError): + root.tk.call('after', 'info', timer1) + + # Cancel same event - nothing happens. + root.after_cancel(timer1) + + # Cancel idle event. + cbcount['count'] = 0 + (script, _) = root.tk.splitlist(root.tk.call('after', 'info', idle1)) + root.tk.call(script) + self.assertEqual(cbcount['count'], 1) + root.after_cancel(idle1) + with self.assertRaises(tkinter.TclError): + root.tk.call(script) + self.assertEqual(cbcount['count'], 1) + with self.assertRaises(tkinter.TclError): + root.tk.call('after', 'info', idle1) + + +tests_gui = (MiscTest, ) + +if __name__ == "__main__": + run_unittest(*tests_gui) diff --git a/Misc/NEWS.d/next/Library/2018-02-16-14-37-14.bpo-32857.-XljAx.rst b/Misc/NEWS.d/next/Library/2018-02-16-14-37-14.bpo-32857.-XljAx.rst new file mode 100644 index 000000000000..4ebbde4d1946 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-16-14-37-14.bpo-32857.-XljAx.rst @@ -0,0 +1 @@ +In :mod:`tkinter`, ``after_cancel(None)`` now raises a :exc:`ValueError` instead of canceling the first scheduled function. Patch by Cheryl Sabella. From webhook-mailer at python.org Sat May 5 12:07:35 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sat, 05 May 2018 16:07:35 -0000 Subject: [Python-checkins] bpo-33422: Fix quotation marks getting deleted when looking up byte/string literals on pydoc. (GH-6701) Message-ID: https://github.com/python/cpython/commit/b2043bbe6034b53f5ad337887f4741b74b70b00d commit: b2043bbe6034b53f5ad337887f4741b74b70b00d branch: master author: Andr?s Delfino committer: Serhiy Storchaka date: 2018-05-05T19:07:32+03:00 summary: bpo-33422: Fix quotation marks getting deleted when looking up byte/string literals on pydoc. (GH-6701) Also update the list of string prefixes. files: A Misc/NEWS.d/next/Library/2018-05-05-09-53-05.bpo-33422.4FtQ0q.rst M Lib/pydoc.py diff --git a/Lib/pydoc.py b/Lib/pydoc.py index e7a1655b228f..199745ca6fa8 100644 --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -1747,8 +1747,9 @@ class Helper: } # Either add symbols to this dictionary or to the symbols dictionary # directly: Whichever is easier. They are merged later. + _strprefixes = [p + q for p in ('b', 'f', 'r', 'u') for q in ("'", '"')] _symbols_inverse = { - 'STRINGS' : ("'", "'''", "r'", "b'", '"""', '"', 'r"', 'b"'), + 'STRINGS' : ("'", "'''", '"', '"""', *_strprefixes), 'OPERATORS' : ('+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&', '|', '^', '~', '<', '>', '<=', '>=', '==', '!=', '<>'), 'COMPARISON' : ('<', '>', '<=', '>=', '==', '!=', '<>'), @@ -1910,7 +1911,13 @@ def interact(self): if not request: break except (KeyboardInterrupt, EOFError): break - request = replace(request, '"', '', "'", '').strip() + request = request.strip() + + # Make sure significant trailing quoting marks of literals don't + # get deleted while cleaning input + if (len(request) > 2 and request[0] == request[-1] in ("'", '"') + and request[0] not in request[1:-1]): + request = request[1:-1] if request.lower() in ('q', 'quit'): break if request == 'help': self.intro() diff --git a/Misc/NEWS.d/next/Library/2018-05-05-09-53-05.bpo-33422.4FtQ0q.rst b/Misc/NEWS.d/next/Library/2018-05-05-09-53-05.bpo-33422.4FtQ0q.rst new file mode 100644 index 000000000000..0d284d508f10 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-05-09-53-05.bpo-33422.4FtQ0q.rst @@ -0,0 +1,2 @@ +Fix trailing quotation marks getting deleted when looking up byte/string +literals on pydoc. Patch by Andr?s Delfino. From webhook-mailer at python.org Sat May 5 12:42:59 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 05 May 2018 16:42:59 -0000 Subject: [Python-checkins] bpo-33422: Fix quotation marks getting deleted when looking up byte/string literals on pydoc. (GH-6701) Message-ID: https://github.com/python/cpython/commit/351782b9927c610ff531100dbdcbbd19d91940a3 commit: 351782b9927c610ff531100dbdcbbd19d91940a3 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-05-05T09:42:56-07:00 summary: bpo-33422: Fix quotation marks getting deleted when looking up byte/string literals on pydoc. (GH-6701) Also update the list of string prefixes. (cherry picked from commit b2043bbe6034b53f5ad337887f4741b74b70b00d) Co-authored-by: Andr?s Delfino files: A Misc/NEWS.d/next/Library/2018-05-05-09-53-05.bpo-33422.4FtQ0q.rst M Lib/pydoc.py diff --git a/Lib/pydoc.py b/Lib/pydoc.py index e7a1655b228f..199745ca6fa8 100644 --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -1747,8 +1747,9 @@ class Helper: } # Either add symbols to this dictionary or to the symbols dictionary # directly: Whichever is easier. They are merged later. + _strprefixes = [p + q for p in ('b', 'f', 'r', 'u') for q in ("'", '"')] _symbols_inverse = { - 'STRINGS' : ("'", "'''", "r'", "b'", '"""', '"', 'r"', 'b"'), + 'STRINGS' : ("'", "'''", '"', '"""', *_strprefixes), 'OPERATORS' : ('+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&', '|', '^', '~', '<', '>', '<=', '>=', '==', '!=', '<>'), 'COMPARISON' : ('<', '>', '<=', '>=', '==', '!=', '<>'), @@ -1910,7 +1911,13 @@ def interact(self): if not request: break except (KeyboardInterrupt, EOFError): break - request = replace(request, '"', '', "'", '').strip() + request = request.strip() + + # Make sure significant trailing quoting marks of literals don't + # get deleted while cleaning input + if (len(request) > 2 and request[0] == request[-1] in ("'", '"') + and request[0] not in request[1:-1]): + request = request[1:-1] if request.lower() in ('q', 'quit'): break if request == 'help': self.intro() diff --git a/Misc/NEWS.d/next/Library/2018-05-05-09-53-05.bpo-33422.4FtQ0q.rst b/Misc/NEWS.d/next/Library/2018-05-05-09-53-05.bpo-33422.4FtQ0q.rst new file mode 100644 index 000000000000..0d284d508f10 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-05-09-53-05.bpo-33422.4FtQ0q.rst @@ -0,0 +1,2 @@ +Fix trailing quotation marks getting deleted when looking up byte/string +literals on pydoc. Patch by Andr?s Delfino. From webhook-mailer at python.org Sat May 5 13:12:22 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 05 May 2018 17:12:22 -0000 Subject: [Python-checkins] bpo-33422: Fix quotation marks getting deleted when looking up byte/string literals on pydoc. (GH-6701) Message-ID: https://github.com/python/cpython/commit/0ba812b1bee65a6cad16f153a7f5074bc271e0e5 commit: 0ba812b1bee65a6cad16f153a7f5074bc271e0e5 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-05-05T10:12:19-07:00 summary: bpo-33422: Fix quotation marks getting deleted when looking up byte/string literals on pydoc. (GH-6701) Also update the list of string prefixes. (cherry picked from commit b2043bbe6034b53f5ad337887f4741b74b70b00d) Co-authored-by: Andr?s Delfino files: A Misc/NEWS.d/next/Library/2018-05-05-09-53-05.bpo-33422.4FtQ0q.rst M Lib/pydoc.py diff --git a/Lib/pydoc.py b/Lib/pydoc.py index 34e2fabf20ee..40ee76044089 100644 --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -1716,8 +1716,9 @@ class Helper: } # Either add symbols to this dictionary or to the symbols dictionary # directly: Whichever is easier. They are merged later. + _strprefixes = [p + q for p in ('b', 'f', 'r', 'u') for q in ("'", '"')] _symbols_inverse = { - 'STRINGS' : ("'", "'''", "r'", "b'", '"""', '"', 'r"', 'b"'), + 'STRINGS' : ("'", "'''", '"', '"""', *_strprefixes), 'OPERATORS' : ('+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&', '|', '^', '~', '<', '>', '<=', '>=', '==', '!=', '<>'), 'COMPARISON' : ('<', '>', '<=', '>=', '==', '!=', '<>'), @@ -1874,7 +1875,13 @@ def interact(self): if not request: break except (KeyboardInterrupt, EOFError): break - request = replace(request, '"', '', "'", '').strip() + request = request.strip() + + # Make sure significant trailing quoting marks of literals don't + # get deleted while cleaning input + if (len(request) > 2 and request[0] == request[-1] in ("'", '"') + and request[0] not in request[1:-1]): + request = request[1:-1] if request.lower() in ('q', 'quit'): break if request == 'help': self.intro() diff --git a/Misc/NEWS.d/next/Library/2018-05-05-09-53-05.bpo-33422.4FtQ0q.rst b/Misc/NEWS.d/next/Library/2018-05-05-09-53-05.bpo-33422.4FtQ0q.rst new file mode 100644 index 000000000000..0d284d508f10 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-05-09-53-05.bpo-33422.4FtQ0q.rst @@ -0,0 +1,2 @@ +Fix trailing quotation marks getting deleted when looking up byte/string +literals on pydoc. Patch by Andr?s Delfino. From webhook-mailer at python.org Sun May 6 01:46:24 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sun, 06 May 2018 05:46:24 -0000 Subject: [Python-checkins] =?utf-8?q?bpo-20087=3A_Update_locale_alias_map?= =?utf-8?q?ping_with_glibc_2=2E27_supported_locales=2E_=28=D0=9F=D0=A0-670?= =?utf-8?q?8=29?= Message-ID: https://github.com/python/cpython/commit/cedc9b74202d8c1ae39bca261cbb45d42ed54d45 commit: cedc9b74202d8c1ae39bca261cbb45d42ed54d45 branch: master author: Serhiy Storchaka committer: GitHub date: 2018-05-06T08:46:15+03:00 summary: bpo-20087: Update locale alias mapping with glibc 2.27 supported locales. (??-6708) files: A Misc/NEWS.d/next/Library/2018-05-05-18-02-24.bpo-20087.lJrvXL.rst M Lib/locale.py M Lib/test/test_locale.py diff --git a/Lib/locale.py b/Lib/locale.py index 18079e73ad69..876d2eb1e123 100644 --- a/Lib/locale.py +++ b/Lib/locale.py @@ -846,6 +846,16 @@ def getpreferredencoding(do_setlocale = True): # # SS 2014-10-01: # Updated alias mapping with glibc 2.19 supported locales. +# +# SS 2018-05-05: +# Updated alias mapping with glibc 2.27 supported locales. +# +# These are the differences compared to the old mapping (Python 3.6.5 +# and older): +# +# updated 'ca_es at valencia' -> 'ca_ES.ISO8859-15 at valencia' to 'ca_ES.UTF-8 at valencia' +# updated 'kk_kz' -> 'kk_KZ.RK1048' to 'kk_KZ.ptcp154' +# updated 'russian' -> 'ru_RU.ISO8859-5' to 'ru_RU.KOI8-R' locale_alias = { 'a3': 'az_AZ.KOI8-C', @@ -856,10 +866,13 @@ def getpreferredencoding(do_setlocale = True): 'aa_et': 'aa_ET.UTF-8', 'af': 'af_ZA.ISO8859-1', 'af_za': 'af_ZA.ISO8859-1', + 'agr_pe': 'agr_PE.UTF-8', + 'ak_gh': 'ak_GH.UTF-8', 'am': 'am_ET.UTF-8', 'am_et': 'am_ET.UTF-8', 'american': 'en_US.ISO8859-1', 'an_es': 'an_ES.ISO8859-15', + 'anp_in': 'anp_IN.UTF-8', 'ar': 'ar_AA.ISO8859-6', 'ar_aa': 'ar_AA.ISO8859-6', 'ar_ae': 'ar_AE.ISO8859-6', @@ -877,6 +890,7 @@ def getpreferredencoding(do_setlocale = True): 'ar_qa': 'ar_QA.ISO8859-6', 'ar_sa': 'ar_SA.ISO8859-6', 'ar_sd': 'ar_SD.ISO8859-6', + 'ar_ss': 'ar_SS.UTF-8', 'ar_sy': 'ar_SY.ISO8859-6', 'ar_tn': 'ar_TN.ISO8859-6', 'ar_ye': 'ar_YE.ISO8859-6', @@ -888,6 +902,7 @@ def getpreferredencoding(do_setlocale = True): 'az': 'az_AZ.ISO8859-9E', 'az_az': 'az_AZ.ISO8859-9E', 'az_az.iso88599e': 'az_AZ.ISO8859-9E', + 'az_ir': 'az_IR.UTF-8', 'be': 'be_BY.CP1251', 'be at latin': 'be_BY.UTF-8 at latin', 'be_bg.utf8': 'bg_BG.UTF-8', @@ -898,13 +913,17 @@ def getpreferredencoding(do_setlocale = True): 'ber_ma': 'ber_MA.UTF-8', 'bg': 'bg_BG.CP1251', 'bg_bg': 'bg_BG.CP1251', + 'bhb_in.utf8': 'bhb_IN.UTF-8', 'bho_in': 'bho_IN.UTF-8', + 'bho_np': 'bho_NP.UTF-8', + 'bi_vu': 'bi_VU.UTF-8', 'bn_bd': 'bn_BD.UTF-8', 'bn_in': 'bn_IN.UTF-8', 'bo_cn': 'bo_CN.UTF-8', 'bo_in': 'bo_IN.UTF-8', 'bokmal': 'nb_NO.ISO8859-1', 'bokm\xe5l': 'nb_NO.ISO8859-1', + 'bokm\xef\xbf\xbd': 'nb_NO.ISO8859-1', 'br': 'br_FR.ISO8859-1', 'br_fr': 'br_FR.ISO8859-1', 'brx_in': 'brx_IN.UTF-8', @@ -923,13 +942,17 @@ def getpreferredencoding(do_setlocale = True): 'ca': 'ca_ES.ISO8859-1', 'ca_ad': 'ca_AD.ISO8859-1', 'ca_es': 'ca_ES.ISO8859-1', - 'ca_es at valencia': 'ca_ES.ISO8859-15 at valencia', + 'ca_es at valencia': 'ca_ES.UTF-8 at valencia', 'ca_fr': 'ca_FR.ISO8859-1', 'ca_it': 'ca_IT.ISO8859-1', 'catalan': 'ca_ES.ISO8859-1', + 'ce_ru': 'ce_RU.UTF-8', 'cextend': 'en_US.ISO8859-1', 'chinese-s': 'zh_CN.eucCN', 'chinese-t': 'zh_TW.eucTW', + 'chr_us': 'chr_US.UTF-8', + 'ckb_iq': 'ckb_IQ.UTF-8', + 'cmn_tw': 'cmn_TW.UTF-8', 'crh_ua': 'crh_UA.UTF-8', 'croatian': 'hr_HR.ISO8859-2', 'cs': 'cs_CZ.ISO8859-2', @@ -951,6 +974,7 @@ def getpreferredencoding(do_setlocale = True): 'de_be': 'de_BE.ISO8859-1', 'de_ch': 'de_CH.ISO8859-1', 'de_de': 'de_DE.ISO8859-1', + 'de_it': 'de_IT.ISO8859-1', 'de_li.utf8': 'de_LI.UTF-8', 'de_lu': 'de_LU.ISO8859-1', 'deutsch': 'de_DE.ISO8859-1', @@ -977,10 +1001,12 @@ def getpreferredencoding(do_setlocale = True): 'en_gb': 'en_GB.ISO8859-1', 'en_hk': 'en_HK.ISO8859-1', 'en_ie': 'en_IE.ISO8859-1', + 'en_il': 'en_IL.UTF-8', 'en_in': 'en_IN.ISO8859-1', 'en_ng': 'en_NG.UTF-8', 'en_nz': 'en_NZ.ISO8859-1', 'en_ph': 'en_PH.ISO8859-1', + 'en_sc.utf8': 'en_SC.UTF-8', 'en_sg': 'en_SG.ISO8859-1', 'en_uk': 'en_GB.ISO8859-1', 'en_us': 'en_US.ISO8859-1', @@ -991,6 +1017,7 @@ def getpreferredencoding(do_setlocale = True): 'en_zw.utf8': 'en_ZS.UTF-8', 'eng_gb': 'en_GB.ISO8859-1', 'english': 'en_EN.ISO8859-1', + 'english.iso88591': 'en_US.ISO8859-1', 'english_uk': 'en_GB.ISO8859-1', 'english_united-states': 'en_US.ISO8859-1', 'english_united-states.437': 'C', @@ -1045,6 +1072,7 @@ def getpreferredencoding(do_setlocale = True): 'fr_fr': 'fr_FR.ISO8859-1', 'fr_lu': 'fr_LU.ISO8859-1', 'fran\xe7ais': 'fr_FR.ISO8859-1', + 'fran\xef\xbf\xbdis': 'fr_FR.ISO8859-1', 'fre_fr': 'fr_FR.ISO8859-1', 'french': 'fr_FR.ISO8859-1', 'french.iso88591': 'fr_CH.ISO8859-1', @@ -1071,12 +1099,14 @@ def getpreferredencoding(do_setlocale = True): 'gv': 'gv_GB.ISO8859-1', 'gv_gb': 'gv_GB.ISO8859-1', 'ha_ng': 'ha_NG.UTF-8', + 'hak_tw': 'hak_TW.UTF-8', 'he': 'he_IL.ISO8859-8', 'he_il': 'he_IL.ISO8859-8', 'hebrew': 'he_IL.ISO8859-8', 'hi': 'hi_IN.ISCII-DEV', 'hi_in': 'hi_IN.ISCII-DEV', 'hi_in.isciidev': 'hi_IN.ISCII-DEV', + 'hif_fj': 'hif_FJ.UTF-8', 'hne': 'hne_IN.UTF-8', 'hne_in': 'hne_IN.UTF-8', 'hr': 'hr_HR.ISO8859-2', @@ -1131,7 +1161,8 @@ def getpreferredencoding(do_setlocale = True): 'ka_ge.georgianacademy': 'ka_GE.GEORGIAN-ACADEMY', 'ka_ge.georgianps': 'ka_GE.GEORGIAN-PS', 'ka_ge.georgianrs': 'ka_GE.GEORGIAN-ACADEMY', - 'kk_kz': 'kk_KZ.RK1048', + 'kab_dz': 'kab_DZ.UTF-8', + 'kk_kz': 'kk_KZ.ptcp154', 'kl': 'kl_GL.ISO8859-1', 'kl_gl': 'kl_GL.ISO8859-1', 'km_kh': 'km_KH.UTF-8', @@ -1157,6 +1188,7 @@ def getpreferredencoding(do_setlocale = True): 'li_nl': 'li_NL.UTF-8', 'lij_it': 'lij_IT.UTF-8', 'lithuanian': 'lt_LT.ISO8859-13', + 'ln_cd': 'ln_CD.UTF-8', 'lo': 'lo_LA.MULELAO-1', 'lo_la': 'lo_LA.MULELAO-1', 'lo_la.cp1133': 'lo_LA.IBM-CP1133', @@ -1166,13 +1198,18 @@ def getpreferredencoding(do_setlocale = True): 'lt_lt': 'lt_LT.ISO8859-13', 'lv': 'lv_LV.ISO8859-13', 'lv_lv': 'lv_LV.ISO8859-13', + 'lzh_tw': 'lzh_TW.UTF-8', 'mag_in': 'mag_IN.UTF-8', 'mai': 'mai_IN.UTF-8', 'mai_in': 'mai_IN.UTF-8', + 'mai_np': 'mai_NP.UTF-8', + 'mfe_mu': 'mfe_MU.UTF-8', 'mg_mg': 'mg_MG.ISO8859-15', 'mhr_ru': 'mhr_RU.UTF-8', 'mi': 'mi_NZ.ISO8859-1', 'mi_nz': 'mi_NZ.ISO8859-1', + 'miq_ni': 'miq_NI.UTF-8', + 'mjw_in': 'mjw_IN.UTF-8', 'mk': 'mk_MK.ISO8859-5', 'mk_mk': 'mk_MK.ISO8859-5', 'ml': 'ml_IN.UTF-8', @@ -1186,7 +1223,7 @@ def getpreferredencoding(do_setlocale = True): 'mt': 'mt_MT.ISO8859-3', 'mt_mt': 'mt_MT.ISO8859-3', 'my_mm': 'my_MM.UTF-8', - 'nan_tw at latin': 'nan_TW.UTF-8 at latin', + 'nan_tw': 'nan_TW.UTF-8', 'nb': 'nb_NO.ISO8859-1', 'nb_no': 'nb_NO.ISO8859-1', 'nds_de': 'nds_DE.UTF-8', @@ -1225,6 +1262,8 @@ def getpreferredencoding(do_setlocale = True): 'pa_in': 'pa_IN.UTF-8', 'pa_pk': 'pa_PK.UTF-8', 'pap_an': 'pap_AN.UTF-8', + 'pap_aw': 'pap_AW.UTF-8', + 'pap_cw': 'pap_CW.UTF-8', 'pd': 'pd_US.ISO8859-1', 'pd_de': 'pd_DE.ISO8859-1', 'pd_us': 'pd_US.ISO8859-1', @@ -1243,6 +1282,8 @@ def getpreferredencoding(do_setlocale = True): 'pt': 'pt_PT.ISO8859-1', 'pt_br': 'pt_BR.ISO8859-1', 'pt_pt': 'pt_PT.ISO8859-1', + 'quz_pe': 'quz_PE.UTF-8', + 'raj_in': 'raj_IN.UTF-8', 'ro': 'ro_RO.ISO8859-2', 'ro_ro': 'ro_RO.ISO8859-2', 'romanian': 'ro_RO.ISO8859-2', @@ -1250,7 +1291,7 @@ def getpreferredencoding(do_setlocale = True): 'ru_ru': 'ru_RU.UTF-8', 'ru_ua': 'ru_UA.KOI8-U', 'rumanian': 'ro_RO.ISO8859-2', - 'russian': 'ru_RU.ISO8859-5', + 'russian': 'ru_RU.KOI8-R', 'rw': 'rw_RW.ISO8859-1', 'rw_rw': 'rw_RW.ISO8859-1', 'sa_in': 'sa_IN.UTF-8', @@ -1262,12 +1303,14 @@ def getpreferredencoding(do_setlocale = True): 'sd_pk': 'sd_PK.UTF-8', 'se_no': 'se_NO.UTF-8', 'serbocroatian': 'sr_RS.UTF-8 at latin', + 'sgs_lt': 'sgs_LT.UTF-8', 'sh': 'sr_RS.UTF-8 at latin', 'sh_ba.iso88592 at bosnia': 'sr_CS.ISO8859-2', 'sh_hr': 'sh_HR.ISO8859-2', 'sh_hr.iso88592': 'hr_HR.ISO8859-2', 'sh_sp': 'sr_CS.ISO8859-2', 'sh_yu': 'sr_RS.UTF-8 at latin', + 'shn_mm': 'shn_MM.UTF-8', 'shs_ca': 'shs_CA.UTF-8', 'si': 'si_LK.UTF-8', 'si_lk': 'si_LK.UTF-8', @@ -1281,6 +1324,7 @@ def getpreferredencoding(do_setlocale = True): 'slovak': 'sk_SK.ISO8859-2', 'slovene': 'sl_SI.ISO8859-2', 'slovenian': 'sl_SI.ISO8859-2', + 'sm_ws': 'sm_WS.UTF-8', 'so_dj': 'so_DJ.ISO8859-1', 'so_et': 'so_ET.UTF-8', 'so_ke': 'so_KE.ISO8859-1', @@ -1327,6 +1371,7 @@ def getpreferredencoding(do_setlocale = True): 'ta_in.tscii': 'ta_IN.TSCII-0', 'ta_in.tscii0': 'ta_IN.TSCII-0', 'ta_lk': 'ta_LK.UTF-8', + 'tcy_in.utf8': 'tcy_IN.UTF-8', 'te': 'te_IN.UTF-8', 'te_in': 'te_IN.UTF-8', 'tg': 'tg_TJ.KOI8-C', @@ -1336,6 +1381,7 @@ def getpreferredencoding(do_setlocale = True): 'th_th.tactis': 'th_TH.TIS620', 'th_th.tis620': 'th_TH.TIS620', 'thai': 'th_TH.ISO8859-11', + 'the_np': 'the_NP.UTF-8', 'ti_er': 'ti_ER.UTF-8', 'ti_et': 'ti_ET.UTF-8', 'tig_er': 'tig_ER.UTF-8', @@ -1344,6 +1390,8 @@ def getpreferredencoding(do_setlocale = True): 'tl_ph': 'tl_PH.ISO8859-1', 'tn': 'tn_ZA.ISO8859-15', 'tn_za': 'tn_ZA.ISO8859-15', + 'to_to': 'to_TO.UTF-8', + 'tpi_pg': 'tpi_PG.UTF-8', 'tr': 'tr_TR.ISO8859-9', 'tr_cy': 'tr_CY.ISO8859-9', 'tr_tr': 'tr_TR.ISO8859-9', @@ -1386,6 +1434,7 @@ def getpreferredencoding(do_setlocale = True): 'yi_us': 'yi_US.CP1255', 'yo_ng': 'yo_NG.UTF-8', 'yue_hk': 'yue_HK.UTF-8', + 'yuw_pg': 'yuw_PG.UTF-8', 'zh': 'zh_CN.eucCN', 'zh_cn': 'zh_CN.gb2312', 'zh_cn.big5': 'zh_TW.big5', diff --git a/Lib/test/test_locale.py b/Lib/test/test_locale.py index d93b3ad048be..e2c2178ae6cc 100644 --- a/Lib/test/test_locale.py +++ b/Lib/test/test_locale.py @@ -441,7 +441,7 @@ def test_latin_modifier(self): def test_valencia_modifier(self): self.check('ca_ES.UTF-8 at valencia', 'ca_ES.UTF-8 at valencia') - self.check('ca_ES at valencia', 'ca_ES.ISO8859-15 at valencia') + self.check('ca_ES at valencia', 'ca_ES.UTF-8 at valencia') self.check('ca at valencia', 'ca_ES.ISO8859-1 at valencia') def test_devanagari_modifier(self): diff --git a/Misc/NEWS.d/next/Library/2018-05-05-18-02-24.bpo-20087.lJrvXL.rst b/Misc/NEWS.d/next/Library/2018-05-05-18-02-24.bpo-20087.lJrvXL.rst new file mode 100644 index 000000000000..2342cb781926 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-05-18-02-24.bpo-20087.lJrvXL.rst @@ -0,0 +1 @@ +Updated alias mapping with glibc 2.27 supported locales. From webhook-mailer at python.org Sun May 6 03:20:16 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sun, 06 May 2018 07:20:16 -0000 Subject: [Python-checkins] [3.7] bpo-20087: Update locale alias mapping with glibc 2.27 supported locales. (GH-6708) (GH-6713) Message-ID: https://github.com/python/cpython/commit/6049bda21b607acc90bbabcc604997e794e8aee1 commit: 6049bda21b607acc90bbabcc604997e794e8aee1 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Serhiy Storchaka date: 2018-05-06T10:20:12+03:00 summary: [3.7] bpo-20087: Update locale alias mapping with glibc 2.27 supported locales. (GH-6708) (GH-6713) (cherry picked from commit cedc9b74202d8c1ae39bca261cbb45d42ed54d45) Co-authored-by: Serhiy Storchaka files: A Misc/NEWS.d/next/Library/2018-05-05-18-02-24.bpo-20087.lJrvXL.rst M Lib/locale.py M Lib/test/test_locale.py diff --git a/Lib/locale.py b/Lib/locale.py index 18079e73ad69..f3d3973d038c 100644 --- a/Lib/locale.py +++ b/Lib/locale.py @@ -846,6 +846,16 @@ def getpreferredencoding(do_setlocale = True): # # SS 2014-10-01: # Updated alias mapping with glibc 2.19 supported locales. +# +# SS 2018-05-05: +# Updated alias mapping with glibc 2.27 supported locales. +# +# These are the differences compared to the old mapping (Python 3.6.5 +# and older): +# +# updated 'ca_es at valencia' -> 'ca_ES.ISO8859-15 at valencia' to 'ca_ES.UTF-8 at valencia' +# updated 'kk_kz' -> 'kk_KZ.RK1048' to 'kk_KZ.ptcp154' +# updated 'russian' -> 'ru_RU.ISO8859-5' to 'ru_RU.KOI8-R' locale_alias = { 'a3': 'az_AZ.KOI8-C', @@ -856,10 +866,13 @@ def getpreferredencoding(do_setlocale = True): 'aa_et': 'aa_ET.UTF-8', 'af': 'af_ZA.ISO8859-1', 'af_za': 'af_ZA.ISO8859-1', + 'agr_pe': 'agr_PE.UTF-8', + 'ak_gh': 'ak_GH.UTF-8', 'am': 'am_ET.UTF-8', 'am_et': 'am_ET.UTF-8', 'american': 'en_US.ISO8859-1', 'an_es': 'an_ES.ISO8859-15', + 'anp_in': 'anp_IN.UTF-8', 'ar': 'ar_AA.ISO8859-6', 'ar_aa': 'ar_AA.ISO8859-6', 'ar_ae': 'ar_AE.ISO8859-6', @@ -877,6 +890,7 @@ def getpreferredencoding(do_setlocale = True): 'ar_qa': 'ar_QA.ISO8859-6', 'ar_sa': 'ar_SA.ISO8859-6', 'ar_sd': 'ar_SD.ISO8859-6', + 'ar_ss': 'ar_SS.UTF-8', 'ar_sy': 'ar_SY.ISO8859-6', 'ar_tn': 'ar_TN.ISO8859-6', 'ar_ye': 'ar_YE.ISO8859-6', @@ -888,6 +902,7 @@ def getpreferredencoding(do_setlocale = True): 'az': 'az_AZ.ISO8859-9E', 'az_az': 'az_AZ.ISO8859-9E', 'az_az.iso88599e': 'az_AZ.ISO8859-9E', + 'az_ir': 'az_IR.UTF-8', 'be': 'be_BY.CP1251', 'be at latin': 'be_BY.UTF-8 at latin', 'be_bg.utf8': 'bg_BG.UTF-8', @@ -898,7 +913,10 @@ def getpreferredencoding(do_setlocale = True): 'ber_ma': 'ber_MA.UTF-8', 'bg': 'bg_BG.CP1251', 'bg_bg': 'bg_BG.CP1251', + 'bhb_in.utf8': 'bhb_IN.UTF-8', 'bho_in': 'bho_IN.UTF-8', + 'bho_np': 'bho_NP.UTF-8', + 'bi_vu': 'bi_VU.UTF-8', 'bn_bd': 'bn_BD.UTF-8', 'bn_in': 'bn_IN.UTF-8', 'bo_cn': 'bo_CN.UTF-8', @@ -923,13 +941,17 @@ def getpreferredencoding(do_setlocale = True): 'ca': 'ca_ES.ISO8859-1', 'ca_ad': 'ca_AD.ISO8859-1', 'ca_es': 'ca_ES.ISO8859-1', - 'ca_es at valencia': 'ca_ES.ISO8859-15 at valencia', + 'ca_es at valencia': 'ca_ES.UTF-8 at valencia', 'ca_fr': 'ca_FR.ISO8859-1', 'ca_it': 'ca_IT.ISO8859-1', 'catalan': 'ca_ES.ISO8859-1', + 'ce_ru': 'ce_RU.UTF-8', 'cextend': 'en_US.ISO8859-1', 'chinese-s': 'zh_CN.eucCN', 'chinese-t': 'zh_TW.eucTW', + 'chr_us': 'chr_US.UTF-8', + 'ckb_iq': 'ckb_IQ.UTF-8', + 'cmn_tw': 'cmn_TW.UTF-8', 'crh_ua': 'crh_UA.UTF-8', 'croatian': 'hr_HR.ISO8859-2', 'cs': 'cs_CZ.ISO8859-2', @@ -951,6 +973,7 @@ def getpreferredencoding(do_setlocale = True): 'de_be': 'de_BE.ISO8859-1', 'de_ch': 'de_CH.ISO8859-1', 'de_de': 'de_DE.ISO8859-1', + 'de_it': 'de_IT.ISO8859-1', 'de_li.utf8': 'de_LI.UTF-8', 'de_lu': 'de_LU.ISO8859-1', 'deutsch': 'de_DE.ISO8859-1', @@ -977,10 +1000,12 @@ def getpreferredencoding(do_setlocale = True): 'en_gb': 'en_GB.ISO8859-1', 'en_hk': 'en_HK.ISO8859-1', 'en_ie': 'en_IE.ISO8859-1', + 'en_il': 'en_IL.UTF-8', 'en_in': 'en_IN.ISO8859-1', 'en_ng': 'en_NG.UTF-8', 'en_nz': 'en_NZ.ISO8859-1', 'en_ph': 'en_PH.ISO8859-1', + 'en_sc.utf8': 'en_SC.UTF-8', 'en_sg': 'en_SG.ISO8859-1', 'en_uk': 'en_GB.ISO8859-1', 'en_us': 'en_US.ISO8859-1', @@ -991,6 +1016,7 @@ def getpreferredencoding(do_setlocale = True): 'en_zw.utf8': 'en_ZS.UTF-8', 'eng_gb': 'en_GB.ISO8859-1', 'english': 'en_EN.ISO8859-1', + 'english.iso88591': 'en_US.ISO8859-1', 'english_uk': 'en_GB.ISO8859-1', 'english_united-states': 'en_US.ISO8859-1', 'english_united-states.437': 'C', @@ -1071,12 +1097,14 @@ def getpreferredencoding(do_setlocale = True): 'gv': 'gv_GB.ISO8859-1', 'gv_gb': 'gv_GB.ISO8859-1', 'ha_ng': 'ha_NG.UTF-8', + 'hak_tw': 'hak_TW.UTF-8', 'he': 'he_IL.ISO8859-8', 'he_il': 'he_IL.ISO8859-8', 'hebrew': 'he_IL.ISO8859-8', 'hi': 'hi_IN.ISCII-DEV', 'hi_in': 'hi_IN.ISCII-DEV', 'hi_in.isciidev': 'hi_IN.ISCII-DEV', + 'hif_fj': 'hif_FJ.UTF-8', 'hne': 'hne_IN.UTF-8', 'hne_in': 'hne_IN.UTF-8', 'hr': 'hr_HR.ISO8859-2', @@ -1131,7 +1159,8 @@ def getpreferredencoding(do_setlocale = True): 'ka_ge.georgianacademy': 'ka_GE.GEORGIAN-ACADEMY', 'ka_ge.georgianps': 'ka_GE.GEORGIAN-PS', 'ka_ge.georgianrs': 'ka_GE.GEORGIAN-ACADEMY', - 'kk_kz': 'kk_KZ.RK1048', + 'kab_dz': 'kab_DZ.UTF-8', + 'kk_kz': 'kk_KZ.ptcp154', 'kl': 'kl_GL.ISO8859-1', 'kl_gl': 'kl_GL.ISO8859-1', 'km_kh': 'km_KH.UTF-8', @@ -1157,6 +1186,7 @@ def getpreferredencoding(do_setlocale = True): 'li_nl': 'li_NL.UTF-8', 'lij_it': 'lij_IT.UTF-8', 'lithuanian': 'lt_LT.ISO8859-13', + 'ln_cd': 'ln_CD.UTF-8', 'lo': 'lo_LA.MULELAO-1', 'lo_la': 'lo_LA.MULELAO-1', 'lo_la.cp1133': 'lo_LA.IBM-CP1133', @@ -1166,13 +1196,18 @@ def getpreferredencoding(do_setlocale = True): 'lt_lt': 'lt_LT.ISO8859-13', 'lv': 'lv_LV.ISO8859-13', 'lv_lv': 'lv_LV.ISO8859-13', + 'lzh_tw': 'lzh_TW.UTF-8', 'mag_in': 'mag_IN.UTF-8', 'mai': 'mai_IN.UTF-8', 'mai_in': 'mai_IN.UTF-8', + 'mai_np': 'mai_NP.UTF-8', + 'mfe_mu': 'mfe_MU.UTF-8', 'mg_mg': 'mg_MG.ISO8859-15', 'mhr_ru': 'mhr_RU.UTF-8', 'mi': 'mi_NZ.ISO8859-1', 'mi_nz': 'mi_NZ.ISO8859-1', + 'miq_ni': 'miq_NI.UTF-8', + 'mjw_in': 'mjw_IN.UTF-8', 'mk': 'mk_MK.ISO8859-5', 'mk_mk': 'mk_MK.ISO8859-5', 'ml': 'ml_IN.UTF-8', @@ -1186,7 +1221,7 @@ def getpreferredencoding(do_setlocale = True): 'mt': 'mt_MT.ISO8859-3', 'mt_mt': 'mt_MT.ISO8859-3', 'my_mm': 'my_MM.UTF-8', - 'nan_tw at latin': 'nan_TW.UTF-8 at latin', + 'nan_tw': 'nan_TW.UTF-8', 'nb': 'nb_NO.ISO8859-1', 'nb_no': 'nb_NO.ISO8859-1', 'nds_de': 'nds_DE.UTF-8', @@ -1225,6 +1260,8 @@ def getpreferredencoding(do_setlocale = True): 'pa_in': 'pa_IN.UTF-8', 'pa_pk': 'pa_PK.UTF-8', 'pap_an': 'pap_AN.UTF-8', + 'pap_aw': 'pap_AW.UTF-8', + 'pap_cw': 'pap_CW.UTF-8', 'pd': 'pd_US.ISO8859-1', 'pd_de': 'pd_DE.ISO8859-1', 'pd_us': 'pd_US.ISO8859-1', @@ -1243,6 +1280,8 @@ def getpreferredencoding(do_setlocale = True): 'pt': 'pt_PT.ISO8859-1', 'pt_br': 'pt_BR.ISO8859-1', 'pt_pt': 'pt_PT.ISO8859-1', + 'quz_pe': 'quz_PE.UTF-8', + 'raj_in': 'raj_IN.UTF-8', 'ro': 'ro_RO.ISO8859-2', 'ro_ro': 'ro_RO.ISO8859-2', 'romanian': 'ro_RO.ISO8859-2', @@ -1250,7 +1289,7 @@ def getpreferredencoding(do_setlocale = True): 'ru_ru': 'ru_RU.UTF-8', 'ru_ua': 'ru_UA.KOI8-U', 'rumanian': 'ro_RO.ISO8859-2', - 'russian': 'ru_RU.ISO8859-5', + 'russian': 'ru_RU.KOI8-R', 'rw': 'rw_RW.ISO8859-1', 'rw_rw': 'rw_RW.ISO8859-1', 'sa_in': 'sa_IN.UTF-8', @@ -1262,12 +1301,14 @@ def getpreferredencoding(do_setlocale = True): 'sd_pk': 'sd_PK.UTF-8', 'se_no': 'se_NO.UTF-8', 'serbocroatian': 'sr_RS.UTF-8 at latin', + 'sgs_lt': 'sgs_LT.UTF-8', 'sh': 'sr_RS.UTF-8 at latin', 'sh_ba.iso88592 at bosnia': 'sr_CS.ISO8859-2', 'sh_hr': 'sh_HR.ISO8859-2', 'sh_hr.iso88592': 'hr_HR.ISO8859-2', 'sh_sp': 'sr_CS.ISO8859-2', 'sh_yu': 'sr_RS.UTF-8 at latin', + 'shn_mm': 'shn_MM.UTF-8', 'shs_ca': 'shs_CA.UTF-8', 'si': 'si_LK.UTF-8', 'si_lk': 'si_LK.UTF-8', @@ -1281,6 +1322,7 @@ def getpreferredencoding(do_setlocale = True): 'slovak': 'sk_SK.ISO8859-2', 'slovene': 'sl_SI.ISO8859-2', 'slovenian': 'sl_SI.ISO8859-2', + 'sm_ws': 'sm_WS.UTF-8', 'so_dj': 'so_DJ.ISO8859-1', 'so_et': 'so_ET.UTF-8', 'so_ke': 'so_KE.ISO8859-1', @@ -1327,6 +1369,7 @@ def getpreferredencoding(do_setlocale = True): 'ta_in.tscii': 'ta_IN.TSCII-0', 'ta_in.tscii0': 'ta_IN.TSCII-0', 'ta_lk': 'ta_LK.UTF-8', + 'tcy_in.utf8': 'tcy_IN.UTF-8', 'te': 'te_IN.UTF-8', 'te_in': 'te_IN.UTF-8', 'tg': 'tg_TJ.KOI8-C', @@ -1336,6 +1379,7 @@ def getpreferredencoding(do_setlocale = True): 'th_th.tactis': 'th_TH.TIS620', 'th_th.tis620': 'th_TH.TIS620', 'thai': 'th_TH.ISO8859-11', + 'the_np': 'the_NP.UTF-8', 'ti_er': 'ti_ER.UTF-8', 'ti_et': 'ti_ET.UTF-8', 'tig_er': 'tig_ER.UTF-8', @@ -1344,6 +1388,8 @@ def getpreferredencoding(do_setlocale = True): 'tl_ph': 'tl_PH.ISO8859-1', 'tn': 'tn_ZA.ISO8859-15', 'tn_za': 'tn_ZA.ISO8859-15', + 'to_to': 'to_TO.UTF-8', + 'tpi_pg': 'tpi_PG.UTF-8', 'tr': 'tr_TR.ISO8859-9', 'tr_cy': 'tr_CY.ISO8859-9', 'tr_tr': 'tr_TR.ISO8859-9', @@ -1386,6 +1432,7 @@ def getpreferredencoding(do_setlocale = True): 'yi_us': 'yi_US.CP1255', 'yo_ng': 'yo_NG.UTF-8', 'yue_hk': 'yue_HK.UTF-8', + 'yuw_pg': 'yuw_PG.UTF-8', 'zh': 'zh_CN.eucCN', 'zh_cn': 'zh_CN.gb2312', 'zh_cn.big5': 'zh_TW.big5', diff --git a/Lib/test/test_locale.py b/Lib/test/test_locale.py index d93b3ad048be..e2c2178ae6cc 100644 --- a/Lib/test/test_locale.py +++ b/Lib/test/test_locale.py @@ -441,7 +441,7 @@ def test_latin_modifier(self): def test_valencia_modifier(self): self.check('ca_ES.UTF-8 at valencia', 'ca_ES.UTF-8 at valencia') - self.check('ca_ES at valencia', 'ca_ES.ISO8859-15 at valencia') + self.check('ca_ES at valencia', 'ca_ES.UTF-8 at valencia') self.check('ca at valencia', 'ca_ES.ISO8859-1 at valencia') def test_devanagari_modifier(self): diff --git a/Misc/NEWS.d/next/Library/2018-05-05-18-02-24.bpo-20087.lJrvXL.rst b/Misc/NEWS.d/next/Library/2018-05-05-18-02-24.bpo-20087.lJrvXL.rst new file mode 100644 index 000000000000..2342cb781926 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-05-18-02-24.bpo-20087.lJrvXL.rst @@ -0,0 +1 @@ +Updated alias mapping with glibc 2.27 supported locales. From webhook-mailer at python.org Sun May 6 03:20:44 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sun, 06 May 2018 07:20:44 -0000 Subject: [Python-checkins] [3.6] bpo-20087: Update locale alias mapping with glibc 2.27 supported locales. (GH-6708) (GH-6714) Message-ID: https://github.com/python/cpython/commit/b1c70d0ffbb235def1deab62a744ffd9b5253924 commit: b1c70d0ffbb235def1deab62a744ffd9b5253924 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Serhiy Storchaka date: 2018-05-06T10:20:42+03:00 summary: [3.6] bpo-20087: Update locale alias mapping with glibc 2.27 supported locales. (GH-6708) (GH-6714) (cherry picked from commit cedc9b74202d8c1ae39bca261cbb45d42ed54d45) Co-authored-by: Serhiy Storchaka files: A Misc/NEWS.d/next/Library/2018-05-05-18-02-24.bpo-20087.lJrvXL.rst M Lib/locale.py M Lib/test/test_locale.py diff --git a/Lib/locale.py b/Lib/locale.py index 4de0090ed9dd..e85f34ea1996 100644 --- a/Lib/locale.py +++ b/Lib/locale.py @@ -828,6 +828,16 @@ def getpreferredencoding(do_setlocale = True): # # SS 2014-10-01: # Updated alias mapping with glibc 2.19 supported locales. +# +# SS 2018-05-05: +# Updated alias mapping with glibc 2.27 supported locales. +# +# These are the differences compared to the old mapping (Python 3.6.5 +# and older): +# +# updated 'ca_es at valencia' -> 'ca_ES.ISO8859-15 at valencia' to 'ca_ES.UTF-8 at valencia' +# updated 'kk_kz' -> 'kk_KZ.RK1048' to 'kk_KZ.ptcp154' +# updated 'russian' -> 'ru_RU.ISO8859-5' to 'ru_RU.KOI8-R' locale_alias = { 'a3': 'az_AZ.KOI8-C', @@ -838,10 +848,13 @@ def getpreferredencoding(do_setlocale = True): 'aa_et': 'aa_ET.UTF-8', 'af': 'af_ZA.ISO8859-1', 'af_za': 'af_ZA.ISO8859-1', + 'agr_pe': 'agr_PE.UTF-8', + 'ak_gh': 'ak_GH.UTF-8', 'am': 'am_ET.UTF-8', 'am_et': 'am_ET.UTF-8', 'american': 'en_US.ISO8859-1', 'an_es': 'an_ES.ISO8859-15', + 'anp_in': 'anp_IN.UTF-8', 'ar': 'ar_AA.ISO8859-6', 'ar_aa': 'ar_AA.ISO8859-6', 'ar_ae': 'ar_AE.ISO8859-6', @@ -859,6 +872,7 @@ def getpreferredencoding(do_setlocale = True): 'ar_qa': 'ar_QA.ISO8859-6', 'ar_sa': 'ar_SA.ISO8859-6', 'ar_sd': 'ar_SD.ISO8859-6', + 'ar_ss': 'ar_SS.UTF-8', 'ar_sy': 'ar_SY.ISO8859-6', 'ar_tn': 'ar_TN.ISO8859-6', 'ar_ye': 'ar_YE.ISO8859-6', @@ -870,6 +884,7 @@ def getpreferredencoding(do_setlocale = True): 'az': 'az_AZ.ISO8859-9E', 'az_az': 'az_AZ.ISO8859-9E', 'az_az.iso88599e': 'az_AZ.ISO8859-9E', + 'az_ir': 'az_IR.UTF-8', 'be': 'be_BY.CP1251', 'be at latin': 'be_BY.UTF-8 at latin', 'be_bg.utf8': 'bg_BG.UTF-8', @@ -880,7 +895,10 @@ def getpreferredencoding(do_setlocale = True): 'ber_ma': 'ber_MA.UTF-8', 'bg': 'bg_BG.CP1251', 'bg_bg': 'bg_BG.CP1251', + 'bhb_in.utf8': 'bhb_IN.UTF-8', 'bho_in': 'bho_IN.UTF-8', + 'bho_np': 'bho_NP.UTF-8', + 'bi_vu': 'bi_VU.UTF-8', 'bn_bd': 'bn_BD.UTF-8', 'bn_in': 'bn_IN.UTF-8', 'bo_cn': 'bo_CN.UTF-8', @@ -905,13 +923,17 @@ def getpreferredencoding(do_setlocale = True): 'ca': 'ca_ES.ISO8859-1', 'ca_ad': 'ca_AD.ISO8859-1', 'ca_es': 'ca_ES.ISO8859-1', - 'ca_es at valencia': 'ca_ES.ISO8859-15 at valencia', + 'ca_es at valencia': 'ca_ES.UTF-8 at valencia', 'ca_fr': 'ca_FR.ISO8859-1', 'ca_it': 'ca_IT.ISO8859-1', 'catalan': 'ca_ES.ISO8859-1', + 'ce_ru': 'ce_RU.UTF-8', 'cextend': 'en_US.ISO8859-1', 'chinese-s': 'zh_CN.eucCN', 'chinese-t': 'zh_TW.eucTW', + 'chr_us': 'chr_US.UTF-8', + 'ckb_iq': 'ckb_IQ.UTF-8', + 'cmn_tw': 'cmn_TW.UTF-8', 'crh_ua': 'crh_UA.UTF-8', 'croatian': 'hr_HR.ISO8859-2', 'cs': 'cs_CZ.ISO8859-2', @@ -933,6 +955,7 @@ def getpreferredencoding(do_setlocale = True): 'de_be': 'de_BE.ISO8859-1', 'de_ch': 'de_CH.ISO8859-1', 'de_de': 'de_DE.ISO8859-1', + 'de_it': 'de_IT.ISO8859-1', 'de_li.utf8': 'de_LI.UTF-8', 'de_lu': 'de_LU.ISO8859-1', 'deutsch': 'de_DE.ISO8859-1', @@ -959,10 +982,12 @@ def getpreferredencoding(do_setlocale = True): 'en_gb': 'en_GB.ISO8859-1', 'en_hk': 'en_HK.ISO8859-1', 'en_ie': 'en_IE.ISO8859-1', + 'en_il': 'en_IL.UTF-8', 'en_in': 'en_IN.ISO8859-1', 'en_ng': 'en_NG.UTF-8', 'en_nz': 'en_NZ.ISO8859-1', 'en_ph': 'en_PH.ISO8859-1', + 'en_sc.utf8': 'en_SC.UTF-8', 'en_sg': 'en_SG.ISO8859-1', 'en_uk': 'en_GB.ISO8859-1', 'en_us': 'en_US.ISO8859-1', @@ -973,6 +998,7 @@ def getpreferredencoding(do_setlocale = True): 'en_zw.utf8': 'en_ZS.UTF-8', 'eng_gb': 'en_GB.ISO8859-1', 'english': 'en_EN.ISO8859-1', + 'english.iso88591': 'en_US.ISO8859-1', 'english_uk': 'en_GB.ISO8859-1', 'english_united-states': 'en_US.ISO8859-1', 'english_united-states.437': 'C', @@ -1053,12 +1079,14 @@ def getpreferredencoding(do_setlocale = True): 'gv': 'gv_GB.ISO8859-1', 'gv_gb': 'gv_GB.ISO8859-1', 'ha_ng': 'ha_NG.UTF-8', + 'hak_tw': 'hak_TW.UTF-8', 'he': 'he_IL.ISO8859-8', 'he_il': 'he_IL.ISO8859-8', 'hebrew': 'he_IL.ISO8859-8', 'hi': 'hi_IN.ISCII-DEV', 'hi_in': 'hi_IN.ISCII-DEV', 'hi_in.isciidev': 'hi_IN.ISCII-DEV', + 'hif_fj': 'hif_FJ.UTF-8', 'hne': 'hne_IN.UTF-8', 'hne_in': 'hne_IN.UTF-8', 'hr': 'hr_HR.ISO8859-2', @@ -1113,7 +1141,8 @@ def getpreferredencoding(do_setlocale = True): 'ka_ge.georgianacademy': 'ka_GE.GEORGIAN-ACADEMY', 'ka_ge.georgianps': 'ka_GE.GEORGIAN-PS', 'ka_ge.georgianrs': 'ka_GE.GEORGIAN-ACADEMY', - 'kk_kz': 'kk_KZ.RK1048', + 'kab_dz': 'kab_DZ.UTF-8', + 'kk_kz': 'kk_KZ.ptcp154', 'kl': 'kl_GL.ISO8859-1', 'kl_gl': 'kl_GL.ISO8859-1', 'km_kh': 'km_KH.UTF-8', @@ -1139,6 +1168,7 @@ def getpreferredencoding(do_setlocale = True): 'li_nl': 'li_NL.UTF-8', 'lij_it': 'lij_IT.UTF-8', 'lithuanian': 'lt_LT.ISO8859-13', + 'ln_cd': 'ln_CD.UTF-8', 'lo': 'lo_LA.MULELAO-1', 'lo_la': 'lo_LA.MULELAO-1', 'lo_la.cp1133': 'lo_LA.IBM-CP1133', @@ -1148,13 +1178,18 @@ def getpreferredencoding(do_setlocale = True): 'lt_lt': 'lt_LT.ISO8859-13', 'lv': 'lv_LV.ISO8859-13', 'lv_lv': 'lv_LV.ISO8859-13', + 'lzh_tw': 'lzh_TW.UTF-8', 'mag_in': 'mag_IN.UTF-8', 'mai': 'mai_IN.UTF-8', 'mai_in': 'mai_IN.UTF-8', + 'mai_np': 'mai_NP.UTF-8', + 'mfe_mu': 'mfe_MU.UTF-8', 'mg_mg': 'mg_MG.ISO8859-15', 'mhr_ru': 'mhr_RU.UTF-8', 'mi': 'mi_NZ.ISO8859-1', 'mi_nz': 'mi_NZ.ISO8859-1', + 'miq_ni': 'miq_NI.UTF-8', + 'mjw_in': 'mjw_IN.UTF-8', 'mk': 'mk_MK.ISO8859-5', 'mk_mk': 'mk_MK.ISO8859-5', 'ml': 'ml_IN.UTF-8', @@ -1168,7 +1203,7 @@ def getpreferredencoding(do_setlocale = True): 'mt': 'mt_MT.ISO8859-3', 'mt_mt': 'mt_MT.ISO8859-3', 'my_mm': 'my_MM.UTF-8', - 'nan_tw at latin': 'nan_TW.UTF-8 at latin', + 'nan_tw': 'nan_TW.UTF-8', 'nb': 'nb_NO.ISO8859-1', 'nb_no': 'nb_NO.ISO8859-1', 'nds_de': 'nds_DE.UTF-8', @@ -1207,6 +1242,8 @@ def getpreferredencoding(do_setlocale = True): 'pa_in': 'pa_IN.UTF-8', 'pa_pk': 'pa_PK.UTF-8', 'pap_an': 'pap_AN.UTF-8', + 'pap_aw': 'pap_AW.UTF-8', + 'pap_cw': 'pap_CW.UTF-8', 'pd': 'pd_US.ISO8859-1', 'pd_de': 'pd_DE.ISO8859-1', 'pd_us': 'pd_US.ISO8859-1', @@ -1225,6 +1262,8 @@ def getpreferredencoding(do_setlocale = True): 'pt': 'pt_PT.ISO8859-1', 'pt_br': 'pt_BR.ISO8859-1', 'pt_pt': 'pt_PT.ISO8859-1', + 'quz_pe': 'quz_PE.UTF-8', + 'raj_in': 'raj_IN.UTF-8', 'ro': 'ro_RO.ISO8859-2', 'ro_ro': 'ro_RO.ISO8859-2', 'romanian': 'ro_RO.ISO8859-2', @@ -1232,7 +1271,7 @@ def getpreferredencoding(do_setlocale = True): 'ru_ru': 'ru_RU.UTF-8', 'ru_ua': 'ru_UA.KOI8-U', 'rumanian': 'ro_RO.ISO8859-2', - 'russian': 'ru_RU.ISO8859-5', + 'russian': 'ru_RU.KOI8-R', 'rw': 'rw_RW.ISO8859-1', 'rw_rw': 'rw_RW.ISO8859-1', 'sa_in': 'sa_IN.UTF-8', @@ -1244,12 +1283,14 @@ def getpreferredencoding(do_setlocale = True): 'sd_pk': 'sd_PK.UTF-8', 'se_no': 'se_NO.UTF-8', 'serbocroatian': 'sr_RS.UTF-8 at latin', + 'sgs_lt': 'sgs_LT.UTF-8', 'sh': 'sr_RS.UTF-8 at latin', 'sh_ba.iso88592 at bosnia': 'sr_CS.ISO8859-2', 'sh_hr': 'sh_HR.ISO8859-2', 'sh_hr.iso88592': 'hr_HR.ISO8859-2', 'sh_sp': 'sr_CS.ISO8859-2', 'sh_yu': 'sr_RS.UTF-8 at latin', + 'shn_mm': 'shn_MM.UTF-8', 'shs_ca': 'shs_CA.UTF-8', 'si': 'si_LK.UTF-8', 'si_lk': 'si_LK.UTF-8', @@ -1263,6 +1304,7 @@ def getpreferredencoding(do_setlocale = True): 'slovak': 'sk_SK.ISO8859-2', 'slovene': 'sl_SI.ISO8859-2', 'slovenian': 'sl_SI.ISO8859-2', + 'sm_ws': 'sm_WS.UTF-8', 'so_dj': 'so_DJ.ISO8859-1', 'so_et': 'so_ET.UTF-8', 'so_ke': 'so_KE.ISO8859-1', @@ -1309,6 +1351,7 @@ def getpreferredencoding(do_setlocale = True): 'ta_in.tscii': 'ta_IN.TSCII-0', 'ta_in.tscii0': 'ta_IN.TSCII-0', 'ta_lk': 'ta_LK.UTF-8', + 'tcy_in.utf8': 'tcy_IN.UTF-8', 'te': 'te_IN.UTF-8', 'te_in': 'te_IN.UTF-8', 'tg': 'tg_TJ.KOI8-C', @@ -1318,6 +1361,7 @@ def getpreferredencoding(do_setlocale = True): 'th_th.tactis': 'th_TH.TIS620', 'th_th.tis620': 'th_TH.TIS620', 'thai': 'th_TH.ISO8859-11', + 'the_np': 'the_NP.UTF-8', 'ti_er': 'ti_ER.UTF-8', 'ti_et': 'ti_ET.UTF-8', 'tig_er': 'tig_ER.UTF-8', @@ -1326,6 +1370,8 @@ def getpreferredencoding(do_setlocale = True): 'tl_ph': 'tl_PH.ISO8859-1', 'tn': 'tn_ZA.ISO8859-15', 'tn_za': 'tn_ZA.ISO8859-15', + 'to_to': 'to_TO.UTF-8', + 'tpi_pg': 'tpi_PG.UTF-8', 'tr': 'tr_TR.ISO8859-9', 'tr_cy': 'tr_CY.ISO8859-9', 'tr_tr': 'tr_TR.ISO8859-9', @@ -1368,6 +1414,7 @@ def getpreferredencoding(do_setlocale = True): 'yi_us': 'yi_US.CP1255', 'yo_ng': 'yo_NG.UTF-8', 'yue_hk': 'yue_HK.UTF-8', + 'yuw_pg': 'yuw_PG.UTF-8', 'zh': 'zh_CN.eucCN', 'zh_cn': 'zh_CN.gb2312', 'zh_cn.big5': 'zh_TW.big5', diff --git a/Lib/test/test_locale.py b/Lib/test/test_locale.py index 650d7373d8e1..a5ec2c51c55d 100644 --- a/Lib/test/test_locale.py +++ b/Lib/test/test_locale.py @@ -430,7 +430,7 @@ def test_latin_modifier(self): def test_valencia_modifier(self): self.check('ca_ES.UTF-8 at valencia', 'ca_ES.UTF-8 at valencia') - self.check('ca_ES at valencia', 'ca_ES.ISO8859-15 at valencia') + self.check('ca_ES at valencia', 'ca_ES.UTF-8 at valencia') self.check('ca at valencia', 'ca_ES.ISO8859-1 at valencia') def test_devanagari_modifier(self): diff --git a/Misc/NEWS.d/next/Library/2018-05-05-18-02-24.bpo-20087.lJrvXL.rst b/Misc/NEWS.d/next/Library/2018-05-05-18-02-24.bpo-20087.lJrvXL.rst new file mode 100644 index 000000000000..2342cb781926 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-05-18-02-24.bpo-20087.lJrvXL.rst @@ -0,0 +1 @@ +Updated alias mapping with glibc 2.27 supported locales. From webhook-mailer at python.org Sun May 6 03:51:52 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sun, 06 May 2018 07:51:52 -0000 Subject: [Python-checkins] [2.7] bpo-20087: Update locale alias mapping with glibc 2.27 supported locales. (GH-6708). (GH-6717) Message-ID: https://github.com/python/cpython/commit/a55ac801f749a731250f3c7c1db7d546d22ae032 commit: a55ac801f749a731250f3c7c1db7d546d22ae032 branch: 2.7 author: Serhiy Storchaka committer: GitHub date: 2018-05-06T10:51:49+03:00 summary: [2.7] bpo-20087: Update locale alias mapping with glibc 2.27 supported locales. (GH-6708). (GH-6717) (cherry picked from commit cedc9b74202d8c1ae39bca261cbb45d42ed54d45) files: A Misc/NEWS.d/next/Library/2018-05-05-18-02-24.bpo-20087.lJrvXL.rst M Lib/locale.py M Lib/test/test_locale.py diff --git a/Lib/locale.py b/Lib/locale.py index 62aad5ae7bf9..51909f81e734 100644 --- a/Lib/locale.py +++ b/Lib/locale.py @@ -798,6 +798,17 @@ def getpreferredencoding(do_setlocale = True): # # SS 2014-10-01: # Updated alias mapping with glibc 2.19 supported locales. +# +# SS 2018-05-05: +# Updated alias mapping with glibc 2.27 supported locales. +# +# These are the differences compared to the old mapping (Python 2.7.15 +# and older): +# +# updated 'ca_es at valencia' -> 'ca_ES.ISO8859-15 at valencia' to 'ca_ES.UTF-8 at valencia' +# updated 'english.iso88591' -> 'en_EN.ISO8859-1' to 'en_US.ISO8859-1' +# updated 'kk_kz' -> 'kk_KZ.RK1048' to 'kk_KZ.ptcp154' +# updated 'russian' -> 'ru_RU.ISO8859-5' to 'ru_RU.KOI8-R' locale_alias = { 'a3': 'az_AZ.KOI8-C', @@ -810,11 +821,14 @@ def getpreferredencoding(do_setlocale = True): 'af': 'af_ZA.ISO8859-1', 'af_za': 'af_ZA.ISO8859-1', 'af_za.iso88591': 'af_ZA.ISO8859-1', + 'agr_pe': 'agr_PE.UTF-8', + 'ak_gh': 'ak_GH.UTF-8', 'am': 'am_ET.UTF-8', 'am_et': 'am_ET.UTF-8', 'american': 'en_US.ISO8859-1', 'american.iso88591': 'en_US.ISO8859-1', 'an_es': 'an_ES.ISO8859-15', + 'anp_in': 'anp_IN.UTF-8', 'ar': 'ar_AA.ISO8859-6', 'ar_aa': 'ar_AA.ISO8859-6', 'ar_aa.iso88596': 'ar_AA.ISO8859-6', @@ -847,6 +861,7 @@ def getpreferredencoding(do_setlocale = True): 'ar_sa.iso88596': 'ar_SA.ISO8859-6', 'ar_sd': 'ar_SD.ISO8859-6', 'ar_sd.iso88596': 'ar_SD.ISO8859-6', + 'ar_ss': 'ar_SS.UTF-8', 'ar_sy': 'ar_SY.ISO8859-6', 'ar_sy.iso88596': 'ar_SY.ISO8859-6', 'ar_tn': 'ar_TN.ISO8859-6', @@ -862,6 +877,7 @@ def getpreferredencoding(do_setlocale = True): 'az': 'az_AZ.ISO8859-9E', 'az_az': 'az_AZ.ISO8859-9E', 'az_az.iso88599e': 'az_AZ.ISO8859-9E', + 'az_ir': 'az_IR.UTF-8', 'be': 'be_BY.CP1251', 'be at latin': 'be_BY.UTF-8 at latin', 'be_bg.utf8': 'bg_BG.UTF-8', @@ -879,7 +895,10 @@ def getpreferredencoding(do_setlocale = True): 'bg_bg.iso88595': 'bg_BG.ISO8859-5', 'bg_bg.koi8r': 'bg_BG.KOI8-R', 'bg_bg.microsoftcp1251': 'bg_BG.CP1251', + 'bhb_in.utf8': 'bhb_IN.UTF-8', 'bho_in': 'bho_IN.UTF-8', + 'bho_np': 'bho_NP.UTF-8', + 'bi_vu': 'bi_VU.UTF-8', 'bn_bd': 'bn_BD.UTF-8', 'bn_in': 'bn_IN.UTF-8', 'bo_cn': 'bo_CN.UTF-8', @@ -921,8 +940,8 @@ def getpreferredencoding(do_setlocale = True): 'ca_es.iso885915': 'ca_ES.ISO8859-15', 'ca_es.iso885915 at euro': 'ca_ES.ISO8859-15', 'ca_es.utf8 at euro': 'ca_ES.UTF-8', - 'ca_es at valencia': 'ca_ES.ISO8859-15 at valencia', 'ca_es at euro': 'ca_ES.ISO8859-15', + 'ca_es at valencia': 'ca_ES.UTF-8 at valencia', 'ca_fr': 'ca_FR.ISO8859-1', 'ca_fr.iso88591': 'ca_FR.ISO8859-1', 'ca_fr.iso885915': 'ca_FR.ISO8859-15', @@ -936,10 +955,14 @@ def getpreferredencoding(do_setlocale = True): 'ca_it.utf8 at euro': 'ca_IT.UTF-8', 'ca_it at euro': 'ca_IT.ISO8859-15', 'catalan': 'ca_ES.ISO8859-1', + 'ce_ru': 'ce_RU.UTF-8', 'cextend': 'en_US.ISO8859-1', 'cextend.en': 'en_US.ISO8859-1', 'chinese-s': 'zh_CN.eucCN', 'chinese-t': 'zh_TW.eucTW', + 'chr_us': 'chr_US.UTF-8', + 'ckb_iq': 'ckb_IQ.UTF-8', + 'cmn_tw': 'cmn_TW.UTF-8', 'crh_ua': 'crh_UA.UTF-8', 'croatian': 'hr_HR.ISO8859-2', 'cs': 'cs_CZ.ISO8859-2', @@ -996,6 +1019,7 @@ def getpreferredencoding(do_setlocale = True): 'de_de.iso885915 at euro': 'de_DE.ISO8859-15', 'de_de.utf8 at euro': 'de_DE.UTF-8', 'de_de at euro': 'de_DE.ISO8859-15', + 'de_it': 'de_IT.ISO8859-1', 'de_li.utf8': 'de_LI.UTF-8', 'de_lu': 'de_LU.ISO8859-1', 'de_lu.iso88591': 'de_LU.ISO8859-1', @@ -1030,6 +1054,8 @@ def getpreferredencoding(do_setlocale = True): 'en_ca': 'en_CA.ISO8859-1', 'en_ca.iso88591': 'en_CA.ISO8859-1', 'en_dk': 'en_DK.ISO8859-1', + 'en_dk.iso88591': 'en_DK.ISO8859-1', + 'en_dk.iso885915': 'en_DK.ISO8859-15', 'en_dl.utf8': 'en_DL.UTF-8', 'en_gb': 'en_GB.ISO8859-1', 'en_gb.88591': 'en_GB.ISO8859-1', @@ -1044,12 +1070,14 @@ def getpreferredencoding(do_setlocale = True): 'en_ie.iso885915 at euro': 'en_IE.ISO8859-15', 'en_ie.utf8 at euro': 'en_IE.UTF-8', 'en_ie at euro': 'en_IE.ISO8859-15', + 'en_il': 'en_IL.UTF-8', 'en_in': 'en_IN.ISO8859-1', 'en_ng': 'en_NG.UTF-8', 'en_nz': 'en_NZ.ISO8859-1', 'en_nz.iso88591': 'en_NZ.ISO8859-1', 'en_ph': 'en_PH.ISO8859-1', 'en_ph.iso88591': 'en_PH.ISO8859-1', + 'en_sc.utf8': 'en_SC.UTF-8', 'en_sg': 'en_SG.ISO8859-1', 'en_sg.iso88591': 'en_SG.ISO8859-1', 'en_uk': 'en_GB.ISO8859-1', @@ -1073,7 +1101,7 @@ def getpreferredencoding(do_setlocale = True): 'eng_gb': 'en_GB.ISO8859-1', 'eng_gb.8859': 'en_GB.ISO8859-1', 'english': 'en_EN.ISO8859-1', - 'english.iso88591': 'en_EN.ISO8859-1', + 'english.iso88591': 'en_US.ISO8859-1', 'english_uk': 'en_GB.ISO8859-1', 'english_uk.8859': 'en_GB.ISO8859-1', 'english_united-states': 'en_US.ISO8859-1', @@ -1268,6 +1296,7 @@ def getpreferredencoding(do_setlocale = True): 'gv_gb.iso885915': 'gv_GB.ISO8859-15', 'gv_gb at euro': 'gv_GB.ISO8859-15', 'ha_ng': 'ha_NG.UTF-8', + 'hak_tw': 'hak_TW.UTF-8', 'he': 'he_IL.ISO8859-8', 'he_il': 'he_IL.ISO8859-8', 'he_il.cp1255': 'he_IL.CP1255', @@ -1278,6 +1307,7 @@ def getpreferredencoding(do_setlocale = True): 'hi': 'hi_IN.ISCII-DEV', 'hi_in': 'hi_IN.ISCII-DEV', 'hi_in.isciidev': 'hi_IN.ISCII-DEV', + 'hif_fj': 'hif_FJ.UTF-8', 'hne': 'hne_IN.UTF-8', 'hne_in': 'hne_IN.UTF-8', 'hr': 'hr_HR.ISO8859-2', @@ -1361,7 +1391,8 @@ def getpreferredencoding(do_setlocale = True): 'ka_ge.georgianacademy': 'ka_GE.GEORGIAN-ACADEMY', 'ka_ge.georgianps': 'ka_GE.GEORGIAN-PS', 'ka_ge.georgianrs': 'ka_GE.GEORGIAN-ACADEMY', - 'kk_kz': 'kk_KZ.RK1048', + 'kab_dz': 'kab_DZ.UTF-8', + 'kk_kz': 'kk_KZ.ptcp154', 'kl': 'kl_GL.ISO8859-1', 'kl_gl': 'kl_GL.ISO8859-1', 'kl_gl.iso88591': 'kl_GL.ISO8859-1', @@ -1379,6 +1410,7 @@ def getpreferredencoding(do_setlocale = True): 'korean.euc': 'ko_KR.eucKR', 'ks': 'ks_IN.UTF-8', 'ks_in': 'ks_IN.UTF-8', + 'ks_in.utf8 at devanagari': 'ks_IN.UTF-8 at devanagari', 'ks_in at devanagari': 'ks_IN.UTF-8 at devanagari', 'ks_in at devanagari.utf8': 'ks_IN.UTF-8 at devanagari', 'ku_tr': 'ku_TR.ISO8859-9', @@ -1396,6 +1428,7 @@ def getpreferredencoding(do_setlocale = True): 'li_nl': 'li_NL.UTF-8', 'lij_it': 'lij_IT.UTF-8', 'lithuanian': 'lt_LT.ISO8859-13', + 'ln_cd': 'ln_CD.UTF-8', 'lo': 'lo_LA.MULELAO-1', 'lo_la': 'lo_LA.MULELAO-1', 'lo_la.cp1133': 'lo_LA.IBM-CP1133', @@ -1409,14 +1442,19 @@ def getpreferredencoding(do_setlocale = True): 'lv_lv': 'lv_LV.ISO8859-13', 'lv_lv.iso885913': 'lv_LV.ISO8859-13', 'lv_lv.iso88594': 'lv_LV.ISO8859-4', + 'lzh_tw': 'lzh_TW.UTF-8', 'mag_in': 'mag_IN.UTF-8', 'mai': 'mai_IN.UTF-8', 'mai_in': 'mai_IN.UTF-8', + 'mai_np': 'mai_NP.UTF-8', + 'mfe_mu': 'mfe_MU.UTF-8', 'mg_mg': 'mg_MG.ISO8859-15', 'mhr_ru': 'mhr_RU.UTF-8', 'mi': 'mi_NZ.ISO8859-1', 'mi_nz': 'mi_NZ.ISO8859-1', 'mi_nz.iso88591': 'mi_NZ.ISO8859-1', + 'miq_ni': 'miq_NI.UTF-8', + 'mjw_in': 'mjw_IN.UTF-8', 'mk': 'mk_MK.ISO8859-5', 'mk_mk': 'mk_MK.ISO8859-5', 'mk_mk.cp1251': 'mk_MK.CP1251', @@ -1435,7 +1473,7 @@ def getpreferredencoding(do_setlocale = True): 'mt_mt': 'mt_MT.ISO8859-3', 'mt_mt.iso88593': 'mt_MT.ISO8859-3', 'my_mm': 'my_MM.UTF-8', - 'nan_tw at latin': 'nan_TW.UTF-8 at latin', + 'nan_tw': 'nan_TW.UTF-8', 'nb': 'nb_NO.ISO8859-1', 'nb_no': 'nb_NO.ISO8859-1', 'nb_no.88591': 'nb_NO.ISO8859-1', @@ -1509,6 +1547,8 @@ def getpreferredencoding(do_setlocale = True): 'pa_in': 'pa_IN.UTF-8', 'pa_pk': 'pa_PK.UTF-8', 'pap_an': 'pap_AN.UTF-8', + 'pap_aw': 'pap_AW.UTF-8', + 'pap_cw': 'pap_CW.UTF-8', 'pd': 'pd_US.ISO8859-1', 'pd_de': 'pd_DE.ISO8859-1', 'pd_de.iso88591': 'pd_DE.ISO8859-1', @@ -1549,6 +1589,8 @@ def getpreferredencoding(do_setlocale = True): 'pt_pt.iso885915 at euro': 'pt_PT.ISO8859-15', 'pt_pt.utf8 at euro': 'pt_PT.UTF-8', 'pt_pt at euro': 'pt_PT.ISO8859-15', + 'quz_pe': 'quz_PE.UTF-8', + 'raj_in': 'raj_IN.UTF-8', 'ro': 'ro_RO.ISO8859-2', 'ro_ro': 'ro_RO.ISO8859-2', 'ro_ro.iso88592': 'ro_RO.ISO8859-2', @@ -1565,7 +1607,7 @@ def getpreferredencoding(do_setlocale = True): 'ru_ua.koi8u': 'ru_UA.KOI8-U', 'ru_ua.microsoftcp1251': 'ru_UA.CP1251', 'rumanian': 'ro_RO.ISO8859-2', - 'russian': 'ru_RU.ISO8859-5', + 'russian': 'ru_RU.KOI8-R', 'rw': 'rw_RW.ISO8859-1', 'rw_rw': 'rw_RW.ISO8859-1', 'rw_rw.iso88591': 'rw_RW.ISO8859-1', @@ -1575,17 +1617,20 @@ def getpreferredencoding(do_setlocale = True): 'sd': 'sd_IN.UTF-8', 'sd at devanagari': 'sd_IN.UTF-8 at devanagari', 'sd_in': 'sd_IN.UTF-8', + 'sd_in.utf8 at devanagari': 'sd_IN.UTF-8 at devanagari', 'sd_in at devanagari': 'sd_IN.UTF-8 at devanagari', 'sd_in at devanagari.utf8': 'sd_IN.UTF-8 at devanagari', 'sd_pk': 'sd_PK.UTF-8', 'se_no': 'se_NO.UTF-8', 'serbocroatian': 'sr_RS.UTF-8 at latin', + 'sgs_lt': 'sgs_LT.UTF-8', 'sh': 'sr_RS.UTF-8 at latin', 'sh_ba.iso88592 at bosnia': 'sr_CS.ISO8859-2', 'sh_hr': 'sh_HR.ISO8859-2', 'sh_hr.iso88592': 'hr_HR.ISO8859-2', 'sh_sp': 'sr_CS.ISO8859-2', 'sh_yu': 'sr_RS.UTF-8 at latin', + 'shn_mm': 'shn_MM.UTF-8', 'shs_ca': 'shs_CA.UTF-8', 'si': 'si_LK.UTF-8', 'si_lk': 'si_LK.UTF-8', @@ -1601,6 +1646,7 @@ def getpreferredencoding(do_setlocale = True): 'slovak': 'sk_SK.ISO8859-2', 'slovene': 'sl_SI.ISO8859-2', 'slovenian': 'sl_SI.ISO8859-2', + 'sm_ws': 'sm_WS.UTF-8', 'so_dj': 'so_DJ.ISO8859-1', 'so_et': 'so_ET.UTF-8', 'so_ke': 'so_KE.ISO8859-1', @@ -1627,6 +1673,7 @@ def getpreferredencoding(do_setlocale = True): 'sr_cs at latn': 'sr_CS.UTF-8 at latin', 'sr_me': 'sr_ME.UTF-8', 'sr_rs': 'sr_RS.UTF-8', + 'sr_rs.utf8 at latn': 'sr_RS.UTF-8 at latin', 'sr_rs at latin': 'sr_RS.UTF-8 at latin', 'sr_rs at latn': 'sr_RS.UTF-8 at latin', 'sr_sp': 'sr_CS.ISO8859-2', @@ -1668,6 +1715,7 @@ def getpreferredencoding(do_setlocale = True): 'ta_in.tscii': 'ta_IN.TSCII-0', 'ta_in.tscii0': 'ta_IN.TSCII-0', 'ta_lk': 'ta_LK.UTF-8', + 'tcy_in.utf8': 'tcy_IN.UTF-8', 'te': 'te_IN.UTF-8', 'te_in': 'te_IN.UTF-8', 'tg': 'tg_TJ.KOI8-C', @@ -1679,6 +1727,7 @@ def getpreferredencoding(do_setlocale = True): 'th_th.tactis': 'th_TH.TIS620', 'th_th.tis620': 'th_TH.TIS620', 'thai': 'th_TH.ISO8859-11', + 'the_np': 'the_NP.UTF-8', 'ti_er': 'ti_ER.UTF-8', 'ti_et': 'ti_ET.UTF-8', 'tig_er': 'tig_ER.UTF-8', @@ -1689,6 +1738,8 @@ def getpreferredencoding(do_setlocale = True): 'tn': 'tn_ZA.ISO8859-15', 'tn_za': 'tn_ZA.ISO8859-15', 'tn_za.iso885915': 'tn_ZA.ISO8859-15', + 'to_to': 'to_TO.UTF-8', + 'tpi_pg': 'tpi_PG.UTF-8', 'tr': 'tr_TR.ISO8859-9', 'tr_cy': 'tr_CY.ISO8859-9', 'tr_tr': 'tr_TR.ISO8859-9', @@ -1750,6 +1801,7 @@ def getpreferredencoding(do_setlocale = True): 'yi_us.microsoftcp1255': 'yi_US.CP1255', 'yo_ng': 'yo_NG.UTF-8', 'yue_hk': 'yue_HK.UTF-8', + 'yuw_pg': 'yuw_PG.UTF-8', 'zh': 'zh_CN.eucCN', 'zh_cn': 'zh_CN.gb2312', 'zh_cn.big5': 'zh_TW.big5', diff --git a/Lib/test/test_locale.py b/Lib/test/test_locale.py index 563ddb144fbb..6070882a37f7 100644 --- a/Lib/test/test_locale.py +++ b/Lib/test/test_locale.py @@ -425,7 +425,7 @@ def test_latin_modifier(self): def test_valencia_modifier(self): self.check('ca_ES.UTF-8 at valencia', 'ca_ES.UTF-8 at valencia') - self.check('ca_ES at valencia', 'ca_ES.ISO8859-15 at valencia') + self.check('ca_ES at valencia', 'ca_ES.UTF-8 at valencia') self.check('ca at valencia', 'ca_ES.ISO8859-1 at valencia') def test_devanagari_modifier(self): diff --git a/Misc/NEWS.d/next/Library/2018-05-05-18-02-24.bpo-20087.lJrvXL.rst b/Misc/NEWS.d/next/Library/2018-05-05-18-02-24.bpo-20087.lJrvXL.rst new file mode 100644 index 000000000000..2342cb781926 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-05-18-02-24.bpo-20087.lJrvXL.rst @@ -0,0 +1 @@ +Updated alias mapping with glibc 2.27 supported locales. From webhook-mailer at python.org Sun May 6 03:52:41 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sun, 06 May 2018 07:52:41 -0000 Subject: [Python-checkins] Remove mojibake in the locale aliases mapping. (GH-6716) Message-ID: https://github.com/python/cpython/commit/a3f19c3f52ddff85dd52eaa01b77b2d50cc9af3f commit: a3f19c3f52ddff85dd52eaa01b77b2d50cc9af3f branch: master author: Serhiy Storchaka committer: GitHub date: 2018-05-06T10:52:38+03:00 summary: Remove mojibake in the locale aliases mapping. (GH-6716) files: M Lib/locale.py M Tools/i18n/makelocalealias.py diff --git a/Lib/locale.py b/Lib/locale.py index 876d2eb1e123..f3d3973d038c 100644 --- a/Lib/locale.py +++ b/Lib/locale.py @@ -923,7 +923,6 @@ def getpreferredencoding(do_setlocale = True): 'bo_in': 'bo_IN.UTF-8', 'bokmal': 'nb_NO.ISO8859-1', 'bokm\xe5l': 'nb_NO.ISO8859-1', - 'bokm\xef\xbf\xbd': 'nb_NO.ISO8859-1', 'br': 'br_FR.ISO8859-1', 'br_fr': 'br_FR.ISO8859-1', 'brx_in': 'brx_IN.UTF-8', @@ -1072,7 +1071,6 @@ def getpreferredencoding(do_setlocale = True): 'fr_fr': 'fr_FR.ISO8859-1', 'fr_lu': 'fr_LU.ISO8859-1', 'fran\xe7ais': 'fr_FR.ISO8859-1', - 'fran\xef\xbf\xbdis': 'fr_FR.ISO8859-1', 'fre_fr': 'fr_FR.ISO8859-1', 'french': 'fr_FR.ISO8859-1', 'french.iso88591': 'fr_CH.ISO8859-1', diff --git a/Tools/i18n/makelocalealias.py b/Tools/i18n/makelocalealias.py index c7ecacec3877..b407a8a643be 100755 --- a/Tools/i18n/makelocalealias.py +++ b/Tools/i18n/makelocalealias.py @@ -19,6 +19,9 @@ def parse(filename): with open(filename, encoding='latin1') as f: lines = list(f) + # Remove mojibake in /usr/share/X11/locale/locale.alias. + # b'\xef\xbf\xbd' == '\ufffd'.encode('utf-8') + lines = [line for line in lines if '\xef\xbf\xbd' not in line] data = {} for line in lines: line = line.strip() From solipsis at pitrou.net Sun May 6 05:12:32 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 06 May 2018 09:12:32 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=1 Message-ID: <20180506091232.1.1D60D0F1D69D1E3C@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_asyncio leaked [0, 0, 3] memory blocks, sum=3 test_collections leaked [-7, 1, 0] memory blocks, sum=-6 test_functools leaked [0, 3, 1] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/refloginrpmZ', '--timeout', '7200'] From webhook-mailer at python.org Mon May 7 01:44:08 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Mon, 07 May 2018 05:44:08 -0000 Subject: [Python-checkins] [2.7] bpo-33422: Fix quotation marks getting deleted when looking up byte/string literals on pydoc. (GH-6701) (GH-6712) Message-ID: https://github.com/python/cpython/commit/c40eeeb5e69df12a5f46edc7ba82ec75c7d1b820 commit: c40eeeb5e69df12a5f46edc7ba82ec75c7d1b820 branch: 2.7 author: Andr?s Delfino committer: Serhiy Storchaka date: 2018-05-07T08:44:03+03:00 summary: [2.7] bpo-33422: Fix quotation marks getting deleted when looking up byte/string literals on pydoc. (GH-6701) (GH-6712) Also update the list of string prefixes. (cherry picked from commit b2043bbe6034b53f5ad337887f4741b74b70b00d) files: A Misc/NEWS.d/next/Library/2018-05-05-09-53-05.bpo-33422.4FtQ0q.rst M Lib/pydoc.py diff --git a/Lib/pydoc.py b/Lib/pydoc.py index b4b190f3f9a6..62cc262ccb83 100755 --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -1647,8 +1647,9 @@ class Helper: } # Either add symbols to this dictionary or to the symbols dictionary # directly: Whichever is easier. They are merged later. + _strprefixes = tuple(p + q for p in ('b', 'r', 'u') for q in ("'", '"')) _symbols_inverse = { - 'STRINGS' : ("'", "'''", "r'", "u'", '"""', '"', 'r"', 'u"'), + 'STRINGS' : ("'", "'''", '"""', '"') + _strprefixes, 'OPERATORS' : ('+', '-', '*', '**', '/', '//', '%', '<<', '>>', '&', '|', '^', '~', '<', '>', '<=', '>=', '==', '!=', '<>'), 'COMPARISON' : ('<', '>', '<=', '>=', '==', '!=', '<>'), @@ -1811,7 +1812,12 @@ def interact(self): if not request: break except (KeyboardInterrupt, EOFError): break - request = strip(replace(request, '"', '', "'", '')) + request = strip(request) + # Make sure significant trailing quotation marks of literals don't + # get deleted while cleaning input + if (len(request) > 2 and request[0] == request[-1] in ("'", '"') + and request[0] not in request[1:-1]): + request = request[1:-1] if lower(request) in ('q', 'quit'): break self.help(request) diff --git a/Misc/NEWS.d/next/Library/2018-05-05-09-53-05.bpo-33422.4FtQ0q.rst b/Misc/NEWS.d/next/Library/2018-05-05-09-53-05.bpo-33422.4FtQ0q.rst new file mode 100644 index 000000000000..0d284d508f10 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-05-09-53-05.bpo-33422.4FtQ0q.rst @@ -0,0 +1,2 @@ +Fix trailing quotation marks getting deleted when looking up byte/string +literals on pydoc. Patch by Andr?s Delfino. From solipsis at pitrou.net Mon May 7 05:08:07 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Mon, 07 May 2018 09:08:07 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=9 Message-ID: <20180507090807.1.94DBBF4B31CE76AA@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_collections leaked [0, 7, 0] memory blocks, sum=7 test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_forkserver leaked [-2, 2, -2] memory blocks, sum=-2 test_multiprocessing_spawn leaked [-2, 2, 0] memory blocks, sum=0 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogH_5Sg2', '--timeout', '7200'] From lp_benchmark_robot at intel.com Mon May 7 21:08:56 2018 From: lp_benchmark_robot at intel.com (lp_benchmark_robot at intel.com) Date: Mon, 7 May 2018 18:08:56 -0700 Subject: [Python-checkins] [65 flat] Results for Python (master branch) 2018-05-07 Message-ID: Results for project python/master, build date: 2018-05-07 03:03:02-07:00. - commit: a3f19c3 - previous commit: 9d3627e - revision date: 2018-05-06 10:52:38+03:00 - environment: Broadwell-EP - cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores, stepping 1, LLC 55 MB - mem: 128 GB - os: Ubuntu 16.04.2 LTS - kernel: 4.4.0-62-generic x86_64 GNU/Linux Baseline results were generated using release v3.6.0, with hash 5c4568a from 2016-12-22 23:38:47+00:00. +-----+------------------------+--------+------------+------------+------------+ | | |relative|change since|change since|current rev | | | benchmark|std_dev*| last run | baseline |run with PGO| +-----+------------------------+--------+------------+------------+------------+ | :-| | 2to3| 0.667% | +0.216% | +8.508% | +7.477% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method| 4.250% | -0.197% | +23.585% | +11.498% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_slots| 2.256% | -1.052% | +24.798% | +11.532% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_unknown| 0.949% | +0.202% | +23.852% | +7.603% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_simple| 2.933% | +0.341% | +10.109% | +14.107% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chameleon| 1.541% | +0.313% | +12.428% | +9.140% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chaos| 0.897% | -0.026% | +9.404% | +9.705% | +-----+------------------------+--------+------------+------------+------------+ | :-| | crypto_pyaes| 0.724% | -0.191% | -1.578% | +9.329% | +-----+------------------------+--------+------------+------------+------------+ | :-| | deltablue| 3.314% | +0.018% | +11.206% | +17.030% | +-----+------------------------+--------+------------+------------+------------+ | :-| | django_template| 1.568% | -0.005% | +21.783% | +12.026% | +-----+------------------------+--------+------------+------------+------------+ | :-| | dulwich_log| 1.112% | +0.554% | +5.807% | +5.761% | +-----+------------------------+--------+------------+------------+------------+ | :-| | fannkuch| 0.384% | -0.055% | +7.083% | +3.746% | +-----+------------------------+--------+------------+------------+------------+ | :-| | float| 1.083% | +0.153% | +2.718% | +7.010% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_text| 1.139% | +0.022% | +13.677% | +9.727% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_xml| 1.985% | -0.857% | +12.033% | +8.867% | +-----+------------------------+--------+------------+------------+------------+ | :-| | go| 5.988% | +1.076% | +4.936% | +11.735% | +-----+------------------------+--------+------------+------------+------------+ | :-| | hexiom| 0.985% | -0.306% | +11.109% | +12.166% | +-----+------------------------+--------+------------+------------+------------+ | :-| | html5lib| 2.608% | -0.007% | +11.398% | +11.528% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_dumps| 1.689% | -0.354% | +1.920% | +10.123% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_loads| 3.842% | -0.494% | -5.633% | +17.002% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_format| 1.361% | +0.393% | +18.543% | +11.843% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_silent| 3.126% | +0.493% | +47.786% | +10.969% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_simple| 1.354% | +1.200% | +13.320% | +12.777% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mako| 0.560% | +0.098% | +15.719% | +14.379% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mdp| 6.598% | +2.836% | +5.502% | +14.836% | +-----+------------------------+--------+------------+------------+------------+ | :-| | meteor_contest| 1.293% | -0.148% | +4.231% | +6.183% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nbody| 0.831% | +0.036% | -0.740% | -0.936% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nqueens| 0.611% | +0.363% | +6.052% | +7.117% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pathlib| 1.311% | -0.396% | -1.509% | +10.857% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle| 2.968% | -0.504% | -0.154% | +23.811% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_dict| 0.317% | -0.083% | +4.246% | +20.767% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_list| 0.802% | -0.050% | +6.010% | +19.028% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_pure_python| 5.984% | -1.131% | +10.343% | +11.770% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pidigits| 0.060% | +0.016% | +0.254% | +9.991% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup| 0.113% | +0.030% | +18.456% | +5.707% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup_no_site| 0.086% | -0.003% | +5.459% | +5.785% | +-----+------------------------+--------+------------+------------+------------+ | :-| | raytrace| 0.953% | -0.328% | +10.115% | +13.328% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_compile| 5.525% | +1.372% | +4.003% | +12.421% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_dna| 0.376% | +0.149% | -1.988% | +13.378% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_effbot| 1.120% | +1.791% | -2.282% | +4.976% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_v8| 1.488% | +0.539% | +3.719% | +8.911% | +-----+------------------------+--------+------------+------------+------------+ | :-| | richards| 1.382% | +0.036% | +9.559% | +14.232% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_fft| 0.646% | -0.140% | -1.486% | +3.666% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_lu| 3.447% | +0.635% | +21.884% | +10.805% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_monte_carlo| 2.297% | -0.159% | +4.931% | +5.159% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sor| 1.882% | +0.610% | +14.601% | +6.648% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sparse_mat_mult| 1.593% | +0.086% | -4.584% | +1.323% | +-----+------------------------+--------+------------+------------+------------+ | :-| | spectral_norm| 0.793% | -0.119% | +3.439% | +6.695% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_declarative| 1.335% | -0.155% | +6.508% | +6.572% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_imperative| 3.486% | +0.318% | +7.722% | +4.694% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlite_synth| 3.411% | -1.322% | -0.844% | +11.275% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_expand| 3.075% | -0.248% | +17.128% | +8.434% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_integrate| 1.490% | -0.043% | +18.058% | +6.485% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_str| 3.928% | +0.066% | +18.935% | +9.187% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_sum| 5.629% | +1.276% | +16.351% | +11.547% | +-----+------------------------+--------+------------+------------+------------+ | :-| | telco| 4.403% | -0.139% | +18.109% | +9.755% | +-----+------------------------+--------+------------+------------+------------+ | :-| | tornado_http| 1.294% | -0.306% | +6.819% | +6.048% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpack_sequence| 0.776% | +0.312% | +2.576% | +2.579% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle| 4.303% | +2.728% | +8.622% | +21.852% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_list| 0.815% | +0.057% | -1.807% | +16.402% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_pure_python| 2.344% | +0.038% | +6.294% | +9.539% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_generate| 0.892% | -0.313% | +2.637% | +12.716% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_iterparse| 1.913% | +0.425% | +2.572% | +8.928% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_parse| 4.170% | +0.201% | -9.111% | +12.550% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_process| 1.073% | +0.027% | +4.379% | +12.101% | +-----+------------------------+--------+------------+------------+------------+ * Relative Standard Deviation (Standard Deviation/Average) If this is not displayed properly please visit our results page here: http://languagesperformance.intel.com/65-flat-results-for-python-master-branch-2018-05-07 Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. From webhook-mailer at python.org Tue May 8 00:48:54 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Tue, 08 May 2018 04:48:54 -0000 Subject: [Python-checkins] bpo-33441: Make the sigset_t converter available in other modules. (GH-6720) Message-ID: https://github.com/python/cpython/commit/d54cfb160c626626394e2f171d3ccfe03309f34e commit: d54cfb160c626626394e2f171d3ccfe03309f34e branch: master author: Serhiy Storchaka committer: GitHub date: 2018-05-08T07:48:50+03:00 summary: bpo-33441: Make the sigset_t converter available in other modules. (GH-6720) * Expose the sigset_t converter via private API _Py_Sigset_Converter(). * Use Argument Clinic for parsing sigset_t in signalmodule.c. * Raise ValueError instead OverflowError for integers out of the C long range. Based on patch by Pablo Galindo Salgado. files: M Lib/test/test_signal.py M Modules/clinic/signalmodule.c.h M Modules/posixmodule.c M Modules/posixmodule.h M Modules/signalmodule.c diff --git a/Lib/test/test_signal.py b/Lib/test/test_signal.py index 7ce89f61ab3e..354c3fde168c 100644 --- a/Lib/test/test_signal.py +++ b/Lib/test/test_signal.py @@ -943,6 +943,10 @@ def test_pthread_sigmask_arguments(self): self.assertRaises(OSError, signal.pthread_sigmask, 1700, []) with self.assertRaises(ValueError): signal.pthread_sigmask(signal.SIG_BLOCK, [signal.NSIG]) + with self.assertRaises(ValueError): + signal.pthread_sigmask(signal.SIG_BLOCK, [0]) + with self.assertRaises(ValueError): + signal.pthread_sigmask(signal.SIG_BLOCK, [1<<1000]) @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'), 'need signal.pthread_sigmask()') diff --git a/Modules/clinic/signalmodule.c.h b/Modules/clinic/signalmodule.c.h index eca2da10ad33..4d7ac38372f2 100644 --- a/Modules/clinic/signalmodule.c.h +++ b/Modules/clinic/signalmodule.c.h @@ -278,17 +278,17 @@ PyDoc_STRVAR(signal_pthread_sigmask__doc__, {"pthread_sigmask", (PyCFunction)signal_pthread_sigmask, METH_FASTCALL, signal_pthread_sigmask__doc__}, static PyObject * -signal_pthread_sigmask_impl(PyObject *module, int how, PyObject *mask); +signal_pthread_sigmask_impl(PyObject *module, int how, sigset_t mask); static PyObject * signal_pthread_sigmask(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int how; - PyObject *mask; + sigset_t mask; - if (!_PyArg_ParseStack(args, nargs, "iO:pthread_sigmask", - &how, &mask)) { + if (!_PyArg_ParseStack(args, nargs, "iO&:pthread_sigmask", + &how, _Py_Sigset_Converter, &mask)) { goto exit; } return_value = signal_pthread_sigmask_impl(module, how, mask); @@ -339,6 +339,24 @@ PyDoc_STRVAR(signal_sigwait__doc__, #define SIGNAL_SIGWAIT_METHODDEF \ {"sigwait", (PyCFunction)signal_sigwait, METH_O, signal_sigwait__doc__}, +static PyObject * +signal_sigwait_impl(PyObject *module, sigset_t sigset); + +static PyObject * +signal_sigwait(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + sigset_t sigset; + + if (!PyArg_Parse(arg, "O&:sigwait", _Py_Sigset_Converter, &sigset)) { + goto exit; + } + return_value = signal_sigwait_impl(module, sigset); + +exit: + return return_value; +} + #endif /* defined(HAVE_SIGWAIT) */ #if (defined(HAVE_SIGFILLSET) || defined(MS_WINDOWS)) @@ -379,6 +397,24 @@ PyDoc_STRVAR(signal_sigwaitinfo__doc__, #define SIGNAL_SIGWAITINFO_METHODDEF \ {"sigwaitinfo", (PyCFunction)signal_sigwaitinfo, METH_O, signal_sigwaitinfo__doc__}, +static PyObject * +signal_sigwaitinfo_impl(PyObject *module, sigset_t sigset); + +static PyObject * +signal_sigwaitinfo(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + sigset_t sigset; + + if (!PyArg_Parse(arg, "O&:sigwaitinfo", _Py_Sigset_Converter, &sigset)) { + goto exit; + } + return_value = signal_sigwaitinfo_impl(module, sigset); + +exit: + return return_value; +} + #endif /* defined(HAVE_SIGWAITINFO) */ #if defined(HAVE_SIGTIMEDWAIT) @@ -395,19 +431,18 @@ PyDoc_STRVAR(signal_sigtimedwait__doc__, {"sigtimedwait", (PyCFunction)signal_sigtimedwait, METH_FASTCALL, signal_sigtimedwait__doc__}, static PyObject * -signal_sigtimedwait_impl(PyObject *module, PyObject *sigset, +signal_sigtimedwait_impl(PyObject *module, sigset_t sigset, PyObject *timeout_obj); static PyObject * signal_sigtimedwait(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - PyObject *sigset; + sigset_t sigset; PyObject *timeout_obj; - if (!_PyArg_UnpackStack(args, nargs, "sigtimedwait", - 2, 2, - &sigset, &timeout_obj)) { + if (!_PyArg_ParseStack(args, nargs, "O&O:sigtimedwait", + _Py_Sigset_Converter, &sigset, &timeout_obj)) { goto exit; } return_value = signal_sigtimedwait_impl(module, sigset, timeout_obj); @@ -499,4 +534,4 @@ signal_pthread_kill(PyObject *module, PyObject *const *args, Py_ssize_t nargs) #ifndef SIGNAL_PTHREAD_KILL_METHODDEF #define SIGNAL_PTHREAD_KILL_METHODDEF #endif /* !defined(SIGNAL_PTHREAD_KILL_METHODDEF) */ -/*[clinic end generated code: output=f35d79e0cfee3f1b input=a9049054013a1b77]*/ +/*[clinic end generated code: output=549f0efdc7405834 input=a9049054013a1b77]*/ diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 4ac6e7658999..a9b3917188c6 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -1267,6 +1267,65 @@ PyLong_FromPy_off_t(Py_off_t offset) #endif } +#ifdef HAVE_SIGSET_T +/* Convert an iterable of integers to a sigset. + Return 1 on success, return 0 and raise an exception on error. */ +int +_Py_Sigset_Converter(PyObject *obj, void *addr) +{ + sigset_t *mask = (sigset_t *)addr; + PyObject *iterator, *item; + long signum; + int overflow; + + if (sigemptyset(mask)) { + /* Probably only if mask == NULL. */ + PyErr_SetFromErrno(PyExc_OSError); + return 0; + } + + iterator = PyObject_GetIter(obj); + if (iterator == NULL) { + return 0; + } + + while ((item = PyIter_Next(iterator)) != NULL) { + signum = PyLong_AsLongAndOverflow(item, &overflow); + Py_DECREF(item); + if (signum <= 0 || signum >= NSIG) { + if (overflow || signum != -1 || !PyErr_Occurred()) { + PyErr_Format(PyExc_ValueError, + "signal number %ld out of range", signum); + } + goto error; + } + if (sigaddset(mask, (int)signum)) { + if (errno != EINVAL) { + /* Probably impossible */ + PyErr_SetFromErrno(PyExc_OSError); + goto error; + } + /* For backwards compatibility, allow idioms such as + * `range(1, NSIG)` but warn about invalid signal numbers + */ + const char msg[] = + "invalid signal number %ld, please use valid_signals()"; + if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1, msg, signum)) { + goto error; + } + } + } + if (!PyErr_Occurred()) { + Py_DECREF(iterator); + return 1; + } + +error: + Py_DECREF(iterator); + return 0; +} +#endif /* HAVE_SIGSET_T */ + #ifdef MS_WINDOWS static int diff --git a/Modules/posixmodule.h b/Modules/posixmodule.h index 1ec1833825f5..1e00562abc33 100644 --- a/Modules/posixmodule.h +++ b/Modules/posixmodule.h @@ -17,8 +17,17 @@ PyAPI_FUNC(PyObject *) _PyLong_FromGid(gid_t); PyAPI_FUNC(int) _Py_Uid_Converter(PyObject *, void *); PyAPI_FUNC(int) _Py_Gid_Converter(PyObject *, void *); #endif /* MS_WINDOWS */ + +#if defined(PYPTHREAD_SIGMASK) || defined(HAVE_SIGWAIT) || \ + defined(HAVE_SIGWAITINFO) || defined(HAVE_SIGTIMEDWAIT) +# define HAVE_SIGSET_T #endif +#ifdef HAVE_SIGSET_T +PyAPI_FUNC(int) _Py_Sigset_Converter(PyObject *, void *); +#endif /* HAVE_SIGSET_T */ +#endif /* Py_LIMITED_API */ + #ifdef __cplusplus } #endif diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c index 003bbb60e387..818df7d46e4c 100644 --- a/Modules/signalmodule.c +++ b/Modules/signalmodule.c @@ -59,6 +59,14 @@ module signal [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=b0301a3bde5fe9d3]*/ +/*[python input] + +class sigset_t_converter(CConverter): + type = 'sigset_t' + converter = '_Py_Sigset_Converter' + +[python start generated code]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=b5689d14466b6823]*/ /* NOTES ON THE INTERACTION BETWEEN SIGNALS AND THREADS @@ -808,69 +816,6 @@ signal_getitimer_impl(PyObject *module, int which) #endif -#if defined(PYPTHREAD_SIGMASK) || defined(HAVE_SIGWAIT) || \ - defined(HAVE_SIGWAITINFO) || defined(HAVE_SIGTIMEDWAIT) -/* Convert an iterable to a sigset. - Return 0 on success, return -1 and raise an exception on error. */ - -static int -iterable_to_sigset(PyObject *iterable, sigset_t *mask) -{ - int result = -1; - PyObject *iterator, *item; - long signum; - - sigemptyset(mask); - - iterator = PyObject_GetIter(iterable); - if (iterator == NULL) - goto error; - - while (1) - { - item = PyIter_Next(iterator); - if (item == NULL) { - if (PyErr_Occurred()) - goto error; - else - break; - } - - signum = PyLong_AsLong(item); - Py_DECREF(item); - if (signum == -1 && PyErr_Occurred()) - goto error; - if (0 < signum && signum < NSIG) { - if (sigaddset(mask, (int)signum)) { - if (errno != EINVAL) { - /* Probably impossible */ - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - /* For backwards compatibility, allow idioms such as - * `range(1, NSIG)` but warn about invalid signal numbers - */ - const char *msg = - "invalid signal number %ld, please use valid_signals()"; - if (PyErr_WarnFormat(PyExc_RuntimeWarning, 1, msg, signum)) { - goto error; - } - } - } - else { - PyErr_Format(PyExc_ValueError, - "signal number %ld out of range", signum); - goto error; - } - } - result = 0; - -error: - Py_XDECREF(iterator); - return result; -} -#endif - #if defined(PYPTHREAD_SIGMASK) || defined(HAVE_SIGPENDING) static PyObject* sigset_to_set(sigset_t mask) @@ -913,23 +858,20 @@ sigset_to_set(sigset_t mask) signal.pthread_sigmask how: int - mask: object + mask: sigset_t / Fetch and/or change the signal mask of the calling thread. [clinic start generated code]*/ static PyObject * -signal_pthread_sigmask_impl(PyObject *module, int how, PyObject *mask) -/*[clinic end generated code: output=ff640fe092bc9181 input=f3b7d7a61b7b8283]*/ +signal_pthread_sigmask_impl(PyObject *module, int how, sigset_t mask) +/*[clinic end generated code: output=0562c0fb192981a8 input=85bcebda442fa77f]*/ { - sigset_t newmask, previous; + sigset_t previous; int err; - if (iterable_to_sigset(mask, &newmask)) - return NULL; - - err = pthread_sigmask(how, &newmask, &previous); + err = pthread_sigmask(how, &mask, &previous); if (err != 0) { errno = err; PyErr_SetFromErrno(PyExc_OSError); @@ -977,7 +919,7 @@ signal_sigpending_impl(PyObject *module) /*[clinic input] signal.sigwait - sigset: object + sigset: sigset_t / Wait for a signal. @@ -988,17 +930,13 @@ and returns the signal number. [clinic start generated code]*/ static PyObject * -signal_sigwait(PyObject *module, PyObject *sigset) -/*[clinic end generated code: output=557173647424f6e4 input=11af2d82d83c2e94]*/ +signal_sigwait_impl(PyObject *module, sigset_t sigset) +/*[clinic end generated code: output=f43770699d682f96 input=a6fbd47b1086d119]*/ { - sigset_t set; int err, signum; - if (iterable_to_sigset(sigset, &set)) - return NULL; - Py_BEGIN_ALLOW_THREADS - err = sigwait(&set, &signum); + err = sigwait(&sigset, &signum); Py_END_ALLOW_THREADS if (err) { errno = err; @@ -1113,7 +1051,7 @@ fill_siginfo(siginfo_t *si) /*[clinic input] signal.sigwaitinfo - sigset: object + sigset: sigset_t / Wait synchronously until one of the signals in *sigset* is delivered. @@ -1122,20 +1060,16 @@ Returns a struct_siginfo containing information about the signal. [clinic start generated code]*/ static PyObject * -signal_sigwaitinfo(PyObject *module, PyObject *sigset) -/*[clinic end generated code: output=c40f27b269cd2309 input=f3779a74a991e171]*/ +signal_sigwaitinfo_impl(PyObject *module, sigset_t sigset) +/*[clinic end generated code: output=1eb2f1fa236fdbca input=3d1a7e1f27fc664c]*/ { - sigset_t set; siginfo_t si; int err; int async_err = 0; - if (iterable_to_sigset(sigset, &set)) - return NULL; - do { Py_BEGIN_ALLOW_THREADS - err = sigwaitinfo(&set, &si); + err = sigwaitinfo(&sigset, &si); Py_END_ALLOW_THREADS } while (err == -1 && errno == EINTR && !(async_err = PyErr_CheckSignals())); @@ -1152,7 +1086,7 @@ signal_sigwaitinfo(PyObject *module, PyObject *sigset) /*[clinic input] signal.sigtimedwait - sigset: object + sigset: sigset_t timeout as timeout_obj: object / @@ -1162,12 +1096,11 @@ The timeout is specified in seconds, with floating point numbers allowed. [clinic start generated code]*/ static PyObject * -signal_sigtimedwait_impl(PyObject *module, PyObject *sigset, +signal_sigtimedwait_impl(PyObject *module, sigset_t sigset, PyObject *timeout_obj) -/*[clinic end generated code: output=f7eff31e679f4312 input=53fd4ea3e3724eb8]*/ +/*[clinic end generated code: output=59c8971e8ae18a64 input=87fd39237cf0b7ba]*/ { struct timespec ts; - sigset_t set; siginfo_t si; int res; _PyTime_t timeout, deadline, monotonic; @@ -1181,9 +1114,6 @@ signal_sigtimedwait_impl(PyObject *module, PyObject *sigset, return NULL; } - if (iterable_to_sigset(sigset, &set)) - return NULL; - deadline = _PyTime_GetMonotonicClock() + timeout; do { @@ -1191,7 +1121,7 @@ signal_sigtimedwait_impl(PyObject *module, PyObject *sigset, return NULL; Py_BEGIN_ALLOW_THREADS - res = sigtimedwait(&set, &si, &ts); + res = sigtimedwait(&sigset, &si, &ts); Py_END_ALLOW_THREADS if (res != -1) From webhook-mailer at python.org Tue May 8 03:09:11 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Tue, 08 May 2018 07:09:11 -0000 Subject: [Python-checkins] bpo-33096: Removed unintentionally backported from Python 3 Tkinter files. (GH-6724) Message-ID: https://github.com/python/cpython/commit/903f189b6e528cbe9500014c6f990c6511b38918 commit: 903f189b6e528cbe9500014c6f990c6511b38918 branch: 2.7 author: Serhiy Storchaka committer: GitHub date: 2018-05-08T10:09:08+03:00 summary: bpo-33096: Removed unintentionally backported from Python 3 Tkinter files. (GH-6724) This partially reverts commit e80a232f2cfdab584133d9779c83885c5f9f1ba6. files: A Misc/NEWS.d/next/Library/2018-05-08-08-03-34.bpo-33096.0hsFhL.rst D Lib/tkinter/test/test_ttk/test_widgets.py D Lib/tkinter/ttk.py diff --git a/Lib/tkinter/test/test_ttk/test_widgets.py b/Lib/tkinter/test/test_ttk/test_widgets.py deleted file mode 100644 index 5b0e29cdccaf..000000000000 --- a/Lib/tkinter/test/test_ttk/test_widgets.py +++ /dev/null @@ -1,1872 +0,0 @@ -import unittest -import tkinter -from tkinter import ttk, TclError -from test.support import requires -import sys - -from tkinter.test.test_ttk.test_functions import MockTclObj -from tkinter.test.support import (AbstractTkTest, tcl_version, get_tk_patchlevel, - simulate_mouse_click) -from tkinter.test.widget_tests import (add_standard_options, noconv, - AbstractWidgetTest, StandardOptionsTests, IntegerSizeTests, PixelSizeTests, - setUpModule) - -requires('gui') - - -class StandardTtkOptionsTests(StandardOptionsTests): - - def test_class(self): - widget = self.create() - self.assertEqual(widget['class'], '') - errmsg='attempt to change read-only option' - if get_tk_patchlevel() < (8, 6, 0, 'beta', 3): - errmsg='Attempt to change read-only option' - self.checkInvalidParam(widget, 'class', 'Foo', errmsg=errmsg) - widget2 = self.create(class_='Foo') - self.assertEqual(widget2['class'], 'Foo') - - def test_padding(self): - widget = self.create() - self.checkParam(widget, 'padding', 0, expected=('0',)) - self.checkParam(widget, 'padding', 5, expected=('5',)) - self.checkParam(widget, 'padding', (5, 6), expected=('5', '6')) - self.checkParam(widget, 'padding', (5, 6, 7), - expected=('5', '6', '7')) - self.checkParam(widget, 'padding', (5, 6, 7, 8), - expected=('5', '6', '7', '8')) - self.checkParam(widget, 'padding', ('5p', '6p', '7p', '8p')) - self.checkParam(widget, 'padding', (), expected='') - - def test_style(self): - widget = self.create() - self.assertEqual(widget['style'], '') - errmsg = 'Layout Foo not found' - if hasattr(self, 'default_orient'): - errmsg = ('Layout %s.Foo not found' % - getattr(self, 'default_orient').title()) - self.checkInvalidParam(widget, 'style', 'Foo', - errmsg=errmsg) - widget2 = self.create(class_='Foo') - self.assertEqual(widget2['class'], 'Foo') - # XXX - pass - - -class WidgetTest(AbstractTkTest, unittest.TestCase): - """Tests methods available in every ttk widget.""" - - def setUp(self): - super().setUp() - self.widget = ttk.Button(self.root, width=0, text="Text") - self.widget.pack() - self.widget.wait_visibility() - - - def test_identify(self): - self.widget.update_idletasks() - self.assertEqual(self.widget.identify( - int(self.widget.winfo_width() / 2), - int(self.widget.winfo_height() / 2) - ), "label") - self.assertEqual(self.widget.identify(-1, -1), "") - - self.assertRaises(tkinter.TclError, self.widget.identify, None, 5) - self.assertRaises(tkinter.TclError, self.widget.identify, 5, None) - self.assertRaises(tkinter.TclError, self.widget.identify, 5, '') - - - def test_widget_state(self): - # XXX not sure about the portability of all these tests - self.assertEqual(self.widget.state(), ()) - self.assertEqual(self.widget.instate(['!disabled']), True) - - # changing from !disabled to disabled - self.assertEqual(self.widget.state(['disabled']), ('!disabled', )) - # no state change - self.assertEqual(self.widget.state(['disabled']), ()) - # change back to !disable but also active - self.assertEqual(self.widget.state(['!disabled', 'active']), - ('!active', 'disabled')) - # no state changes, again - self.assertEqual(self.widget.state(['!disabled', 'active']), ()) - self.assertEqual(self.widget.state(['active', '!disabled']), ()) - - def test_cb(arg1, **kw): - return arg1, kw - self.assertEqual(self.widget.instate(['!disabled'], - test_cb, "hi", **{"msg": "there"}), - ('hi', {'msg': 'there'})) - - # attempt to set invalid statespec - currstate = self.widget.state() - self.assertRaises(tkinter.TclError, self.widget.instate, - ['badstate']) - self.assertRaises(tkinter.TclError, self.widget.instate, - ['disabled', 'badstate']) - # verify that widget didn't change its state - self.assertEqual(currstate, self.widget.state()) - - # ensuring that passing None as state doesn't modify current state - self.widget.state(['active', '!disabled']) - self.assertEqual(self.widget.state(), ('active', )) - - -class AbstractToplevelTest(AbstractWidgetTest, PixelSizeTests): - _conv_pixels = noconv - - - at add_standard_options(StandardTtkOptionsTests) -class FrameTest(AbstractToplevelTest, unittest.TestCase): - OPTIONS = ( - 'borderwidth', 'class', 'cursor', 'height', - 'padding', 'relief', 'style', 'takefocus', - 'width', - ) - - def create(self, **kwargs): - return ttk.Frame(self.root, **kwargs) - - - at add_standard_options(StandardTtkOptionsTests) -class LabelFrameTest(AbstractToplevelTest, unittest.TestCase): - OPTIONS = ( - 'borderwidth', 'class', 'cursor', 'height', - 'labelanchor', 'labelwidget', - 'padding', 'relief', 'style', 'takefocus', - 'text', 'underline', 'width', - ) - - def create(self, **kwargs): - return ttk.LabelFrame(self.root, **kwargs) - - def test_labelanchor(self): - widget = self.create() - self.checkEnumParam(widget, 'labelanchor', - 'e', 'en', 'es', 'n', 'ne', 'nw', 's', 'se', 'sw', 'w', 'wn', 'ws', - errmsg='Bad label anchor specification {}') - self.checkInvalidParam(widget, 'labelanchor', 'center') - - def test_labelwidget(self): - widget = self.create() - label = ttk.Label(self.root, text='Mupp', name='foo') - self.checkParam(widget, 'labelwidget', label, expected='.foo') - label.destroy() - - -class AbstractLabelTest(AbstractWidgetTest): - - def checkImageParam(self, widget, name): - image = tkinter.PhotoImage(master=self.root, name='image1') - image2 = tkinter.PhotoImage(master=self.root, name='image2') - self.checkParam(widget, name, image, expected=('image1',)) - self.checkParam(widget, name, 'image1', expected=('image1',)) - self.checkParam(widget, name, (image,), expected=('image1',)) - self.checkParam(widget, name, (image, 'active', image2), - expected=('image1', 'active', 'image2')) - self.checkParam(widget, name, 'image1 active image2', - expected=('image1', 'active', 'image2')) - self.checkInvalidParam(widget, name, 'spam', - errmsg='image "spam" doesn\'t exist') - - def test_compound(self): - widget = self.create() - self.checkEnumParam(widget, 'compound', - 'none', 'text', 'image', 'center', - 'top', 'bottom', 'left', 'right') - - def test_state(self): - widget = self.create() - self.checkParams(widget, 'state', 'active', 'disabled', 'normal') - - def test_width(self): - widget = self.create() - self.checkParams(widget, 'width', 402, -402, 0) - - - at add_standard_options(StandardTtkOptionsTests) -class LabelTest(AbstractLabelTest, unittest.TestCase): - OPTIONS = ( - 'anchor', 'background', 'borderwidth', - 'class', 'compound', 'cursor', 'font', 'foreground', - 'image', 'justify', 'padding', 'relief', 'state', 'style', - 'takefocus', 'text', 'textvariable', - 'underline', 'width', 'wraplength', - ) - _conv_pixels = noconv - - def create(self, **kwargs): - return ttk.Label(self.root, **kwargs) - - def test_font(self): - widget = self.create() - self.checkParam(widget, 'font', - '-Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*') - - - at add_standard_options(StandardTtkOptionsTests) -class ButtonTest(AbstractLabelTest, unittest.TestCase): - OPTIONS = ( - 'class', 'command', 'compound', 'cursor', 'default', - 'image', 'padding', 'state', 'style', - 'takefocus', 'text', 'textvariable', - 'underline', 'width', - ) - - def create(self, **kwargs): - return ttk.Button(self.root, **kwargs) - - def test_default(self): - widget = self.create() - self.checkEnumParam(widget, 'default', 'normal', 'active', 'disabled') - - def test_invoke(self): - success = [] - btn = ttk.Button(self.root, command=lambda: success.append(1)) - btn.invoke() - self.assertTrue(success) - - - at add_standard_options(StandardTtkOptionsTests) -class CheckbuttonTest(AbstractLabelTest, unittest.TestCase): - OPTIONS = ( - 'class', 'command', 'compound', 'cursor', - 'image', - 'offvalue', 'onvalue', - 'padding', 'state', 'style', - 'takefocus', 'text', 'textvariable', - 'underline', 'variable', 'width', - ) - - def create(self, **kwargs): - return ttk.Checkbutton(self.root, **kwargs) - - def test_offvalue(self): - widget = self.create() - self.checkParams(widget, 'offvalue', 1, 2.3, '', 'any string') - - def test_onvalue(self): - widget = self.create() - self.checkParams(widget, 'onvalue', 1, 2.3, '', 'any string') - - def test_invoke(self): - success = [] - def cb_test(): - success.append(1) - return "cb test called" - - cbtn = ttk.Checkbutton(self.root, command=cb_test) - # the variable automatically created by ttk.Checkbutton is actually - # undefined till we invoke the Checkbutton - self.assertEqual(cbtn.state(), ('alternate', )) - self.assertRaises(tkinter.TclError, cbtn.tk.globalgetvar, - cbtn['variable']) - - res = cbtn.invoke() - self.assertEqual(res, "cb test called") - self.assertEqual(cbtn['onvalue'], - cbtn.tk.globalgetvar(cbtn['variable'])) - self.assertTrue(success) - - cbtn['command'] = '' - res = cbtn.invoke() - self.assertFalse(str(res)) - self.assertLessEqual(len(success), 1) - self.assertEqual(cbtn['offvalue'], - cbtn.tk.globalgetvar(cbtn['variable'])) - - - at add_standard_options(IntegerSizeTests, StandardTtkOptionsTests) -class EntryTest(AbstractWidgetTest, unittest.TestCase): - OPTIONS = ( - 'background', 'class', 'cursor', - 'exportselection', 'font', 'foreground', - 'invalidcommand', 'justify', - 'show', 'state', 'style', 'takefocus', 'textvariable', - 'validate', 'validatecommand', 'width', 'xscrollcommand', - ) - - def setUp(self): - super().setUp() - self.entry = self.create() - - def create(self, **kwargs): - return ttk.Entry(self.root, **kwargs) - - def test_invalidcommand(self): - widget = self.create() - self.checkCommandParam(widget, 'invalidcommand') - - def test_show(self): - widget = self.create() - self.checkParam(widget, 'show', '*') - self.checkParam(widget, 'show', '') - self.checkParam(widget, 'show', ' ') - - def test_state(self): - widget = self.create() - self.checkParams(widget, 'state', - 'disabled', 'normal', 'readonly') - - def test_validate(self): - widget = self.create() - self.checkEnumParam(widget, 'validate', - 'all', 'key', 'focus', 'focusin', 'focusout', 'none') - - def test_validatecommand(self): - widget = self.create() - self.checkCommandParam(widget, 'validatecommand') - - - def test_bbox(self): - self.assertIsBoundingBox(self.entry.bbox(0)) - self.assertRaises(tkinter.TclError, self.entry.bbox, 'noindex') - self.assertRaises(tkinter.TclError, self.entry.bbox, None) - - - def test_identify(self): - self.entry.pack() - self.entry.wait_visibility() - self.entry.update_idletasks() - - self.assertEqual(self.entry.identify(5, 5), "textarea") - self.assertEqual(self.entry.identify(-1, -1), "") - - self.assertRaises(tkinter.TclError, self.entry.identify, None, 5) - self.assertRaises(tkinter.TclError, self.entry.identify, 5, None) - self.assertRaises(tkinter.TclError, self.entry.identify, 5, '') - - - def test_validation_options(self): - success = [] - test_invalid = lambda: success.append(True) - - self.entry['validate'] = 'none' - self.entry['validatecommand'] = lambda: False - - self.entry['invalidcommand'] = test_invalid - self.entry.validate() - self.assertTrue(success) - - self.entry['invalidcommand'] = '' - self.entry.validate() - self.assertEqual(len(success), 1) - - self.entry['invalidcommand'] = test_invalid - self.entry['validatecommand'] = lambda: True - self.entry.validate() - self.assertEqual(len(success), 1) - - self.entry['validatecommand'] = '' - self.entry.validate() - self.assertEqual(len(success), 1) - - self.entry['validatecommand'] = True - self.assertRaises(tkinter.TclError, self.entry.validate) - - - def test_validation(self): - validation = [] - def validate(to_insert): - if not 'a' <= to_insert.lower() <= 'z': - validation.append(False) - return False - validation.append(True) - return True - - self.entry['validate'] = 'key' - self.entry['validatecommand'] = self.entry.register(validate), '%S' - - self.entry.insert('end', 1) - self.entry.insert('end', 'a') - self.assertEqual(validation, [False, True]) - self.assertEqual(self.entry.get(), 'a') - - - def test_revalidation(self): - def validate(content): - for letter in content: - if not 'a' <= letter.lower() <= 'z': - return False - return True - - self.entry['validatecommand'] = self.entry.register(validate), '%P' - - self.entry.insert('end', 'avocado') - self.assertEqual(self.entry.validate(), True) - self.assertEqual(self.entry.state(), ()) - - self.entry.delete(0, 'end') - self.assertEqual(self.entry.get(), '') - - self.entry.insert('end', 'a1b') - self.assertEqual(self.entry.validate(), False) - self.assertEqual(self.entry.state(), ('invalid', )) - - self.entry.delete(1) - self.assertEqual(self.entry.validate(), True) - self.assertEqual(self.entry.state(), ()) - - - at add_standard_options(IntegerSizeTests, StandardTtkOptionsTests) -class ComboboxTest(EntryTest, unittest.TestCase): - OPTIONS = ( - 'background', 'class', 'cursor', 'exportselection', - 'font', 'foreground', 'height', 'invalidcommand', - 'justify', 'postcommand', 'show', 'state', 'style', - 'takefocus', 'textvariable', - 'validate', 'validatecommand', 'values', - 'width', 'xscrollcommand', - ) - - def setUp(self): - super().setUp() - self.combo = self.create() - - def create(self, **kwargs): - return ttk.Combobox(self.root, **kwargs) - - def test_height(self): - widget = self.create() - self.checkParams(widget, 'height', 100, 101.2, 102.6, -100, 0, '1i') - - def _show_drop_down_listbox(self): - width = self.combo.winfo_width() - self.combo.event_generate('', x=width - 5, y=5) - self.combo.event_generate('', x=width - 5, y=5) - self.combo.update_idletasks() - - - def test_virtual_event(self): - success = [] - - self.combo['values'] = [1] - self.combo.bind('<>', - lambda evt: success.append(True)) - self.combo.pack() - self.combo.wait_visibility() - - height = self.combo.winfo_height() - self._show_drop_down_listbox() - self.combo.update() - self.combo.event_generate('') - self.combo.update() - - self.assertTrue(success) - - - def test_postcommand(self): - success = [] - - self.combo['postcommand'] = lambda: success.append(True) - self.combo.pack() - self.combo.wait_visibility() - - self._show_drop_down_listbox() - self.assertTrue(success) - - # testing postcommand removal - self.combo['postcommand'] = '' - self._show_drop_down_listbox() - self.assertEqual(len(success), 1) - - - def test_values(self): - def check_get_current(getval, currval): - self.assertEqual(self.combo.get(), getval) - self.assertEqual(self.combo.current(), currval) - - self.assertEqual(self.combo['values'], - () if tcl_version < (8, 5) else '') - check_get_current('', -1) - - self.checkParam(self.combo, 'values', 'mon tue wed thur', - expected=('mon', 'tue', 'wed', 'thur')) - self.checkParam(self.combo, 'values', ('mon', 'tue', 'wed', 'thur')) - self.checkParam(self.combo, 'values', (42, 3.14, '', 'any string')) - self.checkParam(self.combo, 'values', '', - expected='' if get_tk_patchlevel() < (8, 5, 10) else ()) - - self.combo['values'] = ['a', 1, 'c'] - - self.combo.set('c') - check_get_current('c', 2) - - self.combo.current(0) - check_get_current('a', 0) - - self.combo.set('d') - check_get_current('d', -1) - - # testing values with empty string - self.combo.set('') - self.combo['values'] = (1, 2, '', 3) - check_get_current('', 2) - - # testing values with empty string set through configure - self.combo.configure(values=[1, '', 2]) - self.assertEqual(self.combo['values'], - ('1', '', '2') if self.wantobjects else - '1 {} 2') - - # testing values with spaces - self.combo['values'] = ['a b', 'a\tb', 'a\nb'] - self.assertEqual(self.combo['values'], - ('a b', 'a\tb', 'a\nb') if self.wantobjects else - '{a b} {a\tb} {a\nb}') - - # testing values with special characters - self.combo['values'] = [r'a\tb', '"a"', '} {'] - self.assertEqual(self.combo['values'], - (r'a\tb', '"a"', '} {') if self.wantobjects else - r'a\\tb {"a"} \}\ \{') - - # out of range - self.assertRaises(tkinter.TclError, self.combo.current, - len(self.combo['values'])) - # it expects an integer (or something that can be converted to int) - self.assertRaises(tkinter.TclError, self.combo.current, '') - - # testing creating combobox with empty string in values - combo2 = ttk.Combobox(self.root, values=[1, 2, '']) - self.assertEqual(combo2['values'], - ('1', '2', '') if self.wantobjects else '1 2 {}') - combo2.destroy() - - - at add_standard_options(IntegerSizeTests, StandardTtkOptionsTests) -class PanedWindowTest(AbstractWidgetTest, unittest.TestCase): - OPTIONS = ( - 'class', 'cursor', 'height', - 'orient', 'style', 'takefocus', 'width', - ) - - def setUp(self): - super().setUp() - self.paned = self.create() - - def create(self, **kwargs): - return ttk.PanedWindow(self.root, **kwargs) - - def test_orient(self): - widget = self.create() - self.assertEqual(str(widget['orient']), 'vertical') - errmsg='attempt to change read-only option' - if get_tk_patchlevel() < (8, 6, 0, 'beta', 3): - errmsg='Attempt to change read-only option' - self.checkInvalidParam(widget, 'orient', 'horizontal', - errmsg=errmsg) - widget2 = self.create(orient='horizontal') - self.assertEqual(str(widget2['orient']), 'horizontal') - - def test_add(self): - # attempt to add a child that is not a direct child of the paned window - label = ttk.Label(self.paned) - child = ttk.Label(label) - self.assertRaises(tkinter.TclError, self.paned.add, child) - label.destroy() - child.destroy() - # another attempt - label = ttk.Label(self.root) - child = ttk.Label(label) - self.assertRaises(tkinter.TclError, self.paned.add, child) - child.destroy() - label.destroy() - - good_child = ttk.Label(self.root) - self.paned.add(good_child) - # re-adding a child is not accepted - self.assertRaises(tkinter.TclError, self.paned.add, good_child) - - other_child = ttk.Label(self.paned) - self.paned.add(other_child) - self.assertEqual(self.paned.pane(0), self.paned.pane(1)) - self.assertRaises(tkinter.TclError, self.paned.pane, 2) - good_child.destroy() - other_child.destroy() - self.assertRaises(tkinter.TclError, self.paned.pane, 0) - - - def test_forget(self): - self.assertRaises(tkinter.TclError, self.paned.forget, None) - self.assertRaises(tkinter.TclError, self.paned.forget, 0) - - self.paned.add(ttk.Label(self.root)) - self.paned.forget(0) - self.assertRaises(tkinter.TclError, self.paned.forget, 0) - - - def test_insert(self): - self.assertRaises(tkinter.TclError, self.paned.insert, None, 0) - self.assertRaises(tkinter.TclError, self.paned.insert, 0, None) - self.assertRaises(tkinter.TclError, self.paned.insert, 0, 0) - - child = ttk.Label(self.root) - child2 = ttk.Label(self.root) - child3 = ttk.Label(self.root) - - self.assertRaises(tkinter.TclError, self.paned.insert, 0, child) - - self.paned.insert('end', child2) - self.paned.insert(0, child) - self.assertEqual(self.paned.panes(), (str(child), str(child2))) - - self.paned.insert(0, child2) - self.assertEqual(self.paned.panes(), (str(child2), str(child))) - - self.paned.insert('end', child3) - self.assertEqual(self.paned.panes(), - (str(child2), str(child), str(child3))) - - # reinserting a child should move it to its current position - panes = self.paned.panes() - self.paned.insert('end', child3) - self.assertEqual(panes, self.paned.panes()) - - # moving child3 to child2 position should result in child2 ending up - # in previous child position and child ending up in previous child3 - # position - self.paned.insert(child2, child3) - self.assertEqual(self.paned.panes(), - (str(child3), str(child2), str(child))) - - - def test_pane(self): - self.assertRaises(tkinter.TclError, self.paned.pane, 0) - - child = ttk.Label(self.root) - self.paned.add(child) - self.assertIsInstance(self.paned.pane(0), dict) - self.assertEqual(self.paned.pane(0, weight=None), - 0 if self.wantobjects else '0') - # newer form for querying a single option - self.assertEqual(self.paned.pane(0, 'weight'), - 0 if self.wantobjects else '0') - self.assertEqual(self.paned.pane(0), self.paned.pane(str(child))) - - self.assertRaises(tkinter.TclError, self.paned.pane, 0, - badoption='somevalue') - - - def test_sashpos(self): - self.assertRaises(tkinter.TclError, self.paned.sashpos, None) - self.assertRaises(tkinter.TclError, self.paned.sashpos, '') - self.assertRaises(tkinter.TclError, self.paned.sashpos, 0) - - child = ttk.Label(self.paned, text='a') - self.paned.add(child, weight=1) - self.assertRaises(tkinter.TclError, self.paned.sashpos, 0) - child2 = ttk.Label(self.paned, text='b') - self.paned.add(child2) - self.assertRaises(tkinter.TclError, self.paned.sashpos, 1) - - self.paned.pack(expand=True, fill='both') - self.paned.wait_visibility() - - curr_pos = self.paned.sashpos(0) - self.paned.sashpos(0, 1000) - self.assertNotEqual(curr_pos, self.paned.sashpos(0)) - self.assertIsInstance(self.paned.sashpos(0), int) - - - at add_standard_options(StandardTtkOptionsTests) -class RadiobuttonTest(AbstractLabelTest, unittest.TestCase): - OPTIONS = ( - 'class', 'command', 'compound', 'cursor', - 'image', - 'padding', 'state', 'style', - 'takefocus', 'text', 'textvariable', - 'underline', 'value', 'variable', 'width', - ) - - def create(self, **kwargs): - return ttk.Radiobutton(self.root, **kwargs) - - def test_value(self): - widget = self.create() - self.checkParams(widget, 'value', 1, 2.3, '', 'any string') - - def test_invoke(self): - success = [] - def cb_test(): - success.append(1) - return "cb test called" - - myvar = tkinter.IntVar(self.root) - cbtn = ttk.Radiobutton(self.root, command=cb_test, - variable=myvar, value=0) - cbtn2 = ttk.Radiobutton(self.root, command=cb_test, - variable=myvar, value=1) - - if self.wantobjects: - conv = lambda x: x - else: - conv = int - - res = cbtn.invoke() - self.assertEqual(res, "cb test called") - self.assertEqual(conv(cbtn['value']), myvar.get()) - self.assertEqual(myvar.get(), - conv(cbtn.tk.globalgetvar(cbtn['variable']))) - self.assertTrue(success) - - cbtn2['command'] = '' - res = cbtn2.invoke() - self.assertEqual(str(res), '') - self.assertLessEqual(len(success), 1) - self.assertEqual(conv(cbtn2['value']), myvar.get()) - self.assertEqual(myvar.get(), - conv(cbtn.tk.globalgetvar(cbtn['variable']))) - - self.assertEqual(str(cbtn['variable']), str(cbtn2['variable'])) - - -class MenubuttonTest(AbstractLabelTest, unittest.TestCase): - OPTIONS = ( - 'class', 'compound', 'cursor', 'direction', - 'image', 'menu', 'padding', 'state', 'style', - 'takefocus', 'text', 'textvariable', - 'underline', 'width', - ) - - def create(self, **kwargs): - return ttk.Menubutton(self.root, **kwargs) - - def test_direction(self): - widget = self.create() - self.checkEnumParam(widget, 'direction', - 'above', 'below', 'left', 'right', 'flush') - - def test_menu(self): - widget = self.create() - menu = tkinter.Menu(widget, name='menu') - self.checkParam(widget, 'menu', menu, conv=str) - menu.destroy() - - - at add_standard_options(StandardTtkOptionsTests) -class ScaleTest(AbstractWidgetTest, unittest.TestCase): - OPTIONS = ( - 'class', 'command', 'cursor', 'from', 'length', - 'orient', 'style', 'takefocus', 'to', 'value', 'variable', - ) - _conv_pixels = noconv - default_orient = 'horizontal' - - def setUp(self): - super().setUp() - self.scale = self.create() - self.scale.pack() - self.scale.update() - - def create(self, **kwargs): - return ttk.Scale(self.root, **kwargs) - - def test_from(self): - widget = self.create() - self.checkFloatParam(widget, 'from', 100, 14.9, 15.1, conv=False) - - def test_length(self): - widget = self.create() - self.checkPixelsParam(widget, 'length', 130, 131.2, 135.6, '5i') - - def test_to(self): - widget = self.create() - self.checkFloatParam(widget, 'to', 300, 14.9, 15.1, -10, conv=False) - - def test_value(self): - widget = self.create() - self.checkFloatParam(widget, 'value', 300, 14.9, 15.1, -10, conv=False) - - def test_custom_event(self): - failure = [1, 1, 1] # will need to be empty - - funcid = self.scale.bind('<>', lambda evt: failure.pop()) - - self.scale['from'] = 10 - self.scale['from_'] = 10 - self.scale['to'] = 3 - - self.assertFalse(failure) - - failure = [1, 1, 1] - self.scale.configure(from_=2, to=5) - self.scale.configure(from_=0, to=-2) - self.scale.configure(to=10) - - self.assertFalse(failure) - - - def test_get(self): - if self.wantobjects: - conv = lambda x: x - else: - conv = float - - scale_width = self.scale.winfo_width() - self.assertEqual(self.scale.get(scale_width, 0), self.scale['to']) - - self.assertEqual(conv(self.scale.get(0, 0)), conv(self.scale['from'])) - self.assertEqual(self.scale.get(), self.scale['value']) - self.scale['value'] = 30 - self.assertEqual(self.scale.get(), self.scale['value']) - - self.assertRaises(tkinter.TclError, self.scale.get, '', 0) - self.assertRaises(tkinter.TclError, self.scale.get, 0, '') - - - def test_set(self): - if self.wantobjects: - conv = lambda x: x - else: - conv = float - - # set restricts the max/min values according to the current range - max = conv(self.scale['to']) - new_max = max + 10 - self.scale.set(new_max) - self.assertEqual(conv(self.scale.get()), max) - min = conv(self.scale['from']) - self.scale.set(min - 1) - self.assertEqual(conv(self.scale.get()), min) - - # changing directly the variable doesn't impose this limitation tho - var = tkinter.DoubleVar(self.root) - self.scale['variable'] = var - var.set(max + 5) - self.assertEqual(conv(self.scale.get()), var.get()) - self.assertEqual(conv(self.scale.get()), max + 5) - del var - - # the same happens with the value option - self.scale['value'] = max + 10 - self.assertEqual(conv(self.scale.get()), max + 10) - self.assertEqual(conv(self.scale.get()), conv(self.scale['value'])) - - # nevertheless, note that the max/min values we can get specifying - # x, y coords are the ones according to the current range - self.assertEqual(conv(self.scale.get(0, 0)), min) - self.assertEqual(conv(self.scale.get(self.scale.winfo_width(), 0)), max) - - self.assertRaises(tkinter.TclError, self.scale.set, None) - - - at add_standard_options(StandardTtkOptionsTests) -class ProgressbarTest(AbstractWidgetTest, unittest.TestCase): - OPTIONS = ( - 'class', 'cursor', 'orient', 'length', - 'mode', 'maximum', 'phase', - 'style', 'takefocus', 'value', 'variable', - ) - _conv_pixels = noconv - default_orient = 'horizontal' - - def create(self, **kwargs): - return ttk.Progressbar(self.root, **kwargs) - - def test_length(self): - widget = self.create() - self.checkPixelsParam(widget, 'length', 100.1, 56.7, '2i') - - def test_maximum(self): - widget = self.create() - self.checkFloatParam(widget, 'maximum', 150.2, 77.7, 0, -10, conv=False) - - def test_mode(self): - widget = self.create() - self.checkEnumParam(widget, 'mode', 'determinate', 'indeterminate') - - def test_phase(self): - # XXX - pass - - def test_value(self): - widget = self.create() - self.checkFloatParam(widget, 'value', 150.2, 77.7, 0, -10, - conv=False) - - - at unittest.skipIf(sys.platform == 'darwin', - 'ttk.Scrollbar is special on MacOSX') - at add_standard_options(StandardTtkOptionsTests) -class ScrollbarTest(AbstractWidgetTest, unittest.TestCase): - OPTIONS = ( - 'class', 'command', 'cursor', 'orient', 'style', 'takefocus', - ) - default_orient = 'vertical' - - def create(self, **kwargs): - return ttk.Scrollbar(self.root, **kwargs) - - - at add_standard_options(IntegerSizeTests, StandardTtkOptionsTests) -class NotebookTest(AbstractWidgetTest, unittest.TestCase): - OPTIONS = ( - 'class', 'cursor', 'height', 'padding', 'style', 'takefocus', 'width', - ) - - def setUp(self): - super().setUp() - self.nb = self.create(padding=0) - self.child1 = ttk.Label(self.root) - self.child2 = ttk.Label(self.root) - self.nb.add(self.child1, text='a') - self.nb.add(self.child2, text='b') - - def create(self, **kwargs): - return ttk.Notebook(self.root, **kwargs) - - def test_tab_identifiers(self): - self.nb.forget(0) - self.nb.hide(self.child2) - self.assertRaises(tkinter.TclError, self.nb.tab, self.child1) - self.assertEqual(self.nb.index('end'), 1) - self.nb.add(self.child2) - self.assertEqual(self.nb.index('end'), 1) - self.nb.select(self.child2) - - self.assertTrue(self.nb.tab('current')) - self.nb.add(self.child1, text='a') - - self.nb.pack() - self.nb.wait_visibility() - if sys.platform == 'darwin': - tb_idx = "@20,5" - else: - tb_idx = "@5,5" - self.assertEqual(self.nb.tab(tb_idx), self.nb.tab('current')) - - for i in range(5, 100, 5): - try: - if self.nb.tab('@%d, 5' % i, text=None) == 'a': - break - except tkinter.TclError: - pass - - else: - self.fail("Tab with text 'a' not found") - - - def test_add_and_hidden(self): - self.assertRaises(tkinter.TclError, self.nb.hide, -1) - self.assertRaises(tkinter.TclError, self.nb.hide, 'hi') - self.assertRaises(tkinter.TclError, self.nb.hide, None) - self.assertRaises(tkinter.TclError, self.nb.add, None) - self.assertRaises(tkinter.TclError, self.nb.add, ttk.Label(self.root), - unknown='option') - - tabs = self.nb.tabs() - self.nb.hide(self.child1) - self.nb.add(self.child1) - self.assertEqual(self.nb.tabs(), tabs) - - child = ttk.Label(self.root) - self.nb.add(child, text='c') - tabs = self.nb.tabs() - - curr = self.nb.index('current') - # verify that the tab gets readded at its previous position - child2_index = self.nb.index(self.child2) - self.nb.hide(self.child2) - self.nb.add(self.child2) - self.assertEqual(self.nb.tabs(), tabs) - self.assertEqual(self.nb.index(self.child2), child2_index) - self.assertEqual(str(self.child2), self.nb.tabs()[child2_index]) - # but the tab next to it (not hidden) is the one selected now - self.assertEqual(self.nb.index('current'), curr + 1) - - - def test_forget(self): - self.assertRaises(tkinter.TclError, self.nb.forget, -1) - self.assertRaises(tkinter.TclError, self.nb.forget, 'hi') - self.assertRaises(tkinter.TclError, self.nb.forget, None) - - tabs = self.nb.tabs() - child1_index = self.nb.index(self.child1) - self.nb.forget(self.child1) - self.assertNotIn(str(self.child1), self.nb.tabs()) - self.assertEqual(len(tabs) - 1, len(self.nb.tabs())) - - self.nb.add(self.child1) - self.assertEqual(self.nb.index(self.child1), 1) - self.assertNotEqual(child1_index, self.nb.index(self.child1)) - - - def test_index(self): - self.assertRaises(tkinter.TclError, self.nb.index, -1) - self.assertRaises(tkinter.TclError, self.nb.index, None) - - self.assertIsInstance(self.nb.index('end'), int) - self.assertEqual(self.nb.index(self.child1), 0) - self.assertEqual(self.nb.index(self.child2), 1) - self.assertEqual(self.nb.index('end'), 2) - - - def test_insert(self): - # moving tabs - tabs = self.nb.tabs() - self.nb.insert(1, tabs[0]) - self.assertEqual(self.nb.tabs(), (tabs[1], tabs[0])) - self.nb.insert(self.child1, self.child2) - self.assertEqual(self.nb.tabs(), tabs) - self.nb.insert('end', self.child1) - self.assertEqual(self.nb.tabs(), (tabs[1], tabs[0])) - self.nb.insert('end', 0) - self.assertEqual(self.nb.tabs(), tabs) - # bad moves - self.assertRaises(tkinter.TclError, self.nb.insert, 2, tabs[0]) - self.assertRaises(tkinter.TclError, self.nb.insert, -1, tabs[0]) - - # new tab - child3 = ttk.Label(self.root) - self.nb.insert(1, child3) - self.assertEqual(self.nb.tabs(), (tabs[0], str(child3), tabs[1])) - self.nb.forget(child3) - self.assertEqual(self.nb.tabs(), tabs) - self.nb.insert(self.child1, child3) - self.assertEqual(self.nb.tabs(), (str(child3), ) + tabs) - self.nb.forget(child3) - self.assertRaises(tkinter.TclError, self.nb.insert, 2, child3) - self.assertRaises(tkinter.TclError, self.nb.insert, -1, child3) - - # bad inserts - self.assertRaises(tkinter.TclError, self.nb.insert, 'end', None) - self.assertRaises(tkinter.TclError, self.nb.insert, None, 0) - self.assertRaises(tkinter.TclError, self.nb.insert, None, None) - - - def test_select(self): - self.nb.pack() - self.nb.wait_visibility() - - success = [] - tab_changed = [] - - self.child1.bind('', lambda evt: success.append(True)) - self.nb.bind('<>', - lambda evt: tab_changed.append(True)) - - self.assertEqual(self.nb.select(), str(self.child1)) - self.nb.select(self.child2) - self.assertTrue(success) - self.assertEqual(self.nb.select(), str(self.child2)) - - self.nb.update() - self.assertTrue(tab_changed) - - - def test_tab(self): - self.assertRaises(tkinter.TclError, self.nb.tab, -1) - self.assertRaises(tkinter.TclError, self.nb.tab, 'notab') - self.assertRaises(tkinter.TclError, self.nb.tab, None) - - self.assertIsInstance(self.nb.tab(self.child1), dict) - self.assertEqual(self.nb.tab(self.child1, text=None), 'a') - # newer form for querying a single option - self.assertEqual(self.nb.tab(self.child1, 'text'), 'a') - self.nb.tab(self.child1, text='abc') - self.assertEqual(self.nb.tab(self.child1, text=None), 'abc') - self.assertEqual(self.nb.tab(self.child1, 'text'), 'abc') - - - def test_tabs(self): - self.assertEqual(len(self.nb.tabs()), 2) - - self.nb.forget(self.child1) - self.nb.forget(self.child2) - - self.assertEqual(self.nb.tabs(), ()) - - - def test_traversal(self): - self.nb.pack() - self.nb.wait_visibility() - - self.nb.select(0) - - simulate_mouse_click(self.nb, 5, 5) - self.nb.focus_force() - self.nb.event_generate('') - self.assertEqual(self.nb.select(), str(self.child2)) - self.nb.focus_force() - self.nb.event_generate('') - self.assertEqual(self.nb.select(), str(self.child1)) - self.nb.focus_force() - self.nb.event_generate('') - self.assertEqual(self.nb.select(), str(self.child2)) - - self.nb.tab(self.child1, text='a', underline=0) - self.nb.enable_traversal() - self.nb.focus_force() - simulate_mouse_click(self.nb, 5, 5) - if sys.platform == 'darwin': - self.nb.event_generate('') - else: - self.nb.event_generate('') - self.assertEqual(self.nb.select(), str(self.child1)) - - at add_standard_options(IntegerSizeTests, StandardTtkOptionsTests) -class SpinboxTest(EntryTest, unittest.TestCase): - OPTIONS = ( - 'background', 'class', 'command', 'cursor', 'exportselection', - 'font', 'foreground', 'format', 'from', 'increment', - 'invalidcommand', 'justify', 'show', 'state', 'style', - 'takefocus', 'textvariable', 'to', 'validate', 'validatecommand', - 'values', 'width', 'wrap', 'xscrollcommand', - ) - - def setUp(self): - super().setUp() - self.spin = self.create() - self.spin.pack() - - def create(self, **kwargs): - return ttk.Spinbox(self.root, **kwargs) - - def _click_increment_arrow(self): - width = self.spin.winfo_width() - height = self.spin.winfo_height() - x = width - 5 - y = height//2 - 5 - self.spin.event_generate('', x=x, y=y) - self.spin.event_generate('', x=x, y=y) - self.spin.update_idletasks() - - def _click_decrement_arrow(self): - width = self.spin.winfo_width() - height = self.spin.winfo_height() - x = width - 5 - y = height//2 + 4 - self.spin.event_generate('', x=x, y=y) - self.spin.event_generate('', x=x, y=y) - self.spin.update_idletasks() - - def test_command(self): - success = [] - - self.spin['command'] = lambda: success.append(True) - self.spin.update() - self._click_increment_arrow() - self.spin.update() - self.assertTrue(success) - - self._click_decrement_arrow() - self.assertEqual(len(success), 2) - - # testing postcommand removal - self.spin['command'] = '' - self.spin.update_idletasks() - self._click_increment_arrow() - self._click_decrement_arrow() - self.spin.update() - self.assertEqual(len(success), 2) - - def test_to(self): - self.spin['from'] = 0 - self.spin['to'] = 5 - self.spin.set(4) - self.spin.update() - self._click_increment_arrow() # 5 - - self.assertEqual(self.spin.get(), '5') - - self._click_increment_arrow() # 5 - self.assertEqual(self.spin.get(), '5') - - def test_from(self): - self.spin['from'] = 1 - self.spin['to'] = 10 - self.spin.set(2) - self.spin.update() - self._click_decrement_arrow() # 1 - self.assertEqual(self.spin.get(), '1') - self._click_decrement_arrow() # 1 - self.assertEqual(self.spin.get(), '1') - - def test_increment(self): - self.spin['from'] = 0 - self.spin['to'] = 10 - self.spin['increment'] = 4 - self.spin.set(1) - self.spin.update() - - self._click_increment_arrow() # 5 - self.assertEqual(self.spin.get(), '5') - self.spin['increment'] = 2 - self.spin.update() - self._click_decrement_arrow() # 3 - self.assertEqual(self.spin.get(), '3') - - def test_format(self): - self.spin.set(1) - self.spin['format'] = '%10.3f' - self.spin.update() - self._click_increment_arrow() - value = self.spin.get() - - self.assertEqual(len(value), 10) - self.assertEqual(value.index('.'), 6) - - self.spin['format'] = '' - self.spin.update() - self._click_increment_arrow() - value = self.spin.get() - self.assertTrue('.' not in value) - self.assertEqual(len(value), 1) - - def test_wrap(self): - self.spin['to'] = 10 - self.spin['from'] = 1 - self.spin.set(1) - self.spin['wrap'] = True - self.spin.update() - - self._click_decrement_arrow() - self.assertEqual(self.spin.get(), '10') - - self._click_increment_arrow() - self.assertEqual(self.spin.get(), '1') - - self.spin['wrap'] = False - self.spin.update() - - self._click_decrement_arrow() - self.assertEqual(self.spin.get(), '1') - - def test_values(self): - self.assertEqual(self.spin['values'], - () if tcl_version < (8, 5) else '') - self.checkParam(self.spin, 'values', 'mon tue wed thur', - expected=('mon', 'tue', 'wed', 'thur')) - self.checkParam(self.spin, 'values', ('mon', 'tue', 'wed', 'thur')) - self.checkParam(self.spin, 'values', (42, 3.14, '', 'any string')) - self.checkParam( - self.spin, - 'values', - '', - expected='' if get_tk_patchlevel() < (8, 5, 10) else () - ) - - self.spin['values'] = ['a', 1, 'c'] - - # test incrementing / decrementing values - self.spin.set('a') - self.spin.update() - self._click_increment_arrow() - self.assertEqual(self.spin.get(), '1') - - self._click_decrement_arrow() - self.assertEqual(self.spin.get(), 'a') - - # testing values with empty string set through configure - self.spin.configure(values=[1, '', 2]) - self.assertEqual(self.spin['values'], - ('1', '', '2') if self.wantobjects else - '1 {} 2') - - # testing values with spaces - self.spin['values'] = ['a b', 'a\tb', 'a\nb'] - self.assertEqual(self.spin['values'], - ('a b', 'a\tb', 'a\nb') if self.wantobjects else - '{a b} {a\tb} {a\nb}') - - # testing values with special characters - self.spin['values'] = [r'a\tb', '"a"', '} {'] - self.assertEqual(self.spin['values'], - (r'a\tb', '"a"', '} {') if self.wantobjects else - r'a\\tb {"a"} \}\ \{') - - # testing creating spinbox with empty string in values - spin2 = ttk.Spinbox(self.root, values=[1, 2, '']) - self.assertEqual(spin2['values'], - ('1', '2', '') if self.wantobjects else '1 2 {}') - spin2.destroy() - - - at add_standard_options(StandardTtkOptionsTests) -class TreeviewTest(AbstractWidgetTest, unittest.TestCase): - OPTIONS = ( - 'class', 'columns', 'cursor', 'displaycolumns', - 'height', 'padding', 'selectmode', 'show', - 'style', 'takefocus', 'xscrollcommand', 'yscrollcommand', - ) - - def setUp(self): - super().setUp() - self.tv = self.create(padding=0) - - def create(self, **kwargs): - return ttk.Treeview(self.root, **kwargs) - - def test_columns(self): - widget = self.create() - self.checkParam(widget, 'columns', 'a b c', - expected=('a', 'b', 'c')) - self.checkParam(widget, 'columns', ('a', 'b', 'c')) - self.checkParam(widget, 'columns', (), - expected='' if get_tk_patchlevel() < (8, 5, 10) else ()) - - def test_displaycolumns(self): - widget = self.create() - widget['columns'] = ('a', 'b', 'c') - self.checkParam(widget, 'displaycolumns', 'b a c', - expected=('b', 'a', 'c')) - self.checkParam(widget, 'displaycolumns', ('b', 'a', 'c')) - self.checkParam(widget, 'displaycolumns', '#all', - expected=('#all',)) - self.checkParam(widget, 'displaycolumns', (2, 1, 0)) - self.checkInvalidParam(widget, 'displaycolumns', ('a', 'b', 'd'), - errmsg='Invalid column index d') - self.checkInvalidParam(widget, 'displaycolumns', (1, 2, 3), - errmsg='Column index 3 out of bounds') - self.checkInvalidParam(widget, 'displaycolumns', (1, -2), - errmsg='Column index -2 out of bounds') - - def test_height(self): - widget = self.create() - self.checkPixelsParam(widget, 'height', 100, -100, 0, '3c', conv=False) - self.checkPixelsParam(widget, 'height', 101.2, 102.6, conv=noconv) - - def test_selectmode(self): - widget = self.create() - self.checkEnumParam(widget, 'selectmode', - 'none', 'browse', 'extended') - - def test_show(self): - widget = self.create() - self.checkParam(widget, 'show', 'tree headings', - expected=('tree', 'headings')) - self.checkParam(widget, 'show', ('tree', 'headings')) - self.checkParam(widget, 'show', ('headings', 'tree')) - self.checkParam(widget, 'show', 'tree', expected=('tree',)) - self.checkParam(widget, 'show', 'headings', expected=('headings',)) - - def test_bbox(self): - self.tv.pack() - self.assertEqual(self.tv.bbox(''), '') - self.tv.wait_visibility() - self.tv.update() - - item_id = self.tv.insert('', 'end') - children = self.tv.get_children() - self.assertTrue(children) - - bbox = self.tv.bbox(children[0]) - self.assertIsBoundingBox(bbox) - - # compare width in bboxes - self.tv['columns'] = ['test'] - self.tv.column('test', width=50) - bbox_column0 = self.tv.bbox(children[0], 0) - root_width = self.tv.column('#0', width=None) - if not self.wantobjects: - root_width = int(root_width) - self.assertEqual(bbox_column0[0], bbox[0] + root_width) - - # verify that bbox of a closed item is the empty string - child1 = self.tv.insert(item_id, 'end') - self.assertEqual(self.tv.bbox(child1), '') - - - def test_children(self): - # no children yet, should get an empty tuple - self.assertEqual(self.tv.get_children(), ()) - - item_id = self.tv.insert('', 'end') - self.assertIsInstance(self.tv.get_children(), tuple) - self.assertEqual(self.tv.get_children()[0], item_id) - - # add item_id and child3 as children of child2 - child2 = self.tv.insert('', 'end') - child3 = self.tv.insert('', 'end') - self.tv.set_children(child2, item_id, child3) - self.assertEqual(self.tv.get_children(child2), (item_id, child3)) - - # child3 has child2 as parent, thus trying to set child2 as a children - # of child3 should result in an error - self.assertRaises(tkinter.TclError, - self.tv.set_children, child3, child2) - - # remove child2 children - self.tv.set_children(child2) - self.assertEqual(self.tv.get_children(child2), ()) - - # remove root's children - self.tv.set_children('') - self.assertEqual(self.tv.get_children(), ()) - - - def test_column(self): - # return a dict with all options/values - self.assertIsInstance(self.tv.column('#0'), dict) - # return a single value of the given option - if self.wantobjects: - self.assertIsInstance(self.tv.column('#0', width=None), int) - # set a new value for an option - self.tv.column('#0', width=10) - # testing new way to get option value - self.assertEqual(self.tv.column('#0', 'width'), - 10 if self.wantobjects else '10') - self.assertEqual(self.tv.column('#0', width=None), - 10 if self.wantobjects else '10') - # check read-only option - self.assertRaises(tkinter.TclError, self.tv.column, '#0', id='X') - - self.assertRaises(tkinter.TclError, self.tv.column, 'invalid') - invalid_kws = [ - {'unknown_option': 'some value'}, {'stretch': 'wrong'}, - {'anchor': 'wrong'}, {'width': 'wrong'}, {'minwidth': 'wrong'} - ] - for kw in invalid_kws: - self.assertRaises(tkinter.TclError, self.tv.column, '#0', - **kw) - - - def test_delete(self): - self.assertRaises(tkinter.TclError, self.tv.delete, '#0') - - item_id = self.tv.insert('', 'end') - item2 = self.tv.insert(item_id, 'end') - self.assertEqual(self.tv.get_children(), (item_id, )) - self.assertEqual(self.tv.get_children(item_id), (item2, )) - - self.tv.delete(item_id) - self.assertFalse(self.tv.get_children()) - - # reattach should fail - self.assertRaises(tkinter.TclError, - self.tv.reattach, item_id, '', 'end') - - # test multiple item delete - item1 = self.tv.insert('', 'end') - item2 = self.tv.insert('', 'end') - self.assertEqual(self.tv.get_children(), (item1, item2)) - - self.tv.delete(item1, item2) - self.assertFalse(self.tv.get_children()) - - - def test_detach_reattach(self): - item_id = self.tv.insert('', 'end') - item2 = self.tv.insert(item_id, 'end') - - # calling detach without items is valid, although it does nothing - prev = self.tv.get_children() - self.tv.detach() # this should do nothing - self.assertEqual(prev, self.tv.get_children()) - - self.assertEqual(self.tv.get_children(), (item_id, )) - self.assertEqual(self.tv.get_children(item_id), (item2, )) - - # detach item with children - self.tv.detach(item_id) - self.assertFalse(self.tv.get_children()) - - # reattach item with children - self.tv.reattach(item_id, '', 'end') - self.assertEqual(self.tv.get_children(), (item_id, )) - self.assertEqual(self.tv.get_children(item_id), (item2, )) - - # move a children to the root - self.tv.move(item2, '', 'end') - self.assertEqual(self.tv.get_children(), (item_id, item2)) - self.assertEqual(self.tv.get_children(item_id), ()) - - # bad values - self.assertRaises(tkinter.TclError, - self.tv.reattach, 'nonexistent', '', 'end') - self.assertRaises(tkinter.TclError, - self.tv.detach, 'nonexistent') - self.assertRaises(tkinter.TclError, - self.tv.reattach, item2, 'otherparent', 'end') - self.assertRaises(tkinter.TclError, - self.tv.reattach, item2, '', 'invalid') - - # multiple detach - self.tv.detach(item_id, item2) - self.assertEqual(self.tv.get_children(), ()) - self.assertEqual(self.tv.get_children(item_id), ()) - - - def test_exists(self): - self.assertEqual(self.tv.exists('something'), False) - self.assertEqual(self.tv.exists(''), True) - self.assertEqual(self.tv.exists({}), False) - - # the following will make a tk.call equivalent to - # tk.call(treeview, "exists") which should result in an error - # in the tcl interpreter since tk requires an item. - self.assertRaises(tkinter.TclError, self.tv.exists, None) - - - def test_focus(self): - # nothing is focused right now - self.assertEqual(self.tv.focus(), '') - - item1 = self.tv.insert('', 'end') - self.tv.focus(item1) - self.assertEqual(self.tv.focus(), item1) - - self.tv.delete(item1) - self.assertEqual(self.tv.focus(), '') - - # try focusing inexistent item - self.assertRaises(tkinter.TclError, self.tv.focus, 'hi') - - - def test_heading(self): - # check a dict is returned - self.assertIsInstance(self.tv.heading('#0'), dict) - - # check a value is returned - self.tv.heading('#0', text='hi') - self.assertEqual(self.tv.heading('#0', 'text'), 'hi') - self.assertEqual(self.tv.heading('#0', text=None), 'hi') - - # invalid option - self.assertRaises(tkinter.TclError, self.tv.heading, '#0', - background=None) - # invalid value - self.assertRaises(tkinter.TclError, self.tv.heading, '#0', - anchor=1) - - def test_heading_callback(self): - def simulate_heading_click(x, y): - simulate_mouse_click(self.tv, x, y) - self.tv.update() - - success = [] # no success for now - - self.tv.pack() - self.tv.wait_visibility() - self.tv.heading('#0', command=lambda: success.append(True)) - self.tv.column('#0', width=100) - self.tv.update() - - # assuming that the coords (5, 5) fall into heading #0 - simulate_heading_click(5, 5) - if not success: - self.fail("The command associated to the treeview heading wasn't " - "invoked.") - - success = [] - commands = self.tv.master._tclCommands - self.tv.heading('#0', command=str(self.tv.heading('#0', command=None))) - self.assertEqual(commands, self.tv.master._tclCommands) - simulate_heading_click(5, 5) - if not success: - self.fail("The command associated to the treeview heading wasn't " - "invoked.") - - # XXX The following raises an error in a tcl interpreter, but not in - # Python - #self.tv.heading('#0', command='I dont exist') - #simulate_heading_click(5, 5) - - - def test_index(self): - # item 'what' doesn't exist - self.assertRaises(tkinter.TclError, self.tv.index, 'what') - - self.assertEqual(self.tv.index(''), 0) - - item1 = self.tv.insert('', 'end') - item2 = self.tv.insert('', 'end') - c1 = self.tv.insert(item1, 'end') - c2 = self.tv.insert(item1, 'end') - self.assertEqual(self.tv.index(item1), 0) - self.assertEqual(self.tv.index(c1), 0) - self.assertEqual(self.tv.index(c2), 1) - self.assertEqual(self.tv.index(item2), 1) - - self.tv.move(item2, '', 0) - self.assertEqual(self.tv.index(item2), 0) - self.assertEqual(self.tv.index(item1), 1) - - # check that index still works even after its parent and siblings - # have been detached - self.tv.detach(item1) - self.assertEqual(self.tv.index(c2), 1) - self.tv.detach(c1) - self.assertEqual(self.tv.index(c2), 0) - - # but it fails after item has been deleted - self.tv.delete(item1) - self.assertRaises(tkinter.TclError, self.tv.index, c2) - - - def test_insert_item(self): - # parent 'none' doesn't exist - self.assertRaises(tkinter.TclError, self.tv.insert, 'none', 'end') - - # open values - self.assertRaises(tkinter.TclError, self.tv.insert, '', 'end', - open='') - self.assertRaises(tkinter.TclError, self.tv.insert, '', 'end', - open='please') - self.assertFalse(self.tv.delete(self.tv.insert('', 'end', open=True))) - self.assertFalse(self.tv.delete(self.tv.insert('', 'end', open=False))) - - # invalid index - self.assertRaises(tkinter.TclError, self.tv.insert, '', 'middle') - - # trying to duplicate item id is invalid - itemid = self.tv.insert('', 'end', 'first-item') - self.assertEqual(itemid, 'first-item') - self.assertRaises(tkinter.TclError, self.tv.insert, '', 'end', - 'first-item') - self.assertRaises(tkinter.TclError, self.tv.insert, '', 'end', - MockTclObj('first-item')) - - # unicode values - value = '\xe1ba' - item = self.tv.insert('', 'end', values=(value, )) - self.assertEqual(self.tv.item(item, 'values'), - (value,) if self.wantobjects else value) - self.assertEqual(self.tv.item(item, values=None), - (value,) if self.wantobjects else value) - - self.tv.item(item, values=self.root.splitlist(self.tv.item(item, values=None))) - self.assertEqual(self.tv.item(item, values=None), - (value,) if self.wantobjects else value) - - self.assertIsInstance(self.tv.item(item), dict) - - # erase item values - self.tv.item(item, values='') - self.assertFalse(self.tv.item(item, values=None)) - - # item tags - item = self.tv.insert('', 'end', tags=[1, 2, value]) - self.assertEqual(self.tv.item(item, tags=None), - ('1', '2', value) if self.wantobjects else - '1 2 %s' % value) - self.tv.item(item, tags=[]) - self.assertFalse(self.tv.item(item, tags=None)) - self.tv.item(item, tags=(1, 2)) - self.assertEqual(self.tv.item(item, tags=None), - ('1', '2') if self.wantobjects else '1 2') - - # values with spaces - item = self.tv.insert('', 'end', values=('a b c', - '%s %s' % (value, value))) - self.assertEqual(self.tv.item(item, values=None), - ('a b c', '%s %s' % (value, value)) if self.wantobjects else - '{a b c} {%s %s}' % (value, value)) - - # text - self.assertEqual(self.tv.item( - self.tv.insert('', 'end', text="Label here"), text=None), - "Label here") - self.assertEqual(self.tv.item( - self.tv.insert('', 'end', text=value), text=None), - value) - - # test for values which are not None - itemid = self.tv.insert('', 'end', 0) - self.assertEqual(itemid, '0') - itemid = self.tv.insert('', 'end', 0.0) - self.assertEqual(itemid, '0.0') - # this is because False resolves to 0 and element with 0 iid is already present - self.assertRaises(tkinter.TclError, self.tv.insert, '', 'end', False) - self.assertRaises(tkinter.TclError, self.tv.insert, '', 'end', '') - - - def test_selection(self): - self.assertRaises(TypeError, self.tv.selection, 'spam') - # item 'none' doesn't exist - self.assertRaises(tkinter.TclError, self.tv.selection_set, 'none') - self.assertRaises(tkinter.TclError, self.tv.selection_add, 'none') - self.assertRaises(tkinter.TclError, self.tv.selection_remove, 'none') - self.assertRaises(tkinter.TclError, self.tv.selection_toggle, 'none') - - item1 = self.tv.insert('', 'end') - item2 = self.tv.insert('', 'end') - c1 = self.tv.insert(item1, 'end') - c2 = self.tv.insert(item1, 'end') - c3 = self.tv.insert(item1, 'end') - self.assertEqual(self.tv.selection(), ()) - - self.tv.selection_set(c1, item2) - self.assertEqual(self.tv.selection(), (c1, item2)) - self.tv.selection_set(c2) - self.assertEqual(self.tv.selection(), (c2,)) - - self.tv.selection_add(c1, item2) - self.assertEqual(self.tv.selection(), (c1, c2, item2)) - self.tv.selection_add(item1) - self.assertEqual(self.tv.selection(), (item1, c1, c2, item2)) - self.tv.selection_add() - self.assertEqual(self.tv.selection(), (item1, c1, c2, item2)) - - self.tv.selection_remove(item1, c3) - self.assertEqual(self.tv.selection(), (c1, c2, item2)) - self.tv.selection_remove(c2) - self.assertEqual(self.tv.selection(), (c1, item2)) - self.tv.selection_remove() - self.assertEqual(self.tv.selection(), (c1, item2)) - - self.tv.selection_toggle(c1, c3) - self.assertEqual(self.tv.selection(), (c3, item2)) - self.tv.selection_toggle(item2) - self.assertEqual(self.tv.selection(), (c3,)) - self.tv.selection_toggle() - self.assertEqual(self.tv.selection(), (c3,)) - - self.tv.insert('', 'end', id='with spaces') - self.tv.selection_set('with spaces') - self.assertEqual(self.tv.selection(), ('with spaces',)) - - self.tv.insert('', 'end', id='{brace') - self.tv.selection_set('{brace') - self.assertEqual(self.tv.selection(), ('{brace',)) - - self.tv.insert('', 'end', id='unicode\u20ac') - self.tv.selection_set('unicode\u20ac') - self.assertEqual(self.tv.selection(), ('unicode\u20ac',)) - - self.tv.insert('', 'end', id=b'bytes\xe2\x82\xac') - self.tv.selection_set(b'bytes\xe2\x82\xac') - self.assertEqual(self.tv.selection(), ('bytes\xe2\x82\xac',)) - - self.tv.selection_set() - self.assertEqual(self.tv.selection(), ()) - - # Old interface - self.tv.selection_set((c1, item2)) - self.assertEqual(self.tv.selection(), (c1, item2)) - self.tv.selection_add((c1, item1)) - self.assertEqual(self.tv.selection(), (item1, c1, item2)) - self.tv.selection_remove((item1, c3)) - self.assertEqual(self.tv.selection(), (c1, item2)) - self.tv.selection_toggle((c1, c3)) - self.assertEqual(self.tv.selection(), (c3, item2)) - - - def test_set(self): - self.tv['columns'] = ['A', 'B'] - item = self.tv.insert('', 'end', values=['a', 'b']) - self.assertEqual(self.tv.set(item), {'A': 'a', 'B': 'b'}) - - self.tv.set(item, 'B', 'a') - self.assertEqual(self.tv.item(item, values=None), - ('a', 'a') if self.wantobjects else 'a a') - - self.tv['columns'] = ['B'] - self.assertEqual(self.tv.set(item), {'B': 'a'}) - - self.tv.set(item, 'B', 'b') - self.assertEqual(self.tv.set(item, column='B'), 'b') - self.assertEqual(self.tv.item(item, values=None), - ('b', 'a') if self.wantobjects else 'b a') - - self.tv.set(item, 'B', 123) - self.assertEqual(self.tv.set(item, 'B'), - 123 if self.wantobjects else '123') - self.assertEqual(self.tv.item(item, values=None), - (123, 'a') if self.wantobjects else '123 a') - self.assertEqual(self.tv.set(item), - {'B': 123} if self.wantobjects else {'B': '123'}) - - # inexistent column - self.assertRaises(tkinter.TclError, self.tv.set, item, 'A') - self.assertRaises(tkinter.TclError, self.tv.set, item, 'A', 'b') - - # inexistent item - self.assertRaises(tkinter.TclError, self.tv.set, 'notme') - - - def test_tag_bind(self): - events = [] - item1 = self.tv.insert('', 'end', tags=['call']) - item2 = self.tv.insert('', 'end', tags=['call']) - self.tv.tag_bind('call', '', - lambda evt: events.append(1)) - self.tv.tag_bind('call', '', - lambda evt: events.append(2)) - - self.tv.pack() - self.tv.wait_visibility() - self.tv.update() - - pos_y = set() - found = set() - for i in range(0, 100, 10): - if len(found) == 2: # item1 and item2 already found - break - item_id = self.tv.identify_row(i) - if item_id and item_id not in found: - pos_y.add(i) - found.add(item_id) - - self.assertEqual(len(pos_y), 2) # item1 and item2 y pos - for y in pos_y: - simulate_mouse_click(self.tv, 0, y) - - # by now there should be 4 things in the events list, since each - # item had a bind for two events that were simulated above - self.assertEqual(len(events), 4) - for evt in zip(events[::2], events[1::2]): - self.assertEqual(evt, (1, 2)) - - - def test_tag_configure(self): - # Just testing parameter passing for now - self.assertRaises(TypeError, self.tv.tag_configure) - self.assertRaises(tkinter.TclError, self.tv.tag_configure, - 'test', sky='blue') - self.tv.tag_configure('test', foreground='blue') - self.assertEqual(str(self.tv.tag_configure('test', 'foreground')), - 'blue') - self.assertEqual(str(self.tv.tag_configure('test', foreground=None)), - 'blue') - self.assertIsInstance(self.tv.tag_configure('test'), dict) - - def test_tag_has(self): - item1 = self.tv.insert('', 'end', text='Item 1', tags=['tag1']) - item2 = self.tv.insert('', 'end', text='Item 2', tags=['tag2']) - self.assertRaises(TypeError, self.tv.tag_has) - self.assertRaises(TclError, self.tv.tag_has, 'tag1', 'non-existing') - self.assertTrue(self.tv.tag_has('tag1', item1)) - self.assertFalse(self.tv.tag_has('tag1', item2)) - self.assertFalse(self.tv.tag_has('tag2', item1)) - self.assertTrue(self.tv.tag_has('tag2', item2)) - self.assertFalse(self.tv.tag_has('tag3', item1)) - self.assertFalse(self.tv.tag_has('tag3', item2)) - self.assertEqual(self.tv.tag_has('tag1'), (item1,)) - self.assertEqual(self.tv.tag_has('tag2'), (item2,)) - self.assertEqual(self.tv.tag_has('tag3'), ()) - - - at add_standard_options(StandardTtkOptionsTests) -class SeparatorTest(AbstractWidgetTest, unittest.TestCase): - OPTIONS = ( - 'class', 'cursor', 'orient', 'style', 'takefocus', - # 'state'? - ) - default_orient = 'horizontal' - - def create(self, **kwargs): - return ttk.Separator(self.root, **kwargs) - - - at add_standard_options(StandardTtkOptionsTests) -class SizegripTest(AbstractWidgetTest, unittest.TestCase): - OPTIONS = ( - 'class', 'cursor', 'style', 'takefocus', - # 'state'? - ) - - def create(self, **kwargs): - return ttk.Sizegrip(self.root, **kwargs) - -tests_gui = ( - ButtonTest, CheckbuttonTest, ComboboxTest, EntryTest, - FrameTest, LabelFrameTest, LabelTest, MenubuttonTest, - NotebookTest, PanedWindowTest, ProgressbarTest, - RadiobuttonTest, ScaleTest, ScrollbarTest, SeparatorTest, - SizegripTest, SpinboxTest, TreeviewTest, WidgetTest, - ) - -if __name__ == "__main__": - unittest.main() diff --git a/Lib/tkinter/ttk.py b/Lib/tkinter/ttk.py deleted file mode 100644 index 573544dd84a3..000000000000 --- a/Lib/tkinter/ttk.py +++ /dev/null @@ -1,1660 +0,0 @@ -"""Ttk wrapper. - -This module provides classes to allow using Tk themed widget set. - -Ttk is based on a revised and enhanced version of -TIP #48 (http://tip.tcl.tk/48) specified style engine. - -Its basic idea is to separate, to the extent possible, the code -implementing a widget's behavior from the code implementing its -appearance. Widget class bindings are primarily responsible for -maintaining the widget state and invoking callbacks, all aspects -of the widgets appearance lies at Themes. -""" - -__version__ = "0.3.1" - -__author__ = "Guilherme Polo " - -__all__ = ["Button", "Checkbutton", "Combobox", "Entry", "Frame", "Label", - "Labelframe", "LabelFrame", "Menubutton", "Notebook", "Panedwindow", - "PanedWindow", "Progressbar", "Radiobutton", "Scale", "Scrollbar", - "Separator", "Sizegrip", "Spinbox", "Style", "Treeview", - # Extensions - "LabeledScale", "OptionMenu", - # functions - "tclobjs_to_py", "setup_master"] - -import tkinter -from tkinter import _flatten, _join, _stringify, _splitdict - -# Verify if Tk is new enough to not need the Tile package -_REQUIRE_TILE = True if tkinter.TkVersion < 8.5 else False - -def _load_tile(master): - if _REQUIRE_TILE: - import os - tilelib = os.environ.get('TILE_LIBRARY') - if tilelib: - # append custom tile path to the list of directories that - # Tcl uses when attempting to resolve packages with the package - # command - master.tk.eval( - 'global auto_path; ' - 'lappend auto_path {%s}' % tilelib) - - master.tk.eval('package require tile') # TclError may be raised here - master._tile_loaded = True - -def _format_optvalue(value, script=False): - """Internal function.""" - if script: - # if caller passes a Tcl script to tk.call, all the values need to - # be grouped into words (arguments to a command in Tcl dialect) - value = _stringify(value) - elif isinstance(value, (list, tuple)): - value = _join(value) - return value - -def _format_optdict(optdict, script=False, ignore=None): - """Formats optdict to a tuple to pass it to tk.call. - - E.g. (script=False): - {'foreground': 'blue', 'padding': [1, 2, 3, 4]} returns: - ('-foreground', 'blue', '-padding', '1 2 3 4')""" - - opts = [] - for opt, value in optdict.items(): - if not ignore or opt not in ignore: - opts.append("-%s" % opt) - if value is not None: - opts.append(_format_optvalue(value, script)) - - return _flatten(opts) - -def _mapdict_values(items): - # each value in mapdict is expected to be a sequence, where each item - # is another sequence containing a state (or several) and a value - # E.g. (script=False): - # [('active', 'selected', 'grey'), ('focus', [1, 2, 3, 4])] - # returns: - # ['active selected', 'grey', 'focus', [1, 2, 3, 4]] - opt_val = [] - for *state, val in items: - # hacks for backward compatibility - state[0] # raise IndexError if empty - if len(state) == 1: - # if it is empty (something that evaluates to False), then - # format it to Tcl code to denote the "normal" state - state = state[0] or '' - else: - # group multiple states - state = ' '.join(state) # raise TypeError if not str - opt_val.append(state) - if val is not None: - opt_val.append(val) - return opt_val - -def _format_mapdict(mapdict, script=False): - """Formats mapdict to pass it to tk.call. - - E.g. (script=False): - {'expand': [('active', 'selected', 'grey'), ('focus', [1, 2, 3, 4])]} - - returns: - - ('-expand', '{active selected} grey focus {1, 2, 3, 4}')""" - - opts = [] - for opt, value in mapdict.items(): - opts.extend(("-%s" % opt, - _format_optvalue(_mapdict_values(value), script))) - - return _flatten(opts) - -def _format_elemcreate(etype, script=False, *args, **kw): - """Formats args and kw according to the given element factory etype.""" - spec = None - opts = () - if etype in ("image", "vsapi"): - if etype == "image": # define an element based on an image - # first arg should be the default image name - iname = args[0] - # next args, if any, are statespec/value pairs which is almost - # a mapdict, but we just need the value - imagespec = _join(_mapdict_values(args[1:])) - spec = "%s %s" % (iname, imagespec) - - else: - # define an element whose visual appearance is drawn using the - # Microsoft Visual Styles API which is responsible for the - # themed styles on Windows XP and Vista. - # Availability: Tk 8.6, Windows XP and Vista. - class_name, part_id = args[:2] - statemap = _join(_mapdict_values(args[2:])) - spec = "%s %s %s" % (class_name, part_id, statemap) - - opts = _format_optdict(kw, script) - - elif etype == "from": # clone an element - # it expects a themename and optionally an element to clone from, - # otherwise it will clone {} (empty element) - spec = args[0] # theme name - if len(args) > 1: # elementfrom specified - opts = (_format_optvalue(args[1], script),) - - if script: - spec = '{%s}' % spec - opts = ' '.join(opts) - - return spec, opts - -def _format_layoutlist(layout, indent=0, indent_size=2): - """Formats a layout list so we can pass the result to ttk::style - layout and ttk::style settings. Note that the layout doesn't have to - be a list necessarily. - - E.g.: - [("Menubutton.background", None), - ("Menubutton.button", {"children": - [("Menubutton.focus", {"children": - [("Menubutton.padding", {"children": - [("Menubutton.label", {"side": "left", "expand": 1})] - })] - })] - }), - ("Menubutton.indicator", {"side": "right"}) - ] - - returns: - - Menubutton.background - Menubutton.button -children { - Menubutton.focus -children { - Menubutton.padding -children { - Menubutton.label -side left -expand 1 - } - } - } - Menubutton.indicator -side right""" - script = [] - - for layout_elem in layout: - elem, opts = layout_elem - opts = opts or {} - fopts = ' '.join(_format_optdict(opts, True, ("children",))) - head = "%s%s%s" % (' ' * indent, elem, (" %s" % fopts) if fopts else '') - - if "children" in opts: - script.append(head + " -children {") - indent += indent_size - newscript, indent = _format_layoutlist(opts['children'], indent, - indent_size) - script.append(newscript) - indent -= indent_size - script.append('%s}' % (' ' * indent)) - else: - script.append(head) - - return '\n'.join(script), indent - -def _script_from_settings(settings): - """Returns an appropriate script, based on settings, according to - theme_settings definition to be used by theme_settings and - theme_create.""" - script = [] - # a script will be generated according to settings passed, which - # will then be evaluated by Tcl - for name, opts in settings.items(): - # will format specific keys according to Tcl code - if opts.get('configure'): # format 'configure' - s = ' '.join(_format_optdict(opts['configure'], True)) - script.append("ttk::style configure %s %s;" % (name, s)) - - if opts.get('map'): # format 'map' - s = ' '.join(_format_mapdict(opts['map'], True)) - script.append("ttk::style map %s %s;" % (name, s)) - - if 'layout' in opts: # format 'layout' which may be empty - if not opts['layout']: - s = 'null' # could be any other word, but this one makes sense - else: - s, _ = _format_layoutlist(opts['layout']) - script.append("ttk::style layout %s {\n%s\n}" % (name, s)) - - if opts.get('element create'): # format 'element create' - eopts = opts['element create'] - etype = eopts[0] - - # find where args end, and where kwargs start - argc = 1 # etype was the first one - while argc < len(eopts) and not hasattr(eopts[argc], 'items'): - argc += 1 - - elemargs = eopts[1:argc] - elemkw = eopts[argc] if argc < len(eopts) and eopts[argc] else {} - spec, opts = _format_elemcreate(etype, True, *elemargs, **elemkw) - - script.append("ttk::style element create %s %s %s %s" % ( - name, etype, spec, opts)) - - return '\n'.join(script) - -def _list_from_statespec(stuple): - """Construct a list from the given statespec tuple according to the - accepted statespec accepted by _format_mapdict.""" - nval = [] - for val in stuple: - typename = getattr(val, 'typename', None) - if typename is None: - nval.append(val) - else: # this is a Tcl object - val = str(val) - if typename == 'StateSpec': - val = val.split() - nval.append(val) - - it = iter(nval) - return [_flatten(spec) for spec in zip(it, it)] - -def _list_from_layouttuple(tk, ltuple): - """Construct a list from the tuple returned by ttk::layout, this is - somewhat the reverse of _format_layoutlist.""" - ltuple = tk.splitlist(ltuple) - res = [] - - indx = 0 - while indx < len(ltuple): - name = ltuple[indx] - opts = {} - res.append((name, opts)) - indx += 1 - - while indx < len(ltuple): # grab name's options - opt, val = ltuple[indx:indx + 2] - if not opt.startswith('-'): # found next name - break - - opt = opt[1:] # remove the '-' from the option - indx += 2 - - if opt == 'children': - val = _list_from_layouttuple(tk, val) - - opts[opt] = val - - return res - -def _val_or_dict(tk, options, *args): - """Format options then call Tk command with args and options and return - the appropriate result. - - If no option is specified, a dict is returned. If an option is - specified with the None value, the value for that option is returned. - Otherwise, the function just sets the passed options and the caller - shouldn't be expecting a return value anyway.""" - options = _format_optdict(options) - res = tk.call(*(args + options)) - - if len(options) % 2: # option specified without a value, return its value - return res - - return _splitdict(tk, res, conv=_tclobj_to_py) - -def _convert_stringval(value): - """Converts a value to, hopefully, a more appropriate Python object.""" - value = str(value) - try: - value = int(value) - except (ValueError, TypeError): - pass - - return value - -def _to_number(x): - if isinstance(x, str): - if '.' in x: - x = float(x) - else: - x = int(x) - return x - -def _tclobj_to_py(val): - """Return value converted from Tcl object to Python object.""" - if val and hasattr(val, '__len__') and not isinstance(val, str): - if getattr(val[0], 'typename', None) == 'StateSpec': - val = _list_from_statespec(val) - else: - val = list(map(_convert_stringval, val)) - - elif hasattr(val, 'typename'): # some other (single) Tcl object - val = _convert_stringval(val) - - return val - -def tclobjs_to_py(adict): - """Returns adict with its values converted from Tcl objects to Python - objects.""" - for opt, val in adict.items(): - adict[opt] = _tclobj_to_py(val) - - return adict - -def setup_master(master=None): - """If master is not None, itself is returned. If master is None, - the default master is returned if there is one, otherwise a new - master is created and returned. - - If it is not allowed to use the default root and master is None, - RuntimeError is raised.""" - if master is None: - if tkinter._support_default_root: - master = tkinter._default_root or tkinter.Tk() - else: - raise RuntimeError( - "No master specified and tkinter is " - "configured to not support default root") - return master - - -class Style(object): - """Manipulate style database.""" - - _name = "ttk::style" - - def __init__(self, master=None): - master = setup_master(master) - - if not getattr(master, '_tile_loaded', False): - # Load tile now, if needed - _load_tile(master) - - self.master = master - self.tk = self.master.tk - - - def configure(self, style, query_opt=None, **kw): - """Query or sets the default value of the specified option(s) in - style. - - Each key in kw is an option and each value is either a string or - a sequence identifying the value for that option.""" - if query_opt is not None: - kw[query_opt] = None - result = _val_or_dict(self.tk, kw, self._name, "configure", style) - if result or query_opt: - return result - - - def map(self, style, query_opt=None, **kw): - """Query or sets dynamic values of the specified option(s) in - style. - - Each key in kw is an option and each value should be a list or a - tuple (usually) containing statespecs grouped in tuples, or list, - or something else of your preference. A statespec is compound of - one or more states and then a value.""" - if query_opt is not None: - return _list_from_statespec(self.tk.splitlist( - self.tk.call(self._name, "map", style, '-%s' % query_opt))) - - return _splitdict( - self.tk, - self.tk.call(self._name, "map", style, *_format_mapdict(kw)), - conv=_tclobj_to_py) - - - def lookup(self, style, option, state=None, default=None): - """Returns the value specified for option in style. - - If state is specified it is expected to be a sequence of one - or more states. If the default argument is set, it is used as - a fallback value in case no specification for option is found.""" - state = ' '.join(state) if state else '' - - return self.tk.call(self._name, "lookup", style, '-%s' % option, - state, default) - - - def layout(self, style, layoutspec=None): - """Define the widget layout for given style. If layoutspec is - omitted, return the layout specification for given style. - - layoutspec is expected to be a list or an object different than - None that evaluates to False if you want to "turn off" that style. - If it is a list (or tuple, or something else), each item should be - a tuple where the first item is the layout name and the second item - should have the format described below: - - LAYOUTS - - A layout can contain the value None, if takes no options, or - a dict of options specifying how to arrange the element. - The layout mechanism uses a simplified version of the pack - geometry manager: given an initial cavity, each element is - allocated a parcel. Valid options/values are: - - side: whichside - Specifies which side of the cavity to place the - element; one of top, right, bottom or left. If - omitted, the element occupies the entire cavity. - - sticky: nswe - Specifies where the element is placed inside its - allocated parcel. - - children: [sublayout... ] - Specifies a list of elements to place inside the - element. Each element is a tuple (or other sequence) - where the first item is the layout name, and the other - is a LAYOUT.""" - lspec = None - if layoutspec: - lspec = _format_layoutlist(layoutspec)[0] - elif layoutspec is not None: # will disable the layout ({}, '', etc) - lspec = "null" # could be any other word, but this may make sense - # when calling layout(style) later - - return _list_from_layouttuple(self.tk, - self.tk.call(self._name, "layout", style, lspec)) - - - def element_create(self, elementname, etype, *args, **kw): - """Create a new element in the current theme of given etype.""" - spec, opts = _format_elemcreate(etype, False, *args, **kw) - self.tk.call(self._name, "element", "create", elementname, etype, - spec, *opts) - - - def element_names(self): - """Returns the list of elements defined in the current theme.""" - return tuple(n.lstrip('-') for n in self.tk.splitlist( - self.tk.call(self._name, "element", "names"))) - - - def element_options(self, elementname): - """Return the list of elementname's options.""" - return tuple(o.lstrip('-') for o in self.tk.splitlist( - self.tk.call(self._name, "element", "options", elementname))) - - - def theme_create(self, themename, parent=None, settings=None): - """Creates a new theme. - - It is an error if themename already exists. If parent is - specified, the new theme will inherit styles, elements and - layouts from the specified parent theme. If settings are present, - they are expected to have the same syntax used for theme_settings.""" - script = _script_from_settings(settings) if settings else '' - - if parent: - self.tk.call(self._name, "theme", "create", themename, - "-parent", parent, "-settings", script) - else: - self.tk.call(self._name, "theme", "create", themename, - "-settings", script) - - - def theme_settings(self, themename, settings): - """Temporarily sets the current theme to themename, apply specified - settings and then restore the previous theme. - - Each key in settings is a style and each value may contain the - keys 'configure', 'map', 'layout' and 'element create' and they - are expected to have the same format as specified by the methods - configure, map, layout and element_create respectively.""" - script = _script_from_settings(settings) - self.tk.call(self._name, "theme", "settings", themename, script) - - - def theme_names(self): - """Returns a list of all known themes.""" - return self.tk.splitlist(self.tk.call(self._name, "theme", "names")) - - - def theme_use(self, themename=None): - """If themename is None, returns the theme in use, otherwise, set - the current theme to themename, refreshes all widgets and emits - a <> event.""" - if themename is None: - # Starting on Tk 8.6, checking this global is no longer needed - # since it allows doing self.tk.call(self._name, "theme", "use") - return self.tk.eval("return $ttk::currentTheme") - - # using "ttk::setTheme" instead of "ttk::style theme use" causes - # the variable currentTheme to be updated, also, ttk::setTheme calls - # "ttk::style theme use" in order to change theme. - self.tk.call("ttk::setTheme", themename) - - -class Widget(tkinter.Widget): - """Base class for Tk themed widgets.""" - - def __init__(self, master, widgetname, kw=None): - """Constructs a Ttk Widget with the parent master. - - STANDARD OPTIONS - - class, cursor, takefocus, style - - SCROLLABLE WIDGET OPTIONS - - xscrollcommand, yscrollcommand - - LABEL WIDGET OPTIONS - - text, textvariable, underline, image, compound, width - - WIDGET STATES - - active, disabled, focus, pressed, selected, background, - readonly, alternate, invalid - """ - master = setup_master(master) - if not getattr(master, '_tile_loaded', False): - # Load tile now, if needed - _load_tile(master) - tkinter.Widget.__init__(self, master, widgetname, kw=kw) - - - def identify(self, x, y): - """Returns the name of the element at position x, y, or the empty - string if the point does not lie within any element. - - x and y are pixel coordinates relative to the widget.""" - return self.tk.call(self._w, "identify", x, y) - - - def instate(self, statespec, callback=None, *args, **kw): - """Test the widget's state. - - If callback is not specified, returns True if the widget state - matches statespec and False otherwise. If callback is specified, - then it will be invoked with *args, **kw if the widget state - matches statespec. statespec is expected to be a sequence.""" - ret = self.tk.getboolean( - self.tk.call(self._w, "instate", ' '.join(statespec))) - if ret and callback: - return callback(*args, **kw) - - return ret - - - def state(self, statespec=None): - """Modify or inquire widget state. - - Widget state is returned if statespec is None, otherwise it is - set according to the statespec flags and then a new state spec - is returned indicating which flags were changed. statespec is - expected to be a sequence.""" - if statespec is not None: - statespec = ' '.join(statespec) - - return self.tk.splitlist(str(self.tk.call(self._w, "state", statespec))) - - -class Button(Widget): - """Ttk Button widget, displays a textual label and/or image, and - evaluates a command when pressed.""" - - def __init__(self, master=None, **kw): - """Construct a Ttk Button widget with the parent master. - - STANDARD OPTIONS - - class, compound, cursor, image, state, style, takefocus, - text, textvariable, underline, width - - WIDGET-SPECIFIC OPTIONS - - command, default, width - """ - Widget.__init__(self, master, "ttk::button", kw) - - - def invoke(self): - """Invokes the command associated with the button.""" - return self.tk.call(self._w, "invoke") - - -class Checkbutton(Widget): - """Ttk Checkbutton widget which is either in on- or off-state.""" - - def __init__(self, master=None, **kw): - """Construct a Ttk Checkbutton widget with the parent master. - - STANDARD OPTIONS - - class, compound, cursor, image, state, style, takefocus, - text, textvariable, underline, width - - WIDGET-SPECIFIC OPTIONS - - command, offvalue, onvalue, variable - """ - Widget.__init__(self, master, "ttk::checkbutton", kw) - - - def invoke(self): - """Toggles between the selected and deselected states and - invokes the associated command. If the widget is currently - selected, sets the option variable to the offvalue option - and deselects the widget; otherwise, sets the option variable - to the option onvalue. - - Returns the result of the associated command.""" - return self.tk.call(self._w, "invoke") - - -class Entry(Widget, tkinter.Entry): - """Ttk Entry widget displays a one-line text string and allows that - string to be edited by the user.""" - - def __init__(self, master=None, widget=None, **kw): - """Constructs a Ttk Entry widget with the parent master. - - STANDARD OPTIONS - - class, cursor, style, takefocus, xscrollcommand - - WIDGET-SPECIFIC OPTIONS - - exportselection, invalidcommand, justify, show, state, - textvariable, validate, validatecommand, width - - VALIDATION MODES - - none, key, focus, focusin, focusout, all - """ - Widget.__init__(self, master, widget or "ttk::entry", kw) - - - def bbox(self, index): - """Return a tuple of (x, y, width, height) which describes the - bounding box of the character given by index.""" - return self._getints(self.tk.call(self._w, "bbox", index)) - - - def identify(self, x, y): - """Returns the name of the element at position x, y, or the - empty string if the coordinates are outside the window.""" - return self.tk.call(self._w, "identify", x, y) - - - def validate(self): - """Force revalidation, independent of the conditions specified - by the validate option. Returns False if validation fails, True - if it succeeds. Sets or clears the invalid state accordingly.""" - return self.tk.getboolean(self.tk.call(self._w, "validate")) - - -class Combobox(Entry): - """Ttk Combobox widget combines a text field with a pop-down list of - values.""" - - def __init__(self, master=None, **kw): - """Construct a Ttk Combobox widget with the parent master. - - STANDARD OPTIONS - - class, cursor, style, takefocus - - WIDGET-SPECIFIC OPTIONS - - exportselection, justify, height, postcommand, state, - textvariable, values, width - """ - Entry.__init__(self, master, "ttk::combobox", **kw) - - - def current(self, newindex=None): - """If newindex is supplied, sets the combobox value to the - element at position newindex in the list of values. Otherwise, - returns the index of the current value in the list of values - or -1 if the current value does not appear in the list.""" - if newindex is None: - return self.tk.getint(self.tk.call(self._w, "current")) - return self.tk.call(self._w, "current", newindex) - - - def set(self, value): - """Sets the value of the combobox to value.""" - self.tk.call(self._w, "set", value) - - -class Frame(Widget): - """Ttk Frame widget is a container, used to group other widgets - together.""" - - def __init__(self, master=None, **kw): - """Construct a Ttk Frame with parent master. - - STANDARD OPTIONS - - class, cursor, style, takefocus - - WIDGET-SPECIFIC OPTIONS - - borderwidth, relief, padding, width, height - """ - Widget.__init__(self, master, "ttk::frame", kw) - - -class Label(Widget): - """Ttk Label widget displays a textual label and/or image.""" - - def __init__(self, master=None, **kw): - """Construct a Ttk Label with parent master. - - STANDARD OPTIONS - - class, compound, cursor, image, style, takefocus, text, - textvariable, underline, width - - WIDGET-SPECIFIC OPTIONS - - anchor, background, font, foreground, justify, padding, - relief, text, wraplength - """ - Widget.__init__(self, master, "ttk::label", kw) - - -class Labelframe(Widget): - """Ttk Labelframe widget is a container used to group other widgets - together. It has an optional label, which may be a plain text string - or another widget.""" - - def __init__(self, master=None, **kw): - """Construct a Ttk Labelframe with parent master. - - STANDARD OPTIONS - - class, cursor, style, takefocus - - WIDGET-SPECIFIC OPTIONS - labelanchor, text, underline, padding, labelwidget, width, - height - """ - Widget.__init__(self, master, "ttk::labelframe", kw) - -LabelFrame = Labelframe # tkinter name compatibility - - -class Menubutton(Widget): - """Ttk Menubutton widget displays a textual label and/or image, and - displays a menu when pressed.""" - - def __init__(self, master=None, **kw): - """Construct a Ttk Menubutton with parent master. - - STANDARD OPTIONS - - class, compound, cursor, image, state, style, takefocus, - text, textvariable, underline, width - - WIDGET-SPECIFIC OPTIONS - - direction, menu - """ - Widget.__init__(self, master, "ttk::menubutton", kw) - - -class Notebook(Widget): - """Ttk Notebook widget manages a collection of windows and displays - a single one at a time. Each child window is associated with a tab, - which the user may select to change the currently-displayed window.""" - - def __init__(self, master=None, **kw): - """Construct a Ttk Notebook with parent master. - - STANDARD OPTIONS - - class, cursor, style, takefocus - - WIDGET-SPECIFIC OPTIONS - - height, padding, width - - TAB OPTIONS - - state, sticky, padding, text, image, compound, underline - - TAB IDENTIFIERS (tab_id) - - The tab_id argument found in several methods may take any of - the following forms: - - * An integer between zero and the number of tabs - * The name of a child window - * A positional specification of the form "@x,y", which - defines the tab - * The string "current", which identifies the - currently-selected tab - * The string "end", which returns the number of tabs (only - valid for method index) - """ - Widget.__init__(self, master, "ttk::notebook", kw) - - - def add(self, child, **kw): - """Adds a new tab to the notebook. - - If window is currently managed by the notebook but hidden, it is - restored to its previous position.""" - self.tk.call(self._w, "add", child, *(_format_optdict(kw))) - - - def forget(self, tab_id): - """Removes the tab specified by tab_id, unmaps and unmanages the - associated window.""" - self.tk.call(self._w, "forget", tab_id) - - - def hide(self, tab_id): - """Hides the tab specified by tab_id. - - The tab will not be displayed, but the associated window remains - managed by the notebook and its configuration remembered. Hidden - tabs may be restored with the add command.""" - self.tk.call(self._w, "hide", tab_id) - - - def identify(self, x, y): - """Returns the name of the tab element at position x, y, or the - empty string if none.""" - return self.tk.call(self._w, "identify", x, y) - - - def index(self, tab_id): - """Returns the numeric index of the tab specified by tab_id, or - the total number of tabs if tab_id is the string "end".""" - return self.tk.getint(self.tk.call(self._w, "index", tab_id)) - - - def insert(self, pos, child, **kw): - """Inserts a pane at the specified position. - - pos is either the string end, an integer index, or the name of - a managed child. If child is already managed by the notebook, - moves it to the specified position.""" - self.tk.call(self._w, "insert", pos, child, *(_format_optdict(kw))) - - - def select(self, tab_id=None): - """Selects the specified tab. - - The associated child window will be displayed, and the - previously-selected window (if different) is unmapped. If tab_id - is omitted, returns the widget name of the currently selected - pane.""" - return self.tk.call(self._w, "select", tab_id) - - - def tab(self, tab_id, option=None, **kw): - """Query or modify the options of the specific tab_id. - - If kw is not given, returns a dict of the tab option values. If option - is specified, returns the value of that option. Otherwise, sets the - options to the corresponding values.""" - if option is not None: - kw[option] = None - return _val_or_dict(self.tk, kw, self._w, "tab", tab_id) - - - def tabs(self): - """Returns a list of windows managed by the notebook.""" - return self.tk.splitlist(self.tk.call(self._w, "tabs") or ()) - - - def enable_traversal(self): - """Enable keyboard traversal for a toplevel window containing - this notebook. - - This will extend the bindings for the toplevel window containing - this notebook as follows: - - Control-Tab: selects the tab following the currently selected - one - - Shift-Control-Tab: selects the tab preceding the currently - selected one - - Alt-K: where K is the mnemonic (underlined) character of any - tab, will select that tab. - - Multiple notebooks in a single toplevel may be enabled for - traversal, including nested notebooks. However, notebook traversal - only works properly if all panes are direct children of the - notebook.""" - # The only, and good, difference I see is about mnemonics, which works - # after calling this method. Control-Tab and Shift-Control-Tab always - # works (here at least). - self.tk.call("ttk::notebook::enableTraversal", self._w) - - -class Panedwindow(Widget, tkinter.PanedWindow): - """Ttk Panedwindow widget displays a number of subwindows, stacked - either vertically or horizontally.""" - - def __init__(self, master=None, **kw): - """Construct a Ttk Panedwindow with parent master. - - STANDARD OPTIONS - - class, cursor, style, takefocus - - WIDGET-SPECIFIC OPTIONS - - orient, width, height - - PANE OPTIONS - - weight - """ - Widget.__init__(self, master, "ttk::panedwindow", kw) - - - forget = tkinter.PanedWindow.forget # overrides Pack.forget - - - def insert(self, pos, child, **kw): - """Inserts a pane at the specified positions. - - pos is either the string end, and integer index, or the name - of a child. If child is already managed by the paned window, - moves it to the specified position.""" - self.tk.call(self._w, "insert", pos, child, *(_format_optdict(kw))) - - - def pane(self, pane, option=None, **kw): - """Query or modify the options of the specified pane. - - pane is either an integer index or the name of a managed subwindow. - If kw is not given, returns a dict of the pane option values. If - option is specified then the value for that option is returned. - Otherwise, sets the options to the corresponding values.""" - if option is not None: - kw[option] = None - return _val_or_dict(self.tk, kw, self._w, "pane", pane) - - - def sashpos(self, index, newpos=None): - """If newpos is specified, sets the position of sash number index. - - May adjust the positions of adjacent sashes to ensure that - positions are monotonically increasing. Sash positions are further - constrained to be between 0 and the total size of the widget. - - Returns the new position of sash number index.""" - return self.tk.getint(self.tk.call(self._w, "sashpos", index, newpos)) - -PanedWindow = Panedwindow # tkinter name compatibility - - -class Progressbar(Widget): - """Ttk Progressbar widget shows the status of a long-running - operation. They can operate in two modes: determinate mode shows the - amount completed relative to the total amount of work to be done, and - indeterminate mode provides an animated display to let the user know - that something is happening.""" - - def __init__(self, master=None, **kw): - """Construct a Ttk Progressbar with parent master. - - STANDARD OPTIONS - - class, cursor, style, takefocus - - WIDGET-SPECIFIC OPTIONS - - orient, length, mode, maximum, value, variable, phase - """ - Widget.__init__(self, master, "ttk::progressbar", kw) - - - def start(self, interval=None): - """Begin autoincrement mode: schedules a recurring timer event - that calls method step every interval milliseconds. - - interval defaults to 50 milliseconds (20 steps/second) if omitted.""" - self.tk.call(self._w, "start", interval) - - - def step(self, amount=None): - """Increments the value option by amount. - - amount defaults to 1.0 if omitted.""" - self.tk.call(self._w, "step", amount) - - - def stop(self): - """Stop autoincrement mode: cancels any recurring timer event - initiated by start.""" - self.tk.call(self._w, "stop") - - -class Radiobutton(Widget): - """Ttk Radiobutton widgets are used in groups to show or change a - set of mutually-exclusive options.""" - - def __init__(self, master=None, **kw): - """Construct a Ttk Radiobutton with parent master. - - STANDARD OPTIONS - - class, compound, cursor, image, state, style, takefocus, - text, textvariable, underline, width - - WIDGET-SPECIFIC OPTIONS - - command, value, variable - """ - Widget.__init__(self, master, "ttk::radiobutton", kw) - - - def invoke(self): - """Sets the option variable to the option value, selects the - widget, and invokes the associated command. - - Returns the result of the command, or an empty string if - no command is specified.""" - return self.tk.call(self._w, "invoke") - - -class Scale(Widget, tkinter.Scale): - """Ttk Scale widget is typically used to control the numeric value of - a linked variable that varies uniformly over some range.""" - - def __init__(self, master=None, **kw): - """Construct a Ttk Scale with parent master. - - STANDARD OPTIONS - - class, cursor, style, takefocus - - WIDGET-SPECIFIC OPTIONS - - command, from, length, orient, to, value, variable - """ - Widget.__init__(self, master, "ttk::scale", kw) - - - def configure(self, cnf=None, **kw): - """Modify or query scale options. - - Setting a value for any of the "from", "from_" or "to" options - generates a <> event.""" - if cnf: - kw.update(cnf) - Widget.configure(self, **kw) - if any(['from' in kw, 'from_' in kw, 'to' in kw]): - self.event_generate('<>') - - - def get(self, x=None, y=None): - """Get the current value of the value option, or the value - corresponding to the coordinates x, y if they are specified. - - x and y are pixel coordinates relative to the scale widget - origin.""" - return self.tk.call(self._w, 'get', x, y) - - -class Scrollbar(Widget, tkinter.Scrollbar): - """Ttk Scrollbar controls the viewport of a scrollable widget.""" - - def __init__(self, master=None, **kw): - """Construct a Ttk Scrollbar with parent master. - - STANDARD OPTIONS - - class, cursor, style, takefocus - - WIDGET-SPECIFIC OPTIONS - - command, orient - """ - Widget.__init__(self, master, "ttk::scrollbar", kw) - - -class Separator(Widget): - """Ttk Separator widget displays a horizontal or vertical separator - bar.""" - - def __init__(self, master=None, **kw): - """Construct a Ttk Separator with parent master. - - STANDARD OPTIONS - - class, cursor, style, takefocus - - WIDGET-SPECIFIC OPTIONS - - orient - """ - Widget.__init__(self, master, "ttk::separator", kw) - - -class Sizegrip(Widget): - """Ttk Sizegrip allows the user to resize the containing toplevel - window by pressing and dragging the grip.""" - - def __init__(self, master=None, **kw): - """Construct a Ttk Sizegrip with parent master. - - STANDARD OPTIONS - - class, cursor, state, style, takefocus - """ - Widget.__init__(self, master, "ttk::sizegrip", kw) - - -class Spinbox(Entry): - """Ttk Spinbox is an Entry with increment and decrement arrows - - It is commonly used for number entry or to select from a list of - string values. - """ - - def __init__(self, master=None, **kw): - """Construct a Ttk Spinbox widget with the parent master. - - STANDARD OPTIONS - - class, cursor, style, takefocus, validate, - validatecommand, xscrollcommand, invalidcommand - - WIDGET-SPECIFIC OPTIONS - - to, from_, increment, values, wrap, format, command - """ - Entry.__init__(self, master, "ttk::spinbox", **kw) - - - def set(self, value): - """Sets the value of the Spinbox to value.""" - self.tk.call(self._w, "set", value) - - -class Treeview(Widget, tkinter.XView, tkinter.YView): - """Ttk Treeview widget displays a hierarchical collection of items. - - Each item has a textual label, an optional image, and an optional list - of data values. The data values are displayed in successive columns - after the tree label.""" - - def __init__(self, master=None, **kw): - """Construct a Ttk Treeview with parent master. - - STANDARD OPTIONS - - class, cursor, style, takefocus, xscrollcommand, - yscrollcommand - - WIDGET-SPECIFIC OPTIONS - - columns, displaycolumns, height, padding, selectmode, show - - ITEM OPTIONS - - text, image, values, open, tags - - TAG OPTIONS - - foreground, background, font, image - """ - Widget.__init__(self, master, "ttk::treeview", kw) - - - def bbox(self, item, column=None): - """Returns the bounding box (relative to the treeview widget's - window) of the specified item in the form x y width height. - - If column is specified, returns the bounding box of that cell. - If the item is not visible (i.e., if it is a descendant of a - closed item or is scrolled offscreen), returns an empty string.""" - return self._getints(self.tk.call(self._w, "bbox", item, column)) or '' - - - def get_children(self, item=None): - """Returns a tuple of children belonging to item. - - If item is not specified, returns root children.""" - return self.tk.splitlist( - self.tk.call(self._w, "children", item or '') or ()) - - - def set_children(self, item, *newchildren): - """Replaces item's child with newchildren. - - Children present in item that are not present in newchildren - are detached from tree. No items in newchildren may be an - ancestor of item.""" - self.tk.call(self._w, "children", item, newchildren) - - - def column(self, column, option=None, **kw): - """Query or modify the options for the specified column. - - If kw is not given, returns a dict of the column option values. If - option is specified then the value for that option is returned. - Otherwise, sets the options to the corresponding values.""" - if option is not None: - kw[option] = None - return _val_or_dict(self.tk, kw, self._w, "column", column) - - - def delete(self, *items): - """Delete all specified items and all their descendants. The root - item may not be deleted.""" - self.tk.call(self._w, "delete", items) - - - def detach(self, *items): - """Unlinks all of the specified items from the tree. - - The items and all of their descendants are still present, and may - be reinserted at another point in the tree, but will not be - displayed. The root item may not be detached.""" - self.tk.call(self._w, "detach", items) - - - def exists(self, item): - """Returns True if the specified item is present in the tree, - False otherwise.""" - return self.tk.getboolean(self.tk.call(self._w, "exists", item)) - - - def focus(self, item=None): - """If item is specified, sets the focus item to item. Otherwise, - returns the current focus item, or '' if there is none.""" - return self.tk.call(self._w, "focus", item) - - - def heading(self, column, option=None, **kw): - """Query or modify the heading options for the specified column. - - If kw is not given, returns a dict of the heading option values. If - option is specified then the value for that option is returned. - Otherwise, sets the options to the corresponding values. - - Valid options/values are: - text: text - The text to display in the column heading - image: image_name - Specifies an image to display to the right of the column - heading - anchor: anchor - Specifies how the heading text should be aligned. One of - the standard Tk anchor values - command: callback - A callback to be invoked when the heading label is - pressed. - - To configure the tree column heading, call this with column = "#0" """ - cmd = kw.get('command') - if cmd and not isinstance(cmd, str): - # callback not registered yet, do it now - kw['command'] = self.master.register(cmd, self._substitute) - - if option is not None: - kw[option] = None - - return _val_or_dict(self.tk, kw, self._w, 'heading', column) - - - def identify(self, component, x, y): - """Returns a description of the specified component under the - point given by x and y, or the empty string if no such component - is present at that position.""" - return self.tk.call(self._w, "identify", component, x, y) - - - def identify_row(self, y): - """Returns the item ID of the item at position y.""" - return self.identify("row", 0, y) - - - def identify_column(self, x): - """Returns the data column identifier of the cell at position x. - - The tree column has ID #0.""" - return self.identify("column", x, 0) - - - def identify_region(self, x, y): - """Returns one of: - - heading: Tree heading area. - separator: Space between two columns headings; - tree: The tree area. - cell: A data cell. - - * Availability: Tk 8.6""" - return self.identify("region", x, y) - - - def identify_element(self, x, y): - """Returns the element at position x, y. - - * Availability: Tk 8.6""" - return self.identify("element", x, y) - - - def index(self, item): - """Returns the integer index of item within its parent's list - of children.""" - return self.tk.getint(self.tk.call(self._w, "index", item)) - - - def insert(self, parent, index, iid=None, **kw): - """Creates a new item and return the item identifier of the newly - created item. - - parent is the item ID of the parent item, or the empty string - to create a new top-level item. index is an integer, or the value - end, specifying where in the list of parent's children to insert - the new item. If index is less than or equal to zero, the new node - is inserted at the beginning, if index is greater than or equal to - the current number of children, it is inserted at the end. If iid - is specified, it is used as the item identifier, iid must not - already exist in the tree. Otherwise, a new unique identifier - is generated.""" - opts = _format_optdict(kw) - if iid is not None: - res = self.tk.call(self._w, "insert", parent, index, - "-id", iid, *opts) - else: - res = self.tk.call(self._w, "insert", parent, index, *opts) - - return res - - - def item(self, item, option=None, **kw): - """Query or modify the options for the specified item. - - If no options are given, a dict with options/values for the item - is returned. If option is specified then the value for that option - is returned. Otherwise, sets the options to the corresponding - values as given by kw.""" - if option is not None: - kw[option] = None - return _val_or_dict(self.tk, kw, self._w, "item", item) - - - def move(self, item, parent, index): - """Moves item to position index in parent's list of children. - - It is illegal to move an item under one of its descendants. If - index is less than or equal to zero, item is moved to the - beginning, if greater than or equal to the number of children, - it is moved to the end. If item was detached it is reattached.""" - self.tk.call(self._w, "move", item, parent, index) - - reattach = move # A sensible method name for reattaching detached items - - - def next(self, item): - """Returns the identifier of item's next sibling, or '' if item - is the last child of its parent.""" - return self.tk.call(self._w, "next", item) - - - def parent(self, item): - """Returns the ID of the parent of item, or '' if item is at the - top level of the hierarchy.""" - return self.tk.call(self._w, "parent", item) - - - def prev(self, item): - """Returns the identifier of item's previous sibling, or '' if - item is the first child of its parent.""" - return self.tk.call(self._w, "prev", item) - - - def see(self, item): - """Ensure that item is visible. - - Sets all of item's ancestors open option to True, and scrolls - the widget if necessary so that item is within the visible - portion of the tree.""" - self.tk.call(self._w, "see", item) - - - def selection(self): - """Returns the tuple of selected items.""" - return self.tk.splitlist(self.tk.call(self._w, "selection")) - - - def _selection(self, selop, items): - if len(items) == 1 and isinstance(items[0], (tuple, list)): - items = items[0] - - self.tk.call(self._w, "selection", selop, items) - - - def selection_set(self, *items): - """The specified items becomes the new selection.""" - self._selection("set", items) - - - def selection_add(self, *items): - """Add all of the specified items to the selection.""" - self._selection("add", items) - - - def selection_remove(self, *items): - """Remove all of the specified items from the selection.""" - self._selection("remove", items) - - - def selection_toggle(self, *items): - """Toggle the selection state of each specified item.""" - self._selection("toggle", items) - - - def set(self, item, column=None, value=None): - """Query or set the value of given item. - - With one argument, return a dictionary of column/value pairs - for the specified item. With two arguments, return the current - value of the specified column. With three arguments, set the - value of given column in given item to the specified value.""" - res = self.tk.call(self._w, "set", item, column, value) - if column is None and value is None: - return _splitdict(self.tk, res, - cut_minus=False, conv=_tclobj_to_py) - else: - return res - - - def tag_bind(self, tagname, sequence=None, callback=None): - """Bind a callback for the given event sequence to the tag tagname. - When an event is delivered to an item, the callbacks for each - of the item's tags option are called.""" - self._bind((self._w, "tag", "bind", tagname), sequence, callback, add=0) - - - def tag_configure(self, tagname, option=None, **kw): - """Query or modify the options for the specified tagname. - - If kw is not given, returns a dict of the option settings for tagname. - If option is specified, returns the value for that option for the - specified tagname. Otherwise, sets the options to the corresponding - values for the given tagname.""" - if option is not None: - kw[option] = None - return _val_or_dict(self.tk, kw, self._w, "tag", "configure", - tagname) - - - def tag_has(self, tagname, item=None): - """If item is specified, returns 1 or 0 depending on whether the - specified item has the given tagname. Otherwise, returns a list of - all items which have the specified tag. - - * Availability: Tk 8.6""" - if item is None: - return self.tk.splitlist( - self.tk.call(self._w, "tag", "has", tagname)) - else: - return self.tk.getboolean( - self.tk.call(self._w, "tag", "has", tagname, item)) - - -# Extensions - -class LabeledScale(Frame): - """A Ttk Scale widget with a Ttk Label widget indicating its - current value. - - The Ttk Scale can be accessed through instance.scale, and Ttk Label - can be accessed through instance.label""" - - def __init__(self, master=None, variable=None, from_=0, to=10, **kw): - """Construct a horizontal LabeledScale with parent master, a - variable to be associated with the Ttk Scale widget and its range. - If variable is not specified, a tkinter.IntVar is created. - - WIDGET-SPECIFIC OPTIONS - - compound: 'top' or 'bottom' - Specifies how to display the label relative to the scale. - Defaults to 'top'. - """ - self._label_top = kw.pop('compound', 'top') == 'top' - - Frame.__init__(self, master, **kw) - self._variable = variable or tkinter.IntVar(master) - self._variable.set(from_) - self._last_valid = from_ - - self.label = Label(self) - self.scale = Scale(self, variable=self._variable, from_=from_, to=to) - self.scale.bind('<>', self._adjust) - - # position scale and label according to the compound option - scale_side = 'bottom' if self._label_top else 'top' - label_side = 'top' if scale_side == 'bottom' else 'bottom' - self.scale.pack(side=scale_side, fill='x') - tmp = Label(self).pack(side=label_side) # place holder - self.label.place(anchor='n' if label_side == 'top' else 's') - - # update the label as scale or variable changes - self.__tracecb = self._variable.trace_variable('w', self._adjust) - self.bind('', self._adjust) - self.bind('', self._adjust) - - - def destroy(self): - """Destroy this widget and possibly its associated variable.""" - try: - self._variable.trace_vdelete('w', self.__tracecb) - except AttributeError: - pass - else: - del self._variable - super().destroy() - self.label = None - self.scale = None - - - def _adjust(self, *args): - """Adjust the label position according to the scale.""" - def adjust_label(): - self.update_idletasks() # "force" scale redraw - - x, y = self.scale.coords() - if self._label_top: - y = self.scale.winfo_y() - self.label.winfo_reqheight() - else: - y = self.scale.winfo_reqheight() + self.label.winfo_reqheight() - - self.label.place_configure(x=x, y=y) - - from_ = _to_number(self.scale['from']) - to = _to_number(self.scale['to']) - if to < from_: - from_, to = to, from_ - newval = self._variable.get() - if not from_ <= newval <= to: - # value outside range, set value back to the last valid one - self.value = self._last_valid - return - - self._last_valid = newval - self.label['text'] = newval - self.after_idle(adjust_label) - - @property - def value(self): - """Return current scale value.""" - return self._variable.get() - - @value.setter - def value(self, val): - """Set new scale value.""" - self._variable.set(val) - - -class OptionMenu(Menubutton): - """Themed OptionMenu, based after tkinter's OptionMenu, which allows - the user to select a value from a menu.""" - - def __init__(self, master, variable, default=None, *values, **kwargs): - """Construct a themed OptionMenu widget with master as the parent, - the resource textvariable set to variable, the initially selected - value specified by the default parameter, the menu values given by - *values and additional keywords. - - WIDGET-SPECIFIC OPTIONS - - style: stylename - Menubutton style. - direction: 'above', 'below', 'left', 'right', or 'flush' - Menubutton direction. - command: callback - A callback that will be invoked after selecting an item. - """ - kw = {'textvariable': variable, 'style': kwargs.pop('style', None), - 'direction': kwargs.pop('direction', None)} - Menubutton.__init__(self, master, **kw) - self['menu'] = tkinter.Menu(self, tearoff=False) - - self._variable = variable - self._callback = kwargs.pop('command', None) - if kwargs: - raise tkinter.TclError('unknown option -%s' % ( - next(iter(kwargs.keys())))) - - self.set_menu(default, *values) - - - def __getitem__(self, item): - if item == 'menu': - return self.nametowidget(Menubutton.__getitem__(self, item)) - - return Menubutton.__getitem__(self, item) - - - def set_menu(self, default=None, *values): - """Build a new menu of radiobuttons with *values and optionally - a default value.""" - menu = self['menu'] - menu.delete(0, 'end') - for val in values: - menu.add_radiobutton(label=val, - command=tkinter._setit(self._variable, val, self._callback), - variable=self._variable) - - if default: - self._variable.set(default) - - - def destroy(self): - """Destroy this widget and its associated variable.""" - try: - del self._variable - except AttributeError: - pass - super().destroy() diff --git a/Misc/NEWS.d/next/Library/2018-05-08-08-03-34.bpo-33096.0hsFhL.rst b/Misc/NEWS.d/next/Library/2018-05-08-08-03-34.bpo-33096.0hsFhL.rst new file mode 100644 index 000000000000..2fd23c73e3b6 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-08-08-03-34.bpo-33096.0hsFhL.rst @@ -0,0 +1 @@ +Removed unintentionally backported from Python 3 Tkinter files. From solipsis at pitrou.net Tue May 8 05:13:57 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Tue, 08 May 2018 09:13:57 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=31 Message-ID: <20180508091357.1.5310E3541535AA19@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_collections leaked [-7, 1, 7] memory blocks, sum=1 test_functools leaked [0, 3, 1] memory blocks, sum=4 test_logging leaked [0, 0, 26] memory blocks, sum=26 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflog5R2DMx', '--timeout', '7200'] From webhook-mailer at python.org Tue May 8 08:45:20 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Tue, 08 May 2018 12:45:20 -0000 Subject: [Python-checkins] bpo-33144: Fix choosing random.Random._randbelow implementation. (GH-6563) Message-ID: https://github.com/python/cpython/commit/ec1622d56c80d15740f7f8459c9a79fd55f5d3c7 commit: ec1622d56c80d15740f7f8459c9a79fd55f5d3c7 branch: master author: Serhiy Storchaka committer: GitHub date: 2018-05-08T15:45:15+03:00 summary: bpo-33144: Fix choosing random.Random._randbelow implementation. (GH-6563) random() takes precedence over getrandbits() if defined later in the class tree. files: M Lib/random.py M Lib/test/test_random.py diff --git a/Lib/random.py b/Lib/random.py index 0ed5511e9f63..1e0dcc87ed4a 100644 --- a/Lib/random.py +++ b/Lib/random.py @@ -102,18 +102,16 @@ def __init_subclass__(cls, **kwargs): ranges. """ - if (cls.random is _random.Random.random) or ( - cls.getrandbits is not _random.Random.getrandbits): - # The original random() builtin method has not been overridden - # or a new getrandbits() was supplied. - # The subclass can use the getrandbits-dependent implementation - # of _randbelow(). - cls._randbelow = cls._randbelow_with_getrandbits - else: - # There's an overridden random() method but no new getrandbits(), - # so the subclass can only use the getrandbits-independent - # implementation of _randbelow(). - cls._randbelow = cls._randbelow_without_getrandbits + for c in cls.__mro__: + if '_randbelow' in c.__dict__: + # just inherit it + break + if 'getrandbits' in c.__dict__: + cls._randbelow = cls._randbelow_with_getrandbits + break + if 'random' in c.__dict__: + cls._randbelow = cls._randbelow_without_getrandbits + break def seed(self, a=None, version=2): """Initialize internal state from hashable object. diff --git a/Lib/test/test_random.py b/Lib/test/test_random.py index d91908b03d02..e7ef68ba3d26 100644 --- a/Lib/test/test_random.py +++ b/Lib/test/test_random.py @@ -5,7 +5,6 @@ import time import pickle import warnings -import logging from functools import partial from math import log, exp, pi, fsum, sin, factorial from test import support @@ -940,6 +939,7 @@ def test_betavariate_return_zero(self, gammavariate_mock): gammavariate_mock.return_value = 0.0 self.assertEqual(0.0, random.betavariate(2.71828, 3.14159)) + class TestRandomSubclassing(unittest.TestCase): def test_random_subclass_with_kwargs(self): # SF bug #1486663 -- this used to erroneously raise a TypeError @@ -958,30 +958,80 @@ def test_subclasses_overriding_methods(self): # randrange class SubClass1(random.Random): def random(self): - return super().random() + called.add('SubClass1.random') + return random.Random.random(self) def getrandbits(self, n): - logging.getLogger('getrandbits').info('used getrandbits') - return super().getrandbits(n) - with self.assertLogs('getrandbits'): - SubClass1().randrange(42) + called.add('SubClass1.getrandbits') + return random.Random.getrandbits(self, n) + called = set() + SubClass1().randrange(42) + self.assertEqual(called, {'SubClass1.getrandbits'}) # subclass providing only random => can only use random for randrange class SubClass2(random.Random): def random(self): - logging.getLogger('random').info('used random') - return super().random() - with self.assertLogs('random'): - SubClass2().randrange(42) + called.add('SubClass2.random') + return random.Random.random(self) + called = set() + SubClass2().randrange(42) + self.assertEqual(called, {'SubClass2.random'}) # subclass defining getrandbits to complement its inherited random # => can now rely on getrandbits for randrange again class SubClass3(SubClass2): def getrandbits(self, n): - logging.getLogger('getrandbits').info('used getrandbits') - return super().getrandbits(n) - with self.assertLogs('getrandbits'): - SubClass3().randrange(42) + called.add('SubClass3.getrandbits') + return random.Random.getrandbits(self, n) + called = set() + SubClass3().randrange(42) + self.assertEqual(called, {'SubClass3.getrandbits'}) + + # subclass providing only random and inherited getrandbits + # => random takes precedence + class SubClass4(SubClass3): + def random(self): + called.add('SubClass4.random') + return random.Random.random(self) + called = set() + SubClass4().randrange(42) + self.assertEqual(called, {'SubClass4.random'}) + + # Following subclasses don't define random or getrandbits directly, + # but inherit them from classes which are not subclasses of Random + class Mixin1: + def random(self): + called.add('Mixin1.random') + return random.Random.random(self) + class Mixin2: + def getrandbits(self, n): + called.add('Mixin2.getrandbits') + return random.Random.getrandbits(self, n) + + class SubClass5(Mixin1, random.Random): + pass + called = set() + SubClass5().randrange(42) + self.assertEqual(called, {'Mixin1.random'}) + + class SubClass6(Mixin2, random.Random): + pass + called = set() + SubClass6().randrange(42) + self.assertEqual(called, {'Mixin2.getrandbits'}) + + class SubClass7(Mixin1, Mixin2, random.Random): + pass + called = set() + SubClass7().randrange(42) + self.assertEqual(called, {'Mixin1.random'}) + + class SubClass8(Mixin2, Mixin1, random.Random): + pass + called = set() + SubClass8().randrange(42) + self.assertEqual(called, {'Mixin2.getrandbits'}) + class TestModule(unittest.TestCase): def testMagicConstants(self): From webhook-mailer at python.org Tue May 8 14:38:51 2018 From: webhook-mailer at python.org (Ivan Levkivskyi) Date: Tue, 08 May 2018 18:38:51 -0000 Subject: [Python-checkins] bpo-32717: Document PEP 560 (GH-6726) Message-ID: https://github.com/python/cpython/commit/bd5f96581bf23f6d05fc106996428a8043b6b084 commit: bd5f96581bf23f6d05fc106996428a8043b6b084 branch: master author: Ivan Levkivskyi committer: GitHub date: 2018-05-08T19:38:41+01:00 summary: bpo-32717: Document PEP 560 (GH-6726) files: M Doc/library/types.rst M Doc/reference/datamodel.rst M Doc/whatsnew/3.7.rst diff --git a/Doc/library/types.rst b/Doc/library/types.rst index 67cd4d702ad4..e17070022cd2 100644 --- a/Doc/library/types.rst +++ b/Doc/library/types.rst @@ -59,7 +59,7 @@ Dynamic Type Creation The default value for the ``namespace`` element of the returned tuple has changed. Now an insertion-order-preserving mapping is - used when the metaclass does not have a ``__prepare__`` method, + used when the metaclass does not have a ``__prepare__`` method. .. seealso:: @@ -69,6 +69,23 @@ Dynamic Type Creation :pep:`3115` - Metaclasses in Python 3000 Introduced the ``__prepare__`` namespace hook +.. function:: resolve_bases(bases) + + Resolve MRO entries dynamically as specified by :pep:`560`. + + This function looks for items in *bases* that are not instances of + :class:`type`, and returns a tuple where each such object that has + an ``__mro_entries__`` method is replaced with an unpacked result of + calling this method. If a *bases* item is an instance of :class:`type`, + or it doesn't have an ``__mro_entries__`` method, then it is included in + the return tuple unchanged. + + .. versionadded:: 3.7 + +.. seealso:: + + :pep:`560` - Core support for typing module and generic types + Standard Interpreter Types -------------------------- diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 1e93ef4594a9..b4a0dbf95ec0 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1857,11 +1857,27 @@ passed through to all metaclass operations described below. When a class definition is executed, the following steps occur: +* MRO entries are resolved * the appropriate metaclass is determined * the class namespace is prepared * the class body is executed * the class object is created + +Resolving MRO entries +^^^^^^^^^^^^^^^^^^^^^ + +If a base that appears in class definition is not an instance of :class:`type`, +then an ``__mro_entries__`` method is searched on it. If found, it is called +with the original bases tuple. This method must return a tuple of classes that +will be used instead of this base. The tuple may be empty, in such case +the original base is ignored. + +.. seealso:: + + :pep:`560` - Core support for typing module and generic types + + Determining the appropriate metaclass ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. index:: @@ -2061,6 +2077,27 @@ case the instance is itself a class. module) to the language. +Emulating generic types +----------------------- + +One can implement the generic class syntax as specified by :pep:`484` +(for example ``List[int]``) by defining a special method + +.. classmethod:: object.__class_getitem__(cls, key) + + Return an object representing the specialization of a generic class + by type arguments found in *key*. + +This method is looked up on the class object itself, and when defined in +the class body, this method is implicitly a class method. Note, this +mechanism is primarily reserved for use with static type hints, other usage +is discouraged. + +.. seealso:: + + :pep:`560` - Core support for typing module and generic types + + .. _callable-types: Emulating callable objects diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 408fed4572fa..cc762736a0c7 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -356,6 +356,25 @@ with the correct context in async/await code. PEP written and implemented by Yury Selivanov +PEP 560: Core support for typing module and generic types +--------------------------------------------------------- + +Initially :pep:`484` was designed in such way that it would not introduce *any* +changes to the core CPython interpreter. Now type hints and the :mod:`typing` +module are extensively used by the community, so this restriction is removed. +The PEP introduces two special methods :meth:`__class_getitem__` and +``__mro_entries__``, these methods are now used by most classes and special +constructs in :mod:`typing`. As a result, the speed of various operations +with types increased up to 7 times, the generic types can be used without +metaclass conflicts, and several long standing bugs in :mod:`typing` module are +fixed. + +.. seealso:: + + :pep:`560` -- Core support for typing module and generic types + PEP written and implemented by Ivan Levkivskyi + + New Development Mode: -X dev ---------------------------- From webhook-mailer at python.org Tue May 8 14:52:45 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 08 May 2018 18:52:45 -0000 Subject: [Python-checkins] bpo-32717: Document PEP 560 (GH-6726) Message-ID: https://github.com/python/cpython/commit/101d0d585f99a3b8c8d070b9d4dea15fa3daff62 commit: 101d0d585f99a3b8c8d070b9d4dea15fa3daff62 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-05-08T11:52:36-07:00 summary: bpo-32717: Document PEP 560 (GH-6726) (cherry picked from commit bd5f96581bf23f6d05fc106996428a8043b6b084) Co-authored-by: Ivan Levkivskyi files: M Doc/library/types.rst M Doc/reference/datamodel.rst M Doc/whatsnew/3.7.rst diff --git a/Doc/library/types.rst b/Doc/library/types.rst index 67cd4d702ad4..e17070022cd2 100644 --- a/Doc/library/types.rst +++ b/Doc/library/types.rst @@ -59,7 +59,7 @@ Dynamic Type Creation The default value for the ``namespace`` element of the returned tuple has changed. Now an insertion-order-preserving mapping is - used when the metaclass does not have a ``__prepare__`` method, + used when the metaclass does not have a ``__prepare__`` method. .. seealso:: @@ -69,6 +69,23 @@ Dynamic Type Creation :pep:`3115` - Metaclasses in Python 3000 Introduced the ``__prepare__`` namespace hook +.. function:: resolve_bases(bases) + + Resolve MRO entries dynamically as specified by :pep:`560`. + + This function looks for items in *bases* that are not instances of + :class:`type`, and returns a tuple where each such object that has + an ``__mro_entries__`` method is replaced with an unpacked result of + calling this method. If a *bases* item is an instance of :class:`type`, + or it doesn't have an ``__mro_entries__`` method, then it is included in + the return tuple unchanged. + + .. versionadded:: 3.7 + +.. seealso:: + + :pep:`560` - Core support for typing module and generic types + Standard Interpreter Types -------------------------- diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 1e93ef4594a9..b4a0dbf95ec0 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1857,11 +1857,27 @@ passed through to all metaclass operations described below. When a class definition is executed, the following steps occur: +* MRO entries are resolved * the appropriate metaclass is determined * the class namespace is prepared * the class body is executed * the class object is created + +Resolving MRO entries +^^^^^^^^^^^^^^^^^^^^^ + +If a base that appears in class definition is not an instance of :class:`type`, +then an ``__mro_entries__`` method is searched on it. If found, it is called +with the original bases tuple. This method must return a tuple of classes that +will be used instead of this base. The tuple may be empty, in such case +the original base is ignored. + +.. seealso:: + + :pep:`560` - Core support for typing module and generic types + + Determining the appropriate metaclass ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. index:: @@ -2061,6 +2077,27 @@ case the instance is itself a class. module) to the language. +Emulating generic types +----------------------- + +One can implement the generic class syntax as specified by :pep:`484` +(for example ``List[int]``) by defining a special method + +.. classmethod:: object.__class_getitem__(cls, key) + + Return an object representing the specialization of a generic class + by type arguments found in *key*. + +This method is looked up on the class object itself, and when defined in +the class body, this method is implicitly a class method. Note, this +mechanism is primarily reserved for use with static type hints, other usage +is discouraged. + +.. seealso:: + + :pep:`560` - Core support for typing module and generic types + + .. _callable-types: Emulating callable objects diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index afa0bc2b6071..8425731b842c 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -356,6 +356,25 @@ with the correct context in async/await code. PEP written and implemented by Yury Selivanov +PEP 560: Core support for typing module and generic types +--------------------------------------------------------- + +Initially :pep:`484` was designed in such way that it would not introduce *any* +changes to the core CPython interpreter. Now type hints and the :mod:`typing` +module are extensively used by the community, so this restriction is removed. +The PEP introduces two special methods :meth:`__class_getitem__` and +``__mro_entries__``, these methods are now used by most classes and special +constructs in :mod:`typing`. As a result, the speed of various operations +with types increased up to 7 times, the generic types can be used without +metaclass conflicts, and several long standing bugs in :mod:`typing` module are +fixed. + +.. seealso:: + + :pep:`560` -- Core support for typing module and generic types + PEP written and implemented by Ivan Levkivskyi + + New Development Mode: -X dev ---------------------------- From webhook-mailer at python.org Tue May 8 18:00:29 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Tue, 08 May 2018 22:00:29 -0000 Subject: [Python-checkins] Fix typo in __mul__ and __rmul__ docstring (GH-6674) Message-ID: https://github.com/python/cpython/commit/0904f766e116c269675317e11368a4d29eef0bc6 commit: 0904f766e116c269675317e11368a4d29eef0bc6 branch: master author: Grant Jenks committer: Serhiy Storchaka date: 2018-05-09T01:00:19+03:00 summary: Fix typo in __mul__ and __rmul__ docstring (GH-6674) files: M Objects/typeobject.c diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 1dd534866b4d..a7a9d7bf9fc3 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -6938,9 +6938,9 @@ static slotdef slotdefs[] = { SQSLOT("__add__", sq_concat, NULL, wrap_binaryfunc, "__add__($self, value, /)\n--\n\nReturn self+value."), SQSLOT("__mul__", sq_repeat, NULL, wrap_indexargfunc, - "__mul__($self, value, /)\n--\n\nReturn self*value.n"), + "__mul__($self, value, /)\n--\n\nReturn self*value."), SQSLOT("__rmul__", sq_repeat, NULL, wrap_indexargfunc, - "__rmul__($self, value, /)\n--\n\nReturn self*value."), + "__rmul__($self, value, /)\n--\n\nReturn value*self."), SQSLOT("__getitem__", sq_item, slot_sq_item, wrap_sq_item, "__getitem__($self, key, /)\n--\n\nReturn self[key]."), SQSLOT("__setitem__", sq_ass_item, slot_sq_ass_item, wrap_sq_setitem, From webhook-mailer at python.org Tue May 8 21:23:50 2018 From: webhook-mailer at python.org (Ivan Levkivskyi) Date: Wed, 09 May 2018 01:23:50 -0000 Subject: [Python-checkins] bpo-28556: Minor fixes for typing module (GH-6732) Message-ID: https://github.com/python/cpython/commit/43d12a6bd82bd09ac189069fe1eb40cdbc10a58c commit: 43d12a6bd82bd09ac189069fe1eb40cdbc10a58c branch: master author: Ivan Levkivskyi committer: GitHub date: 2018-05-09T02:23:46+01:00 summary: bpo-28556: Minor fixes for typing module (GH-6732) This also fixes https://bugs.python.org/issue33420 files: A Misc/NEWS.d/next/Library/2018-05-08-16-43-42.bpo-28556._xr5mp.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 390fe60fcc10..46bab5eba6db 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -1324,6 +1324,72 @@ class D(C): with self.assertRaises(Exception): D[T] + def test_new_with_args(self): + + class A(Generic[T]): + pass + + class B: + def __new__(cls, arg): + # call object + obj = super().__new__(cls) + obj.arg = arg + return obj + + # mro: C, A, Generic, B, object + class C(A, B): + pass + + c = C('foo') + self.assertEqual(c.arg, 'foo') + + def test_new_with_args2(self): + + class A: + def __init__(self, arg): + self.from_a = arg + # call object + super().__init__() + + # mro: C, Generic, A, object + class C(Generic[T], A): + def __init__(self, arg): + self.from_c = arg + # call Generic + super().__init__(arg) + + c = C('foo') + self.assertEqual(c.from_a, 'foo') + self.assertEqual(c.from_c, 'foo') + + def test_new_no_args(self): + + class A(Generic[T]): + pass + + class B: + def __new__(cls): + # call object + obj = super().__new__(cls) + obj.from_b = 'b' + return obj + + # mro: C, A, Generic, B, object + class C(A, B): + def __init__(self, arg): + self.arg = arg + + def __new__(cls, arg): + # call A + obj = super().__new__(cls) + obj.from_c = 'c' + return obj + + c = C('foo') + self.assertEqual(c.arg, 'foo') + self.assertEqual(c.from_b, 'b') + self.assertEqual(c.from_c, 'c') + class ClassVarTests(BaseTestCase): @@ -1737,6 +1803,8 @@ def test_get_type_hints_classes(self): self.assertEqual(gth(HasForeignBaseClass), {'some_xrepr': XRepr, 'other_a': mod_generics_cache.A, 'some_b': mod_generics_cache.B}) + self.assertEqual(gth(XRepr.__new__), + {'x': int, 'y': int}) self.assertEqual(gth(mod_generics_cache.B), {'my_inner_a1': mod_generics_cache.B.A, 'my_inner_a2': mod_generics_cache.B.A, diff --git a/Lib/typing.py b/Lib/typing.py index 83296073b914..89b73db15837 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -607,7 +607,8 @@ def __reduce__(self): # * __parameters__ is a tuple of unique free type parameters of a generic # type, for example, Dict[T, T].__parameters__ == (T,); # * __origin__ keeps a reference to a type that was subscripted, -# e.g., Union[T, int].__origin__ == Union; +# e.g., Union[T, int].__origin__ == Union, or the non-generic version of +# the type. # * __args__ is a tuple of all arguments used in subscripting, # e.g., Dict[T, int].__args__ == (T, int). @@ -835,7 +836,11 @@ def __new__(cls, *args, **kwds): if cls is Generic: raise TypeError("Type Generic cannot be instantiated; " "it can be used only as a base class") - return super().__new__(cls) + if super().__new__ is object.__new__: + obj = super().__new__(cls) + else: + obj = super().__new__(cls, *args, **kwds) + return obj @_tp_cache def __class_getitem__(cls, params): @@ -1385,6 +1390,7 @@ def __new__(cls, typename, bases, ns): "follow default field(s) {default_names}" .format(field_name=field_name, default_names=', '.join(defaults_dict.keys()))) + nm_tpl.__new__.__annotations__ = collections.OrderedDict(types) nm_tpl.__new__.__defaults__ = tuple(defaults) nm_tpl._field_defaults = defaults_dict # update from user namespace without overriding special namedtuple attributes diff --git a/Misc/NEWS.d/next/Library/2018-05-08-16-43-42.bpo-28556._xr5mp.rst b/Misc/NEWS.d/next/Library/2018-05-08-16-43-42.bpo-28556._xr5mp.rst new file mode 100644 index 000000000000..8ed4658211fb --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-08-16-43-42.bpo-28556._xr5mp.rst @@ -0,0 +1,3 @@ +Minor fixes in typing module: add annotations to ``NamedTuple.__new__``, +pass ``*args`` and ``**kwds`` in ``Generic.__new__``. Original PRs by +Paulius ?arka and Chad Dombrova. From lp_benchmark_robot at intel.com Tue May 8 21:29:47 2018 From: lp_benchmark_robot at intel.com (lp_benchmark_robot at intel.com) Date: Tue, 8 May 2018 18:29:47 -0700 Subject: [Python-checkins] [1 up, 64 flat] Results for Python (master branch) 2018-05-08 Message-ID: Results for project python/master, build date: 2018-05-08 03:03:02-07:00. - commit: d54cfb1 - previous commit: a3f19c3 - revision date: 2018-05-08 07:48:50+03:00 - environment: Broadwell-EP - cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores, stepping 1, LLC 55 MB - mem: 128 GB - os: Ubuntu 16.04.2 LTS - kernel: 4.4.0-62-generic x86_64 GNU/Linux Baseline results were generated using release v3.6.0, with hash 5c4568a from 2016-12-22 23:38:47+00:00. +-----+------------------------+--------+------------+------------+------------+ | | |relative|change since|change since|current rev | | | benchmark|std_dev*| last run | baseline |run with PGO| +-----+------------------------+--------+------------+------------+------------+ | :-| | 2to3| 0.572% | +1.306% | +9.703% | +6.466% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method| 1.134% | +0.658% | +24.088% | +13.709% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_slots| 1.925% | +0.904% | +25.478% | +13.045% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_unknown| 1.447% | -1.878% | +22.422% | +12.602% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_simple| 3.856% | +1.190% | +11.179% | +14.647% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chameleon| 2.541% | -0.364% | +12.109% | +11.074% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chaos| 0.538% | -0.528% | +8.925% | +8.628% | +-----+------------------------+--------+------------+------------+------------+ | :-| | crypto_pyaes| 0.542% | +1.486% | -0.069% | +7.510% | +-----+------------------------+--------+------------+------------+------------+ | :-| | deltablue| 3.727% | +2.067% | +13.041% | +15.531% | +-----+------------------------+--------+------------+------------+------------+ | :-| | django_template| 4.512% | -1.446% | +20.652% | +13.956% | +-----+------------------------+--------+------------+------------+------------+ | :-| | dulwich_log| 1.379% | -0.345% | +5.482% | +7.297% | +-----+------------------------+--------+------------+------------+------------+ | :-| | fannkuch| 0.661% | +0.086% | +7.163% | +5.138% | +-----+------------------------+--------+------------+------------+------------+ | :-| | float| 1.073% | -0.265% | +2.460% | +7.338% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_text| 1.157% | +0.666% | +14.252% | +10.454% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_xml| 2.269% | -0.887% | +11.253% | +10.404% | +-----+------------------------+--------+------------+------------+------------+ | :-| | go| 5.753% | +1.001% | +5.888% | +10.383% | +-----+------------------------+--------+------------+------------+------------+ | :-| | hexiom| 0.424% | +0.871% | +11.883% | +11.227% | +-----+------------------------+--------+------------+------------+------------+ | :-| | html5lib| 2.806% | +1.022% | +12.304% | +9.043% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_dumps| 2.108% | +1.451% | +3.342% | +8.452% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_loads| 4.237% | +1.555% | -3.990% | +16.036% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_format| 1.493% | -2.009% | +16.907% | +13.928% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_silent| 2.731% | -0.585% | +47.480% | +12.809% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_simple| 1.577% | -0.967% | +12.481% | +13.533% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mako| 0.521% | +1.859% | +17.286% | +13.380% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mdp| 6.268% | -5.467% | +0.335% | +18.394% | +-----+------------------------+--------+------------+------------+------------+ | :-| | meteor_contest| 0.642% | +0.427% | +4.640% | +5.813% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nbody| 0.607% | +1.559% | +0.831% | +0.209% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nqueens| 0.628% | -0.334% | +5.738% | +8.103% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pathlib| 1.322% | +1.993% | +0.514% | +11.710% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle| 1.211% | -0.289% | -0.444% | +22.818% | +-----+------------------------+--------+------------+------------+------------+ | :-) | pickle_dict| 0.599% | +3.311% | +7.416% | +13.907% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_list| 0.923% | +1.047% | +6.994% | +15.660% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_pure_python| 5.292% | +1.307% | +11.515% | +11.301% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pidigits| 0.137% | -0.192% | +0.063% | +10.404% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup| 0.125% | +0.472% | +18.840% | +5.200% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup_no_site| 0.088% | +0.352% | +5.792% | +5.522% | +-----+------------------------+--------+------------+------------+------------+ | :-| | raytrace| 1.378% | -0.472% | +9.690% | +14.068% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_compile| 5.050% | +2.235% | +6.149% | +7.947% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_dna| 0.505% | +1.211% | -0.753% | +12.060% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_effbot| 1.348% | -2.164% | -4.495% | +5.618% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_v8| 2.527% | +1.942% | +5.589% | +6.259% | +-----+------------------------+--------+------------+------------+------------+ | :-| | richards| 1.528% | +0.046% | +9.601% | +15.361% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_fft| 0.520% | -0.744% | -2.242% | +3.623% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_lu| 4.006% | +0.948% | +22.625% | +12.292% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_monte_carlo| 2.126% | +0.522% | +5.427% | +2.119% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sor| 1.300% | +0.649% | +15.155% | +9.328% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sparse_mat_mult| 1.601% | +2.064% | -2.426% | -2.415% | +-----+------------------------+--------+------------+------------+------------+ | :-| | spectral_norm| 0.698% | +0.709% | +4.124% | +4.435% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_declarative| 1.824% | +1.310% | +7.733% | +4.686% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_imperative| 3.318% | +0.479% | +8.164% | +4.057% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlite_synth| 5.665% | +1.614% | +0.784% | +8.649% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_expand| 3.431% | +0.484% | +17.530% | +7.459% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_integrate| 1.416% | +0.426% | +18.407% | +6.004% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_str| 3.992% | +0.026% | +18.956% | +8.018% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_sum| 6.067% | -0.183% | +16.198% | +9.543% | +-----+------------------------+--------+------------+------------+------------+ | :-| | telco| 5.050% | +1.452% | +19.298% | +10.885% | +-----+------------------------+--------+------------+------------+------------+ | :-| | tornado_http| 0.998% | +0.506% | +7.290% | +5.997% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpack_sequence| 0.950% | +0.058% | +2.633% | +2.475% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle| 3.948% | +1.675% | +10.153% | +19.424% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_list| 7.442% | -2.649% | -4.504% | +19.127% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_pure_python| 1.407% | +1.298% | +7.510% | +7.338% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_generate| 1.497% | -0.231% | +2.412% | +12.383% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_iterparse| 2.776% | +1.247% | +3.787% | +8.404% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_parse| 2.789% | +2.127% | -6.790% | +10.351% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_process| 1.040% | -0.040% | +4.341% | +11.299% | +-----+------------------------+--------+------------+------------+------------+ * Relative Standard Deviation (Standard Deviation/Average) If this is not displayed properly please visit our results page here: http://languagesperformance.intel.com/1-up-64-flat-results-for-python-master-branch-2018-05-08 Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. From webhook-mailer at python.org Tue May 8 21:44:19 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 09 May 2018 01:44:19 -0000 Subject: [Python-checkins] bpo-28556: Minor fixes for typing module (GH-6732) Message-ID: https://github.com/python/cpython/commit/3c28a6387b48bad3fcae47906bc166d02a2f8ed2 commit: 3c28a6387b48bad3fcae47906bc166d02a2f8ed2 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-05-08T18:44:09-07:00 summary: bpo-28556: Minor fixes for typing module (GH-6732) This also fixes https://bugs.python.org/issue33420 (cherry picked from commit 43d12a6bd82bd09ac189069fe1eb40cdbc10a58c) Co-authored-by: Ivan Levkivskyi files: A Misc/NEWS.d/next/Library/2018-05-08-16-43-42.bpo-28556._xr5mp.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 390fe60fcc10..46bab5eba6db 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -1324,6 +1324,72 @@ class D(C): with self.assertRaises(Exception): D[T] + def test_new_with_args(self): + + class A(Generic[T]): + pass + + class B: + def __new__(cls, arg): + # call object + obj = super().__new__(cls) + obj.arg = arg + return obj + + # mro: C, A, Generic, B, object + class C(A, B): + pass + + c = C('foo') + self.assertEqual(c.arg, 'foo') + + def test_new_with_args2(self): + + class A: + def __init__(self, arg): + self.from_a = arg + # call object + super().__init__() + + # mro: C, Generic, A, object + class C(Generic[T], A): + def __init__(self, arg): + self.from_c = arg + # call Generic + super().__init__(arg) + + c = C('foo') + self.assertEqual(c.from_a, 'foo') + self.assertEqual(c.from_c, 'foo') + + def test_new_no_args(self): + + class A(Generic[T]): + pass + + class B: + def __new__(cls): + # call object + obj = super().__new__(cls) + obj.from_b = 'b' + return obj + + # mro: C, A, Generic, B, object + class C(A, B): + def __init__(self, arg): + self.arg = arg + + def __new__(cls, arg): + # call A + obj = super().__new__(cls) + obj.from_c = 'c' + return obj + + c = C('foo') + self.assertEqual(c.arg, 'foo') + self.assertEqual(c.from_b, 'b') + self.assertEqual(c.from_c, 'c') + class ClassVarTests(BaseTestCase): @@ -1737,6 +1803,8 @@ def test_get_type_hints_classes(self): self.assertEqual(gth(HasForeignBaseClass), {'some_xrepr': XRepr, 'other_a': mod_generics_cache.A, 'some_b': mod_generics_cache.B}) + self.assertEqual(gth(XRepr.__new__), + {'x': int, 'y': int}) self.assertEqual(gth(mod_generics_cache.B), {'my_inner_a1': mod_generics_cache.B.A, 'my_inner_a2': mod_generics_cache.B.A, diff --git a/Lib/typing.py b/Lib/typing.py index 83296073b914..89b73db15837 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -607,7 +607,8 @@ def __reduce__(self): # * __parameters__ is a tuple of unique free type parameters of a generic # type, for example, Dict[T, T].__parameters__ == (T,); # * __origin__ keeps a reference to a type that was subscripted, -# e.g., Union[T, int].__origin__ == Union; +# e.g., Union[T, int].__origin__ == Union, or the non-generic version of +# the type. # * __args__ is a tuple of all arguments used in subscripting, # e.g., Dict[T, int].__args__ == (T, int). @@ -835,7 +836,11 @@ def __new__(cls, *args, **kwds): if cls is Generic: raise TypeError("Type Generic cannot be instantiated; " "it can be used only as a base class") - return super().__new__(cls) + if super().__new__ is object.__new__: + obj = super().__new__(cls) + else: + obj = super().__new__(cls, *args, **kwds) + return obj @_tp_cache def __class_getitem__(cls, params): @@ -1385,6 +1390,7 @@ def __new__(cls, typename, bases, ns): "follow default field(s) {default_names}" .format(field_name=field_name, default_names=', '.join(defaults_dict.keys()))) + nm_tpl.__new__.__annotations__ = collections.OrderedDict(types) nm_tpl.__new__.__defaults__ = tuple(defaults) nm_tpl._field_defaults = defaults_dict # update from user namespace without overriding special namedtuple attributes diff --git a/Misc/NEWS.d/next/Library/2018-05-08-16-43-42.bpo-28556._xr5mp.rst b/Misc/NEWS.d/next/Library/2018-05-08-16-43-42.bpo-28556._xr5mp.rst new file mode 100644 index 000000000000..8ed4658211fb --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-08-16-43-42.bpo-28556._xr5mp.rst @@ -0,0 +1,3 @@ +Minor fixes in typing module: add annotations to ``NamedTuple.__new__``, +pass ``*args`` and ``**kwds`` in ``Generic.__new__``. Original PRs by +Paulius ?arka and Chad Dombrova. From webhook-mailer at python.org Wed May 9 00:16:38 2018 From: webhook-mailer at python.org (Benjamin Peterson) Date: Wed, 09 May 2018 04:16:38 -0000 Subject: [Python-checkins] closes bpo-33445: fail properly in test_cprofile() (GH-6727) Message-ID: https://github.com/python/cpython/commit/ac9240b9be31d073d1b2e50ce53481ff0fc9ed23 commit: ac9240b9be31d073d1b2e50ce53481ff0fc9ed23 branch: master author: jdemeyer committer: Benjamin Peterson date: 2018-05-08T21:16:35-07:00 summary: closes bpo-33445: fail properly in test_cprofile() (GH-6727) files: M Lib/test/test_profile.py diff --git a/Lib/test/test_profile.py b/Lib/test/test_profile.py index 1fc3c4266965..a9982663175a 100644 --- a/Lib/test/test_profile.py +++ b/Lib/test/test_profile.py @@ -51,13 +51,18 @@ def test_cprofile(self): results = self.do_profiling() expected = self.get_expected_output() self.assertEqual(results[0], 1000) + fail = [] for i, method in enumerate(self.methodnames): - if results[i+1] != expected[method]: - print("Stats.%s output for %s doesn't fit expectation!" % - (method, self.profilerclass.__name__)) - print('\n'.join(unified_diff( - results[i+1].split('\n'), - expected[method].split('\n')))) + a = expected[method] + b = results[i+1] + if a != b: + fail.append(f"\nStats.{method} output for " + f"{self.profilerclass.__name__} " + "does not fit expectation:") + fail.extend(unified_diff(a.split('\n'), b.split('\n'), + lineterm="")) + if fail: + self.fail("\n".join(fail)) def test_calling_conventions(self): # Issue #5330: profile and cProfile wouldn't report C functions called From webhook-mailer at python.org Wed May 9 00:38:03 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 09 May 2018 04:38:03 -0000 Subject: [Python-checkins] closes bpo-33445: fail properly in test_cprofile() (GH-6727) Message-ID: https://github.com/python/cpython/commit/263523ae217e1af580628b4fe0609194823a51aa commit: 263523ae217e1af580628b4fe0609194823a51aa branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-05-08T21:38:00-07:00 summary: closes bpo-33445: fail properly in test_cprofile() (GH-6727) (cherry picked from commit ac9240b9be31d073d1b2e50ce53481ff0fc9ed23) Co-authored-by: jdemeyer files: M Lib/test/test_profile.py diff --git a/Lib/test/test_profile.py b/Lib/test/test_profile.py index 1fc3c4266965..a9982663175a 100644 --- a/Lib/test/test_profile.py +++ b/Lib/test/test_profile.py @@ -51,13 +51,18 @@ def test_cprofile(self): results = self.do_profiling() expected = self.get_expected_output() self.assertEqual(results[0], 1000) + fail = [] for i, method in enumerate(self.methodnames): - if results[i+1] != expected[method]: - print("Stats.%s output for %s doesn't fit expectation!" % - (method, self.profilerclass.__name__)) - print('\n'.join(unified_diff( - results[i+1].split('\n'), - expected[method].split('\n')))) + a = expected[method] + b = results[i+1] + if a != b: + fail.append(f"\nStats.{method} output for " + f"{self.profilerclass.__name__} " + "does not fit expectation:") + fail.extend(unified_diff(a.split('\n'), b.split('\n'), + lineterm="")) + if fail: + self.fail("\n".join(fail)) def test_calling_conventions(self): # Issue #5330: profile and cProfile wouldn't report C functions called From webhook-mailer at python.org Wed May 9 00:59:57 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 09 May 2018 04:59:57 -0000 Subject: [Python-checkins] closes bpo-33445: fail properly in test_cprofile() (GH-6727) Message-ID: https://github.com/python/cpython/commit/c925108b991b9c5f0402feb0e7f725ee3ac7da11 commit: c925108b991b9c5f0402feb0e7f725ee3ac7da11 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-05-08T21:59:50-07:00 summary: closes bpo-33445: fail properly in test_cprofile() (GH-6727) (cherry picked from commit ac9240b9be31d073d1b2e50ce53481ff0fc9ed23) Co-authored-by: jdemeyer files: M Lib/test/test_profile.py diff --git a/Lib/test/test_profile.py b/Lib/test/test_profile.py index 1fc3c4266965..a9982663175a 100644 --- a/Lib/test/test_profile.py +++ b/Lib/test/test_profile.py @@ -51,13 +51,18 @@ def test_cprofile(self): results = self.do_profiling() expected = self.get_expected_output() self.assertEqual(results[0], 1000) + fail = [] for i, method in enumerate(self.methodnames): - if results[i+1] != expected[method]: - print("Stats.%s output for %s doesn't fit expectation!" % - (method, self.profilerclass.__name__)) - print('\n'.join(unified_diff( - results[i+1].split('\n'), - expected[method].split('\n')))) + a = expected[method] + b = results[i+1] + if a != b: + fail.append(f"\nStats.{method} output for " + f"{self.profilerclass.__name__} " + "does not fit expectation:") + fail.extend(unified_diff(a.split('\n'), b.split('\n'), + lineterm="")) + if fail: + self.fail("\n".join(fail)) def test_calling_conventions(self): # Issue #5330: profile and cProfile wouldn't report C functions called From webhook-mailer at python.org Wed May 9 01:49:57 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 09 May 2018 05:49:57 -0000 Subject: [Python-checkins] Fix typo in __mul__ and __rmul__ docstring (GH-6674) Message-ID: https://github.com/python/cpython/commit/a0ff51964f85f446e1eb13c59297b17bd2f435c6 commit: a0ff51964f85f446e1eb13c59297b17bd2f435c6 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-05-08T22:49:47-07:00 summary: Fix typo in __mul__ and __rmul__ docstring (GH-6674) (cherry picked from commit 0904f766e116c269675317e11368a4d29eef0bc6) Co-authored-by: Grant Jenks files: M Objects/typeobject.c diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 1dd534866b4d..a7a9d7bf9fc3 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -6938,9 +6938,9 @@ static slotdef slotdefs[] = { SQSLOT("__add__", sq_concat, NULL, wrap_binaryfunc, "__add__($self, value, /)\n--\n\nReturn self+value."), SQSLOT("__mul__", sq_repeat, NULL, wrap_indexargfunc, - "__mul__($self, value, /)\n--\n\nReturn self*value.n"), + "__mul__($self, value, /)\n--\n\nReturn self*value."), SQSLOT("__rmul__", sq_repeat, NULL, wrap_indexargfunc, - "__rmul__($self, value, /)\n--\n\nReturn self*value."), + "__rmul__($self, value, /)\n--\n\nReturn value*self."), SQSLOT("__getitem__", sq_item, slot_sq_item, wrap_sq_item, "__getitem__($self, key, /)\n--\n\nReturn self[key]."), SQSLOT("__setitem__", sq_ass_item, slot_sq_ass_item, wrap_sq_setitem, From webhook-mailer at python.org Wed May 9 01:50:00 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 09 May 2018 05:50:00 -0000 Subject: [Python-checkins] Fix typo in __mul__ and __rmul__ docstring (GH-6674) Message-ID: https://github.com/python/cpython/commit/7f4f94d474d16b5817df2b05c9678436c08f5efa commit: 7f4f94d474d16b5817df2b05c9678436c08f5efa branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-05-08T22:49:57-07:00 summary: Fix typo in __mul__ and __rmul__ docstring (GH-6674) (cherry picked from commit 0904f766e116c269675317e11368a4d29eef0bc6) Co-authored-by: Grant Jenks files: M Objects/typeobject.c diff --git a/Objects/typeobject.c b/Objects/typeobject.c index e843204f10a6..69b1878fd8f2 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -6740,9 +6740,9 @@ static slotdef slotdefs[] = { SQSLOT("__add__", sq_concat, NULL, wrap_binaryfunc, "__add__($self, value, /)\n--\n\nReturn self+value."), SQSLOT("__mul__", sq_repeat, NULL, wrap_indexargfunc, - "__mul__($self, value, /)\n--\n\nReturn self*value.n"), + "__mul__($self, value, /)\n--\n\nReturn self*value."), SQSLOT("__rmul__", sq_repeat, NULL, wrap_indexargfunc, - "__rmul__($self, value, /)\n--\n\nReturn self*value."), + "__rmul__($self, value, /)\n--\n\nReturn value*self."), SQSLOT("__getitem__", sq_item, slot_sq_item, wrap_sq_item, "__getitem__($self, key, /)\n--\n\nReturn self[key]."), SQSLOT("__setitem__", sq_ass_item, slot_sq_ass_item, wrap_sq_setitem, From webhook-mailer at python.org Wed May 9 03:25:29 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Wed, 09 May 2018 07:25:29 -0000 Subject: [Python-checkins] Fix superfluous if in documentation. (GH-6728) Message-ID: https://github.com/python/cpython/commit/b3c369861b22268dac003eb995951726c972e5ee commit: b3c369861b22268dac003eb995951726c972e5ee branch: master author: Julien Palard committer: Serhiy Storchaka date: 2018-05-09T10:25:22+03:00 summary: Fix superfluous if in documentation. (GH-6728) files: M Doc/library/functions.rst diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index c3b638572338..2d15001bffa7 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -734,7 +734,7 @@ are always available. They are listed here in alphabetical order. :meth:`x.__int__() `. If *x* defines :meth:`x.__trunc__() ` but not :meth:`x.__int__() `, then return - if :meth:`x.__trunc__() `. For floating point numbers, + :meth:`x.__trunc__() `. For floating point numbers, this truncates towards zero. If *x* is not a number or if *base* is given, then *x* must be a string, From webhook-mailer at python.org Wed May 9 04:10:05 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 09 May 2018 08:10:05 -0000 Subject: [Python-checkins] Fix superfluous if in documentation. (GH-6728) Message-ID: https://github.com/python/cpython/commit/c587235f210b18d6f7f31e746fa5e5e259320c83 commit: c587235f210b18d6f7f31e746fa5e5e259320c83 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-05-09T01:10:02-07:00 summary: Fix superfluous if in documentation. (GH-6728) (cherry picked from commit b3c369861b22268dac003eb995951726c972e5ee) Co-authored-by: Julien Palard files: M Doc/library/functions.rst diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index c3b638572338..2d15001bffa7 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -734,7 +734,7 @@ are always available. They are listed here in alphabetical order. :meth:`x.__int__() `. If *x* defines :meth:`x.__trunc__() ` but not :meth:`x.__int__() `, then return - if :meth:`x.__trunc__() `. For floating point numbers, + :meth:`x.__trunc__() `. For floating point numbers, this truncates towards zero. If *x* is not a number or if *base* is given, then *x* must be a string, From webhook-mailer at python.org Wed May 9 04:10:15 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 09 May 2018 08:10:15 -0000 Subject: [Python-checkins] Fix superfluous if in documentation. (GH-6728) Message-ID: https://github.com/python/cpython/commit/6079b607d3fad319f84f0a0174eece44ee6a69b7 commit: 6079b607d3fad319f84f0a0174eece44ee6a69b7 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-05-09T01:10:12-07:00 summary: Fix superfluous if in documentation. (GH-6728) (cherry picked from commit b3c369861b22268dac003eb995951726c972e5ee) Co-authored-by: Julien Palard files: M Doc/library/functions.rst diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index 9cb6b0e1b5ca..56c1377d1734 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -720,7 +720,7 @@ are always available. They are listed here in alphabetical order. :meth:`x.__int__() `. If *x* defines :meth:`x.__trunc__() ` but not :meth:`x.__int__() `, then return - if :meth:`x.__trunc__() `. For floating point numbers, + :meth:`x.__trunc__() `. For floating point numbers, this truncates towards zero. If *x* is not a number or if *base* is given, then *x* must be a string, From webhook-mailer at python.org Wed May 9 04:10:58 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Wed, 09 May 2018 08:10:58 -0000 Subject: [Python-checkins] bpo-13525: Fix incorrect encoding name in the tutorial example. (GH-6738) Message-ID: https://github.com/python/cpython/commit/ddb6215a55b0218b621d5cb755e9dfac8dab231a commit: ddb6215a55b0218b621d5cb755e9dfac8dab231a branch: master author: Serhiy Storchaka committer: GitHub date: 2018-05-09T11:10:55+03:00 summary: bpo-13525: Fix incorrect encoding name in the tutorial example. (GH-6738) files: M Doc/tutorial/interpreter.rst diff --git a/Doc/tutorial/interpreter.rst b/Doc/tutorial/interpreter.rst index 3d57020dabe8..6cdc6c8419af 100644 --- a/Doc/tutorial/interpreter.rst +++ b/Doc/tutorial/interpreter.rst @@ -148,14 +148,14 @@ where *encoding* is one of the valid :mod:`codecs` supported by Python. For example, to declare that Windows-1252 encoding is to be used, the first line of your source code file should be:: - # -*- coding: cp-1252 -*- + # -*- coding: cp1252 -*- One exception to the *first line* rule is when the source code starts with a :ref:`UNIX "shebang" line `. In this case, the encoding declaration should be added as the second line of the file. For example:: #!/usr/bin/env python3 - # -*- coding: cp-1252 -*- + # -*- coding: cp1252 -*- .. rubric:: Footnotes From webhook-mailer at python.org Wed May 9 04:54:42 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 09 May 2018 08:54:42 -0000 Subject: [Python-checkins] bpo-13525: Fix incorrect encoding name in the tutorial example. (GH-6738) Message-ID: https://github.com/python/cpython/commit/8ffff34ea12ca6478d73a337ce52f33660f6f174 commit: 8ffff34ea12ca6478d73a337ce52f33660f6f174 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-05-09T01:54:38-07:00 summary: bpo-13525: Fix incorrect encoding name in the tutorial example. (GH-6738) (cherry picked from commit ddb6215a55b0218b621d5cb755e9dfac8dab231a) Co-authored-by: Serhiy Storchaka files: M Doc/tutorial/interpreter.rst diff --git a/Doc/tutorial/interpreter.rst b/Doc/tutorial/interpreter.rst index bf7ce7764171..a2766e8810a5 100644 --- a/Doc/tutorial/interpreter.rst +++ b/Doc/tutorial/interpreter.rst @@ -148,14 +148,14 @@ where *encoding* is one of the valid :mod:`codecs` supported by Python. For example, to declare that Windows-1252 encoding is to be used, the first line of your source code file should be:: - # -*- coding: cp-1252 -*- + # -*- coding: cp1252 -*- One exception to the *first line* rule is when the source code starts with a :ref:`UNIX "shebang" line `. In this case, the encoding declaration should be added as the second line of the file. For example:: #!/usr/bin/env python3 - # -*- coding: cp-1252 -*- + # -*- coding: cp1252 -*- .. rubric:: Footnotes From webhook-mailer at python.org Wed May 9 05:00:24 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 09 May 2018 09:00:24 -0000 Subject: [Python-checkins] bpo-13525: Fix incorrect encoding name in the tutorial example. (GH-6738) Message-ID: https://github.com/python/cpython/commit/fa40fc0593012893e447875632e9ed3df277561f commit: fa40fc0593012893e447875632e9ed3df277561f branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-05-09T02:00:13-07:00 summary: bpo-13525: Fix incorrect encoding name in the tutorial example. (GH-6738) (cherry picked from commit ddb6215a55b0218b621d5cb755e9dfac8dab231a) Co-authored-by: Serhiy Storchaka files: M Doc/tutorial/interpreter.rst diff --git a/Doc/tutorial/interpreter.rst b/Doc/tutorial/interpreter.rst index 3bd100d46a12..d04f7cefa0df 100644 --- a/Doc/tutorial/interpreter.rst +++ b/Doc/tutorial/interpreter.rst @@ -148,14 +148,14 @@ where *encoding* is one of the valid :mod:`codecs` supported by Python. For example, to declare that Windows-1252 encoding is to be used, the first line of your source code file should be:: - # -*- coding: cp-1252 -*- + # -*- coding: cp1252 -*- One exception to the *first line* rule is when the source code starts with a :ref:`UNIX "shebang" line `. In this case, the encoding declaration should be added as the second line of the file. For example:: #!/usr/bin/env python3 - # -*- coding: cp-1252 -*- + # -*- coding: cp1252 -*- .. rubric:: Footnotes From solipsis at pitrou.net Wed May 9 05:12:30 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 09 May 2018 09:12:30 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=14 Message-ID: <20180509091230.1.4D596DF0F1AD3FF4@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_asyncio leaked [0, 0, 3] memory blocks, sum=3 test_collections leaked [0, 7, 0] memory blocks, sum=7 test_functools leaked [0, 3, 1] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflog9MNS5c', '--timeout', '7200'] From webhook-mailer at python.org Wed May 9 05:35:38 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Wed, 09 May 2018 09:35:38 -0000 Subject: [Python-checkins] [2.7] bpo-13525: Fix incorrect encoding name in the tutorial example. (GH-6738). (GH-6744) Message-ID: https://github.com/python/cpython/commit/d7e783b17feaedbe0f5b30467cb7f43cefadf904 commit: d7e783b17feaedbe0f5b30467cb7f43cefadf904 branch: 2.7 author: Serhiy Storchaka committer: GitHub date: 2018-05-09T12:35:28+03:00 summary: [2.7] bpo-13525: Fix incorrect encoding name in the tutorial example. (GH-6738). (GH-6744) (cherry picked from commit ddb6215a55b0218b621d5cb755e9dfac8dab231a) files: M Doc/tutorial/interpreter.rst diff --git a/Doc/tutorial/interpreter.rst b/Doc/tutorial/interpreter.rst index 6c8609fabaeb..b727be00ab8a 100644 --- a/Doc/tutorial/interpreter.rst +++ b/Doc/tutorial/interpreter.rst @@ -137,12 +137,12 @@ where *encoding* is one of the valid :mod:`codecs` supported by Python. For example, to declare that Windows-1252 encoding is to be used, the first line of your source code file should be:: - # -*- coding: cp-1252 -*- + # -*- coding: cp1252 -*- One exception to the *first line* rule is when the source code starts with a :ref:`UNIX "shebang" line `. In this case, the encoding declaration should be added as the second line of the file. For example:: #!/usr/bin/env python - # -*- coding: cp-1252 -*- + # -*- coding: cp1252 -*- From webhook-mailer at python.org Wed May 9 05:39:35 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Wed, 09 May 2018 09:39:35 -0000 Subject: [Python-checkins] bpo-33311: Do not display parameters displayed in parentheses for module call. (GH-6677) Message-ID: https://github.com/python/cpython/commit/8cf4b34b3665b8bb39ea7111e6b5c3410899d3e4 commit: 8cf4b34b3665b8bb39ea7111e6b5c3410899d3e4 branch: master author: sblondon committer: Serhiy Storchaka date: 2018-05-09T12:39:32+03:00 summary: bpo-33311: Do not display parameters displayed in parentheses for module call. (GH-6677) files: A Misc/NEWS.d/next/Library/2018-05-01-22-33-14.bpo-33311.8YPB-k.rst M Lib/cgitb.py diff --git a/Lib/cgitb.py b/Lib/cgitb.py index 0f5f32c0fade..4f81271be3ca 100644 --- a/Lib/cgitb.py +++ b/Lib/cgitb.py @@ -124,8 +124,9 @@ def html(einfo, context=5): args, varargs, varkw, locals = inspect.getargvalues(frame) call = '' if func != '?': - call = 'in ' + strong(pydoc.html.escape(func)) + \ - inspect.formatargvalues(args, varargs, varkw, locals, + call = 'in ' + strong(pydoc.html.escape(func)) + if func != "": + call += inspect.formatargvalues(args, varargs, varkw, locals, formatvalue=lambda value: '=' + pydoc.html.repr(value)) highlight = {} @@ -207,8 +208,9 @@ def text(einfo, context=5): args, varargs, varkw, locals = inspect.getargvalues(frame) call = '' if func != '?': - call = 'in ' + func + \ - inspect.formatargvalues(args, varargs, varkw, locals, + call = 'in ' + func + if func != "": + call += inspect.formatargvalues(args, varargs, varkw, locals, formatvalue=lambda value: '=' + pydoc.text.repr(value)) highlight = {} diff --git a/Misc/NEWS.d/next/Library/2018-05-01-22-33-14.bpo-33311.8YPB-k.rst b/Misc/NEWS.d/next/Library/2018-05-01-22-33-14.bpo-33311.8YPB-k.rst new file mode 100644 index 000000000000..d0218de373ca --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-01-22-33-14.bpo-33311.8YPB-k.rst @@ -0,0 +1,2 @@ +Text and html output generated by cgitb does not display parentheses if the +current call is done directly in the module. Patch by St?phane Blondon. From webhook-mailer at python.org Wed May 9 06:14:44 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Wed, 09 May 2018 10:14:44 -0000 Subject: [Python-checkins] bpo-33038: Fix gzip.GzipFile for file objects with a non-string name attribute. (GH-6095) Message-ID: https://github.com/python/cpython/commit/afe5f633e49e0e873d42088ae56819609c803ba0 commit: afe5f633e49e0e873d42088ae56819609c803ba0 branch: 2.7 author: Bo Bayles committer: Serhiy Storchaka date: 2018-05-09T13:14:40+03:00 summary: bpo-33038: Fix gzip.GzipFile for file objects with a non-string name attribute. (GH-6095) files: A Misc/NEWS.d/next/Library/2018-03-10-20-14-36.bpo-33038.yA6CP5.rst M Lib/gzip.py M Lib/test/test_gzip.py M Misc/ACKS diff --git a/Lib/gzip.py b/Lib/gzip.py index 07c6db493b0b..76ace394f482 100644 --- a/Lib/gzip.py +++ b/Lib/gzip.py @@ -95,9 +95,8 @@ def __init__(self, filename=None, mode=None, if filename is None: # Issue #13781: os.fdopen() creates a fileobj with a bogus name # attribute. Avoid saving this in the gzip header's filename field. - if hasattr(fileobj, 'name') and fileobj.name != '': - filename = fileobj.name - else: + filename = getattr(fileobj, 'name', '') + if not isinstance(filename, basestring) or filename == '': filename = '' if mode is None: if hasattr(fileobj, 'mode'): mode = fileobj.mode diff --git a/Lib/test/test_gzip.py b/Lib/test/test_gzip.py index 902d93fe043f..cdb1af5c3d13 100644 --- a/Lib/test/test_gzip.py +++ b/Lib/test/test_gzip.py @@ -6,6 +6,7 @@ import os import io import struct +import tempfile gzip = test_support.import_module('gzip') data1 = """ int length=DEFAULTALLOC, err = Z_OK; @@ -331,6 +332,12 @@ def test_fileobj_from_fdopen(self): with gzip.GzipFile(fileobj=f, mode="w") as g: self.assertEqual(g.name, "") + def test_fileobj_from_io_open(self): + fd = os.open(self.filename, os.O_WRONLY | os.O_CREAT) + with io.open(fd, "wb") as f: + with gzip.GzipFile(fileobj=f, mode="w") as g: + self.assertEqual(g.name, "") + def test_fileobj_mode(self): gzip.GzipFile(self.filename, "wb").close() with open(self.filename, "r+b") as f: @@ -359,6 +366,14 @@ def test_read_with_extra(self): with gzip.GzipFile(fileobj=io.BytesIO(gzdata)) as f: self.assertEqual(f.read(), b'Test') + def test_fileobj_without_name(self): + # Issue #33038: GzipFile should not assume that file objects that have + # a .name attribute use a non-None value. + with tempfile.SpooledTemporaryFile() as f: + with gzip.GzipFile(fileobj=f, mode='wb') as archive: + archive.write(b'data') + self.assertEqual(archive.name, '') + def test_main(verbose=None): test_support.run_unittest(TestGzip) diff --git a/Misc/ACKS b/Misc/ACKS index 580b0c5bf76d..458f31e6a6b7 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -94,6 +94,7 @@ Michael R Bax Anthony Baxter Mike Bayer Samuel L. Bayer +Bo Bayles Donald Beaudry David Beazley Carlo Beccarini diff --git a/Misc/NEWS.d/next/Library/2018-03-10-20-14-36.bpo-33038.yA6CP5.rst b/Misc/NEWS.d/next/Library/2018-03-10-20-14-36.bpo-33038.yA6CP5.rst new file mode 100644 index 000000000000..22d394b85ab7 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-03-10-20-14-36.bpo-33038.yA6CP5.rst @@ -0,0 +1,2 @@ +gzip.GzipFile no longer produces an AttributeError exception when used with +a file object with a non-string name attribute. Patch by Bo Bayles. From webhook-mailer at python.org Wed May 9 17:39:00 2018 From: webhook-mailer at python.org (Steve Dower) Date: Wed, 09 May 2018 21:39:00 -0000 Subject: [Python-checkins] bpo-21983: Fix a crash in ctypes.cast() when passed a ctypes structured data type (GH-3859) Message-ID: https://github.com/python/cpython/commit/d518d8bc8d5dac1a1270612f424d33e0e5afc2b5 commit: d518d8bc8d5dac1a1270612f424d33e0e5afc2b5 branch: master author: Oren Milman committer: Steve Dower date: 2018-05-09T14:38:56-07:00 summary: bpo-21983: Fix a crash in ctypes.cast() when passed a ctypes structured data type (GH-3859) files: A Misc/NEWS.d/next/Core and Builtins/2017-10-02-21-02-14.bpo-21983.UoC319.rst M Lib/ctypes/test/test_cast.py M Modules/_ctypes/_ctypes.c diff --git a/Lib/ctypes/test/test_cast.py b/Lib/ctypes/test/test_cast.py index 187d2bde143d..6878f9732826 100644 --- a/Lib/ctypes/test/test_cast.py +++ b/Lib/ctypes/test/test_cast.py @@ -82,5 +82,18 @@ def test_wchar_p(self): self.assertEqual(cast(cast(s, c_void_p), c_wchar_p).value, "hiho") + def test_bad_type_arg(self): + # The type argument must be a ctypes pointer type. + array_type = c_byte * sizeof(c_int) + array = array_type() + self.assertRaises(TypeError, cast, array, None) + self.assertRaises(TypeError, cast, array, array_type) + class Struct(Structure): + _fields_ = [("a", c_int)] + self.assertRaises(TypeError, cast, array, Struct) + class MyUnion(Union): + _fields_ = [("a", c_int)] + self.assertRaises(TypeError, cast, array, MyUnion) + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-10-02-21-02-14.bpo-21983.UoC319.rst b/Misc/NEWS.d/next/Core and Builtins/2017-10-02-21-02-14.bpo-21983.UoC319.rst new file mode 100644 index 000000000000..88a03685073c --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-10-02-21-02-14.bpo-21983.UoC319.rst @@ -0,0 +1,2 @@ +Fix a crash in `ctypes.cast()` in case the type argument is a ctypes +structured data type. Patch by Eryk Sun and Oren Milman. diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 93e8d8d42330..5bf49acb6c2d 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -5319,7 +5319,7 @@ cast_check_pointertype(PyObject *arg) if (PyCFuncPtrTypeObject_Check(arg)) return 1; dict = PyType_stgdict(arg); - if (dict) { + if (dict != NULL && dict->proto != NULL) { if (PyUnicode_Check(dict->proto) && (strchr("sPzUZXO", PyUnicode_AsUTF8(dict->proto)[0]))) { /* simple pointer types, c_void_p, c_wchar_p, BSTR, ... */ From webhook-mailer at python.org Wed May 9 18:28:01 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 09 May 2018 22:28:01 -0000 Subject: [Python-checkins] bpo-21983: Fix a crash in ctypes.cast() when passed a ctypes structured data type (GH-3859) Message-ID: https://github.com/python/cpython/commit/8ac158a6dfb86880e22003afe0ff39ec31b0a094 commit: 8ac158a6dfb86880e22003afe0ff39ec31b0a094 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-05-09T15:27:59-07:00 summary: bpo-21983: Fix a crash in ctypes.cast() when passed a ctypes structured data type (GH-3859) (cherry picked from commit d518d8bc8d5dac1a1270612f424d33e0e5afc2b5) Co-authored-by: Oren Milman files: A Misc/NEWS.d/next/Core and Builtins/2017-10-02-21-02-14.bpo-21983.UoC319.rst M Lib/ctypes/test/test_cast.py M Modules/_ctypes/_ctypes.c diff --git a/Lib/ctypes/test/test_cast.py b/Lib/ctypes/test/test_cast.py index 187d2bde143d..6878f9732826 100644 --- a/Lib/ctypes/test/test_cast.py +++ b/Lib/ctypes/test/test_cast.py @@ -82,5 +82,18 @@ def test_wchar_p(self): self.assertEqual(cast(cast(s, c_void_p), c_wchar_p).value, "hiho") + def test_bad_type_arg(self): + # The type argument must be a ctypes pointer type. + array_type = c_byte * sizeof(c_int) + array = array_type() + self.assertRaises(TypeError, cast, array, None) + self.assertRaises(TypeError, cast, array, array_type) + class Struct(Structure): + _fields_ = [("a", c_int)] + self.assertRaises(TypeError, cast, array, Struct) + class MyUnion(Union): + _fields_ = [("a", c_int)] + self.assertRaises(TypeError, cast, array, MyUnion) + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-10-02-21-02-14.bpo-21983.UoC319.rst b/Misc/NEWS.d/next/Core and Builtins/2017-10-02-21-02-14.bpo-21983.UoC319.rst new file mode 100644 index 000000000000..88a03685073c --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-10-02-21-02-14.bpo-21983.UoC319.rst @@ -0,0 +1,2 @@ +Fix a crash in `ctypes.cast()` in case the type argument is a ctypes +structured data type. Patch by Eryk Sun and Oren Milman. diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 258e805870b1..2c0a769d8724 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -5327,7 +5327,7 @@ cast_check_pointertype(PyObject *arg) if (PyCFuncPtrTypeObject_Check(arg)) return 1; dict = PyType_stgdict(arg); - if (dict) { + if (dict != NULL && dict->proto != NULL) { if (PyUnicode_Check(dict->proto) && (strchr("sPzUZXO", PyUnicode_AsUTF8(dict->proto)[0]))) { /* simple pointer types, c_void_p, c_wchar_p, BSTR, ... */ From lp_benchmark_robot at intel.com Wed May 9 20:51:49 2018 From: lp_benchmark_robot at intel.com (lp_benchmark_robot at intel.com) Date: Wed, 9 May 2018 17:51:49 -0700 Subject: [Python-checkins] [65 flat] Results for Python (master branch) 2018-05-09 Message-ID: <6a734355-2991-4628-9bd8-746498a20897@orsmsx153.amr.corp.intel.com> Results for project python/master, build date: 2018-05-09 03:03:02-07:00. - commit: 8cf4b34 - previous commit: d54cfb1 - revision date: 2018-05-09 12:39:32+03:00 - environment: Broadwell-EP - cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores, stepping 1, LLC 55 MB - mem: 128 GB - os: Ubuntu 16.04.2 LTS - kernel: 4.4.0-62-generic x86_64 GNU/Linux Baseline results were generated using release v3.6.0, with hash 5c4568a from 2016-12-22 23:38:47+00:00. +-----+------------------------+--------+------------+------------+------------+ | | |relative|change since|change since|current rev | | | benchmark|std_dev*| last run | baseline |run with PGO| +-----+------------------------+--------+------------+------------+------------+ | :-| | 2to3| 0.595% | -0.257% | +9.471% | +6.950% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method| 1.426% | -0.362% | +23.813% | +9.597% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_slots| 1.677% | +0.379% | +25.761% | +8.461% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_unknown| 1.140% | +0.016% | +22.435% | +9.691% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_simple| 2.866% | -0.398% | +10.825% | +12.090% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chameleon| 1.851% | +0.005% | +12.113% | +9.581% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chaos| 0.811% | +0.253% | +9.156% | +9.968% | +-----+------------------------+--------+------------+------------+------------+ | :-| | crypto_pyaes| 0.536% | -0.134% | -0.203% | +7.148% | +-----+------------------------+--------+------------+------------+------------+ | :-| | deltablue| 1.466% | +0.547% | +13.517% | +15.466% | +-----+------------------------+--------+------------+------------+------------+ | :-| | django_template| 3.243% | +1.813% | +22.091% | +12.300% | +-----+------------------------+--------+------------+------------+------------+ | :-| | dulwich_log| 1.199% | +0.086% | +5.562% | +5.893% | +-----+------------------------+--------+------------+------------+------------+ | :-| | fannkuch| 0.820% | -0.054% | +7.113% | +5.258% | +-----+------------------------+--------+------------+------------+------------+ | :-| | float| 1.366% | -0.044% | +2.417% | +7.391% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_text| 1.328% | +0.197% | +14.421% | +9.417% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_xml| 1.693% | -0.101% | +11.164% | +9.817% | +-----+------------------------+--------+------------+------------+------------+ | :-| | go| 6.421% | -0.894% | +5.047% | +11.766% | +-----+------------------------+--------+------------+------------+------------+ | :-| | hexiom| 0.485% | -0.028% | +11.859% | +11.480% | +-----+------------------------+--------+------------+------------+------------+ | :-| | html5lib| 2.787% | -0.160% | +12.163% | +10.334% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_dumps| 1.841% | -0.242% | +3.108% | +8.889% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_loads| 7.141% | -1.121% | -5.156% | +17.338% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_format| 1.760% | +0.373% | +17.216% | +14.227% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_silent| 2.772% | +0.708% | +47.852% | +13.084% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_simple| 1.429% | +0.105% | +12.573% | +14.616% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mako| 0.579% | -0.167% | +17.148% | +14.133% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mdp| 6.939% | +0.074% | +0.409% | +18.709% | +-----+------------------------+--------+------------+------------+------------+ | :-| | meteor_contest| 0.654% | -0.082% | +4.561% | +5.973% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nbody| 0.672% | +0.118% | +0.948% | +0.899% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nqueens| 0.928% | -0.050% | +5.691% | +6.550% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pathlib| 1.366% | +0.233% | +0.745% | +10.217% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle| 1.270% | -0.538% | -0.984% | +21.031% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_dict| 0.342% | +0.055% | +7.467% | +18.033% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_list| 5.085% | -0.439% | +6.585% | +19.051% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_pure_python| 4.379% | +0.044% | +11.553% | +10.664% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pidigits| 0.212% | -0.025% | +0.038% | +10.611% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup| 0.119% | -0.034% | +18.812% | +5.319% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup_no_site| 0.091% | +0.010% | +5.801% | +5.531% | +-----+------------------------+--------+------------+------------+------------+ | :-| | raytrace| 0.960% | +0.374% | +10.028% | +14.352% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_compile| 4.816% | -0.168% | +5.991% | +10.032% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_dna| 0.172% | +0.183% | -0.569% | +12.153% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_effbot| 2.339% | -0.273% | -4.780% | +5.803% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_v8| 2.430% | +1.015% | +6.546% | +3.438% | +-----+------------------------+--------+------------+------------+------------+ | :-| | richards| 1.349% | -0.325% | +9.307% | +14.573% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_fft| 0.483% | +0.042% | -2.198% | +5.204% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_lu| 3.064% | -0.142% | +22.515% | +11.896% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_monte_carlo| 1.860% | -0.302% | +5.141% | +6.148% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sor| 1.536% | -0.219% | +14.970% | +9.777% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sparse_mat_mult| 1.529% | +0.182% | -2.239% | -2.383% | +-----+------------------------+--------+------------+------------+------------+ | :-| | spectral_norm| 0.515% | +0.096% | +4.217% | +3.728% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_declarative| 1.900% | +0.332% | +8.039% | +5.206% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_imperative| 3.924% | -0.477% | +7.726% | +5.259% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlite_synth| 4.528% | -0.839% | -0.049% | +9.744% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_expand| 3.446% | -0.094% | +17.452% | +7.416% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_integrate| 1.614% | -0.039% | +18.375% | +6.419% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_str| 4.097% | +0.467% | +19.334% | +8.035% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_sum| 6.257% | +0.072% | +16.258% | +11.437% | +-----+------------------------+--------+------------+------------+------------+ | :-| | telco| 3.809% | +0.849% | +19.983% | +6.930% | +-----+------------------------+--------+------------+------------+------------+ | :-| | tornado_http| 1.074% | -0.001% | +7.289% | +7.192% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpack_sequence| 1.780% | -0.221% | +2.417% | +2.772% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle| 4.072% | -0.814% | +9.422% | +21.118% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_list| 0.848% | +1.137% | -3.316% | +17.417% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_pure_python| 0.825% | +0.389% | +7.870% | +7.552% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_generate| 1.140% | +0.179% | +2.588% | +12.472% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_iterparse| 2.364% | -0.045% | +3.743% | +7.549% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_parse| 3.740% | -0.401% | -7.218% | +9.651% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_process| 1.360% | -0.116% | +4.230% | +11.375% | +-----+------------------------+--------+------------+------------+------------+ * Relative Standard Deviation (Standard Deviation/Average) If this is not displayed properly please visit our results page here: http://languagesperformance.intel.com/65-flat-results-for-python-master-branch-2018-05-09 Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. From webhook-mailer at python.org Thu May 10 04:27:34 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Thu, 10 May 2018 08:27:34 -0000 Subject: [Python-checkins] bpo-20171: Convert the _curses and _curses_panel modules to Argument Clinic. (GH-4251) Message-ID: https://github.com/python/cpython/commit/b00854caa080cec613496d3a5e1b0891c9ff83e6 commit: b00854caa080cec613496d3a5e1b0891c9ff83e6 branch: master author: Serhiy Storchaka committer: GitHub date: 2018-05-10T11:27:23+03:00 summary: bpo-20171: Convert the _curses and _curses_panel modules to Argument Clinic. (GH-4251) files: A Modules/clinic/_curses_panel.c.h M Include/py_curses.h M Modules/_curses_panel.c M Modules/_cursesmodule.c M Modules/clinic/_cursesmodule.c.h diff --git a/Include/py_curses.h b/Include/py_curses.h index 0eebc362a15e..2702b37ea7cf 100644 --- a/Include/py_curses.h +++ b/Include/py_curses.h @@ -91,65 +91,6 @@ static void **PyCurses_API; static const char catchall_ERR[] = "curses function returned ERR"; static const char catchall_NULL[] = "curses function returned NULL"; -/* Function Prototype Macros - They are ugly but very, very useful. ;-) - - X - function name - TYPE - parameter Type - ERGSTR - format string for construction of the return value - PARSESTR - format string for argument parsing - */ - -#define NoArgNoReturnFunction(X) \ -static PyObject *PyCurses_ ## X (PyObject *self) \ -{ \ - PyCursesInitialised \ - return PyCursesCheckERR(X(), # X); } - -#define NoArgOrFlagNoReturnFunction(X) \ -static PyObject *PyCurses_ ## X (PyObject *self, PyObject *args) \ -{ \ - int flag = 0; \ - PyCursesInitialised \ - switch(PyTuple_Size(args)) { \ - case 0: \ - return PyCursesCheckERR(X(), # X); \ - case 1: \ - if (!PyArg_ParseTuple(args, "i;True(1) or False(0)", &flag)) return NULL; \ - if (flag) return PyCursesCheckERR(X(), # X); \ - else return PyCursesCheckERR(no ## X (), # X); \ - default: \ - PyErr_SetString(PyExc_TypeError, # X " requires 0 or 1 arguments"); \ - return NULL; } } - -#define NoArgReturnIntFunction(X) \ -static PyObject *PyCurses_ ## X (PyObject *self) \ -{ \ - PyCursesInitialised \ - return PyLong_FromLong((long) X()); } - - -#define NoArgReturnStringFunction(X) \ -static PyObject *PyCurses_ ## X (PyObject *self) \ -{ \ - PyCursesInitialised \ - return PyBytes_FromString(X()); } - -#define NoArgTrueFalseFunction(X) \ -static PyObject *PyCurses_ ## X (PyObject *self) \ -{ \ - PyCursesInitialised \ - if (X () == FALSE) { \ - Py_RETURN_FALSE; \ - } \ - Py_RETURN_TRUE; } - -#define NoArgNoReturnVoidFunction(X) \ -static PyObject *PyCurses_ ## X (PyObject *self) \ -{ \ - PyCursesInitialised \ - X(); \ - Py_RETURN_NONE; } - #ifdef __cplusplus } #endif diff --git a/Modules/_curses_panel.c b/Modules/_curses_panel.c index a98d2bf3f85f..609718f65f15 100644 --- a/Modules/_curses_panel.c +++ b/Modules/_curses_panel.c @@ -162,38 +162,69 @@ find_po(PANEL *pan) return temp->po; } -/* Function Prototype Macros - They are ugly but very, very useful. ;-) - - X - function name - TYPE - parameter Type - ERGSTR - format string for construction of the return value - PARSESTR - format string for argument parsing */ - -#define Panel_NoArgNoReturnFunction(X) \ -static PyObject *PyCursesPanel_##X(PyCursesPanelObject *self) \ -{ return PyCursesCheckERR(X(self->pan), # X); } - -#define Panel_NoArgTrueFalseFunction(X) \ -static PyObject *PyCursesPanel_##X(PyCursesPanelObject *self) \ -{ \ - if (X (self->pan) == FALSE) { Py_RETURN_FALSE; } \ - else { Py_RETURN_TRUE; } } - -#define Panel_TwoArgNoReturnFunction(X, TYPE, PARSESTR) \ -static PyObject *PyCursesPanel_##X(PyCursesPanelObject *self, PyObject *args) \ -{ \ - TYPE arg1, arg2; \ - if (!PyArg_ParseTuple(args, PARSESTR, &arg1, &arg2)) return NULL; \ - return PyCursesCheckERR(X(self->pan, arg1, arg2), # X); } +/*[clinic input] +module _curses_panel +class _curses_panel.panel "PyCursesPanelObject *" "&PyCursesPanel_Type" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=2f4ef263ca850a31]*/ + +#include "clinic/_curses_panel.c.h" /* ------------- PANEL routines --------------- */ -Panel_NoArgNoReturnFunction(bottom_panel) -Panel_NoArgNoReturnFunction(hide_panel) -Panel_NoArgNoReturnFunction(show_panel) -Panel_NoArgNoReturnFunction(top_panel) -Panel_NoArgTrueFalseFunction(panel_hidden) -Panel_TwoArgNoReturnFunction(move_panel, int, "ii;y,x") +/*[clinic input] +_curses_panel.panel.bottom + +Push the panel to the bottom of the stack. +[clinic start generated code]*/ + +static PyObject * +_curses_panel_panel_bottom_impl(PyCursesPanelObject *self) +/*[clinic end generated code: output=7aa7d14d7e1d1ce6 input=b6c920c071b61e2e]*/ +{ + return PyCursesCheckERR(bottom_panel(self->pan), "bottom"); +} + +/*[clinic input] +_curses_panel.panel.hide + +Hide the panel. + +This does not delete the object, it just makes the window on screen invisible. +[clinic start generated code]*/ + +static PyObject * +_curses_panel_panel_hide_impl(PyCursesPanelObject *self) +/*[clinic end generated code: output=a7bbbd523e1eab49 input=f6ab884e99386118]*/ +{ + return PyCursesCheckERR(hide_panel(self->pan), "hide"); +} + +/*[clinic input] +_curses_panel.panel.show + +Display the panel (which might have been hidden). +[clinic start generated code]*/ + +static PyObject * +_curses_panel_panel_show_impl(PyCursesPanelObject *self) +/*[clinic end generated code: output=6b4553ab45c97769 input=57b167bbefaa3755]*/ +{ + return PyCursesCheckERR(show_panel(self->pan), "show"); +} + +/*[clinic input] +_curses_panel.panel.top + +Push panel to the top of the stack. +[clinic start generated code]*/ + +static PyObject * +_curses_panel_panel_top_impl(PyCursesPanelObject *self) +/*[clinic end generated code: output=0f5f2f8cdd2d1777 input=be33975ec3ca0e9a]*/ +{ + return PyCursesCheckERR(top_panel(self->pan), "top"); +} /* Allocation and deallocation of Panel Objects */ @@ -234,8 +265,15 @@ PyCursesPanel_Dealloc(PyCursesPanelObject *po) /* panel_above(NULL) returns the bottom panel in the stack. To get this behaviour we use curses.panel.bottom_panel(). */ +/*[clinic input] +_curses_panel.panel.above + +Return the panel above the current panel. +[clinic start generated code]*/ + static PyObject * -PyCursesPanel_above(PyCursesPanelObject *self) +_curses_panel_panel_above_impl(PyCursesPanelObject *self) +/*[clinic end generated code: output=70ac06d25fd3b4da input=c059994022976788]*/ { PANEL *pan; PyCursesPanelObject *po; @@ -258,8 +296,15 @@ PyCursesPanel_above(PyCursesPanelObject *self) /* panel_below(NULL) returns the top panel in the stack. To get this behaviour we use curses.panel.top_panel(). */ +/*[clinic input] +_curses_panel.panel.below + +Return the panel below the current panel. +[clinic start generated code]*/ + static PyObject * -PyCursesPanel_below(PyCursesPanelObject *self) +_curses_panel_panel_below_impl(PyCursesPanelObject *self) +/*[clinic end generated code: output=282861122e06e3de input=cc08f61936d297c6]*/ { PANEL *pan; PyCursesPanelObject *po; @@ -280,28 +325,70 @@ PyCursesPanel_below(PyCursesPanelObject *self) return (PyObject *)po; } +/*[clinic input] +_curses_panel.panel.hidden + +Return True if the panel is hidden (not visible), False otherwise. +[clinic start generated code]*/ + static PyObject * -PyCursesPanel_window(PyCursesPanelObject *self) +_curses_panel_panel_hidden_impl(PyCursesPanelObject *self) +/*[clinic end generated code: output=66eebd1ab4501a71 input=453d4b4fce25e21a]*/ +{ + if (panel_hidden(self->pan)) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; +} + +/*[clinic input] +_curses_panel.panel.move + + y: int + x: int + / + +Move the panel to the screen coordinates (y, x). +[clinic start generated code]*/ + +static PyObject * +_curses_panel_panel_move_impl(PyCursesPanelObject *self, int y, int x) +/*[clinic end generated code: output=d867535a89777415 input=e0b36b78acc03fba]*/ +{ + return PyCursesCheckERR(move_panel(self->pan, y, x), "move_panel"); +} + +/*[clinic input] +_curses_panel.panel.window + +Return the window object associated with the panel. +[clinic start generated code]*/ + +static PyObject * +_curses_panel_panel_window_impl(PyCursesPanelObject *self) +/*[clinic end generated code: output=5f05940d4106b4cb input=6067353d2c307901]*/ { Py_INCREF(self->wo); return (PyObject *)self->wo; } +/*[clinic input] +_curses_panel.panel.replace + + win: object(type="PyCursesWindowObject *", subclass_of="&PyCursesWindow_Type") + / + +Change the window associated with the panel to the window win. +[clinic start generated code]*/ + static PyObject * -PyCursesPanel_replace_panel(PyCursesPanelObject *self, PyObject *args) +_curses_panel_panel_replace_impl(PyCursesPanelObject *self, + PyCursesWindowObject *win) +/*[clinic end generated code: output=2253a95f7b287255 input=4b1c4283987d9dfa]*/ { PyCursesPanelObject *po; - PyCursesWindowObject *temp; int rtn; - if (PyTuple_Size(args) != 1) { - PyErr_SetString(PyExc_TypeError, "replace requires one argument"); - return NULL; - } - if (!PyArg_ParseTuple(args, "O!;window object", - &PyCursesWindow_Type, &temp)) - return NULL; - po = find_po(self->pan); if (po == NULL) { PyErr_SetString(PyExc_RuntimeError, @@ -309,18 +396,28 @@ PyCursesPanel_replace_panel(PyCursesPanelObject *self, PyObject *args) return NULL; } - rtn = replace_panel(self->pan, temp->win); + rtn = replace_panel(self->pan, win->win); if (rtn == ERR) { PyErr_SetString(_curses_panelstate_global->PyCursesError, "replace_panel() returned ERR"); return NULL; } - Py_INCREF(temp); - Py_SETREF(po->wo, temp); + Py_INCREF(win); + Py_SETREF(po->wo, win); Py_RETURN_NONE; } +/*[clinic input] +_curses_panel.panel.set_userptr + + obj: object + / + +Set the panel?s user pointer to obj. +[clinic start generated code]*/ + static PyObject * -PyCursesPanel_set_panel_userptr(PyCursesPanelObject *self, PyObject *obj) +_curses_panel_panel_set_userptr(PyCursesPanelObject *self, PyObject *obj) +/*[clinic end generated code: output=6fb145b3af88cf4a input=2056be1cd148b05c]*/ { PyObject *oldobj; int rc; @@ -336,8 +433,15 @@ PyCursesPanel_set_panel_userptr(PyCursesPanelObject *self, PyObject *obj) return PyCursesCheckERR(rc, "set_panel_userptr"); } +/*[clinic input] +_curses_panel.panel.userptr + +Return the user pointer for the panel. +[clinic start generated code]*/ + static PyObject * -PyCursesPanel_userptr(PyCursesPanelObject *self) +_curses_panel_panel_userptr_impl(PyCursesPanelObject *self) +/*[clinic end generated code: output=e849c307b5dc9237 input=f78b7a47aef0fd50]*/ { PyObject *obj; PyCursesInitialised; @@ -355,18 +459,18 @@ PyCursesPanel_userptr(PyCursesPanelObject *self) /* Module interface */ static PyMethodDef PyCursesPanel_Methods[] = { - {"above", (PyCFunction)PyCursesPanel_above, METH_NOARGS}, - {"below", (PyCFunction)PyCursesPanel_below, METH_NOARGS}, - {"bottom", (PyCFunction)PyCursesPanel_bottom_panel, METH_NOARGS}, - {"hidden", (PyCFunction)PyCursesPanel_panel_hidden, METH_NOARGS}, - {"hide", (PyCFunction)PyCursesPanel_hide_panel, METH_NOARGS}, - {"move", (PyCFunction)PyCursesPanel_move_panel, METH_VARARGS}, - {"replace", (PyCFunction)PyCursesPanel_replace_panel, METH_VARARGS}, - {"set_userptr", (PyCFunction)PyCursesPanel_set_panel_userptr, METH_O}, - {"show", (PyCFunction)PyCursesPanel_show_panel, METH_NOARGS}, - {"top", (PyCFunction)PyCursesPanel_top_panel, METH_NOARGS}, - {"userptr", (PyCFunction)PyCursesPanel_userptr, METH_NOARGS}, - {"window", (PyCFunction)PyCursesPanel_window, METH_NOARGS}, + _CURSES_PANEL_PANEL_ABOVE_METHODDEF + _CURSES_PANEL_PANEL_BELOW_METHODDEF + _CURSES_PANEL_PANEL_BOTTOM_METHODDEF + _CURSES_PANEL_PANEL_HIDDEN_METHODDEF + _CURSES_PANEL_PANEL_HIDE_METHODDEF + _CURSES_PANEL_PANEL_MOVE_METHODDEF + _CURSES_PANEL_PANEL_REPLACE_METHODDEF + _CURSES_PANEL_PANEL_SET_USERPTR_METHODDEF + _CURSES_PANEL_PANEL_SHOW_METHODDEF + _CURSES_PANEL_PANEL_TOP_METHODDEF + _CURSES_PANEL_PANEL_USERPTR_METHODDEF + _CURSES_PANEL_PANEL_WINDOW_METHODDEF {NULL, NULL} /* sentinel */ }; @@ -379,7 +483,7 @@ static PyType_Slot PyCursesPanel_Type_slots[] = { }; static PyType_Spec PyCursesPanel_Type_spec = { - "_curses_panel.curses panel", + "_curses_panel.panel", sizeof(PyCursesPanelObject), 0, Py_TPFLAGS_DEFAULT, @@ -390,8 +494,15 @@ static PyType_Spec PyCursesPanel_Type_spec = { panel of the stack, so it's renamed to bottom_panel(). panel.above() *requires* a panel object in the first place which may be undesirable. */ +/*[clinic input] +_curses_panel.bottom_panel + +Return the bottom panel in the panel stack. +[clinic start generated code]*/ + static PyObject * -PyCurses_bottom_panel(PyObject *self) +_curses_panel_bottom_panel_impl(PyObject *module) +/*[clinic end generated code: output=3aba9f985f4c2bd0 input=634c2a8078b3d7e4]*/ { PANEL *pan; PyCursesPanelObject *po; @@ -414,15 +525,20 @@ PyCurses_bottom_panel(PyObject *self) return (PyObject *)po; } +/*[clinic input] +_curses_panel.new_panel + + win: object(type="PyCursesWindowObject *", subclass_of="&PyCursesWindow_Type") + / + +Return a panel object, associating it with the given window win. +[clinic start generated code]*/ + static PyObject * -PyCurses_new_panel(PyObject *self, PyObject *args) +_curses_panel_new_panel_impl(PyObject *module, PyCursesWindowObject *win) +/*[clinic end generated code: output=45e948e0176a9bd2 input=74d4754e0ebe4800]*/ { - PyCursesWindowObject *win; - PANEL *pan; - - if (!PyArg_ParseTuple(args, "O!", &PyCursesWindow_Type, &win)) - return NULL; - pan = new_panel(win->win); + PANEL *pan = new_panel(win->win); if (pan == NULL) { PyErr_SetString(_curses_panelstate_global->PyCursesError, catchall_NULL); return NULL; @@ -435,8 +551,15 @@ PyCurses_new_panel(PyObject *self, PyObject *args) of the stack, so it's renamed to top_panel(). panel.below() *requires* a panel object in the first place which may be undesirable. */ +/*[clinic input] +_curses_panel.top_panel + +Return the top panel in the panel stack. +[clinic start generated code]*/ + static PyObject * -PyCurses_top_panel(PyObject *self) +_curses_panel_top_panel_impl(PyObject *module) +/*[clinic end generated code: output=86704988bea8508e input=e62d6278dba39e79]*/ { PANEL *pan; PyCursesPanelObject *po; @@ -459,7 +582,17 @@ PyCurses_top_panel(PyObject *self) return (PyObject *)po; } -static PyObject *PyCurses_update_panels(PyObject *self) +/*[clinic input] +_curses_panel.update_panels + +Updates the virtual screen after changes in the panel stack. + +This does not call curses.doupdate(), so you?ll have to do this yourself. +[clinic start generated code]*/ + +static PyObject * +_curses_panel_update_panels_impl(PyObject *module) +/*[clinic end generated code: output=2f3b4c2e03d90ded input=a127069202b0a097]*/ { PyCursesInitialised; update_panels(); @@ -470,10 +603,10 @@ static PyObject *PyCurses_update_panels(PyObject *self) /* List of functions defined in the module */ static PyMethodDef PyCurses_methods[] = { - {"bottom_panel", (PyCFunction)PyCurses_bottom_panel, METH_NOARGS}, - {"new_panel", (PyCFunction)PyCurses_new_panel, METH_VARARGS}, - {"top_panel", (PyCFunction)PyCurses_top_panel, METH_NOARGS}, - {"update_panels", (PyCFunction)PyCurses_update_panels, METH_NOARGS}, + _CURSES_PANEL_BOTTOM_PANEL_METHODDEF + _CURSES_PANEL_NEW_PANEL_METHODDEF + _CURSES_PANEL_TOP_PANEL_METHODDEF + _CURSES_PANEL_UPDATE_PANELS_METHODDEF {NULL, NULL} /* sentinel */ }; @@ -523,6 +656,9 @@ PyInit__curses_panel(void) PyDict_SetItemString(d, "version", v); PyDict_SetItemString(d, "__version__", v); Py_DECREF(v); + + Py_INCREF(_curses_panelstate(m)->PyCursesPanel_Type); + PyModule_AddObject(m, "panel", (PyObject *)_curses_panelstate(m)->PyCursesPanel_Type); return m; fail: Py_XDECREF(m); diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c index 7936aef0cc90..fe4c9d15c2f2 100644 --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -135,12 +135,10 @@ typedef chtype attr_t; /* No attr_t type is available */ #endif /*[clinic input] -module curses -class curses.window "PyCursesWindowObject *" "&PyCursesWindow_Type" +module _curses +class _curses.window "PyCursesWindowObject *" "&PyCursesWindow_Type" [clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=88c860abdbb50e0c]*/ - -#include "clinic/_cursesmodule.c.h" +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=43265c372c2887d6]*/ /* Definition of exception curses.error */ @@ -423,8 +421,7 @@ PyTypeObject PyCursesWindow_Type; static PyObject * PyCursesWindow_ ## X \ (PyCursesWindowObject *self) \ { \ - if (X (self->win) == FALSE) { Py_RETURN_FALSE; } \ - else { Py_RETURN_TRUE; } } + return PyBool_FromLong(X(self->win)); } #define Window_NoArgNoReturnVoidFunction(X) \ static PyObject * PyCursesWindow_ ## X \ @@ -562,26 +559,25 @@ PyCursesWindow_Dealloc(PyCursesWindowObject *wo) /* Addch, Addstr, Addnstr */ /*[clinic input] - -curses.window.addch +_curses.window.addch [ y: int - Y-coordinate. + Y-coordinate. x: int - X-coordinate. + X-coordinate. ] ch: object - Character to add. + Character to add. [ - attr: long - Attributes for the character. + attr: long(c_default="A_NORMAL") = _curses.A_NORMAL + Attributes for the character. ] / -Paint character ch at (y, x) with attributes attr. +Paint the character. Paint character ch at (y, x) with attributes attr, overwriting any character previously painted at that location. @@ -590,13 +586,12 @@ current settings for the window object. [clinic start generated code]*/ static PyObject * -curses_window_addch_impl(PyCursesWindowObject *self, int group_left_1, int y, - int x, PyObject *ch, int group_right_1, long attr) -/*[clinic end generated code: output=99f7f85078ec06c3 input=5a41efb34a2de338]*/ +_curses_window_addch_impl(PyCursesWindowObject *self, int group_left_1, + int y, int x, PyObject *ch, int group_right_1, + long attr) +/*[clinic end generated code: output=00f4c37af3378f45 input=95ce131578458196]*/ { - PyCursesWindowObject *cwself = (PyCursesWindowObject *)self; int coordinates_group = group_left_1; - int attr_group = group_right_1; int rtn; int type; chtype cch = 0; @@ -606,31 +601,28 @@ curses_window_addch_impl(PyCursesWindowObject *self, int group_left_1, int y, #endif const char *funcname; - if (!attr_group) - attr = A_NORMAL; - #ifdef HAVE_NCURSESW - type = PyCurses_ConvertToCchar_t(cwself, ch, &cch, wstr); + type = PyCurses_ConvertToCchar_t(self, ch, &cch, wstr); if (type == 2) { funcname = "add_wch"; wstr[1] = L'\0'; setcchar(&wcval, wstr, attr, 0, NULL); if (coordinates_group) - rtn = mvwadd_wch(cwself->win,y,x, &wcval); + rtn = mvwadd_wch(self->win,y,x, &wcval); else { - rtn = wadd_wch(cwself->win, &wcval); + rtn = wadd_wch(self->win, &wcval); } } else #else - type = PyCurses_ConvertToCchar_t(cwself, ch, &cch); + type = PyCurses_ConvertToCchar_t(self, ch, &cch); #endif if (type == 1) { funcname = "addch"; if (coordinates_group) - rtn = mvwaddch(cwself->win,y,x, cch | attr); + rtn = mvwaddch(self->win,y,x, cch | (attr_t) attr); else { - rtn = waddch(cwself->win, cch | attr); + rtn = waddch(self->win, cch | (attr_t) attr); } } else { @@ -639,62 +631,64 @@ curses_window_addch_impl(PyCursesWindowObject *self, int group_left_1, int y, return PyCursesCheckERR(rtn, funcname); } +/*[clinic input] +_curses.window.addstr + + [ + y: int + Y-coordinate. + x: int + X-coordinate. + ] + + str: object + String to add. + + [ + attr: long + Attributes for characters. + ] + / + +Paint the string. + +Paint the string str at (y, x) with attributes attr, +overwriting anything previously on the display. +By default, the character position and attributes are the +current settings for the window object. +[clinic start generated code]*/ + static PyObject * -PyCursesWindow_AddStr(PyCursesWindowObject *self, PyObject *args) +_curses_window_addstr_impl(PyCursesWindowObject *self, int group_left_1, + int y, int x, PyObject *str, int group_right_1, + long attr) +/*[clinic end generated code: output=65a928ea85ff3115 input=ff6cbb91448a22a3]*/ { int rtn; - int x, y; int strtype; - PyObject *strobj, *bytesobj = NULL; + PyObject *bytesobj = NULL; #ifdef HAVE_NCURSESW wchar_t *wstr = NULL; #endif - attr_t attr = A_NORMAL , attr_old = A_NORMAL; - long lattr; - int use_xy = FALSE, use_attr = FALSE; + attr_t attr_old = A_NORMAL; + int use_xy = group_left_1, use_attr = group_right_1; const char *funcname; - switch (PyTuple_Size(args)) { - case 1: - if (!PyArg_ParseTuple(args,"O;str", &strobj)) - return NULL; - break; - case 2: - if (!PyArg_ParseTuple(args,"Ol;str,attr", &strobj, &lattr)) - return NULL; - attr = lattr; - use_attr = TRUE; - break; - case 3: - if (!PyArg_ParseTuple(args,"iiO;int,int,str", &y, &x, &strobj)) - return NULL; - use_xy = TRUE; - break; - case 4: - if (!PyArg_ParseTuple(args,"iiOl;int,int,str,attr", &y, &x, &strobj, &lattr)) - return NULL; - attr = lattr; - use_xy = use_attr = TRUE; - break; - default: - PyErr_SetString(PyExc_TypeError, "addstr requires 1 to 4 arguments"); - return NULL; - } #ifdef HAVE_NCURSESW - strtype = PyCurses_ConvertToString(self, strobj, &bytesobj, &wstr); + strtype = PyCurses_ConvertToString(self, str, &bytesobj, &wstr); #else - strtype = PyCurses_ConvertToString(self, strobj, &bytesobj, NULL); + strtype = PyCurses_ConvertToString(self, str, &bytesobj, NULL); #endif if (strtype == 0) return NULL; - if (use_attr == TRUE) { + if (use_attr) { attr_old = getattrs(self->win); (void)wattrset(self->win,attr); } #ifdef HAVE_NCURSESW if (strtype == 2) { funcname = "addwstr"; - if (use_xy == TRUE) + if (use_xy) rtn = mvwaddwstr(self->win,y,x,wstr); else rtn = waddwstr(self->win,wstr); @@ -705,73 +699,79 @@ PyCursesWindow_AddStr(PyCursesWindowObject *self, PyObject *args) { char *str = PyBytes_AS_STRING(bytesobj); funcname = "addstr"; - if (use_xy == TRUE) + if (use_xy) rtn = mvwaddstr(self->win,y,x,str); else rtn = waddstr(self->win,str); Py_DECREF(bytesobj); } - if (use_attr == TRUE) + if (use_attr) (void)wattrset(self->win,attr_old); return PyCursesCheckERR(rtn, funcname); } +/*[clinic input] +_curses.window.addnstr + + [ + y: int + Y-coordinate. + x: int + X-coordinate. + ] + + str: object + String to add. + + n: int + Maximal number of characters. + + [ + attr: long + Attributes for characters. + ] + / + +Paint at most n characters of the string. + +Paint at most n characters of the string str at (y, x) with +attributes attr, overwriting anything previously on the display. +By default, the character position and attributes are the +current settings for the window object. +[clinic start generated code]*/ + static PyObject * -PyCursesWindow_AddNStr(PyCursesWindowObject *self, PyObject *args) +_curses_window_addnstr_impl(PyCursesWindowObject *self, int group_left_1, + int y, int x, PyObject *str, int n, + int group_right_1, long attr) +/*[clinic end generated code: output=6d21cee2ce6876d9 input=72718415c2744a2a]*/ { - int rtn, x, y, n; + int rtn; int strtype; - PyObject *strobj, *bytesobj = NULL; + PyObject *bytesobj = NULL; #ifdef HAVE_NCURSESW wchar_t *wstr = NULL; #endif - attr_t attr = A_NORMAL , attr_old = A_NORMAL; - long lattr; - int use_xy = FALSE, use_attr = FALSE; + attr_t attr_old = A_NORMAL; + int use_xy = group_left_1, use_attr = group_right_1; const char *funcname; - switch (PyTuple_Size(args)) { - case 2: - if (!PyArg_ParseTuple(args,"Oi;str,n", &strobj, &n)) - return NULL; - break; - case 3: - if (!PyArg_ParseTuple(args,"Oil;str,n,attr", &strobj, &n, &lattr)) - return NULL; - attr = lattr; - use_attr = TRUE; - break; - case 4: - if (!PyArg_ParseTuple(args,"iiOi;y,x,str,n", &y, &x, &strobj, &n)) - return NULL; - use_xy = TRUE; - break; - case 5: - if (!PyArg_ParseTuple(args,"iiOil;y,x,str,n,attr", &y, &x, &strobj, &n, &lattr)) - return NULL; - attr = lattr; - use_xy = use_attr = TRUE; - break; - default: - PyErr_SetString(PyExc_TypeError, "addnstr requires 2 to 5 arguments"); - return NULL; - } #ifdef HAVE_NCURSESW - strtype = PyCurses_ConvertToString(self, strobj, &bytesobj, &wstr); + strtype = PyCurses_ConvertToString(self, str, &bytesobj, &wstr); #else - strtype = PyCurses_ConvertToString(self, strobj, &bytesobj, NULL); + strtype = PyCurses_ConvertToString(self, str, &bytesobj, NULL); #endif if (strtype == 0) return NULL; - if (use_attr == TRUE) { + if (use_attr) { attr_old = getattrs(self->win); (void)wattrset(self->win,attr); } #ifdef HAVE_NCURSESW if (strtype == 2) { funcname = "addnwstr"; - if (use_xy == TRUE) + if (use_xy) rtn = mvwaddnwstr(self->win,y,x,wstr,n); else rtn = waddnwstr(self->win,wstr,n); @@ -782,125 +782,172 @@ PyCursesWindow_AddNStr(PyCursesWindowObject *self, PyObject *args) { char *str = PyBytes_AS_STRING(bytesobj); funcname = "addnstr"; - if (use_xy == TRUE) + if (use_xy) rtn = mvwaddnstr(self->win,y,x,str,n); else rtn = waddnstr(self->win,str,n); Py_DECREF(bytesobj); } - if (use_attr == TRUE) + if (use_attr) (void)wattrset(self->win,attr_old); return PyCursesCheckERR(rtn, funcname); } +/*[clinic input] +_curses.window.bkgd + + ch: object + Background character. + attr: long(c_default="A_NORMAL") = _curses.A_NORMAL + Background attributes. + / + +Set the background property of the window. +[clinic start generated code]*/ + static PyObject * -PyCursesWindow_Bkgd(PyCursesWindowObject *self, PyObject *args) +_curses_window_bkgd_impl(PyCursesWindowObject *self, PyObject *ch, long attr) +/*[clinic end generated code: output=058290afb2cf4034 input=634015bcb339283d]*/ { - PyObject *temp; chtype bkgd; - attr_t attr = A_NORMAL; - long lattr; - - switch (PyTuple_Size(args)) { - case 1: - if (!PyArg_ParseTuple(args, "O;ch or int", &temp)) - return NULL; - break; - case 2: - if (!PyArg_ParseTuple(args,"Ol;ch or int,attr", &temp, &lattr)) - return NULL; - attr = lattr; - break; - default: - PyErr_SetString(PyExc_TypeError, "bkgd requires 1 or 2 arguments"); - return NULL; - } - if (!PyCurses_ConvertToChtype(self, temp, &bkgd)) + if (!PyCurses_ConvertToChtype(self, ch, &bkgd)) return NULL; return PyCursesCheckERR(wbkgd(self->win, bkgd | attr), "bkgd"); } +/*[clinic input] +_curses.window.attroff + + attr: long + / + +Remove attribute attr from the "background" set. +[clinic start generated code]*/ + static PyObject * -PyCursesWindow_AttrOff(PyCursesWindowObject *self, PyObject *args) +_curses_window_attroff_impl(PyCursesWindowObject *self, long attr) +/*[clinic end generated code: output=8a2fcd4df682fc64 input=786beedf06a7befe]*/ { - long lattr; - if (!PyArg_ParseTuple(args,"l;attr", &lattr)) - return NULL; - return PyCursesCheckERR(wattroff(self->win, (attr_t)lattr), "attroff"); + return PyCursesCheckERR(wattroff(self->win, (attr_t)attr), "attroff"); } +/*[clinic input] +_curses.window.attron + + attr: long + / + +Add attribute attr from the "background" set. +[clinic start generated code]*/ + static PyObject * -PyCursesWindow_AttrOn(PyCursesWindowObject *self, PyObject *args) +_curses_window_attron_impl(PyCursesWindowObject *self, long attr) +/*[clinic end generated code: output=7afea43b237fa870 input=5a88fba7b1524f32]*/ { - long lattr; - if (!PyArg_ParseTuple(args,"l;attr", &lattr)) - return NULL; - return PyCursesCheckERR(wattron(self->win, (attr_t)lattr), "attron"); + return PyCursesCheckERR(wattron(self->win, (attr_t)attr), "attron"); } +/*[clinic input] +_curses.window.attrset + + attr: long + / + +Set the "background" set of attributes. +[clinic start generated code]*/ + static PyObject * -PyCursesWindow_AttrSet(PyCursesWindowObject *self, PyObject *args) +_curses_window_attrset_impl(PyCursesWindowObject *self, long attr) +/*[clinic end generated code: output=84e379bff20c0433 input=42e400c0d0154ab5]*/ { - long lattr; - if (!PyArg_ParseTuple(args,"l;attr", &lattr)) - return NULL; - return PyCursesCheckERR(wattrset(self->win, (attr_t)lattr), "attrset"); + return PyCursesCheckERR(wattrset(self->win, (attr_t)attr), "attrset"); } +/*[clinic input] +_curses.window.bkgdset + + ch: object + Background character. + attr: long(c_default="A_NORMAL") = _curses.A_NORMAL + Background attributes. + / + +Set the window's background. +[clinic start generated code]*/ + static PyObject * -PyCursesWindow_BkgdSet(PyCursesWindowObject *self, PyObject *args) +_curses_window_bkgdset_impl(PyCursesWindowObject *self, PyObject *ch, + long attr) +/*[clinic end generated code: output=8cb994fc4d7e2496 input=e09c682425c9e45b]*/ { - PyObject *temp; chtype bkgd; - attr_t attr = A_NORMAL; - long lattr; - - switch (PyTuple_Size(args)) { - case 1: - if (!PyArg_ParseTuple(args, "O;ch or int", &temp)) - return NULL; - break; - case 2: - if (!PyArg_ParseTuple(args,"Ol;ch or int,attr", &temp, &lattr)) - return NULL; - attr = lattr; - break; - default: - PyErr_SetString(PyExc_TypeError, "bkgdset requires 1 or 2 arguments"); - return NULL; - } - if (!PyCurses_ConvertToChtype(self, temp, &bkgd)) + if (!PyCurses_ConvertToChtype(self, ch, &bkgd)) return NULL; wbkgdset(self->win, bkgd | attr); return PyCursesCheckERR(0, "bkgdset"); } +/*[clinic input] +_curses.window.border + + ls: object(c_default="NULL") = _curses.ACS_VLINE + Left side. + rs: object(c_default="NULL") = _curses.ACS_VLINE + Right side. + ts: object(c_default="NULL") = _curses.ACS_HLINE + Top side. + bs: object(c_default="NULL") = _curses.ACS_HLINE + Bottom side. + tl: object(c_default="NULL") = _curses.ACS_ULCORNER + Upper-left corner. + tr: object(c_default="NULL") = _curses.ACS_URCORNER + Upper-right corner. + bl: object(c_default="NULL") = _curses.ACS_LLCORNER + Bottom-left corner. + br: object(c_default="NULL") = _curses.ACS_LRCORNER + Bottom-right corner. + / + +Draw a border around the edges of the window. + +Each parameter specifies the character to use for a specific part of the +border. The characters can be specified as integers or as one-character +strings. A 0 value for any parameter will cause the default character to be +used for that parameter. +[clinic start generated code]*/ + static PyObject * -PyCursesWindow_Border(PyCursesWindowObject *self, PyObject *args) +_curses_window_border_impl(PyCursesWindowObject *self, PyObject *ls, + PyObject *rs, PyObject *ts, PyObject *bs, + PyObject *tl, PyObject *tr, PyObject *bl, + PyObject *br) +/*[clinic end generated code: output=670ef38d3d7c2aa3 input=e015f735d67a240b]*/ { - PyObject *temp[8]; chtype ch[8]; int i; /* Clear the array of parameters */ - for(i=0; i<8; i++) { - temp[i] = NULL; + for(i=0; i<8; i++) ch[i] = 0; - } - if (!PyArg_ParseTuple(args,"|OOOOOOOO;ls,rs,ts,bs,tl,tr,bl,br", - &temp[0], &temp[1], &temp[2], &temp[3], - &temp[4], &temp[5], &temp[6], &temp[7])) +#define CONVERTTOCHTYPE(obj, i) \ + if ((obj) != NULL && !PyCurses_ConvertToChtype(self, (obj), &ch[(i)])) \ return NULL; - for(i=0; i<8; i++) { - if (temp[i] != NULL && !PyCurses_ConvertToChtype(self, temp[i], &ch[i])) - return NULL; - } + CONVERTTOCHTYPE(ls, 0); + CONVERTTOCHTYPE(rs, 1); + CONVERTTOCHTYPE(ts, 2); + CONVERTTOCHTYPE(bs, 3); + CONVERTTOCHTYPE(tl, 4); + CONVERTTOCHTYPE(tr, 5); + CONVERTTOCHTYPE(bl, 6); + CONVERTTOCHTYPE(br, 7); + +#undef CONVERTTOCHTYPE wborder(self->win, ch[0], ch[1], ch[2], ch[3], @@ -908,20 +955,34 @@ PyCursesWindow_Border(PyCursesWindowObject *self, PyObject *args) Py_RETURN_NONE; } +/*[clinic input] +_curses.window.box + + [ + verch: object(c_default="_PyLong_Zero") = 0 + Left and right side. + horch: object(c_default="_PyLong_Zero") = 0 + Top and bottom side. + ] + / + +Draw a border around the edges of the window. + +Similar to border(), but both ls and rs are verch and both ts and bs are +horch. The default corner characters are always used by this function. +[clinic start generated code]*/ + static PyObject * -PyCursesWindow_Box(PyCursesWindowObject *self, PyObject *args) +_curses_window_box_impl(PyCursesWindowObject *self, int group_right_1, + PyObject *verch, PyObject *horch) +/*[clinic end generated code: output=f3fcb038bb287192 input=465a121741c1efdf]*/ { - PyObject *temp1, *temp2; - chtype ch1=0,ch2=0; - switch(PyTuple_Size(args)){ - case 0: break; - default: - if (!PyArg_ParseTuple(args,"OO;verch,horch", &temp1, &temp2)) - return NULL; - if (!PyCurses_ConvertToChtype(self, temp1, &ch1)) { + chtype ch1 = 0, ch2 = 0; + if (group_right_1) { + if (!PyCurses_ConvertToChtype(self, verch, &ch1)) { return NULL; } - if (!PyCurses_ConvertToChtype(self, temp2, &ch2)) { + if (!PyCurses_ConvertToChtype(self, horch, &ch2)) { return NULL; } } @@ -949,6 +1010,32 @@ int py_mvwdelch(WINDOW *w, int y, int x) /* chgat, added by Fabian Kreutz */ #ifdef HAVE_CURSES_WCHGAT +/*[-clinic input] +_curses.window.chgat + + [ + y: int + Y-coordinate. + x: int + X-coordinate. + ] + + n: int = -1 + Number of characters. + + attr: long + Attributes for characters. + / + +Set the attributes of characters. + +Set the attributes of num characters at the current cursor position, or at +position (y, x) if supplied. If no value of num is given or num = -1, the +attribute will be set on all the characters to the end of the line. This +function does not move the cursor. The changed line will be touched using +the touchline() method so that the contents will be redisplayed by the next +window refresh. +[-clinic start generated code]*/ static PyObject * PyCursesWindow_ChgAt(PyCursesWindowObject *self, PyObject *args) { @@ -991,7 +1078,7 @@ PyCursesWindow_ChgAt(PyCursesWindowObject *self, PyObject *args) color = (short)((attr >> 8) & 0xff); attr = attr - (color << 8); - if (use_xy == TRUE) { + if (use_xy) { rtn = mvwchgat(self->win,y,x,num,attr,color,NULL); touchline(self->win,y,1); } else { @@ -1003,50 +1090,61 @@ PyCursesWindow_ChgAt(PyCursesWindowObject *self, PyObject *args) } #endif +/*[clinic input] +_curses.window.delch + + [ + y: int + Y-coordinate. + x: int + X-coordinate. + ] + / + +Delete any character at (y, x). +[clinic start generated code]*/ + static PyObject * -PyCursesWindow_DelCh(PyCursesWindowObject *self, PyObject *args) +_curses_window_delch_impl(PyCursesWindowObject *self, int group_right_1, + int y, int x) +/*[clinic end generated code: output=22e77bb9fa11b461 input=d2f79e630a4fc6d0]*/ { - int rtn; - int x, y; - - switch (PyTuple_Size(args)) { - case 0: - rtn = wdelch(self->win); - break; - case 2: - if (!PyArg_ParseTuple(args,"ii;y,x", &y, &x)) - return NULL; - rtn = py_mvwdelch(self->win,y,x); - break; - default: - PyErr_SetString(PyExc_TypeError, "delch requires 0 or 2 arguments"); - return NULL; + if (!group_right_1) { + return PyCursesCheckERR(wdelch(self->win), "wdelch"); + } + else { + return PyCursesCheckERR(py_mvwdelch(self->win, y, x), "mvwdelch"); } - return PyCursesCheckERR(rtn, "[mv]wdelch"); } +/*[clinic input] +_curses.window.derwin + + [ + nlines: int = 0 + Height. + ncols: int = 0 + Width. + ] + begin_y: int + Top side y-coordinate. + begin_x: int + Left side x-coordinate. + / + +Create a sub-window (window-relative coordinates). + +derwin() is the same as calling subwin(), except that begin_y and begin_x +are relative to the origin of the window, rather than relative to the entire +screen. +[clinic start generated code]*/ + static PyObject * -PyCursesWindow_DerWin(PyCursesWindowObject *self, PyObject *args) +_curses_window_derwin_impl(PyCursesWindowObject *self, int group_left_1, + int nlines, int ncols, int begin_y, int begin_x) +/*[clinic end generated code: output=7924b112d9f70d6e input=966d9481f7f5022e]*/ { WINDOW *win; - int nlines, ncols, begin_y, begin_x; - - nlines = 0; - ncols = 0; - switch (PyTuple_Size(args)) { - case 2: - if (!PyArg_ParseTuple(args,"ii;begin_y,begin_x",&begin_y,&begin_x)) - return NULL; - break; - case 4: - if (!PyArg_ParseTuple(args, "iiii;nlines,ncols,begin_y,begin_x", - &nlines,&ncols,&begin_y,&begin_x)) - return NULL; - break; - default: - PyErr_SetString(PyExc_TypeError, "derwin requires 2 or 4 arguments"); - return NULL; - } win = derwin(self->win,nlines,ncols,begin_y,begin_x); @@ -1058,112 +1156,145 @@ PyCursesWindow_DerWin(PyCursesWindowObject *self, PyObject *args) return (PyObject *)PyCursesWindow_New(win, NULL); } -static PyObject * -PyCursesWindow_EchoChar(PyCursesWindowObject *self, PyObject *args) -{ - PyObject *temp; - chtype ch; - attr_t attr = A_NORMAL; - long lattr; +/*[clinic input] +_curses.window.echochar - switch (PyTuple_Size(args)) { - case 1: - if (!PyArg_ParseTuple(args,"O;ch or int", &temp)) - return NULL; - break; - case 2: - if (!PyArg_ParseTuple(args,"Ol;ch or int,attr", &temp, &lattr)) - return NULL; - attr = lattr; - break; - default: - PyErr_SetString(PyExc_TypeError, "echochar requires 1 or 2 arguments"); + ch: object + Character to add. + attr: long(c_default="A_NORMAL") = _curses.A_NORMAL + Attributes for the character. + / - return NULL; - } +Add character ch with attribute attr, and refresh. +[clinic start generated code]*/ + +static PyObject * +_curses_window_echochar_impl(PyCursesWindowObject *self, PyObject *ch, + long attr) +/*[clinic end generated code: output=13e7dd875d4b9642 input=e7f34b964e92b156]*/ +{ + chtype ch_; - if (!PyCurses_ConvertToChtype(self, temp, &ch)) + if (!PyCurses_ConvertToChtype(self, ch, &ch_)) return NULL; #ifdef py_is_pad if (py_is_pad(self->win)) { - return PyCursesCheckERR(pechochar(self->win, ch | attr), + return PyCursesCheckERR(pechochar(self->win, ch_ | (attr_t)attr), "echochar"); } else #endif - return PyCursesCheckERR(wechochar(self->win, ch | attr), + return PyCursesCheckERR(wechochar(self->win, ch_ | (attr_t)attr), "echochar"); } #ifdef NCURSES_MOUSE_VERSION -static PyObject * -PyCursesWindow_Enclose(PyCursesWindowObject *self, PyObject *args) -{ - int x, y; - if (!PyArg_ParseTuple(args,"ii;y,x", &y, &x)) - return NULL; +/*[clinic input] +_curses.window.enclose -> long - return PyLong_FromLong( wenclose(self->win,y,x) ); -} -#endif + y: int + Y-coordinate. + x: int + X-coordinate. + / -static PyObject * -PyCursesWindow_GetBkgd(PyCursesWindowObject *self) +Return True if the screen-relative coordinates are enclosed by the window. +[clinic start generated code]*/ + +static long +_curses_window_enclose_impl(PyCursesWindowObject *self, int y, int x) +/*[clinic end generated code: output=5251c961cbe3df63 input=dfe1d9d4d05d8642]*/ { - return PyLong_FromLong((long) getbkgd(self->win)); + return wenclose(self->win, y, x); } +#endif -static PyObject * -PyCursesWindow_GetCh(PyCursesWindowObject *self, PyObject *args) +/*[clinic input] +_curses.window.getbkgd -> long + +Return the window's current background character/attribute pair. +[clinic start generated code]*/ + +static long +_curses_window_getbkgd_impl(PyCursesWindowObject *self) +/*[clinic end generated code: output=c52b25dc16b215c3 input=a69db882fa35426c]*/ +{ + return (long) getbkgd(self->win); +} + +/*[clinic input] +_curses.window.getch -> int + + [ + y: int + Y-coordinate. + x: int + X-coordinate. + ] + / + +Get a character code from terminal keyboard. + +The integer returned does not have to be in ASCII range: function keys, +keypad keys and so on return numbers higher than 256. In no-delay mode, -1 +is returned if there is no input, else getch() waits until a key is pressed. +[clinic start generated code]*/ + +static int +_curses_window_getch_impl(PyCursesWindowObject *self, int group_right_1, + int y, int x) +/*[clinic end generated code: output=980aa6af0c0ca387 input=bb24ebfb379f991f]*/ { - int x, y; int rtn; - switch (PyTuple_Size(args)) { - case 0: - Py_BEGIN_ALLOW_THREADS + Py_BEGIN_ALLOW_THREADS + if (!group_right_1) { rtn = wgetch(self->win); - Py_END_ALLOW_THREADS - break; - case 2: - if (!PyArg_ParseTuple(args,"ii;y,x",&y,&x)) - return NULL; - Py_BEGIN_ALLOW_THREADS - rtn = mvwgetch(self->win,y,x); - Py_END_ALLOW_THREADS - break; - default: - PyErr_SetString(PyExc_TypeError, "getch requires 0 or 2 arguments"); - return NULL; } - return PyLong_FromLong((long)rtn); + else { + rtn = mvwgetch(self->win, y, x); + } + Py_END_ALLOW_THREADS + + return rtn; } +/*[clinic input] +_curses.window.getkey + + [ + y: int + Y-coordinate. + x: int + X-coordinate. + ] + / + +Get a character (string) from terminal keyboard. + +Returning a string instead of an integer, as getch() does. Function keys, +keypad keys and other special keys return a multibyte string containing the +key name. In no-delay mode, an exception is raised if there is no input. +[clinic start generated code]*/ + static PyObject * -PyCursesWindow_GetKey(PyCursesWindowObject *self, PyObject *args) +_curses_window_getkey_impl(PyCursesWindowObject *self, int group_right_1, + int y, int x) +/*[clinic end generated code: output=8490a182db46b10f input=be2dee34f5cf57f8]*/ { - int x, y; int rtn; - switch (PyTuple_Size(args)) { - case 0: - Py_BEGIN_ALLOW_THREADS + Py_BEGIN_ALLOW_THREADS + if (!group_right_1) { rtn = wgetch(self->win); - Py_END_ALLOW_THREADS - break; - case 2: - if (!PyArg_ParseTuple(args,"ii;y,x",&y,&x)) - return NULL; - Py_BEGIN_ALLOW_THREADS - rtn = mvwgetch(self->win,y,x); - Py_END_ALLOW_THREADS - break; - default: - PyErr_SetString(PyExc_TypeError, "getkey requires 0 or 2 arguments"); - return NULL; } + else { + rtn = mvwgetch(self->win, y, x); + } + Py_END_ALLOW_THREADS + if (rtn == ERR) { /* getch() returns ERR in nodelay mode */ PyErr_CheckSignals(); @@ -1187,30 +1318,40 @@ PyCursesWindow_GetKey(PyCursesWindowObject *self, PyObject *args) } #ifdef HAVE_NCURSESW +/*[clinic input] +_curses.window.get_wch + + [ + y: int + Y-coordinate. + x: int + X-coordinate. + ] + / + +Get a wide character from terminal keyboard. + +Return a character for most keys, or an integer for function keys, +keypad keys, and other special keys. +[clinic start generated code]*/ + static PyObject * -PyCursesWindow_Get_WCh(PyCursesWindowObject *self, PyObject *args) +_curses_window_get_wch_impl(PyCursesWindowObject *self, int group_right_1, + int y, int x) +/*[clinic end generated code: output=9f4f86e91fe50ef3 input=dd7e5367fb49dc48]*/ { - int x, y; int ct; wint_t rtn; - switch (PyTuple_Size(args)) { - case 0: - Py_BEGIN_ALLOW_THREADS - ct = wget_wch(self->win,&rtn); - Py_END_ALLOW_THREADS - break; - case 2: - if (!PyArg_ParseTuple(args,"ii;y,x",&y,&x)) - return NULL; - Py_BEGIN_ALLOW_THREADS - ct = mvwget_wch(self->win,y,x,&rtn); - Py_END_ALLOW_THREADS - break; - default: - PyErr_SetString(PyExc_TypeError, "get_wch requires 0 or 2 arguments"); - return NULL; + Py_BEGIN_ALLOW_THREADS + if (!group_right_1) { + ct = wget_wch(self->win ,&rtn); + } + else { + ct = mvwget_wch(self->win, y, x, &rtn); } + Py_END_ALLOW_THREADS + if (ct == ERR) { if (PyErr_CheckSignals()) return NULL; @@ -1226,6 +1367,22 @@ PyCursesWindow_Get_WCh(PyCursesWindowObject *self, PyObject *args) } #endif +/*[-clinic input] +_curses.window.getstr + + [ + y: int + Y-coordinate. + x: int + X-coordinate. + ] + n: int = 1023 + Maximal number of characters. + / + +Read a string from the user, with primitive line editing capacity. +[-clinic start generated code]*/ + static PyObject * PyCursesWindow_GetStr(PyCursesWindowObject *self, PyObject *args) { @@ -1288,118 +1445,148 @@ PyCursesWindow_GetStr(PyCursesWindowObject *self, PyObject *args) return PyBytes_FromString(rtn); } +/*[clinic input] +_curses.window.hline + + [ + y: int + Starting Y-coordinate. + x: int + Starting X-coordinate. + ] + + ch: object + Character to draw. + n: int + Line length. + + [ + attr: long(c_default="A_NORMAL") = _curses.A_NORMAL + Attributes for the characters. + ] + / + +Display a horizontal line. +[clinic start generated code]*/ + static PyObject * -PyCursesWindow_Hline(PyCursesWindowObject *self, PyObject *args) +_curses_window_hline_impl(PyCursesWindowObject *self, int group_left_1, + int y, int x, PyObject *ch, int n, + int group_right_1, long attr) +/*[clinic end generated code: output=c00d489d61fc9eef input=81a4dea47268163e]*/ { - PyObject *temp; - chtype ch; - int n, x, y, code = OK; - attr_t attr = A_NORMAL; - long lattr; + chtype ch_; - switch (PyTuple_Size(args)) { - case 2: - if (!PyArg_ParseTuple(args, "Oi;ch or int,n", &temp, &n)) - return NULL; - break; - case 3: - if (!PyArg_ParseTuple(args, "Oil;ch or int,n,attr", &temp, &n, &lattr)) - return NULL; - attr = lattr; - break; - case 4: - if (!PyArg_ParseTuple(args, "iiOi;y,x,ch or int,n", &y, &x, &temp, &n)) - return NULL; - code = wmove(self->win, y, x); - break; - case 5: - if (!PyArg_ParseTuple(args, "iiOil; y,x,ch or int,n,attr", - &y, &x, &temp, &n, &lattr)) - return NULL; - attr = lattr; - code = wmove(self->win, y, x); - break; - default: - PyErr_SetString(PyExc_TypeError, "hline requires 2 to 5 arguments"); + if (!PyCurses_ConvertToChtype(self, ch, &ch_)) return NULL; + if (group_left_1) { + if (wmove(self->win, y, x) == ERR) { + return PyCursesCheckERR(ERR, "wmove"); + } } - - if (code != ERR) { - if (!PyCurses_ConvertToChtype(self, temp, &ch)) - return NULL; - return PyCursesCheckERR(whline(self->win, ch | attr, n), "hline"); - } else - return PyCursesCheckERR(code, "wmove"); + return PyCursesCheckERR(whline(self->win, ch_ | (attr_t)attr, n), "hline"); } +/*[clinic input] +_curses.window.insch + + [ + y: int + Y-coordinate. + x: int + X-coordinate. + ] + + ch: object + Character to insert. + + [ + attr: long(c_default="A_NORMAL") = _curses.A_NORMAL + Attributes for the character. + ] + / + +Insert a character before the current or specified position. + +All characters to the right of the cursor are shifted one position right, with +the rightmost characters on the line being lost. +[clinic start generated code]*/ + static PyObject * -PyCursesWindow_InsCh(PyCursesWindowObject *self, PyObject *args) +_curses_window_insch_impl(PyCursesWindowObject *self, int group_left_1, + int y, int x, PyObject *ch, int group_right_1, + long attr) +/*[clinic end generated code: output=ade8cfe3a3bf3e34 input=336342756ee19812]*/ { - int rtn, x, y, use_xy = FALSE; - PyObject *temp; - chtype ch = 0; - attr_t attr = A_NORMAL; - long lattr; - - switch (PyTuple_Size(args)) { - case 1: - if (!PyArg_ParseTuple(args, "O;ch or int", &temp)) - return NULL; - break; - case 2: - if (!PyArg_ParseTuple(args, "Ol;ch or int,attr", &temp, &lattr)) - return NULL; - attr = lattr; - break; - case 3: - if (!PyArg_ParseTuple(args,"iiO;y,x,ch or int", &y, &x, &temp)) - return NULL; - use_xy = TRUE; - break; - case 4: - if (!PyArg_ParseTuple(args,"iiOl;y,x,ch or int, attr", &y, &x, &temp, &lattr)) - return NULL; - attr = lattr; - use_xy = TRUE; - break; - default: - PyErr_SetString(PyExc_TypeError, "insch requires 1 to 4 arguments"); - return NULL; - } + int rtn; + chtype ch_ = 0; - if (!PyCurses_ConvertToChtype(self, temp, &ch)) + if (!PyCurses_ConvertToChtype(self, ch, &ch_)) return NULL; - if (use_xy == TRUE) - rtn = mvwinsch(self->win,y,x, ch | attr); + if (!group_left_1) { + rtn = winsch(self->win, ch_ | (attr_t)attr); + } else { - rtn = winsch(self->win, ch | attr); + rtn = mvwinsch(self->win, y, x, ch_ | (attr_t)attr); } + return PyCursesCheckERR(rtn, "insch"); } -static PyObject * -PyCursesWindow_InCh(PyCursesWindowObject *self, PyObject *args) +/*[clinic input] +_curses.window.inch -> unsigned_long + + [ + y: int + Y-coordinate. + x: int + X-coordinate. + ] + / + +Return the character at the given position in the window. + +The bottom 8 bits are the character proper, and upper bits are the attributes. +[clinic start generated code]*/ + +static unsigned long +_curses_window_inch_impl(PyCursesWindowObject *self, int group_right_1, + int y, int x) +/*[clinic end generated code: output=6c4719fe978fe86a input=fac23ee11e3b3a66]*/ { - int x, y; unsigned long rtn; - switch (PyTuple_Size(args)) { - case 0: + if (!group_right_1) { rtn = winch(self->win); - break; - case 2: - if (!PyArg_ParseTuple(args,"ii;y,x",&y,&x)) - return NULL; - rtn = mvwinch(self->win,y,x); - break; - default: - PyErr_SetString(PyExc_TypeError, "inch requires 0 to 2 arguments"); - return NULL; } - return PyLong_FromUnsignedLong(rtn); + else { + rtn = mvwinch(self->win, y, x); + } + + return rtn; } +/*[-clinic input] +_curses.window.instr + + [ + y: int + Y-coordinate. + x: int + X-coordinate. + ] + n: int = 1023 + Maximal number of characters. + / + +Return a string of characters, extracted from the window. + +Return a string of characters, extracted from the window starting at the +current cursor position, or at y, x if specified. Attributes are stripped +from the characters. If n is specified, instr() returns a string at most +n characters long (exclusive of the trailing NUL). +[-clinic start generated code]*/ static PyObject * PyCursesWindow_InStr(PyCursesWindowObject *self, PyObject *args) { @@ -1443,64 +1630,66 @@ PyCursesWindow_InStr(PyCursesWindowObject *self, PyObject *args) return PyBytes_FromString(rtn); } +/*[clinic input] +_curses.window.insstr + + [ + y: int + Y-coordinate. + x: int + X-coordinate. + ] + + str: object + String to insert. + + [ + attr: long + Attributes for characters. + ] + / + +Insert the string before the current or specified position. + +Insert a character string (as many characters as will fit on the line) +before the character under the cursor. All characters to the right of +the cursor are shifted right, with the rightmost characters on the line +being lost. The cursor position does not change (after moving to y, x, +if specified). +[clinic start generated code]*/ + static PyObject * -PyCursesWindow_InsStr(PyCursesWindowObject *self, PyObject *args) +_curses_window_insstr_impl(PyCursesWindowObject *self, int group_left_1, + int y, int x, PyObject *str, int group_right_1, + long attr) +/*[clinic end generated code: output=c259a5265ad0b777 input=6827cddc6340a7f3]*/ { int rtn; - int x, y; int strtype; - PyObject *strobj, *bytesobj = NULL; + PyObject *bytesobj = NULL; #ifdef HAVE_NCURSESW wchar_t *wstr = NULL; #endif - attr_t attr = A_NORMAL , attr_old = A_NORMAL; - long lattr; - int use_xy = FALSE, use_attr = FALSE; + attr_t attr_old = A_NORMAL; + int use_xy = group_left_1, use_attr = group_right_1; const char *funcname; - switch (PyTuple_Size(args)) { - case 1: - if (!PyArg_ParseTuple(args,"O;str", &strobj)) - return NULL; - break; - case 2: - if (!PyArg_ParseTuple(args,"Ol;str,attr", &strobj, &lattr)) - return NULL; - attr = lattr; - use_attr = TRUE; - break; - case 3: - if (!PyArg_ParseTuple(args,"iiO;y,x,str", &y, &x, &strobj)) - return NULL; - use_xy = TRUE; - break; - case 4: - if (!PyArg_ParseTuple(args,"iiOl;y,x,str,attr", &y, &x, &strobj, &lattr)) - return NULL; - attr = lattr; - use_xy = use_attr = TRUE; - break; - default: - PyErr_SetString(PyExc_TypeError, "insstr requires 1 to 4 arguments"); - return NULL; - } - #ifdef HAVE_NCURSESW - strtype = PyCurses_ConvertToString(self, strobj, &bytesobj, &wstr); + strtype = PyCurses_ConvertToString(self, str, &bytesobj, &wstr); #else - strtype = PyCurses_ConvertToString(self, strobj, &bytesobj, NULL); + strtype = PyCurses_ConvertToString(self, str, &bytesobj, NULL); #endif if (strtype == 0) return NULL; - if (use_attr == TRUE) { + if (use_attr) { attr_old = getattrs(self->win); - (void)wattrset(self->win,attr); + (void)wattrset(self->win, (attr_t)attr); } #ifdef HAVE_NCURSESW if (strtype == 2) { funcname = "inswstr"; - if (use_xy == TRUE) + if (use_xy) rtn = mvwins_wstr(self->win,y,x,wstr); else rtn = wins_wstr(self->win,wstr); @@ -1511,74 +1700,81 @@ PyCursesWindow_InsStr(PyCursesWindowObject *self, PyObject *args) { char *str = PyBytes_AS_STRING(bytesobj); funcname = "insstr"; - if (use_xy == TRUE) + if (use_xy) rtn = mvwinsstr(self->win,y,x,str); else rtn = winsstr(self->win,str); Py_DECREF(bytesobj); } - if (use_attr == TRUE) + if (use_attr) (void)wattrset(self->win,attr_old); return PyCursesCheckERR(rtn, funcname); } +/*[clinic input] +_curses.window.insnstr + + [ + y: int + Y-coordinate. + x: int + X-coordinate. + ] + + str: object + String to insert. + + n: int + Maximal number of characters. + + [ + attr: long + Attributes for characters. + ] + / + +Insert at most n characters of the string. + +Insert a character string (as many characters as will fit on the line) +before the character under the cursor, up to n characters. If n is zero +or negative, the entire string is inserted. All characters to the right +of the cursor are shifted right, with the rightmost characters on the line +being lost. The cursor position does not change (after moving to y, x, if +specified). +[clinic start generated code]*/ + static PyObject * -PyCursesWindow_InsNStr(PyCursesWindowObject *self, PyObject *args) +_curses_window_insnstr_impl(PyCursesWindowObject *self, int group_left_1, + int y, int x, PyObject *str, int n, + int group_right_1, long attr) +/*[clinic end generated code: output=971a32ea6328ec8b input=70fa0cd543901a4c]*/ { - int rtn, x, y, n; + int rtn; int strtype; - PyObject *strobj, *bytesobj = NULL; + PyObject *bytesobj = NULL; #ifdef HAVE_NCURSESW wchar_t *wstr = NULL; #endif - attr_t attr = A_NORMAL , attr_old = A_NORMAL; - long lattr; - int use_xy = FALSE, use_attr = FALSE; + attr_t attr_old = A_NORMAL; + int use_xy = group_left_1, use_attr = group_right_1; const char *funcname; - switch (PyTuple_Size(args)) { - case 2: - if (!PyArg_ParseTuple(args,"Oi;str,n", &strobj, &n)) - return NULL; - break; - case 3: - if (!PyArg_ParseTuple(args,"Oil;str,n,attr", &strobj, &n, &lattr)) - return NULL; - attr = lattr; - use_attr = TRUE; - break; - case 4: - if (!PyArg_ParseTuple(args,"iiOi;y,x,str,n", &y, &x, &strobj, &n)) - return NULL; - use_xy = TRUE; - break; - case 5: - if (!PyArg_ParseTuple(args,"iiOil;y,x,str,n,attr", &y, &x, &strobj, &n, &lattr)) - return NULL; - attr = lattr; - use_xy = use_attr = TRUE; - break; - default: - PyErr_SetString(PyExc_TypeError, "insnstr requires 2 to 5 arguments"); - return NULL; - } - #ifdef HAVE_NCURSESW - strtype = PyCurses_ConvertToString(self, strobj, &bytesobj, &wstr); + strtype = PyCurses_ConvertToString(self, str, &bytesobj, &wstr); #else - strtype = PyCurses_ConvertToString(self, strobj, &bytesobj, NULL); + strtype = PyCurses_ConvertToString(self, str, &bytesobj, NULL); #endif if (strtype == 0) return NULL; - if (use_attr == TRUE) { + if (use_attr) { attr_old = getattrs(self->win); - (void)wattrset(self->win,attr); + (void)wattrset(self->win, (attr_t)attr); } #ifdef HAVE_NCURSESW if (strtype == 2) { funcname = "insn_wstr"; - if (use_xy == TRUE) + if (use_xy) rtn = mvwins_nwstr(self->win,y,x,wstr,n); else rtn = wins_nwstr(self->win,wstr,n); @@ -1589,160 +1785,226 @@ PyCursesWindow_InsNStr(PyCursesWindowObject *self, PyObject *args) { char *str = PyBytes_AS_STRING(bytesobj); funcname = "insnstr"; - if (use_xy == TRUE) + if (use_xy) rtn = mvwinsnstr(self->win,y,x,str,n); else rtn = winsnstr(self->win,str,n); Py_DECREF(bytesobj); } - if (use_attr == TRUE) + if (use_attr) (void)wattrset(self->win,attr_old); return PyCursesCheckERR(rtn, funcname); } +/*[clinic input] +_curses.window.is_linetouched + + line: int + Line number. + / + +Return True if the specified line was modified, otherwise return False. + +Raise a curses.error exception if line is not valid for the given window. +[clinic start generated code]*/ + static PyObject * -PyCursesWindow_Is_LineTouched(PyCursesWindowObject *self, PyObject *args) +_curses_window_is_linetouched_impl(PyCursesWindowObject *self, int line) +/*[clinic end generated code: output=ad4a4edfee2db08c input=a7be0c189f243914]*/ { - int line, erg; - if (!PyArg_ParseTuple(args,"i;line", &line)) - return NULL; + int erg; erg = is_linetouched(self->win, line); if (erg == ERR) { PyErr_SetString(PyExc_TypeError, "is_linetouched: line number outside of boundaries"); return NULL; - } else - if (erg == FALSE) { - Py_RETURN_FALSE; - } else { - Py_RETURN_TRUE; - } + } + return PyBool_FromLong(erg); } -static PyObject * -PyCursesWindow_NoOutRefresh(PyCursesWindowObject *self, PyObject *args) -{ - int pminrow,pmincol,sminrow,smincol,smaxrow,smaxcol; - int rtn; +#ifdef py_is_pad +/*[clinic input] +_curses.window.noutrefresh -#ifndef py_is_pad - if (0) + [ + pminrow: int + pmincol: int + sminrow: int + smincol: int + smaxrow: int + smaxcol: int + ] + / + +Mark for refresh but wait. + +This function updates the data structure representing the desired state of the +window, but does not force an update of the physical screen. To accomplish +that, call doupdate(). +[clinic start generated code]*/ + +static PyObject * +_curses_window_noutrefresh_impl(PyCursesWindowObject *self, + int group_right_1, int pminrow, int pmincol, + int sminrow, int smincol, int smaxrow, + int smaxcol) +/*[clinic end generated code: output=809a1f3c6a03e23e input=3e56898388cd739e]*/ #else - if (py_is_pad(self->win)) -#endif - { - switch(PyTuple_Size(args)) { - case 6: - if (!PyArg_ParseTuple(args, - "iiiiii;" \ - "pminrow,pmincol,sminrow,smincol,smaxrow,smaxcol", - &pminrow, &pmincol, &sminrow, - &smincol, &smaxrow, &smaxcol)) - return NULL; - Py_BEGIN_ALLOW_THREADS - rtn = pnoutrefresh(self->win, - pminrow, pmincol, sminrow, - smincol, smaxrow, smaxcol); - Py_END_ALLOW_THREADS - return PyCursesCheckERR(rtn, "pnoutrefresh"); - default: - PyErr_SetString(PyCursesError, - "noutrefresh() called for a pad " - "requires 6 arguments"); - return NULL; - } - } else { - if (!PyArg_ParseTuple(args, ":noutrefresh")) - return NULL; +/*[clinic input] +_curses.window.noutrefresh - Py_BEGIN_ALLOW_THREADS - rtn = wnoutrefresh(self->win); - Py_END_ALLOW_THREADS - return PyCursesCheckERR(rtn, "wnoutrefresh"); - } -} +Mark for refresh but wait. + +This function updates the data structure representing the desired state of the +window, but does not force an update of the physical screen. To accomplish +that, call doupdate(). +[clinic start generated code]*/ static PyObject * -PyCursesWindow_Overlay(PyCursesWindowObject *self, PyObject *args) +_curses_window_noutrefresh_impl(PyCursesWindowObject *self) +/*[clinic end generated code: output=6ef6dec666643fee input=876902e3fa431dbd]*/ +#endif { - PyCursesWindowObject *temp; - int use_copywin = FALSE; - int sminrow, smincol, dminrow, dmincol, dmaxrow, dmaxcol; int rtn; - switch (PyTuple_Size(args)) { - case 1: - if (!PyArg_ParseTuple(args, "O!;window object", - &PyCursesWindow_Type, &temp)) - return NULL; - break; - case 7: - if (!PyArg_ParseTuple(args, "O!iiiiii;window object, int, int, int, int, int, int", - &PyCursesWindow_Type, &temp, &sminrow, &smincol, - &dminrow, &dmincol, &dmaxrow, &dmaxcol)) +#ifdef py_is_pad + if (py_is_pad(self->win)) { + if (!group_right_1) { + PyErr_SetString(PyCursesError, + "noutrefresh() called for a pad " + "requires 6 arguments"); return NULL; - use_copywin = TRUE; - break; - default: + } + Py_BEGIN_ALLOW_THREADS + rtn = pnoutrefresh(self->win, pminrow, pmincol, + sminrow, smincol, smaxrow, smaxcol); + Py_END_ALLOW_THREADS + return PyCursesCheckERR(rtn, "pnoutrefresh"); + } + if (group_right_1) { PyErr_SetString(PyExc_TypeError, - "overlay requires one or seven arguments"); + "noutrefresh() takes no arguments (6 given)"); return NULL; } +#endif + Py_BEGIN_ALLOW_THREADS + rtn = wnoutrefresh(self->win); + Py_END_ALLOW_THREADS + return PyCursesCheckERR(rtn, "wnoutrefresh"); +} + +/*[clinic input] +_curses.window.overlay + + destwin: object(type="PyCursesWindowObject *", subclass_of="&PyCursesWindow_Type") + + [ + sminrow: int + smincol: int + dminrow: int + dmincol: int + dmaxrow: int + dmaxcol: int + ] + / + +Overlay the window on top of destwin. + +The windows need not be the same size, only the overlapping region is copied. +This copy is non-destructive, which means that the current background +character does not overwrite the old contents of destwin. + +To get fine-grained control over the copied region, the second form of +overlay() can be used. sminrow and smincol are the upper-left coordinates +of the source window, and the other variables mark a rectangle in the +destination window. +[clinic start generated code]*/ - if (use_copywin == TRUE) { - rtn = copywin(self->win, temp->win, sminrow, smincol, +static PyObject * +_curses_window_overlay_impl(PyCursesWindowObject *self, + PyCursesWindowObject *destwin, int group_right_1, + int sminrow, int smincol, int dminrow, + int dmincol, int dmaxrow, int dmaxcol) +/*[clinic end generated code: output=82bb2c4cb443ca58 input=7edd23ad22cc1984]*/ +{ + int rtn; + + if (group_right_1) { + rtn = copywin(self->win, destwin->win, sminrow, smincol, dminrow, dmincol, dmaxrow, dmaxcol, TRUE); return PyCursesCheckERR(rtn, "copywin"); } else { - rtn = overlay(self->win, temp->win); + rtn = overlay(self->win, destwin->win); return PyCursesCheckERR(rtn, "overlay"); } } +/*[clinic input] +_curses.window.overwrite + + destwin: object(type="PyCursesWindowObject *", subclass_of="&PyCursesWindow_Type") + + [ + sminrow: int + smincol: int + dminrow: int + dmincol: int + dmaxrow: int + dmaxcol: int + ] + / + +Overwrite the window on top of destwin. + +The windows need not be the same size, in which case only the overlapping +region is copied. This copy is destructive, which means that the current +background character overwrites the old contents of destwin. + +To get fine-grained control over the copied region, the second form of +overwrite() can be used. sminrow and smincol are the upper-left coordinates +of the source window, the other variables mark a rectangle in the destination +window. +[clinic start generated code]*/ + static PyObject * -PyCursesWindow_Overwrite(PyCursesWindowObject *self, PyObject *args) +_curses_window_overwrite_impl(PyCursesWindowObject *self, + PyCursesWindowObject *destwin, + int group_right_1, int sminrow, int smincol, + int dminrow, int dmincol, int dmaxrow, + int dmaxcol) +/*[clinic end generated code: output=12ae007d1681be28 input=ea5de1b35cd948e0]*/ { - PyCursesWindowObject *temp; - int use_copywin = FALSE; - int sminrow, smincol, dminrow, dmincol, dmaxrow, dmaxcol; int rtn; - switch (PyTuple_Size(args)) { - case 1: - if (!PyArg_ParseTuple(args, "O!;window object", - &PyCursesWindow_Type, &temp)) - return NULL; - break; - case 7: - if (!PyArg_ParseTuple(args, "O!iiiiii;window object, int, int, int, int, int, int", - &PyCursesWindow_Type, &temp, &sminrow, &smincol, - &dminrow, &dmincol, &dmaxrow, &dmaxcol)) - return NULL; - use_copywin = TRUE; - break; - default: - PyErr_SetString(PyExc_TypeError, - "overwrite requires one or seven arguments"); - return NULL; - } - - if (use_copywin == TRUE) { - rtn = copywin(self->win, temp->win, sminrow, smincol, + if (group_right_1) { + rtn = copywin(self->win, destwin->win, sminrow, smincol, dminrow, dmincol, dmaxrow, dmaxcol, FALSE); return PyCursesCheckERR(rtn, "copywin"); } else { - rtn = overwrite(self->win, temp->win); + rtn = overwrite(self->win, destwin->win); return PyCursesCheckERR(rtn, "overwrite"); } } +/*[clinic input] +_curses.window.putwin + + file: object + / + +Write all data associated with the window into the provided file object. + +This information can be later retrieved using the getwin() function. +[clinic start generated code]*/ + static PyObject * -PyCursesWindow_PutWin(PyCursesWindowObject *self, PyObject *stream) +_curses_window_putwin(PyCursesWindowObject *self, PyObject *file) +/*[clinic end generated code: output=3a25e2a5e7a040ac input=0608648e09c8ea0a]*/ { /* We have to simulate this by writing to a temporary FILE*, - then reading back, then writing to the argument stream. */ + then reading back, then writing to the argument file. */ FILE *fp; PyObject *res = NULL; @@ -1763,7 +2025,7 @@ PyCursesWindow_PutWin(PyCursesWindowObject *self, PyObject *stream) if (n <= 0) break; Py_DECREF(res); - res = _PyObject_CallMethodId(stream, &PyId_write, "y#", buf, n); + res = _PyObject_CallMethodId(file, &PyId_write, "y#", buf, n); if (res == NULL) break; } @@ -1773,88 +2035,137 @@ PyCursesWindow_PutWin(PyCursesWindowObject *self, PyObject *stream) return res; } +/*[clinic input] +_curses.window.redrawln + + beg: int + Starting line number. + num: int + The number of lines. + / + +Mark the specified lines corrupted. + +They should be completely redrawn on the next refresh() call. +[clinic start generated code]*/ + +static PyObject * +_curses_window_redrawln_impl(PyCursesWindowObject *self, int beg, int num) +/*[clinic end generated code: output=ea216e334f9ce1b4 input=152155e258a77a7a]*/ +{ + return PyCursesCheckERR(wredrawln(self->win,beg,num), "redrawln"); +} + +/*[clinic input] +_curses.window.refresh + + [ + pminrow: int + pmincol: int + sminrow: int + smincol: int + smaxrow: int + smaxcol: int + ] + / + +Update the display immediately. + +Synchronize actual screen with previous drawing/deleting methods. +The 6 optional arguments can only be specified when the window is a pad +created with newpad(). The additional parameters are needed to indicate +what part of the pad and screen are involved. pminrow and pmincol specify +the upper left-hand corner of the rectangle to be displayed in the pad. +sminrow, smincol, smaxrow, and smaxcol specify the edges of the rectangle to +be displayed on the screen. The lower right-hand corner of the rectangle to +be displayed in the pad is calculated from the screen coordinates, since the +rectangles must be the same size. Both rectangles must be entirely contained +within their respective structures. Negative values of pminrow, pmincol, +sminrow, or smincol are treated as if they were zero. +[clinic start generated code]*/ + static PyObject * -PyCursesWindow_RedrawLine(PyCursesWindowObject *self, PyObject *args) +_curses_window_refresh_impl(PyCursesWindowObject *self, int group_right_1, + int pminrow, int pmincol, int sminrow, + int smincol, int smaxrow, int smaxcol) +/*[clinic end generated code: output=42199543115e6e63 input=95e01cb5ffc635d0]*/ { - int beg, num; - if (!PyArg_ParseTuple(args, "ii;beg,num", &beg, &num)) + int rtn; + +#ifdef py_is_pad + if (py_is_pad(self->win)) { + if (!group_right_1) { + PyErr_SetString(PyCursesError, + "refresh() for a pad requires 6 arguments"); + return NULL; + } + Py_BEGIN_ALLOW_THREADS + rtn = prefresh(self->win, pminrow, pmincol, + sminrow, smincol, smaxrow, smaxcol); + Py_END_ALLOW_THREADS + return PyCursesCheckERR(rtn, "prefresh"); + } +#endif + if (group_right_1) { + PyErr_SetString(PyExc_TypeError, + "refresh() takes no arguments (6 given)"); return NULL; - return PyCursesCheckERR(wredrawln(self->win,beg,num), "redrawln"); + } + Py_BEGIN_ALLOW_THREADS + rtn = wrefresh(self->win); + Py_END_ALLOW_THREADS + return PyCursesCheckERR(rtn, "prefresh"); } -static PyObject * -PyCursesWindow_Refresh(PyCursesWindowObject *self, PyObject *args) -{ - int pminrow,pmincol,sminrow,smincol,smaxrow,smaxcol; - int rtn; +/*[clinic input] +_curses.window.setscrreg -#ifndef py_is_pad - if (0) -#else - if (py_is_pad(self->win)) -#endif - { - switch(PyTuple_Size(args)) { - case 6: - if (!PyArg_ParseTuple(args, - "iiiiii;" \ - "pminrow,pmincol,sminrow,smincol,smaxrow,smaxcol", - &pminrow, &pmincol, &sminrow, - &smincol, &smaxrow, &smaxcol)) - return NULL; - - Py_BEGIN_ALLOW_THREADS - rtn = prefresh(self->win, - pminrow, pmincol, sminrow, - smincol, smaxrow, smaxcol); - Py_END_ALLOW_THREADS - return PyCursesCheckERR(rtn, "prefresh"); - default: - PyErr_SetString(PyCursesError, - "refresh() for a pad requires 6 arguments"); - return NULL; - } - } else { - if (!PyArg_ParseTuple(args, ":refresh")) - return NULL; - Py_BEGIN_ALLOW_THREADS - rtn = wrefresh(self->win); - Py_END_ALLOW_THREADS - return PyCursesCheckERR(rtn, "prefresh"); - } -} + top: int + First line number. + bottom: int + Last line number. + / + +Define a software scrolling region. + +All scrolling actions will take place in this region. +[clinic start generated code]*/ static PyObject * -PyCursesWindow_SetScrollRegion(PyCursesWindowObject *self, PyObject *args) +_curses_window_setscrreg_impl(PyCursesWindowObject *self, int top, + int bottom) +/*[clinic end generated code: output=486ab5db218d2b1a input=1b517b986838bf0e]*/ { - int x, y; - if (!PyArg_ParseTuple(args,"ii;top, bottom",&y,&x)) - return NULL; - return PyCursesCheckERR(wsetscrreg(self->win,y,x), "wsetscrreg"); + return PyCursesCheckERR(wsetscrreg(self->win, top, bottom), "wsetscrreg"); } +/*[clinic input] +_curses.window.subwin + + [ + nlines: int = 0 + Height. + ncols: int = 0 + Width. + ] + begin_y: int + Top side y-coordinate. + begin_x: int + Left side x-coordinate. + / + +Create a sub-window (screen-relative coordinates). + +By default, the sub-window will extend from the specified position to the +lower right corner of the window. +[clinic start generated code]*/ + static PyObject * -PyCursesWindow_SubWin(PyCursesWindowObject *self, PyObject *args) +_curses_window_subwin_impl(PyCursesWindowObject *self, int group_left_1, + int nlines, int ncols, int begin_y, int begin_x) +/*[clinic end generated code: output=93e898afc348f59a input=2129fa47fd57721c]*/ { WINDOW *win; - int nlines, ncols, begin_y, begin_x; - - nlines = 0; - ncols = 0; - switch (PyTuple_Size(args)) { - case 2: - if (!PyArg_ParseTuple(args,"ii;begin_y,begin_x",&begin_y,&begin_x)) - return NULL; - break; - case 4: - if (!PyArg_ParseTuple(args, "iiii;nlines,ncols,begin_y,begin_x", - &nlines,&ncols,&begin_y,&begin_x)) - return NULL; - break; - default: - PyErr_SetString(PyExc_TypeError, "subwin requires 2 or 4 arguments"); - return NULL; - } /* printf("Subwin: %i %i %i %i \n", nlines, ncols, begin_y, begin_x); */ #ifdef py_is_pad @@ -1873,84 +2184,101 @@ PyCursesWindow_SubWin(PyCursesWindowObject *self, PyObject *args) return (PyObject *)PyCursesWindow_New(win, self->encoding); } +/*[clinic input] +_curses.window.scroll + + [ + lines: int = 1 + Number of lines to scroll. + ] + / + +Scroll the screen or scrolling region. + +Scroll upward if the argument is positive and downward if it is negative. +[clinic start generated code]*/ + static PyObject * -PyCursesWindow_Scroll(PyCursesWindowObject *self, PyObject *args) +_curses_window_scroll_impl(PyCursesWindowObject *self, int group_right_1, + int lines) +/*[clinic end generated code: output=4541a8a11852d360 input=c969ca0cfabbdbec]*/ { - int nlines; - switch(PyTuple_Size(args)) { - case 0: + if (!group_right_1) { return PyCursesCheckERR(scroll(self->win), "scroll"); - case 1: - if (!PyArg_ParseTuple(args, "i;nlines", &nlines)) - return NULL; - return PyCursesCheckERR(wscrl(self->win, nlines), "scroll"); - default: - PyErr_SetString(PyExc_TypeError, "scroll requires 0 or 1 arguments"); - return NULL; + } + else { + return PyCursesCheckERR(wscrl(self->win, lines), "scroll"); } } +/*[clinic input] +_curses.window.touchline + + start: int + count: int + [ + changed: bool(accept={int}) = True + ] + / + +Pretend count lines have been changed, starting with line start. + +If changed is supplied, it specifies whether the affected lines are marked +as having been changed (changed=True) or unchanged (changed=False). +[clinic start generated code]*/ + static PyObject * -PyCursesWindow_TouchLine(PyCursesWindowObject *self, PyObject *args) +_curses_window_touchline_impl(PyCursesWindowObject *self, int start, + int count, int group_right_1, int changed) +/*[clinic end generated code: output=65d05b3f7438c61d input=918ad1cbdadf93ea]*/ { - int st, cnt, val; - switch (PyTuple_Size(args)) { - case 2: - if (!PyArg_ParseTuple(args,"ii;start,count",&st,&cnt)) - return NULL; - return PyCursesCheckERR(touchline(self->win,st,cnt), "touchline"); - case 3: - if (!PyArg_ParseTuple(args, "iii;start,count,val", &st, &cnt, &val)) - return NULL; - return PyCursesCheckERR(wtouchln(self->win, st, cnt, val), "touchline"); - default: - PyErr_SetString(PyExc_TypeError, "touchline requires 2 or 3 arguments"); - return NULL; + if (!group_right_1) { + return PyCursesCheckERR(touchline(self->win, start, count), "touchline"); + } + else { + return PyCursesCheckERR(wtouchln(self->win, start, count, changed), "touchline"); } } +/*[clinic input] +_curses.window.vline + + [ + y: int + Starting Y-coordinate. + x: int + Starting X-coordinate. + ] + + ch: object + Character to draw. + n: int + Line length. + + [ + attr: long(c_default="A_NORMAL") = _curses.A_NORMAL + Attributes for the character. + ] + / + +Display a vertical line. +[clinic start generated code]*/ + static PyObject * -PyCursesWindow_Vline(PyCursesWindowObject *self, PyObject *args) +_curses_window_vline_impl(PyCursesWindowObject *self, int group_left_1, + int y, int x, PyObject *ch, int n, + int group_right_1, long attr) +/*[clinic end generated code: output=287ad1cc8982217f input=a6f2dc86a4648b32]*/ { - PyObject *temp; - chtype ch; - int n, x, y, code = OK; - attr_t attr = A_NORMAL; - long lattr; + chtype ch_; - switch (PyTuple_Size(args)) { - case 2: - if (!PyArg_ParseTuple(args, "Oi;ch or int,n", &temp, &n)) - return NULL; - break; - case 3: - if (!PyArg_ParseTuple(args, "Oil;ch or int,n,attr", &temp, &n, &lattr)) - return NULL; - attr = lattr; - break; - case 4: - if (!PyArg_ParseTuple(args, "iiOi;y,x,ch or int,n", &y, &x, &temp, &n)) - return NULL; - code = wmove(self->win, y, x); - break; - case 5: - if (!PyArg_ParseTuple(args, "iiOil; y,x,ch or int,n,attr", - &y, &x, &temp, &n, &lattr)) - return NULL; - attr = lattr; - code = wmove(self->win, y, x); - break; - default: - PyErr_SetString(PyExc_TypeError, "vline requires 2 to 5 arguments"); + if (!PyCurses_ConvertToChtype(self, ch, &ch_)) return NULL; + if (group_left_1) { + if (wmove(self->win, y, x) == ERR) + return PyCursesCheckERR(ERR, "wmove"); } - - if (code != ERR) { - if (!PyCurses_ConvertToChtype(self, temp, &ch)) - return NULL; - return PyCursesCheckERR(wvline(self->win, ch | attr, n), "vline"); - } else - return PyCursesCheckERR(code, "wmove"); + return PyCursesCheckERR(wvline(self->win, ch_ | (attr_t)attr, n), "vline"); } static PyObject * @@ -1991,59 +2319,56 @@ PyCursesWindow_set_encoding(PyCursesWindowObject *self, PyObject *value) return 0; } +#include "clinic/_cursesmodule.c.h" static PyMethodDef PyCursesWindow_Methods[] = { - CURSES_WINDOW_ADDCH_METHODDEF - {"addnstr", (PyCFunction)PyCursesWindow_AddNStr, METH_VARARGS}, - {"addstr", (PyCFunction)PyCursesWindow_AddStr, METH_VARARGS}, - {"attroff", (PyCFunction)PyCursesWindow_AttrOff, METH_VARARGS}, - {"attron", (PyCFunction)PyCursesWindow_AttrOn, METH_VARARGS}, - {"attrset", (PyCFunction)PyCursesWindow_AttrSet, METH_VARARGS}, - {"bkgd", (PyCFunction)PyCursesWindow_Bkgd, METH_VARARGS}, + _CURSES_WINDOW_ADDCH_METHODDEF + _CURSES_WINDOW_ADDNSTR_METHODDEF + _CURSES_WINDOW_ADDSTR_METHODDEF + _CURSES_WINDOW_ATTROFF_METHODDEF + _CURSES_WINDOW_ATTRON_METHODDEF + _CURSES_WINDOW_ATTRSET_METHODDEF + _CURSES_WINDOW_BKGD_METHODDEF #ifdef HAVE_CURSES_WCHGAT {"chgat", (PyCFunction)PyCursesWindow_ChgAt, METH_VARARGS}, #endif - {"bkgdset", (PyCFunction)PyCursesWindow_BkgdSet, METH_VARARGS}, - {"border", (PyCFunction)PyCursesWindow_Border, METH_VARARGS}, - {"box", (PyCFunction)PyCursesWindow_Box, METH_VARARGS}, + _CURSES_WINDOW_BKGDSET_METHODDEF + _CURSES_WINDOW_BORDER_METHODDEF + _CURSES_WINDOW_BOX_METHODDEF {"clear", (PyCFunction)PyCursesWindow_wclear, METH_NOARGS}, {"clearok", (PyCFunction)PyCursesWindow_clearok, METH_VARARGS}, {"clrtobot", (PyCFunction)PyCursesWindow_wclrtobot, METH_NOARGS}, {"clrtoeol", (PyCFunction)PyCursesWindow_wclrtoeol, METH_NOARGS}, {"cursyncup", (PyCFunction)PyCursesWindow_wcursyncup, METH_NOARGS}, - {"delch", (PyCFunction)PyCursesWindow_DelCh, METH_VARARGS}, + _CURSES_WINDOW_DELCH_METHODDEF {"deleteln", (PyCFunction)PyCursesWindow_wdeleteln, METH_NOARGS}, - {"derwin", (PyCFunction)PyCursesWindow_DerWin, METH_VARARGS}, - {"echochar", (PyCFunction)PyCursesWindow_EchoChar, METH_VARARGS}, -#ifdef NCURSES_MOUSE_VERSION - {"enclose", (PyCFunction)PyCursesWindow_Enclose, METH_VARARGS}, -#endif + _CURSES_WINDOW_DERWIN_METHODDEF + _CURSES_WINDOW_ECHOCHAR_METHODDEF + _CURSES_WINDOW_ENCLOSE_METHODDEF {"erase", (PyCFunction)PyCursesWindow_werase, METH_NOARGS}, {"getbegyx", (PyCFunction)PyCursesWindow_getbegyx, METH_NOARGS}, - {"getbkgd", (PyCFunction)PyCursesWindow_GetBkgd, METH_NOARGS}, - {"getch", (PyCFunction)PyCursesWindow_GetCh, METH_VARARGS}, - {"getkey", (PyCFunction)PyCursesWindow_GetKey, METH_VARARGS}, -#ifdef HAVE_NCURSESW - {"get_wch", (PyCFunction)PyCursesWindow_Get_WCh, METH_VARARGS}, -#endif + _CURSES_WINDOW_GETBKGD_METHODDEF + _CURSES_WINDOW_GETCH_METHODDEF + _CURSES_WINDOW_GETKEY_METHODDEF + _CURSES_WINDOW_GET_WCH_METHODDEF {"getmaxyx", (PyCFunction)PyCursesWindow_getmaxyx, METH_NOARGS}, {"getparyx", (PyCFunction)PyCursesWindow_getparyx, METH_NOARGS}, {"getstr", (PyCFunction)PyCursesWindow_GetStr, METH_VARARGS}, {"getyx", (PyCFunction)PyCursesWindow_getyx, METH_NOARGS}, - {"hline", (PyCFunction)PyCursesWindow_Hline, METH_VARARGS}, + _CURSES_WINDOW_HLINE_METHODDEF {"idcok", (PyCFunction)PyCursesWindow_idcok, METH_VARARGS}, {"idlok", (PyCFunction)PyCursesWindow_idlok, METH_VARARGS}, #ifdef HAVE_CURSES_IMMEDOK {"immedok", (PyCFunction)PyCursesWindow_immedok, METH_VARARGS}, #endif - {"inch", (PyCFunction)PyCursesWindow_InCh, METH_VARARGS}, - {"insch", (PyCFunction)PyCursesWindow_InsCh, METH_VARARGS}, + _CURSES_WINDOW_INCH_METHODDEF + _CURSES_WINDOW_INSCH_METHODDEF {"insdelln", (PyCFunction)PyCursesWindow_winsdelln, METH_VARARGS}, {"insertln", (PyCFunction)PyCursesWindow_winsertln, METH_NOARGS}, - {"insnstr", (PyCFunction)PyCursesWindow_InsNStr, METH_VARARGS}, - {"insstr", (PyCFunction)PyCursesWindow_InsStr, METH_VARARGS}, + _CURSES_WINDOW_INSNSTR_METHODDEF + _CURSES_WINDOW_INSSTR_METHODDEF {"instr", (PyCFunction)PyCursesWindow_InStr, METH_VARARGS}, - {"is_linetouched", (PyCFunction)PyCursesWindow_Is_LineTouched, METH_VARARGS}, + _CURSES_WINDOW_IS_LINETOUCHED_METHODDEF {"is_wintouched", (PyCFunction)PyCursesWindow_is_wintouched, METH_NOARGS}, {"keypad", (PyCFunction)PyCursesWindow_keypad, METH_VARARGS}, {"leaveok", (PyCFunction)PyCursesWindow_leaveok, METH_VARARGS}, @@ -2052,34 +2377,33 @@ static PyMethodDef PyCursesWindow_Methods[] = { {"mvwin", (PyCFunction)PyCursesWindow_mvwin, METH_VARARGS}, {"nodelay", (PyCFunction)PyCursesWindow_nodelay, METH_VARARGS}, {"notimeout", (PyCFunction)PyCursesWindow_notimeout, METH_VARARGS}, - {"noutrefresh", (PyCFunction)PyCursesWindow_NoOutRefresh, METH_VARARGS}, - {"overlay", (PyCFunction)PyCursesWindow_Overlay, METH_VARARGS}, - {"overwrite", (PyCFunction)PyCursesWindow_Overwrite, - METH_VARARGS}, - {"putwin", (PyCFunction)PyCursesWindow_PutWin, METH_O}, - {"redrawln", (PyCFunction)PyCursesWindow_RedrawLine, METH_VARARGS}, + _CURSES_WINDOW_NOUTREFRESH_METHODDEF + _CURSES_WINDOW_OVERLAY_METHODDEF + _CURSES_WINDOW_OVERWRITE_METHODDEF + _CURSES_WINDOW_PUTWIN_METHODDEF + _CURSES_WINDOW_REDRAWLN_METHODDEF {"redrawwin", (PyCFunction)PyCursesWindow_redrawwin, METH_NOARGS}, - {"refresh", (PyCFunction)PyCursesWindow_Refresh, METH_VARARGS}, + _CURSES_WINDOW_REFRESH_METHODDEF #ifndef STRICT_SYSV_CURSES {"resize", (PyCFunction)PyCursesWindow_wresize, METH_VARARGS}, #endif - {"scroll", (PyCFunction)PyCursesWindow_Scroll, METH_VARARGS}, + _CURSES_WINDOW_SCROLL_METHODDEF {"scrollok", (PyCFunction)PyCursesWindow_scrollok, METH_VARARGS}, - {"setscrreg", (PyCFunction)PyCursesWindow_SetScrollRegion, METH_VARARGS}, + _CURSES_WINDOW_SETSCRREG_METHODDEF {"standend", (PyCFunction)PyCursesWindow_wstandend, METH_NOARGS}, {"standout", (PyCFunction)PyCursesWindow_wstandout, METH_NOARGS}, - {"subpad", (PyCFunction)PyCursesWindow_SubWin, METH_VARARGS}, - {"subwin", (PyCFunction)PyCursesWindow_SubWin, METH_VARARGS}, + {"subpad", (PyCFunction)_curses_window_subwin, METH_VARARGS, _curses_window_subwin__doc__}, + _CURSES_WINDOW_SUBWIN_METHODDEF {"syncdown", (PyCFunction)PyCursesWindow_wsyncdown, METH_NOARGS}, #ifdef HAVE_CURSES_SYNCOK {"syncok", (PyCFunction)PyCursesWindow_syncok, METH_VARARGS}, #endif {"syncup", (PyCFunction)PyCursesWindow_wsyncup, METH_NOARGS}, {"timeout", (PyCFunction)PyCursesWindow_wtimeout, METH_VARARGS}, - {"touchline", (PyCFunction)PyCursesWindow_TouchLine, METH_VARARGS}, + _CURSES_WINDOW_TOUCHLINE_METHODDEF {"touchwin", (PyCFunction)PyCursesWindow_touchwin, METH_NOARGS}, {"untouchwin", (PyCFunction)PyCursesWindow_untouchwin, METH_NOARGS}, - {"vline", (PyCFunction)PyCursesWindow_Vline, METH_VARARGS}, + _CURSES_WINDOW_VLINE_METHODDEF {NULL, NULL} /* sentinel */ }; @@ -2127,47 +2451,63 @@ PyTypeObject PyCursesWindow_Type = { PyCursesWindow_getsets, /* tp_getset */ }; +/* Function Prototype Macros - They are ugly but very, very useful. ;-) + + X - function name + TYPE - parameter Type + ERGSTR - format string for construction of the return value + PARSESTR - format string for argument parsing + */ + +#define NoArgNoReturnFunctionBody(X) \ +{ \ + PyCursesInitialised \ + return PyCursesCheckERR(X(), # X); } + +#define NoArgOrFlagNoReturnFunctionBody(X, flag) \ +{ \ + PyCursesInitialised \ + if (flag) \ + return PyCursesCheckERR(X(), # X); \ + else \ + return PyCursesCheckERR(no ## X(), # X); \ +} + +#define NoArgReturnIntFunctionBody(X) \ +{ \ + PyCursesInitialised \ + return PyLong_FromLong((long) X()); } + + +#define NoArgReturnStringFunctionBody(X) \ +{ \ + PyCursesInitialised \ + return PyBytes_FromString(X()); } + +#define NoArgTrueFalseFunctionBody(X) \ +{ \ + PyCursesInitialised \ + return PyBool_FromLong(X()); } + +#define NoArgNoReturnVoidFunctionBody(X) \ +{ \ + PyCursesInitialised \ + X(); \ + Py_RETURN_NONE; } + /********************************************************************* Global Functions **********************************************************************/ -NoArgNoReturnFunction(beep) -NoArgNoReturnFunction(def_prog_mode) -NoArgNoReturnFunction(def_shell_mode) -NoArgNoReturnFunction(doupdate) -NoArgNoReturnFunction(endwin) -NoArgNoReturnFunction(flash) -NoArgNoReturnFunction(nocbreak) -NoArgNoReturnFunction(noecho) -NoArgNoReturnFunction(nonl) -NoArgNoReturnFunction(noraw) -NoArgNoReturnFunction(reset_prog_mode) -NoArgNoReturnFunction(reset_shell_mode) -NoArgNoReturnFunction(resetty) -NoArgNoReturnFunction(savetty) - -NoArgOrFlagNoReturnFunction(cbreak) -NoArgOrFlagNoReturnFunction(echo) -NoArgOrFlagNoReturnFunction(nl) -NoArgOrFlagNoReturnFunction(raw) - -NoArgReturnIntFunction(baudrate) -NoArgReturnIntFunction(termattrs) - -NoArgReturnStringFunction(termname) -NoArgReturnStringFunction(longname) - -NoArgTrueFalseFunction(can_change_color) -NoArgTrueFalseFunction(has_colors) -NoArgTrueFalseFunction(has_ic) -NoArgTrueFalseFunction(has_il) -NoArgTrueFalseFunction(isendwin) -NoArgNoReturnVoidFunction(flushinp) -NoArgNoReturnVoidFunction(noqiflush) - #ifdef HAVE_CURSES_FILTER +/*[clinic input] +_curses.filter + +[clinic start generated code]*/ + static PyObject * -PyCurses_filter(PyObject *self) +_curses_filter_impl(PyObject *module) +/*[clinic end generated code: output=fb5b8a3642eb70b5 input=668c75a6992d3624]*/ { /* not checking for PyCursesInitialised here since filter() must be called before initscr() */ @@ -2176,17 +2516,83 @@ PyCurses_filter(PyObject *self) } #endif +/*[clinic input] +_curses.baudrate + +Return the output speed of the terminal in bits per second. +[clinic start generated code]*/ + +static PyObject * +_curses_baudrate_impl(PyObject *module) +/*[clinic end generated code: output=3c63c6c401d7d9c0 input=921f022ed04a0fd9]*/ +NoArgReturnIntFunctionBody(baudrate) + +/*[clinic input] +_curses.beep + +Emit a short attention sound. +[clinic start generated code]*/ + +static PyObject * +_curses_beep_impl(PyObject *module) +/*[clinic end generated code: output=425274962abe49a2 input=a35698ca7d0162bc]*/ +NoArgNoReturnFunctionBody(beep) + +/*[clinic input] +_curses.can_change_color + +Return True if the programmer can change the colors displayed by the terminal. +[clinic start generated code]*/ + +static PyObject * +_curses_can_change_color_impl(PyObject *module) +/*[clinic end generated code: output=359df8c3c77d8bf1 input=d7718884de0092f2]*/ +NoArgTrueFalseFunctionBody(can_change_color) + +/*[clinic input] +_curses.cbreak + + flag: bool(accept={int}) = True + If false, the effect is the same as calling nocbreak(). + / + +Enter cbreak mode. + +In cbreak mode (sometimes called "rare" mode) normal tty line buffering is +turned off and characters are available to be read one by one. However, +unlike raw mode, special characters (interrupt, quit, suspend, and flow +control) retain their effects on the tty driver and calling program. +Calling first raw() then cbreak() leaves the terminal in cbreak mode. +[clinic start generated code]*/ + +static PyObject * +_curses_cbreak_impl(PyObject *module, int flag) +/*[clinic end generated code: output=9f9dee9664769751 input=150be619eb1f1458]*/ +NoArgOrFlagNoReturnFunctionBody(cbreak, flag) + +/*[clinic input] +_curses.color_content + + color_number: short + The number of the color (0 - COLORS). + / + +Return the red, green, and blue (RGB) components of the specified color. + +A 3-tuple is returned, containing the R, G, B values for the given color, +which will be between 0 (no component) and 1000 (maximum amount of component). +[clinic start generated code]*/ + static PyObject * -PyCurses_Color_Content(PyObject *self, PyObject *args) +_curses_color_content_impl(PyObject *module, short color_number) +/*[clinic end generated code: output=cb15cf3120d4bfc1 input=5555abb1c11e11b7]*/ { - short color,r,g,b; + short r,g,b; PyCursesInitialised; PyCursesInitialisedColor; - if (!PyArg_ParseTuple(args, "h:color_content", &color)) return NULL; - - if (color_content(color, &r, &g, &b) != ERR) + if (color_content(color_number, &r, &g, &b) != ERR) return Py_BuildValue("(iii)", r, g, b); else { PyErr_SetString(PyCursesError, @@ -2195,47 +2601,155 @@ PyCurses_Color_Content(PyObject *self, PyObject *args) } } +/*[clinic input] +_curses.color_pair + + color_number: short + The number of the color (0 - COLORS). + / + +Return the attribute value for displaying text in the specified color. + +This attribute value can be combined with A_STANDOUT, A_REVERSE, and the +other A_* attributes. pair_number() is the counterpart to this function. +[clinic start generated code]*/ + static PyObject * -PyCurses_color_pair(PyObject *self, PyObject *args) +_curses_color_pair_impl(PyObject *module, short color_number) +/*[clinic end generated code: output=6a84cb6b29ecaf9a input=a9d3eb6f50e4dc12]*/ { - int n; - PyCursesInitialised; PyCursesInitialisedColor; - if (!PyArg_ParseTuple(args, "i:color_pair", &n)) return NULL; - return PyLong_FromLong((long) (n << 8)); + return PyLong_FromLong((long) (color_number << 8)); } +/*[clinic input] +_curses.curs_set + + visibility: int + 0 for invisible, 1 for normal visible, or 2 for very visible. + / + +Set the cursor state. + +If the terminal supports the visibility requested, the previous cursor +state is returned; otherwise, an exception is raised. On many terminals, +the "visible" mode is an underline cursor and the "very visible" mode is +a block cursor. +[clinic start generated code]*/ + static PyObject * -PyCurses_Curs_Set(PyObject *self, PyObject *args) +_curses_curs_set_impl(PyObject *module, int visibility) +/*[clinic end generated code: output=ee8e62483b1d6cd4 input=81a7924a65d29504]*/ { - int vis,erg; + int erg; PyCursesInitialised; - if (!PyArg_ParseTuple(args, "i:curs_set", &vis)) return NULL; - - erg = curs_set(vis); + erg = curs_set(visibility); if (erg == ERR) return PyCursesCheckERR(erg, "curs_set"); return PyLong_FromLong((long) erg); } +/*[clinic input] +_curses.def_prog_mode + +Save the current terminal mode as the "program" mode. + +The "program" mode is the mode when the running program is using curses. + +Subsequent calls to reset_prog_mode() will restore this mode. +[clinic start generated code]*/ + static PyObject * -PyCurses_Delay_Output(PyObject *self, PyObject *args) -{ - int ms; +_curses_def_prog_mode_impl(PyObject *module) +/*[clinic end generated code: output=05d5a351fff874aa input=768b9cace620dda5]*/ +NoArgNoReturnFunctionBody(def_prog_mode) - PyCursesInitialised; +/*[clinic input] +_curses.def_shell_mode + +Save the current terminal mode as the "shell" mode. + +The "shell" mode is the mode when the running program is not using curses. + +Subsequent calls to reset_shell_mode() will restore this mode. +[clinic start generated code]*/ + +static PyObject * +_curses_def_shell_mode_impl(PyObject *module) +/*[clinic end generated code: output=d6e42f5c768f860f input=5ead21f6f0baa894]*/ +NoArgNoReturnFunctionBody(def_shell_mode) + +/*[clinic input] +_curses.delay_output + + ms: int + Duration in milliseconds. + / + +Insert a pause in output. +[clinic start generated code]*/ - if (!PyArg_ParseTuple(args, "i:delay_output", &ms)) return NULL; +static PyObject * +_curses_delay_output_impl(PyObject *module, int ms) +/*[clinic end generated code: output=b6613a67f17fa4f4 input=5316457f5f59196c]*/ +{ + PyCursesInitialised; return PyCursesCheckERR(delay_output(ms), "delay_output"); } +/*[clinic input] +_curses.doupdate + +Update the physical screen to match the virtual screen. +[clinic start generated code]*/ + +static PyObject * +_curses_doupdate_impl(PyObject *module) +/*[clinic end generated code: output=f34536975a75680c input=8da80914432a6489]*/ +NoArgNoReturnFunctionBody(doupdate) + +/*[clinic input] +_curses.echo + + flag: bool(accept={int}) = True + If false, the effect is the same as calling noecho(). + / + +Enter echo mode. + +In echo mode, each character input is echoed to the screen as it is entered. +[clinic start generated code]*/ + +static PyObject * +_curses_echo_impl(PyObject *module, int flag) +/*[clinic end generated code: output=03acb2ddfa6c8729 input=2e9e891d637eac5d]*/ +NoArgOrFlagNoReturnFunctionBody(echo, flag) + +/*[clinic input] +_curses.endwin + +De-initialize the library, and return terminal to normal status. +[clinic start generated code]*/ + +static PyObject * +_curses_endwin_impl(PyObject *module) +/*[clinic end generated code: output=c0150cd96d2f4128 input=e172cfa43062f3fa]*/ +NoArgNoReturnFunctionBody(endwin) + +/*[clinic input] +_curses.erasechar + +Return the user's current erase character. +[clinic start generated code]*/ + static PyObject * -PyCurses_EraseChar(PyObject *self) +_curses_erasechar_impl(PyObject *module) +/*[clinic end generated code: output=3df305dc6b926b3f input=628c136c3c5758d3]*/ { char ch; @@ -2246,9 +2760,45 @@ PyCurses_EraseChar(PyObject *self) return PyBytes_FromStringAndSize(&ch, 1); } +/*[clinic input] +_curses.flash + +Flash the screen. + +That is, change it to reverse-video and then change it back in a short interval. +[clinic start generated code]*/ + +static PyObject * +_curses_flash_impl(PyObject *module) +/*[clinic end generated code: output=488b8a0ebd9ea9b8 input=02fdfb06c8fc3171]*/ +NoArgNoReturnFunctionBody(flash) + +/*[clinic input] +_curses.flushinp + +Flush all input buffers. + +This throws away any typeahead that has been typed by the user and has not +yet been processed by the program. +[clinic start generated code]*/ + +static PyObject * +_curses_flushinp_impl(PyObject *module) +/*[clinic end generated code: output=7e7a1fc1473960f5 input=59d042e705cef5ec]*/ +NoArgNoReturnVoidFunctionBody(flushinp) + #ifdef getsyx +/*[clinic input] +_curses.getsyx + +Return the current coordinates of the virtual screen cursor. + +Return a (y, x) tuple. If leaveok is currently true, return (-1, -1). +[clinic start generated code]*/ + static PyObject * -PyCurses_getsyx(PyObject *self) +_curses_getsyx_impl(PyObject *module) +/*[clinic end generated code: output=c8e6c3f42349a038 input=9e1f862f3b4f7cba]*/ { int x = 0; int y = 0; @@ -2262,8 +2812,18 @@ PyCurses_getsyx(PyObject *self) #endif #ifdef NCURSES_MOUSE_VERSION +/*[clinic input] +_curses.getmouse + +Retrieve the queued mouse event. + +After getch() returns KEY_MOUSE to signal a mouse event, this function +returns a 5-tuple (id, x, y, z, bstate). +[clinic start generated code]*/ + static PyObject * -PyCurses_GetMouse(PyObject *self) +_curses_getmouse_impl(PyObject *module) +/*[clinic end generated code: output=ccf4242546b9cfa8 input=5b756ee6f5b481b1]*/ { int rtn; MEVENT event; @@ -2281,18 +2841,29 @@ PyCurses_GetMouse(PyObject *self) (unsigned long) event.bstate); } +/*[clinic input] +_curses.ungetmouse + + id: short + x: int + y: int + z: int + bstate: unsigned_long(bitwise=True) + / + +Push a KEY_MOUSE event onto the input queue. + +The following getmouse() will return the given state data. +[clinic start generated code]*/ + static PyObject * -PyCurses_UngetMouse(PyObject *self, PyObject *args) +_curses_ungetmouse_impl(PyObject *module, short id, int x, int y, int z, + unsigned long bstate) +/*[clinic end generated code: output=3430c9b0fc5c4341 input=fd650b2ca5a01e8f]*/ { MEVENT event; - short id; - int x, y, z; - unsigned long bstate; PyCursesInitialised; - if (!PyArg_ParseTuple(args, "hiiik", - &id, &x, &y, &z, &bstate)) - return NULL; event.id = id; event.x = x; @@ -2303,8 +2874,21 @@ PyCurses_UngetMouse(PyObject *self, PyObject *args) } #endif +/*[clinic input] +_curses.getwin + + file: object + / + +Read window related data stored in the file by an earlier putwin() call. + +The routine then creates and initializes a new window using that data, +returning the new window object. +[clinic start generated code]*/ + static PyObject * -PyCurses_GetWin(PyCursesWindowObject *self, PyObject *stream) +_curses_getwin(PyObject *module, PyObject *file) +/*[clinic end generated code: output=a79e0df3379af756 input=f713d2bba0e4c929]*/ { FILE *fp; PyObject *data; @@ -2322,8 +2906,7 @@ PyCurses_GetWin(PyCursesWindowObject *self, PyObject *stream) if (_Py_set_inheritable(fileno(fp), 0, NULL) < 0) goto error; - - data = _PyObject_CallMethodId(stream, &PyId_read, NULL); + data = _PyObject_CallMethodId(file, &PyId_read, NULL); if (data == NULL) goto error; if (!PyBytes_Check(data)) { @@ -2354,82 +2937,158 @@ PyCurses_GetWin(PyCursesWindowObject *self, PyObject *stream) return res; } +/*[clinic input] +_curses.halfdelay + + tenths: byte + Maximal blocking delay in tenths of seconds (1 - 255). + / + +Enter half-delay mode. + +Use nocbreak() to leave half-delay mode. +[clinic start generated code]*/ + static PyObject * -PyCurses_HalfDelay(PyObject *self, PyObject *args) +_curses_halfdelay_impl(PyObject *module, unsigned char tenths) +/*[clinic end generated code: output=e92cdf0ef33c0663 input=e42dce7259c15100]*/ { - unsigned char tenths; - PyCursesInitialised; - if (!PyArg_ParseTuple(args, "b:halfdelay", &tenths)) return NULL; - return PyCursesCheckERR(halfdelay(tenths), "halfdelay"); } +/*[clinic input] +_curses.has_colors + +Return True if the terminal can display colors; otherwise, return False. +[clinic start generated code]*/ + +static PyObject * +_curses_has_colors_impl(PyObject *module) +/*[clinic end generated code: output=db5667483139e3e2 input=b2ec41b739d896c6]*/ +NoArgTrueFalseFunctionBody(has_colors) + +/*[clinic input] +_curses.has_ic + +Return True if the terminal has insert- and delete-character capabilities. +[clinic start generated code]*/ + +static PyObject * +_curses_has_ic_impl(PyObject *module) +/*[clinic end generated code: output=6be24da9cb1268fe input=9bc2d3a797cc7324]*/ +NoArgTrueFalseFunctionBody(has_ic) + +/*[clinic input] +_curses.has_il + +Return True if the terminal has insert- and delete-line capabilities. +[clinic start generated code]*/ + +static PyObject * +_curses_has_il_impl(PyObject *module) +/*[clinic end generated code: output=d45bd7788ff9f5f4 input=cd939d5607ee5427]*/ +NoArgTrueFalseFunctionBody(has_il) + #ifdef HAVE_CURSES_HAS_KEY +/*[clinic input] +_curses.has_key + + key: int + Key number. + / + +Return True if the current terminal type recognizes a key with that value. +[clinic start generated code]*/ + static PyObject * -PyCurses_has_key(PyObject *self, PyObject *args) +_curses_has_key_impl(PyObject *module, int key) +/*[clinic end generated code: output=19ad48319414d0b1 input=78bd44acf1a4997c]*/ { - int ch; - PyCursesInitialised; - if (!PyArg_ParseTuple(args,"i",&ch)) return NULL; - - if (has_key(ch) == FALSE) { - Py_RETURN_FALSE; - } - Py_RETURN_TRUE; + return PyBool_FromLong(has_key(key)); } #endif +/*[clinic input] +_curses.init_color + + color_number: short + The number of the color to be changed (0 - COLORS). + r: short + Red component (0 - 1000). + g: short + Green component (0 - 1000). + b: short + Blue component (0 - 1000). + / + +Change the definition of a color. + +When init_color() is used, all occurrences of that color on the screen +immediately change to the new definition. This function is a no-op on +most terminals; it is active only if can_change_color() returns 1. +[clinic start generated code]*/ + static PyObject * -PyCurses_Init_Color(PyObject *self, PyObject *args) +_curses_init_color_impl(PyObject *module, short color_number, short r, + short g, short b) +/*[clinic end generated code: output=280236f5efe9776a input=f3a05bd38f619175]*/ { - short color, r, g, b; - PyCursesInitialised; PyCursesInitialisedColor; - switch(PyTuple_Size(args)) { - case 4: - if (!PyArg_ParseTuple(args, "hhhh;color,r,g,b", &color, &r, &g, &b)) return NULL; - break; - default: - PyErr_SetString(PyExc_TypeError, "init_color requires 4 arguments"); - return NULL; - } - - return PyCursesCheckERR(init_color(color, r, g, b), "init_color"); + return PyCursesCheckERR(init_color(color_number, r, g, b), "init_color"); } +/*[clinic input] +_curses.init_pair + + pair_number: short + The number of the color-pair to be changed (1 - (COLOR_PAIRS-1)). + fg: short + Foreground color number (0 - COLORS). + bg: short + Background color number (0 - COLORS). + / + +Change the definition of a color-pair. + +If the color-pair was previously initialized, the screen is refreshed and +all occurrences of that color-pair are changed to the new definition. +[clinic start generated code]*/ + static PyObject * -PyCurses_Init_Pair(PyObject *self, PyObject *args) +_curses_init_pair_impl(PyObject *module, short pair_number, short fg, + short bg) +/*[clinic end generated code: output=9c2ce39c22f376b6 input=c9f0b11b17a2ac6d]*/ { - short pair, f, b; - PyCursesInitialised; PyCursesInitialisedColor; - if (PyTuple_Size(args) != 3) { - PyErr_SetString(PyExc_TypeError, "init_pair requires 3 arguments"); - return NULL; - } - - if (!PyArg_ParseTuple(args, "hhh;pair, f, b", &pair, &f, &b)) return NULL; - - return PyCursesCheckERR(init_pair(pair, f, b), "init_pair"); + return PyCursesCheckERR(init_pair(pair_number, fg, bg), "init_pair"); } static PyObject *ModDict; +/*[clinic input] +_curses.initscr + +Initialize the library. + +Return a WindowObject which represents the whole screen. +[clinic start generated code]*/ + static PyObject * -PyCurses_InitScr(PyObject *self) +_curses_initscr_impl(PyObject *module) +/*[clinic end generated code: output=619fb68443810b7b input=514f4bce1821f6b5]*/ { WINDOW *win; PyCursesWindowObject *winobj; - if (initialised == TRUE) { + if (initialised) { wrefresh(stdscr); return (PyObject *)PyCursesWindow_New(stdscr, NULL); } @@ -2528,19 +3187,24 @@ PyCurses_InitScr(PyObject *self) return (PyObject *)winobj; } +/*[clinic input] +_curses.setupterm + + term: str(accept={str, NoneType}) = NULL + Terminal name. + If omitted, the value of the TERM environment variable will be used. + fd: int = -1 + File descriptor to which any initialization sequences will be sent. + If not supplied, the file descriptor for sys.stdout will be used. + +Initialize the terminal. +[clinic start generated code]*/ + static PyObject * -PyCurses_setupterm(PyObject* self, PyObject *args, PyObject* keywds) +_curses_setupterm_impl(PyObject *module, const char *term, int fd) +/*[clinic end generated code: output=4584e587350f2848 input=8ac5f78ec6268be3]*/ { - int fd = -1; int err; - char* termstr = NULL; - - static char *kwlist[] = {"term", "fd", NULL}; - - if (!PyArg_ParseTupleAndKeywords( - args, keywds, "|zi:setupterm", kwlist, &termstr, &fd)) { - return NULL; - } if (fd == -1) { PyObject* sys_stdout; @@ -2561,7 +3225,7 @@ PyCurses_setupterm(PyObject* self, PyObject *args, PyObject* keywds) } } - if (!initialised_setupterm && setupterm(termstr,fd,&err) == ERR) { + if (!initialised_setupterm && setupterm((char *)term, fd, &err) == ERR) { const char* s = "setupterm: unknown error"; if (err == 0) { @@ -2579,67 +3243,93 @@ PyCurses_setupterm(PyObject* self, PyObject *args, PyObject* keywds) Py_RETURN_NONE; } +/*[clinic input] +_curses.intrflush + + flag: bool(accept={int}) + / + +[clinic start generated code]*/ + static PyObject * -PyCurses_IntrFlush(PyObject *self, PyObject *args) +_curses_intrflush_impl(PyObject *module, int flag) +/*[clinic end generated code: output=c1986df35e999a0f input=fcba57bb28dfd795]*/ { - int ch; - PyCursesInitialised; - switch(PyTuple_Size(args)) { - case 1: - if (!PyArg_ParseTuple(args,"i;True(1), False(0)",&ch)) return NULL; - break; - default: - PyErr_SetString(PyExc_TypeError, "intrflush requires 1 argument"); - return NULL; - } - - return PyCursesCheckERR(intrflush(NULL,ch), "intrflush"); + return PyCursesCheckERR(intrflush(NULL, flag), "intrflush"); } +/*[clinic input] +_curses.isendwin + +Return True if endwin() has been called. +[clinic start generated code]*/ + +static PyObject * +_curses_isendwin_impl(PyObject *module) +/*[clinic end generated code: output=d73179e4a7e1eb8c input=6cdb01a7ebf71397]*/ +NoArgTrueFalseFunctionBody(isendwin) + #ifdef HAVE_CURSES_IS_TERM_RESIZED +/*[clinic input] +_curses.is_term_resized + + nlines: int + Height. + ncols: int + Width. + / + +Return True if resize_term() would modify the window structure, False otherwise. +[clinic start generated code]*/ + static PyObject * -PyCurses_Is_Term_Resized(PyObject *self, PyObject *args) +_curses_is_term_resized_impl(PyObject *module, int nlines, int ncols) +/*[clinic end generated code: output=aafe04afe50f1288 input=ca9c0bd0fb8ab444]*/ { - int lines; - int columns; - int result; - PyCursesInitialised; - if (!PyArg_ParseTuple(args,"ii:is_term_resized", &lines, &columns)) - return NULL; - result = is_term_resized(lines, columns); - if (result == TRUE) { - Py_RETURN_TRUE; - } else { - Py_RETURN_FALSE; - } + return PyBool_FromLong(is_term_resized(nlines, ncols)); } #endif /* HAVE_CURSES_IS_TERM_RESIZED */ +/*[clinic input] +_curses.keyname + + key: int + Key number. + / + +Return the name of specified key. +[clinic start generated code]*/ + static PyObject * -PyCurses_KeyName(PyObject *self, PyObject *args) +_curses_keyname_impl(PyObject *module, int key) +/*[clinic end generated code: output=fa2675ab3f4e056b input=ee4b1d0f243a2a2b]*/ { const char *knp; - int ch; PyCursesInitialised; - if (!PyArg_ParseTuple(args,"i",&ch)) return NULL; - - if (ch < 0) { + if (key < 0) { PyErr_SetString(PyExc_ValueError, "invalid key number"); return NULL; } - knp = keyname(ch); + knp = keyname(key); return PyBytes_FromString((knp == NULL) ? "" : knp); } +/*[clinic input] +_curses.killchar + +Return the user's current line kill character. +[clinic start generated code]*/ + static PyObject * -PyCurses_KillChar(PyObject *self) +_curses_killchar_impl(PyObject *module) +/*[clinic end generated code: output=31c3a45b2c528269 input=1ff171c38df5ccad]*/ { char ch; @@ -2648,74 +3338,132 @@ PyCurses_KillChar(PyObject *self) return PyBytes_FromStringAndSize(&ch, 1); } +/*[clinic input] +_curses.longname + +Return the terminfo long name field describing the current terminal. + +The maximum length of a verbose description is 128 characters. It is defined +only after the call to initscr(). +[clinic start generated code]*/ + static PyObject * -PyCurses_Meta(PyObject *self, PyObject *args) -{ - int ch; +_curses_longname_impl(PyObject *module) +/*[clinic end generated code: output=fdf30433727ef568 input=84c3f20201b1098e]*/ +NoArgReturnStringFunctionBody(longname) - PyCursesInitialised; +/*[clinic input] +_curses.meta - switch(PyTuple_Size(args)) { - case 1: - if (!PyArg_ParseTuple(args,"i;True(1), False(0)",&ch)) return NULL; - break; - default: - PyErr_SetString(PyExc_TypeError, "meta requires 1 argument"); - return NULL; - } + yes: bool(accept={int}) + / + +Enable/disable meta keys. + +If yes is True, allow 8-bit characters to be input. If yes is False, +allow only 7-bit characters. +[clinic start generated code]*/ - return PyCursesCheckERR(meta(stdscr, ch), "meta"); +static PyObject * +_curses_meta_impl(PyObject *module, int yes) +/*[clinic end generated code: output=22f5abda46a605d8 input=af9892e3a74f35db]*/ +{ + PyCursesInitialised; + + return PyCursesCheckERR(meta(stdscr, yes), "meta"); } #ifdef NCURSES_MOUSE_VERSION +/*[clinic input] +_curses.mouseinterval + + interval: int + Time in milliseconds. + / + +Set and retrieve the maximum time between press and release in a click. + +Set the maximum time that can elapse between press and release events in +order for them to be recognized as a click, and return the previous interval +value. +[clinic start generated code]*/ + static PyObject * -PyCurses_MouseInterval(PyObject *self, PyObject *args) +_curses_mouseinterval_impl(PyObject *module, int interval) +/*[clinic end generated code: output=c4f5ff04354634c5 input=75aaa3f0db10ac4e]*/ { - int interval; PyCursesInitialised; - if (!PyArg_ParseTuple(args,"i;interval",&interval)) - return NULL; return PyCursesCheckERR(mouseinterval(interval), "mouseinterval"); } +/*[clinic input] +_curses.mousemask + + newmask: unsigned_long(bitwise=True) + / + +Set the mouse events to be reported, and return a tuple (availmask, oldmask). + +Return a tuple (availmask, oldmask). availmask indicates which of the +specified mouse events can be reported; on complete failure it returns 0. +oldmask is the previous value of the given window's mouse event mask. +If this function is never called, no mouse events are ever reported. +[clinic start generated code]*/ + static PyObject * -PyCurses_MouseMask(PyObject *self, PyObject *args) +_curses_mousemask_impl(PyObject *module, unsigned long newmask) +/*[clinic end generated code: output=9406cf1b8a36e485 input=bdf76b7568a3c541]*/ { - unsigned long newmask; mmask_t oldmask, availmask; PyCursesInitialised; - if (!PyArg_ParseTuple(args,"k;mousemask",&newmask)) - return NULL; availmask = mousemask((mmask_t)newmask, &oldmask); return Py_BuildValue("(kk)", (unsigned long)availmask, (unsigned long)oldmask); } #endif +/*[clinic input] +_curses.napms + + ms: int + Duration in milliseconds. + / + +Sleep for specified time. +[clinic start generated code]*/ + static PyObject * -PyCurses_Napms(PyObject *self, PyObject *args) +_curses_napms_impl(PyObject *module, int ms) +/*[clinic end generated code: output=a40a1da2e39ea438 input=20cd3af2b6900f56]*/ { - int ms; - PyCursesInitialised; - if (!PyArg_ParseTuple(args, "i;ms", &ms)) return NULL; return Py_BuildValue("i", napms(ms)); } +/*[clinic input] +_curses.newpad + + nlines: int + Height. + ncols: int + Width. + / + +Create and return a pointer to a new pad data structure. +[clinic start generated code]*/ + static PyObject * -PyCurses_NewPad(PyObject *self, PyObject *args) +_curses_newpad_impl(PyObject *module, int nlines, int ncols) +/*[clinic end generated code: output=de52a56eb1098ec9 input=93f1272f240d8894]*/ { WINDOW *win; - int nlines, ncols; PyCursesInitialised; - if (!PyArg_ParseTuple(args,"ii;nlines,ncols",&nlines,&ncols)) return NULL; - win = newpad(nlines, ncols); if (win == NULL) { @@ -2726,29 +3474,36 @@ PyCurses_NewPad(PyObject *self, PyObject *args) return (PyObject *)PyCursesWindow_New(win, NULL); } +/*[clinic input] +_curses.newwin + + nlines: int + Height. + ncols: int + Width. + [ + begin_y: int = 0 + Top side y-coordinate. + begin_x: int = 0 + Left side x-coordinate. + ] + / + +Return a new window. + +By default, the window will extend from the specified position to the lower +right corner of the screen. +[clinic start generated code]*/ + static PyObject * -PyCurses_NewWindow(PyObject *self, PyObject *args) +_curses_newwin_impl(PyObject *module, int nlines, int ncols, + int group_right_1, int begin_y, int begin_x) +/*[clinic end generated code: output=c1e0a8dc8ac2826c input=29312c15a72a003d]*/ { WINDOW *win; - int nlines, ncols, begin_y=0, begin_x=0; PyCursesInitialised; - switch (PyTuple_Size(args)) { - case 2: - if (!PyArg_ParseTuple(args,"ii;nlines,ncols",&nlines,&ncols)) - return NULL; - break; - case 4: - if (!PyArg_ParseTuple(args, "iiii;nlines,ncols,begin_y,begin_x", - &nlines,&ncols,&begin_y,&begin_x)) - return NULL; - break; - default: - PyErr_SetString(PyExc_TypeError, "newwin requires 2 or 4 arguments"); - return NULL; - } - win = newwin(nlines,ncols,begin_y,begin_x); if (win == NULL) { PyErr_SetString(PyCursesError, catchall_NULL); @@ -2758,24 +3513,111 @@ PyCurses_NewWindow(PyObject *self, PyObject *args) return (PyObject *)PyCursesWindow_New(win, NULL); } +/*[clinic input] +_curses.nl + + flag: bool(accept={int}) = True + If false, the effect is the same as calling nonl(). + / + +Enter newline mode. + +This mode translates the return key into newline on input, and translates +newline into return and line-feed on output. Newline mode is initially on. +[clinic start generated code]*/ + static PyObject * -PyCurses_Pair_Content(PyObject *self, PyObject *args) -{ - short pair,f,b; +_curses_nl_impl(PyObject *module, int flag) +/*[clinic end generated code: output=b39cc0ffc9015003 input=cf36a63f7b86e28a]*/ +NoArgOrFlagNoReturnFunctionBody(nl, flag) - PyCursesInitialised; - PyCursesInitialisedColor; +/*[clinic input] +_curses.nocbreak - switch(PyTuple_Size(args)) { - case 1: - if (!PyArg_ParseTuple(args, "h;pair", &pair)) return NULL; - break; - default: - PyErr_SetString(PyExc_TypeError, "pair_content requires 1 argument"); - return NULL; - } +Leave cbreak mode. + +Return to normal "cooked" mode with line buffering. +[clinic start generated code]*/ + +static PyObject * +_curses_nocbreak_impl(PyObject *module) +/*[clinic end generated code: output=eabf3833a4fbf620 input=e4b65f7d734af400]*/ +NoArgNoReturnFunctionBody(nocbreak) + +/*[clinic input] +_curses.noecho + +Leave echo mode. + +Echoing of input characters is turned off. +[clinic start generated code]*/ + +static PyObject * +_curses_noecho_impl(PyObject *module) +/*[clinic end generated code: output=cc95ab45bc98f41b input=76714df529e614c3]*/ +NoArgNoReturnFunctionBody(noecho) + +/*[clinic input] +_curses.nonl + +Leave newline mode. + +Disable translation of return into newline on input, and disable low-level +translation of newline into newline/return on output. +[clinic start generated code]*/ + +static PyObject * +_curses_nonl_impl(PyObject *module) +/*[clinic end generated code: output=99e917e9715770c6 input=9d37dd122d3022fc]*/ +NoArgNoReturnFunctionBody(nonl) + +/*[clinic input] +_curses.noqiflush + +Disable queue flushing. + +When queue flushing is disabled, normal flush of input and output queues +associated with the INTR, QUIT and SUSP characters will not be done. +[clinic start generated code]*/ + +static PyObject * +_curses_noqiflush_impl(PyObject *module) +/*[clinic end generated code: output=8b95a4229bbf0877 input=ba3e6b2e3e54c4df]*/ +NoArgNoReturnVoidFunctionBody(noqiflush) + +/*[clinic input] +_curses.noraw + +Leave raw mode. + +Return to normal "cooked" mode with line buffering. +[clinic start generated code]*/ + +static PyObject * +_curses_noraw_impl(PyObject *module) +/*[clinic end generated code: output=39894e5524c430cc input=6ec86692096dffb5]*/ +NoArgNoReturnFunctionBody(noraw) + +/*[clinic input] +_curses.pair_content + + pair_number: short + The number of the color pair (1 - (COLOR_PAIRS-1)). + / + +Return a tuple (fg, bg) containing the colors for the requested color pair. +[clinic start generated code]*/ + +static PyObject * +_curses_pair_content_impl(PyObject *module, short pair_number) +/*[clinic end generated code: output=5a72aa1a28bbacf3 input=f4d7fec5643b976b]*/ +{ + short f, b; + + PyCursesInitialised; + PyCursesInitialisedColor; - if (pair_content(pair, &f, &b)==ERR) { + if (pair_content(pair_number, &f, &b)==ERR) { PyErr_SetString(PyCursesError, "Argument 1 was out of range. (1..COLOR_PAIRS-1)"); return NULL; @@ -2784,57 +3626,71 @@ PyCurses_Pair_Content(PyObject *self, PyObject *args) return Py_BuildValue("(ii)", f, b); } +/*[clinic input] +_curses.pair_number + + attr: int + / + +Return the number of the color-pair set by the specified attribute value. + +color_pair() is the counterpart to this function. +[clinic start generated code]*/ + static PyObject * -PyCurses_pair_number(PyObject *self, PyObject *args) +_curses_pair_number_impl(PyObject *module, int attr) +/*[clinic end generated code: output=85bce7d65c0aa3f4 input=d478548e33f5e61a]*/ { - int n; - PyCursesInitialised; PyCursesInitialisedColor; - switch(PyTuple_Size(args)) { - case 1: - if (!PyArg_ParseTuple(args, "i;pairvalue", &n)) return NULL; - break; - default: - PyErr_SetString(PyExc_TypeError, - "pair_number requires 1 argument"); - return NULL; - } - - return PyLong_FromLong((long) ((n & A_COLOR) >> 8)); + return PyLong_FromLong((long) ((attr & A_COLOR) >> 8)); } +/*[clinic input] +_curses.putp + + string: str(accept={robuffer}) + / + +Emit the value of a specified terminfo capability for the current terminal. + +Note that the output of putp() always goes to standard output. +[clinic start generated code]*/ + static PyObject * -PyCurses_Putp(PyObject *self, PyObject *args) +_curses_putp_impl(PyObject *module, const char *string) +/*[clinic end generated code: output=e98081d1b8eb5816 input=1601faa828b44cb3]*/ { - char *str; - - if (!PyArg_ParseTuple(args,"y;str", &str)) - return NULL; - return PyCursesCheckERR(putp(str), "putp"); + return PyCursesCheckERR(putp(string), "putp"); } +/*[clinic input] +_curses.qiflush + + flag: bool(accept={int}) = True + If false, the effect is the same as calling noqiflush(). + / + +Enable queue flushing. + +If queue flushing is enabled, all output in the display driver queue +will be flushed when the INTR, QUIT and SUSP characters are read. +[clinic start generated code]*/ + static PyObject * -PyCurses_QiFlush(PyObject *self, PyObject *args) +_curses_qiflush_impl(PyObject *module, int flag) +/*[clinic end generated code: output=9167e862f760ea30 input=e9e4a389946a0dbc]*/ { - int flag = 0; - PyCursesInitialised; - switch(PyTuple_Size(args)) { - case 0: + if (flag) { qiflush(); - Py_RETURN_NONE; - case 1: - if (!PyArg_ParseTuple(args, "i;True(1) or False(0)", &flag)) return NULL; - if (flag) qiflush(); - else noqiflush(); - Py_RETURN_NONE; - default: - PyErr_SetString(PyExc_TypeError, "qiflush requires 0 or 1 arguments"); - return NULL; } + else { + noqiflush(); + } + Py_RETURN_NONE; } /* Internal helper used for updating curses.LINES, curses.COLS, _curses.LINES @@ -2888,28 +3744,97 @@ update_lines_cols(void) return 1; } -static PyObject * -PyCurses_update_lines_cols(PyObject *self) +/*[clinic input] +_curses.update_lines_cols -> int + +[clinic start generated code]*/ + +static int +_curses_update_lines_cols_impl(PyObject *module) +/*[clinic end generated code: output=0345e7f072ea711a input=3a87760f7d5197f0]*/ { - return PyLong_FromLong((long) update_lines_cols()); + return update_lines_cols(); } #endif +/*[clinic input] +_curses.raw + + flag: bool(accept={int}) = True + If false, the effect is the same as calling noraw(). + / + +Enter raw mode. + +In raw mode, normal line buffering and processing of interrupt, quit, +suspend, and flow control keys are turned off; characters are presented to +curses input functions one by one. +[clinic start generated code]*/ + +static PyObject * +_curses_raw_impl(PyObject *module, int flag) +/*[clinic end generated code: output=a750e4b342be015b input=e36d8db27832b848]*/ +NoArgOrFlagNoReturnFunctionBody(raw, flag) + +/*[clinic input] +_curses.reset_prog_mode + +Restore the terminal to "program" mode, as previously saved by def_prog_mode(). +[clinic start generated code]*/ + +static PyObject * +_curses_reset_prog_mode_impl(PyObject *module) +/*[clinic end generated code: output=15eb765abf0b6575 input=3d82bea2b3243471]*/ +NoArgNoReturnFunctionBody(reset_prog_mode) + +/*[clinic input] +_curses.reset_shell_mode + +Restore the terminal to "shell" mode, as previously saved by def_shell_mode(). +[clinic start generated code]*/ + +static PyObject * +_curses_reset_shell_mode_impl(PyObject *module) +/*[clinic end generated code: output=0238de2962090d33 input=1c738fa64bd1a24f]*/ +NoArgNoReturnFunctionBody(reset_shell_mode) + +/*[clinic input] +_curses.resetty + +Restore terminal mode. +[clinic start generated code]*/ + +static PyObject * +_curses_resetty_impl(PyObject *module) +/*[clinic end generated code: output=ff4b448e80a7cd63 input=940493de03624bb0]*/ +NoArgNoReturnFunctionBody(resetty) + #ifdef HAVE_CURSES_RESIZETERM +/*[clinic input] +_curses.resizeterm + + nlines: int + Height. + ncols: int + Width. + / + +Resize the standard and current windows to the specified dimensions. + +Adjusts other bookkeeping data used by the curses library that record the +window dimensions (in particular the SIGWINCH handler). +[clinic start generated code]*/ + static PyObject * -PyCurses_ResizeTerm(PyObject *self, PyObject *args) +_curses_resizeterm_impl(PyObject *module, int nlines, int ncols) +/*[clinic end generated code: output=56d6bcc5194ad055 input=0fca02ebad5ffa82]*/ { - int lines; - int columns; PyObject *result; PyCursesInitialised; - if (!PyArg_ParseTuple(args,"ii:resizeterm", &lines, &columns)) - return NULL; - - result = PyCursesCheckERR(resizeterm(lines, columns), "resizeterm"); + result = PyCursesCheckERR(resizeterm(nlines, ncols), "resizeterm"); if (!result) return NULL; if (!update_lines_cols()) @@ -2920,20 +3845,33 @@ PyCurses_ResizeTerm(PyObject *self, PyObject *args) #endif #ifdef HAVE_CURSES_RESIZE_TERM +/*[clinic input] +_curses.resize_term + + nlines: int + Height. + ncols: int + Width. + / + +Backend function used by resizeterm(), performing most of the work. + +When resizing the windows, resize_term() blank-fills the areas that are +extended. The calling application should fill in these areas with appropriate +data. The resize_term() function attempts to resize all windows. However, +due to the calling convention of pads, it is not possible to resize these +without additional interaction with the application. +[clinic start generated code]*/ + static PyObject * -PyCurses_Resize_Term(PyObject *self, PyObject *args) +_curses_resize_term_impl(PyObject *module, int nlines, int ncols) +/*[clinic end generated code: output=9e26d8b9ea311ed2 input=2197edd05b049ed4]*/ { - int lines; - int columns; - PyObject *result; PyCursesInitialised; - if (!PyArg_ParseTuple(args,"ii:resize_term", &lines, &columns)) - return NULL; - - result = PyCursesCheckERR(resize_term(lines, columns), "resize_term"); + result = PyCursesCheckERR(resize_term(nlines, ncols), "resize_term"); if (!result) return NULL; if (!update_lines_cols()) @@ -2942,20 +3880,37 @@ PyCurses_Resize_Term(PyObject *self, PyObject *args) } #endif /* HAVE_CURSES_RESIZE_TERM */ -#ifdef getsyx +/*[clinic input] +_curses.savetty + +Save terminal mode. +[clinic start generated code]*/ + static PyObject * -PyCurses_setsyx(PyObject *self, PyObject *args) -{ - int y,x; +_curses_savetty_impl(PyObject *module) +/*[clinic end generated code: output=6babc49f12b42199 input=fce6b2b7d2200102]*/ +NoArgNoReturnFunctionBody(savetty) - PyCursesInitialised; +#ifdef getsyx +/*[clinic input] +_curses.setsyx - if (PyTuple_Size(args)!=2) { - PyErr_SetString(PyExc_TypeError, "setsyx requires 2 arguments"); - return NULL; - } + y: int + Y-coordinate. + x: int + X-coordinate. + / + +Set the virtual screen cursor. + +If y and x are both -1, then leaveok is set. +[clinic start generated code]*/ - if (!PyArg_ParseTuple(args, "ii;y, x", &y, &x)) return NULL; +static PyObject * +_curses_setsyx_impl(PyObject *module, int y, int x) +/*[clinic end generated code: output=23dcf753511a2464 input=fa7f2b208e10a557]*/ +{ + PyCursesInitialised; setsyx(y,x); @@ -2963,8 +3918,22 @@ PyCurses_setsyx(PyObject *self, PyObject *args) } #endif +/*[clinic input] +_curses.start_color + +Initializes eight basic colors and global variables COLORS and COLOR_PAIRS. + +Must be called if the programmer wants to use colors, and before any other +color manipulation routine is called. It is good practice to call this +routine right after initscr(). + +It also restores the colors on the terminal to the values they had when the +terminal was just turned on. +[clinic start generated code]*/ + static PyObject * -PyCurses_Start_Color(PyObject *self) +_curses_start_color_impl(PyObject *module) +/*[clinic end generated code: output=8b772b41d8090ede input=0ca0ecb2b77e1a12]*/ { int code; PyObject *c, *cp; @@ -2991,42 +3960,91 @@ PyCurses_Start_Color(PyObject *self) } } +/*[clinic input] +_curses.termattrs + +Return a logical OR of all video attributes supported by the terminal. +[clinic start generated code]*/ + static PyObject * -PyCurses_tigetflag(PyObject *self, PyObject *args) -{ - char *capname; +_curses_termattrs_impl(PyObject *module) +/*[clinic end generated code: output=b06f437fce1b6fc4 input=0559882a04f84d1d]*/ +NoArgReturnIntFunctionBody(termattrs) - PyCursesSetupTermCalled; +/*[clinic input] +_curses.termname - if (!PyArg_ParseTuple(args, "s", &capname)) - return NULL; +Return the value of the environment variable TERM, truncated to 14 characters. +[clinic start generated code]*/ + +static PyObject * +_curses_termname_impl(PyObject *module) +/*[clinic end generated code: output=96375577ebbd67fd input=33c08d000944f33f]*/ +NoArgReturnStringFunctionBody(termname) + +/*[clinic input] +_curses.tigetflag + + capname: str + The terminfo capability name. + / + +Return the value of the Boolean capability. + +The value -1 is returned if capname is not a Boolean capability, or 0 if +it is canceled or absent from the terminal description. +[clinic start generated code]*/ + +static PyObject * +_curses_tigetflag_impl(PyObject *module, const char *capname) +/*[clinic end generated code: output=8853c0e55542195b input=b0787af9e3e9a6ce]*/ +{ + PyCursesSetupTermCalled; return PyLong_FromLong( (long) tigetflag( capname ) ); } +/*[clinic input] +_curses.tigetnum + + capname: str + The terminfo capability name. + / + +Return the value of the numeric capability. + +The value -2 is returned if capname is not a numeric capability, or -1 if +it is canceled or absent from the terminal description. +[clinic start generated code]*/ + static PyObject * -PyCurses_tigetnum(PyObject *self, PyObject *args) +_curses_tigetnum_impl(PyObject *module, const char *capname) +/*[clinic end generated code: output=46f8b0a1b5dff42f input=5cdf2f410b109720]*/ { - char *capname; - PyCursesSetupTermCalled; - if (!PyArg_ParseTuple(args, "s", &capname)) - return NULL; - return PyLong_FromLong( (long) tigetnum( capname ) ); } +/*[clinic input] +_curses.tigetstr + + capname: str + The terminfo capability name. + / + +Return the value of the string capability. + +None is returned if capname is not a string capability, or is canceled or +absent from the terminal description. +[clinic start generated code]*/ + static PyObject * -PyCurses_tigetstr(PyObject *self, PyObject *args) +_curses_tigetstr_impl(PyObject *module, const char *capname) +/*[clinic end generated code: output=f22b576ad60248f3 input=36644df25c73c0a7]*/ { - char *capname; - PyCursesSetupTermCalled; - if (!PyArg_ParseTuple(args, "s", &capname)) - return NULL; - capname = tigetstr( capname ); if (capname == NULL || capname == (char*) -1) { Py_RETURN_NONE; @@ -3034,22 +4052,35 @@ PyCurses_tigetstr(PyObject *self, PyObject *args) return PyBytes_FromString( capname ); } +/*[clinic input] +_curses.tparm + + str: str(accept={robuffer}) + Parameterized byte string obtained from the terminfo database. + i1: int = 0 + i2: int = 0 + i3: int = 0 + i4: int = 0 + i5: int = 0 + i6: int = 0 + i7: int = 0 + i8: int = 0 + i9: int = 0 + / + +Instantiate the specified byte string with the supplied parameters. +[clinic start generated code]*/ + static PyObject * -PyCurses_tparm(PyObject *self, PyObject *args) +_curses_tparm_impl(PyObject *module, const char *str, int i1, int i2, int i3, + int i4, int i5, int i6, int i7, int i8, int i9) +/*[clinic end generated code: output=599f62b615c667ff input=5e30b15786f032aa]*/ { - char* fmt; char* result = NULL; - int i1=0,i2=0,i3=0,i4=0,i5=0,i6=0,i7=0,i8=0,i9=0; PyCursesSetupTermCalled; - if (!PyArg_ParseTuple(args, "y|iiiiiiiii:tparm", - &fmt, &i1, &i2, &i3, &i4, - &i5, &i6, &i7, &i8, &i9)) { - return NULL; - } - - result = tparm(fmt,i1,i2,i3,i4,i5,i6,i7,i8,i9); + result = tparm(str,i1,i2,i3,i4,i5,i6,i7,i8,i9); if (!result) { PyErr_SetString(PyCursesError, "tparm() returned NULL"); return NULL; @@ -3059,50 +4090,75 @@ PyCurses_tparm(PyObject *self, PyObject *args) } #ifdef HAVE_CURSES_TYPEAHEAD +/*[clinic input] +_curses.typeahead + + fd: int + File descriptor. + / + +Specify that the file descriptor fd be used for typeahead checking. + +If fd is -1, then no typeahead checking is done. +[clinic start generated code]*/ + static PyObject * -PyCurses_TypeAhead(PyObject *self, PyObject *args) +_curses_typeahead_impl(PyObject *module, int fd) +/*[clinic end generated code: output=084bb649d7066583 input=f2968d8e1805051b]*/ { - int fd; - PyCursesInitialised; - if (!PyArg_ParseTuple(args,"i;fd",&fd)) return NULL; - return PyCursesCheckERR(typeahead( fd ), "typeahead"); } #endif +/*[clinic input] +_curses.unctrl + + ch: object + / + +Return a string which is a printable representation of the character ch. + +Control characters are displayed as a caret followed by the character, +for example as ^C. Printing characters are left as they are. +[clinic start generated code]*/ + static PyObject * -PyCurses_UnCtrl(PyObject *self, PyObject *args) +_curses_unctrl(PyObject *module, PyObject *ch) +/*[clinic end generated code: output=8e07fafc430c9434 input=cd1e35e16cd1ace4]*/ { - PyObject *temp; - chtype ch; + chtype ch_; PyCursesInitialised; - if (!PyArg_ParseTuple(args,"O;ch or int",&temp)) return NULL; - - if (!PyCurses_ConvertToChtype(NULL, temp, &ch)) + if (!PyCurses_ConvertToChtype(NULL, ch, &ch_)) return NULL; - return PyBytes_FromString(unctrl(ch)); + return PyBytes_FromString(unctrl(ch_)); } +/*[clinic input] +_curses.ungetch + + ch: object + / + +Push ch so the next getch() will return it. +[clinic start generated code]*/ + static PyObject * -PyCurses_UngetCh(PyObject *self, PyObject *args) +_curses_ungetch(PyObject *module, PyObject *ch) +/*[clinic end generated code: output=9b19d8268376d887 input=6681e6ae4c42e5eb]*/ { - PyObject *temp; - chtype ch; + chtype ch_; PyCursesInitialised; - if (!PyArg_ParseTuple(args,"O;ch or int",&temp)) - return NULL; - - if (!PyCurses_ConvertToChtype(NULL, temp, &ch)) + if (!PyCurses_ConvertToChtype(NULL, ch, &ch_)) return NULL; - return PyCursesCheckERR(ungetch(ch), "ungetch"); + return PyCursesCheckERR(ungetch(ch_), "ungetch"); } #ifdef HAVE_NCURSESW @@ -3153,46 +4209,70 @@ PyCurses_ConvertToWchar_t(PyObject *obj, } } +/*[clinic input] +_curses.unget_wch + + ch: object + / + +Push ch so the next get_wch() will return it. +[clinic start generated code]*/ + static PyObject * -PyCurses_Unget_Wch(PyObject *self, PyObject *args) +_curses_unget_wch(PyObject *module, PyObject *ch) +/*[clinic end generated code: output=1974c9fb01d37863 input=0d56dc65a46feebb]*/ { - PyObject *obj; wchar_t wch; PyCursesInitialised; - if (!PyArg_ParseTuple(args,"O", &obj)) - return NULL; - - if (!PyCurses_ConvertToWchar_t(obj, &wch)) + if (!PyCurses_ConvertToWchar_t(ch, &wch)) return NULL; return PyCursesCheckERR(unget_wch(wch), "unget_wch"); } #endif -#ifdef HAVE_CURSES_TYPEAHEAD +#ifdef HAVE_CURSES_USE_ENV +/*[clinic input] +_curses.use_env + + flag: bool(accept={int}) + / + +Use environment variables LINES and COLUMNS. + +If used, this function should be called before initscr() or newterm() are +called. + +When flag is False, the values of lines and columns specified in the terminfo +database will be used, even if environment variables LINES and COLUMNS (used +by default) are set, or if curses is running in a window (in which case +default behavior would be to use the window size if LINES and COLUMNS are +not set). +[clinic start generated code]*/ + static PyObject * -PyCurses_Use_Env(PyObject *self, PyObject *args) +_curses_use_env_impl(PyObject *module, int flag) +/*[clinic end generated code: output=b2c445e435c0b164 input=1778eb1e9151ea37]*/ { - int flag; - - switch(PyTuple_Size(args)) { - case 1: - if (!PyArg_ParseTuple(args,"i;True(1), False(0)",&flag)) - return NULL; - break; - default: - PyErr_SetString(PyExc_TypeError, "use_env requires 1 argument"); - return NULL; - } use_env(flag); Py_RETURN_NONE; } #endif #ifndef STRICT_SYSV_CURSES +/*[clinic input] +_curses.use_default_colors + +Allow use of default values for colors on terminals supporting this feature. + +Use this to support transparency in your application. The default color +is assigned to the color number -1. +[clinic start generated code]*/ + static PyObject * -PyCurses_Use_Default_Colors(PyObject *self) +_curses_use_default_colors_impl(PyObject *module) +/*[clinic end generated code: output=a3b81ff71dd901be input=656844367470e8fc]*/ { int code; @@ -3212,109 +4292,80 @@ PyCurses_Use_Default_Colors(PyObject *self) /* List of functions defined in the module */ static PyMethodDef PyCurses_methods[] = { - {"baudrate", (PyCFunction)PyCurses_baudrate, METH_NOARGS}, - {"beep", (PyCFunction)PyCurses_beep, METH_NOARGS}, - {"can_change_color", (PyCFunction)PyCurses_can_change_color, METH_NOARGS}, - {"cbreak", (PyCFunction)PyCurses_cbreak, METH_VARARGS}, - {"color_content", (PyCFunction)PyCurses_Color_Content, METH_VARARGS}, - {"color_pair", (PyCFunction)PyCurses_color_pair, METH_VARARGS}, - {"curs_set", (PyCFunction)PyCurses_Curs_Set, METH_VARARGS}, - {"def_prog_mode", (PyCFunction)PyCurses_def_prog_mode, METH_NOARGS}, - {"def_shell_mode", (PyCFunction)PyCurses_def_shell_mode, METH_NOARGS}, - {"delay_output", (PyCFunction)PyCurses_Delay_Output, METH_VARARGS}, - {"doupdate", (PyCFunction)PyCurses_doupdate, METH_NOARGS}, - {"echo", (PyCFunction)PyCurses_echo, METH_VARARGS}, - {"endwin", (PyCFunction)PyCurses_endwin, METH_NOARGS}, - {"erasechar", (PyCFunction)PyCurses_EraseChar, METH_NOARGS}, -#ifdef HAVE_CURSES_FILTER - {"filter", (PyCFunction)PyCurses_filter, METH_NOARGS}, -#endif - {"flash", (PyCFunction)PyCurses_flash, METH_NOARGS}, - {"flushinp", (PyCFunction)PyCurses_flushinp, METH_NOARGS}, -#ifdef NCURSES_MOUSE_VERSION - {"getmouse", (PyCFunction)PyCurses_GetMouse, METH_NOARGS}, - {"ungetmouse", (PyCFunction)PyCurses_UngetMouse, METH_VARARGS}, -#endif -#ifdef getsyx - {"getsyx", (PyCFunction)PyCurses_getsyx, METH_NOARGS}, -#endif - {"getwin", (PyCFunction)PyCurses_GetWin, METH_O}, - {"has_colors", (PyCFunction)PyCurses_has_colors, METH_NOARGS}, - {"has_ic", (PyCFunction)PyCurses_has_ic, METH_NOARGS}, - {"has_il", (PyCFunction)PyCurses_has_il, METH_NOARGS}, -#ifdef HAVE_CURSES_HAS_KEY - {"has_key", (PyCFunction)PyCurses_has_key, METH_VARARGS}, -#endif - {"halfdelay", (PyCFunction)PyCurses_HalfDelay, METH_VARARGS}, - {"init_color", (PyCFunction)PyCurses_Init_Color, METH_VARARGS}, - {"init_pair", (PyCFunction)PyCurses_Init_Pair, METH_VARARGS}, - {"initscr", (PyCFunction)PyCurses_InitScr, METH_NOARGS}, - {"intrflush", (PyCFunction)PyCurses_IntrFlush, METH_VARARGS}, - {"isendwin", (PyCFunction)PyCurses_isendwin, METH_NOARGS}, -#ifdef HAVE_CURSES_IS_TERM_RESIZED - {"is_term_resized", (PyCFunction)PyCurses_Is_Term_Resized, METH_VARARGS}, -#endif - {"keyname", (PyCFunction)PyCurses_KeyName, METH_VARARGS}, - {"killchar", (PyCFunction)PyCurses_KillChar, METH_NOARGS}, - {"longname", (PyCFunction)PyCurses_longname, METH_NOARGS}, - {"meta", (PyCFunction)PyCurses_Meta, METH_VARARGS}, -#ifdef NCURSES_MOUSE_VERSION - {"mouseinterval", (PyCFunction)PyCurses_MouseInterval, METH_VARARGS}, - {"mousemask", (PyCFunction)PyCurses_MouseMask, METH_VARARGS}, -#endif - {"napms", (PyCFunction)PyCurses_Napms, METH_VARARGS}, - {"newpad", (PyCFunction)PyCurses_NewPad, METH_VARARGS}, - {"newwin", (PyCFunction)PyCurses_NewWindow, METH_VARARGS}, - {"nl", (PyCFunction)PyCurses_nl, METH_VARARGS}, - {"nocbreak", (PyCFunction)PyCurses_nocbreak, METH_NOARGS}, - {"noecho", (PyCFunction)PyCurses_noecho, METH_NOARGS}, - {"nonl", (PyCFunction)PyCurses_nonl, METH_NOARGS}, - {"noqiflush", (PyCFunction)PyCurses_noqiflush, METH_NOARGS}, - {"noraw", (PyCFunction)PyCurses_noraw, METH_NOARGS}, - {"pair_content", (PyCFunction)PyCurses_Pair_Content, METH_VARARGS}, - {"pair_number", (PyCFunction)PyCurses_pair_number, METH_VARARGS}, - {"putp", (PyCFunction)PyCurses_Putp, METH_VARARGS}, - {"qiflush", (PyCFunction)PyCurses_QiFlush, METH_VARARGS}, - {"raw", (PyCFunction)PyCurses_raw, METH_VARARGS}, - {"reset_prog_mode", (PyCFunction)PyCurses_reset_prog_mode, METH_NOARGS}, - {"reset_shell_mode", (PyCFunction)PyCurses_reset_shell_mode, METH_NOARGS}, - {"resetty", (PyCFunction)PyCurses_resetty, METH_NOARGS}, -#ifdef HAVE_CURSES_RESIZETERM - {"resizeterm", (PyCFunction)PyCurses_ResizeTerm, METH_VARARGS}, -#endif -#ifdef HAVE_CURSES_RESIZE_TERM - {"resize_term", (PyCFunction)PyCurses_Resize_Term, METH_VARARGS}, -#endif - {"savetty", (PyCFunction)PyCurses_savetty, METH_NOARGS}, -#ifdef getsyx - {"setsyx", (PyCFunction)PyCurses_setsyx, METH_VARARGS}, -#endif - {"setupterm", (PyCFunction)PyCurses_setupterm, - METH_VARARGS|METH_KEYWORDS}, - {"start_color", (PyCFunction)PyCurses_Start_Color, METH_NOARGS}, - {"termattrs", (PyCFunction)PyCurses_termattrs, METH_NOARGS}, - {"termname", (PyCFunction)PyCurses_termname, METH_NOARGS}, - {"tigetflag", (PyCFunction)PyCurses_tigetflag, METH_VARARGS}, - {"tigetnum", (PyCFunction)PyCurses_tigetnum, METH_VARARGS}, - {"tigetstr", (PyCFunction)PyCurses_tigetstr, METH_VARARGS}, - {"tparm", (PyCFunction)PyCurses_tparm, METH_VARARGS}, -#ifdef HAVE_CURSES_TYPEAHEAD - {"typeahead", (PyCFunction)PyCurses_TypeAhead, METH_VARARGS}, -#endif - {"unctrl", (PyCFunction)PyCurses_UnCtrl, METH_VARARGS}, - {"ungetch", (PyCFunction)PyCurses_UngetCh, METH_VARARGS}, -#if defined(HAVE_CURSES_RESIZETERM) || defined(HAVE_CURSES_RESIZE_TERM) - {"update_lines_cols", (PyCFunction)PyCurses_update_lines_cols, METH_NOARGS}, -#endif -#ifdef HAVE_NCURSESW - {"unget_wch", (PyCFunction)PyCurses_Unget_Wch, METH_VARARGS}, -#endif -#ifdef HAVE_CURSES_USE_ENV - {"use_env", (PyCFunction)PyCurses_Use_Env, METH_VARARGS}, -#endif -#ifndef STRICT_SYSV_CURSES - {"use_default_colors", (PyCFunction)PyCurses_Use_Default_Colors, METH_NOARGS}, -#endif + _CURSES_BAUDRATE_METHODDEF + _CURSES_BEEP_METHODDEF + _CURSES_CAN_CHANGE_COLOR_METHODDEF + _CURSES_CBREAK_METHODDEF + _CURSES_COLOR_CONTENT_METHODDEF + _CURSES_COLOR_PAIR_METHODDEF + _CURSES_CURS_SET_METHODDEF + _CURSES_DEF_PROG_MODE_METHODDEF + _CURSES_DEF_SHELL_MODE_METHODDEF + _CURSES_DELAY_OUTPUT_METHODDEF + _CURSES_DOUPDATE_METHODDEF + _CURSES_ECHO_METHODDEF + _CURSES_ENDWIN_METHODDEF + _CURSES_ERASECHAR_METHODDEF + _CURSES_FILTER_METHODDEF + _CURSES_FLASH_METHODDEF + _CURSES_FLUSHINP_METHODDEF + _CURSES_GETMOUSE_METHODDEF + _CURSES_UNGETMOUSE_METHODDEF + _CURSES_GETSYX_METHODDEF + _CURSES_GETWIN_METHODDEF + _CURSES_HAS_COLORS_METHODDEF + _CURSES_HAS_IC_METHODDEF + _CURSES_HAS_IL_METHODDEF + _CURSES_HAS_KEY_METHODDEF + _CURSES_HALFDELAY_METHODDEF + _CURSES_INIT_COLOR_METHODDEF + _CURSES_INIT_PAIR_METHODDEF + _CURSES_INITSCR_METHODDEF + _CURSES_INTRFLUSH_METHODDEF + _CURSES_ISENDWIN_METHODDEF + _CURSES_IS_TERM_RESIZED_METHODDEF + _CURSES_KEYNAME_METHODDEF + _CURSES_KILLCHAR_METHODDEF + _CURSES_LONGNAME_METHODDEF + _CURSES_META_METHODDEF + _CURSES_MOUSEINTERVAL_METHODDEF + _CURSES_MOUSEMASK_METHODDEF + _CURSES_NAPMS_METHODDEF + _CURSES_NEWPAD_METHODDEF + _CURSES_NEWWIN_METHODDEF + _CURSES_NL_METHODDEF + _CURSES_NOCBREAK_METHODDEF + _CURSES_NOECHO_METHODDEF + _CURSES_NONL_METHODDEF + _CURSES_NOQIFLUSH_METHODDEF + _CURSES_NORAW_METHODDEF + _CURSES_PAIR_CONTENT_METHODDEF + _CURSES_PAIR_NUMBER_METHODDEF + _CURSES_PUTP_METHODDEF + _CURSES_QIFLUSH_METHODDEF + _CURSES_RAW_METHODDEF + _CURSES_RESET_PROG_MODE_METHODDEF + _CURSES_RESET_SHELL_MODE_METHODDEF + _CURSES_RESETTY_METHODDEF + _CURSES_RESIZETERM_METHODDEF + _CURSES_RESIZE_TERM_METHODDEF + _CURSES_SAVETTY_METHODDEF + _CURSES_SETSYX_METHODDEF + _CURSES_SETUPTERM_METHODDEF + _CURSES_START_COLOR_METHODDEF + _CURSES_TERMATTRS_METHODDEF + _CURSES_TERMNAME_METHODDEF + _CURSES_TIGETFLAG_METHODDEF + _CURSES_TIGETNUM_METHODDEF + _CURSES_TIGETSTR_METHODDEF + _CURSES_TPARM_METHODDEF + _CURSES_TYPEAHEAD_METHODDEF + _CURSES_UNCTRL_METHODDEF + _CURSES_UNGETCH_METHODDEF + _CURSES_UPDATE_LINES_COLS_METHODDEF + _CURSES_UNGET_WCH_METHODDEF + _CURSES_USE_ENV_METHODDEF + _CURSES_USE_DEFAULT_COLORS_METHODDEF {NULL, NULL} /* sentinel */ }; @@ -3496,5 +4547,8 @@ PyInit__curses(void) SetDictInt("KEY_MIN", KEY_MIN); SetDictInt("KEY_MAX", KEY_MAX); } + + Py_INCREF(&PyCursesWindow_Type); + PyModule_AddObject(m, "window", (PyObject *)&PyCursesWindow_Type); return m; } diff --git a/Modules/clinic/_curses_panel.c.h b/Modules/clinic/_curses_panel.c.h new file mode 100644 index 000000000000..e11c68d864a6 --- /dev/null +++ b/Modules/clinic/_curses_panel.c.h @@ -0,0 +1,317 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +PyDoc_STRVAR(_curses_panel_panel_bottom__doc__, +"bottom($self, /)\n" +"--\n" +"\n" +"Push the panel to the bottom of the stack."); + +#define _CURSES_PANEL_PANEL_BOTTOM_METHODDEF \ + {"bottom", (PyCFunction)_curses_panel_panel_bottom, METH_NOARGS, _curses_panel_panel_bottom__doc__}, + +static PyObject * +_curses_panel_panel_bottom_impl(PyCursesPanelObject *self); + +static PyObject * +_curses_panel_panel_bottom(PyCursesPanelObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _curses_panel_panel_bottom_impl(self); +} + +PyDoc_STRVAR(_curses_panel_panel_hide__doc__, +"hide($self, /)\n" +"--\n" +"\n" +"Hide the panel.\n" +"\n" +"This does not delete the object, it just makes the window on screen invisible."); + +#define _CURSES_PANEL_PANEL_HIDE_METHODDEF \ + {"hide", (PyCFunction)_curses_panel_panel_hide, METH_NOARGS, _curses_panel_panel_hide__doc__}, + +static PyObject * +_curses_panel_panel_hide_impl(PyCursesPanelObject *self); + +static PyObject * +_curses_panel_panel_hide(PyCursesPanelObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _curses_panel_panel_hide_impl(self); +} + +PyDoc_STRVAR(_curses_panel_panel_show__doc__, +"show($self, /)\n" +"--\n" +"\n" +"Display the panel (which might have been hidden)."); + +#define _CURSES_PANEL_PANEL_SHOW_METHODDEF \ + {"show", (PyCFunction)_curses_panel_panel_show, METH_NOARGS, _curses_panel_panel_show__doc__}, + +static PyObject * +_curses_panel_panel_show_impl(PyCursesPanelObject *self); + +static PyObject * +_curses_panel_panel_show(PyCursesPanelObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _curses_panel_panel_show_impl(self); +} + +PyDoc_STRVAR(_curses_panel_panel_top__doc__, +"top($self, /)\n" +"--\n" +"\n" +"Push panel to the top of the stack."); + +#define _CURSES_PANEL_PANEL_TOP_METHODDEF \ + {"top", (PyCFunction)_curses_panel_panel_top, METH_NOARGS, _curses_panel_panel_top__doc__}, + +static PyObject * +_curses_panel_panel_top_impl(PyCursesPanelObject *self); + +static PyObject * +_curses_panel_panel_top(PyCursesPanelObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _curses_panel_panel_top_impl(self); +} + +PyDoc_STRVAR(_curses_panel_panel_above__doc__, +"above($self, /)\n" +"--\n" +"\n" +"Return the panel above the current panel."); + +#define _CURSES_PANEL_PANEL_ABOVE_METHODDEF \ + {"above", (PyCFunction)_curses_panel_panel_above, METH_NOARGS, _curses_panel_panel_above__doc__}, + +static PyObject * +_curses_panel_panel_above_impl(PyCursesPanelObject *self); + +static PyObject * +_curses_panel_panel_above(PyCursesPanelObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _curses_panel_panel_above_impl(self); +} + +PyDoc_STRVAR(_curses_panel_panel_below__doc__, +"below($self, /)\n" +"--\n" +"\n" +"Return the panel below the current panel."); + +#define _CURSES_PANEL_PANEL_BELOW_METHODDEF \ + {"below", (PyCFunction)_curses_panel_panel_below, METH_NOARGS, _curses_panel_panel_below__doc__}, + +static PyObject * +_curses_panel_panel_below_impl(PyCursesPanelObject *self); + +static PyObject * +_curses_panel_panel_below(PyCursesPanelObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _curses_panel_panel_below_impl(self); +} + +PyDoc_STRVAR(_curses_panel_panel_hidden__doc__, +"hidden($self, /)\n" +"--\n" +"\n" +"Return True if the panel is hidden (not visible), False otherwise."); + +#define _CURSES_PANEL_PANEL_HIDDEN_METHODDEF \ + {"hidden", (PyCFunction)_curses_panel_panel_hidden, METH_NOARGS, _curses_panel_panel_hidden__doc__}, + +static PyObject * +_curses_panel_panel_hidden_impl(PyCursesPanelObject *self); + +static PyObject * +_curses_panel_panel_hidden(PyCursesPanelObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _curses_panel_panel_hidden_impl(self); +} + +PyDoc_STRVAR(_curses_panel_panel_move__doc__, +"move($self, y, x, /)\n" +"--\n" +"\n" +"Move the panel to the screen coordinates (y, x)."); + +#define _CURSES_PANEL_PANEL_MOVE_METHODDEF \ + {"move", (PyCFunction)_curses_panel_panel_move, METH_FASTCALL, _curses_panel_panel_move__doc__}, + +static PyObject * +_curses_panel_panel_move_impl(PyCursesPanelObject *self, int y, int x); + +static PyObject * +_curses_panel_panel_move(PyCursesPanelObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int y; + int x; + + if (!_PyArg_ParseStack(args, nargs, "ii:move", + &y, &x)) { + goto exit; + } + return_value = _curses_panel_panel_move_impl(self, y, x); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_panel_panel_window__doc__, +"window($self, /)\n" +"--\n" +"\n" +"Return the window object associated with the panel."); + +#define _CURSES_PANEL_PANEL_WINDOW_METHODDEF \ + {"window", (PyCFunction)_curses_panel_panel_window, METH_NOARGS, _curses_panel_panel_window__doc__}, + +static PyObject * +_curses_panel_panel_window_impl(PyCursesPanelObject *self); + +static PyObject * +_curses_panel_panel_window(PyCursesPanelObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _curses_panel_panel_window_impl(self); +} + +PyDoc_STRVAR(_curses_panel_panel_replace__doc__, +"replace($self, win, /)\n" +"--\n" +"\n" +"Change the window associated with the panel to the window win."); + +#define _CURSES_PANEL_PANEL_REPLACE_METHODDEF \ + {"replace", (PyCFunction)_curses_panel_panel_replace, METH_O, _curses_panel_panel_replace__doc__}, + +static PyObject * +_curses_panel_panel_replace_impl(PyCursesPanelObject *self, + PyCursesWindowObject *win); + +static PyObject * +_curses_panel_panel_replace(PyCursesPanelObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + PyCursesWindowObject *win; + + if (!PyArg_Parse(arg, "O!:replace", &PyCursesWindow_Type, &win)) { + goto exit; + } + return_value = _curses_panel_panel_replace_impl(self, win); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_panel_panel_set_userptr__doc__, +"set_userptr($self, obj, /)\n" +"--\n" +"\n" +"Set the panel?s user pointer to obj."); + +#define _CURSES_PANEL_PANEL_SET_USERPTR_METHODDEF \ + {"set_userptr", (PyCFunction)_curses_panel_panel_set_userptr, METH_O, _curses_panel_panel_set_userptr__doc__}, + +PyDoc_STRVAR(_curses_panel_panel_userptr__doc__, +"userptr($self, /)\n" +"--\n" +"\n" +"Return the user pointer for the panel."); + +#define _CURSES_PANEL_PANEL_USERPTR_METHODDEF \ + {"userptr", (PyCFunction)_curses_panel_panel_userptr, METH_NOARGS, _curses_panel_panel_userptr__doc__}, + +static PyObject * +_curses_panel_panel_userptr_impl(PyCursesPanelObject *self); + +static PyObject * +_curses_panel_panel_userptr(PyCursesPanelObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _curses_panel_panel_userptr_impl(self); +} + +PyDoc_STRVAR(_curses_panel_bottom_panel__doc__, +"bottom_panel($module, /)\n" +"--\n" +"\n" +"Return the bottom panel in the panel stack."); + +#define _CURSES_PANEL_BOTTOM_PANEL_METHODDEF \ + {"bottom_panel", (PyCFunction)_curses_panel_bottom_panel, METH_NOARGS, _curses_panel_bottom_panel__doc__}, + +static PyObject * +_curses_panel_bottom_panel_impl(PyObject *module); + +static PyObject * +_curses_panel_bottom_panel(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_panel_bottom_panel_impl(module); +} + +PyDoc_STRVAR(_curses_panel_new_panel__doc__, +"new_panel($module, win, /)\n" +"--\n" +"\n" +"Return a panel object, associating it with the given window win."); + +#define _CURSES_PANEL_NEW_PANEL_METHODDEF \ + {"new_panel", (PyCFunction)_curses_panel_new_panel, METH_O, _curses_panel_new_panel__doc__}, + +static PyObject * +_curses_panel_new_panel_impl(PyObject *module, PyCursesWindowObject *win); + +static PyObject * +_curses_panel_new_panel(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + PyCursesWindowObject *win; + + if (!PyArg_Parse(arg, "O!:new_panel", &PyCursesWindow_Type, &win)) { + goto exit; + } + return_value = _curses_panel_new_panel_impl(module, win); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_panel_top_panel__doc__, +"top_panel($module, /)\n" +"--\n" +"\n" +"Return the top panel in the panel stack."); + +#define _CURSES_PANEL_TOP_PANEL_METHODDEF \ + {"top_panel", (PyCFunction)_curses_panel_top_panel, METH_NOARGS, _curses_panel_top_panel__doc__}, + +static PyObject * +_curses_panel_top_panel_impl(PyObject *module); + +static PyObject * +_curses_panel_top_panel(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_panel_top_panel_impl(module); +} + +PyDoc_STRVAR(_curses_panel_update_panels__doc__, +"update_panels($module, /)\n" +"--\n" +"\n" +"Updates the virtual screen after changes in the panel stack.\n" +"\n" +"This does not call curses.doupdate(), so you?ll have to do this yourself."); + +#define _CURSES_PANEL_UPDATE_PANELS_METHODDEF \ + {"update_panels", (PyCFunction)_curses_panel_update_panels, METH_NOARGS, _curses_panel_update_panels__doc__}, + +static PyObject * +_curses_panel_update_panels_impl(PyObject *module); + +static PyObject * +_curses_panel_update_panels(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_panel_update_panels_impl(module); +} +/*[clinic end generated code: output=96f627ca0b08b96d input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_cursesmodule.c.h b/Modules/clinic/_cursesmodule.c.h index 62ff1c8ae18a..b32797fc74ee 100644 --- a/Modules/clinic/_cursesmodule.c.h +++ b/Modules/clinic/_cursesmodule.c.h @@ -2,9 +2,9 @@ preserve [clinic start generated code]*/ -PyDoc_STRVAR(curses_window_addch__doc__, -"addch([y, x,] ch, [attr])\n" -"Paint character ch at (y, x) with attributes attr.\n" +PyDoc_STRVAR(_curses_window_addch__doc__, +"addch([y, x,] ch, [attr=_curses.A_NORMAL])\n" +"Paint the character.\n" "\n" " y\n" " Y-coordinate.\n" @@ -20,15 +20,16 @@ PyDoc_STRVAR(curses_window_addch__doc__, "By default, the character position and attributes are the\n" "current settings for the window object."); -#define CURSES_WINDOW_ADDCH_METHODDEF \ - {"addch", (PyCFunction)curses_window_addch, METH_VARARGS, curses_window_addch__doc__}, +#define _CURSES_WINDOW_ADDCH_METHODDEF \ + {"addch", (PyCFunction)_curses_window_addch, METH_VARARGS, _curses_window_addch__doc__}, static PyObject * -curses_window_addch_impl(PyCursesWindowObject *self, int group_left_1, int y, - int x, PyObject *ch, int group_right_1, long attr); +_curses_window_addch_impl(PyCursesWindowObject *self, int group_left_1, + int y, int x, PyObject *ch, int group_right_1, + long attr); static PyObject * -curses_window_addch(PyCursesWindowObject *self, PyObject *args) +_curses_window_addch(PyCursesWindowObject *self, PyObject *args) { PyObject *return_value = NULL; int group_left_1 = 0; @@ -36,7 +37,7 @@ curses_window_addch(PyCursesWindowObject *self, PyObject *args) int x = 0; PyObject *ch; int group_right_1 = 0; - long attr = 0; + long attr = A_NORMAL; switch (PyTuple_GET_SIZE(args)) { case 1: @@ -64,12 +65,3777 @@ curses_window_addch(PyCursesWindowObject *self, PyObject *args) group_left_1 = 1; break; default: - PyErr_SetString(PyExc_TypeError, "curses.window.addch requires 1 to 4 arguments"); + PyErr_SetString(PyExc_TypeError, "_curses.window.addch requires 1 to 4 arguments"); + goto exit; + } + return_value = _curses_window_addch_impl(self, group_left_1, y, x, ch, group_right_1, attr); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_addstr__doc__, +"addstr([y, x,] str, [attr])\n" +"Paint the string.\n" +"\n" +" y\n" +" Y-coordinate.\n" +" x\n" +" X-coordinate.\n" +" str\n" +" String to add.\n" +" attr\n" +" Attributes for characters.\n" +"\n" +"Paint the string str at (y, x) with attributes attr,\n" +"overwriting anything previously on the display.\n" +"By default, the character position and attributes are the\n" +"current settings for the window object."); + +#define _CURSES_WINDOW_ADDSTR_METHODDEF \ + {"addstr", (PyCFunction)_curses_window_addstr, METH_VARARGS, _curses_window_addstr__doc__}, + +static PyObject * +_curses_window_addstr_impl(PyCursesWindowObject *self, int group_left_1, + int y, int x, PyObject *str, int group_right_1, + long attr); + +static PyObject * +_curses_window_addstr(PyCursesWindowObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int group_left_1 = 0; + int y = 0; + int x = 0; + PyObject *str; + int group_right_1 = 0; + long attr = 0; + + switch (PyTuple_GET_SIZE(args)) { + case 1: + if (!PyArg_ParseTuple(args, "O:addstr", &str)) { + goto exit; + } + break; + case 2: + if (!PyArg_ParseTuple(args, "Ol:addstr", &str, &attr)) { + goto exit; + } + group_right_1 = 1; + break; + case 3: + if (!PyArg_ParseTuple(args, "iiO:addstr", &y, &x, &str)) { + goto exit; + } + group_left_1 = 1; + break; + case 4: + if (!PyArg_ParseTuple(args, "iiOl:addstr", &y, &x, &str, &attr)) { + goto exit; + } + group_right_1 = 1; + group_left_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.addstr requires 1 to 4 arguments"); + goto exit; + } + return_value = _curses_window_addstr_impl(self, group_left_1, y, x, str, group_right_1, attr); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_addnstr__doc__, +"addnstr([y, x,] str, n, [attr])\n" +"Paint at most n characters of the string.\n" +"\n" +" y\n" +" Y-coordinate.\n" +" x\n" +" X-coordinate.\n" +" str\n" +" String to add.\n" +" n\n" +" Maximal number of characters.\n" +" attr\n" +" Attributes for characters.\n" +"\n" +"Paint at most n characters of the string str at (y, x) with\n" +"attributes attr, overwriting anything previously on the display.\n" +"By default, the character position and attributes are the\n" +"current settings for the window object."); + +#define _CURSES_WINDOW_ADDNSTR_METHODDEF \ + {"addnstr", (PyCFunction)_curses_window_addnstr, METH_VARARGS, _curses_window_addnstr__doc__}, + +static PyObject * +_curses_window_addnstr_impl(PyCursesWindowObject *self, int group_left_1, + int y, int x, PyObject *str, int n, + int group_right_1, long attr); + +static PyObject * +_curses_window_addnstr(PyCursesWindowObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int group_left_1 = 0; + int y = 0; + int x = 0; + PyObject *str; + int n; + int group_right_1 = 0; + long attr = 0; + + switch (PyTuple_GET_SIZE(args)) { + case 2: + if (!PyArg_ParseTuple(args, "Oi:addnstr", &str, &n)) { + goto exit; + } + break; + case 3: + if (!PyArg_ParseTuple(args, "Oil:addnstr", &str, &n, &attr)) { + goto exit; + } + group_right_1 = 1; + break; + case 4: + if (!PyArg_ParseTuple(args, "iiOi:addnstr", &y, &x, &str, &n)) { + goto exit; + } + group_left_1 = 1; + break; + case 5: + if (!PyArg_ParseTuple(args, "iiOil:addnstr", &y, &x, &str, &n, &attr)) { + goto exit; + } + group_right_1 = 1; + group_left_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.addnstr requires 2 to 5 arguments"); + goto exit; + } + return_value = _curses_window_addnstr_impl(self, group_left_1, y, x, str, n, group_right_1, attr); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_bkgd__doc__, +"bkgd($self, ch, attr=_curses.A_NORMAL, /)\n" +"--\n" +"\n" +"Set the background property of the window.\n" +"\n" +" ch\n" +" Background character.\n" +" attr\n" +" Background attributes."); + +#define _CURSES_WINDOW_BKGD_METHODDEF \ + {"bkgd", (PyCFunction)_curses_window_bkgd, METH_FASTCALL, _curses_window_bkgd__doc__}, + +static PyObject * +_curses_window_bkgd_impl(PyCursesWindowObject *self, PyObject *ch, long attr); + +static PyObject * +_curses_window_bkgd(PyCursesWindowObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *ch; + long attr = A_NORMAL; + + if (!_PyArg_ParseStack(args, nargs, "O|l:bkgd", + &ch, &attr)) { + goto exit; + } + return_value = _curses_window_bkgd_impl(self, ch, attr); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_attroff__doc__, +"attroff($self, attr, /)\n" +"--\n" +"\n" +"Remove attribute attr from the \"background\" set."); + +#define _CURSES_WINDOW_ATTROFF_METHODDEF \ + {"attroff", (PyCFunction)_curses_window_attroff, METH_O, _curses_window_attroff__doc__}, + +static PyObject * +_curses_window_attroff_impl(PyCursesWindowObject *self, long attr); + +static PyObject * +_curses_window_attroff(PyCursesWindowObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + long attr; + + if (!PyArg_Parse(arg, "l:attroff", &attr)) { + goto exit; + } + return_value = _curses_window_attroff_impl(self, attr); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_attron__doc__, +"attron($self, attr, /)\n" +"--\n" +"\n" +"Add attribute attr from the \"background\" set."); + +#define _CURSES_WINDOW_ATTRON_METHODDEF \ + {"attron", (PyCFunction)_curses_window_attron, METH_O, _curses_window_attron__doc__}, + +static PyObject * +_curses_window_attron_impl(PyCursesWindowObject *self, long attr); + +static PyObject * +_curses_window_attron(PyCursesWindowObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + long attr; + + if (!PyArg_Parse(arg, "l:attron", &attr)) { + goto exit; + } + return_value = _curses_window_attron_impl(self, attr); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_attrset__doc__, +"attrset($self, attr, /)\n" +"--\n" +"\n" +"Set the \"background\" set of attributes."); + +#define _CURSES_WINDOW_ATTRSET_METHODDEF \ + {"attrset", (PyCFunction)_curses_window_attrset, METH_O, _curses_window_attrset__doc__}, + +static PyObject * +_curses_window_attrset_impl(PyCursesWindowObject *self, long attr); + +static PyObject * +_curses_window_attrset(PyCursesWindowObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + long attr; + + if (!PyArg_Parse(arg, "l:attrset", &attr)) { + goto exit; + } + return_value = _curses_window_attrset_impl(self, attr); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_bkgdset__doc__, +"bkgdset($self, ch, attr=_curses.A_NORMAL, /)\n" +"--\n" +"\n" +"Set the window\'s background.\n" +"\n" +" ch\n" +" Background character.\n" +" attr\n" +" Background attributes."); + +#define _CURSES_WINDOW_BKGDSET_METHODDEF \ + {"bkgdset", (PyCFunction)_curses_window_bkgdset, METH_FASTCALL, _curses_window_bkgdset__doc__}, + +static PyObject * +_curses_window_bkgdset_impl(PyCursesWindowObject *self, PyObject *ch, + long attr); + +static PyObject * +_curses_window_bkgdset(PyCursesWindowObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *ch; + long attr = A_NORMAL; + + if (!_PyArg_ParseStack(args, nargs, "O|l:bkgdset", + &ch, &attr)) { + goto exit; + } + return_value = _curses_window_bkgdset_impl(self, ch, attr); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_border__doc__, +"border($self, ls=_curses.ACS_VLINE, rs=_curses.ACS_VLINE,\n" +" ts=_curses.ACS_HLINE, bs=_curses.ACS_HLINE,\n" +" tl=_curses.ACS_ULCORNER, tr=_curses.ACS_URCORNER,\n" +" bl=_curses.ACS_LLCORNER, br=_curses.ACS_LRCORNER, /)\n" +"--\n" +"\n" +"Draw a border around the edges of the window.\n" +"\n" +" ls\n" +" Left side.\n" +" rs\n" +" Right side.\n" +" ts\n" +" Top side.\n" +" bs\n" +" Bottom side.\n" +" tl\n" +" Upper-left corner.\n" +" tr\n" +" Upper-right corner.\n" +" bl\n" +" Bottom-left corner.\n" +" br\n" +" Bottom-right corner.\n" +"\n" +"Each parameter specifies the character to use for a specific part of the\n" +"border. The characters can be specified as integers or as one-character\n" +"strings. A 0 value for any parameter will cause the default character to be\n" +"used for that parameter."); + +#define _CURSES_WINDOW_BORDER_METHODDEF \ + {"border", (PyCFunction)_curses_window_border, METH_FASTCALL, _curses_window_border__doc__}, + +static PyObject * +_curses_window_border_impl(PyCursesWindowObject *self, PyObject *ls, + PyObject *rs, PyObject *ts, PyObject *bs, + PyObject *tl, PyObject *tr, PyObject *bl, + PyObject *br); + +static PyObject * +_curses_window_border(PyCursesWindowObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *ls = NULL; + PyObject *rs = NULL; + PyObject *ts = NULL; + PyObject *bs = NULL; + PyObject *tl = NULL; + PyObject *tr = NULL; + PyObject *bl = NULL; + PyObject *br = NULL; + + if (!_PyArg_UnpackStack(args, nargs, "border", + 0, 8, + &ls, &rs, &ts, &bs, &tl, &tr, &bl, &br)) { + goto exit; + } + return_value = _curses_window_border_impl(self, ls, rs, ts, bs, tl, tr, bl, br); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_box__doc__, +"box([verch=0, horch=0])\n" +"Draw a border around the edges of the window.\n" +"\n" +" verch\n" +" Left and right side.\n" +" horch\n" +" Top and bottom side.\n" +"\n" +"Similar to border(), but both ls and rs are verch and both ts and bs are\n" +"horch. The default corner characters are always used by this function."); + +#define _CURSES_WINDOW_BOX_METHODDEF \ + {"box", (PyCFunction)_curses_window_box, METH_VARARGS, _curses_window_box__doc__}, + +static PyObject * +_curses_window_box_impl(PyCursesWindowObject *self, int group_right_1, + PyObject *verch, PyObject *horch); + +static PyObject * +_curses_window_box(PyCursesWindowObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int group_right_1 = 0; + PyObject *verch = _PyLong_Zero; + PyObject *horch = _PyLong_Zero; + + switch (PyTuple_GET_SIZE(args)) { + case 0: + break; + case 2: + if (!PyArg_ParseTuple(args, "OO:box", &verch, &horch)) { + goto exit; + } + group_right_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.box requires 0 to 2 arguments"); goto exit; } - return_value = curses_window_addch_impl(self, group_left_1, y, x, ch, group_right_1, attr); + return_value = _curses_window_box_impl(self, group_right_1, verch, horch); exit: return return_value; } -/*[clinic end generated code: output=13ffc5f8d79cbfbf input=a9049054013a1b77]*/ + +PyDoc_STRVAR(_curses_window_delch__doc__, +"delch([y, x])\n" +"Delete any character at (y, x).\n" +"\n" +" y\n" +" Y-coordinate.\n" +" x\n" +" X-coordinate."); + +#define _CURSES_WINDOW_DELCH_METHODDEF \ + {"delch", (PyCFunction)_curses_window_delch, METH_VARARGS, _curses_window_delch__doc__}, + +static PyObject * +_curses_window_delch_impl(PyCursesWindowObject *self, int group_right_1, + int y, int x); + +static PyObject * +_curses_window_delch(PyCursesWindowObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int group_right_1 = 0; + int y = 0; + int x = 0; + + switch (PyTuple_GET_SIZE(args)) { + case 0: + break; + case 2: + if (!PyArg_ParseTuple(args, "ii:delch", &y, &x)) { + goto exit; + } + group_right_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.delch requires 0 to 2 arguments"); + goto exit; + } + return_value = _curses_window_delch_impl(self, group_right_1, y, x); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_derwin__doc__, +"derwin([nlines=0, ncols=0,] begin_y, begin_x)\n" +"Create a sub-window (window-relative coordinates).\n" +"\n" +" nlines\n" +" Height.\n" +" ncols\n" +" Width.\n" +" begin_y\n" +" Top side y-coordinate.\n" +" begin_x\n" +" Left side x-coordinate.\n" +"\n" +"derwin() is the same as calling subwin(), except that begin_y and begin_x\n" +"are relative to the origin of the window, rather than relative to the entire\n" +"screen."); + +#define _CURSES_WINDOW_DERWIN_METHODDEF \ + {"derwin", (PyCFunction)_curses_window_derwin, METH_VARARGS, _curses_window_derwin__doc__}, + +static PyObject * +_curses_window_derwin_impl(PyCursesWindowObject *self, int group_left_1, + int nlines, int ncols, int begin_y, int begin_x); + +static PyObject * +_curses_window_derwin(PyCursesWindowObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int group_left_1 = 0; + int nlines = 0; + int ncols = 0; + int begin_y; + int begin_x; + + switch (PyTuple_GET_SIZE(args)) { + case 2: + if (!PyArg_ParseTuple(args, "ii:derwin", &begin_y, &begin_x)) { + goto exit; + } + break; + case 4: + if (!PyArg_ParseTuple(args, "iiii:derwin", &nlines, &ncols, &begin_y, &begin_x)) { + goto exit; + } + group_left_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.derwin requires 2 to 4 arguments"); + goto exit; + } + return_value = _curses_window_derwin_impl(self, group_left_1, nlines, ncols, begin_y, begin_x); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_echochar__doc__, +"echochar($self, ch, attr=_curses.A_NORMAL, /)\n" +"--\n" +"\n" +"Add character ch with attribute attr, and refresh.\n" +"\n" +" ch\n" +" Character to add.\n" +" attr\n" +" Attributes for the character."); + +#define _CURSES_WINDOW_ECHOCHAR_METHODDEF \ + {"echochar", (PyCFunction)_curses_window_echochar, METH_FASTCALL, _curses_window_echochar__doc__}, + +static PyObject * +_curses_window_echochar_impl(PyCursesWindowObject *self, PyObject *ch, + long attr); + +static PyObject * +_curses_window_echochar(PyCursesWindowObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *ch; + long attr = A_NORMAL; + + if (!_PyArg_ParseStack(args, nargs, "O|l:echochar", + &ch, &attr)) { + goto exit; + } + return_value = _curses_window_echochar_impl(self, ch, attr); + +exit: + return return_value; +} + +#if defined(NCURSES_MOUSE_VERSION) + +PyDoc_STRVAR(_curses_window_enclose__doc__, +"enclose($self, y, x, /)\n" +"--\n" +"\n" +"Return True if the screen-relative coordinates are enclosed by the window.\n" +"\n" +" y\n" +" Y-coordinate.\n" +" x\n" +" X-coordinate."); + +#define _CURSES_WINDOW_ENCLOSE_METHODDEF \ + {"enclose", (PyCFunction)_curses_window_enclose, METH_FASTCALL, _curses_window_enclose__doc__}, + +static long +_curses_window_enclose_impl(PyCursesWindowObject *self, int y, int x); + +static PyObject * +_curses_window_enclose(PyCursesWindowObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int y; + int x; + long _return_value; + + if (!_PyArg_ParseStack(args, nargs, "ii:enclose", + &y, &x)) { + goto exit; + } + _return_value = _curses_window_enclose_impl(self, y, x); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromLong(_return_value); + +exit: + return return_value; +} + +#endif /* defined(NCURSES_MOUSE_VERSION) */ + +PyDoc_STRVAR(_curses_window_getbkgd__doc__, +"getbkgd($self, /)\n" +"--\n" +"\n" +"Return the window\'s current background character/attribute pair."); + +#define _CURSES_WINDOW_GETBKGD_METHODDEF \ + {"getbkgd", (PyCFunction)_curses_window_getbkgd, METH_NOARGS, _curses_window_getbkgd__doc__}, + +static long +_curses_window_getbkgd_impl(PyCursesWindowObject *self); + +static PyObject * +_curses_window_getbkgd(PyCursesWindowObject *self, PyObject *Py_UNUSED(ignored)) +{ + PyObject *return_value = NULL; + long _return_value; + + _return_value = _curses_window_getbkgd_impl(self); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromLong(_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_getch__doc__, +"getch([y, x])\n" +"Get a character code from terminal keyboard.\n" +"\n" +" y\n" +" Y-coordinate.\n" +" x\n" +" X-coordinate.\n" +"\n" +"The integer returned does not have to be in ASCII range: function keys,\n" +"keypad keys and so on return numbers higher than 256. In no-delay mode, -1\n" +"is returned if there is no input, else getch() waits until a key is pressed."); + +#define _CURSES_WINDOW_GETCH_METHODDEF \ + {"getch", (PyCFunction)_curses_window_getch, METH_VARARGS, _curses_window_getch__doc__}, + +static int +_curses_window_getch_impl(PyCursesWindowObject *self, int group_right_1, + int y, int x); + +static PyObject * +_curses_window_getch(PyCursesWindowObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int group_right_1 = 0; + int y = 0; + int x = 0; + int _return_value; + + switch (PyTuple_GET_SIZE(args)) { + case 0: + break; + case 2: + if (!PyArg_ParseTuple(args, "ii:getch", &y, &x)) { + goto exit; + } + group_right_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.getch requires 0 to 2 arguments"); + goto exit; + } + _return_value = _curses_window_getch_impl(self, group_right_1, y, x); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromLong((long)_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_getkey__doc__, +"getkey([y, x])\n" +"Get a character (string) from terminal keyboard.\n" +"\n" +" y\n" +" Y-coordinate.\n" +" x\n" +" X-coordinate.\n" +"\n" +"Returning a string instead of an integer, as getch() does. Function keys,\n" +"keypad keys and other special keys return a multibyte string containing the\n" +"key name. In no-delay mode, an exception is raised if there is no input."); + +#define _CURSES_WINDOW_GETKEY_METHODDEF \ + {"getkey", (PyCFunction)_curses_window_getkey, METH_VARARGS, _curses_window_getkey__doc__}, + +static PyObject * +_curses_window_getkey_impl(PyCursesWindowObject *self, int group_right_1, + int y, int x); + +static PyObject * +_curses_window_getkey(PyCursesWindowObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int group_right_1 = 0; + int y = 0; + int x = 0; + + switch (PyTuple_GET_SIZE(args)) { + case 0: + break; + case 2: + if (!PyArg_ParseTuple(args, "ii:getkey", &y, &x)) { + goto exit; + } + group_right_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.getkey requires 0 to 2 arguments"); + goto exit; + } + return_value = _curses_window_getkey_impl(self, group_right_1, y, x); + +exit: + return return_value; +} + +#if defined(HAVE_NCURSESW) + +PyDoc_STRVAR(_curses_window_get_wch__doc__, +"get_wch([y, x])\n" +"Get a wide character from terminal keyboard.\n" +"\n" +" y\n" +" Y-coordinate.\n" +" x\n" +" X-coordinate.\n" +"\n" +"Return a character for most keys, or an integer for function keys,\n" +"keypad keys, and other special keys."); + +#define _CURSES_WINDOW_GET_WCH_METHODDEF \ + {"get_wch", (PyCFunction)_curses_window_get_wch, METH_VARARGS, _curses_window_get_wch__doc__}, + +static PyObject * +_curses_window_get_wch_impl(PyCursesWindowObject *self, int group_right_1, + int y, int x); + +static PyObject * +_curses_window_get_wch(PyCursesWindowObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int group_right_1 = 0; + int y = 0; + int x = 0; + + switch (PyTuple_GET_SIZE(args)) { + case 0: + break; + case 2: + if (!PyArg_ParseTuple(args, "ii:get_wch", &y, &x)) { + goto exit; + } + group_right_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.get_wch requires 0 to 2 arguments"); + goto exit; + } + return_value = _curses_window_get_wch_impl(self, group_right_1, y, x); + +exit: + return return_value; +} + +#endif /* defined(HAVE_NCURSESW) */ + +PyDoc_STRVAR(_curses_window_hline__doc__, +"hline([y, x,] ch, n, [attr=_curses.A_NORMAL])\n" +"Display a horizontal line.\n" +"\n" +" y\n" +" Starting Y-coordinate.\n" +" x\n" +" Starting X-coordinate.\n" +" ch\n" +" Character to draw.\n" +" n\n" +" Line length.\n" +" attr\n" +" Attributes for the characters."); + +#define _CURSES_WINDOW_HLINE_METHODDEF \ + {"hline", (PyCFunction)_curses_window_hline, METH_VARARGS, _curses_window_hline__doc__}, + +static PyObject * +_curses_window_hline_impl(PyCursesWindowObject *self, int group_left_1, + int y, int x, PyObject *ch, int n, + int group_right_1, long attr); + +static PyObject * +_curses_window_hline(PyCursesWindowObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int group_left_1 = 0; + int y = 0; + int x = 0; + PyObject *ch; + int n; + int group_right_1 = 0; + long attr = A_NORMAL; + + switch (PyTuple_GET_SIZE(args)) { + case 2: + if (!PyArg_ParseTuple(args, "Oi:hline", &ch, &n)) { + goto exit; + } + break; + case 3: + if (!PyArg_ParseTuple(args, "Oil:hline", &ch, &n, &attr)) { + goto exit; + } + group_right_1 = 1; + break; + case 4: + if (!PyArg_ParseTuple(args, "iiOi:hline", &y, &x, &ch, &n)) { + goto exit; + } + group_left_1 = 1; + break; + case 5: + if (!PyArg_ParseTuple(args, "iiOil:hline", &y, &x, &ch, &n, &attr)) { + goto exit; + } + group_right_1 = 1; + group_left_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.hline requires 2 to 5 arguments"); + goto exit; + } + return_value = _curses_window_hline_impl(self, group_left_1, y, x, ch, n, group_right_1, attr); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_insch__doc__, +"insch([y, x,] ch, [attr=_curses.A_NORMAL])\n" +"Insert a character before the current or specified position.\n" +"\n" +" y\n" +" Y-coordinate.\n" +" x\n" +" X-coordinate.\n" +" ch\n" +" Character to insert.\n" +" attr\n" +" Attributes for the character.\n" +"\n" +"All characters to the right of the cursor are shifted one position right, with\n" +"the rightmost characters on the line being lost."); + +#define _CURSES_WINDOW_INSCH_METHODDEF \ + {"insch", (PyCFunction)_curses_window_insch, METH_VARARGS, _curses_window_insch__doc__}, + +static PyObject * +_curses_window_insch_impl(PyCursesWindowObject *self, int group_left_1, + int y, int x, PyObject *ch, int group_right_1, + long attr); + +static PyObject * +_curses_window_insch(PyCursesWindowObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int group_left_1 = 0; + int y = 0; + int x = 0; + PyObject *ch; + int group_right_1 = 0; + long attr = A_NORMAL; + + switch (PyTuple_GET_SIZE(args)) { + case 1: + if (!PyArg_ParseTuple(args, "O:insch", &ch)) { + goto exit; + } + break; + case 2: + if (!PyArg_ParseTuple(args, "Ol:insch", &ch, &attr)) { + goto exit; + } + group_right_1 = 1; + break; + case 3: + if (!PyArg_ParseTuple(args, "iiO:insch", &y, &x, &ch)) { + goto exit; + } + group_left_1 = 1; + break; + case 4: + if (!PyArg_ParseTuple(args, "iiOl:insch", &y, &x, &ch, &attr)) { + goto exit; + } + group_right_1 = 1; + group_left_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.insch requires 1 to 4 arguments"); + goto exit; + } + return_value = _curses_window_insch_impl(self, group_left_1, y, x, ch, group_right_1, attr); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_inch__doc__, +"inch([y, x])\n" +"Return the character at the given position in the window.\n" +"\n" +" y\n" +" Y-coordinate.\n" +" x\n" +" X-coordinate.\n" +"\n" +"The bottom 8 bits are the character proper, and upper bits are the attributes."); + +#define _CURSES_WINDOW_INCH_METHODDEF \ + {"inch", (PyCFunction)_curses_window_inch, METH_VARARGS, _curses_window_inch__doc__}, + +static unsigned long +_curses_window_inch_impl(PyCursesWindowObject *self, int group_right_1, + int y, int x); + +static PyObject * +_curses_window_inch(PyCursesWindowObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int group_right_1 = 0; + int y = 0; + int x = 0; + unsigned long _return_value; + + switch (PyTuple_GET_SIZE(args)) { + case 0: + break; + case 2: + if (!PyArg_ParseTuple(args, "ii:inch", &y, &x)) { + goto exit; + } + group_right_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.inch requires 0 to 2 arguments"); + goto exit; + } + _return_value = _curses_window_inch_impl(self, group_right_1, y, x); + if ((_return_value == (unsigned long)-1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromUnsignedLong(_return_value); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_insstr__doc__, +"insstr([y, x,] str, [attr])\n" +"Insert the string before the current or specified position.\n" +"\n" +" y\n" +" Y-coordinate.\n" +" x\n" +" X-coordinate.\n" +" str\n" +" String to insert.\n" +" attr\n" +" Attributes for characters.\n" +"\n" +"Insert a character string (as many characters as will fit on the line)\n" +"before the character under the cursor. All characters to the right of\n" +"the cursor are shifted right, with the rightmost characters on the line\n" +"being lost. The cursor position does not change (after moving to y, x,\n" +"if specified)."); + +#define _CURSES_WINDOW_INSSTR_METHODDEF \ + {"insstr", (PyCFunction)_curses_window_insstr, METH_VARARGS, _curses_window_insstr__doc__}, + +static PyObject * +_curses_window_insstr_impl(PyCursesWindowObject *self, int group_left_1, + int y, int x, PyObject *str, int group_right_1, + long attr); + +static PyObject * +_curses_window_insstr(PyCursesWindowObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int group_left_1 = 0; + int y = 0; + int x = 0; + PyObject *str; + int group_right_1 = 0; + long attr = 0; + + switch (PyTuple_GET_SIZE(args)) { + case 1: + if (!PyArg_ParseTuple(args, "O:insstr", &str)) { + goto exit; + } + break; + case 2: + if (!PyArg_ParseTuple(args, "Ol:insstr", &str, &attr)) { + goto exit; + } + group_right_1 = 1; + break; + case 3: + if (!PyArg_ParseTuple(args, "iiO:insstr", &y, &x, &str)) { + goto exit; + } + group_left_1 = 1; + break; + case 4: + if (!PyArg_ParseTuple(args, "iiOl:insstr", &y, &x, &str, &attr)) { + goto exit; + } + group_right_1 = 1; + group_left_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.insstr requires 1 to 4 arguments"); + goto exit; + } + return_value = _curses_window_insstr_impl(self, group_left_1, y, x, str, group_right_1, attr); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_insnstr__doc__, +"insnstr([y, x,] str, n, [attr])\n" +"Insert at most n characters of the string.\n" +"\n" +" y\n" +" Y-coordinate.\n" +" x\n" +" X-coordinate.\n" +" str\n" +" String to insert.\n" +" n\n" +" Maximal number of characters.\n" +" attr\n" +" Attributes for characters.\n" +"\n" +"Insert a character string (as many characters as will fit on the line)\n" +"before the character under the cursor, up to n characters. If n is zero\n" +"or negative, the entire string is inserted. All characters to the right\n" +"of the cursor are shifted right, with the rightmost characters on the line\n" +"being lost. The cursor position does not change (after moving to y, x, if\n" +"specified)."); + +#define _CURSES_WINDOW_INSNSTR_METHODDEF \ + {"insnstr", (PyCFunction)_curses_window_insnstr, METH_VARARGS, _curses_window_insnstr__doc__}, + +static PyObject * +_curses_window_insnstr_impl(PyCursesWindowObject *self, int group_left_1, + int y, int x, PyObject *str, int n, + int group_right_1, long attr); + +static PyObject * +_curses_window_insnstr(PyCursesWindowObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int group_left_1 = 0; + int y = 0; + int x = 0; + PyObject *str; + int n; + int group_right_1 = 0; + long attr = 0; + + switch (PyTuple_GET_SIZE(args)) { + case 2: + if (!PyArg_ParseTuple(args, "Oi:insnstr", &str, &n)) { + goto exit; + } + break; + case 3: + if (!PyArg_ParseTuple(args, "Oil:insnstr", &str, &n, &attr)) { + goto exit; + } + group_right_1 = 1; + break; + case 4: + if (!PyArg_ParseTuple(args, "iiOi:insnstr", &y, &x, &str, &n)) { + goto exit; + } + group_left_1 = 1; + break; + case 5: + if (!PyArg_ParseTuple(args, "iiOil:insnstr", &y, &x, &str, &n, &attr)) { + goto exit; + } + group_right_1 = 1; + group_left_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.insnstr requires 2 to 5 arguments"); + goto exit; + } + return_value = _curses_window_insnstr_impl(self, group_left_1, y, x, str, n, group_right_1, attr); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_is_linetouched__doc__, +"is_linetouched($self, line, /)\n" +"--\n" +"\n" +"Return True if the specified line was modified, otherwise return False.\n" +"\n" +" line\n" +" Line number.\n" +"\n" +"Raise a curses.error exception if line is not valid for the given window."); + +#define _CURSES_WINDOW_IS_LINETOUCHED_METHODDEF \ + {"is_linetouched", (PyCFunction)_curses_window_is_linetouched, METH_O, _curses_window_is_linetouched__doc__}, + +static PyObject * +_curses_window_is_linetouched_impl(PyCursesWindowObject *self, int line); + +static PyObject * +_curses_window_is_linetouched(PyCursesWindowObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + int line; + + if (!PyArg_Parse(arg, "i:is_linetouched", &line)) { + goto exit; + } + return_value = _curses_window_is_linetouched_impl(self, line); + +exit: + return return_value; +} + +#if defined(py_is_pad) + +PyDoc_STRVAR(_curses_window_noutrefresh__doc__, +"noutrefresh([pminrow, pmincol, sminrow, smincol, smaxrow, smaxcol])\n" +"Mark for refresh but wait.\n" +"\n" +"This function updates the data structure representing the desired state of the\n" +"window, but does not force an update of the physical screen. To accomplish\n" +"that, call doupdate()."); + +#define _CURSES_WINDOW_NOUTREFRESH_METHODDEF \ + {"noutrefresh", (PyCFunction)_curses_window_noutrefresh, METH_VARARGS, _curses_window_noutrefresh__doc__}, + +static PyObject * +_curses_window_noutrefresh_impl(PyCursesWindowObject *self, + int group_right_1, int pminrow, int pmincol, + int sminrow, int smincol, int smaxrow, + int smaxcol); + +static PyObject * +_curses_window_noutrefresh(PyCursesWindowObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int group_right_1 = 0; + int pminrow = 0; + int pmincol = 0; + int sminrow = 0; + int smincol = 0; + int smaxrow = 0; + int smaxcol = 0; + + switch (PyTuple_GET_SIZE(args)) { + case 0: + break; + case 6: + if (!PyArg_ParseTuple(args, "iiiiii:noutrefresh", &pminrow, &pmincol, &sminrow, &smincol, &smaxrow, &smaxcol)) { + goto exit; + } + group_right_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.noutrefresh requires 0 to 6 arguments"); + goto exit; + } + return_value = _curses_window_noutrefresh_impl(self, group_right_1, pminrow, pmincol, sminrow, smincol, smaxrow, smaxcol); + +exit: + return return_value; +} + +#endif /* defined(py_is_pad) */ + +#if !defined(py_is_pad) + +PyDoc_STRVAR(_curses_window_noutrefresh__doc__, +"noutrefresh($self, /)\n" +"--\n" +"\n" +"Mark for refresh but wait.\n" +"\n" +"This function updates the data structure representing the desired state of the\n" +"window, but does not force an update of the physical screen. To accomplish\n" +"that, call doupdate()."); + +#define _CURSES_WINDOW_NOUTREFRESH_METHODDEF \ + {"noutrefresh", (PyCFunction)_curses_window_noutrefresh, METH_NOARGS, _curses_window_noutrefresh__doc__}, + +static PyObject * +_curses_window_noutrefresh_impl(PyCursesWindowObject *self); + +static PyObject * +_curses_window_noutrefresh(PyCursesWindowObject *self, PyObject *Py_UNUSED(ignored)) +{ + return _curses_window_noutrefresh_impl(self); +} + +#endif /* !defined(py_is_pad) */ + +PyDoc_STRVAR(_curses_window_overlay__doc__, +"overlay(destwin, [sminrow, smincol, dminrow, dmincol, dmaxrow, dmaxcol])\n" +"Overlay the window on top of destwin.\n" +"\n" +"The windows need not be the same size, only the overlapping region is copied.\n" +"This copy is non-destructive, which means that the current background\n" +"character does not overwrite the old contents of destwin.\n" +"\n" +"To get fine-grained control over the copied region, the second form of\n" +"overlay() can be used. sminrow and smincol are the upper-left coordinates\n" +"of the source window, and the other variables mark a rectangle in the\n" +"destination window."); + +#define _CURSES_WINDOW_OVERLAY_METHODDEF \ + {"overlay", (PyCFunction)_curses_window_overlay, METH_VARARGS, _curses_window_overlay__doc__}, + +static PyObject * +_curses_window_overlay_impl(PyCursesWindowObject *self, + PyCursesWindowObject *destwin, int group_right_1, + int sminrow, int smincol, int dminrow, + int dmincol, int dmaxrow, int dmaxcol); + +static PyObject * +_curses_window_overlay(PyCursesWindowObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + PyCursesWindowObject *destwin; + int group_right_1 = 0; + int sminrow = 0; + int smincol = 0; + int dminrow = 0; + int dmincol = 0; + int dmaxrow = 0; + int dmaxcol = 0; + + switch (PyTuple_GET_SIZE(args)) { + case 1: + if (!PyArg_ParseTuple(args, "O!:overlay", &PyCursesWindow_Type, &destwin)) { + goto exit; + } + break; + case 7: + if (!PyArg_ParseTuple(args, "O!iiiiii:overlay", &PyCursesWindow_Type, &destwin, &sminrow, &smincol, &dminrow, &dmincol, &dmaxrow, &dmaxcol)) { + goto exit; + } + group_right_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.overlay requires 1 to 7 arguments"); + goto exit; + } + return_value = _curses_window_overlay_impl(self, destwin, group_right_1, sminrow, smincol, dminrow, dmincol, dmaxrow, dmaxcol); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_overwrite__doc__, +"overwrite(destwin, [sminrow, smincol, dminrow, dmincol, dmaxrow,\n" +" dmaxcol])\n" +"Overwrite the window on top of destwin.\n" +"\n" +"The windows need not be the same size, in which case only the overlapping\n" +"region is copied. This copy is destructive, which means that the current\n" +"background character overwrites the old contents of destwin.\n" +"\n" +"To get fine-grained control over the copied region, the second form of\n" +"overwrite() can be used. sminrow and smincol are the upper-left coordinates\n" +"of the source window, the other variables mark a rectangle in the destination\n" +"window."); + +#define _CURSES_WINDOW_OVERWRITE_METHODDEF \ + {"overwrite", (PyCFunction)_curses_window_overwrite, METH_VARARGS, _curses_window_overwrite__doc__}, + +static PyObject * +_curses_window_overwrite_impl(PyCursesWindowObject *self, + PyCursesWindowObject *destwin, + int group_right_1, int sminrow, int smincol, + int dminrow, int dmincol, int dmaxrow, + int dmaxcol); + +static PyObject * +_curses_window_overwrite(PyCursesWindowObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + PyCursesWindowObject *destwin; + int group_right_1 = 0; + int sminrow = 0; + int smincol = 0; + int dminrow = 0; + int dmincol = 0; + int dmaxrow = 0; + int dmaxcol = 0; + + switch (PyTuple_GET_SIZE(args)) { + case 1: + if (!PyArg_ParseTuple(args, "O!:overwrite", &PyCursesWindow_Type, &destwin)) { + goto exit; + } + break; + case 7: + if (!PyArg_ParseTuple(args, "O!iiiiii:overwrite", &PyCursesWindow_Type, &destwin, &sminrow, &smincol, &dminrow, &dmincol, &dmaxrow, &dmaxcol)) { + goto exit; + } + group_right_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.overwrite requires 1 to 7 arguments"); + goto exit; + } + return_value = _curses_window_overwrite_impl(self, destwin, group_right_1, sminrow, smincol, dminrow, dmincol, dmaxrow, dmaxcol); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_putwin__doc__, +"putwin($self, file, /)\n" +"--\n" +"\n" +"Write all data associated with the window into the provided file object.\n" +"\n" +"This information can be later retrieved using the getwin() function."); + +#define _CURSES_WINDOW_PUTWIN_METHODDEF \ + {"putwin", (PyCFunction)_curses_window_putwin, METH_O, _curses_window_putwin__doc__}, + +PyDoc_STRVAR(_curses_window_redrawln__doc__, +"redrawln($self, beg, num, /)\n" +"--\n" +"\n" +"Mark the specified lines corrupted.\n" +"\n" +" beg\n" +" Starting line number.\n" +" num\n" +" The number of lines.\n" +"\n" +"They should be completely redrawn on the next refresh() call."); + +#define _CURSES_WINDOW_REDRAWLN_METHODDEF \ + {"redrawln", (PyCFunction)_curses_window_redrawln, METH_FASTCALL, _curses_window_redrawln__doc__}, + +static PyObject * +_curses_window_redrawln_impl(PyCursesWindowObject *self, int beg, int num); + +static PyObject * +_curses_window_redrawln(PyCursesWindowObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int beg; + int num; + + if (!_PyArg_ParseStack(args, nargs, "ii:redrawln", + &beg, &num)) { + goto exit; + } + return_value = _curses_window_redrawln_impl(self, beg, num); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_refresh__doc__, +"refresh([pminrow, pmincol, sminrow, smincol, smaxrow, smaxcol])\n" +"Update the display immediately.\n" +"\n" +"Synchronize actual screen with previous drawing/deleting methods.\n" +"The 6 optional arguments can only be specified when the window is a pad\n" +"created with newpad(). The additional parameters are needed to indicate\n" +"what part of the pad and screen are involved. pminrow and pmincol specify\n" +"the upper left-hand corner of the rectangle to be displayed in the pad.\n" +"sminrow, smincol, smaxrow, and smaxcol specify the edges of the rectangle to\n" +"be displayed on the screen. The lower right-hand corner of the rectangle to\n" +"be displayed in the pad is calculated from the screen coordinates, since the\n" +"rectangles must be the same size. Both rectangles must be entirely contained\n" +"within their respective structures. Negative values of pminrow, pmincol,\n" +"sminrow, or smincol are treated as if they were zero."); + +#define _CURSES_WINDOW_REFRESH_METHODDEF \ + {"refresh", (PyCFunction)_curses_window_refresh, METH_VARARGS, _curses_window_refresh__doc__}, + +static PyObject * +_curses_window_refresh_impl(PyCursesWindowObject *self, int group_right_1, + int pminrow, int pmincol, int sminrow, + int smincol, int smaxrow, int smaxcol); + +static PyObject * +_curses_window_refresh(PyCursesWindowObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int group_right_1 = 0; + int pminrow = 0; + int pmincol = 0; + int sminrow = 0; + int smincol = 0; + int smaxrow = 0; + int smaxcol = 0; + + switch (PyTuple_GET_SIZE(args)) { + case 0: + break; + case 6: + if (!PyArg_ParseTuple(args, "iiiiii:refresh", &pminrow, &pmincol, &sminrow, &smincol, &smaxrow, &smaxcol)) { + goto exit; + } + group_right_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.refresh requires 0 to 6 arguments"); + goto exit; + } + return_value = _curses_window_refresh_impl(self, group_right_1, pminrow, pmincol, sminrow, smincol, smaxrow, smaxcol); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_setscrreg__doc__, +"setscrreg($self, top, bottom, /)\n" +"--\n" +"\n" +"Define a software scrolling region.\n" +"\n" +" top\n" +" First line number.\n" +" bottom\n" +" Last line number.\n" +"\n" +"All scrolling actions will take place in this region."); + +#define _CURSES_WINDOW_SETSCRREG_METHODDEF \ + {"setscrreg", (PyCFunction)_curses_window_setscrreg, METH_FASTCALL, _curses_window_setscrreg__doc__}, + +static PyObject * +_curses_window_setscrreg_impl(PyCursesWindowObject *self, int top, + int bottom); + +static PyObject * +_curses_window_setscrreg(PyCursesWindowObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int top; + int bottom; + + if (!_PyArg_ParseStack(args, nargs, "ii:setscrreg", + &top, &bottom)) { + goto exit; + } + return_value = _curses_window_setscrreg_impl(self, top, bottom); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_subwin__doc__, +"subwin([nlines=0, ncols=0,] begin_y, begin_x)\n" +"Create a sub-window (screen-relative coordinates).\n" +"\n" +" nlines\n" +" Height.\n" +" ncols\n" +" Width.\n" +" begin_y\n" +" Top side y-coordinate.\n" +" begin_x\n" +" Left side x-coordinate.\n" +"\n" +"By default, the sub-window will extend from the specified position to the\n" +"lower right corner of the window."); + +#define _CURSES_WINDOW_SUBWIN_METHODDEF \ + {"subwin", (PyCFunction)_curses_window_subwin, METH_VARARGS, _curses_window_subwin__doc__}, + +static PyObject * +_curses_window_subwin_impl(PyCursesWindowObject *self, int group_left_1, + int nlines, int ncols, int begin_y, int begin_x); + +static PyObject * +_curses_window_subwin(PyCursesWindowObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int group_left_1 = 0; + int nlines = 0; + int ncols = 0; + int begin_y; + int begin_x; + + switch (PyTuple_GET_SIZE(args)) { + case 2: + if (!PyArg_ParseTuple(args, "ii:subwin", &begin_y, &begin_x)) { + goto exit; + } + break; + case 4: + if (!PyArg_ParseTuple(args, "iiii:subwin", &nlines, &ncols, &begin_y, &begin_x)) { + goto exit; + } + group_left_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.subwin requires 2 to 4 arguments"); + goto exit; + } + return_value = _curses_window_subwin_impl(self, group_left_1, nlines, ncols, begin_y, begin_x); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_scroll__doc__, +"scroll([lines=1])\n" +"Scroll the screen or scrolling region.\n" +"\n" +" lines\n" +" Number of lines to scroll.\n" +"\n" +"Scroll upward if the argument is positive and downward if it is negative."); + +#define _CURSES_WINDOW_SCROLL_METHODDEF \ + {"scroll", (PyCFunction)_curses_window_scroll, METH_VARARGS, _curses_window_scroll__doc__}, + +static PyObject * +_curses_window_scroll_impl(PyCursesWindowObject *self, int group_right_1, + int lines); + +static PyObject * +_curses_window_scroll(PyCursesWindowObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int group_right_1 = 0; + int lines = 1; + + switch (PyTuple_GET_SIZE(args)) { + case 0: + break; + case 1: + if (!PyArg_ParseTuple(args, "i:scroll", &lines)) { + goto exit; + } + group_right_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.scroll requires 0 to 1 arguments"); + goto exit; + } + return_value = _curses_window_scroll_impl(self, group_right_1, lines); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_touchline__doc__, +"touchline(start, count, [changed=True])\n" +"Pretend count lines have been changed, starting with line start.\n" +"\n" +"If changed is supplied, it specifies whether the affected lines are marked\n" +"as having been changed (changed=True) or unchanged (changed=False)."); + +#define _CURSES_WINDOW_TOUCHLINE_METHODDEF \ + {"touchline", (PyCFunction)_curses_window_touchline, METH_VARARGS, _curses_window_touchline__doc__}, + +static PyObject * +_curses_window_touchline_impl(PyCursesWindowObject *self, int start, + int count, int group_right_1, int changed); + +static PyObject * +_curses_window_touchline(PyCursesWindowObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int start; + int count; + int group_right_1 = 0; + int changed = 1; + + switch (PyTuple_GET_SIZE(args)) { + case 2: + if (!PyArg_ParseTuple(args, "ii:touchline", &start, &count)) { + goto exit; + } + break; + case 3: + if (!PyArg_ParseTuple(args, "iii:touchline", &start, &count, &changed)) { + goto exit; + } + group_right_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.touchline requires 2 to 3 arguments"); + goto exit; + } + return_value = _curses_window_touchline_impl(self, start, count, group_right_1, changed); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_window_vline__doc__, +"vline([y, x,] ch, n, [attr=_curses.A_NORMAL])\n" +"Display a vertical line.\n" +"\n" +" y\n" +" Starting Y-coordinate.\n" +" x\n" +" Starting X-coordinate.\n" +" ch\n" +" Character to draw.\n" +" n\n" +" Line length.\n" +" attr\n" +" Attributes for the character."); + +#define _CURSES_WINDOW_VLINE_METHODDEF \ + {"vline", (PyCFunction)_curses_window_vline, METH_VARARGS, _curses_window_vline__doc__}, + +static PyObject * +_curses_window_vline_impl(PyCursesWindowObject *self, int group_left_1, + int y, int x, PyObject *ch, int n, + int group_right_1, long attr); + +static PyObject * +_curses_window_vline(PyCursesWindowObject *self, PyObject *args) +{ + PyObject *return_value = NULL; + int group_left_1 = 0; + int y = 0; + int x = 0; + PyObject *ch; + int n; + int group_right_1 = 0; + long attr = A_NORMAL; + + switch (PyTuple_GET_SIZE(args)) { + case 2: + if (!PyArg_ParseTuple(args, "Oi:vline", &ch, &n)) { + goto exit; + } + break; + case 3: + if (!PyArg_ParseTuple(args, "Oil:vline", &ch, &n, &attr)) { + goto exit; + } + group_right_1 = 1; + break; + case 4: + if (!PyArg_ParseTuple(args, "iiOi:vline", &y, &x, &ch, &n)) { + goto exit; + } + group_left_1 = 1; + break; + case 5: + if (!PyArg_ParseTuple(args, "iiOil:vline", &y, &x, &ch, &n, &attr)) { + goto exit; + } + group_right_1 = 1; + group_left_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.window.vline requires 2 to 5 arguments"); + goto exit; + } + return_value = _curses_window_vline_impl(self, group_left_1, y, x, ch, n, group_right_1, attr); + +exit: + return return_value; +} + +#if defined(HAVE_CURSES_FILTER) + +PyDoc_STRVAR(_curses_filter__doc__, +"filter($module, /)\n" +"--\n" +"\n"); + +#define _CURSES_FILTER_METHODDEF \ + {"filter", (PyCFunction)_curses_filter, METH_NOARGS, _curses_filter__doc__}, + +static PyObject * +_curses_filter_impl(PyObject *module); + +static PyObject * +_curses_filter(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_filter_impl(module); +} + +#endif /* defined(HAVE_CURSES_FILTER) */ + +PyDoc_STRVAR(_curses_baudrate__doc__, +"baudrate($module, /)\n" +"--\n" +"\n" +"Return the output speed of the terminal in bits per second."); + +#define _CURSES_BAUDRATE_METHODDEF \ + {"baudrate", (PyCFunction)_curses_baudrate, METH_NOARGS, _curses_baudrate__doc__}, + +static PyObject * +_curses_baudrate_impl(PyObject *module); + +static PyObject * +_curses_baudrate(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_baudrate_impl(module); +} + +PyDoc_STRVAR(_curses_beep__doc__, +"beep($module, /)\n" +"--\n" +"\n" +"Emit a short attention sound."); + +#define _CURSES_BEEP_METHODDEF \ + {"beep", (PyCFunction)_curses_beep, METH_NOARGS, _curses_beep__doc__}, + +static PyObject * +_curses_beep_impl(PyObject *module); + +static PyObject * +_curses_beep(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_beep_impl(module); +} + +PyDoc_STRVAR(_curses_can_change_color__doc__, +"can_change_color($module, /)\n" +"--\n" +"\n" +"Return True if the programmer can change the colors displayed by the terminal."); + +#define _CURSES_CAN_CHANGE_COLOR_METHODDEF \ + {"can_change_color", (PyCFunction)_curses_can_change_color, METH_NOARGS, _curses_can_change_color__doc__}, + +static PyObject * +_curses_can_change_color_impl(PyObject *module); + +static PyObject * +_curses_can_change_color(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_can_change_color_impl(module); +} + +PyDoc_STRVAR(_curses_cbreak__doc__, +"cbreak($module, flag=True, /)\n" +"--\n" +"\n" +"Enter cbreak mode.\n" +"\n" +" flag\n" +" If false, the effect is the same as calling nocbreak().\n" +"\n" +"In cbreak mode (sometimes called \"rare\" mode) normal tty line buffering is\n" +"turned off and characters are available to be read one by one. However,\n" +"unlike raw mode, special characters (interrupt, quit, suspend, and flow\n" +"control) retain their effects on the tty driver and calling program.\n" +"Calling first raw() then cbreak() leaves the terminal in cbreak mode."); + +#define _CURSES_CBREAK_METHODDEF \ + {"cbreak", (PyCFunction)_curses_cbreak, METH_FASTCALL, _curses_cbreak__doc__}, + +static PyObject * +_curses_cbreak_impl(PyObject *module, int flag); + +static PyObject * +_curses_cbreak(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int flag = 1; + + if (!_PyArg_ParseStack(args, nargs, "|i:cbreak", + &flag)) { + goto exit; + } + return_value = _curses_cbreak_impl(module, flag); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_color_content__doc__, +"color_content($module, color_number, /)\n" +"--\n" +"\n" +"Return the red, green, and blue (RGB) components of the specified color.\n" +"\n" +" color_number\n" +" The number of the color (0 - COLORS).\n" +"\n" +"A 3-tuple is returned, containing the R, G, B values for the given color,\n" +"which will be between 0 (no component) and 1000 (maximum amount of component)."); + +#define _CURSES_COLOR_CONTENT_METHODDEF \ + {"color_content", (PyCFunction)_curses_color_content, METH_O, _curses_color_content__doc__}, + +static PyObject * +_curses_color_content_impl(PyObject *module, short color_number); + +static PyObject * +_curses_color_content(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + short color_number; + + if (!PyArg_Parse(arg, "h:color_content", &color_number)) { + goto exit; + } + return_value = _curses_color_content_impl(module, color_number); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_color_pair__doc__, +"color_pair($module, color_number, /)\n" +"--\n" +"\n" +"Return the attribute value for displaying text in the specified color.\n" +"\n" +" color_number\n" +" The number of the color (0 - COLORS).\n" +"\n" +"This attribute value can be combined with A_STANDOUT, A_REVERSE, and the\n" +"other A_* attributes. pair_number() is the counterpart to this function."); + +#define _CURSES_COLOR_PAIR_METHODDEF \ + {"color_pair", (PyCFunction)_curses_color_pair, METH_O, _curses_color_pair__doc__}, + +static PyObject * +_curses_color_pair_impl(PyObject *module, short color_number); + +static PyObject * +_curses_color_pair(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + short color_number; + + if (!PyArg_Parse(arg, "h:color_pair", &color_number)) { + goto exit; + } + return_value = _curses_color_pair_impl(module, color_number); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_curs_set__doc__, +"curs_set($module, visibility, /)\n" +"--\n" +"\n" +"Set the cursor state.\n" +"\n" +" visibility\n" +" 0 for invisible, 1 for normal visible, or 2 for very visible.\n" +"\n" +"If the terminal supports the visibility requested, the previous cursor\n" +"state is returned; otherwise, an exception is raised. On many terminals,\n" +"the \"visible\" mode is an underline cursor and the \"very visible\" mode is\n" +"a block cursor."); + +#define _CURSES_CURS_SET_METHODDEF \ + {"curs_set", (PyCFunction)_curses_curs_set, METH_O, _curses_curs_set__doc__}, + +static PyObject * +_curses_curs_set_impl(PyObject *module, int visibility); + +static PyObject * +_curses_curs_set(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int visibility; + + if (!PyArg_Parse(arg, "i:curs_set", &visibility)) { + goto exit; + } + return_value = _curses_curs_set_impl(module, visibility); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_def_prog_mode__doc__, +"def_prog_mode($module, /)\n" +"--\n" +"\n" +"Save the current terminal mode as the \"program\" mode.\n" +"\n" +"The \"program\" mode is the mode when the running program is using curses.\n" +"\n" +"Subsequent calls to reset_prog_mode() will restore this mode."); + +#define _CURSES_DEF_PROG_MODE_METHODDEF \ + {"def_prog_mode", (PyCFunction)_curses_def_prog_mode, METH_NOARGS, _curses_def_prog_mode__doc__}, + +static PyObject * +_curses_def_prog_mode_impl(PyObject *module); + +static PyObject * +_curses_def_prog_mode(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_def_prog_mode_impl(module); +} + +PyDoc_STRVAR(_curses_def_shell_mode__doc__, +"def_shell_mode($module, /)\n" +"--\n" +"\n" +"Save the current terminal mode as the \"shell\" mode.\n" +"\n" +"The \"shell\" mode is the mode when the running program is not using curses.\n" +"\n" +"Subsequent calls to reset_shell_mode() will restore this mode."); + +#define _CURSES_DEF_SHELL_MODE_METHODDEF \ + {"def_shell_mode", (PyCFunction)_curses_def_shell_mode, METH_NOARGS, _curses_def_shell_mode__doc__}, + +static PyObject * +_curses_def_shell_mode_impl(PyObject *module); + +static PyObject * +_curses_def_shell_mode(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_def_shell_mode_impl(module); +} + +PyDoc_STRVAR(_curses_delay_output__doc__, +"delay_output($module, ms, /)\n" +"--\n" +"\n" +"Insert a pause in output.\n" +"\n" +" ms\n" +" Duration in milliseconds."); + +#define _CURSES_DELAY_OUTPUT_METHODDEF \ + {"delay_output", (PyCFunction)_curses_delay_output, METH_O, _curses_delay_output__doc__}, + +static PyObject * +_curses_delay_output_impl(PyObject *module, int ms); + +static PyObject * +_curses_delay_output(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int ms; + + if (!PyArg_Parse(arg, "i:delay_output", &ms)) { + goto exit; + } + return_value = _curses_delay_output_impl(module, ms); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_doupdate__doc__, +"doupdate($module, /)\n" +"--\n" +"\n" +"Update the physical screen to match the virtual screen."); + +#define _CURSES_DOUPDATE_METHODDEF \ + {"doupdate", (PyCFunction)_curses_doupdate, METH_NOARGS, _curses_doupdate__doc__}, + +static PyObject * +_curses_doupdate_impl(PyObject *module); + +static PyObject * +_curses_doupdate(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_doupdate_impl(module); +} + +PyDoc_STRVAR(_curses_echo__doc__, +"echo($module, flag=True, /)\n" +"--\n" +"\n" +"Enter echo mode.\n" +"\n" +" flag\n" +" If false, the effect is the same as calling noecho().\n" +"\n" +"In echo mode, each character input is echoed to the screen as it is entered."); + +#define _CURSES_ECHO_METHODDEF \ + {"echo", (PyCFunction)_curses_echo, METH_FASTCALL, _curses_echo__doc__}, + +static PyObject * +_curses_echo_impl(PyObject *module, int flag); + +static PyObject * +_curses_echo(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int flag = 1; + + if (!_PyArg_ParseStack(args, nargs, "|i:echo", + &flag)) { + goto exit; + } + return_value = _curses_echo_impl(module, flag); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_endwin__doc__, +"endwin($module, /)\n" +"--\n" +"\n" +"De-initialize the library, and return terminal to normal status."); + +#define _CURSES_ENDWIN_METHODDEF \ + {"endwin", (PyCFunction)_curses_endwin, METH_NOARGS, _curses_endwin__doc__}, + +static PyObject * +_curses_endwin_impl(PyObject *module); + +static PyObject * +_curses_endwin(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_endwin_impl(module); +} + +PyDoc_STRVAR(_curses_erasechar__doc__, +"erasechar($module, /)\n" +"--\n" +"\n" +"Return the user\'s current erase character."); + +#define _CURSES_ERASECHAR_METHODDEF \ + {"erasechar", (PyCFunction)_curses_erasechar, METH_NOARGS, _curses_erasechar__doc__}, + +static PyObject * +_curses_erasechar_impl(PyObject *module); + +static PyObject * +_curses_erasechar(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_erasechar_impl(module); +} + +PyDoc_STRVAR(_curses_flash__doc__, +"flash($module, /)\n" +"--\n" +"\n" +"Flash the screen.\n" +"\n" +"That is, change it to reverse-video and then change it back in a short interval."); + +#define _CURSES_FLASH_METHODDEF \ + {"flash", (PyCFunction)_curses_flash, METH_NOARGS, _curses_flash__doc__}, + +static PyObject * +_curses_flash_impl(PyObject *module); + +static PyObject * +_curses_flash(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_flash_impl(module); +} + +PyDoc_STRVAR(_curses_flushinp__doc__, +"flushinp($module, /)\n" +"--\n" +"\n" +"Flush all input buffers.\n" +"\n" +"This throws away any typeahead that has been typed by the user and has not\n" +"yet been processed by the program."); + +#define _CURSES_FLUSHINP_METHODDEF \ + {"flushinp", (PyCFunction)_curses_flushinp, METH_NOARGS, _curses_flushinp__doc__}, + +static PyObject * +_curses_flushinp_impl(PyObject *module); + +static PyObject * +_curses_flushinp(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_flushinp_impl(module); +} + +#if defined(getsyx) + +PyDoc_STRVAR(_curses_getsyx__doc__, +"getsyx($module, /)\n" +"--\n" +"\n" +"Return the current coordinates of the virtual screen cursor.\n" +"\n" +"Return a (y, x) tuple. If leaveok is currently true, return (-1, -1)."); + +#define _CURSES_GETSYX_METHODDEF \ + {"getsyx", (PyCFunction)_curses_getsyx, METH_NOARGS, _curses_getsyx__doc__}, + +static PyObject * +_curses_getsyx_impl(PyObject *module); + +static PyObject * +_curses_getsyx(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_getsyx_impl(module); +} + +#endif /* defined(getsyx) */ + +#if defined(NCURSES_MOUSE_VERSION) + +PyDoc_STRVAR(_curses_getmouse__doc__, +"getmouse($module, /)\n" +"--\n" +"\n" +"Retrieve the queued mouse event.\n" +"\n" +"After getch() returns KEY_MOUSE to signal a mouse event, this function\n" +"returns a 5-tuple (id, x, y, z, bstate)."); + +#define _CURSES_GETMOUSE_METHODDEF \ + {"getmouse", (PyCFunction)_curses_getmouse, METH_NOARGS, _curses_getmouse__doc__}, + +static PyObject * +_curses_getmouse_impl(PyObject *module); + +static PyObject * +_curses_getmouse(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_getmouse_impl(module); +} + +#endif /* defined(NCURSES_MOUSE_VERSION) */ + +#if defined(NCURSES_MOUSE_VERSION) + +PyDoc_STRVAR(_curses_ungetmouse__doc__, +"ungetmouse($module, id, x, y, z, bstate, /)\n" +"--\n" +"\n" +"Push a KEY_MOUSE event onto the input queue.\n" +"\n" +"The following getmouse() will return the given state data."); + +#define _CURSES_UNGETMOUSE_METHODDEF \ + {"ungetmouse", (PyCFunction)_curses_ungetmouse, METH_FASTCALL, _curses_ungetmouse__doc__}, + +static PyObject * +_curses_ungetmouse_impl(PyObject *module, short id, int x, int y, int z, + unsigned long bstate); + +static PyObject * +_curses_ungetmouse(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + short id; + int x; + int y; + int z; + unsigned long bstate; + + if (!_PyArg_ParseStack(args, nargs, "hiiik:ungetmouse", + &id, &x, &y, &z, &bstate)) { + goto exit; + } + return_value = _curses_ungetmouse_impl(module, id, x, y, z, bstate); + +exit: + return return_value; +} + +#endif /* defined(NCURSES_MOUSE_VERSION) */ + +PyDoc_STRVAR(_curses_getwin__doc__, +"getwin($module, file, /)\n" +"--\n" +"\n" +"Read window related data stored in the file by an earlier putwin() call.\n" +"\n" +"The routine then creates and initializes a new window using that data,\n" +"returning the new window object."); + +#define _CURSES_GETWIN_METHODDEF \ + {"getwin", (PyCFunction)_curses_getwin, METH_O, _curses_getwin__doc__}, + +PyDoc_STRVAR(_curses_halfdelay__doc__, +"halfdelay($module, tenths, /)\n" +"--\n" +"\n" +"Enter half-delay mode.\n" +"\n" +" tenths\n" +" Maximal blocking delay in tenths of seconds (1 - 255).\n" +"\n" +"Use nocbreak() to leave half-delay mode."); + +#define _CURSES_HALFDELAY_METHODDEF \ + {"halfdelay", (PyCFunction)_curses_halfdelay, METH_O, _curses_halfdelay__doc__}, + +static PyObject * +_curses_halfdelay_impl(PyObject *module, unsigned char tenths); + +static PyObject * +_curses_halfdelay(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + unsigned char tenths; + + if (!PyArg_Parse(arg, "b:halfdelay", &tenths)) { + goto exit; + } + return_value = _curses_halfdelay_impl(module, tenths); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_has_colors__doc__, +"has_colors($module, /)\n" +"--\n" +"\n" +"Return True if the terminal can display colors; otherwise, return False."); + +#define _CURSES_HAS_COLORS_METHODDEF \ + {"has_colors", (PyCFunction)_curses_has_colors, METH_NOARGS, _curses_has_colors__doc__}, + +static PyObject * +_curses_has_colors_impl(PyObject *module); + +static PyObject * +_curses_has_colors(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_has_colors_impl(module); +} + +PyDoc_STRVAR(_curses_has_ic__doc__, +"has_ic($module, /)\n" +"--\n" +"\n" +"Return True if the terminal has insert- and delete-character capabilities."); + +#define _CURSES_HAS_IC_METHODDEF \ + {"has_ic", (PyCFunction)_curses_has_ic, METH_NOARGS, _curses_has_ic__doc__}, + +static PyObject * +_curses_has_ic_impl(PyObject *module); + +static PyObject * +_curses_has_ic(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_has_ic_impl(module); +} + +PyDoc_STRVAR(_curses_has_il__doc__, +"has_il($module, /)\n" +"--\n" +"\n" +"Return True if the terminal has insert- and delete-line capabilities."); + +#define _CURSES_HAS_IL_METHODDEF \ + {"has_il", (PyCFunction)_curses_has_il, METH_NOARGS, _curses_has_il__doc__}, + +static PyObject * +_curses_has_il_impl(PyObject *module); + +static PyObject * +_curses_has_il(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_has_il_impl(module); +} + +#if defined(HAVE_CURSES_HAS_KEY) + +PyDoc_STRVAR(_curses_has_key__doc__, +"has_key($module, key, /)\n" +"--\n" +"\n" +"Return True if the current terminal type recognizes a key with that value.\n" +"\n" +" key\n" +" Key number."); + +#define _CURSES_HAS_KEY_METHODDEF \ + {"has_key", (PyCFunction)_curses_has_key, METH_O, _curses_has_key__doc__}, + +static PyObject * +_curses_has_key_impl(PyObject *module, int key); + +static PyObject * +_curses_has_key(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int key; + + if (!PyArg_Parse(arg, "i:has_key", &key)) { + goto exit; + } + return_value = _curses_has_key_impl(module, key); + +exit: + return return_value; +} + +#endif /* defined(HAVE_CURSES_HAS_KEY) */ + +PyDoc_STRVAR(_curses_init_color__doc__, +"init_color($module, color_number, r, g, b, /)\n" +"--\n" +"\n" +"Change the definition of a color.\n" +"\n" +" color_number\n" +" The number of the color to be changed (0 - COLORS).\n" +" r\n" +" Red component (0 - 1000).\n" +" g\n" +" Green component (0 - 1000).\n" +" b\n" +" Blue component (0 - 1000).\n" +"\n" +"When init_color() is used, all occurrences of that color on the screen\n" +"immediately change to the new definition. This function is a no-op on\n" +"most terminals; it is active only if can_change_color() returns 1."); + +#define _CURSES_INIT_COLOR_METHODDEF \ + {"init_color", (PyCFunction)_curses_init_color, METH_FASTCALL, _curses_init_color__doc__}, + +static PyObject * +_curses_init_color_impl(PyObject *module, short color_number, short r, + short g, short b); + +static PyObject * +_curses_init_color(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + short color_number; + short r; + short g; + short b; + + if (!_PyArg_ParseStack(args, nargs, "hhhh:init_color", + &color_number, &r, &g, &b)) { + goto exit; + } + return_value = _curses_init_color_impl(module, color_number, r, g, b); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_init_pair__doc__, +"init_pair($module, pair_number, fg, bg, /)\n" +"--\n" +"\n" +"Change the definition of a color-pair.\n" +"\n" +" pair_number\n" +" The number of the color-pair to be changed (1 - (COLOR_PAIRS-1)).\n" +" fg\n" +" Foreground color number (0 - COLORS).\n" +" bg\n" +" Background color number (0 - COLORS).\n" +"\n" +"If the color-pair was previously initialized, the screen is refreshed and\n" +"all occurrences of that color-pair are changed to the new definition."); + +#define _CURSES_INIT_PAIR_METHODDEF \ + {"init_pair", (PyCFunction)_curses_init_pair, METH_FASTCALL, _curses_init_pair__doc__}, + +static PyObject * +_curses_init_pair_impl(PyObject *module, short pair_number, short fg, + short bg); + +static PyObject * +_curses_init_pair(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + short pair_number; + short fg; + short bg; + + if (!_PyArg_ParseStack(args, nargs, "hhh:init_pair", + &pair_number, &fg, &bg)) { + goto exit; + } + return_value = _curses_init_pair_impl(module, pair_number, fg, bg); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_initscr__doc__, +"initscr($module, /)\n" +"--\n" +"\n" +"Initialize the library.\n" +"\n" +"Return a WindowObject which represents the whole screen."); + +#define _CURSES_INITSCR_METHODDEF \ + {"initscr", (PyCFunction)_curses_initscr, METH_NOARGS, _curses_initscr__doc__}, + +static PyObject * +_curses_initscr_impl(PyObject *module); + +static PyObject * +_curses_initscr(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_initscr_impl(module); +} + +PyDoc_STRVAR(_curses_setupterm__doc__, +"setupterm($module, /, term=None, fd=-1)\n" +"--\n" +"\n" +"Initialize the terminal.\n" +"\n" +" term\n" +" Terminal name.\n" +" If omitted, the value of the TERM environment variable will be used.\n" +" fd\n" +" File descriptor to which any initialization sequences will be sent.\n" +" If not supplied, the file descriptor for sys.stdout will be used."); + +#define _CURSES_SETUPTERM_METHODDEF \ + {"setupterm", (PyCFunction)_curses_setupterm, METH_FASTCALL|METH_KEYWORDS, _curses_setupterm__doc__}, + +static PyObject * +_curses_setupterm_impl(PyObject *module, const char *term, int fd); + +static PyObject * +_curses_setupterm(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"term", "fd", NULL}; + static _PyArg_Parser _parser = {"|zi:setupterm", _keywords, 0}; + const char *term = NULL; + int fd = -1; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &term, &fd)) { + goto exit; + } + return_value = _curses_setupterm_impl(module, term, fd); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_intrflush__doc__, +"intrflush($module, flag, /)\n" +"--\n" +"\n"); + +#define _CURSES_INTRFLUSH_METHODDEF \ + {"intrflush", (PyCFunction)_curses_intrflush, METH_O, _curses_intrflush__doc__}, + +static PyObject * +_curses_intrflush_impl(PyObject *module, int flag); + +static PyObject * +_curses_intrflush(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int flag; + + if (!PyArg_Parse(arg, "i:intrflush", &flag)) { + goto exit; + } + return_value = _curses_intrflush_impl(module, flag); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_isendwin__doc__, +"isendwin($module, /)\n" +"--\n" +"\n" +"Return True if endwin() has been called."); + +#define _CURSES_ISENDWIN_METHODDEF \ + {"isendwin", (PyCFunction)_curses_isendwin, METH_NOARGS, _curses_isendwin__doc__}, + +static PyObject * +_curses_isendwin_impl(PyObject *module); + +static PyObject * +_curses_isendwin(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_isendwin_impl(module); +} + +#if defined(HAVE_CURSES_IS_TERM_RESIZED) + +PyDoc_STRVAR(_curses_is_term_resized__doc__, +"is_term_resized($module, nlines, ncols, /)\n" +"--\n" +"\n" +"Return True if resize_term() would modify the window structure, False otherwise.\n" +"\n" +" nlines\n" +" Height.\n" +" ncols\n" +" Width."); + +#define _CURSES_IS_TERM_RESIZED_METHODDEF \ + {"is_term_resized", (PyCFunction)_curses_is_term_resized, METH_FASTCALL, _curses_is_term_resized__doc__}, + +static PyObject * +_curses_is_term_resized_impl(PyObject *module, int nlines, int ncols); + +static PyObject * +_curses_is_term_resized(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int nlines; + int ncols; + + if (!_PyArg_ParseStack(args, nargs, "ii:is_term_resized", + &nlines, &ncols)) { + goto exit; + } + return_value = _curses_is_term_resized_impl(module, nlines, ncols); + +exit: + return return_value; +} + +#endif /* defined(HAVE_CURSES_IS_TERM_RESIZED) */ + +PyDoc_STRVAR(_curses_keyname__doc__, +"keyname($module, key, /)\n" +"--\n" +"\n" +"Return the name of specified key.\n" +"\n" +" key\n" +" Key number."); + +#define _CURSES_KEYNAME_METHODDEF \ + {"keyname", (PyCFunction)_curses_keyname, METH_O, _curses_keyname__doc__}, + +static PyObject * +_curses_keyname_impl(PyObject *module, int key); + +static PyObject * +_curses_keyname(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int key; + + if (!PyArg_Parse(arg, "i:keyname", &key)) { + goto exit; + } + return_value = _curses_keyname_impl(module, key); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_killchar__doc__, +"killchar($module, /)\n" +"--\n" +"\n" +"Return the user\'s current line kill character."); + +#define _CURSES_KILLCHAR_METHODDEF \ + {"killchar", (PyCFunction)_curses_killchar, METH_NOARGS, _curses_killchar__doc__}, + +static PyObject * +_curses_killchar_impl(PyObject *module); + +static PyObject * +_curses_killchar(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_killchar_impl(module); +} + +PyDoc_STRVAR(_curses_longname__doc__, +"longname($module, /)\n" +"--\n" +"\n" +"Return the terminfo long name field describing the current terminal.\n" +"\n" +"The maximum length of a verbose description is 128 characters. It is defined\n" +"only after the call to initscr()."); + +#define _CURSES_LONGNAME_METHODDEF \ + {"longname", (PyCFunction)_curses_longname, METH_NOARGS, _curses_longname__doc__}, + +static PyObject * +_curses_longname_impl(PyObject *module); + +static PyObject * +_curses_longname(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_longname_impl(module); +} + +PyDoc_STRVAR(_curses_meta__doc__, +"meta($module, yes, /)\n" +"--\n" +"\n" +"Enable/disable meta keys.\n" +"\n" +"If yes is True, allow 8-bit characters to be input. If yes is False,\n" +"allow only 7-bit characters."); + +#define _CURSES_META_METHODDEF \ + {"meta", (PyCFunction)_curses_meta, METH_O, _curses_meta__doc__}, + +static PyObject * +_curses_meta_impl(PyObject *module, int yes); + +static PyObject * +_curses_meta(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int yes; + + if (!PyArg_Parse(arg, "i:meta", &yes)) { + goto exit; + } + return_value = _curses_meta_impl(module, yes); + +exit: + return return_value; +} + +#if defined(NCURSES_MOUSE_VERSION) + +PyDoc_STRVAR(_curses_mouseinterval__doc__, +"mouseinterval($module, interval, /)\n" +"--\n" +"\n" +"Set and retrieve the maximum time between press and release in a click.\n" +"\n" +" interval\n" +" Time in milliseconds.\n" +"\n" +"Set the maximum time that can elapse between press and release events in\n" +"order for them to be recognized as a click, and return the previous interval\n" +"value."); + +#define _CURSES_MOUSEINTERVAL_METHODDEF \ + {"mouseinterval", (PyCFunction)_curses_mouseinterval, METH_O, _curses_mouseinterval__doc__}, + +static PyObject * +_curses_mouseinterval_impl(PyObject *module, int interval); + +static PyObject * +_curses_mouseinterval(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int interval; + + if (!PyArg_Parse(arg, "i:mouseinterval", &interval)) { + goto exit; + } + return_value = _curses_mouseinterval_impl(module, interval); + +exit: + return return_value; +} + +#endif /* defined(NCURSES_MOUSE_VERSION) */ + +#if defined(NCURSES_MOUSE_VERSION) + +PyDoc_STRVAR(_curses_mousemask__doc__, +"mousemask($module, newmask, /)\n" +"--\n" +"\n" +"Set the mouse events to be reported, and return a tuple (availmask, oldmask).\n" +"\n" +"Return a tuple (availmask, oldmask). availmask indicates which of the\n" +"specified mouse events can be reported; on complete failure it returns 0.\n" +"oldmask is the previous value of the given window\'s mouse event mask.\n" +"If this function is never called, no mouse events are ever reported."); + +#define _CURSES_MOUSEMASK_METHODDEF \ + {"mousemask", (PyCFunction)_curses_mousemask, METH_O, _curses_mousemask__doc__}, + +static PyObject * +_curses_mousemask_impl(PyObject *module, unsigned long newmask); + +static PyObject * +_curses_mousemask(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + unsigned long newmask; + + if (!PyArg_Parse(arg, "k:mousemask", &newmask)) { + goto exit; + } + return_value = _curses_mousemask_impl(module, newmask); + +exit: + return return_value; +} + +#endif /* defined(NCURSES_MOUSE_VERSION) */ + +PyDoc_STRVAR(_curses_napms__doc__, +"napms($module, ms, /)\n" +"--\n" +"\n" +"Sleep for specified time.\n" +"\n" +" ms\n" +" Duration in milliseconds."); + +#define _CURSES_NAPMS_METHODDEF \ + {"napms", (PyCFunction)_curses_napms, METH_O, _curses_napms__doc__}, + +static PyObject * +_curses_napms_impl(PyObject *module, int ms); + +static PyObject * +_curses_napms(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int ms; + + if (!PyArg_Parse(arg, "i:napms", &ms)) { + goto exit; + } + return_value = _curses_napms_impl(module, ms); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_newpad__doc__, +"newpad($module, nlines, ncols, /)\n" +"--\n" +"\n" +"Create and return a pointer to a new pad data structure.\n" +"\n" +" nlines\n" +" Height.\n" +" ncols\n" +" Width."); + +#define _CURSES_NEWPAD_METHODDEF \ + {"newpad", (PyCFunction)_curses_newpad, METH_FASTCALL, _curses_newpad__doc__}, + +static PyObject * +_curses_newpad_impl(PyObject *module, int nlines, int ncols); + +static PyObject * +_curses_newpad(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int nlines; + int ncols; + + if (!_PyArg_ParseStack(args, nargs, "ii:newpad", + &nlines, &ncols)) { + goto exit; + } + return_value = _curses_newpad_impl(module, nlines, ncols); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_newwin__doc__, +"newwin(nlines, ncols, [begin_y=0, begin_x=0])\n" +"Return a new window.\n" +"\n" +" nlines\n" +" Height.\n" +" ncols\n" +" Width.\n" +" begin_y\n" +" Top side y-coordinate.\n" +" begin_x\n" +" Left side x-coordinate.\n" +"\n" +"By default, the window will extend from the specified position to the lower\n" +"right corner of the screen."); + +#define _CURSES_NEWWIN_METHODDEF \ + {"newwin", (PyCFunction)_curses_newwin, METH_VARARGS, _curses_newwin__doc__}, + +static PyObject * +_curses_newwin_impl(PyObject *module, int nlines, int ncols, + int group_right_1, int begin_y, int begin_x); + +static PyObject * +_curses_newwin(PyObject *module, PyObject *args) +{ + PyObject *return_value = NULL; + int nlines; + int ncols; + int group_right_1 = 0; + int begin_y = 0; + int begin_x = 0; + + switch (PyTuple_GET_SIZE(args)) { + case 2: + if (!PyArg_ParseTuple(args, "ii:newwin", &nlines, &ncols)) { + goto exit; + } + break; + case 4: + if (!PyArg_ParseTuple(args, "iiii:newwin", &nlines, &ncols, &begin_y, &begin_x)) { + goto exit; + } + group_right_1 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "_curses.newwin requires 2 to 4 arguments"); + goto exit; + } + return_value = _curses_newwin_impl(module, nlines, ncols, group_right_1, begin_y, begin_x); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_nl__doc__, +"nl($module, flag=True, /)\n" +"--\n" +"\n" +"Enter newline mode.\n" +"\n" +" flag\n" +" If false, the effect is the same as calling nonl().\n" +"\n" +"This mode translates the return key into newline on input, and translates\n" +"newline into return and line-feed on output. Newline mode is initially on."); + +#define _CURSES_NL_METHODDEF \ + {"nl", (PyCFunction)_curses_nl, METH_FASTCALL, _curses_nl__doc__}, + +static PyObject * +_curses_nl_impl(PyObject *module, int flag); + +static PyObject * +_curses_nl(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int flag = 1; + + if (!_PyArg_ParseStack(args, nargs, "|i:nl", + &flag)) { + goto exit; + } + return_value = _curses_nl_impl(module, flag); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_nocbreak__doc__, +"nocbreak($module, /)\n" +"--\n" +"\n" +"Leave cbreak mode.\n" +"\n" +"Return to normal \"cooked\" mode with line buffering."); + +#define _CURSES_NOCBREAK_METHODDEF \ + {"nocbreak", (PyCFunction)_curses_nocbreak, METH_NOARGS, _curses_nocbreak__doc__}, + +static PyObject * +_curses_nocbreak_impl(PyObject *module); + +static PyObject * +_curses_nocbreak(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_nocbreak_impl(module); +} + +PyDoc_STRVAR(_curses_noecho__doc__, +"noecho($module, /)\n" +"--\n" +"\n" +"Leave echo mode.\n" +"\n" +"Echoing of input characters is turned off."); + +#define _CURSES_NOECHO_METHODDEF \ + {"noecho", (PyCFunction)_curses_noecho, METH_NOARGS, _curses_noecho__doc__}, + +static PyObject * +_curses_noecho_impl(PyObject *module); + +static PyObject * +_curses_noecho(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_noecho_impl(module); +} + +PyDoc_STRVAR(_curses_nonl__doc__, +"nonl($module, /)\n" +"--\n" +"\n" +"Leave newline mode.\n" +"\n" +"Disable translation of return into newline on input, and disable low-level\n" +"translation of newline into newline/return on output."); + +#define _CURSES_NONL_METHODDEF \ + {"nonl", (PyCFunction)_curses_nonl, METH_NOARGS, _curses_nonl__doc__}, + +static PyObject * +_curses_nonl_impl(PyObject *module); + +static PyObject * +_curses_nonl(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_nonl_impl(module); +} + +PyDoc_STRVAR(_curses_noqiflush__doc__, +"noqiflush($module, /)\n" +"--\n" +"\n" +"Disable queue flushing.\n" +"\n" +"When queue flushing is disabled, normal flush of input and output queues\n" +"associated with the INTR, QUIT and SUSP characters will not be done."); + +#define _CURSES_NOQIFLUSH_METHODDEF \ + {"noqiflush", (PyCFunction)_curses_noqiflush, METH_NOARGS, _curses_noqiflush__doc__}, + +static PyObject * +_curses_noqiflush_impl(PyObject *module); + +static PyObject * +_curses_noqiflush(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_noqiflush_impl(module); +} + +PyDoc_STRVAR(_curses_noraw__doc__, +"noraw($module, /)\n" +"--\n" +"\n" +"Leave raw mode.\n" +"\n" +"Return to normal \"cooked\" mode with line buffering."); + +#define _CURSES_NORAW_METHODDEF \ + {"noraw", (PyCFunction)_curses_noraw, METH_NOARGS, _curses_noraw__doc__}, + +static PyObject * +_curses_noraw_impl(PyObject *module); + +static PyObject * +_curses_noraw(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_noraw_impl(module); +} + +PyDoc_STRVAR(_curses_pair_content__doc__, +"pair_content($module, pair_number, /)\n" +"--\n" +"\n" +"Return a tuple (fg, bg) containing the colors for the requested color pair.\n" +"\n" +" pair_number\n" +" The number of the color pair (1 - (COLOR_PAIRS-1))."); + +#define _CURSES_PAIR_CONTENT_METHODDEF \ + {"pair_content", (PyCFunction)_curses_pair_content, METH_O, _curses_pair_content__doc__}, + +static PyObject * +_curses_pair_content_impl(PyObject *module, short pair_number); + +static PyObject * +_curses_pair_content(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + short pair_number; + + if (!PyArg_Parse(arg, "h:pair_content", &pair_number)) { + goto exit; + } + return_value = _curses_pair_content_impl(module, pair_number); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_pair_number__doc__, +"pair_number($module, attr, /)\n" +"--\n" +"\n" +"Return the number of the color-pair set by the specified attribute value.\n" +"\n" +"color_pair() is the counterpart to this function."); + +#define _CURSES_PAIR_NUMBER_METHODDEF \ + {"pair_number", (PyCFunction)_curses_pair_number, METH_O, _curses_pair_number__doc__}, + +static PyObject * +_curses_pair_number_impl(PyObject *module, int attr); + +static PyObject * +_curses_pair_number(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int attr; + + if (!PyArg_Parse(arg, "i:pair_number", &attr)) { + goto exit; + } + return_value = _curses_pair_number_impl(module, attr); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_putp__doc__, +"putp($module, string, /)\n" +"--\n" +"\n" +"Emit the value of a specified terminfo capability for the current terminal.\n" +"\n" +"Note that the output of putp() always goes to standard output."); + +#define _CURSES_PUTP_METHODDEF \ + {"putp", (PyCFunction)_curses_putp, METH_O, _curses_putp__doc__}, + +static PyObject * +_curses_putp_impl(PyObject *module, const char *string); + +static PyObject * +_curses_putp(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + const char *string; + + if (!PyArg_Parse(arg, "y:putp", &string)) { + goto exit; + } + return_value = _curses_putp_impl(module, string); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_qiflush__doc__, +"qiflush($module, flag=True, /)\n" +"--\n" +"\n" +"Enable queue flushing.\n" +"\n" +" flag\n" +" If false, the effect is the same as calling noqiflush().\n" +"\n" +"If queue flushing is enabled, all output in the display driver queue\n" +"will be flushed when the INTR, QUIT and SUSP characters are read."); + +#define _CURSES_QIFLUSH_METHODDEF \ + {"qiflush", (PyCFunction)_curses_qiflush, METH_FASTCALL, _curses_qiflush__doc__}, + +static PyObject * +_curses_qiflush_impl(PyObject *module, int flag); + +static PyObject * +_curses_qiflush(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int flag = 1; + + if (!_PyArg_ParseStack(args, nargs, "|i:qiflush", + &flag)) { + goto exit; + } + return_value = _curses_qiflush_impl(module, flag); + +exit: + return return_value; +} + +#if (defined(HAVE_CURSES_RESIZETERM) || defined(HAVE_CURSES_RESIZE_TERM)) + +PyDoc_STRVAR(_curses_update_lines_cols__doc__, +"update_lines_cols($module, /)\n" +"--\n" +"\n"); + +#define _CURSES_UPDATE_LINES_COLS_METHODDEF \ + {"update_lines_cols", (PyCFunction)_curses_update_lines_cols, METH_NOARGS, _curses_update_lines_cols__doc__}, + +static int +_curses_update_lines_cols_impl(PyObject *module); + +static PyObject * +_curses_update_lines_cols(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + PyObject *return_value = NULL; + int _return_value; + + _return_value = _curses_update_lines_cols_impl(module); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromLong((long)_return_value); + +exit: + return return_value; +} + +#endif /* (defined(HAVE_CURSES_RESIZETERM) || defined(HAVE_CURSES_RESIZE_TERM)) */ + +PyDoc_STRVAR(_curses_raw__doc__, +"raw($module, flag=True, /)\n" +"--\n" +"\n" +"Enter raw mode.\n" +"\n" +" flag\n" +" If false, the effect is the same as calling noraw().\n" +"\n" +"In raw mode, normal line buffering and processing of interrupt, quit,\n" +"suspend, and flow control keys are turned off; characters are presented to\n" +"curses input functions one by one."); + +#define _CURSES_RAW_METHODDEF \ + {"raw", (PyCFunction)_curses_raw, METH_FASTCALL, _curses_raw__doc__}, + +static PyObject * +_curses_raw_impl(PyObject *module, int flag); + +static PyObject * +_curses_raw(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int flag = 1; + + if (!_PyArg_ParseStack(args, nargs, "|i:raw", + &flag)) { + goto exit; + } + return_value = _curses_raw_impl(module, flag); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_reset_prog_mode__doc__, +"reset_prog_mode($module, /)\n" +"--\n" +"\n" +"Restore the terminal to \"program\" mode, as previously saved by def_prog_mode()."); + +#define _CURSES_RESET_PROG_MODE_METHODDEF \ + {"reset_prog_mode", (PyCFunction)_curses_reset_prog_mode, METH_NOARGS, _curses_reset_prog_mode__doc__}, + +static PyObject * +_curses_reset_prog_mode_impl(PyObject *module); + +static PyObject * +_curses_reset_prog_mode(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_reset_prog_mode_impl(module); +} + +PyDoc_STRVAR(_curses_reset_shell_mode__doc__, +"reset_shell_mode($module, /)\n" +"--\n" +"\n" +"Restore the terminal to \"shell\" mode, as previously saved by def_shell_mode()."); + +#define _CURSES_RESET_SHELL_MODE_METHODDEF \ + {"reset_shell_mode", (PyCFunction)_curses_reset_shell_mode, METH_NOARGS, _curses_reset_shell_mode__doc__}, + +static PyObject * +_curses_reset_shell_mode_impl(PyObject *module); + +static PyObject * +_curses_reset_shell_mode(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_reset_shell_mode_impl(module); +} + +PyDoc_STRVAR(_curses_resetty__doc__, +"resetty($module, /)\n" +"--\n" +"\n" +"Restore terminal mode."); + +#define _CURSES_RESETTY_METHODDEF \ + {"resetty", (PyCFunction)_curses_resetty, METH_NOARGS, _curses_resetty__doc__}, + +static PyObject * +_curses_resetty_impl(PyObject *module); + +static PyObject * +_curses_resetty(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_resetty_impl(module); +} + +#if defined(HAVE_CURSES_RESIZETERM) + +PyDoc_STRVAR(_curses_resizeterm__doc__, +"resizeterm($module, nlines, ncols, /)\n" +"--\n" +"\n" +"Resize the standard and current windows to the specified dimensions.\n" +"\n" +" nlines\n" +" Height.\n" +" ncols\n" +" Width.\n" +"\n" +"Adjusts other bookkeeping data used by the curses library that record the\n" +"window dimensions (in particular the SIGWINCH handler)."); + +#define _CURSES_RESIZETERM_METHODDEF \ + {"resizeterm", (PyCFunction)_curses_resizeterm, METH_FASTCALL, _curses_resizeterm__doc__}, + +static PyObject * +_curses_resizeterm_impl(PyObject *module, int nlines, int ncols); + +static PyObject * +_curses_resizeterm(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int nlines; + int ncols; + + if (!_PyArg_ParseStack(args, nargs, "ii:resizeterm", + &nlines, &ncols)) { + goto exit; + } + return_value = _curses_resizeterm_impl(module, nlines, ncols); + +exit: + return return_value; +} + +#endif /* defined(HAVE_CURSES_RESIZETERM) */ + +#if defined(HAVE_CURSES_RESIZE_TERM) + +PyDoc_STRVAR(_curses_resize_term__doc__, +"resize_term($module, nlines, ncols, /)\n" +"--\n" +"\n" +"Backend function used by resizeterm(), performing most of the work.\n" +"\n" +" nlines\n" +" Height.\n" +" ncols\n" +" Width.\n" +"\n" +"When resizing the windows, resize_term() blank-fills the areas that are\n" +"extended. The calling application should fill in these areas with appropriate\n" +"data. The resize_term() function attempts to resize all windows. However,\n" +"due to the calling convention of pads, it is not possible to resize these\n" +"without additional interaction with the application."); + +#define _CURSES_RESIZE_TERM_METHODDEF \ + {"resize_term", (PyCFunction)_curses_resize_term, METH_FASTCALL, _curses_resize_term__doc__}, + +static PyObject * +_curses_resize_term_impl(PyObject *module, int nlines, int ncols); + +static PyObject * +_curses_resize_term(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int nlines; + int ncols; + + if (!_PyArg_ParseStack(args, nargs, "ii:resize_term", + &nlines, &ncols)) { + goto exit; + } + return_value = _curses_resize_term_impl(module, nlines, ncols); + +exit: + return return_value; +} + +#endif /* defined(HAVE_CURSES_RESIZE_TERM) */ + +PyDoc_STRVAR(_curses_savetty__doc__, +"savetty($module, /)\n" +"--\n" +"\n" +"Save terminal mode."); + +#define _CURSES_SAVETTY_METHODDEF \ + {"savetty", (PyCFunction)_curses_savetty, METH_NOARGS, _curses_savetty__doc__}, + +static PyObject * +_curses_savetty_impl(PyObject *module); + +static PyObject * +_curses_savetty(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_savetty_impl(module); +} + +#if defined(getsyx) + +PyDoc_STRVAR(_curses_setsyx__doc__, +"setsyx($module, y, x, /)\n" +"--\n" +"\n" +"Set the virtual screen cursor.\n" +"\n" +" y\n" +" Y-coordinate.\n" +" x\n" +" X-coordinate.\n" +"\n" +"If y and x are both -1, then leaveok is set."); + +#define _CURSES_SETSYX_METHODDEF \ + {"setsyx", (PyCFunction)_curses_setsyx, METH_FASTCALL, _curses_setsyx__doc__}, + +static PyObject * +_curses_setsyx_impl(PyObject *module, int y, int x); + +static PyObject * +_curses_setsyx(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + int y; + int x; + + if (!_PyArg_ParseStack(args, nargs, "ii:setsyx", + &y, &x)) { + goto exit; + } + return_value = _curses_setsyx_impl(module, y, x); + +exit: + return return_value; +} + +#endif /* defined(getsyx) */ + +PyDoc_STRVAR(_curses_start_color__doc__, +"start_color($module, /)\n" +"--\n" +"\n" +"Initializes eight basic colors and global variables COLORS and COLOR_PAIRS.\n" +"\n" +"Must be called if the programmer wants to use colors, and before any other\n" +"color manipulation routine is called. It is good practice to call this\n" +"routine right after initscr().\n" +"\n" +"It also restores the colors on the terminal to the values they had when the\n" +"terminal was just turned on."); + +#define _CURSES_START_COLOR_METHODDEF \ + {"start_color", (PyCFunction)_curses_start_color, METH_NOARGS, _curses_start_color__doc__}, + +static PyObject * +_curses_start_color_impl(PyObject *module); + +static PyObject * +_curses_start_color(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_start_color_impl(module); +} + +PyDoc_STRVAR(_curses_termattrs__doc__, +"termattrs($module, /)\n" +"--\n" +"\n" +"Return a logical OR of all video attributes supported by the terminal."); + +#define _CURSES_TERMATTRS_METHODDEF \ + {"termattrs", (PyCFunction)_curses_termattrs, METH_NOARGS, _curses_termattrs__doc__}, + +static PyObject * +_curses_termattrs_impl(PyObject *module); + +static PyObject * +_curses_termattrs(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_termattrs_impl(module); +} + +PyDoc_STRVAR(_curses_termname__doc__, +"termname($module, /)\n" +"--\n" +"\n" +"Return the value of the environment variable TERM, truncated to 14 characters."); + +#define _CURSES_TERMNAME_METHODDEF \ + {"termname", (PyCFunction)_curses_termname, METH_NOARGS, _curses_termname__doc__}, + +static PyObject * +_curses_termname_impl(PyObject *module); + +static PyObject * +_curses_termname(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_termname_impl(module); +} + +PyDoc_STRVAR(_curses_tigetflag__doc__, +"tigetflag($module, capname, /)\n" +"--\n" +"\n" +"Return the value of the Boolean capability.\n" +"\n" +" capname\n" +" The terminfo capability name.\n" +"\n" +"The value -1 is returned if capname is not a Boolean capability, or 0 if\n" +"it is canceled or absent from the terminal description."); + +#define _CURSES_TIGETFLAG_METHODDEF \ + {"tigetflag", (PyCFunction)_curses_tigetflag, METH_O, _curses_tigetflag__doc__}, + +static PyObject * +_curses_tigetflag_impl(PyObject *module, const char *capname); + +static PyObject * +_curses_tigetflag(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + const char *capname; + + if (!PyArg_Parse(arg, "s:tigetflag", &capname)) { + goto exit; + } + return_value = _curses_tigetflag_impl(module, capname); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_tigetnum__doc__, +"tigetnum($module, capname, /)\n" +"--\n" +"\n" +"Return the value of the numeric capability.\n" +"\n" +" capname\n" +" The terminfo capability name.\n" +"\n" +"The value -2 is returned if capname is not a numeric capability, or -1 if\n" +"it is canceled or absent from the terminal description."); + +#define _CURSES_TIGETNUM_METHODDEF \ + {"tigetnum", (PyCFunction)_curses_tigetnum, METH_O, _curses_tigetnum__doc__}, + +static PyObject * +_curses_tigetnum_impl(PyObject *module, const char *capname); + +static PyObject * +_curses_tigetnum(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + const char *capname; + + if (!PyArg_Parse(arg, "s:tigetnum", &capname)) { + goto exit; + } + return_value = _curses_tigetnum_impl(module, capname); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_tigetstr__doc__, +"tigetstr($module, capname, /)\n" +"--\n" +"\n" +"Return the value of the string capability.\n" +"\n" +" capname\n" +" The terminfo capability name.\n" +"\n" +"None is returned if capname is not a string capability, or is canceled or\n" +"absent from the terminal description."); + +#define _CURSES_TIGETSTR_METHODDEF \ + {"tigetstr", (PyCFunction)_curses_tigetstr, METH_O, _curses_tigetstr__doc__}, + +static PyObject * +_curses_tigetstr_impl(PyObject *module, const char *capname); + +static PyObject * +_curses_tigetstr(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + const char *capname; + + if (!PyArg_Parse(arg, "s:tigetstr", &capname)) { + goto exit; + } + return_value = _curses_tigetstr_impl(module, capname); + +exit: + return return_value; +} + +PyDoc_STRVAR(_curses_tparm__doc__, +"tparm($module, str, i1=0, i2=0, i3=0, i4=0, i5=0, i6=0, i7=0, i8=0,\n" +" i9=0, /)\n" +"--\n" +"\n" +"Instantiate the specified byte string with the supplied parameters.\n" +"\n" +" str\n" +" Parameterized byte string obtained from the terminfo database."); + +#define _CURSES_TPARM_METHODDEF \ + {"tparm", (PyCFunction)_curses_tparm, METH_FASTCALL, _curses_tparm__doc__}, + +static PyObject * +_curses_tparm_impl(PyObject *module, const char *str, int i1, int i2, int i3, + int i4, int i5, int i6, int i7, int i8, int i9); + +static PyObject * +_curses_tparm(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + const char *str; + int i1 = 0; + int i2 = 0; + int i3 = 0; + int i4 = 0; + int i5 = 0; + int i6 = 0; + int i7 = 0; + int i8 = 0; + int i9 = 0; + + if (!_PyArg_ParseStack(args, nargs, "y|iiiiiiiii:tparm", + &str, &i1, &i2, &i3, &i4, &i5, &i6, &i7, &i8, &i9)) { + goto exit; + } + return_value = _curses_tparm_impl(module, str, i1, i2, i3, i4, i5, i6, i7, i8, i9); + +exit: + return return_value; +} + +#if defined(HAVE_CURSES_TYPEAHEAD) + +PyDoc_STRVAR(_curses_typeahead__doc__, +"typeahead($module, fd, /)\n" +"--\n" +"\n" +"Specify that the file descriptor fd be used for typeahead checking.\n" +"\n" +" fd\n" +" File descriptor.\n" +"\n" +"If fd is -1, then no typeahead checking is done."); + +#define _CURSES_TYPEAHEAD_METHODDEF \ + {"typeahead", (PyCFunction)_curses_typeahead, METH_O, _curses_typeahead__doc__}, + +static PyObject * +_curses_typeahead_impl(PyObject *module, int fd); + +static PyObject * +_curses_typeahead(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int fd; + + if (!PyArg_Parse(arg, "i:typeahead", &fd)) { + goto exit; + } + return_value = _curses_typeahead_impl(module, fd); + +exit: + return return_value; +} + +#endif /* defined(HAVE_CURSES_TYPEAHEAD) */ + +PyDoc_STRVAR(_curses_unctrl__doc__, +"unctrl($module, ch, /)\n" +"--\n" +"\n" +"Return a string which is a printable representation of the character ch.\n" +"\n" +"Control characters are displayed as a caret followed by the character,\n" +"for example as ^C. Printing characters are left as they are."); + +#define _CURSES_UNCTRL_METHODDEF \ + {"unctrl", (PyCFunction)_curses_unctrl, METH_O, _curses_unctrl__doc__}, + +PyDoc_STRVAR(_curses_ungetch__doc__, +"ungetch($module, ch, /)\n" +"--\n" +"\n" +"Push ch so the next getch() will return it."); + +#define _CURSES_UNGETCH_METHODDEF \ + {"ungetch", (PyCFunction)_curses_ungetch, METH_O, _curses_ungetch__doc__}, + +#if defined(HAVE_NCURSESW) + +PyDoc_STRVAR(_curses_unget_wch__doc__, +"unget_wch($module, ch, /)\n" +"--\n" +"\n" +"Push ch so the next get_wch() will return it."); + +#define _CURSES_UNGET_WCH_METHODDEF \ + {"unget_wch", (PyCFunction)_curses_unget_wch, METH_O, _curses_unget_wch__doc__}, + +#endif /* defined(HAVE_NCURSESW) */ + +#if defined(HAVE_CURSES_USE_ENV) + +PyDoc_STRVAR(_curses_use_env__doc__, +"use_env($module, flag, /)\n" +"--\n" +"\n" +"Use environment variables LINES and COLUMNS.\n" +"\n" +"If used, this function should be called before initscr() or newterm() are\n" +"called.\n" +"\n" +"When flag is False, the values of lines and columns specified in the terminfo\n" +"database will be used, even if environment variables LINES and COLUMNS (used\n" +"by default) are set, or if curses is running in a window (in which case\n" +"default behavior would be to use the window size if LINES and COLUMNS are\n" +"not set)."); + +#define _CURSES_USE_ENV_METHODDEF \ + {"use_env", (PyCFunction)_curses_use_env, METH_O, _curses_use_env__doc__}, + +static PyObject * +_curses_use_env_impl(PyObject *module, int flag); + +static PyObject * +_curses_use_env(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + int flag; + + if (!PyArg_Parse(arg, "i:use_env", &flag)) { + goto exit; + } + return_value = _curses_use_env_impl(module, flag); + +exit: + return return_value; +} + +#endif /* defined(HAVE_CURSES_USE_ENV) */ + +#if !defined(STRICT_SYSV_CURSES) + +PyDoc_STRVAR(_curses_use_default_colors__doc__, +"use_default_colors($module, /)\n" +"--\n" +"\n" +"Allow use of default values for colors on terminals supporting this feature.\n" +"\n" +"Use this to support transparency in your application. The default color\n" +"is assigned to the color number -1."); + +#define _CURSES_USE_DEFAULT_COLORS_METHODDEF \ + {"use_default_colors", (PyCFunction)_curses_use_default_colors, METH_NOARGS, _curses_use_default_colors__doc__}, + +static PyObject * +_curses_use_default_colors_impl(PyObject *module); + +static PyObject * +_curses_use_default_colors(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _curses_use_default_colors_impl(module); +} + +#endif /* !defined(STRICT_SYSV_CURSES) */ + +#ifndef _CURSES_WINDOW_ENCLOSE_METHODDEF + #define _CURSES_WINDOW_ENCLOSE_METHODDEF +#endif /* !defined(_CURSES_WINDOW_ENCLOSE_METHODDEF) */ + +#ifndef _CURSES_WINDOW_GET_WCH_METHODDEF + #define _CURSES_WINDOW_GET_WCH_METHODDEF +#endif /* !defined(_CURSES_WINDOW_GET_WCH_METHODDEF) */ + +#ifndef _CURSES_WINDOW_NOUTREFRESH_METHODDEF + #define _CURSES_WINDOW_NOUTREFRESH_METHODDEF +#endif /* !defined(_CURSES_WINDOW_NOUTREFRESH_METHODDEF) */ + +#ifndef _CURSES_FILTER_METHODDEF + #define _CURSES_FILTER_METHODDEF +#endif /* !defined(_CURSES_FILTER_METHODDEF) */ + +#ifndef _CURSES_GETSYX_METHODDEF + #define _CURSES_GETSYX_METHODDEF +#endif /* !defined(_CURSES_GETSYX_METHODDEF) */ + +#ifndef _CURSES_GETMOUSE_METHODDEF + #define _CURSES_GETMOUSE_METHODDEF +#endif /* !defined(_CURSES_GETMOUSE_METHODDEF) */ + +#ifndef _CURSES_UNGETMOUSE_METHODDEF + #define _CURSES_UNGETMOUSE_METHODDEF +#endif /* !defined(_CURSES_UNGETMOUSE_METHODDEF) */ + +#ifndef _CURSES_HAS_KEY_METHODDEF + #define _CURSES_HAS_KEY_METHODDEF +#endif /* !defined(_CURSES_HAS_KEY_METHODDEF) */ + +#ifndef _CURSES_IS_TERM_RESIZED_METHODDEF + #define _CURSES_IS_TERM_RESIZED_METHODDEF +#endif /* !defined(_CURSES_IS_TERM_RESIZED_METHODDEF) */ + +#ifndef _CURSES_MOUSEINTERVAL_METHODDEF + #define _CURSES_MOUSEINTERVAL_METHODDEF +#endif /* !defined(_CURSES_MOUSEINTERVAL_METHODDEF) */ + +#ifndef _CURSES_MOUSEMASK_METHODDEF + #define _CURSES_MOUSEMASK_METHODDEF +#endif /* !defined(_CURSES_MOUSEMASK_METHODDEF) */ + +#ifndef _CURSES_UPDATE_LINES_COLS_METHODDEF + #define _CURSES_UPDATE_LINES_COLS_METHODDEF +#endif /* !defined(_CURSES_UPDATE_LINES_COLS_METHODDEF) */ + +#ifndef _CURSES_RESIZETERM_METHODDEF + #define _CURSES_RESIZETERM_METHODDEF +#endif /* !defined(_CURSES_RESIZETERM_METHODDEF) */ + +#ifndef _CURSES_RESIZE_TERM_METHODDEF + #define _CURSES_RESIZE_TERM_METHODDEF +#endif /* !defined(_CURSES_RESIZE_TERM_METHODDEF) */ + +#ifndef _CURSES_SETSYX_METHODDEF + #define _CURSES_SETSYX_METHODDEF +#endif /* !defined(_CURSES_SETSYX_METHODDEF) */ + +#ifndef _CURSES_TYPEAHEAD_METHODDEF + #define _CURSES_TYPEAHEAD_METHODDEF +#endif /* !defined(_CURSES_TYPEAHEAD_METHODDEF) */ + +#ifndef _CURSES_UNGET_WCH_METHODDEF + #define _CURSES_UNGET_WCH_METHODDEF +#endif /* !defined(_CURSES_UNGET_WCH_METHODDEF) */ + +#ifndef _CURSES_USE_ENV_METHODDEF + #define _CURSES_USE_ENV_METHODDEF +#endif /* !defined(_CURSES_USE_ENV_METHODDEF) */ + +#ifndef _CURSES_USE_DEFAULT_COLORS_METHODDEF + #define _CURSES_USE_DEFAULT_COLORS_METHODDEF +#endif /* !defined(_CURSES_USE_DEFAULT_COLORS_METHODDEF) */ +/*[clinic end generated code: output=763ffe3abc3a97c7 input=a9049054013a1b77]*/ From solipsis at pitrou.net Thu May 10 05:07:59 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 10 May 2018 09:07:59 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=7 Message-ID: <20180510090759.1.3D97FF63F0E7EA37@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_collections leaked [0, 7, -7] memory blocks, sum=0 test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_fork leaked [0, -1, 2] memory blocks, sum=1 test_multiprocessing_forkserver leaked [2, -1, 1] memory blocks, sum=2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogOYS5Kn', '--timeout', '7200'] From webhook-mailer at python.org Thu May 10 09:38:54 2018 From: webhook-mailer at python.org (Nick Coghlan) Date: Thu, 10 May 2018 13:38:54 -0000 Subject: [Python-checkins] bpo-26701: Tweak the documentation for special methods in int(). (GH-6741) Message-ID: https://github.com/python/cpython/commit/df00f048250b9a07195b0e3b1c5c0161fdcc9db8 commit: df00f048250b9a07195b0e3b1c5c0161fdcc9db8 branch: master author: Serhiy Storchaka committer: Nick Coghlan date: 2018-05-10T23:38:44+10:00 summary: bpo-26701: Tweak the documentation for special methods in int(). (GH-6741) files: M Doc/library/functions.rst diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index 2d15001bffa7..3b05a3a4ed32 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -671,8 +671,8 @@ are always available. They are listed here in alphabetical order. .. function:: hex(x) Convert an integer number to a lowercase hexadecimal string prefixed with - "0x". If x is not a Python :class:`int` object, it has to define an - __index__() method that returns an integer. Some examples: + "0x". If *x* is not a Python :class:`int` object, it has to define an + :meth:`__index__` method that returns an integer. Some examples: >>> hex(255) '0xff' @@ -730,12 +730,10 @@ are always available. They are listed here in alphabetical order. int(x, base=10) Return an integer object constructed from a number or string *x*, or return - ``0`` if no arguments are given. If *x* is a number, return - :meth:`x.__int__() `. If *x* defines - :meth:`x.__trunc__() ` but not - :meth:`x.__int__() `, then return - :meth:`x.__trunc__() `. For floating point numbers, - this truncates towards zero. + ``0`` if no arguments are given. If *x* defines :meth:`__int__`, + ``int(x)`` returns ``x.__int__()``. If *x* defines :meth:`__trunc__`, + it returns ``x.__trunc__()``. + For floating point numbers, this truncates towards zero. If *x* is not a number or if *base* is given, then *x* must be a string, :class:`bytes`, or :class:`bytearray` instance representing an :ref:`integer From webhook-mailer at python.org Thu May 10 10:38:10 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 10 May 2018 14:38:10 -0000 Subject: [Python-checkins] bpo-26701: Tweak the documentation for special methods in int(). (GH-6741) Message-ID: https://github.com/python/cpython/commit/22df4187c3882c6ec67180902e1151e65b03aee0 commit: 22df4187c3882c6ec67180902e1151e65b03aee0 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-05-10T07:38:06-07:00 summary: bpo-26701: Tweak the documentation for special methods in int(). (GH-6741) (cherry picked from commit df00f048250b9a07195b0e3b1c5c0161fdcc9db8) Co-authored-by: Serhiy Storchaka files: M Doc/library/functions.rst diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index 2d15001bffa7..3b05a3a4ed32 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -671,8 +671,8 @@ are always available. They are listed here in alphabetical order. .. function:: hex(x) Convert an integer number to a lowercase hexadecimal string prefixed with - "0x". If x is not a Python :class:`int` object, it has to define an - __index__() method that returns an integer. Some examples: + "0x". If *x* is not a Python :class:`int` object, it has to define an + :meth:`__index__` method that returns an integer. Some examples: >>> hex(255) '0xff' @@ -730,12 +730,10 @@ are always available. They are listed here in alphabetical order. int(x, base=10) Return an integer object constructed from a number or string *x*, or return - ``0`` if no arguments are given. If *x* is a number, return - :meth:`x.__int__() `. If *x* defines - :meth:`x.__trunc__() ` but not - :meth:`x.__int__() `, then return - :meth:`x.__trunc__() `. For floating point numbers, - this truncates towards zero. + ``0`` if no arguments are given. If *x* defines :meth:`__int__`, + ``int(x)`` returns ``x.__int__()``. If *x* defines :meth:`__trunc__`, + it returns ``x.__trunc__()``. + For floating point numbers, this truncates towards zero. If *x* is not a number or if *base* is given, then *x* must be a string, :class:`bytes`, or :class:`bytearray` instance representing an :ref:`integer From webhook-mailer at python.org Thu May 10 10:38:23 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 10 May 2018 14:38:23 -0000 Subject: [Python-checkins] bpo-26701: Tweak the documentation for special methods in int(). (GH-6741) Message-ID: https://github.com/python/cpython/commit/7488c79b600cd173b0ccea13adb567d078e7b835 commit: 7488c79b600cd173b0ccea13adb567d078e7b835 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-05-10T07:38:20-07:00 summary: bpo-26701: Tweak the documentation for special methods in int(). (GH-6741) (cherry picked from commit df00f048250b9a07195b0e3b1c5c0161fdcc9db8) Co-authored-by: Serhiy Storchaka files: M Doc/library/functions.rst diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index 56c1377d1734..94675c1aa83b 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -657,8 +657,8 @@ are always available. They are listed here in alphabetical order. .. function:: hex(x) Convert an integer number to a lowercase hexadecimal string prefixed with - "0x". If x is not a Python :class:`int` object, it has to define an - __index__() method that returns an integer. Some examples: + "0x". If *x* is not a Python :class:`int` object, it has to define an + :meth:`__index__` method that returns an integer. Some examples: >>> hex(255) '0xff' @@ -716,12 +716,10 @@ are always available. They are listed here in alphabetical order. int(x, base=10) Return an integer object constructed from a number or string *x*, or return - ``0`` if no arguments are given. If *x* is a number, return - :meth:`x.__int__() `. If *x* defines - :meth:`x.__trunc__() ` but not - :meth:`x.__int__() `, then return - :meth:`x.__trunc__() `. For floating point numbers, - this truncates towards zero. + ``0`` if no arguments are given. If *x* defines :meth:`__int__`, + ``int(x)`` returns ``x.__int__()``. If *x* defines :meth:`__trunc__`, + it returns ``x.__trunc__()``. + For floating point numbers, this truncates towards zero. If *x* is not a number or if *base* is given, then *x* must be a string, :class:`bytes`, or :class:`bytearray` instance representing an :ref:`integer From lp_benchmark_robot at intel.com Thu May 10 20:58:50 2018 From: lp_benchmark_robot at intel.com (lp_benchmark_robot at intel.com) Date: Thu, 10 May 2018 17:58:50 -0700 Subject: [Python-checkins] [65 flat] Results for Python (master branch) 2018-05-10 Message-ID: <2a0a62d0-fb4a-4275-84b0-d11f3778171a@orsmsx103.amr.corp.intel.com> Results for project python/master, build date: 2018-05-10 03:03:05-07:00. - commit: b00854c - previous commit: 8cf4b34 - revision date: 2018-05-10 11:27:23+03:00 - environment: Broadwell-EP - cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores, stepping 1, LLC 55 MB - mem: 128 GB - os: Ubuntu 16.04.2 LTS - kernel: 4.4.0-62-generic x86_64 GNU/Linux Baseline results were generated using release v3.6.0, with hash 5c4568a from 2016-12-22 23:38:47+00:00. +-----+------------------------+--------+------------+------------+------------+ | | |relative|change since|change since|current rev | | | benchmark|std_dev*| last run | baseline |run with PGO| +-----+------------------------+--------+------------+------------+------------+ | :-| | 2to3| 0.598% | +0.287% | +9.731% | +6.151% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method| 0.974% | +0.280% | +24.027% | +13.475% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_slots| 2.022% | -0.240% | +25.583% | +12.067% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_unknown| 0.624% | +0.387% | +22.735% | +12.745% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_simple| 1.961% | +0.119% | +10.932% | +13.851% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chameleon| 2.112% | -0.288% | +11.859% | +9.654% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chaos| 0.633% | +0.361% | +9.484% | +8.736% | +-----+------------------------+--------+------------+------------+------------+ | :-| | crypto_pyaes| 0.806% | +0.197% | -0.005% | +8.106% | +-----+------------------------+--------+------------+------------+------------+ | :-| | deltablue| 1.544% | +0.342% | +13.813% | +14.040% | +-----+------------------------+--------+------------+------------+------------+ | :-| | django_template| 2.816% | -1.200% | +21.156% | +12.863% | +-----+------------------------+--------+------------+------------+------------+ | :-| | dulwich_log| 0.934% | -0.011% | +5.552% | +6.745% | +-----+------------------------+--------+------------+------------+------------+ | :-| | fannkuch| 0.333% | +0.316% | +7.407% | +4.274% | +-----+------------------------+--------+------------+------------+------------+ | :-| | float| 1.116% | -0.119% | +2.300% | +7.525% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_text| 1.110% | -0.019% | +14.405% | +9.546% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_xml| 1.473% | +0.293% | +11.424% | +9.403% | +-----+------------------------+--------+------------+------------+------------+ | :-| | go| 6.179% | +0.158% | +5.197% | +10.497% | +-----+------------------------+--------+------------+------------+------------+ | :-| | hexiom| 0.443% | +0.035% | +11.890% | +10.735% | +-----+------------------------+--------+------------+------------+------------+ | :-| | html5lib| 2.825% | +0.394% | +12.509% | +9.851% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_dumps| 1.665% | +0.005% | +3.114% | +7.871% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_loads| 5.703% | +0.319% | -4.820% | +15.373% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_format| 1.624% | +0.534% | +17.658% | +13.080% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_silent| 2.767% | +0.119% | +47.914% | +12.202% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_simple| 1.516% | +1.037% | +13.480% | +12.649% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mako| 0.429% | +0.238% | +17.345% | +13.656% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mdp| 7.072% | -0.236% | +0.175% | +18.538% | +-----+------------------------+--------+------------+------------+------------+ | :-| | meteor_contest| 0.619% | +0.082% | +4.639% | +6.274% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nbody| 1.365% | -0.263% | +0.688% | -1.214% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nqueens| 0.677% | +0.158% | +5.840% | +6.350% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pathlib| 1.441% | -0.777% | -0.026% | +11.083% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle| 4.081% | -0.445% | -1.433% | +23.124% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_dict| 0.435% | +0.032% | +7.497% | +14.253% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_list| 0.919% | +0.251% | +6.820% | +17.060% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_pure_python| 5.079% | -0.360% | +11.234% | +10.611% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pidigits| 0.204% | -0.010% | +0.028% | +9.506% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup| 0.128% | +0.163% | +18.944% | +4.993% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup_no_site| 0.086% | +0.106% | +5.901% | +5.289% | +-----+------------------------+--------+------------+------------+------------+ | :-| | raytrace| 0.908% | -0.062% | +9.973% | +13.463% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_compile| 4.943% | -0.040% | +5.953% | +10.831% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_dna| 0.443% | -0.293% | -0.863% | +12.444% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_effbot| 2.383% | +0.511% | -4.245% | +6.772% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_v8| 2.261% | -0.600% | +5.985% | +4.492% | +-----+------------------------+--------+------------+------------+------------+ | :-| | richards| 1.334% | +0.369% | +9.641% | +14.661% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_fft| 1.973% | -0.253% | -2.457% | +3.546% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_lu| 3.164% | +0.571% | +22.958% | +11.584% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_monte_carlo| 2.019% | +0.107% | +5.243% | +5.724% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sor| 1.817% | +0.578% | +15.461% | +8.951% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sparse_mat_mult| 2.062% | -0.336% | -2.583% | -5.441% | +-----+------------------------+--------+------------+------------+------------+ | :-| | spectral_norm| 0.676% | +0.006% | +4.223% | +4.773% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_declarative| 1.693% | -0.202% | +7.853% | +5.420% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_imperative| 3.424% | +0.173% | +7.885% | +4.395% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlite_synth| 3.517% | +0.811% | +0.763% | +7.968% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_expand| 3.070% | +0.324% | +17.720% | +7.093% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_integrate| 1.478% | -0.117% | +18.280% | +6.378% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_str| 3.771% | +0.128% | +19.438% | +7.777% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_sum| 6.526% | -0.455% | +15.877% | +11.557% | +-----+------------------------+--------+------------+------------+------------+ | :-| | telco| 2.862% | -0.156% | +19.858% | +9.224% | +-----+------------------------+--------+------------+------------+------------+ | :-| | tornado_http| 0.891% | +0.331% | +7.596% | +4.755% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpack_sequence| 4.864% | -0.267% | +2.157% | +0.141% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle| 8.663% | -2.952% | +6.747% | +22.972% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_list| 0.746% | -0.077% | -3.396% | +15.623% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_pure_python| 1.553% | -0.197% | +7.688% | +7.620% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_generate| 0.935% | -0.111% | +2.479% | +11.103% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_iterparse| 1.840% | +0.283% | +4.016% | +8.022% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_parse| 3.377% | -0.495% | -7.749% | +10.127% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_process| 1.976% | -0.018% | +4.213% | +10.894% | +-----+------------------------+--------+------------+------------+------------+ * Relative Standard Deviation (Standard Deviation/Average) If this is not displayed properly please visit our results page here: http://languagesperformance.intel.com/65-flat-results-for-python-master-branch-2018-05-10 Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. From webhook-mailer at python.org Thu May 10 23:10:13 2018 From: webhook-mailer at python.org (Ivan Levkivskyi) Date: Fri, 11 May 2018 03:10:13 -0000 Subject: [Python-checkins] Fix a bug in Generic.__new__ (GH-6758) Message-ID: https://github.com/python/cpython/commit/b551e9f0ff25018a5606465003e2c51c04f693a3 commit: b551e9f0ff25018a5606465003e2c51c04f693a3 branch: master author: Ivan Levkivskyi committer: GitHub date: 2018-05-10T23:10:10-04:00 summary: Fix a bug in Generic.__new__ (GH-6758) files: 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 46bab5eba6db..314716cd7de3 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -1367,6 +1367,9 @@ def test_new_no_args(self): class A(Generic[T]): pass + with self.assertRaises(TypeError): + A('foo') + class B: def __new__(cls): # call object diff --git a/Lib/typing.py b/Lib/typing.py index 89b73db15837..8025dfd93262 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -836,7 +836,7 @@ def __new__(cls, *args, **kwds): if cls is Generic: raise TypeError("Type Generic cannot be instantiated; " "it can be used only as a base class") - if super().__new__ is object.__new__: + if super().__new__ is object.__new__ and cls.__init__ is not object.__init__: obj = super().__new__(cls) else: obj = super().__new__(cls, *args, **kwds) From webhook-mailer at python.org Thu May 10 23:15:17 2018 From: webhook-mailer at python.org (Ivan Levkivskyi) Date: Fri, 11 May 2018 03:15:17 -0000 Subject: [Python-checkins] Backport recent typing updates (GH-6759) Message-ID: https://github.com/python/cpython/commit/308dbe03887a60a192860bc533af15e7520169a6 commit: 308dbe03887a60a192860bc533af15e7520169a6 branch: 3.6 author: Ivan Levkivskyi committer: GitHub date: 2018-05-10T23:15:14-04:00 summary: Backport recent typing updates (GH-6759) files: A Misc/NEWS.d/next/Library/2018-05-10-14-51-19.bpo-28556.y3zK6I.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 fe5247c26027..4843d6faf704 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -1310,6 +1310,74 @@ class D(C): with self.assertRaises(Exception): D[T] + def test_new_with_args(self): + + class A(Generic[T]): + pass + + class B: + def __new__(cls, arg): + # call object + obj = super().__new__(cls) + obj.arg = arg + return obj + + # mro: C, A, Generic, B, object + class C(A, B): + pass + + c = C('foo') + self.assertEqual(c.arg, 'foo') + + def test_new_with_args2(self): + + class A: + def __init__(self, arg): + self.from_a = arg + # call object + super().__init__() + + # mro: C, Generic, A, object + class C(Generic[T], A): + def __init__(self, arg): + self.from_c = arg + # call Generic + super().__init__(arg) + + c = C('foo') + self.assertEqual(c.from_a, 'foo') + self.assertEqual(c.from_c, 'foo') + + def test_new_no_args(self): + + class A(Generic[T]): + pass + + with self.assertRaises(TypeError): + A('foo') + + class B: + def __new__(cls): + # call object + obj = super().__new__(cls) + obj.from_b = 'b' + return obj + + # mro: C, A, Generic, B, object + class C(A, B): + def __init__(self, arg): + self.arg = arg + + def __new__(cls, arg): + # call A + obj = super().__new__(cls) + obj.from_c = 'c' + return obj + + c = C('foo') + self.assertEqual(c.arg, 'foo') + self.assertEqual(c.from_b, 'b') + self.assertEqual(c.from_c, 'c') class ClassVarTests(BaseTestCase): @@ -1739,6 +1807,8 @@ def test_get_type_hints_classes(self): self.assertEqual(gth(HasForeignBaseClass), {'some_xrepr': XRepr, 'other_a': mod_generics_cache.A, 'some_b': mod_generics_cache.B}) + self.assertEqual(gth(XRepr.__new__), + {'x': int, 'y': int}) self.assertEqual(gth(mod_generics_cache.B), {'my_inner_a1': mod_generics_cache.B.A, 'my_inner_a2': mod_generics_cache.B.A, diff --git a/Lib/typing.py b/Lib/typing.py index b5564cc29a2d..f2b6aaf3a927 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -1181,10 +1181,18 @@ def _generic_new(base_cls, cls, *args, **kwds): # Assure type is erased on instantiation, # but attempt to store it in __orig_class__ if cls.__origin__ is None: - return base_cls.__new__(cls) + if (base_cls.__new__ is object.__new__ and + cls.__init__ is not object.__init__): + return base_cls.__new__(cls) + else: + return base_cls.__new__(cls, *args, **kwds) else: origin = cls._gorg - obj = base_cls.__new__(origin) + if (base_cls.__new__ is object.__new__ and + cls.__init__ is not object.__init__): + obj = base_cls.__new__(origin) + else: + obj = base_cls.__new__(origin, *args, **kwds) try: obj.__orig_class__ = cls except AttributeError: @@ -2146,6 +2154,7 @@ def __new__(cls, typename, bases, ns): "follow default field(s) {default_names}" .format(field_name=field_name, default_names=', '.join(defaults_dict.keys()))) + nm_tpl.__new__.__annotations__ = collections.OrderedDict(types) nm_tpl.__new__.__defaults__ = tuple(defaults) nm_tpl._field_defaults = defaults_dict # update from user namespace without overriding special namedtuple attributes diff --git a/Misc/NEWS.d/next/Library/2018-05-10-14-51-19.bpo-28556.y3zK6I.rst b/Misc/NEWS.d/next/Library/2018-05-10-14-51-19.bpo-28556.y3zK6I.rst new file mode 100644 index 000000000000..8ed4658211fb --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-10-14-51-19.bpo-28556.y3zK6I.rst @@ -0,0 +1,3 @@ +Minor fixes in typing module: add annotations to ``NamedTuple.__new__``, +pass ``*args`` and ``**kwds`` in ``Generic.__new__``. Original PRs by +Paulius ?arka and Chad Dombrova. From webhook-mailer at python.org Thu May 10 23:30:58 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 11 May 2018 03:30:58 -0000 Subject: [Python-checkins] Fix a bug in Generic.__new__ (GH-6758) Message-ID: https://github.com/python/cpython/commit/c5444b355695755035d4a5cadc0467e850bb04c2 commit: c5444b355695755035d4a5cadc0467e850bb04c2 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-05-10T20:30:47-07:00 summary: Fix a bug in Generic.__new__ (GH-6758) (cherry picked from commit b551e9f0ff25018a5606465003e2c51c04f693a3) Co-authored-by: Ivan Levkivskyi files: 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 46bab5eba6db..314716cd7de3 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -1367,6 +1367,9 @@ def test_new_no_args(self): class A(Generic[T]): pass + with self.assertRaises(TypeError): + A('foo') + class B: def __new__(cls): # call object diff --git a/Lib/typing.py b/Lib/typing.py index 89b73db15837..8025dfd93262 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -836,7 +836,7 @@ def __new__(cls, *args, **kwds): if cls is Generic: raise TypeError("Type Generic cannot be instantiated; " "it can be used only as a base class") - if super().__new__ is object.__new__: + if super().__new__ is object.__new__ and cls.__init__ is not object.__init__: obj = super().__new__(cls) else: obj = super().__new__(cls, *args, **kwds) From webhook-mailer at python.org Fri May 11 01:40:53 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Fri, 11 May 2018 05:40:53 -0000 Subject: [Python-checkins] bpo-33455: Pass os.environ in test_posix::test_specify_environment. (GH-6753) Message-ID: https://github.com/python/cpython/commit/7ec8f28656ea9d84048e9b5655375c6a74a59f53 commit: 7ec8f28656ea9d84048e9b5655375c6a74a59f53 branch: master author: Miro Hron?ok committer: Serhiy Storchaka date: 2018-05-11T08:40:43+03:00 summary: bpo-33455: Pass os.environ in test_posix::test_specify_environment. (GH-6753) Pass os.environ's copy to new process created at test_posix: test_specify_environment. Otherwise important variables such as LD_LIBRARY_PATH are not set and the child process might not work at all in an environment where such variables are required for Python to function. files: M Lib/test/test_posix.py diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py index b94da3f45a2c..ecf3e93eb048 100644 --- a/Lib/test/test_posix.py +++ b/Lib/test/test_posix.py @@ -1462,7 +1462,7 @@ def test_specify_environment(self): """ pid = posix.posix_spawn(sys.executable, [sys.executable, '-c', script], - {'foo': 'bar'}) + {**os.environ, 'foo': 'bar'}) self.assertEqual(os.waitpid(pid, 0), (pid, 0)) with open(envfile) as f: self.assertEqual(f.read(), 'bar') From webhook-mailer at python.org Fri May 11 02:01:47 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 11 May 2018 06:01:47 -0000 Subject: [Python-checkins] bpo-33455: Pass os.environ in test_posix::test_specify_environment. (GH-6753) Message-ID: https://github.com/python/cpython/commit/6e9456e4f6123b13750a10e6ae2eba83504d2f1a commit: 6e9456e4f6123b13750a10e6ae2eba83504d2f1a branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-05-10T23:01:44-07:00 summary: bpo-33455: Pass os.environ in test_posix::test_specify_environment. (GH-6753) Pass os.environ's copy to new process created at test_posix: test_specify_environment. Otherwise important variables such as LD_LIBRARY_PATH are not set and the child process might not work at all in an environment where such variables are required for Python to function. (cherry picked from commit 7ec8f28656ea9d84048e9b5655375c6a74a59f53) Co-authored-by: Miro Hron?ok files: M Lib/test/test_posix.py diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py index b94da3f45a2c..ecf3e93eb048 100644 --- a/Lib/test/test_posix.py +++ b/Lib/test/test_posix.py @@ -1462,7 +1462,7 @@ def test_specify_environment(self): """ pid = posix.posix_spawn(sys.executable, [sys.executable, '-c', script], - {'foo': 'bar'}) + {**os.environ, 'foo': 'bar'}) self.assertEqual(os.waitpid(pid, 0), (pid, 0)) with open(envfile) as f: self.assertEqual(f.read(), 'bar') From solipsis at pitrou.net Fri May 11 05:10:07 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 11 May 2018 09:10:07 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=4 Message-ID: <20180511091007.1.2D1B9B7E9D7DA6C3@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_collections leaked [0, 7, -7] memory blocks, sum=0 test_functools leaked [0, 3, 1] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogcugkTk', '--timeout', '7200'] From lp_benchmark_robot at intel.com Fri May 11 19:28:04 2018 From: lp_benchmark_robot at intel.com (lp_benchmark_robot at intel.com) Date: Fri, 11 May 2018 16:28:04 -0700 Subject: [Python-checkins] [65 flat] Results for Python (master branch) 2018-05-11 Message-ID: <91afcc5b-0a83-4b07-b330-a508693fe7e8@orsmsx156.amr.corp.intel.com> Results for project python/master, build date: 2018-05-11 03:03:34-07:00. - commit: 7ec8f28 - previous commit: b00854c - revision date: 2018-05-11 08:40:43+03:00 - environment: Broadwell-EP - cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores, stepping 1, LLC 55 MB - mem: 128 GB - os: Ubuntu 16.04.2 LTS - kernel: 4.4.0-62-generic x86_64 GNU/Linux Baseline results were generated using release v3.6.0, with hash 5c4568a from 2016-12-22 23:38:47+00:00. +-----+------------------------+--------+------------+------------+------------+ | | |relative|change since|change since|current rev | | | benchmark|std_dev*| last run | baseline |run with PGO| +-----+------------------------+--------+------------+------------+------------+ | :-| | 2to3| 0.517% | -0.067% | +9.670% | +6.341% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method| 0.584% | +0.285% | +24.243% | +13.628% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_slots| 2.528% | -0.321% | +25.344% | +12.605% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_unknown| 0.745% | -0.068% | +22.682% | +11.762% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_simple| 3.179% | -0.194% | +10.759% | +14.010% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chameleon| 1.911% | +0.481% | +12.283% | +9.748% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chaos| 0.750% | -0.188% | +9.313% | +8.640% | +-----+------------------------+--------+------------+------------+------------+ | :-| | crypto_pyaes| 0.705% | +0.021% | +0.016% | +7.700% | +-----+------------------------+--------+------------+------------+------------+ | :-| | deltablue| 1.713% | -0.507% | +13.376% | +13.137% | +-----+------------------------+--------+------------+------------+------------+ | :-| | django_template| 2.764% | +0.185% | +21.302% | +11.959% | +-----+------------------------+--------+------------+------------+------------+ | :-| | dulwich_log| 1.085% | -0.310% | +5.259% | +6.954% | +-----+------------------------+--------+------------+------------+------------+ | :-| | fannkuch| 0.380% | -0.070% | +7.343% | +5.530% | +-----+------------------------+--------+------------+------------+------------+ | :-| | float| 1.113% | +0.337% | +2.629% | +5.535% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_text| 1.044% | +0.238% | +14.609% | +9.378% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_xml| 1.618% | +0.667% | +12.015% | +9.328% | +-----+------------------------+--------+------------+------------+------------+ | :-| | go| 5.815% | +0.394% | +5.570% | +10.791% | +-----+------------------------+--------+------------+------------+------------+ | :-| | hexiom| 0.499% | -0.055% | +11.842% | +10.557% | +-----+------------------------+--------+------------+------------+------------+ | :-| | html5lib| 2.996% | -0.398% | +12.161% | +9.441% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_dumps| 1.391% | +0.454% | +3.554% | +8.207% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_loads| 6.434% | -0.247% | -5.079% | +14.584% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_format| 1.156% | -0.068% | +17.602% | +11.528% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_silent| 2.921% | -0.867% | +47.463% | +13.067% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_simple| 1.622% | -0.783% | +12.803% | +11.109% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mako| 0.771% | -0.070% | +17.288% | +14.118% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mdp| 5.920% | +1.548% | +1.719% | +16.992% | +-----+------------------------+--------+------------+------------+------------+ | :-| | meteor_contest| 0.510% | -0.012% | +4.628% | +7.551% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nbody| 1.288% | +0.193% | +0.879% | +0.051% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nqueens| 0.488% | -0.118% | +5.729% | +5.737% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pathlib| 1.997% | +0.715% | +0.689% | +9.599% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle| 3.711% | +0.262% | -1.168% | +21.231% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_dict| 0.602% | -0.115% | +7.391% | +14.180% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_list| 0.799% | +0.515% | +7.300% | +15.281% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_pure_python| 3.572% | +1.178% | +12.280% | +10.007% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pidigits| 0.126% | +0.026% | +0.054% | +10.583% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup| 0.111% | -0.067% | +18.890% | +5.045% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup_no_site| 0.091% | +0.063% | +5.960% | +5.277% | +-----+------------------------+--------+------------+------------+------------+ | :-| | raytrace| 1.246% | -0.243% | +9.754% | +13.136% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_compile| 4.888% | +0.407% | +6.336% | +7.120% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_dna| 0.616% | +0.017% | -0.846% | +10.662% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_effbot| 2.508% | -0.705% | -4.980% | +5.075% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_v8| 2.203% | -0.371% | +5.637% | +7.816% | +-----+------------------------+--------+------------+------------+------------+ | :-| | richards| 1.846% | -0.297% | +9.373% | +14.929% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_fft| 0.497% | +0.205% | -2.246% | +5.441% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_lu| 4.298% | +0.084% | +23.022% | +12.241% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_monte_carlo| 1.837% | +0.118% | +5.355% | +5.274% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sor| 1.641% | -0.448% | +15.082% | +6.289% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sparse_mat_mult| 2.011% | -0.185% | -2.773% | +1.349% | +-----+------------------------+--------+------------+------------+------------+ | :-| | spectral_norm| 0.483% | +0.140% | +4.356% | +6.216% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_declarative| 1.728% | -0.050% | +7.807% | +5.308% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_imperative| 3.536% | +0.160% | +8.033% | +3.490% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlite_synth| 3.864% | -0.080% | +0.683% | +9.648% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_expand| 2.521% | +0.193% | +17.878% | +5.654% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_integrate| 1.295% | +0.369% | +18.581% | +5.545% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_str| 4.081% | -0.196% | +19.280% | +6.898% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_sum| 6.643% | +0.014% | +15.889% | +8.355% | +-----+------------------------+--------+------------+------------+------------+ | :-| | telco| 2.835% | +0.034% | +19.886% | +6.929% | +-----+------------------------+--------+------------+------------+------------+ | :-| | tornado_http| 0.985% | -0.155% | +7.453% | +4.297% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpack_sequence| 0.639% | +0.899% | +3.037% | -0.487% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle| 6.760% | +1.833% | +8.457% | +21.448% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_list| 2.250% | -0.347% | -3.755% | +18.366% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_pure_python| 2.933% | -0.540% | +7.190% | +8.256% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_generate| 1.307% | +0.066% | +2.544% | +12.744% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_iterparse| 2.070% | -0.077% | +3.942% | +7.395% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_parse| 3.324% | +0.763% | -6.927% | +10.026% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_process| 1.195% | +0.171% | +4.377% | +11.810% | +-----+------------------------+--------+------------+------------+------------+ * Relative Standard Deviation (Standard Deviation/Average) If this is not displayed properly please visit our results page here: http://languagesperformance.intel.com/65-flat-results-for-python-master-branch-2018-05-11 Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. From solipsis at pitrou.net Sat May 12 05:11:05 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 12 May 2018 09:11:05 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=10 Message-ID: <20180512091105.1.6EDE4E40E51B07B5@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_collections leaked [0, 0, 7] memory blocks, sum=7 test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_forkserver leaked [1, -2, 0] memory blocks, sum=-1 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogyvv1DD', '--timeout', '7200'] From solipsis at pitrou.net Sun May 13 05:09:54 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 13 May 2018 09:09:54 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=9 Message-ID: <20180513090954.1.7C24978D63EAC83E@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_collections leaked [7, 0, 0] memory blocks, sum=7 test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_forkserver leaked [0, 0, -2] memory blocks, sum=-2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogyOYFZ1', '--timeout', '7200'] From webhook-mailer at python.org Sun May 13 06:57:35 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sun, 13 May 2018 10:57:35 -0000 Subject: [Python-checkins] bpo-28055: Fix unaligned accesses in siphash24(). (GH-6123) Message-ID: https://github.com/python/cpython/commit/1e2ec8a996daec65d8d5a3d43b66a9909c6d0653 commit: 1e2ec8a996daec65d8d5a3d43b66a9909c6d0653 branch: master author: Rolf Eike Beer committer: Serhiy Storchaka date: 2018-05-13T13:57:31+03:00 summary: bpo-28055: Fix unaligned accesses in siphash24(). (GH-6123) The hash implementation casts the input pointer to uint64_t* and directly reads from this, which may cause unaligned accesses. Use memcpy() instead so this code will not crash with SIGBUS on sparc. https://bugs.gentoo.org/show_bug.cgi?id=636400 files: A Misc/NEWS.d/next/Core and Builtins/2018-04-25-20-44-42.bpo-28055.f49kfC.rst M Python/pyhash.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-04-25-20-44-42.bpo-28055.f49kfC.rst b/Misc/NEWS.d/next/Core and Builtins/2018-04-25-20-44-42.bpo-28055.f49kfC.rst new file mode 100644 index 000000000000..c7d849906fc9 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-04-25-20-44-42.bpo-28055.f49kfC.rst @@ -0,0 +1 @@ +Fix unaligned accesses in siphash24(). Patch by Rolf Eike Beer. diff --git a/Python/pyhash.c b/Python/pyhash.c index 9e6e594f441a..6fc12fde3fc7 100644 --- a/Python/pyhash.c +++ b/Python/pyhash.c @@ -366,7 +366,7 @@ static PyHash_FuncDef PyHash_Func = {fnv, "fnv", 8 * SIZEOF_PY_HASH_T, static uint64_t siphash24(uint64_t k0, uint64_t k1, const void *src, Py_ssize_t src_sz) { uint64_t b = (uint64_t)src_sz << 56; - const uint64_t *in = (uint64_t*)src; + const uint8_t *in = (uint8_t*)src; uint64_t v0 = k0 ^ 0x736f6d6570736575ULL; uint64_t v1 = k1 ^ 0x646f72616e646f6dULL; @@ -375,12 +375,13 @@ siphash24(uint64_t k0, uint64_t k1, const void *src, Py_ssize_t src_sz) { uint64_t t; uint8_t *pt; - uint8_t *m; while (src_sz >= 8) { - uint64_t mi = _le64toh(*in); - in += 1; - src_sz -= 8; + uint64_t mi; + memcpy(&mi, in, sizeof(mi)); + mi = _le64toh(mi); + in += sizeof(mi); + src_sz -= sizeof(mi); v3 ^= mi; DOUBLE_ROUND(v0,v1,v2,v3); v0 ^= mi; @@ -388,15 +389,14 @@ siphash24(uint64_t k0, uint64_t k1, const void *src, Py_ssize_t src_sz) { t = 0; pt = (uint8_t *)&t; - m = (uint8_t *)in; switch (src_sz) { - case 7: pt[6] = m[6]; /* fall through */ - case 6: pt[5] = m[5]; /* fall through */ - case 5: pt[4] = m[4]; /* fall through */ - case 4: memcpy(pt, m, sizeof(uint32_t)); break; - case 3: pt[2] = m[2]; /* fall through */ - case 2: pt[1] = m[1]; /* fall through */ - case 1: pt[0] = m[0]; /* fall through */ + case 7: pt[6] = in[6]; /* fall through */ + case 6: pt[5] = in[5]; /* fall through */ + case 5: pt[4] = in[4]; /* fall through */ + case 4: memcpy(pt, in, sizeof(uint32_t)); break; + case 3: pt[2] = in[2]; /* fall through */ + case 2: pt[1] = in[1]; /* fall through */ + case 1: pt[0] = in[0]; /* fall through */ } b |= _le64toh(t); From webhook-mailer at python.org Sun May 13 07:17:11 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sun, 13 May 2018 11:17:11 -0000 Subject: [Python-checkins] bpo-28055: Fix unaligned accesses in siphash24(). (GH-6123) Message-ID: https://github.com/python/cpython/commit/8ed545f6de37efdadbcf71c45bb8136b8cb9619d commit: 8ed545f6de37efdadbcf71c45bb8136b8cb9619d branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-05-13T04:17:07-07:00 summary: bpo-28055: Fix unaligned accesses in siphash24(). (GH-6123) The hash implementation casts the input pointer to uint64_t* and directly reads from this, which may cause unaligned accesses. Use memcpy() instead so this code will not crash with SIGBUS on sparc. https://bugs.gentoo.org/show_bug.cgi?id=636400 (cherry picked from commit 1e2ec8a996daec65d8d5a3d43b66a9909c6d0653) Co-authored-by: Rolf Eike Beer files: A Misc/NEWS.d/next/Core and Builtins/2018-04-25-20-44-42.bpo-28055.f49kfC.rst M Python/pyhash.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-04-25-20-44-42.bpo-28055.f49kfC.rst b/Misc/NEWS.d/next/Core and Builtins/2018-04-25-20-44-42.bpo-28055.f49kfC.rst new file mode 100644 index 000000000000..c7d849906fc9 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-04-25-20-44-42.bpo-28055.f49kfC.rst @@ -0,0 +1 @@ +Fix unaligned accesses in siphash24(). Patch by Rolf Eike Beer. diff --git a/Python/pyhash.c b/Python/pyhash.c index 9e6e594f441a..6fc12fde3fc7 100644 --- a/Python/pyhash.c +++ b/Python/pyhash.c @@ -366,7 +366,7 @@ static PyHash_FuncDef PyHash_Func = {fnv, "fnv", 8 * SIZEOF_PY_HASH_T, static uint64_t siphash24(uint64_t k0, uint64_t k1, const void *src, Py_ssize_t src_sz) { uint64_t b = (uint64_t)src_sz << 56; - const uint64_t *in = (uint64_t*)src; + const uint8_t *in = (uint8_t*)src; uint64_t v0 = k0 ^ 0x736f6d6570736575ULL; uint64_t v1 = k1 ^ 0x646f72616e646f6dULL; @@ -375,12 +375,13 @@ siphash24(uint64_t k0, uint64_t k1, const void *src, Py_ssize_t src_sz) { uint64_t t; uint8_t *pt; - uint8_t *m; while (src_sz >= 8) { - uint64_t mi = _le64toh(*in); - in += 1; - src_sz -= 8; + uint64_t mi; + memcpy(&mi, in, sizeof(mi)); + mi = _le64toh(mi); + in += sizeof(mi); + src_sz -= sizeof(mi); v3 ^= mi; DOUBLE_ROUND(v0,v1,v2,v3); v0 ^= mi; @@ -388,15 +389,14 @@ siphash24(uint64_t k0, uint64_t k1, const void *src, Py_ssize_t src_sz) { t = 0; pt = (uint8_t *)&t; - m = (uint8_t *)in; switch (src_sz) { - case 7: pt[6] = m[6]; /* fall through */ - case 6: pt[5] = m[5]; /* fall through */ - case 5: pt[4] = m[4]; /* fall through */ - case 4: memcpy(pt, m, sizeof(uint32_t)); break; - case 3: pt[2] = m[2]; /* fall through */ - case 2: pt[1] = m[1]; /* fall through */ - case 1: pt[0] = m[0]; /* fall through */ + case 7: pt[6] = in[6]; /* fall through */ + case 6: pt[5] = in[5]; /* fall through */ + case 5: pt[4] = in[4]; /* fall through */ + case 4: memcpy(pt, in, sizeof(uint32_t)); break; + case 3: pt[2] = in[2]; /* fall through */ + case 2: pt[1] = in[1]; /* fall through */ + case 1: pt[0] = in[0]; /* fall through */ } b |= _le64toh(t); From webhook-mailer at python.org Sun May 13 07:40:06 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sun, 13 May 2018 11:40:06 -0000 Subject: [Python-checkins] bpo-28055: Fix unaligned accesses in siphash24(). (GH-6123) Message-ID: https://github.com/python/cpython/commit/0d17e60b33aca1a4d151a8a2bd6eaa331f0ec658 commit: 0d17e60b33aca1a4d151a8a2bd6eaa331f0ec658 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-05-13T04:40:03-07:00 summary: bpo-28055: Fix unaligned accesses in siphash24(). (GH-6123) The hash implementation casts the input pointer to uint64_t* and directly reads from this, which may cause unaligned accesses. Use memcpy() instead so this code will not crash with SIGBUS on sparc. https://bugs.gentoo.org/show_bug.cgi?id=636400 (cherry picked from commit 1e2ec8a996daec65d8d5a3d43b66a9909c6d0653) Co-authored-by: Rolf Eike Beer files: A Misc/NEWS.d/next/Core and Builtins/2018-04-25-20-44-42.bpo-28055.f49kfC.rst M Python/pyhash.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-04-25-20-44-42.bpo-28055.f49kfC.rst b/Misc/NEWS.d/next/Core and Builtins/2018-04-25-20-44-42.bpo-28055.f49kfC.rst new file mode 100644 index 000000000000..c7d849906fc9 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-04-25-20-44-42.bpo-28055.f49kfC.rst @@ -0,0 +1 @@ +Fix unaligned accesses in siphash24(). Patch by Rolf Eike Beer. diff --git a/Python/pyhash.c b/Python/pyhash.c index a2ec2309c706..a8570740565e 100644 --- a/Python/pyhash.c +++ b/Python/pyhash.c @@ -369,7 +369,7 @@ siphash24(const void *src, Py_ssize_t src_sz) { uint64_t k0 = _le64toh(_Py_HashSecret.siphash.k0); uint64_t k1 = _le64toh(_Py_HashSecret.siphash.k1); uint64_t b = (uint64_t)src_sz << 56; - const uint64_t *in = (uint64_t*)src; + const uint8_t *in = (uint8_t*)src; uint64_t v0 = k0 ^ 0x736f6d6570736575ULL; uint64_t v1 = k1 ^ 0x646f72616e646f6dULL; @@ -378,12 +378,13 @@ siphash24(const void *src, Py_ssize_t src_sz) { uint64_t t; uint8_t *pt; - uint8_t *m; while (src_sz >= 8) { - uint64_t mi = _le64toh(*in); - in += 1; - src_sz -= 8; + uint64_t mi; + memcpy(&mi, in, sizeof(mi)); + mi = _le64toh(mi); + in += sizeof(mi); + src_sz -= sizeof(mi); v3 ^= mi; DOUBLE_ROUND(v0,v1,v2,v3); v0 ^= mi; @@ -391,15 +392,14 @@ siphash24(const void *src, Py_ssize_t src_sz) { t = 0; pt = (uint8_t *)&t; - m = (uint8_t *)in; switch (src_sz) { - case 7: pt[6] = m[6]; /* fall through */ - case 6: pt[5] = m[5]; /* fall through */ - case 5: pt[4] = m[4]; /* fall through */ - case 4: memcpy(pt, m, sizeof(uint32_t)); break; - case 3: pt[2] = m[2]; /* fall through */ - case 2: pt[1] = m[1]; /* fall through */ - case 1: pt[0] = m[0]; /* fall through */ + case 7: pt[6] = in[6]; /* fall through */ + case 6: pt[5] = in[5]; /* fall through */ + case 5: pt[4] = in[4]; /* fall through */ + case 4: memcpy(pt, in, sizeof(uint32_t)); break; + case 3: pt[2] = in[2]; /* fall through */ + case 2: pt[1] = in[1]; /* fall through */ + case 1: pt[0] = in[0]; /* fall through */ } b |= _le64toh(t); From webhook-mailer at python.org Sun May 13 17:04:56 2018 From: webhook-mailer at python.org (Fred Drake) Date: Sun, 13 May 2018 21:04:56 -0000 Subject: [Python-checkins] fix error message in ast.c (#6776) Message-ID: https://github.com/python/cpython/commit/898ff92dac30264fccb34783494889b026148f6d commit: 898ff92dac30264fccb34783494889b026148f6d branch: master author: Jelle Zijlstra committer: Fred Drake date: 2018-05-13T17:04:53-04:00 summary: fix error message in ast.c (#6776) small_stmt -> compound_stmt files: M Python/ast.c diff --git a/Python/ast.c b/Python/ast.c index 0d692ffd95bd..03a489a74ef0 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -4063,7 +4063,7 @@ ast_for_stmt(struct compiling *c, const node *n) return ast_for_async_stmt(c, ch); default: PyErr_Format(PyExc_SystemError, - "unhandled small_stmt: TYPE=%d NCH=%d\n", + "unhandled compound_stmt: TYPE=%d NCH=%d\n", TYPE(n), NCH(n)); return NULL; } From webhook-mailer at python.org Sun May 13 20:55:38 2018 From: webhook-mailer at python.org (Benjamin Peterson) Date: Mon, 14 May 2018 00:55:38 -0000 Subject: [Python-checkins] bpo-33488: Satisfy markdownlint for the pull request template. (GH-6786) Message-ID: https://github.com/python/cpython/commit/5cd22cf2097a6dd209999cf97858d54564a3be87 commit: 5cd22cf2097a6dd209999cf97858d54564a3be87 branch: master author: Eitan Adler committer: Benjamin Peterson date: 2018-05-13T17:55:35-07:00 summary: bpo-33488: Satisfy markdownlint for the pull request template. (GH-6786) ./.github/PULL_REQUEST_TEMPLATE.md:8: MD031 Fenced code blocks should be surrounded by blank lines ./.github/PULL_REQUEST_TEMPLATE.md:10: MD031 Fenced code blocks should be surrounded by blank lines ./.github/PULL_REQUEST_TEMPLATE.md:19: MD031 Fenced code blocks should be surrounded by blank lines ./.github/PULL_REQUEST_TEMPLATE.md:21: MD031 Fenced code blocks should be surrounded by blank lines files: M .github/PULL_REQUEST_TEMPLATE.md diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 917791eb287f..2731c0e8e550 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -5,9 +5,11 @@ Please read this comment in its entirety. It's quite important. # Pull Request title It should be in the following format: + ``` bpo-NNNN: Summary of the changes made ``` + Where: bpo-NNNN refers to the issue number in the https://bugs.python.org. Most PRs will require an issue number. Trivial changes, like fixing a typo, do not need an issue. @@ -16,9 +18,11 @@ Most PRs will require an issue number. Trivial changes, like fixing a typo, do n If this is a backport PR (PR made against branches other than `master`), please ensure that the PR title is in the following format: + ``` [X.Y] (GH-NNNN) ``` + Where: [X.Y] is the branch name, e.g. [3.6]. GH-NNNN refers to the PR number from `master`. From webhook-mailer at python.org Sun May 13 21:27:01 2018 From: webhook-mailer at python.org (Benjamin Peterson) Date: Mon, 14 May 2018 01:27:01 -0000 Subject: [Python-checkins] [3.7] bpo-33488: Satisfy markdownlint for the pull request template. (GH-6786) Message-ID: <mailman.5.1526261222.2757.python-checkins@python.org> https://github.com/python/cpython/commit/f1ee4a2e52d98698ec2c0a0e8acb6cd3bbc9bf1f commit: f1ee4a2e52d98698ec2c0a0e8acb6cd3bbc9bf1f branch: 3.7 author: Benjamin Peterson <benjamin at python.org> committer: GitHub <noreply at github.com> date: 2018-05-13T18:26:58-07:00 summary: [3.7] bpo-33488: Satisfy markdownlint for the pull request template. (GH-6786) ./.github/PULL_REQUEST_TEMPLATE.md:8: MD031 Fenced code blocks should be surrounded by blank lines ./.github/PULL_REQUEST_TEMPLATE.md:10: MD031 Fenced code blocks should be surrounded by blank lines ./.github/PULL_REQUEST_TEMPLATE.md:19: MD031 Fenced code blocks should be surrounded by blank lines ./.github/PULL_REQUEST_TEMPLATE.md:21: MD031 Fenced code blocks should be surrounded by blank lines. (cherry picked from commit 5cd22cf2097a6dd209999cf97858d54564a3be87) Co-authored-by: Eitan Adler <grimreaper at users.noreply.github.com> files: M .github/PULL_REQUEST_TEMPLATE.md diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 0f238d0558cd..402e528feb2f 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,8 +1,10 @@ !!! If this is a backport PR (PR made against branches other than `master`), please ensure that the PR title is in the following format: + ``` [X.Y] <title from the original PR> (GH-NNNN) ``` + Where: [X.Y] is the branch name, e.g. [3.6]. GH-NNNN refers to the PR number from `master`. From solipsis at pitrou.net Mon May 14 05:09:26 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Mon, 14 May 2018 09:09:26 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=-3 Message-ID: <20180514090926.1.D72736158AB16CC2@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_collections leaked [-7, 8, -7] memory blocks, sum=-6 test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_fork leaked [2, -1, 0] memory blocks, sum=1 test_multiprocessing_forkserver leaked [0, 0, -2] memory blocks, sum=-2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogh7Cj0d', '--timeout', '7200'] From webhook-mailer at python.org Mon May 14 10:00:41 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Mon, 14 May 2018 14:00:41 -0000 Subject: [Python-checkins] bpo-32601: Let test_expanduser use the same user if no others found. (GH-5246) Message-ID: <mailman.6.1526306443.2757.python-checkins@python.org> https://github.com/python/cpython/commit/5c0d462689e1a69537eaeba6ab94e3ff3524fc31 commit: 5c0d462689e1a69537eaeba6ab94e3ff3524fc31 branch: master author: Anders Kaseorg <andersk at mit.edu> committer: Serhiy Storchaka <storchaka at gmail.com> date: 2018-05-14T17:00:37+03:00 summary: bpo-32601: Let test_expanduser use the same user if no others found. (GH-5246) This happens in the NixOS build sandbox, for example, where the only other user is nobody with home directory /. files: M Lib/test/test_pathlib.py diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index 53215550b435..d1a3fba2ded9 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -2142,6 +2142,9 @@ def test_expanduser(self): otherhome = pwdent.pw_dir.rstrip('/') if othername != username and otherhome: break + else: + othername = username + otherhome = userhome p1 = P('~/Documents') p2 = P('~' + username + '/Documents') From webhook-mailer at python.org Mon May 14 10:10:44 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Mon, 14 May 2018 14:10:44 -0000 Subject: [Python-checkins] bpo-32861: urllib.robotparser fix incomplete __str__ methods. (GH-5711) Message-ID: <mailman.7.1526307045.2757.python-checkins@python.org> https://github.com/python/cpython/commit/bd08a0af2d88c590ede762102bd42da3437e9980 commit: bd08a0af2d88c590ede762102bd42da3437e9980 branch: master author: Michael Lazar <lazar.michael22 at gmail.com> committer: Serhiy Storchaka <storchaka at gmail.com> date: 2018-05-14T17:10:41+03:00 summary: bpo-32861: urllib.robotparser fix incomplete __str__ methods. (GH-5711) The urllib.robotparser's __str__ representation now includes wildcard entries and the "Crawl-delay" and "Request-rate" fields. Also removes extra newlines that were being appended to the end of the string. files: A Misc/NEWS.d/next/Library/2018-04-02-20-44-54.bpo-32861.HeBjzN.rst M Lib/test/test_robotparser.py M Lib/urllib/robotparser.py diff --git a/Lib/test/test_robotparser.py b/Lib/test/test_robotparser.py index 75198b70ad4f..bee8d238be6b 100644 --- a/Lib/test/test_robotparser.py +++ b/Lib/test/test_robotparser.py @@ -246,6 +246,32 @@ class DefaultEntryTest(BaseRequestRateTest, unittest.TestCase): bad = ['/cyberworld/map/index.html'] +class StringFormattingTest(BaseRobotTest, unittest.TestCase): + robots_txt = """\ +User-agent: * +Crawl-delay: 1 +Request-rate: 3/15 +Disallow: /cyberworld/map/ # This is an infinite virtual URL space + +# Cybermapper knows where to go. +User-agent: cybermapper +Disallow: /some/path + """ + + expected_output = """\ +User-agent: cybermapper +Disallow: /some/path + +User-agent: * +Crawl-delay: 1 +Request-rate: 3/15 +Disallow: /cyberworld/map/\ +""" + + def test_string_formatting(self): + self.assertEqual(str(self.parser), self.expected_output) + + class RobotHandler(BaseHTTPRequestHandler): def do_GET(self): diff --git a/Lib/urllib/robotparser.py b/Lib/urllib/robotparser.py index daac29c68dc3..92e4efe6865e 100644 --- a/Lib/urllib/robotparser.py +++ b/Lib/urllib/robotparser.py @@ -190,7 +190,10 @@ def request_rate(self, useragent): return self.default_entry.req_rate def __str__(self): - return ''.join([str(entry) + "\n" for entry in self.entries]) + entries = self.entries + if self.default_entry is not None: + entries = entries + [self.default_entry] + return '\n\n'.join(map(str, entries)) class RuleLine: @@ -222,10 +225,14 @@ def __init__(self): def __str__(self): ret = [] for agent in self.useragents: - ret.extend(["User-agent: ", agent, "\n"]) - for line in self.rulelines: - ret.extend([str(line), "\n"]) - return ''.join(ret) + ret.append(f"User-agent: {agent}") + if self.delay is not None: + ret.append(f"Crawl-delay: {self.delay}") + if self.req_rate is not None: + rate = self.req_rate + ret.append(f"Request-rate: {rate.requests}/{rate.seconds}") + ret.extend(map(str, self.rulelines)) + return '\n'.join(ret) def applies_to(self, useragent): """check if this entry applies to the specified agent""" diff --git a/Misc/NEWS.d/next/Library/2018-04-02-20-44-54.bpo-32861.HeBjzN.rst b/Misc/NEWS.d/next/Library/2018-04-02-20-44-54.bpo-32861.HeBjzN.rst new file mode 100644 index 000000000000..2bb24d7edab5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-04-02-20-44-54.bpo-32861.HeBjzN.rst @@ -0,0 +1,4 @@ +The urllib.robotparser's ``__str__`` representation now includes wildcard +entries and the "Crawl-delay" and "Request-rate" fields. Also removes extra +newlines that were being appended to the end of the string. Patch by +Michael Lazar. From webhook-mailer at python.org Mon May 14 10:22:09 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 14 May 2018 14:22:09 -0000 Subject: [Python-checkins] bpo-32601: Let test_expanduser use the same user if no others found. (GH-5246) Message-ID: <mailman.8.1526307729.2757.python-checkins@python.org> https://github.com/python/cpython/commit/2e01f7d5fe51b492e39d97bf0da2a83f2efb977d commit: 2e01f7d5fe51b492e39d97bf0da2a83f2efb977d branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-14T07:22:05-07:00 summary: bpo-32601: Let test_expanduser use the same user if no others found. (GH-5246) This happens in the NixOS build sandbox, for example, where the only other user is nobody with home directory /. (cherry picked from commit 5c0d462689e1a69537eaeba6ab94e3ff3524fc31) Co-authored-by: Anders Kaseorg <andersk at mit.edu> files: M Lib/test/test_pathlib.py diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index 53215550b435..d1a3fba2ded9 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -2142,6 +2142,9 @@ def test_expanduser(self): otherhome = pwdent.pw_dir.rstrip('/') if othername != username and otherhome: break + else: + othername = username + otherhome = userhome p1 = P('~/Documents') p2 = P('~' + username + '/Documents') From webhook-mailer at python.org Mon May 14 10:45:38 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 14 May 2018 14:45:38 -0000 Subject: [Python-checkins] bpo-32601: Let test_expanduser use the same user if no others found. (GH-5246) Message-ID: <mailman.9.1526309139.2757.python-checkins@python.org> https://github.com/python/cpython/commit/48fdbbf6bb0cd0ea9d284ba650a80bffa6310c6b commit: 48fdbbf6bb0cd0ea9d284ba650a80bffa6310c6b branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-14T07:45:34-07:00 summary: bpo-32601: Let test_expanduser use the same user if no others found. (GH-5246) This happens in the NixOS build sandbox, for example, where the only other user is nobody with home directory /. (cherry picked from commit 5c0d462689e1a69537eaeba6ab94e3ff3524fc31) Co-authored-by: Anders Kaseorg <andersk at mit.edu> files: M Lib/test/test_pathlib.py diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index a4d2f8d98333..db53a8f202dc 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -2145,6 +2145,9 @@ def test_expanduser(self): otherhome = pwdent.pw_dir.rstrip('/') if othername != username and otherhome: break + else: + othername = username + otherhome = userhome p1 = P('~/Documents') p2 = P('~' + username + '/Documents') From webhook-mailer at python.org Mon May 14 10:48:04 2018 From: webhook-mailer at python.org (Mariatta) Date: Mon, 14 May 2018 14:48:04 -0000 Subject: [Python-checkins] bpo-22069: Update TextIO documentation (GH-6609) Message-ID: <mailman.10.1526309286.2757.python-checkins@python.org> https://github.com/python/cpython/commit/7ffd4c58fae08b29259eebd6cbcd2287820b14e8 commit: 7ffd4c58fae08b29259eebd6cbcd2287820b14e8 branch: master author: Elena Oat <oat.elena at gmail.com> committer: Mariatta <Mariatta at users.noreply.github.com> date: 2018-05-14T10:48:01-04:00 summary: bpo-22069: Update TextIO documentation (GH-6609) Clarify that flush is implied when the call to write contains a newline character. files: M Doc/library/io.rst diff --git a/Doc/library/io.rst b/Doc/library/io.rst index 5c71d900fd25..f2e0fdbc5bf3 100644 --- a/Doc/library/io.rst +++ b/Doc/library/io.rst @@ -889,7 +889,7 @@ Text I/O characters written are translated to the given string. If *line_buffering* is ``True``, :meth:`flush` is implied when a call to - write contains a newline character. + write contains a newline character or a carriage return. If *write_through* is ``True``, calls to :meth:`write` are guaranteed not to be buffered: any data written on the :class:`TextIOWrapper` From webhook-mailer at python.org Mon May 14 11:37:39 2018 From: webhook-mailer at python.org (Eric V. Smith) Date: Mon, 14 May 2018 15:37:39 -0000 Subject: [Python-checkins] bpo-33494: Change dataclasses.Fields repr to use the repr of each of its members (GH-6798) Message-ID: <mailman.11.1526312260.2757.python-checkins@python.org> https://github.com/python/cpython/commit/2473eea65d592a80a5362a00362738a33196aba1 commit: 2473eea65d592a80a5362a00362738a33196aba1 branch: master author: Eric V. Smith <ericvsmith at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-14T11:37:28-04:00 summary: bpo-33494: Change dataclasses.Fields repr to use the repr of each of its members (GH-6798) files: A Misc/NEWS.d/next/Library/2018-05-14-10-29-03.bpo-33495.TeGTQJ.rst M Lib/dataclasses.py diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index 04e07f8cf8c2..c60eeaa58368 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -230,14 +230,14 @@ def __init__(self, default, default_factory, init, repr, hash, compare, def __repr__(self): return ('Field(' f'name={self.name!r},' - f'type={self.type},' - f'default={self.default},' - f'default_factory={self.default_factory},' - f'init={self.init},' - f'repr={self.repr},' - f'hash={self.hash},' - f'compare={self.compare},' - f'metadata={self.metadata}' + f'type={self.type!r},' + f'default={self.default!r},' + f'default_factory={self.default_factory!r},' + f'init={self.init!r},' + f'repr={self.repr!r},' + f'hash={self.hash!r},' + f'compare={self.compare!r},' + f'metadata={self.metadata!r}' ')') # This is used to support the PEP 487 __set_name__ protocol in the diff --git a/Misc/NEWS.d/next/Library/2018-05-14-10-29-03.bpo-33495.TeGTQJ.rst b/Misc/NEWS.d/next/Library/2018-05-14-10-29-03.bpo-33495.TeGTQJ.rst new file mode 100644 index 000000000000..22cf04cd2e43 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-14-10-29-03.bpo-33495.TeGTQJ.rst @@ -0,0 +1,3 @@ +Change dataclasses.Fields repr to use the repr of each of its members, +instead of str. This makes it more clear what each field actually +represents. This is especially true for the 'type' member. From webhook-mailer at python.org Mon May 14 11:51:53 2018 From: webhook-mailer at python.org (Alex Gaynor) Date: Mon, 14 May 2018 15:51:53 -0000 Subject: [Python-checkins] Remove `ifdef` check for an OpenSSL version (0.9.6) we don't support (GH-6800) Message-ID: <mailman.12.1526313115.2757.python-checkins@python.org> https://github.com/python/cpython/commit/f04224210d93212bd9ad17d67ef5e1c70171a13e commit: f04224210d93212bd9ad17d67ef5e1c70171a13e branch: master author: Alex Gaynor <alex.gaynor at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-14T11:51:45-04:00 summary: Remove `ifdef` check for an OpenSSL version (0.9.6) we don't support (GH-6800) files: M Modules/_ssl.c diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 4baabd52bc9f..650f030345f7 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -919,11 +919,8 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock, BIO_up_ref(outbio->bio); SSL_set_bio(self->ssl, inbio->bio, outbio->bio); } - mode = SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER; -#ifdef SSL_MODE_AUTO_RETRY - mode |= SSL_MODE_AUTO_RETRY; -#endif - SSL_set_mode(self->ssl, mode); + SSL_set_mode(self->ssl, + SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_AUTO_RETRY); if (server_hostname != NULL) { if (_ssl_configure_hostname(self, server_hostname) < 0) { From webhook-mailer at python.org Mon May 14 12:08:56 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 14 May 2018 16:08:56 -0000 Subject: [Python-checkins] bpo-22069: Update TextIO documentation (GH-6609) Message-ID: <mailman.13.1526314137.2757.python-checkins@python.org> https://github.com/python/cpython/commit/050e041bf7e5260013a74c75a05a3f0fb16447ec commit: 050e041bf7e5260013a74c75a05a3f0fb16447ec branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-14T09:08:53-07:00 summary: bpo-22069: Update TextIO documentation (GH-6609) Clarify that flush is implied when the call to write contains a newline character. (cherry picked from commit 7ffd4c58fae08b29259eebd6cbcd2287820b14e8) Co-authored-by: Elena Oat <oat.elena at gmail.com> files: M Doc/library/io.rst diff --git a/Doc/library/io.rst b/Doc/library/io.rst index 5c71d900fd25..f2e0fdbc5bf3 100644 --- a/Doc/library/io.rst +++ b/Doc/library/io.rst @@ -889,7 +889,7 @@ Text I/O characters written are translated to the given string. If *line_buffering* is ``True``, :meth:`flush` is implied when a call to - write contains a newline character. + write contains a newline character or a carriage return. If *write_through* is ``True``, calls to :meth:`write` are guaranteed not to be buffered: any data written on the :class:`TextIOWrapper` From webhook-mailer at python.org Mon May 14 12:11:45 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 14 May 2018 16:11:45 -0000 Subject: [Python-checkins] bpo-22069: Update TextIO documentation (GH-6609) Message-ID: <mailman.14.1526314306.2757.python-checkins@python.org> https://github.com/python/cpython/commit/84fc6c59cf286fc4e6b3a700c6db36ecc2bff92b commit: 84fc6c59cf286fc4e6b3a700c6db36ecc2bff92b branch: 2.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-14T09:11:42-07:00 summary: bpo-22069: Update TextIO documentation (GH-6609) Clarify that flush is implied when the call to write contains a newline character. (cherry picked from commit 7ffd4c58fae08b29259eebd6cbcd2287820b14e8) Co-authored-by: Elena Oat <oat.elena at gmail.com> files: M Doc/library/io.rst diff --git a/Doc/library/io.rst b/Doc/library/io.rst index b99324cdb38a..300041dc3bb1 100644 --- a/Doc/library/io.rst +++ b/Doc/library/io.rst @@ -809,7 +809,7 @@ Text I/O the given string. If *line_buffering* is ``True``, :meth:`flush` is implied when a call to - write contains a newline character. + write contains a newline character or a carriage return. :class:`TextIOWrapper` provides one attribute in addition to those of :class:`TextIOBase` and its parents: From webhook-mailer at python.org Mon May 14 12:18:10 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 14 May 2018 16:18:10 -0000 Subject: [Python-checkins] bpo-22069: Update TextIO documentation (GH-6609) Message-ID: <mailman.15.1526314692.2757.python-checkins@python.org> https://github.com/python/cpython/commit/9fd5b5fdf851d35a5c1314360119850e86a1fd0d commit: 9fd5b5fdf851d35a5c1314360119850e86a1fd0d branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-14T09:18:07-07:00 summary: bpo-22069: Update TextIO documentation (GH-6609) Clarify that flush is implied when the call to write contains a newline character. (cherry picked from commit 7ffd4c58fae08b29259eebd6cbcd2287820b14e8) Co-authored-by: Elena Oat <oat.elena at gmail.com> files: M Doc/library/io.rst diff --git a/Doc/library/io.rst b/Doc/library/io.rst index af38fd727587..73b3efff0f49 100644 --- a/Doc/library/io.rst +++ b/Doc/library/io.rst @@ -880,7 +880,7 @@ Text I/O characters written are translated to the given string. If *line_buffering* is ``True``, :meth:`flush` is implied when a call to - write contains a newline character. + write contains a newline character or a carriage return. If *write_through* is ``True``, calls to :meth:`write` are guaranteed not to be buffered: any data written on the :class:`TextIOWrapper` From webhook-mailer at python.org Mon May 14 12:22:04 2018 From: webhook-mailer at python.org (Andrew Svetlov) Date: Mon, 14 May 2018 16:22:04 -0000 Subject: [Python-checkins] Add versionchanged in create_datagram_endpoint doc (#4697) Message-ID: <mailman.16.1526314925.2757.python-checkins@python.org> https://github.com/python/cpython/commit/0ded580403d470651a963b0915c7a52de627c45e commit: 0ded580403d470651a963b0915c7a52de627c45e branch: master author: Romuald Brunet <romuald at chivil.com> committer: Andrew Svetlov <andrew.svetlov at gmail.com> date: 2018-05-14T19:22:00+03:00 summary: Add versionchanged in create_datagram_endpoint doc (#4697) Most of the parameters were added in 3.4.4 (b9bf913ab32), but this change was not documented files: M Doc/library/asyncio-eventloop.rst diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index ca8055bd162f..2770fa6f8acd 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -393,6 +393,9 @@ Creating connections See :ref:`UDP echo client protocol <asyncio-udp-echo-client-protocol>` and :ref:`UDP echo server protocol <asyncio-udp-echo-server-protocol>` examples. + .. versionchanged:: 3.4.4 + The *family*, *proto*, *flags*, *reuse_address*, *reuse_port, + *allow_broadcast*, and *sock* parameters were added. .. coroutinemethod:: AbstractEventLoop.create_unix_connection(protocol_factory, path=None, \*, ssl=None, sock=None, server_hostname=None, ssl_handshake_timeout=None) From webhook-mailer at python.org Mon May 14 13:31:13 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 14 May 2018 17:31:13 -0000 Subject: [Python-checkins] bpo-33494: Change dataclasses.Fields repr to use the repr of each of its members (GH-6798) Message-ID: <mailman.17.1526319076.2757.python-checkins@python.org> https://github.com/python/cpython/commit/ceb45f0df87071319e6f73fb03e663ac39917daf commit: ceb45f0df87071319e6f73fb03e663ac39917daf branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-14T10:31:10-07:00 summary: bpo-33494: Change dataclasses.Fields repr to use the repr of each of its members (GH-6798) (cherry picked from commit 2473eea65d592a80a5362a00362738a33196aba1) Co-authored-by: Eric V. Smith <ericvsmith at users.noreply.github.com> files: A Misc/NEWS.d/next/Library/2018-05-14-10-29-03.bpo-33495.TeGTQJ.rst M Lib/dataclasses.py diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index 04e07f8cf8c2..c60eeaa58368 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -230,14 +230,14 @@ def __init__(self, default, default_factory, init, repr, hash, compare, def __repr__(self): return ('Field(' f'name={self.name!r},' - f'type={self.type},' - f'default={self.default},' - f'default_factory={self.default_factory},' - f'init={self.init},' - f'repr={self.repr},' - f'hash={self.hash},' - f'compare={self.compare},' - f'metadata={self.metadata}' + f'type={self.type!r},' + f'default={self.default!r},' + f'default_factory={self.default_factory!r},' + f'init={self.init!r},' + f'repr={self.repr!r},' + f'hash={self.hash!r},' + f'compare={self.compare!r},' + f'metadata={self.metadata!r}' ')') # This is used to support the PEP 487 __set_name__ protocol in the diff --git a/Misc/NEWS.d/next/Library/2018-05-14-10-29-03.bpo-33495.TeGTQJ.rst b/Misc/NEWS.d/next/Library/2018-05-14-10-29-03.bpo-33495.TeGTQJ.rst new file mode 100644 index 000000000000..22cf04cd2e43 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-14-10-29-03.bpo-33495.TeGTQJ.rst @@ -0,0 +1,3 @@ +Change dataclasses.Fields repr to use the repr of each of its members, +instead of str. This makes it more clear what each field actually +represents. This is especially true for the 'type' member. From webhook-mailer at python.org Mon May 14 13:45:48 2018 From: webhook-mailer at python.org (Alex Gaynor) Date: Mon, 14 May 2018 17:45:48 -0000 Subject: [Python-checkins] Remove `ifdef` check for an OpenSSL version (0.9.6) we don't support (GH-6807) Message-ID: <mailman.18.1526319949.2757.python-checkins@python.org> https://github.com/python/cpython/commit/67d1968a41ccc954bdaf841bcabc4138a5ed04d7 commit: 67d1968a41ccc954bdaf841bcabc4138a5ed04d7 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Alex Gaynor <alex.gaynor at gmail.com> date: 2018-05-14T13:45:45-04:00 summary: Remove `ifdef` check for an OpenSSL version (0.9.6) we don't support (GH-6807) (cherry picked from commit f04224210d93212bd9ad17d67ef5e1c70171a13e) Co-authored-by: Alex Gaynor <alex.gaynor at gmail.com> files: M Modules/_ssl.c diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 4baabd52bc9f..650f030345f7 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -919,11 +919,8 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock, BIO_up_ref(outbio->bio); SSL_set_bio(self->ssl, inbio->bio, outbio->bio); } - mode = SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER; -#ifdef SSL_MODE_AUTO_RETRY - mode |= SSL_MODE_AUTO_RETRY; -#endif - SSL_set_mode(self->ssl, mode); + SSL_set_mode(self->ssl, + SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | SSL_MODE_AUTO_RETRY); if (server_hostname != NULL) { if (_ssl_configure_hostname(self, server_hostname) < 0) { From webhook-mailer at python.org Mon May 14 14:03:20 2018 From: webhook-mailer at python.org (larryhastings) Date: Mon, 14 May 2018 18:03:20 -0000 Subject: [Python-checkins] [3.5] bpo-33001: Prevent buffer overrun in os.symlink (GH-5989) (#5991) Message-ID: <mailman.19.1526321002.2757.python-checkins@python.org> https://github.com/python/cpython/commit/f381cfe07d15d52f27de771a62a8167668f0dd51 commit: f381cfe07d15d52f27de771a62a8167668f0dd51 branch: 3.5 author: Steve Dower <steve.dower at microsoft.com> committer: larryhastings <larry at hastings.org> date: 2018-05-14T14:03:17-04:00 summary: [3.5] bpo-33001: Prevent buffer overrun in os.symlink (GH-5989) (#5991) * bpo-33001: Minimal fix to prevent buffer overrun in os.symlink * Remove invalid test files: A Misc/NEWS.d/next/Security/2018-03-05-10-09-51.bpo-33001.elj4Aa.rst M Lib/test/test_os.py M Modules/posixmodule.c diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index bb5d2e3429ce..e2077383bf47 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -2117,6 +2117,46 @@ def test_12084(self): os.remove(file1) shutil.rmtree(level1) + def test_buffer_overflow(self): + # Older versions would have a buffer overflow when detecting + # whether a link source was a directory. This test ensures we + # no longer crash, but does not otherwise validate the behavior + segment = 'X' * 27 + path = os.path.join(*[segment] * 10) + test_cases = [ + # overflow with absolute src + ('\\' + path, segment), + # overflow dest with relative src + (segment, path), + # overflow when joining src + (path[:180], path[:180]), + ] + for src, dest in test_cases: + try: + os.symlink(src, dest) + except FileNotFoundError: + pass + else: + try: + os.remove(dest) + except OSError: + pass + # Also test with bytes, since that is a separate code path. + # However, because of the stack layout, it is not possible + # to exploit the overflow on Python 3.5 using bytes + try: + os.symlink(os.fsencode(src), os.fsencode(dest)) + except ValueError: + # Conversion function checks for len(arg) >= 260 + pass + except FileNotFoundError: + pass + else: + try: + os.remove(dest) + except OSError: + pass + @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") class Win32JunctionTests(unittest.TestCase): diff --git a/Misc/NEWS.d/next/Security/2018-03-05-10-09-51.bpo-33001.elj4Aa.rst b/Misc/NEWS.d/next/Security/2018-03-05-10-09-51.bpo-33001.elj4Aa.rst new file mode 100644 index 000000000000..2acbac9e1af6 --- /dev/null +++ b/Misc/NEWS.d/next/Security/2018-03-05-10-09-51.bpo-33001.elj4Aa.rst @@ -0,0 +1 @@ +Minimal fix to prevent buffer overrun in os.symlink on Windows diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index d42416b0270e..102c5405bd59 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -7259,39 +7259,50 @@ check_CreateSymbolicLink(void) return (Py_CreateSymbolicLinkW && Py_CreateSymbolicLinkA); } -/* Remove the last portion of the path */ -static void +/* Remove the last portion of the path - return 0 on success */ +static int _dirnameW(WCHAR *path) { WCHAR *ptr; + size_t length = wcsnlen_s(path, MAX_PATH); + if (length == MAX_PATH) { + return -1; + } /* walk the path from the end until a backslash is encountered */ - for(ptr = path + wcslen(path); ptr != path; ptr--) { + for(ptr = path + length; ptr != path; ptr--) { if (*ptr == L'\\' || *ptr == L'/') break; } *ptr = 0; + return 0; } -/* Remove the last portion of the path */ -static void +/* Remove the last portion of the path - return 0 on success */ +static int _dirnameA(char *path) { char *ptr; + size_t length = strnlen_s(path, MAX_PATH); + if (length == MAX_PATH) { + return -1; + } /* walk the path from the end until a backslash is encountered */ - for(ptr = path + strlen(path); ptr != path; ptr--) { + for(ptr = path + length; ptr != path; ptr--) { if (*ptr == '\\' || *ptr == '/') break; } *ptr = 0; + return 0; } /* Is this path absolute? */ static int _is_absW(const WCHAR *path) { - return path[0] == L'\\' || path[0] == L'/' || path[1] == L':'; + return path[0] == L'\\' || path[0] == L'/' || + (path[0] && path[1] == L':'); } @@ -7299,50 +7310,47 @@ _is_absW(const WCHAR *path) static int _is_absA(const char *path) { - return path[0] == '\\' || path[0] == '/' || path[1] == ':'; + return path[0] == '\\' || path[0] == '/' || + (path[0] && path[1] == ':'); } -/* join root and rest with a backslash */ -static void +/* join root and rest with a backslash - return 0 on success */ +static int _joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest) { - size_t root_len; - if (_is_absW(rest)) { - wcscpy(dest_path, rest); - return; + return wcscpy_s(dest_path, MAX_PATH, rest); } - root_len = wcslen(root); + if (wcscpy_s(dest_path, MAX_PATH, root)) { + return -1; + } - wcscpy(dest_path, root); - if(root_len) { - dest_path[root_len] = L'\\'; - root_len++; + if (dest_path[0] && wcscat_s(dest_path, MAX_PATH, L"\\")) { + return -1; } - wcscpy(dest_path+root_len, rest); + + return wcscat_s(dest_path, MAX_PATH, rest); } -/* join root and rest with a backslash */ -static void +/* join root and rest with a backslash - return 0 on success */ +static int _joinA(char *dest_path, const char *root, const char *rest) { - size_t root_len; - if (_is_absA(rest)) { - strcpy(dest_path, rest); - return; + return strcpy_s(dest_path, MAX_PATH, rest); } - root_len = strlen(root); + if (strcpy_s(dest_path, MAX_PATH, root)) { + return -1; + } - strcpy(dest_path, root); - if(root_len) { - dest_path[root_len] = '\\'; - root_len++; + if (dest_path[0] && strcat_s(dest_path, MAX_PATH, "\\")) { + return -1; } - strcpy(dest_path+root_len, rest); + + return strcat_s(dest_path, MAX_PATH, rest); } /* Return True if the path at src relative to dest is a directory */ @@ -7354,10 +7362,14 @@ _check_dirW(WCHAR *src, WCHAR *dest) WCHAR src_resolved[MAX_PATH] = L""; /* dest_parent = os.path.dirname(dest) */ - wcscpy(dest_parent, dest); - _dirnameW(dest_parent); + if (wcscpy_s(dest_parent, MAX_PATH, dest) || + _dirnameW(dest_parent)) { + return 0; + } /* src_resolved = os.path.join(dest_parent, src) */ - _joinW(src_resolved, dest_parent, src); + if (_joinW(src_resolved, dest_parent, src)) { + return 0; + } return ( GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info) && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY @@ -7373,10 +7385,14 @@ _check_dirA(char *src, char *dest) char src_resolved[MAX_PATH] = ""; /* dest_parent = os.path.dirname(dest) */ - strcpy(dest_parent, dest); - _dirnameA(dest_parent); + if (strcpy_s(dest_parent, MAX_PATH, dest) || + _dirnameA(dest_parent)) { + return 0; + } /* src_resolved = os.path.join(dest_parent, src) */ - _joinA(src_resolved, dest_parent, src); + if (_joinA(src_resolved, dest_parent, src)) { + return 0; + } return ( GetFileAttributesExA(src_resolved, GetFileExInfoStandard, &src_info) && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY @@ -7441,6 +7457,7 @@ os_symlink_impl(PyObject *module, path_t *src, path_t *dst, #ifdef MS_WINDOWS Py_BEGIN_ALLOW_THREADS + _Py_BEGIN_SUPPRESS_IPH if (dst->wide) { /* if src is a directory, ensure target_is_directory==1 */ target_is_directory |= _check_dirW(src->wide, dst->wide); @@ -7453,6 +7470,7 @@ os_symlink_impl(PyObject *module, path_t *src, path_t *dst, result = Py_CreateSymbolicLinkA(dst->narrow, src->narrow, target_is_directory); } + _Py_END_SUPPRESS_IPH Py_END_ALLOW_THREADS if (!result) From webhook-mailer at python.org Mon May 14 14:14:33 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Mon, 14 May 2018 18:14:33 -0000 Subject: [Python-checkins] [3.7] bpo-32861: urllib.robotparser fix incomplete __str__ methods. (GH-5711) (GH-6795) Message-ID: <mailman.20.1526321675.2757.python-checkins@python.org> https://github.com/python/cpython/commit/c3fa1f2b93fa4bf96a8aadc74ee196384cefa31e commit: c3fa1f2b93fa4bf96a8aadc74ee196384cefa31e branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Serhiy Storchaka <storchaka at gmail.com> date: 2018-05-14T21:14:30+03:00 summary: [3.7] bpo-32861: urllib.robotparser fix incomplete __str__ methods. (GH-5711) (GH-6795) The urllib.robotparser's __str__ representation now includes wildcard entries and the "Crawl-delay" and "Request-rate" fields. (cherry picked from commit bd08a0af2d88c590ede762102bd42da3437e9980) Co-authored-by: Michael Lazar <lazar.michael22 at gmail.com> files: A Misc/NEWS.d/next/Library/2018-04-02-20-44-54.bpo-32861.HeBjzN.rst M Lib/test/test_robotparser.py M Lib/urllib/robotparser.py diff --git a/Lib/test/test_robotparser.py b/Lib/test/test_robotparser.py index 75198b70ad4f..140636590aa8 100644 --- a/Lib/test/test_robotparser.py +++ b/Lib/test/test_robotparser.py @@ -246,6 +246,33 @@ class DefaultEntryTest(BaseRequestRateTest, unittest.TestCase): bad = ['/cyberworld/map/index.html'] +class StringFormattingTest(BaseRobotTest, unittest.TestCase): + robots_txt = """\ +User-agent: * +Crawl-delay: 1 +Request-rate: 3/15 +Disallow: /cyberworld/map/ # This is an infinite virtual URL space + +# Cybermapper knows where to go. +User-agent: cybermapper +Disallow: /some/path + """ + + expected_output = """\ +User-agent: cybermapper +Disallow: /some/path + +User-agent: * +Crawl-delay: 1 +Request-rate: 3/15 +Disallow: /cyberworld/map/ + +""" + + def test_string_formatting(self): + self.assertEqual(str(self.parser), self.expected_output) + + class RobotHandler(BaseHTTPRequestHandler): def do_GET(self): diff --git a/Lib/urllib/robotparser.py b/Lib/urllib/robotparser.py index daac29c68dc3..883ef249210e 100644 --- a/Lib/urllib/robotparser.py +++ b/Lib/urllib/robotparser.py @@ -190,7 +190,10 @@ def request_rate(self, useragent): return self.default_entry.req_rate def __str__(self): - return ''.join([str(entry) + "\n" for entry in self.entries]) + entries = self.entries + if self.default_entry is not None: + entries = entries + [self.default_entry] + return '\n'.join(map(str, entries)) + '\n' class RuleLine: @@ -222,10 +225,15 @@ def __init__(self): def __str__(self): ret = [] for agent in self.useragents: - ret.extend(["User-agent: ", agent, "\n"]) - for line in self.rulelines: - ret.extend([str(line), "\n"]) - return ''.join(ret) + ret.append(f"User-agent: {agent}") + if self.delay is not None: + ret.append(f"Crawl-delay: {self.delay}") + if self.req_rate is not None: + rate = self.req_rate + ret.append(f"Request-rate: {rate.requests}/{rate.seconds}") + ret.extend(map(str, self.rulelines)) + ret.append('') # for compatibility + return '\n'.join(ret) def applies_to(self, useragent): """check if this entry applies to the specified agent""" diff --git a/Misc/NEWS.d/next/Library/2018-04-02-20-44-54.bpo-32861.HeBjzN.rst b/Misc/NEWS.d/next/Library/2018-04-02-20-44-54.bpo-32861.HeBjzN.rst new file mode 100644 index 000000000000..13defbb03cff --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-04-02-20-44-54.bpo-32861.HeBjzN.rst @@ -0,0 +1,3 @@ +The urllib.robotparser's ``__str__`` representation now includes wildcard +entries and the "Crawl-delay" and "Request-rate" fields. Patch by +Michael Lazar. From webhook-mailer at python.org Mon May 14 15:05:00 2018 From: webhook-mailer at python.org (Ivan Levkivskyi) Date: Mon, 14 May 2018 19:05:00 -0000 Subject: [Python-checkins] bpo-32769: Write annotation entry for glossary (GH-6657) Message-ID: <mailman.21.1526324700.2757.python-checkins@python.org> https://github.com/python/cpython/commit/f2290fb19a9b1a5fbeef0971016f72683e8cd1ad commit: f2290fb19a9b1a5fbeef0971016f72683e8cd1ad branch: master author: Andr?s Delfino <adelfino at gmail.com> committer: Ivan Levkivskyi <levkivskyi at gmail.com> date: 2018-05-14T15:04:55-04:00 summary: bpo-32769: Write annotation entry for glossary (GH-6657) https://bugs.python.org/issue32769 files: M Doc/glossary.rst diff --git a/Doc/glossary.rst b/Doc/glossary.rst index 2eab00314682..16b52670ef20 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -39,6 +39,18 @@ Glossary and loaders (in the :mod:`importlib.abc` module). You can create your own ABCs with the :mod:`abc` module. + annotation + A metadata value associated with a global variable, a class attribute or a + function or method parameter or return value, that stores a + :term:`type hint`. + + Annotations are stored in the :attr:`__annotations__` special attribute + of a module (when annotating a global variable), class (when annotating + one of its attributes) or function or method (when annotating a parameter or a + return value) and can be accessed using :func:`typing.get_type_hints`. + + See :pep:`484` and :pep:`526` which describe this functionality. + argument A value passed to a :term:`function` (or :term:`method`) when calling the function. There are two kinds of argument: @@ -175,6 +187,15 @@ Glossary normally contain method definitions which operate on instances of the class. + class variable + A variable defined in a class and intended to be modified only at + class level (i.e., not in an instance of the class). + + Class variables can be specified as such through + :term:`type hints <type hint>`. + + See :pep:`526` which describes class variable annotations. + coercion The implicit conversion of an instance of one type to another during an operation which involves two arguments of the same type. For example, @@ -367,16 +388,19 @@ Glossary and the :ref:`function` section. function annotation - An arbitrary metadata value associated with a function parameter or return - value. Its syntax is explained in section :ref:`function`. Annotations - may be accessed via the :attr:`__annotations__` special attribute of a - function object. + An :term:`annotation` of a function, or a method. + + For example, this function has its parameters annotated as taking + :class:`int` arguments and its return value annotated as being an + :class:`int` as well:: + + def sum_two_numbers(a: int, b: int) -> int: + return a + b - See also the :term:`variable annotation` glossary entry. + Its syntax is explained in section :ref:`function`. - Annotations are meant to provide a standard way for programmers to - document types of functions they design. See :pep:`484`, which - describes this functionality. + See also the :term:`variable annotation` glossary entry, and :pep:`484`, + which describes this functionality. __future__ A pseudo-module which programmers can use to enable new language features @@ -1009,6 +1033,18 @@ Glossary :attr:`~instance.__class__` attribute or can be retrieved with ``type(obj)``. + type hint + A specification about the expected type for a global variable, class + variable, function or method parameter or return value. + + While type hints are optional and are not enforced by Python when used, + they are useful for static type analysis tools, and aid IDEs on code + completion and refactoring. + + Type hints are stored in :term:`annotations <annotation>`. + + See also :pep:`483` which describe this functionality. + universal newlines A manner of interpreting text streams in which all of the following are recognized as ending a line: the Unix end-of-line convention ``'\n'``, @@ -1017,17 +1053,21 @@ Glossary :func:`bytes.splitlines` for an additional use. variable annotation - A type metadata value associated with a module global variable or - a class attribute. Its syntax is explained in section :ref:`annassign`. - Annotations are stored in the :attr:`__annotations__` special - attribute of a class or module object and can be accessed using - :func:`typing.get_type_hints`. + An :term:`annotation` of a global variable, or a class attribute. + + For example, this variable is annotated as taking :class:`int` values:: + + count: int = 0 + + When annotating variables, assignment is optional:: + + class C: + field: int - See also the :term:`function annotation` glossary entry. + Its syntax is explained in section :ref:`annassign`. - Annotations are meant to provide a standard way for programmers to - document types of functions they design. See :pep:`484` and :pep:`526` - which describe this functionality. + See also the :term:`function annotation` glossary entry, and :pep:`484` + and :pep:`526` which describe this functionality. virtual environment A cooperatively isolated runtime environment that allows Python users From webhook-mailer at python.org Mon May 14 15:10:55 2018 From: webhook-mailer at python.org (Brett Cannon) Date: Mon, 14 May 2018 19:10:55 -0000 Subject: [Python-checkins] bpo-33443 Fix typo in Python/import.c (GH-6722) Message-ID: <mailman.22.1526325057.2757.python-checkins@python.org> https://github.com/python/cpython/commit/5e6312c39e1fc32ecef18d340bcd5f7e314170e1 commit: 5e6312c39e1fc32ecef18d340bcd5f7e314170e1 branch: master author: ukwksk <ukwksk at gmail.com> committer: Brett Cannon <brettcannon at users.noreply.github.com> date: 2018-05-14T12:10:52-07:00 summary: bpo-33443 Fix typo in Python/import.c (GH-6722) files: M Python/import.c diff --git a/Python/import.c b/Python/import.c index bb1d69e16895..3a591836654b 100644 --- a/Python/import.c +++ b/Python/import.c @@ -92,7 +92,7 @@ _PyImportHooks_Init(void) _PyInitError _PyImportZip_Init(void) { - PyObject *path_hooks, *zimpimport; + PyObject *path_hooks, *zipimport; int err = 0; path_hooks = PySys_GetObject("path_hooks"); @@ -104,17 +104,17 @@ _PyImportZip_Init(void) if (Py_VerboseFlag) PySys_WriteStderr("# installing zipimport hook\n"); - zimpimport = PyImport_ImportModule("zipimport"); - if (zimpimport == NULL) { + zipimport = PyImport_ImportModule("zipimport"); + if (zipimport == NULL) { PyErr_Clear(); /* No zip import module -- okay */ if (Py_VerboseFlag) PySys_WriteStderr("# can't import zipimport\n"); } else { _Py_IDENTIFIER(zipimporter); - PyObject *zipimporter = _PyObject_GetAttrId(zimpimport, + PyObject *zipimporter = _PyObject_GetAttrId(zipimport, &PyId_zipimporter); - Py_DECREF(zimpimport); + Py_DECREF(zipimport); if (zipimporter == NULL) { PyErr_Clear(); /* No zipimporter object -- okay */ if (Py_VerboseFlag) From webhook-mailer at python.org Mon May 14 16:12:42 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 14 May 2018 20:12:42 -0000 Subject: [Python-checkins] Add versionchanged in create_datagram_endpoint doc (GH-4697) Message-ID: <mailman.23.1526328763.2757.python-checkins@python.org> https://github.com/python/cpython/commit/c6348cf395a89adf019d0d65e3488aa23395b7f1 commit: c6348cf395a89adf019d0d65e3488aa23395b7f1 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-14T13:12:38-07:00 summary: Add versionchanged in create_datagram_endpoint doc (GH-4697) Most of the parameters were added in 3.4.4 (b9bf913ab32), but this change was not documented (cherry picked from commit 0ded580403d470651a963b0915c7a52de627c45e) Co-authored-by: Romuald Brunet <romuald at chivil.com> files: M Doc/library/asyncio-eventloop.rst diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index ca8055bd162f..2770fa6f8acd 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -393,6 +393,9 @@ Creating connections See :ref:`UDP echo client protocol <asyncio-udp-echo-client-protocol>` and :ref:`UDP echo server protocol <asyncio-udp-echo-server-protocol>` examples. + .. versionchanged:: 3.4.4 + The *family*, *proto*, *flags*, *reuse_address*, *reuse_port, + *allow_broadcast*, and *sock* parameters were added. .. coroutinemethod:: AbstractEventLoop.create_unix_connection(protocol_factory, path=None, \*, ssl=None, sock=None, server_hostname=None, ssl_handshake_timeout=None) From webhook-mailer at python.org Mon May 14 16:12:50 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 14 May 2018 20:12:50 -0000 Subject: [Python-checkins] Add versionchanged in create_datagram_endpoint doc (GH-4697) Message-ID: <mailman.24.1526328771.2757.python-checkins@python.org> https://github.com/python/cpython/commit/914bad6e2c5131f32366be86e0bf3ad01f7de5e2 commit: 914bad6e2c5131f32366be86e0bf3ad01f7de5e2 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-14T13:12:47-07:00 summary: Add versionchanged in create_datagram_endpoint doc (GH-4697) Most of the parameters were added in 3.4.4 (b9bf913ab32), but this change was not documented (cherry picked from commit 0ded580403d470651a963b0915c7a52de627c45e) Co-authored-by: Romuald Brunet <romuald at chivil.com> files: M Doc/library/asyncio-eventloop.rst diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index 27c170e3ec84..bdba9962df62 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -389,6 +389,9 @@ Creating connections See :ref:`UDP echo client protocol <asyncio-udp-echo-client-protocol>` and :ref:`UDP echo server protocol <asyncio-udp-echo-server-protocol>` examples. + .. versionchanged:: 3.4.4 + The *family*, *proto*, *flags*, *reuse_address*, *reuse_port, + *allow_broadcast*, and *sock* parameters were added. .. coroutinemethod:: AbstractEventLoop.create_unix_connection(protocol_factory, path, \*, ssl=None, sock=None, server_hostname=None) From webhook-mailer at python.org Mon May 14 16:48:23 2018 From: webhook-mailer at python.org (Alex Gaynor) Date: Mon, 14 May 2018 20:48:23 -0000 Subject: [Python-checkins] Fixed an unused variable warning introduced in GH-6800 (GH-6816) Message-ID: <mailman.25.1526330904.2757.python-checkins@python.org> https://github.com/python/cpython/commit/00717a46a120dd8c8c74970fd75d201a5f42ab18 commit: 00717a46a120dd8c8c74970fd75d201a5f42ab18 branch: master author: Alex Gaynor <alex.gaynor at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-14T16:48:14-04:00 summary: Fixed an unused variable warning introduced in GH-6800 (GH-6816) files: M Modules/_ssl.c diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 650f030345f7..7670833bf5f5 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -882,7 +882,6 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock, { PySSLSocket *self; SSL_CTX *ctx = sslctx->ctx; - long mode; self = PyObject_New(PySSLSocket, &PySSLSocket_Type); if (self == NULL) From webhook-mailer at python.org Mon May 14 17:16:55 2018 From: webhook-mailer at python.org (Eric V. Smith) Date: Mon, 14 May 2018 21:16:55 -0000 Subject: [Python-checkins] bpo-33502: dataclass._Dataclassparams repr: use repr of each member. (GH-6812) Message-ID: <mailman.26.1526332617.2757.python-checkins@python.org> https://github.com/python/cpython/commit/3059042410dce69806b94be72d5c8055d616f3a3 commit: 3059042410dce69806b94be72d5c8055d616f3a3 branch: master author: Eric V. Smith <ericvsmith at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-14T17:16:52-04:00 summary: bpo-33502: dataclass._Dataclassparams repr: use repr of each member. (GH-6812) files: A f.py A j.py A t.py A x.py M Lib/dataclasses.py diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index c60eeaa58368..2ce6a02dcd7a 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -274,12 +274,12 @@ def __init__(self, init, repr, eq, order, unsafe_hash, frozen): def __repr__(self): return ('_DataclassParams(' - f'init={self.init},' - f'repr={self.repr},' - f'eq={self.eq},' - f'order={self.order},' - f'unsafe_hash={self.unsafe_hash},' - f'frozen={self.frozen}' + f'init={self.init!r},' + f'repr={self.repr!r},' + f'eq={self.eq!r},' + f'order={self.order!r},' + f'unsafe_hash={self.unsafe_hash!r},' + f'frozen={self.frozen!r}' ')') diff --git a/f.py b/f.py new file mode 100644 index 000000000000..02a3668c10ca --- /dev/null +++ b/f.py @@ -0,0 +1,12 @@ +from __future__ import annotations +from dataclasses import dataclass +from typing import List +from typing import ClassVar as CV + + at dataclass +class A: + a: List[str] + + at dataclass +class B(A): + b: CV[int] diff --git a/j.py b/j.py new file mode 100644 index 000000000000..9551702cfe9c --- /dev/null +++ b/j.py @@ -0,0 +1,15 @@ + +class X: + def __init__(self, value): + self.value = value + def __str__(self): + return str(self.value) + def __format__(self, fmt): + assert fmt[0] == '=' + self.value = eval(fmt[1:]) + return '' + +x = X(3) +print(x) +f'{x:=4}' # Behold! +print(x) diff --git a/t.py b/t.py new file mode 100644 index 000000000000..7484cf9758b3 --- /dev/null +++ b/t.py @@ -0,0 +1,20 @@ +from dataclasses import * + +class D: + """A descriptor class that knows its name.""" + def __set_name__(self, owner, name): + self.name = name + def __get__(self, instance, owner): + if instance is not None: + return 1 + return self + +from dataclasses import * + + at dataclass +class C: + d: int = field(default=D(), init=False) + + at dataclass +class E(C): + e: int = field(default=D(), init=False) diff --git a/x.py b/x.py new file mode 100644 index 000000000000..2b78f3e96fc7 --- /dev/null +++ b/x.py @@ -0,0 +1,31 @@ +#from __future__ import annotations +from typing import ClassVar, Dict, get_type_hints +from dataclasses import * + +class Starship: + stats: ClassVar[Dict[str, int]] = {} + +#print(get_type_hints(Starship)) + +#class A: +# a: Dict[int, C] + +#print(get_type_hints(A)) + +cv = [ClassVar[int]] + + at dataclass +class C: + CVS = [ClassVar[str]] + a: cv[0] + b: 'C' + c: 'CVS[0]' + x: 'ClassVar["int"]' + y: 'ClassVar[C]' + +print() +print(C.__annotations__) +print(C.__dataclass_fields__) + + +#print(get_type_hints(C)) From webhook-mailer at python.org Mon May 14 17:52:46 2018 From: webhook-mailer at python.org (Gregory P. Smith) Date: Mon, 14 May 2018 21:52:46 -0000 Subject: [Python-checkins] bpo-20104: Remove posix_spawn from 3.7 (GH-6794) Message-ID: <mailman.27.1526334768.2757.python-checkins@python.org> https://github.com/python/cpython/commit/8e633a4035bcff458c45fa095f4b8eab2f158466 commit: 8e633a4035bcff458c45fa095f4b8eab2f158466 branch: 3.7 author: Pablo Galindo <Pablogsal at gmail.com> committer: Gregory P. Smith <greg at krypto.org> date: 2018-05-14T17:52:43-04:00 summary: bpo-20104: Remove posix_spawn from 3.7 (GH-6794) Remove os.posix_spawn, the API isn't complete and we're still figuring out how it should look. wait for 3.8. files: A Misc/NEWS.d/next/Core and Builtins/2018-05-14-11-34-55.bpo-20104.kqBNzv.rst M Doc/library/os.rst M Doc/whatsnew/3.7.rst M Lib/test/test_posix.py M Misc/NEWS.d/3.7.0b1.rst M Modules/clinic/posixmodule.c.h M Modules/posixmodule.c diff --git a/Doc/library/os.rst b/Doc/library/os.rst index 5699d50a2034..784acf0ac5d8 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -3365,47 +3365,6 @@ written in Python, such as a mail server's external command delivery program. subprocesses. -.. function:: posix_spawn(path, argv, env, file_actions=None) - - Wraps the :c:func:`posix_spawn` C library API for use from Python. - - Most users should use :func:`subprocess.run` instead of :func:`posix_spawn`. - - The *path*, *args*, and *env* arguments are similar to :func:`execve`. - - The *file_actions* argument may be a sequence of tuples describing actions - to take on specific file descriptors in the child process between the C - library implementation's :c:func:`fork` and :c:func:`exec` steps. - The first item in each tuple must be one of the three type indicator - listed below describing the remaining tuple elements: - - .. data:: POSIX_SPAWN_OPEN - - (``os.POSIX_SPAWN_OPEN``, *fd*, *path*, *flags*, *mode*) - - Performs ``os.dup2(os.open(path, flags, mode), fd)``. - - .. data:: POSIX_SPAWN_CLOSE - - (``os.POSIX_SPAWN_CLOSE``, *fd*) - - Performs ``os.close(fd)``. - - .. data:: POSIX_SPAWN_DUP2 - - (``os.POSIX_SPAWN_DUP2``, *fd*, *new_fd*) - - Performs ``os.dup2(fd, new_fd)``. - - These tuples correspond to the C library - :c:func:`posix_spawn_file_actions_addopen`, - :c:func:`posix_spawn_file_actions_addclose`, and - :c:func:`posix_spawn_file_actions_adddup2` API calls used to prepare - for the :c:func:`posix_spawn` call itself. - - .. versionadded:: 3.7 - - .. function:: register_at_fork(*, before=None, after_in_parent=None, \ after_in_child=None) diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 8425731b842c..0a0c7d3659f1 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -616,10 +616,6 @@ Exposed the system calls *preadv*, *preadv2*, *pwritev* and *pwritev2* through the new functions :func:`~os.preadv` and :func:`~os.pwritev`. (Contributed by Pablo Galindo in :issue:`31368`.) -Exposed the system call *posix_spawn* through the new function -:func:`~os.posix_spawn`. (Contributed by Pablo Galindo, Serhiy Storchaka and -Gregory P. Smith in :issue:`20104`.) - pdb --- diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py index ecf3e93eb048..bf7c8c2119fb 100644 --- a/Lib/test/test_posix.py +++ b/Lib/test/test_posix.py @@ -1421,168 +1421,9 @@ def test_setgroups(self): posix.setgroups(groups) self.assertListEqual(groups, posix.getgroups()) - - at unittest.skipUnless(hasattr(os, 'posix_spawn'), "test needs os.posix_spawn") -class TestPosixSpawn(unittest.TestCase): - def test_returns_pid(self): - pidfile = support.TESTFN - self.addCleanup(support.unlink, pidfile) - script = f"""if 1: - import os - with open({pidfile!r}, "w") as pidfile: - pidfile.write(str(os.getpid())) - """ - pid = posix.posix_spawn(sys.executable, - [sys.executable, '-c', script], - os.environ) - self.assertEqual(os.waitpid(pid, 0), (pid, 0)) - with open(pidfile) as f: - self.assertEqual(f.read(), str(pid)) - - def test_no_such_executable(self): - no_such_executable = 'no_such_executable' - try: - pid = posix.posix_spawn(no_such_executable, - [no_such_executable], - os.environ) - except FileNotFoundError as exc: - self.assertEqual(exc.filename, no_such_executable) - else: - pid2, status = os.waitpid(pid, 0) - self.assertEqual(pid2, pid) - self.assertNotEqual(status, 0) - - def test_specify_environment(self): - envfile = support.TESTFN - self.addCleanup(support.unlink, envfile) - script = f"""if 1: - import os - with open({envfile!r}, "w") as envfile: - envfile.write(os.environ['foo']) - """ - pid = posix.posix_spawn(sys.executable, - [sys.executable, '-c', script], - {**os.environ, 'foo': 'bar'}) - self.assertEqual(os.waitpid(pid, 0), (pid, 0)) - with open(envfile) as f: - self.assertEqual(f.read(), 'bar') - - def test_empty_file_actions(self): - pid = posix.posix_spawn( - sys.executable, - [sys.executable, '-c', 'pass'], - os.environ, - [] - ) - self.assertEqual(os.waitpid(pid, 0), (pid, 0)) - - def test_multiple_file_actions(self): - file_actions = [ - (os.POSIX_SPAWN_OPEN, 3, os.path.realpath(__file__), os.O_RDONLY, 0), - (os.POSIX_SPAWN_CLOSE, 0), - (os.POSIX_SPAWN_DUP2, 1, 4), - ] - pid = posix.posix_spawn(sys.executable, - [sys.executable, "-c", "pass"], - os.environ, file_actions) - self.assertEqual(os.waitpid(pid, 0), (pid, 0)) - - def test_bad_file_actions(self): - with self.assertRaises(TypeError): - posix.posix_spawn(sys.executable, - [sys.executable, "-c", "pass"], - os.environ, [None]) - with self.assertRaises(TypeError): - posix.posix_spawn(sys.executable, - [sys.executable, "-c", "pass"], - os.environ, [()]) - with self.assertRaises(TypeError): - posix.posix_spawn(sys.executable, - [sys.executable, "-c", "pass"], - os.environ, [(None,)]) - with self.assertRaises(TypeError): - posix.posix_spawn(sys.executable, - [sys.executable, "-c", "pass"], - os.environ, [(12345,)]) - with self.assertRaises(TypeError): - posix.posix_spawn(sys.executable, - [sys.executable, "-c", "pass"], - os.environ, [(os.POSIX_SPAWN_CLOSE,)]) - with self.assertRaises(TypeError): - posix.posix_spawn(sys.executable, - [sys.executable, "-c", "pass"], - os.environ, [(os.POSIX_SPAWN_CLOSE, 1, 2)]) - with self.assertRaises(TypeError): - posix.posix_spawn(sys.executable, - [sys.executable, "-c", "pass"], - os.environ, [(os.POSIX_SPAWN_CLOSE, None)]) - with self.assertRaises(ValueError): - posix.posix_spawn(sys.executable, - [sys.executable, "-c", "pass"], - os.environ, - [(os.POSIX_SPAWN_OPEN, 3, __file__ + '\0', - os.O_RDONLY, 0)]) - - def test_open_file(self): - outfile = support.TESTFN - self.addCleanup(support.unlink, outfile) - script = """if 1: - import sys - sys.stdout.write("hello") - """ - file_actions = [ - (os.POSIX_SPAWN_OPEN, 1, outfile, - os.O_WRONLY | os.O_CREAT | os.O_TRUNC, - stat.S_IRUSR | stat.S_IWUSR), - ] - pid = posix.posix_spawn(sys.executable, - [sys.executable, '-c', script], - os.environ, file_actions) - self.assertEqual(os.waitpid(pid, 0), (pid, 0)) - with open(outfile) as f: - self.assertEqual(f.read(), 'hello') - - def test_close_file(self): - closefile = support.TESTFN - self.addCleanup(support.unlink, closefile) - script = f"""if 1: - import os - try: - os.fstat(0) - except OSError as e: - with open({closefile!r}, 'w') as closefile: - closefile.write('is closed %d' % e.errno) - """ - pid = posix.posix_spawn(sys.executable, - [sys.executable, '-c', script], - os.environ, - [(os.POSIX_SPAWN_CLOSE, 0),]) - self.assertEqual(os.waitpid(pid, 0), (pid, 0)) - with open(closefile) as f: - self.assertEqual(f.read(), 'is closed %d' % errno.EBADF) - - def test_dup2(self): - dupfile = support.TESTFN - self.addCleanup(support.unlink, dupfile) - script = """if 1: - import sys - sys.stdout.write("hello") - """ - with open(dupfile, "wb") as childfile: - file_actions = [ - (os.POSIX_SPAWN_DUP2, childfile.fileno(), 1), - ] - pid = posix.posix_spawn(sys.executable, - [sys.executable, '-c', script], - os.environ, file_actions) - self.assertEqual(os.waitpid(pid, 0), (pid, 0)) - with open(dupfile) as f: - self.assertEqual(f.read(), 'hello') - - def test_main(): try: - support.run_unittest(PosixTester, PosixGroupsTester, TestPosixSpawn) + support.run_unittest(PosixTester, PosixGroupsTester) finally: support.reap_children() diff --git a/Misc/NEWS.d/3.7.0b1.rst b/Misc/NEWS.d/3.7.0b1.rst index ec7b3c8ecf78..185d59c7adf3 100644 --- a/Misc/NEWS.d/3.7.0b1.rst +++ b/Misc/NEWS.d/3.7.0b1.rst @@ -142,6 +142,7 @@ Remove the STORE_ANNOTATION bytecode. .. section: Core and Builtins Expose posix_spawn as a low level API in the os module. +(removed before 3.7.0rc1) .. diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-05-14-11-34-55.bpo-20104.kqBNzv.rst b/Misc/NEWS.d/next/Core and Builtins/2018-05-14-11-34-55.bpo-20104.kqBNzv.rst new file mode 100644 index 000000000000..28c5b3302b4a --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-05-14-11-34-55.bpo-20104.kqBNzv.rst @@ -0,0 +1,2 @@ +The new `os.posix_spawn` added in 3.7.0b1 was removed as we are still +working on what the API should look like. Expect this in 3.8 instead. diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h index e4bbd082450b..ab1f75350340 100644 --- a/Modules/clinic/posixmodule.c.h +++ b/Modules/clinic/posixmodule.c.h @@ -1727,54 +1727,6 @@ os_execve(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *k #endif /* defined(HAVE_EXECV) */ -#if defined(HAVE_POSIX_SPAWN) - -PyDoc_STRVAR(os_posix_spawn__doc__, -"posix_spawn($module, path, argv, env, file_actions=None, /)\n" -"--\n" -"\n" -"Execute the program specified by path in a new process.\n" -"\n" -" path\n" -" Path of executable file.\n" -" argv\n" -" Tuple or list of strings.\n" -" env\n" -" Dictionary of strings mapping to strings.\n" -" file_actions\n" -" A sequence of file action tuples."); - -#define OS_POSIX_SPAWN_METHODDEF \ - {"posix_spawn", (PyCFunction)os_posix_spawn, METH_FASTCALL, os_posix_spawn__doc__}, - -static PyObject * -os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv, - PyObject *env, PyObject *file_actions); - -static PyObject * -os_posix_spawn(PyObject *module, PyObject *const *args, Py_ssize_t nargs) -{ - PyObject *return_value = NULL; - path_t path = PATH_T_INITIALIZE("posix_spawn", "path", 0, 0); - PyObject *argv; - PyObject *env; - PyObject *file_actions = Py_None; - - if (!_PyArg_ParseStack(args, nargs, "O&OO|O:posix_spawn", - path_converter, &path, &argv, &env, &file_actions)) { - goto exit; - } - return_value = os_posix_spawn_impl(module, &path, argv, env, file_actions); - -exit: - /* Cleanup for path */ - path_cleanup(&path); - - return return_value; -} - -#endif /* defined(HAVE_POSIX_SPAWN) */ - #if (defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV)) PyDoc_STRVAR(os_spawnv__doc__, @@ -6194,10 +6146,6 @@ os_getrandom(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject #define OS_EXECVE_METHODDEF #endif /* !defined(OS_EXECVE_METHODDEF) */ -#ifndef OS_POSIX_SPAWN_METHODDEF - #define OS_POSIX_SPAWN_METHODDEF -#endif /* !defined(OS_POSIX_SPAWN_METHODDEF) */ - #ifndef OS_SPAWNV_METHODDEF #define OS_SPAWNV_METHODDEF #endif /* !defined(OS_SPAWNV_METHODDEF) */ @@ -6589,4 +6537,4 @@ os_getrandom(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject #ifndef OS_GETRANDOM_METHODDEF #define OS_GETRANDOM_METHODDEF #endif /* !defined(OS_GETRANDOM_METHODDEF) */ -/*[clinic end generated code: output=8d3d9dddf254c3c2 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=c966c821d557b7c0 input=a9049054013a1b77]*/ diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index a81580db0a3b..c3682b4a0fd5 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -246,10 +246,6 @@ extern int lstat(const char *, struct stat *); #endif /* !_MSC_VER */ -#ifdef HAVE_POSIX_SPAWN -#include <spawn.h> -#endif - #ifdef HAVE_UTIME_H #include <utime.h> #endif /* HAVE_UTIME_H */ @@ -5106,218 +5102,6 @@ os_execve_impl(PyObject *module, path_t *path, PyObject *argv, PyObject *env) #endif /* HAVE_EXECV */ -#ifdef HAVE_POSIX_SPAWN - -enum posix_spawn_file_actions_identifier { - POSIX_SPAWN_OPEN, - POSIX_SPAWN_CLOSE, - POSIX_SPAWN_DUP2 -}; - -static int -parse_file_actions(PyObject *file_actions, - posix_spawn_file_actions_t *file_actionsp) -{ - PyObject *seq; - PyObject *file_action = NULL; - PyObject *tag_obj; - - seq = PySequence_Fast(file_actions, - "file_actions must be a sequence or None"); - if (seq == NULL) { - return -1; - } - - errno = posix_spawn_file_actions_init(file_actionsp); - if (errno) { - posix_error(); - Py_DECREF(seq); - return -1; - } - - for (int i = 0; i < PySequence_Fast_GET_SIZE(seq); ++i) { - file_action = PySequence_Fast_GET_ITEM(seq, i); - Py_INCREF(file_action); - if (!PyTuple_Check(file_action) || !PyTuple_GET_SIZE(file_action)) { - PyErr_SetString(PyExc_TypeError, - "Each file_actions element must be a non-empty tuple"); - goto fail; - } - long tag = PyLong_AsLong(PyTuple_GET_ITEM(file_action, 0)); - if (tag == -1 && PyErr_Occurred()) { - goto fail; - } - - /* Populate the file_actions object */ - switch (tag) { - case POSIX_SPAWN_OPEN: { - int fd, oflag; - PyObject *path; - unsigned long mode; - if (!PyArg_ParseTuple(file_action, "OiO&ik" - ";A open file_action tuple must have 5 elements", - &tag_obj, &fd, PyUnicode_FSConverter, &path, - &oflag, &mode)) - { - goto fail; - } - errno = posix_spawn_file_actions_addopen(file_actionsp, - fd, PyBytes_AS_STRING(path), oflag, (mode_t)mode); - Py_DECREF(path); /* addopen copied it. */ - if (errno) { - posix_error(); - goto fail; - } - break; - } - case POSIX_SPAWN_CLOSE: { - int fd; - if (!PyArg_ParseTuple(file_action, "Oi" - ";A close file_action tuple must have 2 elements", - &tag_obj, &fd)) - { - goto fail; - } - errno = posix_spawn_file_actions_addclose(file_actionsp, fd); - if (errno) { - posix_error(); - goto fail; - } - break; - } - case POSIX_SPAWN_DUP2: { - int fd1, fd2; - if (!PyArg_ParseTuple(file_action, "Oii" - ";A dup2 file_action tuple must have 3 elements", - &tag_obj, &fd1, &fd2)) - { - goto fail; - } - errno = posix_spawn_file_actions_adddup2(file_actionsp, - fd1, fd2); - if (errno) { - posix_error(); - goto fail; - } - break; - } - default: { - PyErr_SetString(PyExc_TypeError, - "Unknown file_actions identifier"); - goto fail; - } - } - Py_DECREF(file_action); - } - Py_DECREF(seq); - return 0; - -fail: - Py_DECREF(seq); - Py_DECREF(file_action); - (void)posix_spawn_file_actions_destroy(file_actionsp); - return -1; -} - -/*[clinic input] - -os.posix_spawn - path: path_t - Path of executable file. - argv: object - Tuple or list of strings. - env: object - Dictionary of strings mapping to strings. - file_actions: object = None - A sequence of file action tuples. - / - -Execute the program specified by path in a new process. -[clinic start generated code]*/ - -static PyObject * -os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv, - PyObject *env, PyObject *file_actions) -/*[clinic end generated code: output=d023521f541c709c input=a3db1021d33230dc]*/ -{ - EXECV_CHAR **argvlist = NULL; - EXECV_CHAR **envlist = NULL; - posix_spawn_file_actions_t file_actions_buf; - posix_spawn_file_actions_t *file_actionsp = NULL; - Py_ssize_t argc, envc; - PyObject *result = NULL; - pid_t pid; - int err_code; - - /* posix_spawn has three arguments: (path, argv, env), where - argv is a list or tuple of strings and env is a dictionary - like posix.environ. */ - - if (!PyList_Check(argv) && !PyTuple_Check(argv)) { - PyErr_SetString(PyExc_TypeError, - "posix_spawn: argv must be a tuple or list"); - goto exit; - } - argc = PySequence_Size(argv); - if (argc < 1) { - PyErr_SetString(PyExc_ValueError, "posix_spawn: argv must not be empty"); - return NULL; - } - - if (!PyMapping_Check(env)) { - PyErr_SetString(PyExc_TypeError, - "posix_spawn: environment must be a mapping object"); - goto exit; - } - - argvlist = parse_arglist(argv, &argc); - if (argvlist == NULL) { - goto exit; - } - if (!argvlist[0][0]) { - PyErr_SetString(PyExc_ValueError, - "posix_spawn: argv first element cannot be empty"); - goto exit; - } - - envlist = parse_envlist(env, &envc); - if (envlist == NULL) { - goto exit; - } - - if (file_actions != Py_None) { - if (parse_file_actions(file_actions, &file_actions_buf)) { - goto exit; - } - file_actionsp = &file_actions_buf; - } - - _Py_BEGIN_SUPPRESS_IPH - err_code = posix_spawn(&pid, path->narrow, - file_actionsp, NULL, argvlist, envlist); - _Py_END_SUPPRESS_IPH - if (err_code) { - errno = err_code; - PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object); - goto exit; - } - result = PyLong_FromPid(pid); - -exit: - if (file_actionsp) { - (void)posix_spawn_file_actions_destroy(file_actionsp); - } - if (envlist) { - free_string_array(envlist, envc); - } - if (argvlist) { - free_string_array(argvlist, argc); - } - return result; -} -#endif /* HAVE_POSIX_SPAWN */ - - #if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) /*[clinic input] os.spawnv @@ -12839,7 +12623,6 @@ static PyMethodDef posix_methods[] = { OS_NICE_METHODDEF OS_GETPRIORITY_METHODDEF OS_SETPRIORITY_METHODDEF - OS_POSIX_SPAWN_METHODDEF #ifdef HAVE_READLINK {"readlink", (PyCFunction)posix_readlink, METH_VARARGS | METH_KEYWORDS, @@ -13394,13 +13177,6 @@ all_ins(PyObject *m) if (PyModule_AddIntConstant(m, "RWF_NOWAIT", RWF_NOWAIT)) return -1; #endif -/* constants for posix_spawn */ -#ifdef HAVE_POSIX_SPAWN - if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1; - if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1; - if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1; -#endif - #ifdef HAVE_SPAWNV if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1; if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1; From webhook-mailer at python.org Mon May 14 18:03:59 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Mon, 14 May 2018 22:03:59 -0000 Subject: [Python-checkins] [3.7] bpo-32861: urllib.robotparser fix incomplete __str__ methods. (GH-5711) (GH-6795) (GH-6818) Message-ID: <mailman.28.1526335440.2757.python-checkins@python.org> https://github.com/python/cpython/commit/3936fd7b2c271f723d1a98fda3ca9c7efd329c04 commit: 3936fd7b2c271f723d1a98fda3ca9c7efd329c04 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Serhiy Storchaka <storchaka at gmail.com> date: 2018-05-15T01:03:56+03:00 summary: [3.7] bpo-32861: urllib.robotparser fix incomplete __str__ methods. (GH-5711) (GH-6795) (GH-6818) The urllib.robotparser's __str__ representation now includes wildcard entries and the "Crawl-delay" and "Request-rate" fields. (cherry picked from commit c3fa1f2b93fa4bf96a8aadc74ee196384cefa31e) Co-authored-by: Michael Lazar <lazar.michael22 at gmail.com> files: A Misc/NEWS.d/next/Library/2018-04-02-20-44-54.bpo-32861.HeBjzN.rst M Lib/test/test_robotparser.py M Lib/urllib/robotparser.py diff --git a/Lib/test/test_robotparser.py b/Lib/test/test_robotparser.py index e47344c11953..3f3018511c67 100644 --- a/Lib/test/test_robotparser.py +++ b/Lib/test/test_robotparser.py @@ -249,6 +249,33 @@ class DefaultEntryTest(BaseRequestRateTest, unittest.TestCase): bad = ['/cyberworld/map/index.html'] +class StringFormattingTest(BaseRobotTest, unittest.TestCase): + robots_txt = """\ +User-agent: * +Crawl-delay: 1 +Request-rate: 3/15 +Disallow: /cyberworld/map/ # This is an infinite virtual URL space + +# Cybermapper knows where to go. +User-agent: cybermapper +Disallow: /some/path + """ + + expected_output = """\ +User-agent: cybermapper +Disallow: /some/path + +User-agent: * +Crawl-delay: 1 +Request-rate: 3/15 +Disallow: /cyberworld/map/ + +""" + + def test_string_formatting(self): + self.assertEqual(str(self.parser), self.expected_output) + + class RobotHandler(BaseHTTPRequestHandler): def do_GET(self): diff --git a/Lib/urllib/robotparser.py b/Lib/urllib/robotparser.py index daac29c68dc3..883ef249210e 100644 --- a/Lib/urllib/robotparser.py +++ b/Lib/urllib/robotparser.py @@ -190,7 +190,10 @@ def request_rate(self, useragent): return self.default_entry.req_rate def __str__(self): - return ''.join([str(entry) + "\n" for entry in self.entries]) + entries = self.entries + if self.default_entry is not None: + entries = entries + [self.default_entry] + return '\n'.join(map(str, entries)) + '\n' class RuleLine: @@ -222,10 +225,15 @@ def __init__(self): def __str__(self): ret = [] for agent in self.useragents: - ret.extend(["User-agent: ", agent, "\n"]) - for line in self.rulelines: - ret.extend([str(line), "\n"]) - return ''.join(ret) + ret.append(f"User-agent: {agent}") + if self.delay is not None: + ret.append(f"Crawl-delay: {self.delay}") + if self.req_rate is not None: + rate = self.req_rate + ret.append(f"Request-rate: {rate.requests}/{rate.seconds}") + ret.extend(map(str, self.rulelines)) + ret.append('') # for compatibility + return '\n'.join(ret) def applies_to(self, useragent): """check if this entry applies to the specified agent""" diff --git a/Misc/NEWS.d/next/Library/2018-04-02-20-44-54.bpo-32861.HeBjzN.rst b/Misc/NEWS.d/next/Library/2018-04-02-20-44-54.bpo-32861.HeBjzN.rst new file mode 100644 index 000000000000..13defbb03cff --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-04-02-20-44-54.bpo-32861.HeBjzN.rst @@ -0,0 +1,3 @@ +The urllib.robotparser's ``__str__`` representation now includes wildcard +entries and the "Crawl-delay" and "Request-rate" fields. Patch by +Michael Lazar. From webhook-mailer at python.org Mon May 14 18:09:51 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Mon, 14 May 2018 22:09:51 -0000 Subject: [Python-checkins] [2.7] bpo-32861: robotparser fix incomplete __str__ methods. (GH-5711) (GH-6795) (GH-6817) Message-ID: <mailman.29.1526335792.2757.python-checkins@python.org> https://github.com/python/cpython/commit/861d38443d4b85cdc7b87afc4adee55f51c2f4b3 commit: 861d38443d4b85cdc7b87afc4adee55f51c2f4b3 branch: 2.7 author: Serhiy Storchaka <storchaka at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-15T01:09:47+03:00 summary: [2.7] bpo-32861: robotparser fix incomplete __str__ methods. (GH-5711) (GH-6795) (GH-6817) The robotparser's __str__ representation now includes wildcard entries. (cherry picked from commit c3fa1f2b93fa4bf96a8aadc74ee196384cefa31e) Co-authored-by: Michael Lazar <lazar.michael22 at gmail.com>. files: A Misc/NEWS.d/next/Library/2018-04-02-20-44-54.bpo-32861.HeBjzN.rst M Lib/robotparser.py M Lib/test/test_robotparser.py M Misc/ACKS diff --git a/Lib/robotparser.py b/Lib/robotparser.py index a7137a3064ff..4e13f7f780ca 100644 --- a/Lib/robotparser.py +++ b/Lib/robotparser.py @@ -160,7 +160,10 @@ def can_fetch(self, useragent, url): def __str__(self): - return ''.join([str(entry) + "\n" for entry in self.entries]) + entries = self.entries + if self.default_entry is not None: + entries = entries + [self.default_entry] + return '\n'.join(map(str, entries)) + '\n' class RuleLine: diff --git a/Lib/test/test_robotparser.py b/Lib/test/test_robotparser.py index 8ed5d8903619..ba7ccf8b58da 100644 --- a/Lib/test/test_robotparser.py +++ b/Lib/test/test_robotparser.py @@ -136,6 +136,31 @@ class DefaultEntryTest(BaseRobotTest, unittest.TestCase): bad = ['/cyberworld/map/index.html'] +class StringFormattingTest(BaseRobotTest, unittest.TestCase): + robots_txt = """\ +User-agent: * +Crawl-delay: 1 +Request-rate: 3/15 +Disallow: /cyberworld/map/ # This is an infinite virtual URL space + +# Cybermapper knows where to go. +User-agent: cybermapper +Disallow: /some/path + """ + + expected_output = """\ +User-agent: cybermapper +Disallow: /some/path + +User-agent: * +Disallow: /cyberworld/map/ + +""" + + def test_string_formatting(self): + self.assertEqual(str(self.parser), self.expected_output) + + class RobotHandler(BaseHTTPRequestHandler): def do_GET(self): @@ -226,6 +251,7 @@ def test_main(): UseFirstUserAgentWildcardTest, EmptyQueryStringTest, DefaultEntryTest, + StringFormattingTest, PasswordProtectedSiteTestCase, NetworkTestCase) diff --git a/Misc/ACKS b/Misc/ACKS index 458f31e6a6b7..394fbb93f2f1 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -807,6 +807,7 @@ Ben Laurie Simon Law Julia Lawall Chris Lawrence +Michael Lazar Brian Leair Mathieu Leduc-Hamel Amandine Lee diff --git a/Misc/NEWS.d/next/Library/2018-04-02-20-44-54.bpo-32861.HeBjzN.rst b/Misc/NEWS.d/next/Library/2018-04-02-20-44-54.bpo-32861.HeBjzN.rst new file mode 100644 index 000000000000..13defbb03cff --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-04-02-20-44-54.bpo-32861.HeBjzN.rst @@ -0,0 +1,3 @@ +The urllib.robotparser's ``__str__`` representation now includes wildcard +entries and the "Crawl-delay" and "Request-rate" fields. Patch by +Michael Lazar. From webhook-mailer at python.org Mon May 14 18:11:58 2018 From: webhook-mailer at python.org (Ned Deily) Date: Mon, 14 May 2018 22:11:58 -0000 Subject: [Python-checkins] bpo-33497: Add errors param to cgi.parse_multipart and make an encoding in FieldStorage use the given errors (GH-6804) Message-ID: <mailman.30.1526335920.2757.python-checkins@python.org> https://github.com/python/cpython/commit/545c955be997efd6b3827b981024e6b9945d82d1 commit: 545c955be997efd6b3827b981024e6b9945d82d1 branch: master author: Amber Brown <hawkowl at atleastfornow.net> committer: Ned Deily <nad at python.org> date: 2018-05-14T18:11:55-04:00 summary: bpo-33497: Add errors param to cgi.parse_multipart and make an encoding in FieldStorage use the given errors (GH-6804) files: M Doc/library/cgi.rst M Lib/cgi.py M Lib/test/test_cgi.py diff --git a/Doc/library/cgi.rst b/Doc/library/cgi.rst index 17386b831833..0b1aead9ddf1 100644 --- a/Doc/library/cgi.rst +++ b/Doc/library/cgi.rst @@ -296,7 +296,7 @@ algorithms implemented in this module in other circumstances. instead. It is maintained here only for backward compatibility. -.. function:: parse_multipart(fp, pdict, encoding="utf-8") +.. function:: parse_multipart(fp, pdict, encoding="utf-8", errors="replace") Parse input of type :mimetype:`multipart/form-data` (for file uploads). Arguments are *fp* for the input file, *pdict* for a dictionary containing @@ -312,8 +312,8 @@ algorithms implemented in this module in other circumstances. which is much more flexible. .. versionchanged:: 3.7 - Added the *encoding* parameter. For non-file fields, the value is now - a list of strings, not bytes. + Added the *encoding* and *errors* parameters. For non-file fields, the + value is now a list of strings, not bytes. .. function:: parse_header(string) diff --git a/Lib/cgi.py b/Lib/cgi.py index f5e85aa263b9..f82cc6c8bd56 100755 --- a/Lib/cgi.py +++ b/Lib/cgi.py @@ -198,13 +198,14 @@ def parse_qsl(qs, keep_blank_values=0, strict_parsing=0): DeprecationWarning, 2) return urllib.parse.parse_qsl(qs, keep_blank_values, strict_parsing) -def parse_multipart(fp, pdict, encoding="utf-8"): +def parse_multipart(fp, pdict, encoding="utf-8", errors="replace"): """Parse multipart input. Arguments: fp : input file pdict: dictionary containing other parameters of content-type header - encoding: request encoding + encoding, errors: request encoding and error handler, passed to + FieldStorage Returns a dictionary just like parse_qs(): keys are the field names, each value is a list of values for that field. For non-file fields, the value @@ -217,7 +218,7 @@ def parse_multipart(fp, pdict, encoding="utf-8"): headers = Message() headers.set_type(ctype) headers['Content-Length'] = pdict['CONTENT-LENGTH'] - fs = FieldStorage(fp, headers=headers, encoding=encoding, + fs = FieldStorage(fp, headers=headers, encoding=encoding, errors=errors, environ={'REQUEST_METHOD': 'POST'}) return {k: fs.getlist(k) for k in fs} @@ -458,7 +459,8 @@ def __init__(self, fp=None, headers=None, outerboundary=b'', self.type = ctype self.type_options = pdict if 'boundary' in pdict: - self.innerboundary = pdict['boundary'].encode(self.encoding) + self.innerboundary = pdict['boundary'].encode(self.encoding, + self.errors) else: self.innerboundary = b"" diff --git a/Lib/test/test_cgi.py b/Lib/test/test_cgi.py index 903d0731f977..4f2bba14a1bd 100644 --- a/Lib/test/test_cgi.py +++ b/Lib/test/test_cgi.py @@ -130,6 +130,24 @@ def test_parse_multipart(self): 'file': [b'Testing 123.\n'], 'title': ['']} self.assertEqual(result, expected) + def test_parse_multipart_invalid_encoding(self): + BOUNDARY = "JfISa01" + POSTDATA = """--JfISa01 +Content-Disposition: form-data; name="submit-name" +Content-Length: 3 + +\u2603 +--JfISa01""" + fp = BytesIO(POSTDATA.encode('utf8')) + env = {'boundary': BOUNDARY.encode('latin1'), + 'CONTENT-LENGTH': str(len(POSTDATA.encode('utf8')))} + result = cgi.parse_multipart(fp, env, encoding="ascii", + errors="surrogateescape") + expected = {'submit-name': ["\udce2\udc98\udc83"]} + self.assertEqual(result, expected) + self.assertEqual("\u2603".encode('utf8'), + result["submit-name"][0].encode('utf8', 'surrogateescape')) + def test_fieldstorage_properties(self): fs = cgi.FieldStorage() self.assertFalse(fs) From webhook-mailer at python.org Mon May 14 18:14:10 2018 From: webhook-mailer at python.org (Ivan Levkivskyi) Date: Mon, 14 May 2018 22:14:10 -0000 Subject: [Python-checkins] Add AsyncContextManager to typing module documentation. (GH-6822) Message-ID: <mailman.31.1526336051.2757.python-checkins@python.org> https://github.com/python/cpython/commit/b7b493e2fb00414e4766e1455cfd26ef15c4e5b8 commit: b7b493e2fb00414e4766e1455cfd26ef15c4e5b8 branch: master author: Travis DePrato <773453+travigd at users.noreply.github.com> committer: Ivan Levkivskyi <levkivskyi at gmail.com> date: 2018-05-14T18:14:07-04:00 summary: Add AsyncContextManager to typing module documentation. (GH-6822) files: A Misc/NEWS.d/next/Documentation/2018-05-14-15-15-41.bpo-33421.3GU_QO.rst M Doc/library/typing.rst diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index 9c4777ac2fe5..142e169b89c4 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -666,6 +666,12 @@ The module defines the following classes, functions and decorators: .. versionadded:: 3.6 +.. class:: AsyncContextManager(Generic[T_co]) + + A generic version of :class:`contextlib.AbstractAsyncContextManager`. + + .. versionadded:: 3.6 + .. class:: Dict(dict, MutableMapping[KT, VT]) A generic version of :class:`dict`. diff --git a/Misc/NEWS.d/next/Documentation/2018-05-14-15-15-41.bpo-33421.3GU_QO.rst b/Misc/NEWS.d/next/Documentation/2018-05-14-15-15-41.bpo-33421.3GU_QO.rst new file mode 100644 index 000000000000..75694b7be1e7 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2018-05-14-15-15-41.bpo-33421.3GU_QO.rst @@ -0,0 +1 @@ +Add missing documentation for ``typing.AsyncContextManager``. From webhook-mailer at python.org Mon May 14 18:15:18 2018 From: webhook-mailer at python.org (Ned Deily) Date: Mon, 14 May 2018 22:15:18 -0000 Subject: [Python-checkins] bpo-33497: Add NEWS and ACKS entries. (GH-6838) Message-ID: <mailman.32.1526336119.2757.python-checkins@python.org> https://github.com/python/cpython/commit/d063b84d9ee435e9ae981c18faccaff5562792c3 commit: d063b84d9ee435e9ae981c18faccaff5562792c3 branch: master author: Ned Deily <nad at python.org> committer: GitHub <noreply at github.com> date: 2018-05-14T18:15:15-04:00 summary: bpo-33497: Add NEWS and ACKS entries. (GH-6838) files: A Misc/NEWS.d/next/Library/2018-05-14-17-49-34.bpo-33497.wWT6XM.rst M Misc/ACKS diff --git a/Misc/ACKS b/Misc/ACKS index 587bbecbc36a..665b4dd7f43f 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -207,6 +207,7 @@ Ammar Brohi Josh Bronson Daniel Brotsky Jean Brouwers +Amber Brown Gary S. Brown Titus Brown Oleg Broytmann diff --git a/Misc/NEWS.d/next/Library/2018-05-14-17-49-34.bpo-33497.wWT6XM.rst b/Misc/NEWS.d/next/Library/2018-05-14-17-49-34.bpo-33497.wWT6XM.rst new file mode 100644 index 000000000000..d919dfdca75e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-14-17-49-34.bpo-33497.wWT6XM.rst @@ -0,0 +1,2 @@ +Add errors param to cgi.parse_multipart and make an encoding in FieldStorage +use the given errors (needed for Twisted). Patch by Amber Brown. From webhook-mailer at python.org Mon May 14 18:20:11 2018 From: webhook-mailer at python.org (Ned Deily) Date: Mon, 14 May 2018 22:20:11 -0000 Subject: [Python-checkins] bpo-33497: Add errors param to cgi.parse_multipart and make an encoding in FieldStorage use the given errors (GH-6804) (GH-6837) Message-ID: <mailman.33.1526336413.2757.python-checkins@python.org> https://github.com/python/cpython/commit/e8f968dcde520160bea7c98d298e58128f9abaa4 commit: e8f968dcde520160bea7c98d298e58128f9abaa4 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Ned Deily <nad at python.org> date: 2018-05-14T18:20:06-04:00 summary: bpo-33497: Add errors param to cgi.parse_multipart and make an encoding in FieldStorage use the given errors (GH-6804) (GH-6837) (cherry picked from commit 545c955be997efd6b3827b981024e6b9945d82d1) Co-authored-by: Amber Brown <hawkowl at atleastfornow.net> files: M Doc/library/cgi.rst M Lib/cgi.py M Lib/test/test_cgi.py diff --git a/Doc/library/cgi.rst b/Doc/library/cgi.rst index 17386b831833..0b1aead9ddf1 100644 --- a/Doc/library/cgi.rst +++ b/Doc/library/cgi.rst @@ -296,7 +296,7 @@ algorithms implemented in this module in other circumstances. instead. It is maintained here only for backward compatibility. -.. function:: parse_multipart(fp, pdict, encoding="utf-8") +.. function:: parse_multipart(fp, pdict, encoding="utf-8", errors="replace") Parse input of type :mimetype:`multipart/form-data` (for file uploads). Arguments are *fp* for the input file, *pdict* for a dictionary containing @@ -312,8 +312,8 @@ algorithms implemented in this module in other circumstances. which is much more flexible. .. versionchanged:: 3.7 - Added the *encoding* parameter. For non-file fields, the value is now - a list of strings, not bytes. + Added the *encoding* and *errors* parameters. For non-file fields, the + value is now a list of strings, not bytes. .. function:: parse_header(string) diff --git a/Lib/cgi.py b/Lib/cgi.py index f5e85aa263b9..f82cc6c8bd56 100755 --- a/Lib/cgi.py +++ b/Lib/cgi.py @@ -198,13 +198,14 @@ def parse_qsl(qs, keep_blank_values=0, strict_parsing=0): DeprecationWarning, 2) return urllib.parse.parse_qsl(qs, keep_blank_values, strict_parsing) -def parse_multipart(fp, pdict, encoding="utf-8"): +def parse_multipart(fp, pdict, encoding="utf-8", errors="replace"): """Parse multipart input. Arguments: fp : input file pdict: dictionary containing other parameters of content-type header - encoding: request encoding + encoding, errors: request encoding and error handler, passed to + FieldStorage Returns a dictionary just like parse_qs(): keys are the field names, each value is a list of values for that field. For non-file fields, the value @@ -217,7 +218,7 @@ def parse_multipart(fp, pdict, encoding="utf-8"): headers = Message() headers.set_type(ctype) headers['Content-Length'] = pdict['CONTENT-LENGTH'] - fs = FieldStorage(fp, headers=headers, encoding=encoding, + fs = FieldStorage(fp, headers=headers, encoding=encoding, errors=errors, environ={'REQUEST_METHOD': 'POST'}) return {k: fs.getlist(k) for k in fs} @@ -458,7 +459,8 @@ def __init__(self, fp=None, headers=None, outerboundary=b'', self.type = ctype self.type_options = pdict if 'boundary' in pdict: - self.innerboundary = pdict['boundary'].encode(self.encoding) + self.innerboundary = pdict['boundary'].encode(self.encoding, + self.errors) else: self.innerboundary = b"" diff --git a/Lib/test/test_cgi.py b/Lib/test/test_cgi.py index 903d0731f977..4f2bba14a1bd 100644 --- a/Lib/test/test_cgi.py +++ b/Lib/test/test_cgi.py @@ -130,6 +130,24 @@ def test_parse_multipart(self): 'file': [b'Testing 123.\n'], 'title': ['']} self.assertEqual(result, expected) + def test_parse_multipart_invalid_encoding(self): + BOUNDARY = "JfISa01" + POSTDATA = """--JfISa01 +Content-Disposition: form-data; name="submit-name" +Content-Length: 3 + +\u2603 +--JfISa01""" + fp = BytesIO(POSTDATA.encode('utf8')) + env = {'boundary': BOUNDARY.encode('latin1'), + 'CONTENT-LENGTH': str(len(POSTDATA.encode('utf8')))} + result = cgi.parse_multipart(fp, env, encoding="ascii", + errors="surrogateescape") + expected = {'submit-name': ["\udce2\udc98\udc83"]} + self.assertEqual(result, expected) + self.assertEqual("\u2603".encode('utf8'), + result["submit-name"][0].encode('utf8', 'surrogateescape')) + def test_fieldstorage_properties(self): fs = cgi.FieldStorage() self.assertFalse(fs) From webhook-mailer at python.org Mon May 14 18:21:12 2018 From: webhook-mailer at python.org (Ned Deily) Date: Mon, 14 May 2018 22:21:12 -0000 Subject: [Python-checkins] bpo-33497: Add NEWS and ACKS entries. (GH-6838) (GH-6840) Message-ID: <mailman.34.1526336474.2757.python-checkins@python.org> https://github.com/python/cpython/commit/5195039bb5529f1b18d30e8bfcabdee739912d76 commit: 5195039bb5529f1b18d30e8bfcabdee739912d76 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Ned Deily <nad at python.org> date: 2018-05-14T18:21:10-04:00 summary: bpo-33497: Add NEWS and ACKS entries. (GH-6838) (GH-6840) (cherry picked from commit d063b84d9ee435e9ae981c18faccaff5562792c3) Co-authored-by: Ned Deily <nad at python.org> files: A Misc/NEWS.d/next/Library/2018-05-14-17-49-34.bpo-33497.wWT6XM.rst M Misc/ACKS diff --git a/Misc/ACKS b/Misc/ACKS index 0bb3f35d4915..9d6a9238c8a5 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -206,6 +206,7 @@ Ammar Brohi Josh Bronson Daniel Brotsky Jean Brouwers +Amber Brown Gary S. Brown Titus Brown Oleg Broytmann diff --git a/Misc/NEWS.d/next/Library/2018-05-14-17-49-34.bpo-33497.wWT6XM.rst b/Misc/NEWS.d/next/Library/2018-05-14-17-49-34.bpo-33497.wWT6XM.rst new file mode 100644 index 000000000000..d919dfdca75e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-14-17-49-34.bpo-33497.wWT6XM.rst @@ -0,0 +1,2 @@ +Add errors param to cgi.parse_multipart and make an encoding in FieldStorage +use the given errors (needed for Twisted). Patch by Amber Brown. From webhook-mailer at python.org Mon May 14 19:42:33 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 14 May 2018 23:42:33 -0000 Subject: [Python-checkins] Fixed an unused variable warning introduced in GH-6800 (GH-6816) Message-ID: <mailman.35.1526341355.2757.python-checkins@python.org> https://github.com/python/cpython/commit/3b26e8cab738bec05e7e5178a390b9b4b7f208b6 commit: 3b26e8cab738bec05e7e5178a390b9b4b7f208b6 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-14T16:42:30-07:00 summary: Fixed an unused variable warning introduced in GH-6800 (GH-6816) (cherry picked from commit 00717a46a120dd8c8c74970fd75d201a5f42ab18) Co-authored-by: Alex Gaynor <alex.gaynor at gmail.com> files: M Modules/_ssl.c diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 650f030345f7..7670833bf5f5 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -882,7 +882,6 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock, { PySSLSocket *self; SSL_CTX *ctx = sslctx->ctx; - long mode; self = PyObject_New(PySSLSocket, &PySSLSocket_Type); if (self == NULL) From webhook-mailer at python.org Mon May 14 19:54:38 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Mon, 14 May 2018 23:54:38 -0000 Subject: [Python-checkins] bpo-16865: Support arrays >=2GB in ctypes. (GH-3006) Message-ID: <mailman.36.1526342080.2757.python-checkins@python.org> https://github.com/python/cpython/commit/735abadd5bd91db4a9e6f4311969b0afacca0a1a commit: 735abadd5bd91db4a9e6f4311969b0afacca0a1a branch: master author: Segev Finer <segev208 at gmail.com> committer: Serhiy Storchaka <storchaka at gmail.com> date: 2018-05-15T02:54:29+03:00 summary: bpo-16865: Support arrays >=2GB in ctypes. (GH-3006) files: A Misc/NEWS.d/next/Library/2017-09-29-16-40-38.bpo-16865.l-f6I_.rst M Lib/ctypes/test/test_arrays.py M Modules/_ctypes/_ctypes.c diff --git a/Lib/ctypes/test/test_arrays.py b/Lib/ctypes/test/test_arrays.py index 4ed566b48e67..6e562cfd24e6 100644 --- a/Lib/ctypes/test/test_arrays.py +++ b/Lib/ctypes/test/test_arrays.py @@ -1,4 +1,6 @@ import unittest +from test.support import bigmemtest, _2G +import sys from ctypes import * from ctypes.test import need_symbol @@ -181,5 +183,10 @@ class T(Array): _type_ = c_int _length_ = 1.87 + @unittest.skipUnless(sys.maxsize > 2**32, 'requires 64bit platform') + @bigmemtest(size=_2G, memuse=1, dry_run=False) + def test_large_array(self, size): + c_char * size + if __name__ == '__main__': unittest.main() diff --git a/Misc/NEWS.d/next/Library/2017-09-29-16-40-38.bpo-16865.l-f6I_.rst b/Misc/NEWS.d/next/Library/2017-09-29-16-40-38.bpo-16865.l-f6I_.rst new file mode 100644 index 000000000000..afaff736bf1c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-09-29-16-40-38.bpo-16865.l-f6I_.rst @@ -0,0 +1 @@ +Support arrays >=2GiB in :mod:`ctypes`. Patch by Segev Finer. diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 5bf49acb6c2d..3ae6348fef43 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -1390,8 +1390,7 @@ PyCArrayType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) StgDictObject *stgdict; StgDictObject *itemdict; PyObject *length_attr, *type_attr; - long length; - int overflow; + Py_ssize_t length; Py_ssize_t itemsize, itemalign; /* create the new instance (which is a class, @@ -1413,14 +1412,15 @@ PyCArrayType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) Py_XDECREF(length_attr); goto error; } - length = PyLong_AsLongAndOverflow(length_attr, &overflow); - if (overflow) { - PyErr_SetString(PyExc_OverflowError, - "The '_length_' attribute is too large"); - Py_DECREF(length_attr); + length = PyLong_AsSsize_t(length_attr); + Py_DECREF(length_attr); + if (length == -1 && PyErr_Occurred()) { + if (PyErr_ExceptionMatches(PyExc_OverflowError)) { + PyErr_SetString(PyExc_OverflowError, + "The '_length_' attribute is too large"); + } goto error; } - Py_DECREF(length_attr); type_attr = PyObject_GetAttrString((PyObject *)result, "_type_"); if (!type_attr) { From webhook-mailer at python.org Mon May 14 19:57:33 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 14 May 2018 23:57:33 -0000 Subject: [Python-checkins] bpo-33502: dataclass._Dataclassparams repr: use repr of each member. (GH-6812) Message-ID: <mailman.37.1526342254.2757.python-checkins@python.org> https://github.com/python/cpython/commit/b57aeac82ce6ee3d64cef3b6f7e9f9f2d7813f70 commit: b57aeac82ce6ee3d64cef3b6f7e9f9f2d7813f70 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-14T16:57:30-07:00 summary: bpo-33502: dataclass._Dataclassparams repr: use repr of each member. (GH-6812) (cherry picked from commit 3059042410dce69806b94be72d5c8055d616f3a3) Co-authored-by: Eric V. Smith <ericvsmith at users.noreply.github.com> files: A f.py A j.py A t.py A x.py M Lib/dataclasses.py diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index c60eeaa58368..2ce6a02dcd7a 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -274,12 +274,12 @@ def __init__(self, init, repr, eq, order, unsafe_hash, frozen): def __repr__(self): return ('_DataclassParams(' - f'init={self.init},' - f'repr={self.repr},' - f'eq={self.eq},' - f'order={self.order},' - f'unsafe_hash={self.unsafe_hash},' - f'frozen={self.frozen}' + f'init={self.init!r},' + f'repr={self.repr!r},' + f'eq={self.eq!r},' + f'order={self.order!r},' + f'unsafe_hash={self.unsafe_hash!r},' + f'frozen={self.frozen!r}' ')') diff --git a/f.py b/f.py new file mode 100644 index 000000000000..02a3668c10ca --- /dev/null +++ b/f.py @@ -0,0 +1,12 @@ +from __future__ import annotations +from dataclasses import dataclass +from typing import List +from typing import ClassVar as CV + + at dataclass +class A: + a: List[str] + + at dataclass +class B(A): + b: CV[int] diff --git a/j.py b/j.py new file mode 100644 index 000000000000..9551702cfe9c --- /dev/null +++ b/j.py @@ -0,0 +1,15 @@ + +class X: + def __init__(self, value): + self.value = value + def __str__(self): + return str(self.value) + def __format__(self, fmt): + assert fmt[0] == '=' + self.value = eval(fmt[1:]) + return '' + +x = X(3) +print(x) +f'{x:=4}' # Behold! +print(x) diff --git a/t.py b/t.py new file mode 100644 index 000000000000..7484cf9758b3 --- /dev/null +++ b/t.py @@ -0,0 +1,20 @@ +from dataclasses import * + +class D: + """A descriptor class that knows its name.""" + def __set_name__(self, owner, name): + self.name = name + def __get__(self, instance, owner): + if instance is not None: + return 1 + return self + +from dataclasses import * + + at dataclass +class C: + d: int = field(default=D(), init=False) + + at dataclass +class E(C): + e: int = field(default=D(), init=False) diff --git a/x.py b/x.py new file mode 100644 index 000000000000..2b78f3e96fc7 --- /dev/null +++ b/x.py @@ -0,0 +1,31 @@ +#from __future__ import annotations +from typing import ClassVar, Dict, get_type_hints +from dataclasses import * + +class Starship: + stats: ClassVar[Dict[str, int]] = {} + +#print(get_type_hints(Starship)) + +#class A: +# a: Dict[int, C] + +#print(get_type_hints(A)) + +cv = [ClassVar[int]] + + at dataclass +class C: + CVS = [ClassVar[str]] + a: cv[0] + b: 'C' + c: 'CVS[0]' + x: 'ClassVar["int"]' + y: 'ClassVar[C]' + +print() +print(C.__annotations__) +print(C.__dataclass_fields__) + + +#print(get_type_hints(C)) From webhook-mailer at python.org Mon May 14 21:00:21 2018 From: webhook-mailer at python.org (Eric V. Smith) Date: Tue, 15 May 2018 01:00:21 -0000 Subject: [Python-checkins] Remove accidentally checked in files. (GH-6835) Message-ID: <mailman.38.1526346022.2757.python-checkins@python.org> https://github.com/python/cpython/commit/046d311654eb15ccc8f471290334f7ac6aad5f15 commit: 046d311654eb15ccc8f471290334f7ac6aad5f15 branch: master author: Eric V. Smith <ericvsmith at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-14T21:00:18-04:00 summary: Remove accidentally checked in files. (GH-6835) files: D f.py D j.py D t.py D x.py diff --git a/f.py b/f.py deleted file mode 100644 index 02a3668c10ca..000000000000 --- a/f.py +++ /dev/null @@ -1,12 +0,0 @@ -from __future__ import annotations -from dataclasses import dataclass -from typing import List -from typing import ClassVar as CV - - at dataclass -class A: - a: List[str] - - at dataclass -class B(A): - b: CV[int] diff --git a/j.py b/j.py deleted file mode 100644 index 9551702cfe9c..000000000000 --- a/j.py +++ /dev/null @@ -1,15 +0,0 @@ - -class X: - def __init__(self, value): - self.value = value - def __str__(self): - return str(self.value) - def __format__(self, fmt): - assert fmt[0] == '=' - self.value = eval(fmt[1:]) - return '' - -x = X(3) -print(x) -f'{x:=4}' # Behold! -print(x) diff --git a/t.py b/t.py deleted file mode 100644 index 7484cf9758b3..000000000000 --- a/t.py +++ /dev/null @@ -1,20 +0,0 @@ -from dataclasses import * - -class D: - """A descriptor class that knows its name.""" - def __set_name__(self, owner, name): - self.name = name - def __get__(self, instance, owner): - if instance is not None: - return 1 - return self - -from dataclasses import * - - at dataclass -class C: - d: int = field(default=D(), init=False) - - at dataclass -class E(C): - e: int = field(default=D(), init=False) diff --git a/x.py b/x.py deleted file mode 100644 index 2b78f3e96fc7..000000000000 --- a/x.py +++ /dev/null @@ -1,31 +0,0 @@ -#from __future__ import annotations -from typing import ClassVar, Dict, get_type_hints -from dataclasses import * - -class Starship: - stats: ClassVar[Dict[str, int]] = {} - -#print(get_type_hints(Starship)) - -#class A: -# a: Dict[int, C] - -#print(get_type_hints(A)) - -cv = [ClassVar[int]] - - at dataclass -class C: - CVS = [ClassVar[str]] - a: cv[0] - b: 'C' - c: 'CVS[0]' - x: 'ClassVar["int"]' - y: 'ClassVar[C]' - -print() -print(C.__annotations__) -print(C.__dataclass_fields__) - - -#print(get_type_hints(C)) From lp_benchmark_robot at intel.com Mon May 14 21:04:08 2018 From: lp_benchmark_robot at intel.com (lp_benchmark_robot at intel.com) Date: Mon, 14 May 2018 18:04:08 -0700 Subject: [Python-checkins] [65 flat] Results for Python (master branch) 2018-05-14 Message-ID: <c9162184-18e3-4587-b134-89aaa17a248b@orsmsx155.amr.corp.intel.com> Results for project python/master, build date: 2018-05-14 03:03:18-07:00. - commit: 5cd22cf - previous commit: 7ec8f28 - revision date: 2018-05-13 17:55:35-07:00 - environment: Broadwell-EP - cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores, stepping 1, LLC 55 MB - mem: 128 GB - os: Ubuntu 16.04.2 LTS - kernel: 4.4.0-62-generic x86_64 GNU/Linux Baseline results were generated using release v3.6.0, with hash 5c4568a from 2016-12-22 23:38:47+00:00. +-----+------------------------+--------+------------+------------+------------+ | | |relative|change since|change since|current rev | | | benchmark|std_dev*| last run | baseline |run with PGO| +-----+------------------------+--------+------------+------------+------------+ | :-| | 2to3| 0.521% | -0.592% | +9.135% | +6.776% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method| 0.430% | -0.048% | +24.207% | +13.925% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_slots| 1.382% | +0.603% | +25.794% | +12.007% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_unknown| 0.962% | -0.037% | +22.654% | +12.549% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_simple| 2.326% | +0.503% | +11.208% | +12.285% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chameleon| 1.652% | -0.016% | +12.269% | +9.061% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chaos| 0.540% | -0.204% | +9.129% | +9.107% | +-----+------------------------+--------+------------+------------+------------+ | :-| | crypto_pyaes| 0.548% | +0.301% | +0.317% | +8.041% | +-----+------------------------+--------+------------+------------+------------+ | :-| | deltablue| 3.939% | -2.381% | +11.313% | +16.524% | +-----+------------------------+--------+------------+------------+------------+ | :-| | django_template| 2.347% | -0.576% | +20.848% | +11.566% | +-----+------------------------+--------+------------+------------+------------+ | :-| | dulwich_log| 1.305% | +0.412% | +5.649% | +7.592% | +-----+------------------------+--------+------------+------------+------------+ | :-| | fannkuch| 0.614% | -0.411% | +6.962% | +4.890% | +-----+------------------------+--------+------------+------------+------------+ | :-| | float| 1.093% | +0.271% | +2.893% | +6.917% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_text| 1.011% | +0.399% | +14.949% | +4.514% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_xml| 1.513% | -0.799% | +11.312% | +6.997% | +-----+------------------------+--------+------------+------------+------------+ | :-| | go| 6.150% | -0.470% | +5.127% | +11.902% | +-----+------------------------+--------+------------+------------+------------+ | :-| | hexiom| 0.706% | +0.267% | +12.078% | +11.101% | +-----+------------------------+--------+------------+------------+------------+ | :-| | html5lib| 2.692% | -0.165% | +12.015% | +9.222% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_dumps| 2.764% | -1.458% | +2.148% | +7.957% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_loads| 4.722% | +0.645% | -4.402% | +15.113% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_format| 1.427% | +0.253% | +17.811% | +12.874% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_silent| 2.541% | +0.237% | +47.587% | +12.790% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_simple| 1.741% | +0.067% | +12.861% | +13.528% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mako| 0.684% | -0.229% | +17.098% | +14.452% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mdp| 6.368% | -0.973% | +0.763% | +18.273% | +-----+------------------------+--------+------------+------------+------------+ | :-| | meteor_contest| 0.576% | -0.388% | +4.258% | +5.860% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nbody| 0.638% | -0.748% | +0.138% | -2.627% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nqueens| 0.685% | +0.455% | +6.157% | +5.407% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pathlib| 1.799% | -0.881% | -0.186% | +10.641% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle| 4.158% | -0.145% | -1.315% | +22.597% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_dict| 0.198% | +0.121% | +7.503% | +14.102% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_list| 0.740% | -0.171% | +7.141% | +15.668% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_pure_python| 5.226% | -1.004% | +11.400% | +10.556% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pidigits| 0.293% | +0.027% | +0.081% | +9.997% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup| 0.118% | -0.147% | +18.771% | +5.207% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup_no_site| 0.086% | -0.209% | +5.764% | +5.348% | +-----+------------------------+--------+------------+------------+------------+ | :-| | raytrace| 1.352% | +0.303% | +10.027% | +13.124% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_compile| 4.729% | +0.838% | +7.121% | +6.147% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_dna| 0.408% | -1.218% | -2.074% | +13.027% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_effbot| 2.348% | +1.907% | -2.978% | +3.983% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_v8| 1.458% | -0.890% | +4.797% | +5.569% | +-----+------------------------+--------+------------+------------+------------+ | :-| | richards| 1.416% | +0.320% | +9.663% | +13.621% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_fft| 0.477% | +0.610% | -1.622% | +4.146% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_lu| 3.065% | -0.555% | +22.595% | +11.862% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_monte_carlo| 2.198% | +0.116% | +5.464% | +4.653% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sor| 2.002% | +0.084% | +15.154% | +8.501% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sparse_mat_mult| 0.791% | +0.546% | -2.212% | -0.032% | +-----+------------------------+--------+------------+------------+------------+ | :-| | spectral_norm| 0.641% | +1.736% | +6.017% | +4.362% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_declarative| 1.351% | -1.461% | +6.460% | +6.067% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_imperative| 4.183% | -0.618% | +7.465% | +4.209% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlite_synth| 3.654% | -1.660% | -0.965% | +9.374% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_expand| 3.266% | -0.477% | +17.487% | +6.485% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_integrate| 1.380% | -0.009% | +18.574% | +5.119% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_str| 3.824% | +0.114% | +19.372% | +6.479% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_sum| 6.188% | -1.501% | +14.626% | +10.022% | +-----+------------------------+--------+------------+------------+------------+ | :-| | telco| 3.290% | -0.537% | +19.455% | +9.912% | +-----+------------------------+--------+------------+------------+------------+ | :-| | tornado_http| 0.933% | -0.002% | +7.451% | +5.234% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpack_sequence| 0.683% | -0.052% | +2.987% | +1.897% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle| 3.170% | +1.464% | +9.797% | +19.799% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_list| 0.638% | +0.512% | -3.224% | +17.718% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_pure_python| 0.738% | +0.517% | +7.669% | +7.741% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_generate| 1.478% | +0.058% | +2.600% | +12.282% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_iterparse| 1.956% | +0.381% | +4.308% | +7.566% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_parse| 3.121% | +0.914% | -5.949% | +9.994% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_process| 1.107% | +0.487% | +4.843% | +10.745% | +-----+------------------------+--------+------------+------------+------------+ * Relative Standard Deviation (Standard Deviation/Average) If this is not displayed properly please visit our results page here: http://languagesperformance.intel.com/65-flat-results-for-python-master-branch-2018-05-14 Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. From webhook-mailer at python.org Mon May 14 21:10:56 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 15 May 2018 01:10:56 -0000 Subject: [Python-checkins] Add AsyncContextManager to typing module documentation. (GH-6822) Message-ID: <mailman.39.1526346658.2757.python-checkins@python.org> https://github.com/python/cpython/commit/cc598ae26447a10d1580d95b8442e8ce3c68baea commit: cc598ae26447a10d1580d95b8442e8ce3c68baea branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-14T18:10:47-07:00 summary: Add AsyncContextManager to typing module documentation. (GH-6822) (cherry picked from commit b7b493e2fb00414e4766e1455cfd26ef15c4e5b8) Co-authored-by: Travis DePrato <773453+travigd at users.noreply.github.com> files: A Misc/NEWS.d/next/Documentation/2018-05-14-15-15-41.bpo-33421.3GU_QO.rst M Doc/library/typing.rst diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index 9c4777ac2fe5..142e169b89c4 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -666,6 +666,12 @@ The module defines the following classes, functions and decorators: .. versionadded:: 3.6 +.. class:: AsyncContextManager(Generic[T_co]) + + A generic version of :class:`contextlib.AbstractAsyncContextManager`. + + .. versionadded:: 3.6 + .. class:: Dict(dict, MutableMapping[KT, VT]) A generic version of :class:`dict`. diff --git a/Misc/NEWS.d/next/Documentation/2018-05-14-15-15-41.bpo-33421.3GU_QO.rst b/Misc/NEWS.d/next/Documentation/2018-05-14-15-15-41.bpo-33421.3GU_QO.rst new file mode 100644 index 000000000000..75694b7be1e7 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2018-05-14-15-15-41.bpo-33421.3GU_QO.rst @@ -0,0 +1 @@ +Add missing documentation for ``typing.AsyncContextManager``. From webhook-mailer at python.org Mon May 14 22:07:28 2018 From: webhook-mailer at python.org (Ivan Levkivskyi) Date: Tue, 15 May 2018 02:07:28 -0000 Subject: [Python-checkins] Add AsyncContextManager to typing module documentation. (GH-6823) Message-ID: <mailman.40.1526350049.2757.python-checkins@python.org> https://github.com/python/cpython/commit/295465dc2963d2d9c4bc6241a80e0f1fa73e1f9c commit: 295465dc2963d2d9c4bc6241a80e0f1fa73e1f9c branch: 3.6 author: Travis DePrato <773453+travigd at users.noreply.github.com> committer: Ivan Levkivskyi <levkivskyi at gmail.com> date: 2018-05-14T22:07:21-04:00 summary: Add AsyncContextManager to typing module documentation. (GH-6823) files: A Misc/NEWS.d/next/Documentation/2018-05-14-15-23-51.bpo-33421.3GU_QO.rst M Doc/library/typing.rst diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index 9c4777ac2fe5..4a8f2f8e12e6 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -666,6 +666,13 @@ The module defines the following classes, functions and decorators: .. versionadded:: 3.6 +.. class:: AsyncContextManager(Generic[T_co]) + + An ABC with async abstract :meth:`__aenter__` and :meth:`__aexit__` + methods. + + .. versionadded:: 3.6 + .. class:: Dict(dict, MutableMapping[KT, VT]) A generic version of :class:`dict`. diff --git a/Misc/NEWS.d/next/Documentation/2018-05-14-15-23-51.bpo-33421.3GU_QO.rst b/Misc/NEWS.d/next/Documentation/2018-05-14-15-23-51.bpo-33421.3GU_QO.rst new file mode 100644 index 000000000000..75694b7be1e7 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2018-05-14-15-23-51.bpo-33421.3GU_QO.rst @@ -0,0 +1 @@ +Add missing documentation for ``typing.AsyncContextManager``. From webhook-mailer at python.org Mon May 14 23:55:44 2018 From: webhook-mailer at python.org (Benjamin Peterson) Date: Tue, 15 May 2018 03:55:44 -0000 Subject: [Python-checkins] bpo-33483: more correctly handle finding the C compiler (GH-6780) Message-ID: <mailman.41.1526356544.2757.python-checkins@python.org> https://github.com/python/cpython/commit/98929b545e86e7c7296c912d8f34e8e8d3fd6439 commit: 98929b545e86e7c7296c912d8f34e8e8d3fd6439 branch: master author: Eitan Adler <grimreaper at users.noreply.github.com> committer: Benjamin Peterson <benjamin at python.org> date: 2018-05-14T20:55:41-07:00 summary: bpo-33483: more correctly handle finding the C compiler (GH-6780) Instead of passing configure args such as --without-gcc or --with-icc, instead prefer to rely on the native way of finding the compiler: passing CC (or CPP or CXX depending). This allows configure to find the correct compiler instead of having to be explicitly told. It also more correctly builds on both macOS and FreeBSD since the system compiler is used by default (cc) files: A Misc/NEWS.d/next/Build/2018-05-13-17-21-54.bpo-33483.WOs-en.rst M configure.ac diff --git a/Misc/NEWS.d/next/Build/2018-05-13-17-21-54.bpo-33483.WOs-en.rst b/Misc/NEWS.d/next/Build/2018-05-13-17-21-54.bpo-33483.WOs-en.rst new file mode 100644 index 000000000000..9808711e14ea --- /dev/null +++ b/Misc/NEWS.d/next/Build/2018-05-13-17-21-54.bpo-33483.WOs-en.rst @@ -0,0 +1,2 @@ +C compiler is now correctly detected from the standard environment +variables. --without-gcc and --with-icc options have been removed. diff --git a/configure.ac b/configure.ac index b52247356d75..883c90505219 100644 --- a/configure.ac +++ b/configure.ac @@ -555,43 +555,6 @@ EXPORT_MACOSX_DEPLOYMENT_TARGET='#' # when running configure or make. The build should not break if they do. # BASECFLAGS should generally not be messed with, however. -# XXX shouldn't some/most/all of this code be merged with the stuff later -# on that fiddles with OPT and BASECFLAGS? -AC_MSG_CHECKING(for --without-gcc) -AC_ARG_WITH(gcc, - AS_HELP_STRING([--without-gcc], [never use gcc]), -[ - case $withval in - no) CC=${CC:-cc} - without_gcc=yes;; - yes) CC=gcc - without_gcc=no;; - *) CC=$withval - without_gcc=$withval;; - esac], [ - case $ac_sys_system in - AIX*) CC=${CC:-xlc_r} - without_gcc=;; - *) without_gcc=no;; - esac]) -AC_MSG_RESULT($without_gcc) - -AC_MSG_CHECKING(for --with-icc) -AC_ARG_WITH(icc, - AS_HELP_STRING([--with-icc], [build with icc]), -[ - case $withval in - no) CC=${CC:-cc} - with_icc=no;; - yes) CC=icc - CXX=icpc - with_icc=yes;; - *) CC=$withval - with_icc=$withval;; - esac], [ - with_icc=no]) -AC_MSG_RESULT($with_icc) - # If the user switches compilers, we can't believe the cache if test ! -z "$ac_cv_prog_CC" -a ! -z "$CC" -a "$CC" != "$ac_cv_prog_CC" then @@ -1749,7 +1712,6 @@ yes) BASECFLAGS="$BASECFLAGS -m486 -DSCO5" ;; - # is there any other compiler on Darwin besides gcc? Darwin*) # -Wno-long-double, -no-cpp-precomp, and -mno-fused-madd # used to be here, but non-Apple gcc doesn't accept them. From webhook-mailer at python.org Tue May 15 00:39:26 2018 From: webhook-mailer at python.org (Benjamin Peterson) Date: Tue, 15 May 2018 04:39:26 -0000 Subject: [Python-checkins] run autoreconf (GH-6850) Message-ID: <mailman.42.1526359166.2757.python-checkins@python.org> https://github.com/python/cpython/commit/540162260c09cf58c7477d4b94941e6908283970 commit: 540162260c09cf58c7477d4b94941e6908283970 branch: master author: Benjamin Peterson <benjamin at python.org> committer: GitHub <noreply at github.com> date: 2018-05-14T21:39:22-07:00 summary: run autoreconf (GH-6850) files: M aclocal.m4 M configure diff --git a/aclocal.m4 b/aclocal.m4 index 69205776ed4c..6aa28ee7a5c4 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -1,6 +1,6 @@ -# generated automatically by aclocal 1.15 -*- Autoconf -*- +# generated automatically by aclocal 1.15.1 -*- Autoconf -*- -# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Copyright (C) 1996-2017 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -12,280 +12,4 @@ # PARTICULAR PURPOSE. m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) -dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- -dnl serial 11 (pkg-config-0.29.1) -dnl -dnl Copyright ? 2004 Scott James Remnant <scott at netsplit.com>. -dnl Copyright ? 2012-2015 Dan Nicholson <dbn.lists at gmail.com> -dnl -dnl This program is free software; you can redistribute it and/or modify -dnl it under the terms of the GNU General Public License as published by -dnl the Free Software Foundation; either version 2 of the License, or -dnl (at your option) any later version. -dnl -dnl This program is distributed in the hope that it will be useful, but -dnl WITHOUT ANY WARRANTY; without even the implied warranty of -dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -dnl General Public License for more details. -dnl -dnl You should have received a copy of the GNU General Public License -dnl along with this program; if not, write to the Free Software -dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -dnl 02111-1307, USA. -dnl -dnl As a special exception to the GNU General Public License, if you -dnl distribute this file as part of a program that contains a -dnl configuration script generated by Autoconf, you may include it under -dnl the same distribution terms that you use for the rest of that -dnl program. - -dnl PKG_PREREQ(MIN-VERSION) -dnl ----------------------- -dnl Since: 0.29 -dnl -dnl Verify that the version of the pkg-config macros are at least -dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's -dnl installed version of pkg-config, this checks the developer's version -dnl of pkg.m4 when generating configure. -dnl -dnl To ensure that this macro is defined, also add: -dnl m4_ifndef([PKG_PREREQ], -dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) -dnl -dnl See the "Since" comment for each macro you use to see what version -dnl of the macros you require. -m4_defun([PKG_PREREQ], -[m4_define([PKG_MACROS_VERSION], [0.29.1]) -m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, - [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) -])dnl PKG_PREREQ - -dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) -dnl ---------------------------------- -dnl Since: 0.16 -dnl -dnl Search for the pkg-config tool and set the PKG_CONFIG variable to -dnl first found in the path. Checks that the version of pkg-config found -dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is -dnl used since that's the first version where most current features of -dnl pkg-config existed. -AC_DEFUN([PKG_PROG_PKG_CONFIG], -[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) -m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) -m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) -AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) -AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) -AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) - -if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then - AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) -fi -if test -n "$PKG_CONFIG"; then - _pkg_min_version=m4_default([$1], [0.9.0]) - AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) - if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - PKG_CONFIG="" - fi -fi[]dnl -])dnl PKG_PROG_PKG_CONFIG - -dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) -dnl ------------------------------------------------------------------- -dnl Since: 0.18 -dnl -dnl Check to see whether a particular set of modules exists. Similar to -dnl PKG_CHECK_MODULES(), but does not set variables or print errors. -dnl -dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) -dnl only at the first occurence in configure.ac, so if the first place -dnl it's called might be skipped (such as if it is within an "if", you -dnl have to call PKG_CHECK_EXISTS manually -AC_DEFUN([PKG_CHECK_EXISTS], -[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl -if test -n "$PKG_CONFIG" && \ - AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then - m4_default([$2], [:]) -m4_ifvaln([$3], [else - $3])dnl -fi]) - -dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) -dnl --------------------------------------------- -dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting -dnl pkg_failed based on the result. -m4_define([_PKG_CONFIG], -[if test -n "$$1"; then - pkg_cv_[]$1="$$1" - elif test -n "$PKG_CONFIG"; then - PKG_CHECK_EXISTS([$3], - [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` - test "x$?" != "x0" && pkg_failed=yes ], - [pkg_failed=yes]) - else - pkg_failed=untried -fi[]dnl -])dnl _PKG_CONFIG - -dnl _PKG_SHORT_ERRORS_SUPPORTED -dnl --------------------------- -dnl Internal check to see if pkg-config supports short errors. -AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], -[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) -if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then - _pkg_short_errors_supported=yes -else - _pkg_short_errors_supported=no -fi[]dnl -])dnl _PKG_SHORT_ERRORS_SUPPORTED - - -dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], -dnl [ACTION-IF-NOT-FOUND]) -dnl -------------------------------------------------------------- -dnl Since: 0.4.0 -dnl -dnl Note that if there is a possibility the first call to -dnl PKG_CHECK_MODULES might not happen, you should be sure to include an -dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac -AC_DEFUN([PKG_CHECK_MODULES], -[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl -AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl -AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl - -pkg_failed=no -AC_MSG_CHECKING([for $1]) - -_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) -_PKG_CONFIG([$1][_LIBS], [libs], [$2]) - -m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS -and $1[]_LIBS to avoid the need to call pkg-config. -See the pkg-config man page for more details.]) - -if test $pkg_failed = yes; then - AC_MSG_RESULT([no]) - _PKG_SHORT_ERRORS_SUPPORTED - if test $_pkg_short_errors_supported = yes; then - $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` - else - $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` - fi - # Put the nasty error message in config.log where it belongs - echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD - - m4_default([$4], [AC_MSG_ERROR( -[Package requirements ($2) were not met: - -$$1_PKG_ERRORS - -Consider adjusting the PKG_CONFIG_PATH environment variable if you -installed software in a non-standard prefix. - -_PKG_TEXT])[]dnl - ]) -elif test $pkg_failed = untried; then - AC_MSG_RESULT([no]) - m4_default([$4], [AC_MSG_FAILURE( -[The pkg-config script could not be found or is too old. Make sure it -is in your PATH or set the PKG_CONFIG environment variable to the full -path to pkg-config. - -_PKG_TEXT - -To get pkg-config, see <http://pkg-config.freedesktop.org/>.])[]dnl - ]) -else - $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS - $1[]_LIBS=$pkg_cv_[]$1[]_LIBS - AC_MSG_RESULT([yes]) - $3 -fi[]dnl -])dnl PKG_CHECK_MODULES - - -dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], -dnl [ACTION-IF-NOT-FOUND]) -dnl --------------------------------------------------------------------- -dnl Since: 0.29 -dnl -dnl Checks for existence of MODULES and gathers its build flags with -dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags -dnl and VARIABLE-PREFIX_LIBS from --libs. -dnl -dnl Note that if there is a possibility the first call to -dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to -dnl include an explicit call to PKG_PROG_PKG_CONFIG in your -dnl configure.ac. -AC_DEFUN([PKG_CHECK_MODULES_STATIC], -[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl -_save_PKG_CONFIG=$PKG_CONFIG -PKG_CONFIG="$PKG_CONFIG --static" -PKG_CHECK_MODULES($@) -PKG_CONFIG=$_save_PKG_CONFIG[]dnl -])dnl PKG_CHECK_MODULES_STATIC - - -dnl PKG_INSTALLDIR([DIRECTORY]) -dnl ------------------------- -dnl Since: 0.27 -dnl -dnl Substitutes the variable pkgconfigdir as the location where a module -dnl should install pkg-config .pc files. By default the directory is -dnl $libdir/pkgconfig, but the default can be changed by passing -dnl DIRECTORY. The user can override through the --with-pkgconfigdir -dnl parameter. -AC_DEFUN([PKG_INSTALLDIR], -[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) -m4_pushdef([pkg_description], - [pkg-config installation directory @<:@]pkg_default[@:>@]) -AC_ARG_WITH([pkgconfigdir], - [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, - [with_pkgconfigdir=]pkg_default) -AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) -m4_popdef([pkg_default]) -m4_popdef([pkg_description]) -])dnl PKG_INSTALLDIR - - -dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) -dnl -------------------------------- -dnl Since: 0.27 -dnl -dnl Substitutes the variable noarch_pkgconfigdir as the location where a -dnl module should install arch-independent pkg-config .pc files. By -dnl default the directory is $datadir/pkgconfig, but the default can be -dnl changed by passing DIRECTORY. The user can override through the -dnl --with-noarch-pkgconfigdir parameter. -AC_DEFUN([PKG_NOARCH_INSTALLDIR], -[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) -m4_pushdef([pkg_description], - [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) -AC_ARG_WITH([noarch-pkgconfigdir], - [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, - [with_noarch_pkgconfigdir=]pkg_default) -AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) -m4_popdef([pkg_default]) -m4_popdef([pkg_description]) -])dnl PKG_NOARCH_INSTALLDIR - - -dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, -dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) -dnl ------------------------------------------- -dnl Since: 0.28 -dnl -dnl Retrieves the value of the pkg-config variable for the given module. -AC_DEFUN([PKG_CHECK_VAR], -[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl -AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl - -_PKG_CONFIG([$1], [variable="][$3]["], [$2]) -AS_VAR_COPY([$1], [pkg_cv_][$1]) - -AS_VAR_IF([$1], [""], [$5], [$4])dnl -])dnl PKG_CHECK_VAR - m4_include([m4/ax_check_openssl.m4]) diff --git a/configure b/configure index adf8cf3ab9c1..b098bac6472a 100755 --- a/configure +++ b/configure @@ -626,6 +626,7 @@ ac_subst_vars='LTLIBOBJS OPENSSL_LDFLAGS OPENSSL_LIBS OPENSSL_INCLUDES +PKG_CONFIG ENSUREPIP SRCDIRS THREADHEADERS @@ -653,9 +654,6 @@ LDLAST TCLTK_LIBS TCLTK_INCLUDES LIBFFI_INCLUDEDIR -PKG_CONFIG_LIBDIR -PKG_CONFIG_PATH -PKG_CONFIG SHLIBS CFLAGSFORSHARED LINKFORSHARED @@ -808,8 +806,6 @@ enable_universalsdk with_universal_archs with_framework_name enable_framework -with_gcc -with_icc with_cxx_main with_suffix enable_shared @@ -852,10 +848,7 @@ CFLAGS LDFLAGS LIBS CPPFLAGS -CPP -PKG_CONFIG -PKG_CONFIG_PATH -PKG_CONFIG_LIBDIR' +CPP' # Initialize some variables set by options. @@ -1506,8 +1499,6 @@ Optional Packages: --with-framework-name=FRAMEWORK specify an alternate name of the framework built with --enable-framework - --without-gcc never use gcc - --with-icc build with icc --with-cxx-main=<compiler> compile main() and link python executable with C++ compiler @@ -1568,11 +1559,6 @@ Some influential environment variables: CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if you have headers in a nonstandard directory <include dir> CPP C preprocessor - PKG_CONFIG path to pkg-config utility - PKG_CONFIG_PATH - directories to add to pkg-config's search path - PKG_CONFIG_LIBDIR - path overriding pkg-config's built-in search path Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. @@ -3454,57 +3440,6 @@ EXPORT_MACOSX_DEPLOYMENT_TARGET='#' # when running configure or make. The build should not break if they do. # BASECFLAGS should generally not be messed with, however. -# XXX shouldn't some/most/all of this code be merged with the stuff later -# on that fiddles with OPT and BASECFLAGS? -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --without-gcc" >&5 -$as_echo_n "checking for --without-gcc... " >&6; } - -# Check whether --with-gcc was given. -if test "${with_gcc+set}" = set; then : - withval=$with_gcc; - case $withval in - no) CC=${CC:-cc} - without_gcc=yes;; - yes) CC=gcc - without_gcc=no;; - *) CC=$withval - without_gcc=$withval;; - esac -else - - case $ac_sys_system in - AIX*) CC=${CC:-xlc_r} - without_gcc=;; - *) without_gcc=no;; - esac -fi - -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $without_gcc" >&5 -$as_echo "$without_gcc" >&6; } - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-icc" >&5 -$as_echo_n "checking for --with-icc... " >&6; } - -# Check whether --with-icc was given. -if test "${with_icc+set}" = set; then : - withval=$with_icc; - case $withval in - no) CC=${CC:-cc} - with_icc=no;; - yes) CC=icc - CXX=icpc - with_icc=yes;; - *) CC=$withval - with_icc=$withval;; - esac -else - - with_icc=no -fi - -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_icc" >&5 -$as_echo "$with_icc" >&6; } - # If the user switches compilers, we can't believe the cache if test ! -z "$ac_cv_prog_CC" -a ! -z "$CC" -a "$CC" != "$ac_cv_prog_CC" then @@ -7216,7 +7151,6 @@ $as_echo "$ac_cv_enable_implicit_function_declaration_error" >&6; } BASECFLAGS="$BASECFLAGS -m486 -DSCO5" ;; - # is there any other compiler on Darwin besides gcc? Darwin*) # -Wno-long-double, -no-cpp-precomp, and -mno-fused-madd # used to be here, but non-Apple gcc doesn't accept them. @@ -9969,126 +9903,7 @@ $as_echo "no" >&6; } fi - - - - - - - -if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. -set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_PKG_CONFIG+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $PKG_CONFIG in - [\\/]* | ?:[\\/]*) - ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -PKG_CONFIG=$ac_cv_path_PKG_CONFIG -if test -n "$PKG_CONFIG"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 -$as_echo "$PKG_CONFIG" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_path_PKG_CONFIG"; then - ac_pt_PKG_CONFIG=$PKG_CONFIG - # Extract the first word of "pkg-config", so it can be a program name with args. -set dummy pkg-config; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $ac_pt_PKG_CONFIG in - [\\/]* | ?:[\\/]*) - ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG -if test -n "$ac_pt_PKG_CONFIG"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 -$as_echo "$ac_pt_PKG_CONFIG" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_pt_PKG_CONFIG" = x; then - PKG_CONFIG="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - PKG_CONFIG=$ac_pt_PKG_CONFIG - fi -else - PKG_CONFIG="$ac_cv_path_PKG_CONFIG" -fi - -fi -if test -n "$PKG_CONFIG"; then - _pkg_min_version=0.9.0 - { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 -$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } - if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - PKG_CONFIG="" - fi -fi +PKG_PROG_PKG_CONFIG # Check for use of the system expat library { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-system-expat" >&5 From webhook-mailer at python.org Tue May 15 01:40:30 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 15 May 2018 05:40:30 -0000 Subject: [Python-checkins] bpo-16865: Support arrays >=2GB in ctypes. (GH-3006) Message-ID: <mailman.43.1526362832.2757.python-checkins@python.org> https://github.com/python/cpython/commit/2ce72e243fbc0e4f07f1191b20be548bfa5cbe11 commit: 2ce72e243fbc0e4f07f1191b20be548bfa5cbe11 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-14T22:40:27-07:00 summary: bpo-16865: Support arrays >=2GB in ctypes. (GH-3006) (cherry picked from commit 735abadd5bd91db4a9e6f4311969b0afacca0a1a) Co-authored-by: Segev Finer <segev208 at gmail.com> files: A Misc/NEWS.d/next/Library/2017-09-29-16-40-38.bpo-16865.l-f6I_.rst M Lib/ctypes/test/test_arrays.py M Modules/_ctypes/_ctypes.c diff --git a/Lib/ctypes/test/test_arrays.py b/Lib/ctypes/test/test_arrays.py index 4ed566b48e67..6e562cfd24e6 100644 --- a/Lib/ctypes/test/test_arrays.py +++ b/Lib/ctypes/test/test_arrays.py @@ -1,4 +1,6 @@ import unittest +from test.support import bigmemtest, _2G +import sys from ctypes import * from ctypes.test import need_symbol @@ -181,5 +183,10 @@ class T(Array): _type_ = c_int _length_ = 1.87 + @unittest.skipUnless(sys.maxsize > 2**32, 'requires 64bit platform') + @bigmemtest(size=_2G, memuse=1, dry_run=False) + def test_large_array(self, size): + c_char * size + if __name__ == '__main__': unittest.main() diff --git a/Misc/NEWS.d/next/Library/2017-09-29-16-40-38.bpo-16865.l-f6I_.rst b/Misc/NEWS.d/next/Library/2017-09-29-16-40-38.bpo-16865.l-f6I_.rst new file mode 100644 index 000000000000..afaff736bf1c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-09-29-16-40-38.bpo-16865.l-f6I_.rst @@ -0,0 +1 @@ +Support arrays >=2GiB in :mod:`ctypes`. Patch by Segev Finer. diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 93e8d8d42330..66bce151eb70 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -1390,8 +1390,7 @@ PyCArrayType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) StgDictObject *stgdict; StgDictObject *itemdict; PyObject *length_attr, *type_attr; - long length; - int overflow; + Py_ssize_t length; Py_ssize_t itemsize, itemalign; /* create the new instance (which is a class, @@ -1413,14 +1412,15 @@ PyCArrayType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) Py_XDECREF(length_attr); goto error; } - length = PyLong_AsLongAndOverflow(length_attr, &overflow); - if (overflow) { - PyErr_SetString(PyExc_OverflowError, - "The '_length_' attribute is too large"); - Py_DECREF(length_attr); + length = PyLong_AsSsize_t(length_attr); + Py_DECREF(length_attr); + if (length == -1 && PyErr_Occurred()) { + if (PyErr_ExceptionMatches(PyExc_OverflowError)) { + PyErr_SetString(PyExc_OverflowError, + "The '_length_' attribute is too large"); + } goto error; } - Py_DECREF(length_attr); type_attr = PyObject_GetAttrString((PyObject *)result, "_type_"); if (!type_attr) { From webhook-mailer at python.org Tue May 15 01:55:55 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 15 May 2018 05:55:55 -0000 Subject: [Python-checkins] bpo-16865: Support arrays >=2GB in ctypes. (GH-3006) Message-ID: <mailman.44.1526363757.2757.python-checkins@python.org> https://github.com/python/cpython/commit/726894addc02effaa369fded3caaba94875c1f3d commit: 726894addc02effaa369fded3caaba94875c1f3d branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-14T22:55:52-07:00 summary: bpo-16865: Support arrays >=2GB in ctypes. (GH-3006) (cherry picked from commit 735abadd5bd91db4a9e6f4311969b0afacca0a1a) Co-authored-by: Segev Finer <segev208 at gmail.com> files: A Misc/NEWS.d/next/Library/2017-09-29-16-40-38.bpo-16865.l-f6I_.rst M Lib/ctypes/test/test_arrays.py M Modules/_ctypes/_ctypes.c diff --git a/Lib/ctypes/test/test_arrays.py b/Lib/ctypes/test/test_arrays.py index 4ed566b48e67..6e562cfd24e6 100644 --- a/Lib/ctypes/test/test_arrays.py +++ b/Lib/ctypes/test/test_arrays.py @@ -1,4 +1,6 @@ import unittest +from test.support import bigmemtest, _2G +import sys from ctypes import * from ctypes.test import need_symbol @@ -181,5 +183,10 @@ class T(Array): _type_ = c_int _length_ = 1.87 + @unittest.skipUnless(sys.maxsize > 2**32, 'requires 64bit platform') + @bigmemtest(size=_2G, memuse=1, dry_run=False) + def test_large_array(self, size): + c_char * size + if __name__ == '__main__': unittest.main() diff --git a/Misc/NEWS.d/next/Library/2017-09-29-16-40-38.bpo-16865.l-f6I_.rst b/Misc/NEWS.d/next/Library/2017-09-29-16-40-38.bpo-16865.l-f6I_.rst new file mode 100644 index 000000000000..afaff736bf1c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-09-29-16-40-38.bpo-16865.l-f6I_.rst @@ -0,0 +1 @@ +Support arrays >=2GiB in :mod:`ctypes`. Patch by Segev Finer. diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 2c0a769d8724..69d73f5a958f 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -1392,8 +1392,7 @@ PyCArrayType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) StgDictObject *stgdict; StgDictObject *itemdict; PyObject *length_attr, *type_attr; - long length; - int overflow; + Py_ssize_t length; Py_ssize_t itemsize, itemalign; /* create the new instance (which is a class, @@ -1415,14 +1414,15 @@ PyCArrayType_new(PyTypeObject *type, PyObject *args, PyObject *kwds) Py_XDECREF(length_attr); goto error; } - length = PyLong_AsLongAndOverflow(length_attr, &overflow); - if (overflow) { - PyErr_SetString(PyExc_OverflowError, - "The '_length_' attribute is too large"); - Py_DECREF(length_attr); + length = PyLong_AsSsize_t(length_attr); + Py_DECREF(length_attr); + if (length == -1 && PyErr_Occurred()) { + if (PyErr_ExceptionMatches(PyExc_OverflowError)) { + PyErr_SetString(PyExc_OverflowError, + "The '_length_' attribute is too large"); + } goto error; } - Py_DECREF(length_attr); type_attr = PyObject_GetAttrString((PyObject *)result, "_type_"); if (!type_attr) { From webhook-mailer at python.org Tue May 15 04:48:17 2018 From: webhook-mailer at python.org (Ned Deily) Date: Tue, 15 May 2018 08:48:17 -0000 Subject: [Python-checkins] Remove accidentally checked in files. (GH-6835) (GH-6844) Message-ID: <mailman.45.1526374099.2757.python-checkins@python.org> https://github.com/python/cpython/commit/28ff86eff0f6b02e87138fb08b6028f4b19d4f04 commit: 28ff86eff0f6b02e87138fb08b6028f4b19d4f04 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Ned Deily <nad at python.org> date: 2018-05-15T04:48:07-04:00 summary: Remove accidentally checked in files. (GH-6835) (GH-6844) (cherry picked from commit 046d311654eb15ccc8f471290334f7ac6aad5f15) Co-authored-by: Eric V. Smith <ericvsmith at users.noreply.github.com> files: D f.py D j.py D t.py D x.py diff --git a/f.py b/f.py deleted file mode 100644 index 02a3668c10ca..000000000000 --- a/f.py +++ /dev/null @@ -1,12 +0,0 @@ -from __future__ import annotations -from dataclasses import dataclass -from typing import List -from typing import ClassVar as CV - - at dataclass -class A: - a: List[str] - - at dataclass -class B(A): - b: CV[int] diff --git a/j.py b/j.py deleted file mode 100644 index 9551702cfe9c..000000000000 --- a/j.py +++ /dev/null @@ -1,15 +0,0 @@ - -class X: - def __init__(self, value): - self.value = value - def __str__(self): - return str(self.value) - def __format__(self, fmt): - assert fmt[0] == '=' - self.value = eval(fmt[1:]) - return '' - -x = X(3) -print(x) -f'{x:=4}' # Behold! -print(x) diff --git a/t.py b/t.py deleted file mode 100644 index 7484cf9758b3..000000000000 --- a/t.py +++ /dev/null @@ -1,20 +0,0 @@ -from dataclasses import * - -class D: - """A descriptor class that knows its name.""" - def __set_name__(self, owner, name): - self.name = name - def __get__(self, instance, owner): - if instance is not None: - return 1 - return self - -from dataclasses import * - - at dataclass -class C: - d: int = field(default=D(), init=False) - - at dataclass -class E(C): - e: int = field(default=D(), init=False) diff --git a/x.py b/x.py deleted file mode 100644 index 2b78f3e96fc7..000000000000 --- a/x.py +++ /dev/null @@ -1,31 +0,0 @@ -#from __future__ import annotations -from typing import ClassVar, Dict, get_type_hints -from dataclasses import * - -class Starship: - stats: ClassVar[Dict[str, int]] = {} - -#print(get_type_hints(Starship)) - -#class A: -# a: Dict[int, C] - -#print(get_type_hints(A)) - -cv = [ClassVar[int]] - - at dataclass -class C: - CVS = [ClassVar[str]] - a: cv[0] - b: 'C' - c: 'CVS[0]' - x: 'ClassVar["int"]' - y: 'ClassVar[C]' - -print() -print(C.__annotations__) -print(C.__dataclass_fields__) - - -#print(get_type_hints(C)) From solipsis at pitrou.net Tue May 15 05:17:07 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Tue, 15 May 2018 09:17:07 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=13 Message-ID: <20180515091707.1.79793920DC525A65@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_collections leaked [0, 7, 0] memory blocks, sum=7 test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_forkserver leaked [2, -2, 2] memory blocks, sum=2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogmVvIgp', '--timeout', '7200'] From webhook-mailer at python.org Tue May 15 08:36:31 2018 From: webhook-mailer at python.org (Eric V. Smith) Date: Tue, 15 May 2018 12:36:31 -0000 Subject: [Python-checkins] bpo-33517: dataclasses: Add the field type to Field repr (GH-6858) Message-ID: <mailman.46.1526387792.2757.python-checkins@python.org> https://github.com/python/cpython/commit/01abc6ec3a61769c55ee86834a432fb97801d28f commit: 01abc6ec3a61769c55ee86834a432fb97801d28f branch: master author: Eric V. Smith <ericvsmith at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-15T08:36:21-04:00 summary: bpo-33517: dataclasses: Add the field type to Field repr (GH-6858) files: M Lib/dataclasses.py diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index 2ce6a02dcd7a..0f9041604a5a 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -166,9 +166,14 @@ class _MISSING_TYPE: _EMPTY_METADATA = types.MappingProxyType({}) # Markers for the various kinds of fields and pseudo-fields. -_FIELD = object() # An actual field. -_FIELD_CLASSVAR = object() # Not a field, but a ClassVar. -_FIELD_INITVAR = object() # Not a field, but an InitVar. +class _FIELD_BASE: + def __init__(self, name): + self.name = name + def __repr__(self): + return self.name +_FIELD = _FIELD_BASE('_FIELD') +_FIELD_CLASSVAR = _FIELD_BASE('_FIELD_CLASSVAR') +_FIELD_INITVAR = _FIELD_BASE('_FIELD_INITVAR') # The name of an attribute on the class where we store the Field # objects. Also used to check if a class is a Data Class. @@ -237,7 +242,8 @@ def __repr__(self): f'repr={self.repr!r},' f'hash={self.hash!r},' f'compare={self.compare!r},' - f'metadata={self.metadata!r}' + f'metadata={self.metadata!r},' + f'_field_type={self._field_type}' ')') # This is used to support the PEP 487 __set_name__ protocol in the From webhook-mailer at python.org Tue May 15 09:01:54 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 15 May 2018 13:01:54 -0000 Subject: [Python-checkins] bpo-33517: dataclasses: Add the field type to Field repr (GH-6858) Message-ID: <mailman.47.1526389317.2757.python-checkins@python.org> https://github.com/python/cpython/commit/5c7e079158db869c9ede1ac9b5b9735091d3ffb6 commit: 5c7e079158db869c9ede1ac9b5b9735091d3ffb6 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-15T06:01:51-07:00 summary: bpo-33517: dataclasses: Add the field type to Field repr (GH-6858) (cherry picked from commit 01abc6ec3a61769c55ee86834a432fb97801d28f) Co-authored-by: Eric V. Smith <ericvsmith at users.noreply.github.com> files: M Lib/dataclasses.py diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index 2ce6a02dcd7a..0f9041604a5a 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -166,9 +166,14 @@ class _MISSING_TYPE: _EMPTY_METADATA = types.MappingProxyType({}) # Markers for the various kinds of fields and pseudo-fields. -_FIELD = object() # An actual field. -_FIELD_CLASSVAR = object() # Not a field, but a ClassVar. -_FIELD_INITVAR = object() # Not a field, but an InitVar. +class _FIELD_BASE: + def __init__(self, name): + self.name = name + def __repr__(self): + return self.name +_FIELD = _FIELD_BASE('_FIELD') +_FIELD_CLASSVAR = _FIELD_BASE('_FIELD_CLASSVAR') +_FIELD_INITVAR = _FIELD_BASE('_FIELD_INITVAR') # The name of an attribute on the class where we store the Field # objects. Also used to check if a class is a Data Class. @@ -237,7 +242,8 @@ def __repr__(self): f'repr={self.repr!r},' f'hash={self.hash!r},' f'compare={self.compare!r},' - f'metadata={self.metadata!r}' + f'metadata={self.metadata!r},' + f'_field_type={self._field_type}' ')') # This is used to support the PEP 487 __set_name__ protocol in the From webhook-mailer at python.org Tue May 15 09:56:22 2018 From: webhook-mailer at python.org (Eric Snow) Date: Tue, 15 May 2018 13:56:22 -0000 Subject: [Python-checkins] bpo-32604: Remove xid registry. (#6813) Message-ID: <mailman.48.1526392584.2757.python-checkins@python.org> https://github.com/python/cpython/commit/6bd0c476c58ca0046969f70dc2a4e4dfb3268062 commit: 6bd0c476c58ca0046969f70dc2a4e4dfb3268062 branch: 3.7 author: Eric Snow <ericsnowcurrently at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-15T09:56:18-04:00 summary: bpo-32604: Remove xid registry. (#6813) Remove the interpreters testing helper (and xid registry). files: A Misc/NEWS.d/next/Tests/2018-05-14-13-32-46.bpo-32604.a_z6D_.rst D Lib/test/test__xxsubinterpreters.py D Modules/_xxsubinterpretersmodule.c M Include/internal/pystate.h M Misc/NEWS.d/3.7.0b1.rst M PC/config.c M PCbuild/pythoncore.vcxproj M Python/pystate.c M setup.py diff --git a/Include/internal/pystate.h b/Include/internal/pystate.h index da642c6fd007..721d34fa4c19 100644 --- a/Include/internal/pystate.h +++ b/Include/internal/pystate.h @@ -73,75 +73,6 @@ PyAPI_FUNC(int) _PyInterpreterState_IDInitref(PyInterpreterState *); PyAPI_FUNC(void) _PyInterpreterState_IDIncref(PyInterpreterState *); PyAPI_FUNC(void) _PyInterpreterState_IDDecref(PyInterpreterState *); - -/* cross-interpreter data */ - -struct _xid; - -// _PyCrossInterpreterData is similar to Py_buffer as an effectively -// opaque struct that holds data outside the object machinery. This -// is necessary to pass between interpreters in the same process. -typedef struct _xid { - // data is the cross-interpreter-safe derivation of a Python object - // (see _PyObject_GetCrossInterpreterData). It will be NULL if the - // new_object func (below) encodes the data. - void *data; - // obj is the Python object from which the data was derived. This - // is non-NULL only if the data remains bound to the object in some - // way, such that the object must be "released" (via a decref) when - // the data is released. In that case it is automatically - // incref'ed (to match the automatic decref when releaed). - PyObject *obj; - // interp is the ID of the owning interpreter of the original - // object. It corresponds to the active interpreter when - // _PyObject_GetCrossInterpreterData() was called. This should only - // be set by the cross-interpreter machinery. - // - // We use the ID rather than the PyInterpreterState to avoid issues - // with deleted interpreters. - int64_t interp; - // new_object is a function that returns a new object in the current - // interpreter given the data. The resulting object (a new - // reference) will be equivalent to the original object. This field - // is required. - PyObject *(*new_object)(struct _xid *); - // free is called when the data is released. If it is NULL then - // nothing will be done to free the data. For some types this is - // okay (e.g. bytes) and for those types this field should be set - // to NULL. However, for most the data was allocated just for - // cross-interpreter use, so it must be freed when - // _PyCrossInterpreterData_Release is called or the memory will - // leak. In that case, at the very least this field should be set - // to PyMem_RawFree (the default if not explicitly set to NULL). - // The call will happen with the original interpreter activated. - void (*free)(void *); -} _PyCrossInterpreterData; - -typedef int (*crossinterpdatafunc)(PyObject *, _PyCrossInterpreterData *); -PyAPI_FUNC(int) _PyObject_CheckCrossInterpreterData(PyObject *); - -PyAPI_FUNC(int) _PyObject_GetCrossInterpreterData(PyObject *, _PyCrossInterpreterData *); -PyAPI_FUNC(PyObject *) _PyCrossInterpreterData_NewObject(_PyCrossInterpreterData *); -PyAPI_FUNC(void) _PyCrossInterpreterData_Release(_PyCrossInterpreterData *); - -/* cross-interpreter data registry */ - -/* For now we use a global registry of shareable classes. An - alternative would be to add a tp_* slot for a class's - crossinterpdatafunc. It would be simpler and more efficient. */ - -PyAPI_FUNC(int) _PyCrossInterpreterData_Register_Class(PyTypeObject *, crossinterpdatafunc); -PyAPI_FUNC(crossinterpdatafunc) _PyCrossInterpreterData_Lookup(PyObject *); - -struct _xidregitem; - -struct _xidregitem { - PyTypeObject *cls; - crossinterpdatafunc getdata; - struct _xidregitem *next; -}; - - /* Full Python runtime state */ typedef struct pyruntimestate { @@ -163,11 +94,6 @@ typedef struct pyruntimestate { using a Python int. */ int64_t next_id; } interpreters; - // XXX Remove this field once we have a tp_* slot. - struct _xidregistry { - PyThread_type_lock mutex; - struct _xidregitem *head; - } xidregistry; #define NEXITFUNCS 32 void (*exitfuncs[NEXITFUNCS])(void); diff --git a/Lib/test/test__xxsubinterpreters.py b/Lib/test/test__xxsubinterpreters.py deleted file mode 100644 index 4ef77716c662..000000000000 --- a/Lib/test/test__xxsubinterpreters.py +++ /dev/null @@ -1,1229 +0,0 @@ -import contextlib -import os -import pickle -from textwrap import dedent, indent -import threading -import time -import unittest - -from test import support -from test.support import script_helper - -interpreters = support.import_module('_xxsubinterpreters') - - -def _captured_script(script): - r, w = os.pipe() - indented = script.replace('\n', '\n ') - wrapped = dedent(f""" - import contextlib - with open({w}, 'w') as chan: - with contextlib.redirect_stdout(chan): - {indented} - """) - return wrapped, open(r) - - -def _run_output(interp, request, shared=None): - script, chan = _captured_script(request) - with chan: - interpreters.run_string(interp, script, shared) - return chan.read() - - - at contextlib.contextmanager -def _running(interp): - r, w = os.pipe() - def run(): - interpreters.run_string(interp, dedent(f""" - # wait for "signal" - with open({r}) as chan: - chan.read() - """)) - - t = threading.Thread(target=run) - t.start() - - yield - - with open(w, 'w') as chan: - chan.write('done') - t.join() - - -class IsShareableTests(unittest.TestCase): - - def test_default_shareables(self): - shareables = [ - # singletons - None, - # builtin objects - b'spam', - ] - for obj in shareables: - with self.subTest(obj): - self.assertTrue( - interpreters.is_shareable(obj)) - - def test_not_shareable(self): - class Cheese: - def __init__(self, name): - self.name = name - def __str__(self): - return self.name - - class SubBytes(bytes): - """A subclass of a shareable type.""" - - not_shareables = [ - # singletons - True, - False, - NotImplemented, - ..., - # builtin types and objects - type, - object, - object(), - Exception(), - 42, - 100.0, - 'spam', - # user-defined types and objects - Cheese, - Cheese('Wensleydale'), - SubBytes(b'spam'), - ] - for obj in not_shareables: - with self.subTest(obj): - self.assertFalse( - interpreters.is_shareable(obj)) - - -class TestBase(unittest.TestCase): - - def tearDown(self): - for id in interpreters.list_all(): - if id == 0: # main - continue - try: - interpreters.destroy(id) - except RuntimeError: - pass # already destroyed - - for cid in interpreters.channel_list_all(): - try: - interpreters.channel_destroy(cid) - except interpreters.ChannelNotFoundError: - pass # already destroyed - - -class ListAllTests(TestBase): - - def test_initial(self): - main = interpreters.get_main() - ids = interpreters.list_all() - self.assertEqual(ids, [main]) - - def test_after_creating(self): - main = interpreters.get_main() - first = interpreters.create() - second = interpreters.create() - ids = interpreters.list_all() - self.assertEqual(ids, [main, first, second]) - - def test_after_destroying(self): - main = interpreters.get_main() - first = interpreters.create() - second = interpreters.create() - interpreters.destroy(first) - ids = interpreters.list_all() - self.assertEqual(ids, [main, second]) - - -class GetCurrentTests(TestBase): - - def test_main(self): - main = interpreters.get_main() - cur = interpreters.get_current() - self.assertEqual(cur, main) - - def test_subinterpreter(self): - main = interpreters.get_main() - interp = interpreters.create() - out = _run_output(interp, dedent(""" - import _xxsubinterpreters as _interpreters - print(int(_interpreters.get_current())) - """)) - cur = int(out.strip()) - _, expected = interpreters.list_all() - self.assertEqual(cur, expected) - self.assertNotEqual(cur, main) - - -class GetMainTests(TestBase): - - def test_from_main(self): - [expected] = interpreters.list_all() - main = interpreters.get_main() - self.assertEqual(main, expected) - - def test_from_subinterpreter(self): - [expected] = interpreters.list_all() - interp = interpreters.create() - out = _run_output(interp, dedent(""" - import _xxsubinterpreters as _interpreters - print(int(_interpreters.get_main())) - """)) - main = int(out.strip()) - self.assertEqual(main, expected) - - -class IsRunningTests(TestBase): - - def test_main(self): - main = interpreters.get_main() - self.assertTrue(interpreters.is_running(main)) - - def test_subinterpreter(self): - interp = interpreters.create() - self.assertFalse(interpreters.is_running(interp)) - - with _running(interp): - self.assertTrue(interpreters.is_running(interp)) - self.assertFalse(interpreters.is_running(interp)) - - def test_from_subinterpreter(self): - interp = interpreters.create() - out = _run_output(interp, dedent(f""" - import _xxsubinterpreters as _interpreters - if _interpreters.is_running({int(interp)}): - print(True) - else: - print(False) - """)) - self.assertEqual(out.strip(), 'True') - - def test_already_destroyed(self): - interp = interpreters.create() - interpreters.destroy(interp) - with self.assertRaises(RuntimeError): - interpreters.is_running(interp) - - def test_does_not_exist(self): - with self.assertRaises(RuntimeError): - interpreters.is_running(1_000_000) - - def test_bad_id(self): - with self.assertRaises(RuntimeError): - interpreters.is_running(-1) - - -class InterpreterIDTests(TestBase): - - def test_with_int(self): - id = interpreters.InterpreterID(10, force=True) - - self.assertEqual(int(id), 10) - - def test_coerce_id(self): - id = interpreters.InterpreterID('10', force=True) - self.assertEqual(int(id), 10) - - id = interpreters.InterpreterID(10.0, force=True) - self.assertEqual(int(id), 10) - - class Int(str): - def __init__(self, value): - self._value = value - def __int__(self): - return self._value - - id = interpreters.InterpreterID(Int(10), force=True) - self.assertEqual(int(id), 10) - - def test_bad_id(self): - for id in [-1, 'spam']: - with self.subTest(id): - with self.assertRaises(ValueError): - interpreters.InterpreterID(id) - with self.assertRaises(OverflowError): - interpreters.InterpreterID(2**64) - with self.assertRaises(TypeError): - interpreters.InterpreterID(object()) - - def test_does_not_exist(self): - id = interpreters.channel_create() - with self.assertRaises(RuntimeError): - interpreters.InterpreterID(int(id) + 1) # unforced - - def test_repr(self): - id = interpreters.InterpreterID(10, force=True) - self.assertEqual(repr(id), 'InterpreterID(10)') - - def test_equality(self): - id1 = interpreters.create() - id2 = interpreters.InterpreterID(int(id1)) - id3 = interpreters.create() - - self.assertTrue(id1 == id1) - self.assertTrue(id1 == id2) - self.assertTrue(id1 == int(id1)) - self.assertFalse(id1 == id3) - - self.assertFalse(id1 != id1) - self.assertFalse(id1 != id2) - self.assertTrue(id1 != id3) - - -class CreateTests(TestBase): - - def test_in_main(self): - id = interpreters.create() - - self.assertIn(id, interpreters.list_all()) - - @unittest.skip('enable this test when working on pystate.c') - def test_unique_id(self): - seen = set() - for _ in range(100): - id = interpreters.create() - interpreters.destroy(id) - seen.add(id) - - self.assertEqual(len(seen), 100) - - def test_in_thread(self): - lock = threading.Lock() - id = None - def f(): - nonlocal id - id = interpreters.create() - lock.acquire() - lock.release() - - t = threading.Thread(target=f) - with lock: - t.start() - t.join() - self.assertIn(id, interpreters.list_all()) - - def test_in_subinterpreter(self): - main, = interpreters.list_all() - id1 = interpreters.create() - out = _run_output(id1, dedent(""" - import _xxsubinterpreters as _interpreters - id = _interpreters.create() - print(int(id)) - """)) - id2 = int(out.strip()) - - self.assertEqual(set(interpreters.list_all()), {main, id1, id2}) - - def test_in_threaded_subinterpreter(self): - main, = interpreters.list_all() - id1 = interpreters.create() - id2 = None - def f(): - nonlocal id2 - out = _run_output(id1, dedent(""" - import _xxsubinterpreters as _interpreters - id = _interpreters.create() - print(int(id)) - """)) - id2 = int(out.strip()) - - t = threading.Thread(target=f) - t.start() - t.join() - - self.assertEqual(set(interpreters.list_all()), {main, id1, id2}) - - def test_after_destroy_all(self): - before = set(interpreters.list_all()) - # Create 3 subinterpreters. - ids = [] - for _ in range(3): - id = interpreters.create() - ids.append(id) - # Now destroy them. - for id in ids: - interpreters.destroy(id) - # Finally, create another. - id = interpreters.create() - self.assertEqual(set(interpreters.list_all()), before | {id}) - - def test_after_destroy_some(self): - before = set(interpreters.list_all()) - # Create 3 subinterpreters. - id1 = interpreters.create() - id2 = interpreters.create() - id3 = interpreters.create() - # Now destroy 2 of them. - interpreters.destroy(id1) - interpreters.destroy(id3) - # Finally, create another. - id = interpreters.create() - self.assertEqual(set(interpreters.list_all()), before | {id, id2}) - - -class DestroyTests(TestBase): - - def test_one(self): - id1 = interpreters.create() - id2 = interpreters.create() - id3 = interpreters.create() - self.assertIn(id2, interpreters.list_all()) - interpreters.destroy(id2) - self.assertNotIn(id2, interpreters.list_all()) - self.assertIn(id1, interpreters.list_all()) - self.assertIn(id3, interpreters.list_all()) - - def test_all(self): - before = set(interpreters.list_all()) - ids = set() - for _ in range(3): - id = interpreters.create() - ids.add(id) - self.assertEqual(set(interpreters.list_all()), before | ids) - for id in ids: - interpreters.destroy(id) - self.assertEqual(set(interpreters.list_all()), before) - - def test_main(self): - main, = interpreters.list_all() - with self.assertRaises(RuntimeError): - interpreters.destroy(main) - - def f(): - with self.assertRaises(RuntimeError): - interpreters.destroy(main) - - t = threading.Thread(target=f) - t.start() - t.join() - - def test_already_destroyed(self): - id = interpreters.create() - interpreters.destroy(id) - with self.assertRaises(RuntimeError): - interpreters.destroy(id) - - def test_does_not_exist(self): - with self.assertRaises(RuntimeError): - interpreters.destroy(1_000_000) - - def test_bad_id(self): - with self.assertRaises(RuntimeError): - interpreters.destroy(-1) - - def test_from_current(self): - main, = interpreters.list_all() - id = interpreters.create() - script = dedent(f""" - import _xxsubinterpreters as _interpreters - try: - _interpreters.destroy({int(id)}) - except RuntimeError: - pass - """) - - interpreters.run_string(id, script) - self.assertEqual(set(interpreters.list_all()), {main, id}) - - def test_from_sibling(self): - main, = interpreters.list_all() - id1 = interpreters.create() - id2 = interpreters.create() - script = dedent(f""" - import _xxsubinterpreters as _interpreters - _interpreters.destroy({int(id2)}) - """) - interpreters.run_string(id1, script) - - self.assertEqual(set(interpreters.list_all()), {main, id1}) - - def test_from_other_thread(self): - id = interpreters.create() - def f(): - interpreters.destroy(id) - - t = threading.Thread(target=f) - t.start() - t.join() - - def test_still_running(self): - main, = interpreters.list_all() - interp = interpreters.create() - with _running(interp): - with self.assertRaises(RuntimeError): - interpreters.destroy(interp) - self.assertTrue(interpreters.is_running(interp)) - - -class RunStringTests(TestBase): - - SCRIPT = dedent(""" - with open('{}', 'w') as out: - out.write('{}') - """) - FILENAME = 'spam' - - def setUp(self): - super().setUp() - self.id = interpreters.create() - self._fs = None - - def tearDown(self): - if self._fs is not None: - self._fs.close() - super().tearDown() - - @property - def fs(self): - if self._fs is None: - self._fs = FSFixture(self) - return self._fs - - def test_success(self): - script, file = _captured_script('print("it worked!", end="")') - with file: - interpreters.run_string(self.id, script) - out = file.read() - - self.assertEqual(out, 'it worked!') - - def test_in_thread(self): - script, file = _captured_script('print("it worked!", end="")') - with file: - def f(): - interpreters.run_string(self.id, script) - - t = threading.Thread(target=f) - t.start() - t.join() - out = file.read() - - self.assertEqual(out, 'it worked!') - - def test_create_thread(self): - script, file = _captured_script(""" - import threading - def f(): - print('it worked!', end='') - - t = threading.Thread(target=f) - t.start() - t.join() - """) - with file: - interpreters.run_string(self.id, script) - out = file.read() - - self.assertEqual(out, 'it worked!') - - @unittest.skipUnless(hasattr(os, 'fork'), "test needs os.fork()") - def test_fork(self): - import tempfile - with tempfile.NamedTemporaryFile('w+') as file: - file.write('') - file.flush() - - expected = 'spam spam spam spam spam' - script = dedent(f""" - # (inspired by Lib/test/test_fork.py) - import os - pid = os.fork() - if pid == 0: # child - with open('{file.name}', 'w') as out: - out.write('{expected}') - # Kill the unittest runner in the child process. - os._exit(1) - else: - SHORT_SLEEP = 0.1 - import time - for _ in range(10): - spid, status = os.waitpid(pid, os.WNOHANG) - if spid == pid: - break - time.sleep(SHORT_SLEEP) - assert(spid == pid) - """) - interpreters.run_string(self.id, script) - - file.seek(0) - content = file.read() - self.assertEqual(content, expected) - - def test_already_running(self): - with _running(self.id): - with self.assertRaises(RuntimeError): - interpreters.run_string(self.id, 'print("spam")') - - def test_does_not_exist(self): - id = 0 - while id in interpreters.list_all(): - id += 1 - with self.assertRaises(RuntimeError): - interpreters.run_string(id, 'print("spam")') - - def test_error_id(self): - with self.assertRaises(RuntimeError): - interpreters.run_string(-1, 'print("spam")') - - def test_bad_id(self): - with self.assertRaises(TypeError): - interpreters.run_string('spam', 'print("spam")') - - def test_bad_script(self): - with self.assertRaises(TypeError): - interpreters.run_string(self.id, 10) - - def test_bytes_for_script(self): - with self.assertRaises(TypeError): - interpreters.run_string(self.id, b'print("spam")') - - @contextlib.contextmanager - def assert_run_failed(self, exctype, msg=None): - with self.assertRaises(interpreters.RunFailedError) as caught: - yield - if msg is None: - self.assertEqual(str(caught.exception).split(':')[0], - str(exctype)) - else: - self.assertEqual(str(caught.exception), - "{}: {}".format(exctype, msg)) - - def test_invalid_syntax(self): - with self.assert_run_failed(SyntaxError): - # missing close paren - interpreters.run_string(self.id, 'print("spam"') - - def test_failure(self): - with self.assert_run_failed(Exception, 'spam'): - interpreters.run_string(self.id, 'raise Exception("spam")') - - def test_SystemExit(self): - with self.assert_run_failed(SystemExit, '42'): - interpreters.run_string(self.id, 'raise SystemExit(42)') - - def test_sys_exit(self): - with self.assert_run_failed(SystemExit): - interpreters.run_string(self.id, dedent(""" - import sys - sys.exit() - """)) - - with self.assert_run_failed(SystemExit, '42'): - interpreters.run_string(self.id, dedent(""" - import sys - sys.exit(42) - """)) - - def test_with_shared(self): - r, w = os.pipe() - - shared = { - 'spam': b'ham', - 'eggs': b'-1', - 'cheddar': None, - } - script = dedent(f""" - eggs = int(eggs) - spam = 42 - result = spam + eggs - - ns = dict(vars()) - del ns['__builtins__'] - import pickle - with open({w}, 'wb') as chan: - pickle.dump(ns, chan) - """) - interpreters.run_string(self.id, script, shared) - with open(r, 'rb') as chan: - ns = pickle.load(chan) - - self.assertEqual(ns['spam'], 42) - self.assertEqual(ns['eggs'], -1) - self.assertEqual(ns['result'], 41) - self.assertIsNone(ns['cheddar']) - - def test_shared_overwrites(self): - interpreters.run_string(self.id, dedent(""" - spam = 'eggs' - ns1 = dict(vars()) - del ns1['__builtins__'] - """)) - - shared = {'spam': b'ham'} - script = dedent(f""" - ns2 = dict(vars()) - del ns2['__builtins__'] - """) - interpreters.run_string(self.id, script, shared) - - r, w = os.pipe() - script = dedent(f""" - ns = dict(vars()) - del ns['__builtins__'] - import pickle - with open({w}, 'wb') as chan: - pickle.dump(ns, chan) - """) - interpreters.run_string(self.id, script) - with open(r, 'rb') as chan: - ns = pickle.load(chan) - - self.assertEqual(ns['ns1']['spam'], 'eggs') - self.assertEqual(ns['ns2']['spam'], b'ham') - self.assertEqual(ns['spam'], b'ham') - - def test_shared_overwrites_default_vars(self): - r, w = os.pipe() - - shared = {'__name__': b'not __main__'} - script = dedent(f""" - spam = 42 - - ns = dict(vars()) - del ns['__builtins__'] - import pickle - with open({w}, 'wb') as chan: - pickle.dump(ns, chan) - """) - interpreters.run_string(self.id, script, shared) - with open(r, 'rb') as chan: - ns = pickle.load(chan) - - self.assertEqual(ns['__name__'], b'not __main__') - - def test_main_reused(self): - r, w = os.pipe() - interpreters.run_string(self.id, dedent(f""" - spam = True - - ns = dict(vars()) - del ns['__builtins__'] - import pickle - with open({w}, 'wb') as chan: - pickle.dump(ns, chan) - del ns, pickle, chan - """)) - with open(r, 'rb') as chan: - ns1 = pickle.load(chan) - - r, w = os.pipe() - interpreters.run_string(self.id, dedent(f""" - eggs = False - - ns = dict(vars()) - del ns['__builtins__'] - import pickle - with open({w}, 'wb') as chan: - pickle.dump(ns, chan) - """)) - with open(r, 'rb') as chan: - ns2 = pickle.load(chan) - - self.assertIn('spam', ns1) - self.assertNotIn('eggs', ns1) - self.assertIn('eggs', ns2) - self.assertIn('spam', ns2) - - def test_execution_namespace_is_main(self): - r, w = os.pipe() - - script = dedent(f""" - spam = 42 - - ns = dict(vars()) - ns['__builtins__'] = str(ns['__builtins__']) - import pickle - with open({w}, 'wb') as chan: - pickle.dump(ns, chan) - """) - interpreters.run_string(self.id, script) - with open(r, 'rb') as chan: - ns = pickle.load(chan) - - ns.pop('__builtins__') - ns.pop('__loader__') - self.assertEqual(ns, { - '__name__': '__main__', - '__annotations__': {}, - '__doc__': None, - '__package__': None, - '__spec__': None, - 'spam': 42, - }) - - # XXX Fix this test! - @unittest.skip('blocking forever') - def test_still_running_at_exit(self): - script = dedent(f""" - from textwrap import dedent - import threading - import _xxsubinterpreters as _interpreters - id = _interpreters.create() - def f(): - _interpreters.run_string(id, dedent(''' - import time - # Give plenty of time for the main interpreter to finish. - time.sleep(1_000_000) - ''')) - - t = threading.Thread(target=f) - t.start() - """) - with support.temp_dir() as dirname: - filename = script_helper.make_script(dirname, 'interp', script) - with script_helper.spawn_python(filename) as proc: - retcode = proc.wait() - - self.assertEqual(retcode, 0) - - -class ChannelIDTests(TestBase): - - def test_default_kwargs(self): - cid = interpreters._channel_id(10, force=True) - - self.assertEqual(int(cid), 10) - self.assertEqual(cid.end, 'both') - - def test_with_kwargs(self): - cid = interpreters._channel_id(10, send=True, force=True) - self.assertEqual(cid.end, 'send') - - cid = interpreters._channel_id(10, send=True, recv=False, force=True) - self.assertEqual(cid.end, 'send') - - cid = interpreters._channel_id(10, recv=True, force=True) - self.assertEqual(cid.end, 'recv') - - cid = interpreters._channel_id(10, recv=True, send=False, force=True) - self.assertEqual(cid.end, 'recv') - - cid = interpreters._channel_id(10, send=True, recv=True, force=True) - self.assertEqual(cid.end, 'both') - - def test_coerce_id(self): - cid = interpreters._channel_id('10', force=True) - self.assertEqual(int(cid), 10) - - cid = interpreters._channel_id(10.0, force=True) - self.assertEqual(int(cid), 10) - - class Int(str): - def __init__(self, value): - self._value = value - def __int__(self): - return self._value - - cid = interpreters._channel_id(Int(10), force=True) - self.assertEqual(int(cid), 10) - - def test_bad_id(self): - for cid in [-1, 'spam']: - with self.subTest(cid): - with self.assertRaises(ValueError): - interpreters._channel_id(cid) - with self.assertRaises(OverflowError): - interpreters._channel_id(2**64) - with self.assertRaises(TypeError): - interpreters._channel_id(object()) - - def test_bad_kwargs(self): - with self.assertRaises(ValueError): - interpreters._channel_id(10, send=False, recv=False) - - def test_does_not_exist(self): - cid = interpreters.channel_create() - with self.assertRaises(interpreters.ChannelNotFoundError): - interpreters._channel_id(int(cid) + 1) # unforced - - def test_repr(self): - cid = interpreters._channel_id(10, force=True) - self.assertEqual(repr(cid), 'ChannelID(10)') - - cid = interpreters._channel_id(10, send=True, force=True) - self.assertEqual(repr(cid), 'ChannelID(10, send=True)') - - cid = interpreters._channel_id(10, recv=True, force=True) - self.assertEqual(repr(cid), 'ChannelID(10, recv=True)') - - cid = interpreters._channel_id(10, send=True, recv=True, force=True) - self.assertEqual(repr(cid), 'ChannelID(10)') - - def test_equality(self): - cid1 = interpreters.channel_create() - cid2 = interpreters._channel_id(int(cid1)) - cid3 = interpreters.channel_create() - - self.assertTrue(cid1 == cid1) - self.assertTrue(cid1 == cid2) - self.assertTrue(cid1 == int(cid1)) - self.assertFalse(cid1 == cid3) - - self.assertFalse(cid1 != cid1) - self.assertFalse(cid1 != cid2) - self.assertTrue(cid1 != cid3) - - -class ChannelTests(TestBase): - - def test_sequential_ids(self): - before = interpreters.channel_list_all() - id1 = interpreters.channel_create() - id2 = interpreters.channel_create() - id3 = interpreters.channel_create() - after = interpreters.channel_list_all() - - self.assertEqual(id2, int(id1) + 1) - self.assertEqual(id3, int(id2) + 1) - self.assertEqual(set(after) - set(before), {id1, id2, id3}) - - def test_ids_global(self): - id1 = interpreters.create() - out = _run_output(id1, dedent(""" - import _xxsubinterpreters as _interpreters - cid = _interpreters.channel_create() - print(int(cid)) - """)) - cid1 = int(out.strip()) - - id2 = interpreters.create() - out = _run_output(id2, dedent(""" - import _xxsubinterpreters as _interpreters - cid = _interpreters.channel_create() - print(int(cid)) - """)) - cid2 = int(out.strip()) - - self.assertEqual(cid2, int(cid1) + 1) - - #################### - - def test_drop_single_user(self): - cid = interpreters.channel_create() - interpreters.channel_send(cid, b'spam') - interpreters.channel_recv(cid) - interpreters.channel_drop_interpreter(cid, send=True, recv=True) - - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_send(cid, b'eggs') - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_recv(cid) - - def test_drop_multiple_users(self): - cid = interpreters.channel_create() - id1 = interpreters.create() - id2 = interpreters.create() - interpreters.run_string(id1, dedent(f""" - import _xxsubinterpreters as _interpreters - _interpreters.channel_send({int(cid)}, b'spam') - """)) - out = _run_output(id2, dedent(f""" - import _xxsubinterpreters as _interpreters - obj = _interpreters.channel_recv({int(cid)}) - _interpreters.channel_drop_interpreter({int(cid)}) - print(repr(obj)) - """)) - interpreters.run_string(id1, dedent(f""" - _interpreters.channel_drop_interpreter({int(cid)}) - """)) - - self.assertEqual(out.strip(), "b'spam'") - - def test_drop_no_kwargs(self): - cid = interpreters.channel_create() - interpreters.channel_send(cid, b'spam') - interpreters.channel_recv(cid) - interpreters.channel_drop_interpreter(cid) - - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_send(cid, b'eggs') - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_recv(cid) - - def test_drop_multiple_times(self): - cid = interpreters.channel_create() - interpreters.channel_send(cid, b'spam') - interpreters.channel_recv(cid) - interpreters.channel_drop_interpreter(cid, send=True, recv=True) - - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_drop_interpreter(cid, send=True, recv=True) - - def test_drop_with_unused_items(self): - cid = interpreters.channel_create() - interpreters.channel_send(cid, b'spam') - interpreters.channel_send(cid, b'ham') - interpreters.channel_drop_interpreter(cid, send=True, recv=True) - - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_recv(cid) - - def test_drop_never_used(self): - cid = interpreters.channel_create() - interpreters.channel_drop_interpreter(cid) - - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_send(cid, b'spam') - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_recv(cid) - - def test_drop_by_unassociated_interp(self): - cid = interpreters.channel_create() - interpreters.channel_send(cid, b'spam') - interp = interpreters.create() - interpreters.run_string(interp, dedent(f""" - import _xxsubinterpreters as _interpreters - _interpreters.channel_drop_interpreter({int(cid)}) - """)) - obj = interpreters.channel_recv(cid) - interpreters.channel_drop_interpreter(cid) - - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_send(cid, b'eggs') - self.assertEqual(obj, b'spam') - - def test_drop_close_if_unassociated(self): - cid = interpreters.channel_create() - interp = interpreters.create() - interpreters.run_string(interp, dedent(f""" - import _xxsubinterpreters as _interpreters - obj = _interpreters.channel_send({int(cid)}, b'spam') - _interpreters.channel_drop_interpreter({int(cid)}) - """)) - - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_recv(cid) - - def test_drop_partially(self): - # XXX Is partial close too weird/confusing? - cid = interpreters.channel_create() - interpreters.channel_send(cid, None) - interpreters.channel_recv(cid) - interpreters.channel_send(cid, b'spam') - interpreters.channel_drop_interpreter(cid, send=True) - obj = interpreters.channel_recv(cid) - - self.assertEqual(obj, b'spam') - - def test_drop_used_multiple_times_by_single_user(self): - cid = interpreters.channel_create() - interpreters.channel_send(cid, b'spam') - interpreters.channel_send(cid, b'spam') - interpreters.channel_send(cid, b'spam') - interpreters.channel_recv(cid) - interpreters.channel_drop_interpreter(cid, send=True, recv=True) - - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_send(cid, b'eggs') - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_recv(cid) - - #################### - - def test_close_single_user(self): - cid = interpreters.channel_create() - interpreters.channel_send(cid, b'spam') - interpreters.channel_recv(cid) - interpreters.channel_close(cid) - - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_send(cid, b'eggs') - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_recv(cid) - - def test_close_multiple_users(self): - cid = interpreters.channel_create() - id1 = interpreters.create() - id2 = interpreters.create() - interpreters.run_string(id1, dedent(f""" - import _xxsubinterpreters as _interpreters - _interpreters.channel_send({int(cid)}, b'spam') - """)) - interpreters.run_string(id2, dedent(f""" - import _xxsubinterpreters as _interpreters - _interpreters.channel_recv({int(cid)}) - """)) - interpreters.channel_close(cid) - with self.assertRaises(interpreters.RunFailedError) as cm: - interpreters.run_string(id1, dedent(f""" - _interpreters.channel_send({int(cid)}, b'spam') - """)) - self.assertIn('ChannelClosedError', str(cm.exception)) - with self.assertRaises(interpreters.RunFailedError) as cm: - interpreters.run_string(id2, dedent(f""" - _interpreters.channel_send({int(cid)}, b'spam') - """)) - self.assertIn('ChannelClosedError', str(cm.exception)) - - def test_close_multiple_times(self): - cid = interpreters.channel_create() - interpreters.channel_send(cid, b'spam') - interpreters.channel_recv(cid) - interpreters.channel_close(cid) - - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_close(cid) - - def test_close_with_unused_items(self): - cid = interpreters.channel_create() - interpreters.channel_send(cid, b'spam') - interpreters.channel_send(cid, b'ham') - interpreters.channel_close(cid) - - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_recv(cid) - - def test_close_never_used(self): - cid = interpreters.channel_create() - interpreters.channel_close(cid) - - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_send(cid, b'spam') - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_recv(cid) - - def test_close_by_unassociated_interp(self): - cid = interpreters.channel_create() - interpreters.channel_send(cid, b'spam') - interp = interpreters.create() - interpreters.run_string(interp, dedent(f""" - import _xxsubinterpreters as _interpreters - _interpreters.channel_close({int(cid)}) - """)) - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_recv(cid) - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_close(cid) - - def test_close_used_multiple_times_by_single_user(self): - cid = interpreters.channel_create() - interpreters.channel_send(cid, b'spam') - interpreters.channel_send(cid, b'spam') - interpreters.channel_send(cid, b'spam') - interpreters.channel_recv(cid) - interpreters.channel_close(cid) - - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_send(cid, b'eggs') - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_recv(cid) - - #################### - - def test_send_recv_main(self): - cid = interpreters.channel_create() - orig = b'spam' - interpreters.channel_send(cid, orig) - obj = interpreters.channel_recv(cid) - - self.assertEqual(obj, orig) - self.assertIsNot(obj, orig) - - def test_send_recv_same_interpreter(self): - id1 = interpreters.create() - out = _run_output(id1, dedent(""" - import _xxsubinterpreters as _interpreters - cid = _interpreters.channel_create() - orig = b'spam' - _interpreters.channel_send(cid, orig) - obj = _interpreters.channel_recv(cid) - assert obj is not orig - assert obj == orig - """)) - - def test_send_recv_different_interpreters(self): - cid = interpreters.channel_create() - id1 = interpreters.create() - out = _run_output(id1, dedent(f""" - import _xxsubinterpreters as _interpreters - _interpreters.channel_send({int(cid)}, b'spam') - """)) - obj = interpreters.channel_recv(cid) - - self.assertEqual(obj, b'spam') - - def test_send_recv_different_threads(self): - cid = interpreters.channel_create() - - def f(): - while True: - try: - obj = interpreters.channel_recv(cid) - break - except interpreters.ChannelEmptyError: - time.sleep(0.1) - interpreters.channel_send(cid, obj) - t = threading.Thread(target=f) - t.start() - - interpreters.channel_send(cid, b'spam') - t.join() - obj = interpreters.channel_recv(cid) - - self.assertEqual(obj, b'spam') - - def test_send_recv_different_interpreters_and_threads(self): - cid = interpreters.channel_create() - id1 = interpreters.create() - out = None - - def f(): - nonlocal out - out = _run_output(id1, dedent(f""" - import time - import _xxsubinterpreters as _interpreters - while True: - try: - obj = _interpreters.channel_recv({int(cid)}) - break - except _interpreters.ChannelEmptyError: - time.sleep(0.1) - assert(obj == b'spam') - _interpreters.channel_send({int(cid)}, b'eggs') - """)) - t = threading.Thread(target=f) - t.start() - - interpreters.channel_send(cid, b'spam') - t.join() - obj = interpreters.channel_recv(cid) - - self.assertEqual(obj, b'eggs') - - def test_send_not_found(self): - with self.assertRaises(interpreters.ChannelNotFoundError): - interpreters.channel_send(10, b'spam') - - def test_recv_not_found(self): - with self.assertRaises(interpreters.ChannelNotFoundError): - interpreters.channel_recv(10) - - def test_recv_empty(self): - cid = interpreters.channel_create() - with self.assertRaises(interpreters.ChannelEmptyError): - interpreters.channel_recv(cid) - - def test_run_string_arg(self): - cid = interpreters.channel_create() - interp = interpreters.create() - - out = _run_output(interp, dedent(""" - import _xxsubinterpreters as _interpreters - print(cid.end) - _interpreters.channel_send(cid, b'spam') - """), - dict(cid=cid.send)) - obj = interpreters.channel_recv(cid) - - self.assertEqual(obj, b'spam') - self.assertEqual(out.strip(), 'send') - - -if __name__ == '__main__': - unittest.main() diff --git a/Misc/NEWS.d/3.7.0b1.rst b/Misc/NEWS.d/3.7.0b1.rst index 185d59c7adf3..3f850904d4be 100644 --- a/Misc/NEWS.d/3.7.0b1.rst +++ b/Misc/NEWS.d/3.7.0b1.rst @@ -748,6 +748,8 @@ subinterpreter C-API and a new cross-interpreter data sharing mechanism. The module is primarily intended for more thorough testing of the existing subinterpreter support. +Note that the _xxsubinterpreters module has been removed in 3.7.0rc1. + .. .. bpo: 32602 diff --git a/Misc/NEWS.d/next/Tests/2018-05-14-13-32-46.bpo-32604.a_z6D_.rst b/Misc/NEWS.d/next/Tests/2018-05-14-13-32-46.bpo-32604.a_z6D_.rst new file mode 100644 index 000000000000..f854dd95412a --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2018-05-14-13-32-46.bpo-32604.a_z6D_.rst @@ -0,0 +1,2 @@ +Remove the _xxsubinterpreters module (meant for testing) and associated +helpers. This module was originally added recently in 3.7b1. diff --git a/Modules/_xxsubinterpretersmodule.c b/Modules/_xxsubinterpretersmodule.c deleted file mode 100644 index 49d3b48e3879..000000000000 --- a/Modules/_xxsubinterpretersmodule.c +++ /dev/null @@ -1,2650 +0,0 @@ - -/* interpreters module */ -/* low-level access to interpreter primitives */ - -#include "Python.h" -#include "frameobject.h" -#include "internal/pystate.h" - - -static char * -_copy_raw_string(PyObject *strobj) -{ - const char *str = PyUnicode_AsUTF8(strobj); - if (str == NULL) { - return NULL; - } - char *copied = PyMem_Malloc(strlen(str)+1); - if (str == NULL) { - PyErr_NoMemory(); - return NULL; - } - strcpy(copied, str); - return copied; -} - -static PyInterpreterState * -_get_current(void) -{ - PyThreadState *tstate = PyThreadState_Get(); - // PyThreadState_Get() aborts if lookup fails, so we don't need - // to check the result for NULL. - return tstate->interp; -} - -static int64_t -_coerce_id(PyObject *id) -{ - id = PyNumber_Long(id); - if (id == NULL) { - if (PyErr_ExceptionMatches(PyExc_TypeError)) { - PyErr_SetString(PyExc_TypeError, - "'id' must be a non-negative int"); - } - else { - PyErr_SetString(PyExc_ValueError, - "'id' must be a non-negative int"); - } - return -1; - } - int64_t cid = PyLong_AsLongLong(id); - Py_DECREF(id); - if (cid == -1 && PyErr_Occurred() != NULL) { - if (!PyErr_ExceptionMatches(PyExc_OverflowError)) { - PyErr_SetString(PyExc_ValueError, - "'id' must be a non-negative int"); - } - return -1; - } - if (cid < 0) { - PyErr_SetString(PyExc_ValueError, - "'id' must be a non-negative int"); - return -1; - } - return cid; -} - - -/* data-sharing-specific code ***********************************************/ - -struct _sharednsitem { - char *name; - _PyCrossInterpreterData data; -}; - -static int -_sharednsitem_init(struct _sharednsitem *item, PyObject *key, PyObject *value) -{ - item->name = _copy_raw_string(key); - if (item->name == NULL) { - return -1; - } - if (_PyObject_GetCrossInterpreterData(value, &item->data) != 0) { - return -1; - } - return 0; -} - -static void -_sharednsitem_clear(struct _sharednsitem *item) -{ - if (item->name != NULL) { - PyMem_Free(item->name); - } - _PyCrossInterpreterData_Release(&item->data); -} - -static int -_sharednsitem_apply(struct _sharednsitem *item, PyObject *ns) -{ - PyObject *name = PyUnicode_FromString(item->name); - if (name == NULL) { - return -1; - } - PyObject *value = _PyCrossInterpreterData_NewObject(&item->data); - if (value == NULL) { - Py_DECREF(name); - return -1; - } - int res = PyDict_SetItem(ns, name, value); - Py_DECREF(name); - Py_DECREF(value); - return res; -} - -typedef struct _sharedns { - Py_ssize_t len; - struct _sharednsitem* items; -} _sharedns; - -static _sharedns * -_sharedns_new(Py_ssize_t len) -{ - _sharedns *shared = PyMem_NEW(_sharedns, 1); - if (shared == NULL) { - PyErr_NoMemory(); - return NULL; - } - shared->len = len; - shared->items = PyMem_NEW(struct _sharednsitem, len); - if (shared->items == NULL) { - PyErr_NoMemory(); - PyMem_Free(shared); - return NULL; - } - return shared; -} - -static void -_sharedns_free(_sharedns *shared) -{ - for (Py_ssize_t i=0; i < shared->len; i++) { - _sharednsitem_clear(&shared->items[i]); - } - PyMem_Free(shared->items); - PyMem_Free(shared); -} - -static _sharedns * -_get_shared_ns(PyObject *shareable) -{ - if (shareable == NULL || shareable == Py_None) { - return NULL; - } - Py_ssize_t len = PyDict_Size(shareable); - if (len == 0) { - return NULL; - } - - _sharedns *shared = _sharedns_new(len); - if (shared == NULL) { - return NULL; - } - Py_ssize_t pos = 0; - for (Py_ssize_t i=0; i < len; i++) { - PyObject *key, *value; - if (PyDict_Next(shareable, &pos, &key, &value) == 0) { - break; - } - if (_sharednsitem_init(&shared->items[i], key, value) != 0) { - break; - } - } - if (PyErr_Occurred()) { - _sharedns_free(shared); - return NULL; - } - return shared; -} - -static int -_sharedns_apply(_sharedns *shared, PyObject *ns) -{ - for (Py_ssize_t i=0; i < shared->len; i++) { - if (_sharednsitem_apply(&shared->items[i], ns) != 0) { - return -1; - } - } - return 0; -} - -// Ultimately we'd like to preserve enough information about the -// exception and traceback that we could re-constitute (or at least -// simulate, a la traceback.TracebackException), and even chain, a copy -// of the exception in the calling interpreter. - -typedef struct _sharedexception { - char *name; - char *msg; -} _sharedexception; - -static _sharedexception * -_sharedexception_new(void) -{ - _sharedexception *err = PyMem_NEW(_sharedexception, 1); - if (err == NULL) { - PyErr_NoMemory(); - return NULL; - } - err->name = NULL; - err->msg = NULL; - return err; -} - -static void -_sharedexception_clear(_sharedexception *exc) -{ - if (exc->name != NULL) { - PyMem_Free(exc->name); - } - if (exc->msg != NULL) { - PyMem_Free(exc->msg); - } -} - -static void -_sharedexception_free(_sharedexception *exc) -{ - _sharedexception_clear(exc); - PyMem_Free(exc); -} - -static _sharedexception * -_sharedexception_bind(PyObject *exctype, PyObject *exc, PyObject *tb) -{ - assert(exctype != NULL); - char *failure = NULL; - - _sharedexception *err = _sharedexception_new(); - if (err == NULL) { - goto finally; - } - - PyObject *name = PyUnicode_FromFormat("%S", exctype); - if (name == NULL) { - failure = "unable to format exception type name"; - goto finally; - } - err->name = _copy_raw_string(name); - Py_DECREF(name); - if (err->name == NULL) { - if (PyErr_ExceptionMatches(PyExc_MemoryError)) { - failure = "out of memory copying exception type name"; - } - failure = "unable to encode and copy exception type name"; - goto finally; - } - - if (exc != NULL) { - PyObject *msg = PyUnicode_FromFormat("%S", exc); - if (msg == NULL) { - failure = "unable to format exception message"; - goto finally; - } - err->msg = _copy_raw_string(msg); - Py_DECREF(msg); - if (err->msg == NULL) { - if (PyErr_ExceptionMatches(PyExc_MemoryError)) { - failure = "out of memory copying exception message"; - } - failure = "unable to encode and copy exception message"; - goto finally; - } - } - -finally: - if (failure != NULL) { - PyErr_Clear(); - if (err->name != NULL) { - PyMem_Free(err->name); - err->name = NULL; - } - err->msg = failure; - } - return err; -} - -static void -_sharedexception_apply(_sharedexception *exc, PyObject *wrapperclass) -{ - if (exc->name != NULL) { - if (exc->msg != NULL) { - PyErr_Format(wrapperclass, "%s: %s", exc->name, exc->msg); - } - else { - PyErr_SetString(wrapperclass, exc->name); - } - } - else if (exc->msg != NULL) { - PyErr_SetString(wrapperclass, exc->msg); - } - else { - PyErr_SetNone(wrapperclass); - } -} - - -/* channel-specific code ****************************************************/ - -static PyObject *ChannelError; -static PyObject *ChannelNotFoundError; -static PyObject *ChannelClosedError; -static PyObject *ChannelEmptyError; - -static int -channel_exceptions_init(PyObject *ns) -{ - // XXX Move the exceptions into per-module memory? - - // A channel-related operation failed. - ChannelError = PyErr_NewException("_xxsubinterpreters.ChannelError", - PyExc_RuntimeError, NULL); - if (ChannelError == NULL) { - return -1; - } - if (PyDict_SetItemString(ns, "ChannelError", ChannelError) != 0) { - return -1; - } - - // An operation tried to use a channel that doesn't exist. - ChannelNotFoundError = PyErr_NewException( - "_xxsubinterpreters.ChannelNotFoundError", ChannelError, NULL); - if (ChannelNotFoundError == NULL) { - return -1; - } - if (PyDict_SetItemString(ns, "ChannelNotFoundError", ChannelNotFoundError) != 0) { - return -1; - } - - // An operation tried to use a closed channel. - ChannelClosedError = PyErr_NewException( - "_xxsubinterpreters.ChannelClosedError", ChannelError, NULL); - if (ChannelClosedError == NULL) { - return -1; - } - if (PyDict_SetItemString(ns, "ChannelClosedError", ChannelClosedError) != 0) { - return -1; - } - - // An operation tried to pop from an empty channel. - ChannelEmptyError = PyErr_NewException( - "_xxsubinterpreters.ChannelEmptyError", ChannelError, NULL); - if (ChannelEmptyError == NULL) { - return -1; - } - if (PyDict_SetItemString(ns, "ChannelEmptyError", ChannelEmptyError) != 0) { - return -1; - } - - return 0; -} - -/* the channel queue */ - -struct _channelitem; - -typedef struct _channelitem { - _PyCrossInterpreterData *data; - struct _channelitem *next; -} _channelitem; - -static _channelitem * -_channelitem_new(void) -{ - _channelitem *item = PyMem_NEW(_channelitem, 1); - if (item == NULL) { - PyErr_NoMemory(); - return NULL; - } - item->data = NULL; - item->next = NULL; - return item; -} - -static void -_channelitem_clear(_channelitem *item) -{ - if (item->data != NULL) { - _PyCrossInterpreterData_Release(item->data); - PyMem_Free(item->data); - item->data = NULL; - } - item->next = NULL; -} - -static void -_channelitem_free(_channelitem *item) -{ - _channelitem_clear(item); - PyMem_Free(item); -} - -static void -_channelitem_free_all(_channelitem *item) -{ - while (item != NULL) { - _channelitem *last = item; - item = item->next; - _channelitem_free(last); - } -} - -static _PyCrossInterpreterData * -_channelitem_popped(_channelitem *item) -{ - _PyCrossInterpreterData *data = item->data; - item->data = NULL; - _channelitem_free(item); - return data; -} - -typedef struct _channelqueue { - int64_t count; - _channelitem *first; - _channelitem *last; -} _channelqueue; - -static _channelqueue * -_channelqueue_new(void) -{ - _channelqueue *queue = PyMem_NEW(_channelqueue, 1); - if (queue == NULL) { - PyErr_NoMemory(); - return NULL; - } - queue->count = 0; - queue->first = NULL; - queue->last = NULL; - return queue; -} - -static void -_channelqueue_clear(_channelqueue *queue) -{ - _channelitem_free_all(queue->first); - queue->count = 0; - queue->first = NULL; - queue->last = NULL; -} - -static void -_channelqueue_free(_channelqueue *queue) -{ - _channelqueue_clear(queue); - PyMem_Free(queue); -} - -static int -_channelqueue_put(_channelqueue *queue, _PyCrossInterpreterData *data) -{ - _channelitem *item = _channelitem_new(); - if (item == NULL) { - return -1; - } - item->data = data; - - queue->count += 1; - if (queue->first == NULL) { - queue->first = item; - } - else { - queue->last->next = item; - } - queue->last = item; - return 0; -} - -static _PyCrossInterpreterData * -_channelqueue_get(_channelqueue *queue) -{ - _channelitem *item = queue->first; - if (item == NULL) { - return NULL; - } - queue->first = item->next; - if (queue->last == item) { - queue->last = NULL; - } - queue->count -= 1; - - return _channelitem_popped(item); -} - -/* channel-interpreter associations */ - -struct _channelend; - -typedef struct _channelend { - struct _channelend *next; - int64_t interp; - int open; -} _channelend; - -static _channelend * -_channelend_new(int64_t interp) -{ - _channelend *end = PyMem_NEW(_channelend, 1); - if (end == NULL) { - PyErr_NoMemory(); - return NULL; - } - end->next = NULL; - end->interp = interp; - end->open = 1; - return end; -} - -static void -_channelend_free(_channelend *end) -{ - PyMem_Free(end); -} - -static void -_channelend_free_all(_channelend *end) -{ - while (end != NULL) { - _channelend *last = end; - end = end->next; - _channelend_free(last); - } -} - -static _channelend * -_channelend_find(_channelend *first, int64_t interp, _channelend **pprev) -{ - _channelend *prev = NULL; - _channelend *end = first; - while (end != NULL) { - if (end->interp == interp) { - break; - } - prev = end; - end = end->next; - } - if (pprev != NULL) { - *pprev = prev; - } - return end; -} - -typedef struct _channelassociations { - // Note that the list entries are never removed for interpreter - // for which the channel is closed. This should be a problem in - // practice. Also, a channel isn't automatically closed when an - // interpreter is destroyed. - int64_t numsendopen; - int64_t numrecvopen; - _channelend *send; - _channelend *recv; -} _channelends; - -static _channelends * -_channelends_new(void) -{ - _channelends *ends = PyMem_NEW(_channelends, 1); - if (ends== NULL) { - return NULL; - } - ends->numsendopen = 0; - ends->numrecvopen = 0; - ends->send = NULL; - ends->recv = NULL; - return ends; -} - -static void -_channelends_clear(_channelends *ends) -{ - _channelend_free_all(ends->send); - ends->send = NULL; - ends->numsendopen = 0; - - _channelend_free_all(ends->recv); - ends->recv = NULL; - ends->numrecvopen = 0; -} - -static void -_channelends_free(_channelends *ends) -{ - _channelends_clear(ends); - PyMem_Free(ends); -} - -static _channelend * -_channelends_add(_channelends *ends, _channelend *prev, int64_t interp, - int send) -{ - _channelend *end = _channelend_new(interp); - if (end == NULL) { - return NULL; - } - - if (prev == NULL) { - if (send) { - ends->send = end; - } - else { - ends->recv = end; - } - } - else { - prev->next = end; - } - if (send) { - ends->numsendopen += 1; - } - else { - ends->numrecvopen += 1; - } - return end; -} - -static int -_channelends_associate(_channelends *ends, int64_t interp, int send) -{ - _channelend *prev; - _channelend *end = _channelend_find(send ? ends->send : ends->recv, - interp, &prev); - if (end != NULL) { - if (!end->open) { - PyErr_SetString(ChannelClosedError, "channel already closed"); - return -1; - } - // already associated - return 0; - } - if (_channelends_add(ends, prev, interp, send) == NULL) { - return -1; - } - return 0; -} - -static int -_channelends_is_open(_channelends *ends) -{ - if (ends->numsendopen != 0 || ends->numrecvopen != 0) { - return 1; - } - if (ends->send == NULL && ends->recv == NULL) { - return 1; - } - return 0; -} - -static void -_channelends_close_end(_channelends *ends, _channelend *end, int send) -{ - end->open = 0; - if (send) { - ends->numsendopen -= 1; - } - else { - ends->numrecvopen -= 1; - } -} - -static int -_channelends_close_interpreter(_channelends *ends, int64_t interp, int which) -{ - _channelend *prev; - _channelend *end; - if (which >= 0) { // send/both - end = _channelend_find(ends->send, interp, &prev); - if (end == NULL) { - // never associated so add it - end = _channelends_add(ends, prev, interp, 1); - if (end == NULL) { - return -1; - } - } - _channelends_close_end(ends, end, 1); - } - if (which <= 0) { // recv/both - end = _channelend_find(ends->recv, interp, &prev); - if (end == NULL) { - // never associated so add it - end = _channelends_add(ends, prev, interp, 0); - if (end == NULL) { - return -1; - } - } - _channelends_close_end(ends, end, 0); - } - return 0; -} - -static void -_channelends_close_all(_channelends *ends) -{ - // Ensure all the "send"-associated interpreters are closed. - _channelend *end; - for (end = ends->send; end != NULL; end = end->next) { - _channelends_close_end(ends, end, 1); - } - - // Ensure all the "recv"-associated interpreters are closed. - for (end = ends->recv; end != NULL; end = end->next) { - _channelends_close_end(ends, end, 0); - } -} - -/* channels */ - -struct _channel; - -typedef struct _channel { - PyThread_type_lock mutex; - _channelqueue *queue; - _channelends *ends; - int open; -} _PyChannelState; - -static _PyChannelState * -_channel_new(void) -{ - _PyChannelState *chan = PyMem_NEW(_PyChannelState, 1); - if (chan == NULL) { - return NULL; - } - chan->mutex = PyThread_allocate_lock(); - if (chan->mutex == NULL) { - PyMem_Free(chan); - PyErr_SetString(ChannelError, - "can't initialize mutex for new channel"); - return NULL; - } - chan->queue = _channelqueue_new(); - if (chan->queue == NULL) { - PyMem_Free(chan); - return NULL; - } - chan->ends = _channelends_new(); - if (chan->ends == NULL) { - _channelqueue_free(chan->queue); - PyMem_Free(chan); - return NULL; - } - chan->open = 1; - return chan; -} - -static void -_channel_free(_PyChannelState *chan) -{ - PyThread_acquire_lock(chan->mutex, WAIT_LOCK); - _channelqueue_free(chan->queue); - _channelends_free(chan->ends); - PyThread_release_lock(chan->mutex); - - PyThread_free_lock(chan->mutex); - PyMem_Free(chan); -} - -static int -_channel_add(_PyChannelState *chan, int64_t interp, - _PyCrossInterpreterData *data) -{ - int res = -1; - PyThread_acquire_lock(chan->mutex, WAIT_LOCK); - - if (!chan->open) { - PyErr_SetString(ChannelClosedError, "channel closed"); - goto done; - } - if (_channelends_associate(chan->ends, interp, 1) != 0) { - goto done; - } - - if (_channelqueue_put(chan->queue, data) != 0) { - goto done; - } - - res = 0; -done: - PyThread_release_lock(chan->mutex); - return res; -} - -static _PyCrossInterpreterData * -_channel_next(_PyChannelState *chan, int64_t interp) -{ - _PyCrossInterpreterData *data = NULL; - PyThread_acquire_lock(chan->mutex, WAIT_LOCK); - - if (!chan->open) { - PyErr_SetString(ChannelClosedError, "channel closed"); - goto done; - } - if (_channelends_associate(chan->ends, interp, 0) != 0) { - goto done; - } - - data = _channelqueue_get(chan->queue); -done: - PyThread_release_lock(chan->mutex); - return data; -} - -static int -_channel_close_interpreter(_PyChannelState *chan, int64_t interp, int which) -{ - PyThread_acquire_lock(chan->mutex, WAIT_LOCK); - - int res = -1; - if (!chan->open) { - PyErr_SetString(ChannelClosedError, "channel already closed"); - goto done; - } - - if (_channelends_close_interpreter(chan->ends, interp, which) != 0) { - goto done; - } - chan->open = _channelends_is_open(chan->ends); - - res = 0; -done: - PyThread_release_lock(chan->mutex); - return res; -} - -static int -_channel_close_all(_PyChannelState *chan) -{ - int res = -1; - PyThread_acquire_lock(chan->mutex, WAIT_LOCK); - - if (!chan->open) { - PyErr_SetString(ChannelClosedError, "channel already closed"); - goto done; - } - - chan->open = 0; - - // We *could* also just leave these in place, since we've marked - // the channel as closed already. - _channelends_close_all(chan->ends); - - res = 0; -done: - PyThread_release_lock(chan->mutex); - return res; -} - -/* the set of channels */ - -struct _channelref; - -typedef struct _channelref { - int64_t id; - _PyChannelState *chan; - struct _channelref *next; - Py_ssize_t objcount; -} _channelref; - -static _channelref * -_channelref_new(int64_t id, _PyChannelState *chan) -{ - _channelref *ref = PyMem_NEW(_channelref, 1); - if (ref == NULL) { - return NULL; - } - ref->id = id; - ref->chan = chan; - ref->next = NULL; - ref->objcount = 0; - return ref; -} - -//static void -//_channelref_clear(_channelref *ref) -//{ -// ref->id = -1; -// ref->chan = NULL; -// ref->next = NULL; -// ref->objcount = 0; -//} - -static void -_channelref_free(_channelref *ref) -{ - //_channelref_clear(ref); - PyMem_Free(ref); -} - -static _channelref * -_channelref_find(_channelref *first, int64_t id, _channelref **pprev) -{ - _channelref *prev = NULL; - _channelref *ref = first; - while (ref != NULL) { - if (ref->id == id) { - break; - } - prev = ref; - ref = ref->next; - } - if (pprev != NULL) { - *pprev = prev; - } - return ref; -} - -typedef struct _channels { - PyThread_type_lock mutex; - _channelref *head; - int64_t numopen; - int64_t next_id; -} _channels; - -static int -_channels_init(_channels *channels) -{ - if (channels->mutex == NULL) { - channels->mutex = PyThread_allocate_lock(); - if (channels->mutex == NULL) { - PyErr_SetString(ChannelError, - "can't initialize mutex for channel management"); - return -1; - } - } - channels->head = NULL; - channels->numopen = 0; - channels->next_id = 0; - return 0; -} - -static int64_t -_channels_next_id(_channels *channels) // needs lock -{ - int64_t id = channels->next_id; - if (id < 0) { - /* overflow */ - PyErr_SetString(ChannelError, - "failed to get a channel ID"); - return -1; - } - channels->next_id += 1; - return id; -} - -static _PyChannelState * -_channels_lookup(_channels *channels, int64_t id, PyThread_type_lock *pmutex) -{ - _PyChannelState *chan = NULL; - PyThread_acquire_lock(channels->mutex, WAIT_LOCK); - if (pmutex != NULL) { - *pmutex = NULL; - } - - _channelref *ref = _channelref_find(channels->head, id, NULL); - if (ref == NULL) { - PyErr_Format(ChannelNotFoundError, "channel %d not found", id); - goto done; - } - if (ref->chan == NULL || !ref->chan->open) { - PyErr_Format(ChannelClosedError, "channel %d closed", id); - goto done; - } - - if (pmutex != NULL) { - // The mutex will be closed by the caller. - *pmutex = channels->mutex; - } - - chan = ref->chan; -done: - if (pmutex == NULL || *pmutex == NULL) { - PyThread_release_lock(channels->mutex); - } - return chan; -} - -static int64_t -_channels_add(_channels *channels, _PyChannelState *chan) -{ - int64_t cid = -1; - PyThread_acquire_lock(channels->mutex, WAIT_LOCK); - - // Create a new ref. - int64_t id = _channels_next_id(channels); - if (id < 0) { - goto done; - } - _channelref *ref = _channelref_new(id, chan); - if (ref == NULL) { - goto done; - } - - // Add it to the list. - // We assume that the channel is a new one (not already in the list). - ref->next = channels->head; - channels->head = ref; - channels->numopen += 1; - - cid = id; -done: - PyThread_release_lock(channels->mutex); - return cid; -} - -static int -_channels_close(_channels *channels, int64_t cid, _PyChannelState **pchan) -{ - int res = -1; - PyThread_acquire_lock(channels->mutex, WAIT_LOCK); - if (pchan != NULL) { - *pchan = NULL; - } - - _channelref *ref = _channelref_find(channels->head, cid, NULL); - if (ref == NULL) { - PyErr_Format(ChannelNotFoundError, "channel %d not found", cid); - goto done; - } - - if (ref->chan == NULL) { - PyErr_Format(ChannelClosedError, "channel %d closed", cid); - goto done; - } - else { - if (_channel_close_all(ref->chan) != 0) { - goto done; - } - if (pchan != NULL) { - *pchan = ref->chan; - } - else { - _channel_free(ref->chan); - } - ref->chan = NULL; - } - - res = 0; -done: - PyThread_release_lock(channels->mutex); - return res; -} - -static void -_channels_remove_ref(_channels *channels, _channelref *ref, _channelref *prev, - _PyChannelState **pchan) -{ - if (ref == channels->head) { - channels->head = ref->next; - } - else { - prev->next = ref->next; - } - channels->numopen -= 1; - - if (pchan != NULL) { - *pchan = ref->chan; - } - _channelref_free(ref); -} - -static int -_channels_remove(_channels *channels, int64_t id, _PyChannelState **pchan) -{ - int res = -1; - PyThread_acquire_lock(channels->mutex, WAIT_LOCK); - - if (pchan != NULL) { - *pchan = NULL; - } - - _channelref *prev = NULL; - _channelref *ref = _channelref_find(channels->head, id, &prev); - if (ref == NULL) { - PyErr_Format(ChannelNotFoundError, "channel %d not found", id); - goto done; - } - - _channels_remove_ref(channels, ref, prev, pchan); - - res = 0; -done: - PyThread_release_lock(channels->mutex); - return res; -} - -static int -_channels_add_id_object(_channels *channels, int64_t id) -{ - int res = -1; - PyThread_acquire_lock(channels->mutex, WAIT_LOCK); - - _channelref *ref = _channelref_find(channels->head, id, NULL); - if (ref == NULL) { - PyErr_Format(ChannelNotFoundError, "channel %d not found", id); - goto done; - } - ref->objcount += 1; - - res = 0; -done: - PyThread_release_lock(channels->mutex); - return res; -} - -static void -_channels_drop_id_object(_channels *channels, int64_t id) -{ - PyThread_acquire_lock(channels->mutex, WAIT_LOCK); - - _channelref *prev = NULL; - _channelref *ref = _channelref_find(channels->head, id, &prev); - if (ref == NULL) { - // Already destroyed. - goto done; - } - ref->objcount -= 1; - - // Destroy if no longer used. - if (ref->objcount == 0) { - _PyChannelState *chan = NULL; - _channels_remove_ref(channels, ref, prev, &chan); - if (chan != NULL) { - _channel_free(chan); - } - } - -done: - PyThread_release_lock(channels->mutex); -} - -int64_t * -_channels_list_all(_channels *channels, int64_t *count) -{ - int64_t *cids = NULL; - PyThread_acquire_lock(channels->mutex, WAIT_LOCK); - int64_t numopen = channels->numopen; - if (numopen >= PY_SSIZE_T_MAX) { - PyErr_SetString(PyExc_RuntimeError, "too many channels open"); - goto done; - } - int64_t *ids = PyMem_NEW(int64_t, (Py_ssize_t)(channels->numopen)); - if (ids == NULL) { - goto done; - } - _channelref *ref = channels->head; - for (int64_t i=0; ref != NULL; ref = ref->next, i++) { - ids[i] = ref->id; - } - *count = channels->numopen; - - cids = ids; -done: - PyThread_release_lock(channels->mutex); - return cids; -} - -/* "high"-level channel-related functions */ - -static int64_t -_channel_create(_channels *channels) -{ - _PyChannelState *chan = _channel_new(); - if (chan == NULL) { - return -1; - } - int64_t id = _channels_add(channels, chan); - if (id < 0) { - _channel_free(chan); - return -1; - } - return id; -} - -static int -_channel_destroy(_channels *channels, int64_t id) -{ - _PyChannelState *chan = NULL; - if (_channels_remove(channels, id, &chan) != 0) { - return -1; - } - if (chan != NULL) { - _channel_free(chan); - } - return 0; -} - -static int -_channel_send(_channels *channels, int64_t id, PyObject *obj) -{ - PyInterpreterState *interp = _get_current(); - if (interp == NULL) { - return -1; - } - - // Look up the channel. - PyThread_type_lock mutex = NULL; - _PyChannelState *chan = _channels_lookup(channels, id, &mutex); - if (chan == NULL) { - return -1; - } - // Past this point we are responsible for releasing the mutex. - - // Convert the object to cross-interpreter data. - _PyCrossInterpreterData *data = PyMem_NEW(_PyCrossInterpreterData, 1); - if (data == NULL) { - PyThread_release_lock(mutex); - return -1; - } - if (_PyObject_GetCrossInterpreterData(obj, data) != 0) { - PyThread_release_lock(mutex); - return -1; - } - - // Add the data to the channel. - int res = _channel_add(chan, interp->id, data); - PyThread_release_lock(mutex); - if (res != 0) { - _PyCrossInterpreterData_Release(data); - PyMem_Free(data); - return -1; - } - - return 0; -} - -static PyObject * -_channel_recv(_channels *channels, int64_t id) -{ - PyInterpreterState *interp = _get_current(); - if (interp == NULL) { - return NULL; - } - - // Look up the channel. - PyThread_type_lock mutex = NULL; - _PyChannelState *chan = _channels_lookup(channels, id, &mutex); - if (chan == NULL) { - return NULL; - } - // Past this point we are responsible for releasing the mutex. - - // Pop off the next item from the channel. - _PyCrossInterpreterData *data = _channel_next(chan, interp->id); - PyThread_release_lock(mutex); - if (data == NULL) { - PyErr_Format(ChannelEmptyError, "channel %d is empty", id); - return NULL; - } - - // Convert the data back to an object. - PyObject *obj = _PyCrossInterpreterData_NewObject(data); - if (obj == NULL) { - return NULL; - } - _PyCrossInterpreterData_Release(data); - PyMem_Free(data); - - return obj; -} - -static int -_channel_drop(_channels *channels, int64_t id, int send, int recv) -{ - PyInterpreterState *interp = _get_current(); - if (interp == NULL) { - return -1; - } - - // Look up the channel. - PyThread_type_lock mutex = NULL; - _PyChannelState *chan = _channels_lookup(channels, id, &mutex); - if (chan == NULL) { - return -1; - } - // Past this point we are responsible for releasing the mutex. - - // Close one or both of the two ends. - int res = _channel_close_interpreter(chan, interp->id, send-recv); - PyThread_release_lock(mutex); - return res; -} - -static int -_channel_close(_channels *channels, int64_t id) -{ - return _channels_close(channels, id, NULL); -} - -/* ChannelID class */ - -#define CHANNEL_SEND 1 -#define CHANNEL_RECV -1 - -static PyTypeObject ChannelIDtype; - -typedef struct channelid { - PyObject_HEAD - int64_t id; - int end; - _channels *channels; -} channelid; - -static channelid * -newchannelid(PyTypeObject *cls, int64_t cid, int end, _channels *channels, - int force) -{ - channelid *self = PyObject_New(channelid, cls); - if (self == NULL) { - return NULL; - } - self->id = cid; - self->end = end; - self->channels = channels; - - if (_channels_add_id_object(channels, cid) != 0) { - if (force && PyErr_ExceptionMatches(ChannelNotFoundError)) { - PyErr_Clear(); - } - else { - Py_DECREF((PyObject *)self); - return NULL; - } - } - - return self; -} - -static _channels * _global_channels(void); - -static PyObject * -channelid_new(PyTypeObject *cls, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"id", "send", "recv", "force", NULL}; - PyObject *id; - int send = -1; - int recv = -1; - int force = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwds, - "O|$ppp:ChannelID.__init__", kwlist, - &id, &send, &recv, &force)) - return NULL; - - // Coerce and check the ID. - int64_t cid; - if (PyObject_TypeCheck(id, &ChannelIDtype)) { - cid = ((channelid *)id)->id; - } - else { - cid = _coerce_id(id); - if (cid < 0) { - return NULL; - } - } - - // Handle "send" and "recv". - if (send == 0 && recv == 0) { - PyErr_SetString(PyExc_ValueError, - "'send' and 'recv' cannot both be False"); - return NULL; - } - - int end = 0; - if (send == 1) { - if (recv == 0 || recv == -1) { - end = CHANNEL_SEND; - } - } - else if (recv == 1) { - end = CHANNEL_RECV; - } - - return (PyObject *)newchannelid(cls, cid, end, _global_channels(), force); -} - -static void -channelid_dealloc(PyObject *v) -{ - int64_t cid = ((channelid *)v)->id; - _channels *channels = ((channelid *)v)->channels; - Py_TYPE(v)->tp_free(v); - - _channels_drop_id_object(channels, cid); -} - -static PyObject * -channelid_repr(PyObject *self) -{ - PyTypeObject *type = Py_TYPE(self); - const char *name = _PyType_Name(type); - - channelid *cid = (channelid *)self; - const char *fmt; - if (cid->end == CHANNEL_SEND) { - fmt = "%s(%d, send=True)"; - } - else if (cid->end == CHANNEL_RECV) { - fmt = "%s(%d, recv=True)"; - } - else { - fmt = "%s(%d)"; - } - return PyUnicode_FromFormat(fmt, name, cid->id); -} - -PyObject * -channelid_int(PyObject *self) -{ - channelid *cid = (channelid *)self; - return PyLong_FromLongLong(cid->id); -} - -static PyNumberMethods channelid_as_number = { - 0, /* nb_add */ - 0, /* nb_subtract */ - 0, /* nb_multiply */ - 0, /* nb_remainder */ - 0, /* nb_divmod */ - 0, /* nb_power */ - 0, /* nb_negative */ - 0, /* nb_positive */ - 0, /* nb_absolute */ - 0, /* nb_bool */ - 0, /* nb_invert */ - 0, /* nb_lshift */ - 0, /* nb_rshift */ - 0, /* nb_and */ - 0, /* nb_xor */ - 0, /* nb_or */ - (unaryfunc)channelid_int, /* nb_int */ - 0, /* nb_reserved */ - 0, /* nb_float */ - - 0, /* nb_inplace_add */ - 0, /* nb_inplace_subtract */ - 0, /* nb_inplace_multiply */ - 0, /* nb_inplace_remainder */ - 0, /* nb_inplace_power */ - 0, /* nb_inplace_lshift */ - 0, /* nb_inplace_rshift */ - 0, /* nb_inplace_and */ - 0, /* nb_inplace_xor */ - 0, /* nb_inplace_or */ - - 0, /* nb_floor_divide */ - 0, /* nb_true_divide */ - 0, /* nb_inplace_floor_divide */ - 0, /* nb_inplace_true_divide */ - - (unaryfunc)channelid_int, /* nb_index */ -}; - -static Py_hash_t -channelid_hash(PyObject *self) -{ - channelid *cid = (channelid *)self; - PyObject *id = PyLong_FromLongLong(cid->id); - if (id == NULL) { - return -1; - } - Py_hash_t hash = PyObject_Hash(id); - Py_DECREF(id); - return hash; -} - -static PyObject * -channelid_richcompare(PyObject *self, PyObject *other, int op) -{ - if (op != Py_EQ && op != Py_NE) { - Py_RETURN_NOTIMPLEMENTED; - } - - if (!PyObject_TypeCheck(self, &ChannelIDtype)) { - Py_RETURN_NOTIMPLEMENTED; - } - - channelid *cid = (channelid *)self; - int equal; - if (PyObject_TypeCheck(other, &ChannelIDtype)) { - channelid *othercid = (channelid *)other; - if (cid->end != othercid->end) { - equal = 0; - } - else { - equal = (cid->id == othercid->id); - } - } - else { - other = PyNumber_Long(other); - if (other == NULL) { - PyErr_Clear(); - Py_RETURN_NOTIMPLEMENTED; - } - int64_t othercid = PyLong_AsLongLong(other); - Py_DECREF(other); - if (othercid == -1 && PyErr_Occurred() != NULL) { - return NULL; - } - if (othercid < 0) { - equal = 0; - } - else { - equal = (cid->id == othercid); - } - } - - if ((op == Py_EQ && equal) || (op == Py_NE && !equal)) { - Py_RETURN_TRUE; - } - Py_RETURN_FALSE; -} - -struct _channelid_xid { - int64_t id; - int end; -}; - -static PyObject * -_channelid_from_xid(_PyCrossInterpreterData *data) -{ - struct _channelid_xid *xid = (struct _channelid_xid *)data->data; - return (PyObject *)newchannelid(&ChannelIDtype, xid->id, xid->end, - _global_channels(), 0); -} - -static int -_channelid_shared(PyObject *obj, _PyCrossInterpreterData *data) -{ - struct _channelid_xid *xid = PyMem_NEW(struct _channelid_xid, 1); - if (xid == NULL) { - return -1; - } - xid->id = ((channelid *)obj)->id; - xid->end = ((channelid *)obj)->end; - - data->data = xid; - data->obj = obj; - data->new_object = _channelid_from_xid; - data->free = PyMem_Free; - return 0; -} - -static PyObject * -channelid_end(PyObject *self, void *end) -{ - int force = 1; - channelid *cid = (channelid *)self; - if (end != NULL) { - return (PyObject *)newchannelid(Py_TYPE(self), cid->id, *(int *)end, - cid->channels, force); - } - - if (cid->end == CHANNEL_SEND) { - return PyUnicode_InternFromString("send"); - } - if (cid->end == CHANNEL_RECV) { - return PyUnicode_InternFromString("recv"); - } - return PyUnicode_InternFromString("both"); -} - -static int _channelid_end_send = CHANNEL_SEND; -static int _channelid_end_recv = CHANNEL_RECV; - -static PyGetSetDef channelid_getsets[] = { - {"end", (getter)channelid_end, NULL, - PyDoc_STR("'send', 'recv', or 'both'")}, - {"send", (getter)channelid_end, NULL, - PyDoc_STR("the 'send' end of the channel"), &_channelid_end_send}, - {"recv", (getter)channelid_end, NULL, - PyDoc_STR("the 'recv' end of the channel"), &_channelid_end_recv}, - {NULL} -}; - -PyDoc_STRVAR(channelid_doc, -"A channel ID identifies a channel and may be used as an int."); - -static PyTypeObject ChannelIDtype = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "_xxsubinterpreters.ChannelID", /* tp_name */ - sizeof(channelid), /* tp_size */ - 0, /* tp_itemsize */ - (destructor)channelid_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - (reprfunc)channelid_repr, /* tp_repr */ - &channelid_as_number, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - channelid_hash, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | - Py_TPFLAGS_LONG_SUBCLASS, /* tp_flags */ - channelid_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - channelid_richcompare, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - 0, /* tp_members */ - channelid_getsets, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - // Note that we do not set tp_new to channelid_new. Instead we - // set it to NULL, meaning it cannot be instantiated from Python - // code. We do this because there is a strong relationship between - // channel IDs and the channel lifecycle, so this limitation avoids - // related complications. - NULL, /* tp_new */ -}; - - -/* interpreter-specific code ************************************************/ - -static PyObject * RunFailedError = NULL; - -static int -interp_exceptions_init(PyObject *ns) -{ - // XXX Move the exceptions into per-module memory? - - if (RunFailedError == NULL) { - // An uncaught exception came out of interp_run_string(). - RunFailedError = PyErr_NewException("_xxsubinterpreters.RunFailedError", - PyExc_RuntimeError, NULL); - if (RunFailedError == NULL) { - return -1; - } - if (PyDict_SetItemString(ns, "RunFailedError", RunFailedError) != 0) { - return -1; - } - } - - return 0; -} - -static int -_is_running(PyInterpreterState *interp) -{ - PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); - if (PyThreadState_Next(tstate) != NULL) { - PyErr_SetString(PyExc_RuntimeError, - "interpreter has more than one thread"); - return -1; - } - PyFrameObject *frame = tstate->frame; - if (frame == NULL) { - if (PyErr_Occurred() != NULL) { - return -1; - } - return 0; - } - return (int)(frame->f_executing); -} - -static int -_ensure_not_running(PyInterpreterState *interp) -{ - int is_running = _is_running(interp); - if (is_running < 0) { - return -1; - } - if (is_running) { - PyErr_Format(PyExc_RuntimeError, "interpreter already running"); - return -1; - } - return 0; -} - -static int -_run_script(PyInterpreterState *interp, const char *codestr, - _sharedns *shared, _sharedexception **exc) -{ - PyObject *exctype = NULL; - PyObject *excval = NULL; - PyObject *tb = NULL; - - PyObject *main_mod = PyMapping_GetItemString(interp->modules, "__main__"); - if (main_mod == NULL) { - goto error; - } - PyObject *ns = PyModule_GetDict(main_mod); // borrowed - Py_DECREF(main_mod); - if (ns == NULL) { - goto error; - } - Py_INCREF(ns); - - // Apply the cross-interpreter data. - if (shared != NULL) { - if (_sharedns_apply(shared, ns) != 0) { - Py_DECREF(ns); - goto error; - } - } - - // Run the string (see PyRun_SimpleStringFlags). - PyObject *result = PyRun_StringFlags(codestr, Py_file_input, ns, ns, NULL); - Py_DECREF(ns); - if (result == NULL) { - goto error; - } - else { - Py_DECREF(result); // We throw away the result. - } - - *exc = NULL; - return 0; - -error: - PyErr_Fetch(&exctype, &excval, &tb); - - _sharedexception *sharedexc = _sharedexception_bind(exctype, excval, tb); - Py_XDECREF(exctype); - Py_XDECREF(excval); - Py_XDECREF(tb); - if (sharedexc == NULL) { - fprintf(stderr, "RunFailedError: script raised an uncaught exception"); - PyErr_Clear(); - sharedexc = NULL; - } - else { - assert(!PyErr_Occurred()); - } - *exc = sharedexc; - return -1; -} - -static int -_run_script_in_interpreter(PyInterpreterState *interp, const char *codestr, - PyObject *shareables) -{ - if (_ensure_not_running(interp) < 0) { - return -1; - } - - _sharedns *shared = _get_shared_ns(shareables); - if (shared == NULL && PyErr_Occurred()) { - return -1; - } - - // Switch to interpreter. - PyThreadState *save_tstate = NULL; - if (interp != PyThreadState_Get()->interp) { - // XXX Using the "head" thread isn't strictly correct. - PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); - // XXX Possible GILState issues? - save_tstate = PyThreadState_Swap(tstate); - } - - // Run the script. - _sharedexception *exc = NULL; - int result = _run_script(interp, codestr, shared, &exc); - - // Switch back. - if (save_tstate != NULL) { - PyThreadState_Swap(save_tstate); - } - - // Propagate any exception out to the caller. - if (exc != NULL) { - _sharedexception_apply(exc, RunFailedError); - _sharedexception_free(exc); - } - else if (result != 0) { - // We were unable to allocate a shared exception. - PyErr_NoMemory(); - } - - if (shared != NULL) { - _sharedns_free(shared); - } - - return result; -} - -/* InterpreterID class */ - -static PyTypeObject InterpreterIDtype; - -typedef struct interpid { - PyObject_HEAD - int64_t id; -} interpid; - -static interpid * -newinterpid(PyTypeObject *cls, int64_t id, int force) -{ - PyInterpreterState *interp = _PyInterpreterState_LookUpID(id); - if (interp == NULL) { - if (force) { - PyErr_Clear(); - } - else { - return NULL; - } - } - - interpid *self = PyObject_New(interpid, cls); - if (self == NULL) { - return NULL; - } - self->id = id; - - if (interp != NULL) { - _PyInterpreterState_IDIncref(interp); - } - return self; -} - -static PyObject * -interpid_new(PyTypeObject *cls, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"id", "force", NULL}; - PyObject *idobj; - int force = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwds, - "O|$p:InterpreterID.__init__", kwlist, - &idobj, &force)) { - return NULL; - } - - // Coerce and check the ID. - int64_t id; - if (PyObject_TypeCheck(idobj, &InterpreterIDtype)) { - id = ((interpid *)idobj)->id; - } - else { - id = _coerce_id(idobj); - if (id < 0) { - return NULL; - } - } - - return (PyObject *)newinterpid(cls, id, force); -} - -static void -interpid_dealloc(PyObject *v) -{ - int64_t id = ((interpid *)v)->id; - PyInterpreterState *interp = _PyInterpreterState_LookUpID(id); - if (interp != NULL) { - _PyInterpreterState_IDDecref(interp); - } - else { - // already deleted - PyErr_Clear(); - } - Py_TYPE(v)->tp_free(v); -} - -static PyObject * -interpid_repr(PyObject *self) -{ - PyTypeObject *type = Py_TYPE(self); - const char *name = _PyType_Name(type); - interpid *id = (interpid *)self; - return PyUnicode_FromFormat("%s(%d)", name, id->id); -} - -PyObject * -interpid_int(PyObject *self) -{ - interpid *id = (interpid *)self; - return PyLong_FromLongLong(id->id); -} - -static PyNumberMethods interpid_as_number = { - 0, /* nb_add */ - 0, /* nb_subtract */ - 0, /* nb_multiply */ - 0, /* nb_remainder */ - 0, /* nb_divmod */ - 0, /* nb_power */ - 0, /* nb_negative */ - 0, /* nb_positive */ - 0, /* nb_absolute */ - 0, /* nb_bool */ - 0, /* nb_invert */ - 0, /* nb_lshift */ - 0, /* nb_rshift */ - 0, /* nb_and */ - 0, /* nb_xor */ - 0, /* nb_or */ - (unaryfunc)interpid_int, /* nb_int */ - 0, /* nb_reserved */ - 0, /* nb_float */ - - 0, /* nb_inplace_add */ - 0, /* nb_inplace_subtract */ - 0, /* nb_inplace_multiply */ - 0, /* nb_inplace_remainder */ - 0, /* nb_inplace_power */ - 0, /* nb_inplace_lshift */ - 0, /* nb_inplace_rshift */ - 0, /* nb_inplace_and */ - 0, /* nb_inplace_xor */ - 0, /* nb_inplace_or */ - - 0, /* nb_floor_divide */ - 0, /* nb_true_divide */ - 0, /* nb_inplace_floor_divide */ - 0, /* nb_inplace_true_divide */ - - (unaryfunc)interpid_int, /* nb_index */ -}; - -static Py_hash_t -interpid_hash(PyObject *self) -{ - interpid *id = (interpid *)self; - PyObject *obj = PyLong_FromLongLong(id->id); - if (obj == NULL) { - return -1; - } - Py_hash_t hash = PyObject_Hash(obj); - Py_DECREF(obj); - return hash; -} - -static PyObject * -interpid_richcompare(PyObject *self, PyObject *other, int op) -{ - if (op != Py_EQ && op != Py_NE) { - Py_RETURN_NOTIMPLEMENTED; - } - - if (!PyObject_TypeCheck(self, &InterpreterIDtype)) { - Py_RETURN_NOTIMPLEMENTED; - } - - interpid *id = (interpid *)self; - int equal; - if (PyObject_TypeCheck(other, &InterpreterIDtype)) { - interpid *otherid = (interpid *)other; - equal = (id->id == otherid->id); - } - else { - other = PyNumber_Long(other); - if (other == NULL) { - PyErr_Clear(); - Py_RETURN_NOTIMPLEMENTED; - } - int64_t otherid = PyLong_AsLongLong(other); - Py_DECREF(other); - if (otherid == -1 && PyErr_Occurred() != NULL) { - return NULL; - } - if (otherid < 0) { - equal = 0; - } - else { - equal = (id->id == otherid); - } - } - - if ((op == Py_EQ && equal) || (op == Py_NE && !equal)) { - Py_RETURN_TRUE; - } - Py_RETURN_FALSE; -} - -PyDoc_STRVAR(interpid_doc, -"A interpreter ID identifies a interpreter and may be used as an int."); - -static PyTypeObject InterpreterIDtype = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - "interpreters.InterpreterID", /* tp_name */ - sizeof(interpid), /* tp_size */ - 0, /* tp_itemsize */ - (destructor)interpid_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_as_async */ - (reprfunc)interpid_repr, /* tp_repr */ - &interpid_as_number, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - interpid_hash, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | - Py_TPFLAGS_LONG_SUBCLASS, /* tp_flags */ - interpid_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - interpid_richcompare, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - 0, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - interpid_new, /* tp_new */ -}; - -static PyObject * -_get_id(PyInterpreterState *interp) -{ - PY_INT64_T id = PyInterpreterState_GetID(interp); - if (id < 0) { - return NULL; - } - return (PyObject *)newinterpid(&InterpreterIDtype, id, 0); -} - -static PyInterpreterState * -_look_up(PyObject *requested_id) -{ - int64_t id; - if (PyObject_TypeCheck(requested_id, &InterpreterIDtype)) { - id = ((interpid *)requested_id)->id; - } - else { - id = PyLong_AsLongLong(requested_id); - if (id == -1 && PyErr_Occurred() != NULL) { - return NULL; - } - assert(id <= INT64_MAX); - } - return _PyInterpreterState_LookUpID(id); -} - - -/* module level code ********************************************************/ - -/* globals is the process-global state for the module. It holds all - the data that we need to share between interpreters, so it cannot - hold PyObject values. */ -static struct globals { - _channels channels; -} _globals = {{0}}; - -static int -_init_globals(void) -{ - if (_channels_init(&_globals.channels) != 0) { - return -1; - } - return 0; -} - -static _channels * -_global_channels(void) { - return &_globals.channels; -} - -static PyObject * -interp_create(PyObject *self, PyObject *args) -{ - if (!PyArg_UnpackTuple(args, "create", 0, 0)) { - return NULL; - } - - // Create and initialize the new interpreter. - PyThreadState *save_tstate = PyThreadState_Swap(NULL); - // XXX Possible GILState issues? - PyThreadState *tstate = Py_NewInterpreter(); - PyThreadState_Swap(save_tstate); - if (tstate == NULL) { - /* Since no new thread state was created, there is no exception to - propagate; raise a fresh one after swapping in the old thread - state. */ - PyErr_SetString(PyExc_RuntimeError, "interpreter creation failed"); - return NULL; - } - if (_PyInterpreterState_IDInitref(tstate->interp) != 0) { - goto error; - }; - return _get_id(tstate->interp); - -error: - // XXX Possible GILState issues? - save_tstate = PyThreadState_Swap(tstate); - Py_EndInterpreter(tstate); - PyThreadState_Swap(save_tstate); - return NULL; -} - -PyDoc_STRVAR(create_doc, -"create() -> ID\n\ -\n\ -Create a new interpreter and return a unique generated ID."); - - -static PyObject * -interp_destroy(PyObject *self, PyObject *args) -{ - PyObject *id; - if (!PyArg_UnpackTuple(args, "destroy", 1, 1, &id)) { - return NULL; - } - if (!PyLong_Check(id)) { - PyErr_SetString(PyExc_TypeError, "ID must be an int"); - return NULL; - } - - // Look up the interpreter. - PyInterpreterState *interp = _look_up(id); - if (interp == NULL) { - return NULL; - } - - // Ensure we don't try to destroy the current interpreter. - PyInterpreterState *current = _get_current(); - if (current == NULL) { - return NULL; - } - if (interp == current) { - PyErr_SetString(PyExc_RuntimeError, - "cannot destroy the current interpreter"); - return NULL; - } - - // Ensure the interpreter isn't running. - /* XXX We *could* support destroying a running interpreter but - aren't going to worry about it for now. */ - if (_ensure_not_running(interp) < 0) { - return NULL; - } - - // Destroy the interpreter. - //PyInterpreterState_Delete(interp); - PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); - // XXX Possible GILState issues? - PyThreadState *save_tstate = PyThreadState_Swap(tstate); - Py_EndInterpreter(tstate); - PyThreadState_Swap(save_tstate); - - Py_RETURN_NONE; -} - -PyDoc_STRVAR(destroy_doc, -"destroy(ID)\n\ -\n\ -Destroy the identified interpreter.\n\ -\n\ -Attempting to destroy the current interpreter results in a RuntimeError.\n\ -So does an unrecognized ID."); - - -static PyObject * -interp_list_all(PyObject *self) -{ - PyObject *ids, *id; - PyInterpreterState *interp; - - ids = PyList_New(0); - if (ids == NULL) { - return NULL; - } - - interp = PyInterpreterState_Head(); - while (interp != NULL) { - id = _get_id(interp); - if (id == NULL) { - Py_DECREF(ids); - return NULL; - } - // insert at front of list - int res = PyList_Insert(ids, 0, id); - Py_DECREF(id); - if (res < 0) { - Py_DECREF(ids); - return NULL; - } - - interp = PyInterpreterState_Next(interp); - } - - return ids; -} - -PyDoc_STRVAR(list_all_doc, -"list_all() -> [ID]\n\ -\n\ -Return a list containing the ID of every existing interpreter."); - - -static PyObject * -interp_get_current(PyObject *self) -{ - PyInterpreterState *interp =_get_current(); - if (interp == NULL) { - return NULL; - } - return _get_id(interp); -} - -PyDoc_STRVAR(get_current_doc, -"get_current() -> ID\n\ -\n\ -Return the ID of current interpreter."); - - -static PyObject * -interp_get_main(PyObject *self) -{ - // Currently, 0 is always the main interpreter. - return PyLong_FromLongLong(0); -} - -PyDoc_STRVAR(get_main_doc, -"get_main() -> ID\n\ -\n\ -Return the ID of main interpreter."); - - -static PyObject * -interp_run_string(PyObject *self, PyObject *args) -{ - PyObject *id, *code; - PyObject *shared = NULL; - if (!PyArg_UnpackTuple(args, "run_string", 2, 3, &id, &code, &shared)) { - return NULL; - } - if (!PyLong_Check(id)) { - PyErr_SetString(PyExc_TypeError, "first arg (ID) must be an int"); - return NULL; - } - if (!PyUnicode_Check(code)) { - PyErr_SetString(PyExc_TypeError, - "second arg (code) must be a string"); - return NULL; - } - - // Look up the interpreter. - PyInterpreterState *interp = _look_up(id); - if (interp == NULL) { - return NULL; - } - - // Extract code. - Py_ssize_t size; - const char *codestr = PyUnicode_AsUTF8AndSize(code, &size); - if (codestr == NULL) { - return NULL; - } - if (strlen(codestr) != (size_t)size) { - PyErr_SetString(PyExc_ValueError, - "source code string cannot contain null bytes"); - return NULL; - } - - // Run the code in the interpreter. - if (_run_script_in_interpreter(interp, codestr, shared) != 0) { - return NULL; - } - Py_RETURN_NONE; -} - -PyDoc_STRVAR(run_string_doc, -"run_string(ID, sourcetext)\n\ -\n\ -Execute the provided string in the identified interpreter.\n\ -\n\ -See PyRun_SimpleStrings."); - - -static PyObject * -object_is_shareable(PyObject *self, PyObject *args) -{ - PyObject *obj; - if (!PyArg_UnpackTuple(args, "is_shareable", 1, 1, &obj)) { - return NULL; - } - if (_PyObject_CheckCrossInterpreterData(obj) == 0) { - Py_RETURN_TRUE; - } - PyErr_Clear(); - Py_RETURN_FALSE; -} - -PyDoc_STRVAR(is_shareable_doc, -"is_shareable(obj) -> bool\n\ -\n\ -Return True if the object's data may be shared between interpreters and\n\ -False otherwise."); - - -static PyObject * -interp_is_running(PyObject *self, PyObject *args) -{ - PyObject *id; - if (!PyArg_UnpackTuple(args, "is_running", 1, 1, &id)) { - return NULL; - } - if (!PyLong_Check(id)) { - PyErr_SetString(PyExc_TypeError, "ID must be an int"); - return NULL; - } - - PyInterpreterState *interp = _look_up(id); - if (interp == NULL) { - return NULL; - } - int is_running = _is_running(interp); - if (is_running < 0) { - return NULL; - } - if (is_running) { - Py_RETURN_TRUE; - } - Py_RETURN_FALSE; -} - -PyDoc_STRVAR(is_running_doc, -"is_running(id) -> bool\n\ -\n\ -Return whether or not the identified interpreter is running."); - -static PyObject * -channel_create(PyObject *self) -{ - int64_t cid = _channel_create(&_globals.channels); - if (cid < 0) { - return NULL; - } - PyObject *id = (PyObject *)newchannelid(&ChannelIDtype, cid, 0, - &_globals.channels, 0); - if (id == NULL) { - if (_channel_destroy(&_globals.channels, cid) != 0) { - // XXX issue a warning? - } - return NULL; - } - assert(((channelid *)id)->channels != NULL); - return id; -} - -PyDoc_STRVAR(channel_create_doc, -"channel_create() -> ID\n\ -\n\ -Create a new cross-interpreter channel and return a unique generated ID."); - -static PyObject * -channel_destroy(PyObject *self, PyObject *args) -{ - PyObject *id; - if (!PyArg_UnpackTuple(args, "channel_destroy", 1, 1, &id)) { - return NULL; - } - int64_t cid = _coerce_id(id); - if (cid < 0) { - return NULL; - } - - if (_channel_destroy(&_globals.channels, cid) != 0) { - return NULL; - } - Py_RETURN_NONE; -} - -PyDoc_STRVAR(channel_destroy_doc, -"channel_destroy(ID)\n\ -\n\ -Close and finalize the channel. Afterward attempts to use the channel\n\ -will behave as though it never existed."); - -static PyObject * -channel_list_all(PyObject *self) -{ - int64_t count = 0; - int64_t *cids = _channels_list_all(&_globals.channels, &count); - if (cids == NULL) { - if (count == 0) { - return PyList_New(0); - } - return NULL; - } - PyObject *ids = PyList_New((Py_ssize_t)count); - if (ids == NULL) { - goto finally; - } - int64_t *cur = cids; - for (int64_t i=0; i < count; cur++, i++) { - PyObject *id = (PyObject *)newchannelid(&ChannelIDtype, *cur, 0, - &_globals.channels, 0); - if (id == NULL) { - Py_DECREF(ids); - ids = NULL; - break; - } - PyList_SET_ITEM(ids, i, id); - } - -finally: - PyMem_Free(cids); - return ids; -} - -PyDoc_STRVAR(channel_list_all_doc, -"channel_list_all() -> [ID]\n\ -\n\ -Return the list of all IDs for active channels."); - -static PyObject * -channel_send(PyObject *self, PyObject *args) -{ - PyObject *id; - PyObject *obj; - if (!PyArg_UnpackTuple(args, "channel_send", 2, 2, &id, &obj)) { - return NULL; - } - int64_t cid = _coerce_id(id); - if (cid < 0) { - return NULL; - } - - if (_channel_send(&_globals.channels, cid, obj) != 0) { - return NULL; - } - Py_RETURN_NONE; -} - -PyDoc_STRVAR(channel_send_doc, -"channel_send(ID, obj)\n\ -\n\ -Add the object's data to the channel's queue."); - -static PyObject * -channel_recv(PyObject *self, PyObject *args) -{ - PyObject *id; - if (!PyArg_UnpackTuple(args, "channel_recv", 1, 1, &id)) { - return NULL; - } - int64_t cid = _coerce_id(id); - if (cid < 0) { - return NULL; - } - - return _channel_recv(&_globals.channels, cid); -} - -PyDoc_STRVAR(channel_recv_doc, -"channel_recv(ID) -> obj\n\ -\n\ -Return a new object from the data at the from of the channel's queue."); - -static PyObject * -channel_close(PyObject *self, PyObject *args, PyObject *kwds) -{ - PyObject *id; - if (!PyArg_UnpackTuple(args, "channel_recv", 1, 1, &id)) { - return NULL; - } - int64_t cid = _coerce_id(id); - if (cid < 0) { - return NULL; - } - - if (_channel_close(&_globals.channels, cid) != 0) { - return NULL; - } - Py_RETURN_NONE; -} - -PyDoc_STRVAR(channel_close_doc, -"channel_close(ID)\n\ -\n\ -Close the channel for all interpreters. Once the channel's ID has\n\ -no more ref counts the channel will be destroyed."); - -static PyObject * -channel_drop_interpreter(PyObject *self, PyObject *args, PyObject *kwds) -{ - // Note that only the current interpreter is affected. - static char *kwlist[] = {"id", "send", "recv", NULL}; - PyObject *id; - int send = -1; - int recv = -1; - if (!PyArg_ParseTupleAndKeywords(args, kwds, - "O|$pp:channel_drop_interpreter", kwlist, - &id, &send, &recv)) - return NULL; - - int64_t cid = _coerce_id(id); - if (cid < 0) { - return NULL; - } - if (send < 0 && recv < 0) { - send = 1; - recv = 1; - } - else { - if (send < 0) { - send = 0; - } - if (recv < 0) { - recv = 0; - } - } - if (_channel_drop(&_globals.channels, cid, send, recv) != 0) { - return NULL; - } - Py_RETURN_NONE; -} - -PyDoc_STRVAR(channel_drop_interpreter_doc, -"channel_drop_interpreter(ID, *, send=None, recv=None)\n\ -\n\ -Close the channel for the current interpreter. 'send' and 'recv'\n\ -(bool) may be used to indicate the ends to close. By default both\n\ -ends are closed. Closing an already closed end is a noop."); - -static PyObject * -channel__channel_id(PyObject *self, PyObject *args, PyObject *kwds) -{ - return channelid_new(&ChannelIDtype, args, kwds); -} - -static PyMethodDef module_functions[] = { - {"create", (PyCFunction)interp_create, - METH_VARARGS, create_doc}, - {"destroy", (PyCFunction)interp_destroy, - METH_VARARGS, destroy_doc}, - {"list_all", (PyCFunction)interp_list_all, - METH_NOARGS, list_all_doc}, - {"get_current", (PyCFunction)interp_get_current, - METH_NOARGS, get_current_doc}, - {"get_main", (PyCFunction)interp_get_main, - METH_NOARGS, get_main_doc}, - {"is_running", (PyCFunction)interp_is_running, - METH_VARARGS, is_running_doc}, - {"run_string", (PyCFunction)interp_run_string, - METH_VARARGS, run_string_doc}, - - {"is_shareable", (PyCFunction)object_is_shareable, - METH_VARARGS, is_shareable_doc}, - - {"channel_create", (PyCFunction)channel_create, - METH_NOARGS, channel_create_doc}, - {"channel_destroy", (PyCFunction)channel_destroy, - METH_VARARGS, channel_destroy_doc}, - {"channel_list_all", (PyCFunction)channel_list_all, - METH_NOARGS, channel_list_all_doc}, - {"channel_send", (PyCFunction)channel_send, - METH_VARARGS, channel_send_doc}, - {"channel_recv", (PyCFunction)channel_recv, - METH_VARARGS, channel_recv_doc}, - {"channel_close", (PyCFunction)channel_close, - METH_VARARGS, channel_close_doc}, - {"channel_drop_interpreter", (PyCFunction)channel_drop_interpreter, - METH_VARARGS | METH_KEYWORDS, channel_drop_interpreter_doc}, - {"_channel_id", (PyCFunction)channel__channel_id, - METH_VARARGS | METH_KEYWORDS, NULL}, - - {NULL, NULL} /* sentinel */ -}; - - -/* initialization function */ - -PyDoc_STRVAR(module_doc, -"This module provides primitive operations to manage Python interpreters.\n\ -The 'interpreters' module provides a more convenient interface."); - -static struct PyModuleDef interpretersmodule = { - PyModuleDef_HEAD_INIT, - "_xxsubinterpreters", /* m_name */ - module_doc, /* m_doc */ - -1, /* m_size */ - module_functions, /* m_methods */ - NULL, /* m_slots */ - NULL, /* m_traverse */ - NULL, /* m_clear */ - NULL /* m_free */ -}; - - -PyMODINIT_FUNC -PyInit__xxsubinterpreters(void) -{ - if (_init_globals() != 0) { - return NULL; - } - - /* Initialize types */ - ChannelIDtype.tp_base = &PyLong_Type; - if (PyType_Ready(&ChannelIDtype) != 0) { - return NULL; - } - InterpreterIDtype.tp_base = &PyLong_Type; - if (PyType_Ready(&InterpreterIDtype) != 0) { - return NULL; - } - - /* Create the module */ - PyObject *module = PyModule_Create(&interpretersmodule); - if (module == NULL) { - return NULL; - } - - /* Add exception types */ - PyObject *ns = PyModule_GetDict(module); // borrowed - if (interp_exceptions_init(ns) != 0) { - return NULL; - } - if (channel_exceptions_init(ns) != 0) { - return NULL; - } - - /* Add other types */ - Py_INCREF(&ChannelIDtype); - if (PyDict_SetItemString(ns, "ChannelID", (PyObject *)&ChannelIDtype) != 0) { - return NULL; - } - Py_INCREF(&InterpreterIDtype); - if (PyDict_SetItemString(ns, "InterpreterID", (PyObject *)&InterpreterIDtype) != 0) { - return NULL; - } - - if (_PyCrossInterpreterData_Register_Class(&ChannelIDtype, _channelid_shared)) { - return NULL; - } - - return module; -} diff --git a/PC/config.c b/PC/config.c index 568a0fa9a467..2037b3db64ba 100644 --- a/PC/config.c +++ b/PC/config.c @@ -32,9 +32,8 @@ extern PyObject* PyInit__locale(void); #endif extern PyObject* PyInit__codecs(void); extern PyObject* PyInit__weakref(void); -/* XXX: These two should really be extracted to standalone extensions. */ +/* XXX: This one should really be extracted to standalone extension. */ extern PyObject* PyInit_xxsubtype(void); -extern PyObject* PyInit__xxsubinterpreters(void); extern PyObject* PyInit_zipimport(void); extern PyObject* PyInit__random(void); extern PyObject* PyInit_itertools(void); @@ -130,7 +129,6 @@ struct _inittab _PyImport_Inittab[] = { {"_json", PyInit__json}, {"xxsubtype", PyInit_xxsubtype}, - {"_xxsubinterpreters", PyInit__xxsubinterpreters}, {"zipimport", PyInit_zipimport}, #ifdef _Py_HAVE_ZLIB {"zlib", PyInit_zlib}, diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index 90330faa0cf2..d19b5f5acf89 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -280,7 +280,6 @@ <ClCompile Include="..\Modules\_tracemalloc.c" /> <ClCompile Include="..\Modules\timemodule.c" /> <ClCompile Include="..\Modules\xxsubtype.c" /> - <ClCompile Include="..\Modules\_xxsubinterpretersmodule.c" /> <ClCompile Include="..\Modules\zipimport.c" /> <ClCompile Include="..\Modules\_io\fileio.c" /> <ClCompile Include="..\Modules\_io\bytesio.c" /> diff --git a/Python/pystate.c b/Python/pystate.c index 140d2fba8efd..7750f4ca8a55 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -56,11 +56,6 @@ _PyRuntimeState_Init_impl(_PyRuntimeState *runtime) } runtime->interpreters.next_id = -1; - runtime->xidregistry.mutex = PyThread_allocate_lock(); - if (runtime->xidregistry.mutex == NULL) { - return _Py_INIT_ERR("Can't initialize threads for cross-interpreter data registry"); - } - return _Py_INIT_OK(); } @@ -1128,259 +1123,6 @@ PyGILState_Release(PyGILState_STATE oldstate) } -/**************************/ -/* cross-interpreter data */ -/**************************/ - -/* cross-interpreter data */ - -crossinterpdatafunc _PyCrossInterpreterData_Lookup(PyObject *); - -/* This is a separate func from _PyCrossInterpreterData_Lookup in order - to keep the registry code separate. */ -static crossinterpdatafunc -_lookup_getdata(PyObject *obj) -{ - crossinterpdatafunc getdata = _PyCrossInterpreterData_Lookup(obj); - if (getdata == NULL && PyErr_Occurred() == 0) - PyErr_Format(PyExc_ValueError, - "%S does not support cross-interpreter data", obj); - return getdata; -} - -int -_PyObject_CheckCrossInterpreterData(PyObject *obj) -{ - crossinterpdatafunc getdata = _lookup_getdata(obj); - if (getdata == NULL) { - return -1; - } - return 0; -} - -static int -_check_xidata(_PyCrossInterpreterData *data) -{ - // data->data can be anything, including NULL, so we don't check it. - - // data->obj may be NULL, so we don't check it. - - if (data->interp < 0) { - PyErr_SetString(PyExc_SystemError, "missing interp"); - return -1; - } - - if (data->new_object == NULL) { - PyErr_SetString(PyExc_SystemError, "missing new_object func"); - return -1; - } - - // data->free may be NULL, so we don't check it. - - return 0; -} - -int -_PyObject_GetCrossInterpreterData(PyObject *obj, _PyCrossInterpreterData *data) -{ - PyThreadState *tstate = PyThreadState_Get(); - // PyThreadState_Get() aborts if lookup fails, so we don't need - // to check the result for NULL. - PyInterpreterState *interp = tstate->interp; - - // Reset data before re-populating. - *data = (_PyCrossInterpreterData){0}; - data->free = PyMem_RawFree; // Set a default that may be overridden. - - // Call the "getdata" func for the object. - Py_INCREF(obj); - crossinterpdatafunc getdata = _lookup_getdata(obj); - if (getdata == NULL) { - Py_DECREF(obj); - return -1; - } - int res = getdata(obj, data); - Py_DECREF(obj); - if (res != 0) { - return -1; - } - - // Fill in the blanks and validate the result. - Py_XINCREF(data->obj); - data->interp = interp->id; - if (_check_xidata(data) != 0) { - _PyCrossInterpreterData_Release(data); - return -1; - } - - return 0; -} - -void -_PyCrossInterpreterData_Release(_PyCrossInterpreterData *data) -{ - if (data->data == NULL && data->obj == NULL) { - // Nothing to release! - return; - } - - // Switch to the original interpreter. - PyInterpreterState *interp = _PyInterpreterState_LookUpID(data->interp); - if (interp == NULL) { - // The intepreter was already destroyed. - if (data->free != NULL) { - // XXX Someone leaked some memory... - } - return; - } - - PyThreadState *save_tstate = NULL; - if (interp != PyThreadState_Get()->interp) { - // XXX Using the "head" thread isn't strictly correct. - PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); - // XXX Possible GILState issues? - save_tstate = PyThreadState_Swap(tstate); - } - - // "Release" the data and/or the object. - if (data->free != NULL) { - data->free(data->data); - } - Py_XDECREF(data->obj); - - // Switch back. - if (save_tstate != NULL) { - PyThreadState_Swap(save_tstate); - } -} - -PyObject * -_PyCrossInterpreterData_NewObject(_PyCrossInterpreterData *data) -{ - return data->new_object(data); -} - -/* registry of {type -> crossinterpdatafunc} */ - -/* For now we use a global registry of shareable classes. An - alternative would be to add a tp_* slot for a class's - crossinterpdatafunc. It would be simpler and more efficient. */ - -static int -_register_xidata(PyTypeObject *cls, crossinterpdatafunc getdata) -{ - // Note that we effectively replace already registered classes - // rather than failing. - struct _xidregitem *newhead = PyMem_RawMalloc(sizeof(struct _xidregitem)); - if (newhead == NULL) - return -1; - newhead->cls = cls; - newhead->getdata = getdata; - newhead->next = _PyRuntime.xidregistry.head; - _PyRuntime.xidregistry.head = newhead; - return 0; -} - -static void _register_builtins_for_crossinterpreter_data(void); - -int -_PyCrossInterpreterData_Register_Class(PyTypeObject *cls, - crossinterpdatafunc getdata) -{ - if (!PyType_Check(cls)) { - PyErr_Format(PyExc_ValueError, "only classes may be registered"); - return -1; - } - if (getdata == NULL) { - PyErr_Format(PyExc_ValueError, "missing 'getdata' func"); - return -1; - } - - // Make sure the class isn't ever deallocated. - Py_INCREF((PyObject *)cls); - - PyThread_acquire_lock(_PyRuntime.xidregistry.mutex, WAIT_LOCK); - if (_PyRuntime.xidregistry.head == NULL) { - _register_builtins_for_crossinterpreter_data(); - } - int res = _register_xidata(cls, getdata); - PyThread_release_lock(_PyRuntime.xidregistry.mutex); - return res; -} - -crossinterpdatafunc -_PyCrossInterpreterData_Lookup(PyObject *obj) -{ - PyObject *cls = PyObject_Type(obj); - crossinterpdatafunc getdata = NULL; - PyThread_acquire_lock(_PyRuntime.xidregistry.mutex, WAIT_LOCK); - struct _xidregitem *cur = _PyRuntime.xidregistry.head; - if (cur == NULL) { - _register_builtins_for_crossinterpreter_data(); - cur = _PyRuntime.xidregistry.head; - } - for(; cur != NULL; cur = cur->next) { - if (cur->cls == (PyTypeObject *)cls) { - getdata = cur->getdata; - break; - } - } - Py_DECREF(cls); - PyThread_release_lock(_PyRuntime.xidregistry.mutex); - return getdata; -} - -/* cross-interpreter data for builtin types */ - -static PyObject * -_new_bytes_object(_PyCrossInterpreterData *data) -{ - return PyBytes_FromString((char *)(data->data)); -} - -static int -_bytes_shared(PyObject *obj, _PyCrossInterpreterData *data) -{ - data->data = (void *)(PyBytes_AS_STRING(obj)); - data->obj = obj; // Will be "released" (decref'ed) when data released. - data->new_object = _new_bytes_object; - data->free = NULL; // Do not free the data (it belongs to the object). - return 0; -} - -static PyObject * -_new_none_object(_PyCrossInterpreterData *data) -{ - // XXX Singleton refcounts are problematic across interpreters... - Py_INCREF(Py_None); - return Py_None; -} - -static int -_none_shared(PyObject *obj, _PyCrossInterpreterData *data) -{ - data->data = NULL; - // data->obj remains NULL - data->new_object = _new_none_object; - data->free = NULL; // There is nothing to free. - return 0; -} - -static void -_register_builtins_for_crossinterpreter_data(void) -{ - // None - if (_register_xidata((PyTypeObject *)PyObject_Type(Py_None), _none_shared) != 0) { - Py_FatalError("could not register None for cross-interpreter sharing"); - } - - // bytes - if (_register_xidata(&PyBytes_Type, _bytes_shared) != 0) { - Py_FatalError("could not register bytes for cross-interpreter sharing"); - } -} - - #ifdef __cplusplus } #endif diff --git a/setup.py b/setup.py index 8536c350fe3a..a97a7559cae7 100644 --- a/setup.py +++ b/setup.py @@ -757,10 +757,6 @@ def detect_modules(self): ['_xxtestfuzz/_xxtestfuzz.c', '_xxtestfuzz/fuzzer.c']) ) - # Python interface to subinterpreter C-API. - exts.append(Extension('_xxsubinterpreters', ['_xxsubinterpretersmodule.c'], - define_macros=[('Py_BUILD_CORE', '')])) - # # Here ends the simple stuff. From here on, modules need certain # libraries, are platform-specific, or present other surprises. From webhook-mailer at python.org Tue May 15 11:17:03 2018 From: webhook-mailer at python.org (Petr Viktorin) Date: Tue, 15 May 2018 15:17:03 -0000 Subject: [Python-checkins] bpo-28167: bump platform.linux_distribution removal to 3.8 (GH-6669) Message-ID: <mailman.49.1526397426.2757.python-checkins@python.org> https://github.com/python/cpython/commit/9eb40bc38de83e6ad3fad1931bba1cd36ae88c24 commit: 9eb40bc38de83e6ad3fad1931bba1cd36ae88c24 branch: master author: Matthias Bussonnier <bussonniermatthias at gmail.com> committer: Petr Viktorin <encukou at gmail.com> date: 2018-05-15T11:17:00-04:00 summary: bpo-28167: bump platform.linux_distribution removal to 3.8 (GH-6669) Also bump PendingDeprecationWarning to DeprecationWarning. files: A Misc/NEWS.d/next/Library/2018-05-02-07-26-29.bpo-28167.7FwDfN.rst M Doc/library/platform.rst M Lib/platform.py M Lib/test/test_platform.py diff --git a/Doc/library/platform.rst b/Doc/library/platform.rst index eea0abbae4d4..f5cb52cb4745 100644 --- a/Doc/library/platform.rst +++ b/Doc/library/platform.rst @@ -248,7 +248,8 @@ Unix Platforms This is another name for :func:`linux_distribution`. - .. deprecated-removed:: 3.5 3.7 + .. deprecated-removed:: 3.5 3.8 + See alternative like the `distro <https://pypi.org/project/distro>`_ package. .. function:: linux_distribution(distname='', version='', id='', supported_dists=('SuSE','debian','redhat','mandrake',...), full_distribution_name=1) @@ -266,7 +267,8 @@ Unix Platforms parameters. ``id`` is the item in parentheses after the version number. It is usually the version codename. - .. deprecated-removed:: 3.5 3.7 + .. deprecated-removed:: 3.5 3.8 + See alternative like the `distro <https://pypi.org/project/distro>`_ package. .. function:: libc_ver(executable=sys.executable, lib='', version='', chunksize=2048) diff --git a/Lib/platform.py b/Lib/platform.py index dc981ec144cc..20f9817f4ffb 100755 --- a/Lib/platform.py +++ b/Lib/platform.py @@ -302,7 +302,7 @@ def linux_distribution(distname='', version='', id='', full_distribution_name=1): import warnings warnings.warn("dist() and linux_distribution() functions are deprecated " - "in Python 3.5", PendingDeprecationWarning, stacklevel=2) + "in Python 3.5", DeprecationWarning, stacklevel=2) return _linux_distribution(distname, version, id, supported_dists, full_distribution_name) @@ -376,7 +376,7 @@ def dist(distname='', version='', id='', """ import warnings warnings.warn("dist() and linux_distribution() functions are deprecated " - "in Python 3.5", PendingDeprecationWarning, stacklevel=2) + "in Python 3.5", DeprecationWarning, stacklevel=2) return _linux_distribution(distname, version, id, supported_dists=supported_dists, full_distribution_name=0) @@ -1345,7 +1345,7 @@ def platform(aliased=0, terse=0): 'ignore', r'dist\(\) and linux_distribution\(\) ' 'functions are deprecated .*', - PendingDeprecationWarning, + DeprecationWarning, ) distname, distversion, distid = dist('') if distname and not terse: diff --git a/Lib/test/test_platform.py b/Lib/test/test_platform.py index 2cf4d3f5dfdb..5f1e28a5d950 100644 --- a/Lib/test/test_platform.py +++ b/Lib/test/test_platform.py @@ -353,14 +353,14 @@ def test_linux_distribution_encoding(self): class DeprecationTest(unittest.TestCase): def test_dist_deprecation(self): - with self.assertWarns(PendingDeprecationWarning) as cm: + with self.assertWarns(DeprecationWarning) as cm: platform.dist() self.assertEqual(str(cm.warning), 'dist() and linux_distribution() functions are ' 'deprecated in Python 3.5') def test_linux_distribution_deprecation(self): - with self.assertWarns(PendingDeprecationWarning) as cm: + with self.assertWarns(DeprecationWarning) as cm: platform.linux_distribution() self.assertEqual(str(cm.warning), 'dist() and linux_distribution() functions are ' diff --git a/Misc/NEWS.d/next/Library/2018-05-02-07-26-29.bpo-28167.7FwDfN.rst b/Misc/NEWS.d/next/Library/2018-05-02-07-26-29.bpo-28167.7FwDfN.rst new file mode 100644 index 000000000000..a4971e5b77ba --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-02-07-26-29.bpo-28167.7FwDfN.rst @@ -0,0 +1,3 @@ +The function ``platform.linux_ditribution`` and ``platform.dist`` now +trigger a ``DeprecationWarning`` and have been marked for removal in Python +3.8 From webhook-mailer at python.org Tue May 15 11:19:54 2018 From: webhook-mailer at python.org (Ethan Furman) Date: Tue, 15 May 2018 15:19:54 -0000 Subject: [Python-checkins] bpo-31947: remove None default for names param in Enum._create_ GH-4288 (GH-6485) Message-ID: <mailman.50.1526397595.2757.python-checkins@python.org> https://github.com/python/cpython/commit/c50e5b1f1f2501f697aa52d9c9a440bdeced7006 commit: c50e5b1f1f2501f697aa52d9c9a440bdeced7006 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Ethan Furman <ethan at stoneleaf.us> date: 2018-05-15T08:19:50-07:00 summary: bpo-31947: remove None default for names param in Enum._create_ GH-4288 (GH-6485) (cherry picked from commit b8e21f12891382bc0aac5ccd13dcb4a990d65e0a) Co-authored-by: anentropic <ego at anentropic.com> files: M Lib/enum.py diff --git a/Lib/enum.py b/Lib/enum.py index 73dd613887d2..112523e998f7 100644 --- a/Lib/enum.py +++ b/Lib/enum.py @@ -361,7 +361,7 @@ def __setattr__(cls, name, value): raise AttributeError('Cannot reassign members.') super().__setattr__(name, value) - def _create_(cls, class_name, names=None, *, module=None, qualname=None, type=None, start=1): + def _create_(cls, class_name, names, *, module=None, qualname=None, type=None, start=1): """Convenience method to create a new Enum class. `names` can be: From webhook-mailer at python.org Tue May 15 13:30:16 2018 From: webhook-mailer at python.org (Petr Viktorin) Date: Tue, 15 May 2018 17:30:16 -0000 Subject: [Python-checkins] bpo-28167: bump platform.linux_distribution removal to 3.8 (GH-6669) (GH-6862) Message-ID: <mailman.51.1526405420.2757.python-checkins@python.org> https://github.com/python/cpython/commit/f4fdb619ddb5b00178c79c2b90adc45075b5f17d commit: f4fdb619ddb5b00178c79c2b90adc45075b5f17d branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Petr Viktorin <encukou at gmail.com> date: 2018-05-15T13:30:06-04:00 summary: bpo-28167: bump platform.linux_distribution removal to 3.8 (GH-6669) (GH-6862) Also bump PendingDeprecationWarning to DeprecationWarning. (cherry picked from commit 9eb40bc38de83e6ad3fad1931bba1cd36ae88c24) Co-authored-by: Matthias Bussonnier <bussonniermatthias at gmail.com> files: A Misc/NEWS.d/next/Library/2018-05-02-07-26-29.bpo-28167.7FwDfN.rst M Doc/library/platform.rst M Lib/platform.py M Lib/test/test_platform.py diff --git a/Doc/library/platform.rst b/Doc/library/platform.rst index eea0abbae4d4..f5cb52cb4745 100644 --- a/Doc/library/platform.rst +++ b/Doc/library/platform.rst @@ -248,7 +248,8 @@ Unix Platforms This is another name for :func:`linux_distribution`. - .. deprecated-removed:: 3.5 3.7 + .. deprecated-removed:: 3.5 3.8 + See alternative like the `distro <https://pypi.org/project/distro>`_ package. .. function:: linux_distribution(distname='', version='', id='', supported_dists=('SuSE','debian','redhat','mandrake',...), full_distribution_name=1) @@ -266,7 +267,8 @@ Unix Platforms parameters. ``id`` is the item in parentheses after the version number. It is usually the version codename. - .. deprecated-removed:: 3.5 3.7 + .. deprecated-removed:: 3.5 3.8 + See alternative like the `distro <https://pypi.org/project/distro>`_ package. .. function:: libc_ver(executable=sys.executable, lib='', version='', chunksize=2048) diff --git a/Lib/platform.py b/Lib/platform.py index dc981ec144cc..20f9817f4ffb 100755 --- a/Lib/platform.py +++ b/Lib/platform.py @@ -302,7 +302,7 @@ def linux_distribution(distname='', version='', id='', full_distribution_name=1): import warnings warnings.warn("dist() and linux_distribution() functions are deprecated " - "in Python 3.5", PendingDeprecationWarning, stacklevel=2) + "in Python 3.5", DeprecationWarning, stacklevel=2) return _linux_distribution(distname, version, id, supported_dists, full_distribution_name) @@ -376,7 +376,7 @@ def dist(distname='', version='', id='', """ import warnings warnings.warn("dist() and linux_distribution() functions are deprecated " - "in Python 3.5", PendingDeprecationWarning, stacklevel=2) + "in Python 3.5", DeprecationWarning, stacklevel=2) return _linux_distribution(distname, version, id, supported_dists=supported_dists, full_distribution_name=0) @@ -1345,7 +1345,7 @@ def platform(aliased=0, terse=0): 'ignore', r'dist\(\) and linux_distribution\(\) ' 'functions are deprecated .*', - PendingDeprecationWarning, + DeprecationWarning, ) distname, distversion, distid = dist('') if distname and not terse: diff --git a/Lib/test/test_platform.py b/Lib/test/test_platform.py index 2cf4d3f5dfdb..5f1e28a5d950 100644 --- a/Lib/test/test_platform.py +++ b/Lib/test/test_platform.py @@ -353,14 +353,14 @@ def test_linux_distribution_encoding(self): class DeprecationTest(unittest.TestCase): def test_dist_deprecation(self): - with self.assertWarns(PendingDeprecationWarning) as cm: + with self.assertWarns(DeprecationWarning) as cm: platform.dist() self.assertEqual(str(cm.warning), 'dist() and linux_distribution() functions are ' 'deprecated in Python 3.5') def test_linux_distribution_deprecation(self): - with self.assertWarns(PendingDeprecationWarning) as cm: + with self.assertWarns(DeprecationWarning) as cm: platform.linux_distribution() self.assertEqual(str(cm.warning), 'dist() and linux_distribution() functions are ' diff --git a/Misc/NEWS.d/next/Library/2018-05-02-07-26-29.bpo-28167.7FwDfN.rst b/Misc/NEWS.d/next/Library/2018-05-02-07-26-29.bpo-28167.7FwDfN.rst new file mode 100644 index 000000000000..a4971e5b77ba --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-02-07-26-29.bpo-28167.7FwDfN.rst @@ -0,0 +1,3 @@ +The function ``platform.linux_ditribution`` and ``platform.dist`` now +trigger a ``DeprecationWarning`` and have been marked for removal in Python +3.8 From webhook-mailer at python.org Tue May 15 13:31:51 2018 From: webhook-mailer at python.org (Petr Viktorin) Date: Tue, 15 May 2018 17:31:51 -0000 Subject: [Python-checkins] bpo-28167: bump platform.linux_distribution removal to 3.8 (GH-6864) Message-ID: <mailman.52.1526405511.2757.python-checkins@python.org> https://github.com/python/cpython/commit/e618e96581a711f2bc4f9bbcff6069bea15f0177 commit: e618e96581a711f2bc4f9bbcff6069bea15f0177 branch: 3.6 author: Petr Viktorin <encukou at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-15T13:31:47-04:00 summary: bpo-28167: bump platform.linux_distribution removal to 3.8 (GH-6864) This is a backport of the documentation part of GH-6862 Co-authored-by: Matthias Bussonnier <bussonniermatthias at gmail.com> files: M Doc/library/platform.rst diff --git a/Doc/library/platform.rst b/Doc/library/platform.rst index eea0abbae4d4..f5cb52cb4745 100644 --- a/Doc/library/platform.rst +++ b/Doc/library/platform.rst @@ -248,7 +248,8 @@ Unix Platforms This is another name for :func:`linux_distribution`. - .. deprecated-removed:: 3.5 3.7 + .. deprecated-removed:: 3.5 3.8 + See alternative like the `distro <https://pypi.org/project/distro>`_ package. .. function:: linux_distribution(distname='', version='', id='', supported_dists=('SuSE','debian','redhat','mandrake',...), full_distribution_name=1) @@ -266,7 +267,8 @@ Unix Platforms parameters. ``id`` is the item in parentheses after the version number. It is usually the version codename. - .. deprecated-removed:: 3.5 3.7 + .. deprecated-removed:: 3.5 3.8 + See alternative like the `distro <https://pypi.org/project/distro>`_ package. .. function:: libc_ver(executable=sys.executable, lib='', version='', chunksize=2048) From webhook-mailer at python.org Tue May 15 14:20:42 2018 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Tue, 15 May 2018 18:20:42 -0000 Subject: [Python-checkins] bpo-29706: Test that IDLE colors async/await as keywords. (GH-6846) Message-ID: <mailman.53.1526408444.2757.python-checkins@python.org> https://github.com/python/cpython/commit/389a48ede92bf7965889d554d2cd17b50d6e3d86 commit: 389a48ede92bf7965889d554d2cd17b50d6e3d86 branch: master author: Terry Jan Reedy <tjreedy at udel.edu> committer: GitHub <noreply at github.com> date: 2018-05-15T14:20:38-04:00 summary: bpo-29706: Test that IDLE colors async/await as keywords. (GH-6846) Added to the eye-verified htest, not to the unittests. Also remove some stray leftover comments. files: M Lib/idlelib/colorizer.py diff --git a/Lib/idlelib/colorizer.py b/Lib/idlelib/colorizer.py index 5cb85f24dfd7..1f31ce22d7e5 100644 --- a/Lib/idlelib/colorizer.py +++ b/Lib/idlelib/colorizer.py @@ -17,8 +17,6 @@ def make_pat(): builtinlist = [str(name) for name in dir(builtins) if not name.startswith('_') and \ name not in keyword.kwlist] - # self.file = open("file") : - # 1st 'file' colorized normal, 2nd as builtin, 3rd as string builtin = r"([^.'\"\\#]\b|^)" + any("BUILTIN", builtinlist) + r"\b" comment = any("COMMENT", [r"#[^\n]*"]) stringprefix = r"(?i:r|u|f|fr|rf|b|br|rb)?" @@ -268,13 +266,14 @@ def _color_delegator(parent): # htest # "else: float(None)\n" "if iF + If + IF: 'keyword matching must respect case'\n" "if'': x or'' # valid string-keyword no-space combinations\n" + "async def f(): await g()\n" "# All valid prefixes for unicode and byte strings should be colored.\n" "'x', '''x''', \"x\", \"\"\"x\"\"\"\n" "r'x', u'x', R'x', U'x', f'x', F'x'\n" "fr'x', Fr'x', fR'x', FR'x', rf'x', rF'x', Rf'x', RF'x'\n" "b'x',B'x', br'x',Br'x',bR'x',BR'x', rb'x'.rB'x',Rb'x',RB'x'\n" "# Invalid combinations of legal characters should be half colored.\n" - "ur'x', ru'x', uf'x', fu'x', UR'x', ufr'x', rfu'x', xf'x', fx'x'" + "ur'x', ru'x', uf'x', fu'x', UR'x', ufr'x', rfu'x', xf'x', fx'x'\n" ) text = Text(top, background="white") text.pack(expand=1, fill="both") From webhook-mailer at python.org Tue May 15 14:41:17 2018 From: webhook-mailer at python.org (Barry Warsaw) Date: Tue, 15 May 2018 18:41:17 -0000 Subject: [Python-checkins] bpo-33465: Use an unlikely to be built-in C extension in a test (#6797) Message-ID: <mailman.54.1526409679.2757.python-checkins@python.org> https://github.com/python/cpython/commit/8709b236fc997077d24b4802320db287640f82e2 commit: 8709b236fc997077d24b4802320db287640f82e2 branch: master author: Barry Warsaw <barry at python.org> committer: GitHub <noreply at github.com> date: 2018-05-15T14:41:13-04:00 summary: bpo-33465: Use an unlikely to be built-in C extension in a test (#6797) files: M Lib/test/test_import/__init__.py diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py index c23fac1ecc24..fb9453ad0b39 100644 --- a/Lib/test/test_import/__init__.py +++ b/Lib/test/test_import/__init__.py @@ -90,13 +90,14 @@ def test_from_import_missing_attr_has_name_and_path(self): self.assertEqual(cm.exception.path, os.__file__) self.assertRegex(str(cm.exception), r"cannot import name 'i_dont_exist' from 'os' \(.*os.py\)") + @cpython_only def test_from_import_missing_attr_has_name_and_so_path(self): - import select + import _testcapi with self.assertRaises(ImportError) as cm: - from select import i_dont_exist - self.assertEqual(cm.exception.name, 'select') - self.assertEqual(cm.exception.path, select.__file__) - self.assertRegex(str(cm.exception), r"cannot import name 'i_dont_exist' from 'select' \(.*\.(so|pyd)\)") + from _testcapi import i_dont_exist + self.assertEqual(cm.exception.name, '_testcapi') + self.assertEqual(cm.exception.path, _testcapi.__file__) + self.assertRegex(str(cm.exception), r"cannot import name 'i_dont_exist' from '_testcapi' \(.*\.(so|pyd)\)") def test_from_import_missing_attr_has_name(self): with self.assertRaises(ImportError) as cm: From webhook-mailer at python.org Tue May 15 14:42:15 2018 From: webhook-mailer at python.org (Victor Stinner) Date: Tue, 15 May 2018 18:42:15 -0000 Subject: [Python-checkins] bpo-33509: Fix _warnings for module_globals=None (#6833) Message-ID: <mailman.55.1526409736.2757.python-checkins@python.org> https://github.com/python/cpython/commit/b056562860c227bad2e0ba7cd3130e115c007768 commit: b056562860c227bad2e0ba7cd3130e115c007768 branch: master author: Victor Stinner <vstinner at redhat.com> committer: GitHub <noreply at github.com> date: 2018-05-15T20:42:12+02:00 summary: bpo-33509: Fix _warnings for module_globals=None (#6833) Don't crash on warnings.warn_explicit() if module_globals is not a dict. files: A Misc/NEWS.d/next/Core and Builtins/2018-05-14-17-31-02.bpo-33509.pIUfTd.rst M Lib/test/test_warnings/__init__.py M Python/_warnings.c diff --git a/Lib/test/test_warnings/__init__.py b/Lib/test/test_warnings/__init__.py index 31ab94b74716..940db5c143c9 100644 --- a/Lib/test/test_warnings/__init__.py +++ b/Lib/test/test_warnings/__init__.py @@ -218,6 +218,25 @@ def test_once(self): 42) self.assertEqual(len(w), 0) + def test_module_globals(self): + with original_warnings.catch_warnings(record=True, + module=self.module) as w: + # bpo-33509: module_globals=None must not crash + self.module.warn_explicit('msg', UserWarning, "filename", 42, + module_globals=None) + self.assertEqual(len(w), 1) + + # Invalid module_globals type + with self.assertRaises(TypeError): + self.module.warn_explicit('msg', UserWarning, "filename", 42, + module_globals=True) + self.assertEqual(len(w), 1) + + # Empty module_globals + self.module.warn_explicit('msg', UserWarning, "filename", 42, + module_globals={}) + self.assertEqual(len(w), 2) + def test_inheritance(self): with original_warnings.catch_warnings(module=self.module) as w: self.module.resetwarnings() diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-05-14-17-31-02.bpo-33509.pIUfTd.rst b/Misc/NEWS.d/next/Core and Builtins/2018-05-14-17-31-02.bpo-33509.pIUfTd.rst new file mode 100644 index 000000000000..3d80a8c7f3eb --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-05-14-17-31-02.bpo-33509.pIUfTd.rst @@ -0,0 +1,2 @@ +Fix module_globals parameter of warnings.warn_explicit(): don't crash if +module_globals is not a dict. diff --git a/Python/_warnings.c b/Python/_warnings.c index 0568af4df5a8..29e475d67d1f 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -951,7 +951,14 @@ warnings_warn_explicit(PyObject *self, PyObject *args, PyObject *kwds) ®istry, &module_globals, &sourceobj)) return NULL; - if (module_globals) { + if (module_globals && module_globals != Py_None) { + if (!PyDict_Check(module_globals)) { + PyErr_Format(PyExc_TypeError, + "module_globals must be a dict, not '%.200s'", + Py_TYPE(module_globals)->tp_name); + return NULL; + } + source_line = get_source_line(module_globals, lineno); if (source_line == NULL && PyErr_Occurred()) { return NULL; From webhook-mailer at python.org Tue May 15 14:58:39 2018 From: webhook-mailer at python.org (Ned Deily) Date: Tue, 15 May 2018 18:58:39 -0000 Subject: [Python-checkins] bpo-33503: Fix the broken pypi link in the source and the documentation (GH-6814) Message-ID: <mailman.56.1526410720.2757.python-checkins@python.org> https://github.com/python/cpython/commit/19177fbd5d6d9b29ccc302d65f9d9417ece082ce commit: 19177fbd5d6d9b29ccc302d65f9d9417ece082ce branch: master author: St?phane Wirtel <stephane at wirtel.be> committer: Ned Deily <nad at python.org> date: 2018-05-15T14:58:35-04:00 summary: bpo-33503: Fix the broken pypi link in the source and the documentation (GH-6814) files: A Misc/NEWS.d/next/Documentation/2018-05-14-20-08-58.bpo-33503.Wvt0qg.rst M Doc/distributing/index.rst M Doc/distutils/apiref.rst M Doc/distutils/packageindex.rst M Doc/distutils/setupscript.rst M Doc/faq/general.rst M Doc/faq/library.rst M Doc/howto/curses.rst M Doc/howto/pyporting.rst M Doc/installing/index.rst M Doc/library/distribution.rst M Doc/library/index.rst M Doc/library/pprint.rst M Doc/library/re.rst M Doc/library/ssl.rst M Doc/library/unittest.mock.rst M Doc/library/xml.rst M Doc/tutorial/venv.rst M Doc/tutorial/whatnow.rst M Doc/using/windows.rst M Doc/whatsnew/2.3.rst M Doc/whatsnew/2.5.rst M Doc/whatsnew/2.7.rst M Doc/whatsnew/3.5.rst diff --git a/Doc/distributing/index.rst b/Doc/distributing/index.rst index aedbe712d3db..5dd14b1f7a60 100644 --- a/Doc/distributing/index.rst +++ b/Doc/distributing/index.rst @@ -31,7 +31,7 @@ installing other Python projects, refer to the Key terms ========= -* the `Python Packaging Index <https://pypi.python.org/pypi>`__ is a public +* the `Python Packaging Index <https://pypi.org>`__ is a public repository of open source licensed packages made available for use by other Python users * the `Python Packaging Authority diff --git a/Doc/distutils/apiref.rst b/Doc/distutils/apiref.rst index 9fce46ad2669..3c89468220a4 100644 --- a/Doc/distutils/apiref.rst +++ b/Doc/distutils/apiref.rst @@ -78,7 +78,7 @@ setup script). Indirectly provides the :class:`distutils.dist.Distribution` and | | be built | :class:`distutils.core.Extension` | +--------------------+--------------------------------+-------------------------------------------------------------+ | *classifiers* | A list of categories for the | a list of strings; valid classifiers are listed on `PyPI | - | | package | <https://pypi.python.org/pypi?:action=list_classifiers>`_. | + | | package | <https://pypi.org/classifiers>`_. | +--------------------+--------------------------------+-------------------------------------------------------------+ | *distclass* | the :class:`Distribution` | a subclass of | | | class to use | :class:`distutils.core.Distribution` | diff --git a/Doc/distutils/packageindex.rst b/Doc/distutils/packageindex.rst index 086e14eb255a..50cb74f2b6ca 100644 --- a/Doc/distutils/packageindex.rst +++ b/Doc/distutils/packageindex.rst @@ -250,4 +250,4 @@ without warnings does not guarantee that PyPI will convert the content successfully. -.. _Python Package Index (PyPI): https://pypi.python.org/pypi +.. _Python Package Index (PyPI): https://pypi.org diff --git a/Doc/distutils/setupscript.rst b/Doc/distutils/setupscript.rst index 952607a4073b..1d96acbe98f6 100644 --- a/Doc/distutils/setupscript.rst +++ b/Doc/distutils/setupscript.rst @@ -625,7 +625,7 @@ Notes: (7) The valid classifiers are listed on - `PyPI <https://pypi.python.org/pypi?:action=list_classifiers>`_. + `PyPI <https://pypi.org/classifiers>`_. (8) To preserve backward compatibility, this field also accepts a string. If diff --git a/Doc/faq/general.rst b/Doc/faq/general.rst index 0d1cb198da87..9d3e199fca6b 100644 --- a/Doc/faq/general.rst +++ b/Doc/faq/general.rst @@ -117,7 +117,7 @@ programming), software engineering (unit testing, logging, profiling, parsing Python code), and operating system interfaces (system calls, filesystems, TCP/IP sockets). Look at the table of contents for :ref:`library-index` to get an idea of what's available. A wide variety of third-party extensions are also -available. Consult `the Python Package Index <https://pypi.python.org/pypi>`_ to +available. Consult `the Python Package Index <https://pypi.org>`_ to find packages of interest to you. diff --git a/Doc/faq/library.rst b/Doc/faq/library.rst index aec4bf9b85d5..ab92a879a885 100644 --- a/Doc/faq/library.rst +++ b/Doc/faq/library.rst @@ -19,7 +19,7 @@ standard library module. (Eventually you'll learn what's in the standard library and will be able to skip this step.) For third-party packages, search the `Python Package Index -<https://pypi.python.org/pypi>`_ or try `Google <https://www.google.com>`_ or +<https://pypi.org>`_ or try `Google <https://www.google.com>`_ or another Web search engine. Searching for "Python" plus a keyword or two for your topic of interest will usually find something helpful. @@ -611,7 +611,7 @@ use ``p.read(n)``. "expect" library. A Python extension that interfaces to expect is called "expy" and available from http://expectpy.sourceforge.net. A pure Python solution that works like expect is `pexpect - <https://pypi.python.org/pypi/pexpect/>`_. + <https://pypi.org/project/pexpect/>`_. How do I access the serial (RS232) port? diff --git a/Doc/howto/curses.rst b/Doc/howto/curses.rst index 19d65d6996b7..cc4b4785b122 100644 --- a/Doc/howto/curses.rst +++ b/Doc/howto/curses.rst @@ -41,7 +41,7 @@ appearance---and the curses library will figure out what control codes need to be sent to the terminal to produce the right output. curses doesn't provide many user-interface concepts such as buttons, checkboxes, or dialogs; if you need such features, consider a user interface library such as -`Urwid <https://pypi.python.org/pypi/urwid/>`_. +`Urwid <https://pypi.org/project/urwid/>`_. The curses library was originally written for BSD Unix; the later System V versions of Unix from AT&T added many enhancements and new functions. BSD curses @@ -55,7 +55,7 @@ everything, though. The Windows version of Python doesn't include the :mod:`curses` module. A ported version called `UniCurses -<https://pypi.python.org/pypi/UniCurses>`_ is available. You could +<https://pypi.org/project/UniCurses>`_ is available. You could also try `the Console module <http://effbot.org/zone/console-index.htm>`_ written by Fredrik Lundh, which doesn't use the same API as curses but provides cursor-addressable text output @@ -432,7 +432,7 @@ User Input The C curses library offers only very simple input mechanisms. Python's :mod:`curses` module adds a basic text-input widget. (Other libraries -such as `Urwid <https://pypi.python.org/pypi/urwid/>`_ have more extensive +such as `Urwid <https://pypi.org/project/urwid/>`_ have more extensive collections of widgets.) There are two methods for getting input from a window: diff --git a/Doc/howto/pyporting.rst b/Doc/howto/pyporting.rst index 98c81206741a..3be6bb380d66 100644 --- a/Doc/howto/pyporting.rst +++ b/Doc/howto/pyporting.rst @@ -427,25 +427,25 @@ to make sure everything functions as expected in both versions of Python. .. _2to3: https://docs.python.org/3/library/2to3.html -.. _caniusepython3: https://pypi.python.org/pypi/caniusepython3 +.. _caniusepython3: https://pypi.org/project/caniusepython3 .. _cheat sheet: http://python-future.org/compatible_idioms.html -.. _coverage.py: https://pypi.python.org/pypi/coverage +.. _coverage.py: https://pypi.org/project/coverage .. _Futurize: http://python-future.org/automatic_conversion.html .. _importlib: https://docs.python.org/3/library/importlib.html#module-importlib -.. _importlib2: https://pypi.python.org/pypi/importlib2 +.. _importlib2: https://pypi.org/project/importlib2 .. _Modernize: https://python-modernize.readthedocs.io/ .. _mypy: http://mypy-lang.org/ .. _Porting to Python 3: http://python3porting.com/ -.. _Pylint: https://pypi.python.org/pypi/pylint +.. _Pylint: https://pypi.org/project/pylint .. _Python 3 Q & A: https://ncoghlan-devs-python-notes.readthedocs.io/en/latest/python3/questions_and_answers.html .. _pytype: https://github.com/google/pytype .. _python-future: http://python-future.org/ .. _python-porting: https://mail.python.org/mailman/listinfo/python-porting -.. _six: https://pypi.python.org/pypi/six -.. _tox: https://pypi.python.org/pypi/tox -.. _trove classifier: https://pypi.python.org/pypi?%3Aaction=list_classifiers +.. _six: https://pypi.org/project/six +.. _tox: https://pypi.org/project/tox +.. _trove classifier: https://pypi.org/classifiers .. _"What's New": https://docs.python.org/3/whatsnew/index.html diff --git a/Doc/installing/index.rst b/Doc/installing/index.rst index 9f9f5a070b26..8f105a15161c 100644 --- a/Doc/installing/index.rst +++ b/Doc/installing/index.rst @@ -44,7 +44,7 @@ Key terms ``venv``. It allows virtual environments to be used on versions of Python prior to 3.4, which either don't provide ``venv`` at all, or aren't able to automatically install ``pip`` into created environments. -* The `Python Packaging Index <https://pypi.python.org/pypi>`__ is a public +* The `Python Packaging Index <https://pypi.org>`__ is a public repository of open source licensed packages made available for use by other Python users. * the `Python Packaging Authority diff --git a/Doc/library/distribution.rst b/Doc/library/distribution.rst index 3e6e84b42a2e..8d4befe41b32 100644 --- a/Doc/library/distribution.rst +++ b/Doc/library/distribution.rst @@ -4,7 +4,7 @@ Software Packaging and Distribution These libraries help you with publishing and installing Python software. While these modules are designed to work in conjunction with the -`Python Package Index <https://pypi.python.org/pypi>`__, they can also be used +`Python Package Index <https://pypi.org>`__, they can also be used with a local index server, or without any index server at all. .. toctree:: diff --git a/Doc/library/index.rst b/Doc/library/index.rst index da6a460e2c31..b8fbf44ae49f 100644 --- a/Doc/library/index.rst +++ b/Doc/library/index.rst @@ -30,7 +30,7 @@ optional components. In addition to the standard library, there is a growing collection of several thousand components (from individual programs and modules to packages and entire application development frameworks), available from -the `Python Package Index <https://pypi.python.org/pypi>`_. +the `Python Package Index <https://pypi.org>`_. .. toctree:: diff --git a/Doc/library/pprint.rst b/Doc/library/pprint.rst index 65d94fe386c8..aa97d3eabafa 100644 --- a/Doc/library/pprint.rst +++ b/Doc/library/pprint.rst @@ -212,12 +212,12 @@ Example ------- To demonstrate several uses of the :func:`pprint` function and its parameters, -let's fetch information about a project from `PyPI <https://pypi.python.org/pypi>`_:: +let's fetch information about a project from `PyPI <https://pypi.org>`_:: >>> import json >>> import pprint >>> from urllib.request import urlopen - >>> with urlopen('http://pypi.python.org/pypi/Twisted/json') as url: + >>> with urlopen('http://pypi.org/project/Twisted/json') as url: ... http_info = url.info() ... raw_data = url.read().decode(http_info.get_content_charset()) >>> project_info = json.loads(raw_data) @@ -248,9 +248,9 @@ In its basic form, :func:`pprint` shows the whole object:: 'maintainer': '', 'maintainer_email': '', 'name': 'Twisted', - 'package_url': 'http://pypi.python.org/pypi/Twisted', + 'package_url': 'http://pypi.org/project/Twisted', 'platform': 'UNKNOWN', - 'release_url': 'http://pypi.python.org/pypi/Twisted/12.3.0', + 'release_url': 'http://pypi.org/project/Twisted/12.3.0', 'requires_python': None, 'stable_version': None, 'summary': 'An asynchronous networking framework written in Python', @@ -264,7 +264,7 @@ In its basic form, :func:`pprint` shows the whole object:: 'python_version': 'source', 'size': 2615733, 'upload_time': '2012-12-26T12:47:03', - 'url': 'https://pypi.python.org/packages/source/T/Twisted/Twisted-12.3.0.tar.bz2'}, + 'url': 'https://pypi.org/packages/source/T/Twisted/Twisted-12.3.0.tar.bz2'}, {'comment_text': '', 'downloads': 5224, 'filename': 'Twisted-12.3.0.win32-py2.7.msi', @@ -274,7 +274,7 @@ In its basic form, :func:`pprint` shows the whole object:: 'python_version': '2.7', 'size': 2916352, 'upload_time': '2012-12-26T12:48:15', - 'url': 'https://pypi.python.org/packages/2.7/T/Twisted/Twisted-12.3.0.win32-py2.7.msi'}]} + 'url': 'https://pypi.org/packages/2.7/T/Twisted/Twisted-12.3.0.win32-py2.7.msi'}]} The result can be limited to a certain *depth* (ellipsis is used for deeper contents):: @@ -301,9 +301,9 @@ contents):: 'maintainer': '', 'maintainer_email': '', 'name': 'Twisted', - 'package_url': 'http://pypi.python.org/pypi/Twisted', + 'package_url': 'http://pypi.org/project/Twisted', 'platform': 'UNKNOWN', - 'release_url': 'http://pypi.python.org/pypi/Twisted/12.3.0', + 'release_url': 'http://pypi.org/project/Twisted/12.3.0', 'requires_python': None, 'stable_version': None, 'summary': 'An asynchronous networking framework written in Python', @@ -339,9 +339,9 @@ cannot be split, the specified width will be exceeded:: 'maintainer': '', 'maintainer_email': '', 'name': 'Twisted', - 'package_url': 'http://pypi.python.org/pypi/Twisted', + 'package_url': 'http://pypi.org/project/Twisted', 'platform': 'UNKNOWN', - 'release_url': 'http://pypi.python.org/pypi/Twisted/12.3.0', + 'release_url': 'http://pypi.org/project/Twisted/12.3.0', 'requires_python': None, 'stable_version': None, 'summary': 'An asynchronous networking ' diff --git a/Doc/library/re.rst b/Doc/library/re.rst index ddb74f8d386c..b5a888345995 100644 --- a/Doc/library/re.rst +++ b/Doc/library/re.rst @@ -45,7 +45,7 @@ fine-tuning parameters. .. seealso:: - The third-party `regex <https://pypi.python.org/pypi/regex/>`_ module, + The third-party `regex <https://pypi.org/project/regex/>`_ module, which has an API compatible with the standard library :mod:`re` module, but offers additional functionality and a more thorough Unicode support. diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 8082a383d5ab..f96549427afc 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -2158,9 +2158,9 @@ Visual inspection shows that the certificate does identify the desired service (('commonName', 'www.python.org'),)), 'subjectAltName': (('DNS', 'www.python.org'), ('DNS', 'python.org'), - ('DNS', 'pypi.python.org'), + ('DNS', 'pypi.org'), ('DNS', 'docs.python.org'), - ('DNS', 'testpypi.python.org'), + ('DNS', 'testpypi.org'), ('DNS', 'bugs.python.org'), ('DNS', 'wiki.python.org'), ('DNS', 'hg.python.org'), diff --git a/Doc/library/unittest.mock.rst b/Doc/library/unittest.mock.rst index ac9dd3b6f793..bb647bb6a811 100644 --- a/Doc/library/unittest.mock.rst +++ b/Doc/library/unittest.mock.rst @@ -35,7 +35,7 @@ is based on the 'action -> assertion' pattern instead of 'record -> replay' used by many mocking frameworks. There is a backport of :mod:`unittest.mock` for earlier versions of Python, -available as `mock on PyPI <https://pypi.python.org/pypi/mock>`_. +available as `mock on PyPI <https://pypi.org/project/mock>`_. Quick Guide @@ -2085,7 +2085,7 @@ mock_open the start. If you need more control over the data that you are feeding to the tested code you will need to customize this mock for yourself. When that is insufficient, one of the in-memory filesystem packages on `PyPI - <https://pypi.python.org/pypi>`_ can offer a realistic filesystem for testing. + <https://pypi.org>`_ can offer a realistic filesystem for testing. .. versionchanged:: 3.4 Added :meth:`~io.IOBase.readline` and :meth:`~io.IOBase.readlines` support. diff --git a/Doc/library/xml.rst b/Doc/library/xml.rst index d833b7fe9977..63c24f80ac87 100644 --- a/Doc/library/xml.rst +++ b/Doc/library/xml.rst @@ -130,8 +130,8 @@ but will not be included in any bugfix releases of Python because they break backward compatibility. -.. _defusedxml: https://pypi.python.org/pypi/defusedxml/ -.. _defusedexpat: https://pypi.python.org/pypi/defusedexpat/ +.. _defusedxml: https://pypi.org/project/defusedxml/ +.. _defusedexpat: https://pypi.org/project/defusedexpat/ .. _Billion Laughs: https://en.wikipedia.org/wiki/Billion_laughs .. _ZIP bomb: https://en.wikipedia.org/wiki/Zip_bomb .. _DTD: https://en.wikipedia.org/wiki/Document_type_definition diff --git a/Doc/tutorial/venv.rst b/Doc/tutorial/venv.rst index e2dd57d48f22..dc4136e42a88 100644 --- a/Doc/tutorial/venv.rst +++ b/Doc/tutorial/venv.rst @@ -88,7 +88,7 @@ Managing Packages with pip You can install, upgrade, and remove packages using a program called :program:`pip`. By default ``pip`` will install packages from the Python -Package Index, <https://pypi.python.org/pypi>. You can browse the Python +Package Index, <https://pypi.org>. You can browse the Python Package Index by going to it in your web browser, or you can use ``pip``'s limited search feature: diff --git a/Doc/tutorial/whatnow.rst b/Doc/tutorial/whatnow.rst index 1ea22ae5cdcc..d876d0740d80 100644 --- a/Doc/tutorial/whatnow.rst +++ b/Doc/tutorial/whatnow.rst @@ -38,7 +38,7 @@ More Python resources: * https://docs.python.org: Fast access to Python's documentation. -* https://pypi.python.org/pypi: The Python Package Index, previously also nicknamed +* https://pypi.org: The Python Package Index, previously also nicknamed the Cheese Shop, is an index of user-created Python modules that are available for download. Once you begin releasing code, you can register it here so that others can find it. diff --git a/Doc/using/windows.rst b/Doc/using/windows.rst index 3bab6fe503ca..5cbf13f51081 100644 --- a/Doc/using/windows.rst +++ b/Doc/using/windows.rst @@ -848,7 +848,7 @@ The Windows-specific standard modules are documented in PyWin32 ------- -The `PyWin32 <https://pypi.python.org/pypi/pywin32>`_ module by Mark Hammond +The `PyWin32 <https://pypi.org/project/pywin32>`_ module by Mark Hammond is a collection of modules for advanced Windows-specific support. This includes utilities for: diff --git a/Doc/whatsnew/2.3.rst b/Doc/whatsnew/2.3.rst index b5628a910ae8..590015af98f1 100644 --- a/Doc/whatsnew/2.3.rst +++ b/Doc/whatsnew/2.3.rst @@ -659,7 +659,7 @@ The heart of the catalog is the new Distutils :command:`register` command. Running ``python setup.py register`` will collect the metadata describing a package, such as its name, version, maintainer, description, &c., and send it to a central catalog server. The resulting catalog is available from -https://pypi.python.org/pypi. +https://pypi.org. To make the catalog a bit more useful, a new optional *classifiers* keyword argument has been added to the Distutils :func:`setup` function. A list of diff --git a/Doc/whatsnew/2.5.rst b/Doc/whatsnew/2.5.rst index 15d35d384c40..79c5a73dcf2b 100644 --- a/Doc/whatsnew/2.5.rst +++ b/Doc/whatsnew/2.5.rst @@ -229,7 +229,7 @@ required packages. :: ) Another new enhancement to the Python package index at -https://pypi.python.org is storing source and binary archives for a +https://pypi.org is storing source and binary archives for a package. The new :command:`upload` Distutils command will upload a package to the repository. diff --git a/Doc/whatsnew/2.7.rst b/Doc/whatsnew/2.7.rst index 90ce06c32868..02525f4c4c9b 100644 --- a/Doc/whatsnew/2.7.rst +++ b/Doc/whatsnew/2.7.rst @@ -1828,7 +1828,7 @@ new features were added. Most of these features were implemented by Michael Foord, unless otherwise noted. The enhanced version of the module is downloadable separately for use with Python versions 2.4 to 2.6, packaged as the :mod:`unittest2` package, from -https://pypi.python.org/pypi/unittest2. +https://pypi.org/project/unittest2. When used from the command line, the module can automatically discover tests. It's not as fancy as `py.test <http://pytest.org>`__ or diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst index a6ba5bbb720c..3e3329a84cf4 100644 --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -951,7 +951,7 @@ New :class:`~collections.abc.Awaitable`, :class:`~collections.abc.Coroutine`, (Contributed by Yury Selivanov in :issue:`24184`.) For earlier Python versions, a backport of the new ABCs is available in an -external `PyPI package <https://pypi.python.org/pypi/backports_abc>`_. +external `PyPI package <https://pypi.org/project/backports_abc>`_. compileall diff --git a/Misc/NEWS.d/next/Documentation/2018-05-14-20-08-58.bpo-33503.Wvt0qg.rst b/Misc/NEWS.d/next/Documentation/2018-05-14-20-08-58.bpo-33503.Wvt0qg.rst new file mode 100644 index 000000000000..27025c31a036 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2018-05-14-20-08-58.bpo-33503.Wvt0qg.rst @@ -0,0 +1 @@ +Fix broken pypi link From webhook-mailer at python.org Tue May 15 15:57:16 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 15 May 2018 19:57:16 -0000 Subject: [Python-checkins] bpo-29706: Test that IDLE colors async/await as keywords. (GH-6846) Message-ID: <mailman.57.1526414237.2757.python-checkins@python.org> https://github.com/python/cpython/commit/8717cfeb6b8bebdfe13df0e9268ddd252ab5ecad commit: 8717cfeb6b8bebdfe13df0e9268ddd252ab5ecad branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-15T12:57:13-07:00 summary: bpo-29706: Test that IDLE colors async/await as keywords. (GH-6846) Added to the eye-verified htest, not to the unittests. Also remove some stray leftover comments. (cherry picked from commit 389a48ede92bf7965889d554d2cd17b50d6e3d86) Co-authored-by: Terry Jan Reedy <tjreedy at udel.edu> files: M Lib/idlelib/colorizer.py diff --git a/Lib/idlelib/colorizer.py b/Lib/idlelib/colorizer.py index 5cb85f24dfd7..1f31ce22d7e5 100644 --- a/Lib/idlelib/colorizer.py +++ b/Lib/idlelib/colorizer.py @@ -17,8 +17,6 @@ def make_pat(): builtinlist = [str(name) for name in dir(builtins) if not name.startswith('_') and \ name not in keyword.kwlist] - # self.file = open("file") : - # 1st 'file' colorized normal, 2nd as builtin, 3rd as string builtin = r"([^.'\"\\#]\b|^)" + any("BUILTIN", builtinlist) + r"\b" comment = any("COMMENT", [r"#[^\n]*"]) stringprefix = r"(?i:r|u|f|fr|rf|b|br|rb)?" @@ -268,13 +266,14 @@ def _color_delegator(parent): # htest # "else: float(None)\n" "if iF + If + IF: 'keyword matching must respect case'\n" "if'': x or'' # valid string-keyword no-space combinations\n" + "async def f(): await g()\n" "# All valid prefixes for unicode and byte strings should be colored.\n" "'x', '''x''', \"x\", \"\"\"x\"\"\"\n" "r'x', u'x', R'x', U'x', f'x', F'x'\n" "fr'x', Fr'x', fR'x', FR'x', rf'x', rF'x', Rf'x', RF'x'\n" "b'x',B'x', br'x',Br'x',bR'x',BR'x', rb'x'.rB'x',Rb'x',RB'x'\n" "# Invalid combinations of legal characters should be half colored.\n" - "ur'x', ru'x', uf'x', fu'x', UR'x', ufr'x', rfu'x', xf'x', fx'x'" + "ur'x', ru'x', uf'x', fu'x', UR'x', ufr'x', rfu'x', xf'x', fx'x'\n" ) text = Text(top, background="white") text.pack(expand=1, fill="both") From webhook-mailer at python.org Tue May 15 16:25:43 2018 From: webhook-mailer at python.org (Ned Deily) Date: Tue, 15 May 2018 20:25:43 -0000 Subject: [Python-checkins] bpo-32257: Add ssl.OP_NO_RENEGOTIATION (GH-5904) Message-ID: <mailman.58.1526415944.2757.python-checkins@python.org> https://github.com/python/cpython/commit/67c48016638aac9a15afe6fd6754d53d2bdd6b76 commit: 67c48016638aac9a15afe6fd6754d53d2bdd6b76 branch: master author: Christian Heimes <christian at python.org> committer: Ned Deily <nad at python.org> date: 2018-05-15T16:25:40-04:00 summary: bpo-32257: Add ssl.OP_NO_RENEGOTIATION (GH-5904) The ssl module now contains OP_NO_RENEGOTIATION constant, available with OpenSSL 1.1.0h or 1.1.1. Note, OpenSSL 1.1.0h hasn't been released yet. Signed-off-by: Christian Heimes <christian at python.org> files: A Misc/NEWS.d/next/Library/2018-02-26-09-08-07.bpo-32257.6ElnUt.rst M Doc/library/ssl.rst M Modules/_ssl.c diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index f96549427afc..dcb26664feae 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -803,6 +803,15 @@ Constants The option is deprecated since OpenSSL 1.1.0. It was added to 2.7.15, 3.6.3 and 3.7.0 for backwards compatibility with OpenSSL 1.0.2. +.. data:: OP_NO_RENEGOTIATION + + Disable all renegotiation in TLSv1.2 and earlier. Do not send + HelloRequest messages, and ignore renegotiation requests via ClientHello. + + This option is only available with OpenSSL 1.1.0h and later. + + .. versionadded:: 3.7 + .. data:: OP_CIPHER_SERVER_PREFERENCE Use the server's cipher ordering preference, rather than the client's. diff --git a/Misc/NEWS.d/next/Library/2018-02-26-09-08-07.bpo-32257.6ElnUt.rst b/Misc/NEWS.d/next/Library/2018-02-26-09-08-07.bpo-32257.6ElnUt.rst new file mode 100644 index 000000000000..e74c39b68100 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-26-09-08-07.bpo-32257.6ElnUt.rst @@ -0,0 +1,2 @@ +The ssl module now contains OP_NO_RENEGOTIATION constant, available with +OpenSSL 1.1.0h or 1.1.1. diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 7670833bf5f5..bf379f01a1d2 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -5845,6 +5845,10 @@ PyInit__ssl(void) PyModule_AddIntConstant(m, "OP_ENABLE_MIDDLEBOX_COMPAT", SSL_OP_ENABLE_MIDDLEBOX_COMPAT); #endif +#ifdef SSL_OP_NO_RENEGOTIATION + PyModule_AddIntConstant(m, "OP_NO_RENEGOTIATION", + SSL_OP_NO_RENEGOTIATION); +#endif #ifdef X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT PyModule_AddIntConstant(m, "HOSTFLAG_ALWAYS_CHECK_SUBJECT", From webhook-mailer at python.org Tue May 15 16:48:17 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 15 May 2018 20:48:17 -0000 Subject: [Python-checkins] bpo-29706: Test that IDLE colors async/await as keywords. (GH-6846) Message-ID: <mailman.59.1526417298.2757.python-checkins@python.org> https://github.com/python/cpython/commit/7c59a33491b0bde639a9382ef1de2423207a8cc7 commit: 7c59a33491b0bde639a9382ef1de2423207a8cc7 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-15T13:48:14-07:00 summary: bpo-29706: Test that IDLE colors async/await as keywords. (GH-6846) Added to the eye-verified htest, not to the unittests. Also remove some stray leftover comments. (cherry picked from commit 389a48ede92bf7965889d554d2cd17b50d6e3d86) Co-authored-by: Terry Jan Reedy <tjreedy at udel.edu> files: M Lib/idlelib/colorizer.py diff --git a/Lib/idlelib/colorizer.py b/Lib/idlelib/colorizer.py index 5cb85f24dfd7..1f31ce22d7e5 100644 --- a/Lib/idlelib/colorizer.py +++ b/Lib/idlelib/colorizer.py @@ -17,8 +17,6 @@ def make_pat(): builtinlist = [str(name) for name in dir(builtins) if not name.startswith('_') and \ name not in keyword.kwlist] - # self.file = open("file") : - # 1st 'file' colorized normal, 2nd as builtin, 3rd as string builtin = r"([^.'\"\\#]\b|^)" + any("BUILTIN", builtinlist) + r"\b" comment = any("COMMENT", [r"#[^\n]*"]) stringprefix = r"(?i:r|u|f|fr|rf|b|br|rb)?" @@ -268,13 +266,14 @@ def _color_delegator(parent): # htest # "else: float(None)\n" "if iF + If + IF: 'keyword matching must respect case'\n" "if'': x or'' # valid string-keyword no-space combinations\n" + "async def f(): await g()\n" "# All valid prefixes for unicode and byte strings should be colored.\n" "'x', '''x''', \"x\", \"\"\"x\"\"\"\n" "r'x', u'x', R'x', U'x', f'x', F'x'\n" "fr'x', Fr'x', fR'x', FR'x', rf'x', rF'x', Rf'x', RF'x'\n" "b'x',B'x', br'x',Br'x',bR'x',BR'x', rb'x'.rB'x',Rb'x',RB'x'\n" "# Invalid combinations of legal characters should be half colored.\n" - "ur'x', ru'x', uf'x', fu'x', UR'x', ufr'x', rfu'x', xf'x', fx'x'" + "ur'x', ru'x', uf'x', fu'x', UR'x', ufr'x', rfu'x', xf'x', fx'x'\n" ) text = Text(top, background="white") text.pack(expand=1, fill="both") From webhook-mailer at python.org Tue May 15 16:56:31 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 15 May 2018 20:56:31 -0000 Subject: [Python-checkins] bpo-33509: Fix _warnings for module_globals=None (GH-6833) Message-ID: <mailman.60.1526417793.2757.python-checkins@python.org> https://github.com/python/cpython/commit/820219f7867f2bbfe0ac4d4f0d1ea1fdef7795a9 commit: 820219f7867f2bbfe0ac4d4f0d1ea1fdef7795a9 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-15T13:56:28-07:00 summary: bpo-33509: Fix _warnings for module_globals=None (GH-6833) Don't crash on warnings.warn_explicit() if module_globals is not a dict. (cherry picked from commit b056562860c227bad2e0ba7cd3130e115c007768) Co-authored-by: Victor Stinner <vstinner at redhat.com> files: A Misc/NEWS.d/next/Core and Builtins/2018-05-14-17-31-02.bpo-33509.pIUfTd.rst M Lib/test/test_warnings/__init__.py M Python/_warnings.c diff --git a/Lib/test/test_warnings/__init__.py b/Lib/test/test_warnings/__init__.py index 31ab94b74716..940db5c143c9 100644 --- a/Lib/test/test_warnings/__init__.py +++ b/Lib/test/test_warnings/__init__.py @@ -218,6 +218,25 @@ def test_once(self): 42) self.assertEqual(len(w), 0) + def test_module_globals(self): + with original_warnings.catch_warnings(record=True, + module=self.module) as w: + # bpo-33509: module_globals=None must not crash + self.module.warn_explicit('msg', UserWarning, "filename", 42, + module_globals=None) + self.assertEqual(len(w), 1) + + # Invalid module_globals type + with self.assertRaises(TypeError): + self.module.warn_explicit('msg', UserWarning, "filename", 42, + module_globals=True) + self.assertEqual(len(w), 1) + + # Empty module_globals + self.module.warn_explicit('msg', UserWarning, "filename", 42, + module_globals={}) + self.assertEqual(len(w), 2) + def test_inheritance(self): with original_warnings.catch_warnings(module=self.module) as w: self.module.resetwarnings() diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-05-14-17-31-02.bpo-33509.pIUfTd.rst b/Misc/NEWS.d/next/Core and Builtins/2018-05-14-17-31-02.bpo-33509.pIUfTd.rst new file mode 100644 index 000000000000..3d80a8c7f3eb --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-05-14-17-31-02.bpo-33509.pIUfTd.rst @@ -0,0 +1,2 @@ +Fix module_globals parameter of warnings.warn_explicit(): don't crash if +module_globals is not a dict. diff --git a/Python/_warnings.c b/Python/_warnings.c index 0568af4df5a8..29e475d67d1f 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -951,7 +951,14 @@ warnings_warn_explicit(PyObject *self, PyObject *args, PyObject *kwds) ®istry, &module_globals, &sourceobj)) return NULL; - if (module_globals) { + if (module_globals && module_globals != Py_None) { + if (!PyDict_Check(module_globals)) { + PyErr_Format(PyExc_TypeError, + "module_globals must be a dict, not '%.200s'", + Py_TYPE(module_globals)->tp_name); + return NULL; + } + source_line = get_source_line(module_globals, lineno); if (source_line == NULL && PyErr_Occurred()) { return NULL; From webhook-mailer at python.org Tue May 15 17:24:30 2018 From: webhook-mailer at python.org (Barry Warsaw) Date: Tue, 15 May 2018 21:24:30 -0000 Subject: [Python-checkins] bpo-33465: Use an unlikely to be built-in C extension in a test (GH-6797) (#6869) Message-ID: <mailman.61.1526419471.2757.python-checkins@python.org> https://github.com/python/cpython/commit/2cdb70ac5df30db021417ab71a327d9b4322de13 commit: 2cdb70ac5df30db021417ab71a327d9b4322de13 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Barry Warsaw <barry at python.org> date: 2018-05-15T17:24:26-04:00 summary: bpo-33465: Use an unlikely to be built-in C extension in a test (GH-6797) (#6869) (cherry picked from commit 8709b236fc997077d24b4802320db287640f82e2) Co-authored-by: Barry Warsaw <barry at python.org> files: M Lib/test/test_import/__init__.py diff --git a/Lib/test/test_import/__init__.py b/Lib/test/test_import/__init__.py index 049ee57e58a0..1fc4de11e178 100644 --- a/Lib/test/test_import/__init__.py +++ b/Lib/test/test_import/__init__.py @@ -90,13 +90,14 @@ def test_from_import_missing_attr_has_name_and_path(self): self.assertEqual(cm.exception.path, os.__file__) self.assertRegex(str(cm.exception), r"cannot import name 'i_dont_exist' from 'os' \(.*os.py\)") + @cpython_only def test_from_import_missing_attr_has_name_and_so_path(self): - import select + import _testcapi with self.assertRaises(ImportError) as cm: - from select import i_dont_exist - self.assertEqual(cm.exception.name, 'select') - self.assertEqual(cm.exception.path, select.__file__) - self.assertRegex(str(cm.exception), r"cannot import name 'i_dont_exist' from 'select' \(.*\.(so|pyd)\)") + from _testcapi import i_dont_exist + self.assertEqual(cm.exception.name, '_testcapi') + self.assertEqual(cm.exception.path, _testcapi.__file__) + self.assertRegex(str(cm.exception), r"cannot import name 'i_dont_exist' from '_testcapi' \(.*\.(so|pyd)\)") def test_from_import_missing_attr_has_name(self): with self.assertRaises(ImportError) as cm: From webhook-mailer at python.org Tue May 15 17:42:00 2018 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Tue, 15 May 2018 21:42:00 -0000 Subject: [Python-checkins] bpo-30928: Update idlelib/NEWS.txt to 2018-05-14. (#6873) Message-ID: <mailman.62.1526420522.2757.python-checkins@python.org> https://github.com/python/cpython/commit/038b21f2caaed0f02fee524277cc61e2c6ae0e9a commit: 038b21f2caaed0f02fee524277cc61e2c6ae0e9a branch: master author: Terry Jan Reedy <tjreedy at udel.edu> committer: GitHub <noreply at github.com> date: 2018-05-15T17:41:57-04:00 summary: bpo-30928: Update idlelib/NEWS.txt to 2018-05-14. (#6873) files: M Lib/idlelib/NEWS.txt diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index c8b0caabd284..e255b0402d42 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -3,6 +3,27 @@ Released on 2018-06-18? ====================================== +bpo-21474: Update word/identifier definition from ascii to unicode. +In text and entry boxes, this affects selection by double-click, +movement left/right by control-left/right, and deletion left/right +by control-BACKSPACE/DEL. + +bpo-33204: Consistently color invalid string prefixes. +A 'u' string prefix cannot be paired with either 'r' or 'f'. +IDLE now consistently colors as much of the prefix, starting at the +right, as is valid. Revise and extend colorizer test. + +bpo-32984: Set __file__ while running a startup file. +Like Python, IDLE optionally runs 1 startup file in the Shell window +before presenting the first interactive input prompt. For IDLE, +option -s runs a file named in environmental variable IDLESTARTUP or +PYTHONSTARTUP; -r file runs file. Python sets __file__ to the startup +file name before running the file and unsets it before the first +prompt. IDLE now does the same when run normally, without the -n +option. + +bpo-32940: Replace StringTranslatePseudoMapping with faster code. + bpo-32916: Change 'str' to 'code' in idlelib.pyparse and users. bpo-32905: Remove unused code in pyparse module. From webhook-mailer at python.org Tue May 15 18:08:12 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Tue, 15 May 2018 22:08:12 -0000 Subject: [Python-checkins] bpo-33454: Fix arguments parsing in _xxsubinterpreters.channel_close(). (GH-6747) Message-ID: <mailman.63.1526422094.2757.python-checkins@python.org> https://github.com/python/cpython/commit/d8dcd57edb88ce57063e5c2b85fe0ee1abb1ce8b commit: d8dcd57edb88ce57063e5c2b85fe0ee1abb1ce8b branch: master author: Serhiy Storchaka <storchaka at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-16T01:08:09+03:00 summary: bpo-33454: Fix arguments parsing in _xxsubinterpreters.channel_close(). (GH-6747) files: M Modules/_xxsubinterpretersmodule.c diff --git a/Modules/_xxsubinterpretersmodule.c b/Modules/_xxsubinterpretersmodule.c index 634823a7a271..f5e2ea3c79d6 100644 --- a/Modules/_xxsubinterpretersmodule.c +++ b/Modules/_xxsubinterpretersmodule.c @@ -2470,12 +2470,8 @@ PyDoc_STRVAR(channel_recv_doc, Return a new object from the data at the from of the channel's queue."); static PyObject * -channel_close(PyObject *self, PyObject *args, PyObject *kwds) +channel_close(PyObject *self, PyObject *id) { - PyObject *id; - if (!PyArg_UnpackTuple(args, "channel_recv", 1, 1, &id)) { - return NULL; - } int64_t cid = _coerce_id(id); if (cid < 0) { return NULL; @@ -2570,8 +2566,8 @@ static PyMethodDef module_functions[] = { METH_VARARGS, channel_send_doc}, {"channel_recv", (PyCFunction)channel_recv, METH_VARARGS, channel_recv_doc}, - {"channel_close", (PyCFunction)channel_close, - METH_VARARGS, channel_close_doc}, + {"channel_close", channel_close, + METH_O, channel_close_doc}, {"channel_drop_interpreter", (PyCFunction)channel_drop_interpreter, METH_VARARGS | METH_KEYWORDS, channel_drop_interpreter_doc}, {"_channel_id", (PyCFunction)channel__channel_id, From webhook-mailer at python.org Tue May 15 20:10:49 2018 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Wed, 16 May 2018 00:10:49 -0000 Subject: [Python-checkins] [3.6] bpo-29706: IDLE now colors async and await as keywords in 3.6. (#6879) Message-ID: <mailman.64.1526429450.2757.python-checkins@python.org> https://github.com/python/cpython/commit/1b0d65fa102fae087254009f6d9903b1d4257d78 commit: 1b0d65fa102fae087254009f6d9903b1d4257d78 branch: 3.6 author: Terry Jan Reedy <tjreedy at udel.edu> committer: GitHub <noreply at github.com> date: 2018-05-15T20:10:46-04:00 summary: [3.6] bpo-29706: IDLE now colors async and await as keywords in 3.6. (#6879) They become full keywords in 3.7. files: A Misc/NEWS.d/next/IDLE/2018-05-15-17-01-10.bpo-29706.id4H5i.rst M Lib/idlelib/colorizer.py diff --git a/Lib/idlelib/colorizer.py b/Lib/idlelib/colorizer.py index 1f31ce22d7e5..f450ec2fd4ef 100644 --- a/Lib/idlelib/colorizer.py +++ b/Lib/idlelib/colorizer.py @@ -13,7 +13,7 @@ def any(name, alternates): return "(?P<%s>" % name + "|".join(alternates) + ")" def make_pat(): - kw = r"\b" + any("KEYWORD", keyword.kwlist) + r"\b" + kw = r"\b" + any("KEYWORD", keyword.kwlist + ['async', 'await']) + r"\b" builtinlist = [str(name) for name in dir(builtins) if not name.startswith('_') and \ name not in keyword.kwlist] diff --git a/Misc/NEWS.d/next/IDLE/2018-05-15-17-01-10.bpo-29706.id4H5i.rst b/Misc/NEWS.d/next/IDLE/2018-05-15-17-01-10.bpo-29706.id4H5i.rst new file mode 100644 index 000000000000..b25a878b1567 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2018-05-15-17-01-10.bpo-29706.id4H5i.rst @@ -0,0 +1,2 @@ +IDLE now colors async and await as keywords in 3.6. They become full +keywords in 3.7. From webhook-mailer at python.org Tue May 15 20:48:21 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 16 May 2018 00:48:21 -0000 Subject: [Python-checkins] bpo-30928: Update idlelib/NEWS.txt to 2018-05-14. (GH-6873) Message-ID: <mailman.65.1526431702.2757.python-checkins@python.org> https://github.com/python/cpython/commit/3d484435d261ef6e3204902f50778b545428dd7e commit: 3d484435d261ef6e3204902f50778b545428dd7e branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-15T17:48:17-07:00 summary: bpo-30928: Update idlelib/NEWS.txt to 2018-05-14. (GH-6873) (cherry picked from commit 038b21f2caaed0f02fee524277cc61e2c6ae0e9a) Co-authored-by: Terry Jan Reedy <tjreedy at udel.edu> files: M Lib/idlelib/NEWS.txt diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index c8b0caabd284..e255b0402d42 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -3,6 +3,27 @@ Released on 2018-06-18? ====================================== +bpo-21474: Update word/identifier definition from ascii to unicode. +In text and entry boxes, this affects selection by double-click, +movement left/right by control-left/right, and deletion left/right +by control-BACKSPACE/DEL. + +bpo-33204: Consistently color invalid string prefixes. +A 'u' string prefix cannot be paired with either 'r' or 'f'. +IDLE now consistently colors as much of the prefix, starting at the +right, as is valid. Revise and extend colorizer test. + +bpo-32984: Set __file__ while running a startup file. +Like Python, IDLE optionally runs 1 startup file in the Shell window +before presenting the first interactive input prompt. For IDLE, +option -s runs a file named in environmental variable IDLESTARTUP or +PYTHONSTARTUP; -r file runs file. Python sets __file__ to the startup +file name before running the file and unsets it before the first +prompt. IDLE now does the same when run normally, without the -n +option. + +bpo-32940: Replace StringTranslatePseudoMapping with faster code. + bpo-32916: Change 'str' to 'code' in idlelib.pyparse and users. bpo-32905: Remove unused code in pyparse module. From webhook-mailer at python.org Tue May 15 21:14:53 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 16 May 2018 01:14:53 -0000 Subject: [Python-checkins] bpo-30928: Update idlelib/NEWS.txt to 2018-05-14. (GH-6873) Message-ID: <mailman.66.1526433295.2757.python-checkins@python.org> https://github.com/python/cpython/commit/47793dec38b9485601a1b2fae90d5f19c3442434 commit: 47793dec38b9485601a1b2fae90d5f19c3442434 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-15T18:14:51-07:00 summary: bpo-30928: Update idlelib/NEWS.txt to 2018-05-14. (GH-6873) (cherry picked from commit 038b21f2caaed0f02fee524277cc61e2c6ae0e9a) Co-authored-by: Terry Jan Reedy <tjreedy at udel.edu> files: M Lib/idlelib/NEWS.txt diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index bf2b52ac2338..7ceaf755155f 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -3,6 +3,27 @@ Released on 2017-03-26? ====================================== +bpo-21474: Update word/identifier definition from ascii to unicode. +In text and entry boxes, this affects selection by double-click, +movement left/right by control-left/right, and deletion left/right +by control-BACKSPACE/DEL. + +bpo-33204: Consistently color invalid string prefixes. +A 'u' string prefix cannot be paired with either 'r' or 'f'. +IDLE now consistently colors as much of the prefix, starting at the +right, as is valid. Revise and extend colorizer test. + +bpo-32984: Set __file__ while running a startup file. +Like Python, IDLE optionally runs 1 startup file in the Shell window +before presenting the first interactive input prompt. For IDLE, +option -s runs a file named in environmental variable IDLESTARTUP or +PYTHONSTARTUP; -r file runs file. Python sets __file__ to the startup +file name before running the file and unsets it before the first +prompt. IDLE now does the same when run normally, without the -n +option. + +bpo-32940: Replace StringTranslatePseudoMapping with faster code. + bpo-32916: Change 'str' to 'code' in idlelib.pyparse and users. bpo-32905: Remove unused code in pyparse module. From webhook-mailer at python.org Tue May 15 22:44:30 2018 From: webhook-mailer at python.org (Eric V. Smith) Date: Wed, 16 May 2018 02:44:30 -0000 Subject: [Python-checkins] bpo-33453: Handle string type annotations in dataclasses. (GH-6768) Message-ID: <mailman.67.1526438671.2757.python-checkins@python.org> https://github.com/python/cpython/commit/2a7bacbd913cf2bf568b3c0f85a758946d3cf4e9 commit: 2a7bacbd913cf2bf568b3c0f85a758946d3cf4e9 branch: master author: Eric V. Smith <ericvsmith at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-15T22:44:27-04:00 summary: bpo-33453: Handle string type annotations in dataclasses. (GH-6768) files: A Lib/test/dataclass_module_1.py A Lib/test/dataclass_module_1_str.py A Lib/test/dataclass_module_2.py A Lib/test/dataclass_module_2_str.py A Misc/NEWS.d/next/Library/2018-05-12-06-01-02.bpo-33453.Fj-jMD.rst M Lib/dataclasses.py M Lib/test/test_dataclasses.py diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index 0f9041604a5a..c93aadc95e0a 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -1,3 +1,4 @@ +import re import sys import copy import types @@ -187,6 +188,10 @@ def __repr__(self): # __init__. _POST_INIT_NAME = '__post_init__' +# String regex that string annotations for ClassVar or InitVar must match. +# Allows "identifier.identifier[" or "identifier[". +# https://bugs.python.org/issue33453 for details. +_MODULE_IDENTIFIER_RE = re.compile(r'^(?:\s*(\w+)\s*\.)?\s*(\w+)') class _InitVarMeta(type): def __getitem__(self, params): @@ -532,6 +537,80 @@ def _hash_fn(fields): [f'return hash({self_tuple})']) +def _is_classvar(a_type, typing): + if typing: + # This test uses a typing internal class, but it's the best + # way to test if this is a ClassVar. + return (a_type is typing.ClassVar + or (type(a_type) is typing._GenericAlias + and a_type.__origin__ is typing.ClassVar)) + + +def _is_initvar(a_type, dataclasses): + # The module we're checking against is the module we're + # currently in (dataclasses.py). + return a_type is dataclasses.InitVar + + +def _is_type(annotation, cls, a_module, a_type, is_type_predicate): + # Given a type annotation string, does it refer to a_type in + # a_module? For example, when checking that annotation denotes a + # ClassVar, then a_module is typing, and a_type is + # typing.ClassVar. + + # It's possible to look up a_module given a_type, but it involves + # looking in sys.modules (again!), and seems like a waste since + # the caller already knows a_module. + + # - annotation is a string type annotation + # - cls is the class that this annotation was found in + # - a_module is the module we want to match + # - a_type is the type in that module we want to match + # - is_type_predicate is a function called with (obj, a_module) + # that determines if obj is of the desired type. + + # Since this test does not do a local namespace lookup (and + # instead only a module (global) lookup), there are some things it + # gets wrong. + + # With string annotations, this will work: + # CV = ClassVar + # @dataclass + # class C0: + # cv0: CV + + # But this will not: + # @dataclass + # class C1: + # CV = ClassVar + # cv1: CV + + # In C1, the code in this function will look up "CV" in the module + # and not find it, so it will not consider cv1 as a ClassVar. + # This is a fairly obscure corner case, and the best way to fix it + # would be to eval() the string "CV" with the correct global and + # local namespaces. However that would involve a eval() penalty + # for every single field of every dataclass that's defined. It + # was judged not worth it. + + match = _MODULE_IDENTIFIER_RE.match(annotation) + if match: + ns = None + module_name = match.group(1) + if not module_name: + # No module name, assume the class's module did + # "from dataclasses import InitVar". + ns = sys.modules.get(cls.__module__).__dict__ + else: + # Look up module_name in the class's module. + module = sys.modules.get(cls.__module__) + if module and module.__dict__.get(module_name) is a_module: + ns = sys.modules.get(a_type.__module__).__dict__ + if ns and is_type_predicate(ns.get(match.group(2)), a_module): + return True + return False + + def _get_field(cls, a_name, a_type): # Return a Field object for this field name and type. ClassVars # and InitVars are also returned, but marked as such (see @@ -548,34 +627,54 @@ def _get_field(cls, a_name, a_type): default = MISSING f = field(default=default) - # Assume it's a normal field until proven otherwise. - f._field_type = _FIELD - # Only at this point do we know the name and the type. Set them. f.name = a_name f.type = a_type - # If typing has not been imported, then it's impossible for - # any annotation to be a ClassVar. So, only look for ClassVar - # if typing has been imported. + # Assume it's a normal field until proven otherwise. We're next + # going to decide if it's a ClassVar or InitVar, everything else + # is just a normal field. + f._field_type = _FIELD + + # In addition to checking for actual types here, also check for + # string annotations. get_type_hints() won't always work for us + # (see https://github.com/python/typing/issues/508 for example), + # plus it's expensive and would require an eval for every stirng + # annotation. So, make a best effort to see if this is a + # ClassVar or InitVar using regex's and checking that the thing + # referenced is actually of the correct type. + + # For the complete discussion, see https://bugs.python.org/issue33453 + + # If typing has not been imported, then it's impossible for any + # annotation to be a ClassVar. So, only look for ClassVar if + # typing has been imported by any module (not necessarily cls's + # module). typing = sys.modules.get('typing') - if typing is not None: + if typing: # This test uses a typing internal class, but it's the best # way to test if this is a ClassVar. - if (type(a_type) is typing._GenericAlias and - a_type.__origin__ is typing.ClassVar): - # This field is a ClassVar, so it's not a field. + if (_is_classvar(a_type, typing) + or (isinstance(f.type, str) + and _is_type(f.type, cls, typing, typing.ClassVar, + _is_classvar))): f._field_type = _FIELD_CLASSVAR + # If the type is InitVar, or if it's a matching string annotation, + # then it's an InitVar. if f._field_type is _FIELD: - # Check if this is an InitVar. - if a_type is InitVar: - # InitVars are not fields, either. + # The module we're checking against is the module we're + # currently in (dataclasses.py). + dataclasses = sys.modules[__name__] + if (_is_initvar(a_type, dataclasses) + or (isinstance(f.type, str) + and _is_type(f.type, cls, dataclasses, dataclasses.InitVar, + _is_initvar))): f._field_type = _FIELD_INITVAR - # Validations for fields. This is delayed until now, instead of - # in the Field() constructor, since only here do we know the field - # name, which allows better error reporting. + # Validations for individual fields. This is delayed until now, + # instead of in the Field() constructor, since only here do we + # know the field name, which allows for better error reporting. # Special restrictions for ClassVar and InitVar. if f._field_type in (_FIELD_CLASSVAR, _FIELD_INITVAR): @@ -605,7 +704,6 @@ def _set_new_attribute(cls, name, value): return False - # Decide if/how we're going to create a hash function. Key is # (unsafe_hash, eq, frozen, does-hash-exist). Value is the action to # take. The common case is to do nothing, so instead of providing a @@ -865,7 +963,7 @@ def fields(class_or_instance): # Might it be worth caching this, per class? try: - fields = getattr(class_or_instance, _FIELDS) + fields = getattr(class_or_instance, _FIELDS) except AttributeError: raise TypeError('must be called with a dataclass type or instance') diff --git a/Lib/test/dataclass_module_1.py b/Lib/test/dataclass_module_1.py new file mode 100644 index 000000000000..87a33f8191d3 --- /dev/null +++ b/Lib/test/dataclass_module_1.py @@ -0,0 +1,32 @@ +#from __future__ import annotations +USING_STRINGS = False + +# dataclass_module_1.py and dataclass_module_1_str.py are identical +# except only the latter uses string annotations. + +import dataclasses +import typing + +T_CV2 = typing.ClassVar[int] +T_CV3 = typing.ClassVar + +T_IV2 = dataclasses.InitVar[int] +T_IV3 = dataclasses.InitVar + + at dataclasses.dataclass +class CV: + T_CV4 = typing.ClassVar + cv0: typing.ClassVar[int] = 20 + cv1: typing.ClassVar = 30 + cv2: T_CV2 + cv3: T_CV3 + not_cv4: T_CV4 # When using string annotations, this field is not recognized as a ClassVar. + + at dataclasses.dataclass +class IV: + T_IV4 = dataclasses.InitVar + iv0: dataclasses.InitVar[int] + iv1: dataclasses.InitVar + iv2: T_IV2 + iv3: T_IV3 + not_iv4: T_IV4 # When using string annotations, this field is not recognized as an InitVar. diff --git a/Lib/test/dataclass_module_1_str.py b/Lib/test/dataclass_module_1_str.py new file mode 100644 index 000000000000..6de490b7ad78 --- /dev/null +++ b/Lib/test/dataclass_module_1_str.py @@ -0,0 +1,32 @@ +from __future__ import annotations +USING_STRINGS = True + +# dataclass_module_1.py and dataclass_module_1_str.py are identical +# except only the latter uses string annotations. + +import dataclasses +import typing + +T_CV2 = typing.ClassVar[int] +T_CV3 = typing.ClassVar + +T_IV2 = dataclasses.InitVar[int] +T_IV3 = dataclasses.InitVar + + at dataclasses.dataclass +class CV: + T_CV4 = typing.ClassVar + cv0: typing.ClassVar[int] = 20 + cv1: typing.ClassVar = 30 + cv2: T_CV2 + cv3: T_CV3 + not_cv4: T_CV4 # When using string annotations, this field is not recognized as a ClassVar. + + at dataclasses.dataclass +class IV: + T_IV4 = dataclasses.InitVar + iv0: dataclasses.InitVar[int] + iv1: dataclasses.InitVar + iv2: T_IV2 + iv3: T_IV3 + not_iv4: T_IV4 # When using string annotations, this field is not recognized as an InitVar. diff --git a/Lib/test/dataclass_module_2.py b/Lib/test/dataclass_module_2.py new file mode 100644 index 000000000000..68fb733e2992 --- /dev/null +++ b/Lib/test/dataclass_module_2.py @@ -0,0 +1,32 @@ +#from __future__ import annotations +USING_STRINGS = False + +# dataclass_module_2.py and dataclass_module_2_str.py are identical +# except only the latter uses string annotations. + +from dataclasses import dataclass, InitVar +from typing import ClassVar + +T_CV2 = ClassVar[int] +T_CV3 = ClassVar + +T_IV2 = InitVar[int] +T_IV3 = InitVar + + at dataclass +class CV: + T_CV4 = ClassVar + cv0: ClassVar[int] = 20 + cv1: ClassVar = 30 + cv2: T_CV2 + cv3: T_CV3 + not_cv4: T_CV4 # When using string annotations, this field is not recognized as a ClassVar. + + at dataclass +class IV: + T_IV4 = InitVar + iv0: InitVar[int] + iv1: InitVar + iv2: T_IV2 + iv3: T_IV3 + not_iv4: T_IV4 # When using string annotations, this field is not recognized as an InitVar. diff --git a/Lib/test/dataclass_module_2_str.py b/Lib/test/dataclass_module_2_str.py new file mode 100644 index 000000000000..b363d17c176c --- /dev/null +++ b/Lib/test/dataclass_module_2_str.py @@ -0,0 +1,32 @@ +from __future__ import annotations +USING_STRINGS = True + +# dataclass_module_2.py and dataclass_module_2_str.py are identical +# except only the latter uses string annotations. + +from dataclasses import dataclass, InitVar +from typing import ClassVar + +T_CV2 = ClassVar[int] +T_CV3 = ClassVar + +T_IV2 = InitVar[int] +T_IV3 = InitVar + + at dataclass +class CV: + T_CV4 = ClassVar + cv0: ClassVar[int] = 20 + cv1: ClassVar = 30 + cv2: T_CV2 + cv3: T_CV3 + not_cv4: T_CV4 # When using string annotations, this field is not recognized as a ClassVar. + + at dataclass +class IV: + T_IV4 = InitVar + iv0: InitVar[int] + iv1: InitVar + iv2: T_IV2 + iv3: T_IV3 + not_iv4: T_IV4 # When using string annotations, this field is not recognized as an InitVar. diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index 2c890a2cbe92..b251c04cb9a1 100755 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -12,6 +12,9 @@ from collections import deque, OrderedDict, namedtuple from functools import total_ordering +import typing # Needed for the string "typing.ClassVar[int]" to work as an annotation. +import dataclasses # Needed for the string "dataclasses.InitVar[int]" to work as an annotation. + # Just any custom exception we can catch. class CustomError(Exception): pass @@ -600,7 +603,6 @@ class C: class C: x: ClassVar[typ] = Subclass() - def test_deliberately_mutable_defaults(self): # If a mutable default isn't in the known list of # (list, dict, set), then it's okay. @@ -924,14 +926,16 @@ class C: z: ClassVar[int] = 1000 w: ClassVar[int] = 2000 t: ClassVar[int] = 3000 + s: ClassVar = 4000 c = C(5) self.assertEqual(repr(c), 'TestCase.test_class_var.<locals>.C(x=5, y=10)') self.assertEqual(len(fields(C)), 2) # We have 2 fields. - self.assertEqual(len(C.__annotations__), 5) # And 3 ClassVars. + self.assertEqual(len(C.__annotations__), 6) # And 4 ClassVars. self.assertEqual(c.z, 1000) self.assertEqual(c.w, 2000) self.assertEqual(c.t, 3000) + self.assertEqual(c.s, 4000) C.z += 1 self.assertEqual(c.z, 1001) c = C(20) @@ -939,6 +943,7 @@ class C: self.assertEqual(c.z, 1001) self.assertEqual(c.w, 2000) self.assertEqual(c.t, 3000) + self.assertEqual(c.s, 4000) def test_class_var_no_default(self): # If a ClassVar has no default value, it should not be set on the class. @@ -2798,5 +2803,149 @@ class C: self.assertEqual(D.__set_name__.call_count, 1) +class TestStringAnnotations(unittest.TestCase): + def test_classvar(self): + # Some expressions recognized as ClassVar really aren't. But + # if you're using string annotations, it's not an exact + # science. + # These tests assume that both "import typing" and "from + # typing import *" have been run in this file. + for typestr in ('ClassVar[int]', + 'ClassVar [int]' + ' ClassVar [int]', + 'ClassVar', + ' ClassVar ', + 'typing.ClassVar[int]', + 'typing.ClassVar[str]', + ' typing.ClassVar[str]', + 'typing .ClassVar[str]', + 'typing. ClassVar[str]', + 'typing.ClassVar [str]', + 'typing.ClassVar [ str]', + + # Not syntactically valid, but these will + # be treated as ClassVars. + 'typing.ClassVar.[int]', + 'typing.ClassVar+', + ): + with self.subTest(typestr=typestr): + @dataclass + class C: + x: typestr + + # x is a ClassVar, so C() takes no args. + C() + + # And it won't appear in the class's dict because it doesn't + # have a default. + self.assertNotIn('x', C.__dict__) + + def test_isnt_classvar(self): + for typestr in ('CV', + 't.ClassVar', + 't.ClassVar[int]', + 'typing..ClassVar[int]', + 'Classvar', + 'Classvar[int]', + 'typing.ClassVarx[int]', + 'typong.ClassVar[int]', + 'dataclasses.ClassVar[int]', + 'typingxClassVar[str]', + ): + with self.subTest(typestr=typestr): + @dataclass + class C: + x: typestr + + # x is not a ClassVar, so C() takes one arg. + self.assertEqual(C(10).x, 10) + + def test_initvar(self): + # These tests assume that both "import dataclasses" and "from + # dataclasses import *" have been run in this file. + for typestr in ('InitVar[int]', + 'InitVar [int]' + ' InitVar [int]', + 'InitVar', + ' InitVar ', + 'dataclasses.InitVar[int]', + 'dataclasses.InitVar[str]', + ' dataclasses.InitVar[str]', + 'dataclasses .InitVar[str]', + 'dataclasses. InitVar[str]', + 'dataclasses.InitVar [str]', + 'dataclasses.InitVar [ str]', + + # Not syntactically valid, but these will + # be treated as InitVars. + 'dataclasses.InitVar.[int]', + 'dataclasses.InitVar+', + ): + with self.subTest(typestr=typestr): + @dataclass + class C: + x: typestr + + # x is an InitVar, so doesn't create a member. + with self.assertRaisesRegex(AttributeError, + "object has no attribute 'x'"): + C(1).x + + def test_isnt_initvar(self): + for typestr in ('IV', + 'dc.InitVar', + 'xdataclasses.xInitVar', + 'typing.xInitVar[int]', + ): + with self.subTest(typestr=typestr): + @dataclass + class C: + x: typestr + + # x is not an InitVar, so there will be a member x. + self.assertEqual(C(10).x, 10) + + def test_classvar_module_level_import(self): + from . import dataclass_module_1 + from . import dataclass_module_1_str + from . import dataclass_module_2 + from . import dataclass_module_2_str + + for m in (dataclass_module_1, dataclass_module_1_str, + dataclass_module_2, dataclass_module_2_str, + ): + with self.subTest(m=m): + # There's a difference in how the ClassVars are + # interpreted when using string annotations or + # not. See the imported modules for details. + if m.USING_STRINGS: + c = m.CV(10) + else: + c = m.CV() + self.assertEqual(c.cv0, 20) + + + # There's a difference in how the InitVars are + # interpreted when using string annotations or + # not. See the imported modules for details. + c = m.IV(0, 1, 2, 3, 4) + + for field_name in ('iv0', 'iv1', 'iv2', 'iv3'): + with self.subTest(field_name=field_name): + with self.assertRaisesRegex(AttributeError, f"object has no attribute '{field_name}'"): + # Since field_name is an InitVar, it's + # not an instance field. + getattr(c, field_name) + + if m.USING_STRINGS: + # iv4 is interpreted as a normal field. + self.assertIn('not_iv4', c.__dict__) + self.assertEqual(c.not_iv4, 4) + else: + # iv4 is interpreted as an InitVar, so it + # won't exist on the instance. + self.assertNotIn('not_iv4', c.__dict__) + + if __name__ == '__main__': unittest.main() diff --git a/Misc/NEWS.d/next/Library/2018-05-12-06-01-02.bpo-33453.Fj-jMD.rst b/Misc/NEWS.d/next/Library/2018-05-12-06-01-02.bpo-33453.Fj-jMD.rst new file mode 100644 index 000000000000..6595b1265a4e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-12-06-01-02.bpo-33453.Fj-jMD.rst @@ -0,0 +1,4 @@ +Fix dataclasses to work if using literal string type annotations or if using +PEP 563 "Postponed Evaluation of Annotations". Only specific string +prefixes are detected for both ClassVar ("ClassVar" and "typing.ClassVar") +and InitVar ("InitVar" and "dataclasses.InitVar"). From lp_benchmark_robot at intel.com Tue May 15 23:03:53 2018 From: lp_benchmark_robot at intel.com (lp_benchmark_robot at intel.com) Date: Tue, 15 May 2018 20:03:53 -0700 Subject: [Python-checkins] [65 flat] Results for Python (master branch) 2018-05-15 Message-ID: <98a83c82-3545-4e39-b179-2535ec31c9ce@orsmsx108.amr.corp.intel.com> Results for project python/master, build date: 2018-05-15 03:03:14-07:00. - commit: 5401622 - previous commit: 5cd22cf - revision date: 2018-05-14 21:39:22-07:00 - environment: Broadwell-EP - cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores, stepping 1, LLC 55 MB - mem: 128 GB - os: Ubuntu 16.04.2 LTS - kernel: 4.4.0-62-generic x86_64 GNU/Linux Baseline results were generated using release v3.6.0, with hash 5c4568a from 2016-12-22 23:38:47+00:00. +-----+------------------------+--------+------------+------------+------------+ | | |relative|change since|change since|current rev | | | benchmark|std_dev*| last run | baseline |run with PGO| +-----+------------------------+--------+------------+------------+------------+ | :-| | 2to3| 0.601% | -0.258% | +8.900% | +6.899% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method| 1.902% | -0.585% | +23.764% | +14.522% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_slots| 1.289% | +0.004% | +25.797% | +13.059% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_unknown| 0.866% | +0.046% | +22.689% | +12.113% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_simple| 3.251% | -0.563% | +10.709% | +13.326% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chameleon| 2.302% | -0.280% | +12.023% | +10.920% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chaos| 1.397% | +0.017% | +9.145% | +8.654% | +-----+------------------------+--------+------------+------------+------------+ | :-| | crypto_pyaes| 0.587% | -0.049% | +0.268% | +8.142% | +-----+------------------------+--------+------------+------------+------------+ | :-| | deltablue| 3.606% | +0.277% | +11.559% | +16.508% | +-----+------------------------+--------+------------+------------+------------+ | :-| | django_template| 3.846% | -0.363% | +20.561% | +13.010% | +-----+------------------------+--------+------------+------------+------------+ | :-| | dulwich_log| 1.165% | -0.071% | +5.582% | +6.648% | +-----+------------------------+--------+------------+------------+------------+ | :-| | fannkuch| 0.774% | -0.028% | +6.936% | +4.542% | +-----+------------------------+--------+------------+------------+------------+ | :-| | float| 1.079% | -0.481% | +2.426% | +7.066% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_text| 1.075% | +0.060% | +15.000% | +8.883% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_xml| 2.189% | +0.154% | +11.448% | +8.874% | +-----+------------------------+--------+------------+------------+------------+ | :-| | go| 6.419% | -0.296% | +4.846% | +12.790% | +-----+------------------------+--------+------------+------------+------------+ | :-| | hexiom| 0.557% | -0.064% | +12.022% | +10.498% | +-----+------------------------+--------+------------+------------+------------+ | :-| | html5lib| 2.998% | -0.634% | +11.458% | +10.276% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_dumps| 2.633% | +0.249% | +2.392% | +9.921% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_loads| 4.030% | +0.251% | -4.140% | +14.925% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_format| 1.338% | -0.689% | +17.244% | +14.013% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_silent| 2.172% | +1.373% | +48.307% | +12.691% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_simple| 1.672% | -0.405% | +12.509% | +13.778% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mako| 0.469% | +0.249% | +17.305% | +14.233% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mdp| 7.154% | +0.064% | +0.826% | +17.962% | +-----+------------------------+--------+------------+------------+------------+ | :-| | meteor_contest| 0.798% | -0.268% | +4.001% | +6.965% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nbody| 0.552% | +0.221% | +0.359% | -1.254% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nqueens| 0.650% | -0.013% | +6.145% | +8.012% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pathlib| 1.527% | -1.248% | -1.435% | +10.735% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle| 1.256% | +0.378% | -0.932% | +23.478% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_dict| 0.182% | +0.028% | +7.529% | +17.506% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_list| 0.941% | -0.423% | +6.748% | +19.217% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_pure_python| 5.980% | -0.259% | +11.170% | +10.874% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pidigits| 0.106% | +0.056% | +0.136% | +10.073% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup| 0.121% | -0.094% | +18.695% | +5.117% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup_no_site| 0.087% | -0.081% | +5.687% | +5.370% | +-----+------------------------+--------+------------+------------+------------+ | :-| | raytrace| 1.120% | +0.216% | +10.221% | +12.102% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_compile| 4.006% | -0.046% | +7.079% | +8.983% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_dna| 0.491% | -0.050% | -2.125% | +13.590% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_effbot| 1.779% | +0.305% | -2.664% | +5.037% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_v8| 1.433% | -0.449% | +4.370% | +7.318% | +-----+------------------------+--------+------------+------------+------------+ | :-| | richards| 1.275% | -0.096% | +9.576% | +14.999% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_fft| 2.156% | -0.458% | -2.088% | +5.278% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_lu| 5.473% | -1.038% | +21.791% | +13.216% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_monte_carlo| 1.985% | -0.722% | +4.781% | +2.285% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sor| 1.191% | -0.185% | +14.997% | +8.258% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sparse_mat_mult| 2.695% | -0.614% | -2.839% | +1.222% | +-----+------------------------+--------+------------+------------+------------+ | :-| | spectral_norm| 0.403% | +0.205% | +6.210% | +4.234% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_declarative| 1.251% | -0.048% | +6.415% | +6.954% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_imperative| 3.772% | +0.302% | +7.744% | +4.580% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlite_synth| 3.351% | +0.051% | -0.914% | +10.995% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_expand| 2.901% | +0.483% | +17.885% | +6.180% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_integrate| 1.507% | -0.169% | +18.436% | +5.733% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_str| 4.715% | -0.497% | +18.971% | +6.907% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_sum| 5.998% | +1.137% | +15.596% | +9.862% | +-----+------------------------+--------+------------+------------+------------+ | :-| | telco| 4.415% | +0.042% | +19.489% | +10.154% | +-----+------------------------+--------+------------+------------+------------+ | :-| | tornado_http| 1.108% | -0.174% | +7.290% | +6.695% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpack_sequence| 0.754% | -0.050% | +2.938% | +2.247% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle| 7.648% | -1.797% | +8.177% | +20.116% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_list| 1.741% | -0.479% | -3.718% | +16.399% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_pure_python| 2.441% | -0.602% | +7.114% | +7.341% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_generate| 1.378% | -0.055% | +2.547% | +12.825% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_iterparse| 2.480% | +0.406% | +4.697% | +6.978% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_parse| 4.082% | -0.740% | -6.733% | +10.923% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_process| 1.194% | +0.225% | +5.057% | +11.368% | +-----+------------------------+--------+------------+------------+------------+ * Relative Standard Deviation (Standard Deviation/Average) If this is not displayed properly please visit our results page here: http://languagesperformance.intel.com/65-flat-results-for-python-master-branch-2018-05-15 Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. From webhook-mailer at python.org Wed May 16 00:22:16 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 16 May 2018 04:22:16 -0000 Subject: [Python-checkins] bpo-33453: Handle string type annotations in dataclasses. (GH-6768) Message-ID: <mailman.68.1526444539.2757.python-checkins@python.org> https://github.com/python/cpython/commit/c73268aad7645a146b3e0e088c198a1fb74d57ff commit: c73268aad7645a146b3e0e088c198a1fb74d57ff branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-15T21:22:13-07:00 summary: bpo-33453: Handle string type annotations in dataclasses. (GH-6768) (cherry picked from commit 2a7bacbd913cf2bf568b3c0f85a758946d3cf4e9) Co-authored-by: Eric V. Smith <ericvsmith at users.noreply.github.com> files: A Lib/test/dataclass_module_1.py A Lib/test/dataclass_module_1_str.py A Lib/test/dataclass_module_2.py A Lib/test/dataclass_module_2_str.py A Misc/NEWS.d/next/Library/2018-05-12-06-01-02.bpo-33453.Fj-jMD.rst M Lib/dataclasses.py M Lib/test/test_dataclasses.py diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index 0f9041604a5a..c93aadc95e0a 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -1,3 +1,4 @@ +import re import sys import copy import types @@ -187,6 +188,10 @@ def __repr__(self): # __init__. _POST_INIT_NAME = '__post_init__' +# String regex that string annotations for ClassVar or InitVar must match. +# Allows "identifier.identifier[" or "identifier[". +# https://bugs.python.org/issue33453 for details. +_MODULE_IDENTIFIER_RE = re.compile(r'^(?:\s*(\w+)\s*\.)?\s*(\w+)') class _InitVarMeta(type): def __getitem__(self, params): @@ -532,6 +537,80 @@ def _hash_fn(fields): [f'return hash({self_tuple})']) +def _is_classvar(a_type, typing): + if typing: + # This test uses a typing internal class, but it's the best + # way to test if this is a ClassVar. + return (a_type is typing.ClassVar + or (type(a_type) is typing._GenericAlias + and a_type.__origin__ is typing.ClassVar)) + + +def _is_initvar(a_type, dataclasses): + # The module we're checking against is the module we're + # currently in (dataclasses.py). + return a_type is dataclasses.InitVar + + +def _is_type(annotation, cls, a_module, a_type, is_type_predicate): + # Given a type annotation string, does it refer to a_type in + # a_module? For example, when checking that annotation denotes a + # ClassVar, then a_module is typing, and a_type is + # typing.ClassVar. + + # It's possible to look up a_module given a_type, but it involves + # looking in sys.modules (again!), and seems like a waste since + # the caller already knows a_module. + + # - annotation is a string type annotation + # - cls is the class that this annotation was found in + # - a_module is the module we want to match + # - a_type is the type in that module we want to match + # - is_type_predicate is a function called with (obj, a_module) + # that determines if obj is of the desired type. + + # Since this test does not do a local namespace lookup (and + # instead only a module (global) lookup), there are some things it + # gets wrong. + + # With string annotations, this will work: + # CV = ClassVar + # @dataclass + # class C0: + # cv0: CV + + # But this will not: + # @dataclass + # class C1: + # CV = ClassVar + # cv1: CV + + # In C1, the code in this function will look up "CV" in the module + # and not find it, so it will not consider cv1 as a ClassVar. + # This is a fairly obscure corner case, and the best way to fix it + # would be to eval() the string "CV" with the correct global and + # local namespaces. However that would involve a eval() penalty + # for every single field of every dataclass that's defined. It + # was judged not worth it. + + match = _MODULE_IDENTIFIER_RE.match(annotation) + if match: + ns = None + module_name = match.group(1) + if not module_name: + # No module name, assume the class's module did + # "from dataclasses import InitVar". + ns = sys.modules.get(cls.__module__).__dict__ + else: + # Look up module_name in the class's module. + module = sys.modules.get(cls.__module__) + if module and module.__dict__.get(module_name) is a_module: + ns = sys.modules.get(a_type.__module__).__dict__ + if ns and is_type_predicate(ns.get(match.group(2)), a_module): + return True + return False + + def _get_field(cls, a_name, a_type): # Return a Field object for this field name and type. ClassVars # and InitVars are also returned, but marked as such (see @@ -548,34 +627,54 @@ def _get_field(cls, a_name, a_type): default = MISSING f = field(default=default) - # Assume it's a normal field until proven otherwise. - f._field_type = _FIELD - # Only at this point do we know the name and the type. Set them. f.name = a_name f.type = a_type - # If typing has not been imported, then it's impossible for - # any annotation to be a ClassVar. So, only look for ClassVar - # if typing has been imported. + # Assume it's a normal field until proven otherwise. We're next + # going to decide if it's a ClassVar or InitVar, everything else + # is just a normal field. + f._field_type = _FIELD + + # In addition to checking for actual types here, also check for + # string annotations. get_type_hints() won't always work for us + # (see https://github.com/python/typing/issues/508 for example), + # plus it's expensive and would require an eval for every stirng + # annotation. So, make a best effort to see if this is a + # ClassVar or InitVar using regex's and checking that the thing + # referenced is actually of the correct type. + + # For the complete discussion, see https://bugs.python.org/issue33453 + + # If typing has not been imported, then it's impossible for any + # annotation to be a ClassVar. So, only look for ClassVar if + # typing has been imported by any module (not necessarily cls's + # module). typing = sys.modules.get('typing') - if typing is not None: + if typing: # This test uses a typing internal class, but it's the best # way to test if this is a ClassVar. - if (type(a_type) is typing._GenericAlias and - a_type.__origin__ is typing.ClassVar): - # This field is a ClassVar, so it's not a field. + if (_is_classvar(a_type, typing) + or (isinstance(f.type, str) + and _is_type(f.type, cls, typing, typing.ClassVar, + _is_classvar))): f._field_type = _FIELD_CLASSVAR + # If the type is InitVar, or if it's a matching string annotation, + # then it's an InitVar. if f._field_type is _FIELD: - # Check if this is an InitVar. - if a_type is InitVar: - # InitVars are not fields, either. + # The module we're checking against is the module we're + # currently in (dataclasses.py). + dataclasses = sys.modules[__name__] + if (_is_initvar(a_type, dataclasses) + or (isinstance(f.type, str) + and _is_type(f.type, cls, dataclasses, dataclasses.InitVar, + _is_initvar))): f._field_type = _FIELD_INITVAR - # Validations for fields. This is delayed until now, instead of - # in the Field() constructor, since only here do we know the field - # name, which allows better error reporting. + # Validations for individual fields. This is delayed until now, + # instead of in the Field() constructor, since only here do we + # know the field name, which allows for better error reporting. # Special restrictions for ClassVar and InitVar. if f._field_type in (_FIELD_CLASSVAR, _FIELD_INITVAR): @@ -605,7 +704,6 @@ def _set_new_attribute(cls, name, value): return False - # Decide if/how we're going to create a hash function. Key is # (unsafe_hash, eq, frozen, does-hash-exist). Value is the action to # take. The common case is to do nothing, so instead of providing a @@ -865,7 +963,7 @@ def fields(class_or_instance): # Might it be worth caching this, per class? try: - fields = getattr(class_or_instance, _FIELDS) + fields = getattr(class_or_instance, _FIELDS) except AttributeError: raise TypeError('must be called with a dataclass type or instance') diff --git a/Lib/test/dataclass_module_1.py b/Lib/test/dataclass_module_1.py new file mode 100644 index 000000000000..87a33f8191d3 --- /dev/null +++ b/Lib/test/dataclass_module_1.py @@ -0,0 +1,32 @@ +#from __future__ import annotations +USING_STRINGS = False + +# dataclass_module_1.py and dataclass_module_1_str.py are identical +# except only the latter uses string annotations. + +import dataclasses +import typing + +T_CV2 = typing.ClassVar[int] +T_CV3 = typing.ClassVar + +T_IV2 = dataclasses.InitVar[int] +T_IV3 = dataclasses.InitVar + + at dataclasses.dataclass +class CV: + T_CV4 = typing.ClassVar + cv0: typing.ClassVar[int] = 20 + cv1: typing.ClassVar = 30 + cv2: T_CV2 + cv3: T_CV3 + not_cv4: T_CV4 # When using string annotations, this field is not recognized as a ClassVar. + + at dataclasses.dataclass +class IV: + T_IV4 = dataclasses.InitVar + iv0: dataclasses.InitVar[int] + iv1: dataclasses.InitVar + iv2: T_IV2 + iv3: T_IV3 + not_iv4: T_IV4 # When using string annotations, this field is not recognized as an InitVar. diff --git a/Lib/test/dataclass_module_1_str.py b/Lib/test/dataclass_module_1_str.py new file mode 100644 index 000000000000..6de490b7ad78 --- /dev/null +++ b/Lib/test/dataclass_module_1_str.py @@ -0,0 +1,32 @@ +from __future__ import annotations +USING_STRINGS = True + +# dataclass_module_1.py and dataclass_module_1_str.py are identical +# except only the latter uses string annotations. + +import dataclasses +import typing + +T_CV2 = typing.ClassVar[int] +T_CV3 = typing.ClassVar + +T_IV2 = dataclasses.InitVar[int] +T_IV3 = dataclasses.InitVar + + at dataclasses.dataclass +class CV: + T_CV4 = typing.ClassVar + cv0: typing.ClassVar[int] = 20 + cv1: typing.ClassVar = 30 + cv2: T_CV2 + cv3: T_CV3 + not_cv4: T_CV4 # When using string annotations, this field is not recognized as a ClassVar. + + at dataclasses.dataclass +class IV: + T_IV4 = dataclasses.InitVar + iv0: dataclasses.InitVar[int] + iv1: dataclasses.InitVar + iv2: T_IV2 + iv3: T_IV3 + not_iv4: T_IV4 # When using string annotations, this field is not recognized as an InitVar. diff --git a/Lib/test/dataclass_module_2.py b/Lib/test/dataclass_module_2.py new file mode 100644 index 000000000000..68fb733e2992 --- /dev/null +++ b/Lib/test/dataclass_module_2.py @@ -0,0 +1,32 @@ +#from __future__ import annotations +USING_STRINGS = False + +# dataclass_module_2.py and dataclass_module_2_str.py are identical +# except only the latter uses string annotations. + +from dataclasses import dataclass, InitVar +from typing import ClassVar + +T_CV2 = ClassVar[int] +T_CV3 = ClassVar + +T_IV2 = InitVar[int] +T_IV3 = InitVar + + at dataclass +class CV: + T_CV4 = ClassVar + cv0: ClassVar[int] = 20 + cv1: ClassVar = 30 + cv2: T_CV2 + cv3: T_CV3 + not_cv4: T_CV4 # When using string annotations, this field is not recognized as a ClassVar. + + at dataclass +class IV: + T_IV4 = InitVar + iv0: InitVar[int] + iv1: InitVar + iv2: T_IV2 + iv3: T_IV3 + not_iv4: T_IV4 # When using string annotations, this field is not recognized as an InitVar. diff --git a/Lib/test/dataclass_module_2_str.py b/Lib/test/dataclass_module_2_str.py new file mode 100644 index 000000000000..b363d17c176c --- /dev/null +++ b/Lib/test/dataclass_module_2_str.py @@ -0,0 +1,32 @@ +from __future__ import annotations +USING_STRINGS = True + +# dataclass_module_2.py and dataclass_module_2_str.py are identical +# except only the latter uses string annotations. + +from dataclasses import dataclass, InitVar +from typing import ClassVar + +T_CV2 = ClassVar[int] +T_CV3 = ClassVar + +T_IV2 = InitVar[int] +T_IV3 = InitVar + + at dataclass +class CV: + T_CV4 = ClassVar + cv0: ClassVar[int] = 20 + cv1: ClassVar = 30 + cv2: T_CV2 + cv3: T_CV3 + not_cv4: T_CV4 # When using string annotations, this field is not recognized as a ClassVar. + + at dataclass +class IV: + T_IV4 = InitVar + iv0: InitVar[int] + iv1: InitVar + iv2: T_IV2 + iv3: T_IV3 + not_iv4: T_IV4 # When using string annotations, this field is not recognized as an InitVar. diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index 2c890a2cbe92..b251c04cb9a1 100755 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -12,6 +12,9 @@ from collections import deque, OrderedDict, namedtuple from functools import total_ordering +import typing # Needed for the string "typing.ClassVar[int]" to work as an annotation. +import dataclasses # Needed for the string "dataclasses.InitVar[int]" to work as an annotation. + # Just any custom exception we can catch. class CustomError(Exception): pass @@ -600,7 +603,6 @@ class C: class C: x: ClassVar[typ] = Subclass() - def test_deliberately_mutable_defaults(self): # If a mutable default isn't in the known list of # (list, dict, set), then it's okay. @@ -924,14 +926,16 @@ class C: z: ClassVar[int] = 1000 w: ClassVar[int] = 2000 t: ClassVar[int] = 3000 + s: ClassVar = 4000 c = C(5) self.assertEqual(repr(c), 'TestCase.test_class_var.<locals>.C(x=5, y=10)') self.assertEqual(len(fields(C)), 2) # We have 2 fields. - self.assertEqual(len(C.__annotations__), 5) # And 3 ClassVars. + self.assertEqual(len(C.__annotations__), 6) # And 4 ClassVars. self.assertEqual(c.z, 1000) self.assertEqual(c.w, 2000) self.assertEqual(c.t, 3000) + self.assertEqual(c.s, 4000) C.z += 1 self.assertEqual(c.z, 1001) c = C(20) @@ -939,6 +943,7 @@ class C: self.assertEqual(c.z, 1001) self.assertEqual(c.w, 2000) self.assertEqual(c.t, 3000) + self.assertEqual(c.s, 4000) def test_class_var_no_default(self): # If a ClassVar has no default value, it should not be set on the class. @@ -2798,5 +2803,149 @@ class C: self.assertEqual(D.__set_name__.call_count, 1) +class TestStringAnnotations(unittest.TestCase): + def test_classvar(self): + # Some expressions recognized as ClassVar really aren't. But + # if you're using string annotations, it's not an exact + # science. + # These tests assume that both "import typing" and "from + # typing import *" have been run in this file. + for typestr in ('ClassVar[int]', + 'ClassVar [int]' + ' ClassVar [int]', + 'ClassVar', + ' ClassVar ', + 'typing.ClassVar[int]', + 'typing.ClassVar[str]', + ' typing.ClassVar[str]', + 'typing .ClassVar[str]', + 'typing. ClassVar[str]', + 'typing.ClassVar [str]', + 'typing.ClassVar [ str]', + + # Not syntactically valid, but these will + # be treated as ClassVars. + 'typing.ClassVar.[int]', + 'typing.ClassVar+', + ): + with self.subTest(typestr=typestr): + @dataclass + class C: + x: typestr + + # x is a ClassVar, so C() takes no args. + C() + + # And it won't appear in the class's dict because it doesn't + # have a default. + self.assertNotIn('x', C.__dict__) + + def test_isnt_classvar(self): + for typestr in ('CV', + 't.ClassVar', + 't.ClassVar[int]', + 'typing..ClassVar[int]', + 'Classvar', + 'Classvar[int]', + 'typing.ClassVarx[int]', + 'typong.ClassVar[int]', + 'dataclasses.ClassVar[int]', + 'typingxClassVar[str]', + ): + with self.subTest(typestr=typestr): + @dataclass + class C: + x: typestr + + # x is not a ClassVar, so C() takes one arg. + self.assertEqual(C(10).x, 10) + + def test_initvar(self): + # These tests assume that both "import dataclasses" and "from + # dataclasses import *" have been run in this file. + for typestr in ('InitVar[int]', + 'InitVar [int]' + ' InitVar [int]', + 'InitVar', + ' InitVar ', + 'dataclasses.InitVar[int]', + 'dataclasses.InitVar[str]', + ' dataclasses.InitVar[str]', + 'dataclasses .InitVar[str]', + 'dataclasses. InitVar[str]', + 'dataclasses.InitVar [str]', + 'dataclasses.InitVar [ str]', + + # Not syntactically valid, but these will + # be treated as InitVars. + 'dataclasses.InitVar.[int]', + 'dataclasses.InitVar+', + ): + with self.subTest(typestr=typestr): + @dataclass + class C: + x: typestr + + # x is an InitVar, so doesn't create a member. + with self.assertRaisesRegex(AttributeError, + "object has no attribute 'x'"): + C(1).x + + def test_isnt_initvar(self): + for typestr in ('IV', + 'dc.InitVar', + 'xdataclasses.xInitVar', + 'typing.xInitVar[int]', + ): + with self.subTest(typestr=typestr): + @dataclass + class C: + x: typestr + + # x is not an InitVar, so there will be a member x. + self.assertEqual(C(10).x, 10) + + def test_classvar_module_level_import(self): + from . import dataclass_module_1 + from . import dataclass_module_1_str + from . import dataclass_module_2 + from . import dataclass_module_2_str + + for m in (dataclass_module_1, dataclass_module_1_str, + dataclass_module_2, dataclass_module_2_str, + ): + with self.subTest(m=m): + # There's a difference in how the ClassVars are + # interpreted when using string annotations or + # not. See the imported modules for details. + if m.USING_STRINGS: + c = m.CV(10) + else: + c = m.CV() + self.assertEqual(c.cv0, 20) + + + # There's a difference in how the InitVars are + # interpreted when using string annotations or + # not. See the imported modules for details. + c = m.IV(0, 1, 2, 3, 4) + + for field_name in ('iv0', 'iv1', 'iv2', 'iv3'): + with self.subTest(field_name=field_name): + with self.assertRaisesRegex(AttributeError, f"object has no attribute '{field_name}'"): + # Since field_name is an InitVar, it's + # not an instance field. + getattr(c, field_name) + + if m.USING_STRINGS: + # iv4 is interpreted as a normal field. + self.assertIn('not_iv4', c.__dict__) + self.assertEqual(c.not_iv4, 4) + else: + # iv4 is interpreted as an InitVar, so it + # won't exist on the instance. + self.assertNotIn('not_iv4', c.__dict__) + + if __name__ == '__main__': unittest.main() diff --git a/Misc/NEWS.d/next/Library/2018-05-12-06-01-02.bpo-33453.Fj-jMD.rst b/Misc/NEWS.d/next/Library/2018-05-12-06-01-02.bpo-33453.Fj-jMD.rst new file mode 100644 index 000000000000..6595b1265a4e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-12-06-01-02.bpo-33453.Fj-jMD.rst @@ -0,0 +1,4 @@ +Fix dataclasses to work if using literal string type annotations or if using +PEP 563 "Postponed Evaluation of Annotations". Only specific string +prefixes are detected for both ClassVar ("ClassVar" and "typing.ClassVar") +and InitVar ("InitVar" and "dataclasses.InitVar"). From webhook-mailer at python.org Wed May 16 01:58:20 2018 From: webhook-mailer at python.org (Benjamin Peterson) Date: Wed, 16 May 2018 05:58:20 -0000 Subject: [Python-checkins] closes bpo-33512: use standard for detecting long double (GH-6847) Message-ID: <mailman.69.1526450302.2757.python-checkins@python.org> https://github.com/python/cpython/commit/3055c947f98a078bd10d6a8cc352048a1b771d60 commit: 3055c947f98a078bd10d6a8cc352048a1b771d60 branch: master author: Eitan Adler <grimreaper at users.noreply.github.com> committer: Benjamin Peterson <benjamin at python.org> date: 2018-05-15T22:58:09-07:00 summary: closes bpo-33512: use standard for detecting long double (GH-6847) files: A Misc/NEWS.d/next/Build/2018-05-15-02-07-49.bpo-33512.X4Fy1Q.rst M configure M configure.ac M pyconfig.h.in diff --git a/Misc/NEWS.d/next/Build/2018-05-15-02-07-49.bpo-33512.X4Fy1Q.rst b/Misc/NEWS.d/next/Build/2018-05-15-02-07-49.bpo-33512.X4Fy1Q.rst new file mode 100644 index 000000000000..6b74551f1ba4 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2018-05-15-02-07-49.bpo-33512.X4Fy1Q.rst @@ -0,0 +1 @@ +configure's check for "long double" has been simplified diff --git a/configure b/configure index b098bac6472a..669060bea128 100755 --- a/configure +++ b/configure @@ -779,7 +779,6 @@ infodir docdir oldincludedir includedir -runstatedir localstatedir sharedstatedir sysconfdir @@ -887,7 +886,6 @@ datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' -runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' @@ -1140,15 +1138,6 @@ do | -silent | --silent | --silen | --sile | --sil) silent=yes ;; - -runstatedir | --runstatedir | --runstatedi | --runstated \ - | --runstate | --runstat | --runsta | --runst | --runs \ - | --run | --ru | --r) - ac_prev=runstatedir ;; - -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ - | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ - | --run=* | --ru=* | --r=*) - runstatedir=$ac_optarg ;; - -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ @@ -1286,7 +1275,7 @@ fi for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir runstatedir + libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. @@ -1439,7 +1428,6 @@ Fine tuning of the installation directories: --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] - --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] @@ -8603,32 +8591,48 @@ _ACEOF -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for long double support" >&5 -$as_echo_n "checking for long double support... " >&6; } -have_long_double=no -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for long double" >&5 +$as_echo_n "checking for long double... " >&6; } +if ${ac_cv_type_long_double+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$GCC" = yes; then + ac_cv_type_long_double=yes + else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* The Stardent Vistra knows sizeof (long double), but does + not support it. */ + long double foo = 0.0L; int main () { -long double x; x = (long double)0; +static int test_array [1 - 2 * !(/* On Ultrix 4.3 cc, long double is 4 and double is 8. */ + sizeof (double) <= sizeof (long double))]; +test_array [0] = 0; +return test_array [0]; + ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - + ac_cv_type_long_double=yes +else + ac_cv_type_long_double=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_long_double" >&5 +$as_echo "$ac_cv_type_long_double" >&6; } + if test $ac_cv_type_long_double = yes; then $as_echo "#define HAVE_LONG_DOUBLE 1" >>confdefs.h - have_long_double=yes + fi -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_long_double" >&5 -$as_echo "$have_long_double" >&6; } -if test "$have_long_double" = yes ; then # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. @@ -8662,7 +8666,6 @@ cat >>confdefs.h <<_ACEOF _ACEOF -fi # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects diff --git a/configure.ac b/configure.ac index 883c90505219..679fac318e17 100644 --- a/configure.ac +++ b/configure.ac @@ -2198,16 +2198,8 @@ AC_CHECK_SIZEOF(size_t, 4) AC_CHECK_SIZEOF(pid_t, 4) AC_CHECK_SIZEOF(uintptr_t) -AC_MSG_CHECKING(for long double support) -have_long_double=no -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[long double x; x = (long double)0;]])],[ - AC_DEFINE(HAVE_LONG_DOUBLE, 1, [Define this if you have the type long double.]) - have_long_double=yes -],[]) -AC_MSG_RESULT($have_long_double) -if test "$have_long_double" = yes ; then +AC_TYPE_LONG_DOUBLE AC_CHECK_SIZEOF(long double, 16) -fi AC_CHECK_SIZEOF(_Bool, 1) diff --git a/pyconfig.h.in b/pyconfig.h.in index 848872a7dca3..2af411705a67 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -617,7 +617,7 @@ /* Define to 1 if you have the `log2' function. */ #undef HAVE_LOG2 -/* Define this if you have the type long double. */ +/* Define to 1 if the system has the type `long double'. */ #undef HAVE_LONG_DOUBLE /* Define to 1 if you have the `lstat' function. */ From webhook-mailer at python.org Wed May 16 02:39:16 2018 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Wed, 16 May 2018 06:39:16 -0000 Subject: [Python-checkins] bpo-30928: update idlelib/NEWS.txt for 3.6. (#6888) Message-ID: <mailman.70.1526452759.2757.python-checkins@python.org> https://github.com/python/cpython/commit/8fa36b6be47356f8e42a8bd0b3dba24a8fbd6c35 commit: 8fa36b6be47356f8e42a8bd0b3dba24a8fbd6c35 branch: 3.6 author: Terry Jan Reedy <tjreedy at udel.edu> committer: GitHub <noreply at github.com> date: 2018-05-16T02:39:13-04:00 summary: bpo-30928: update idlelib/NEWS.txt for 3.6. (#6888) files: M Lib/idlelib/NEWS.txt diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index 7ceaf755155f..20ee68e0caca 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -1,8 +1,11 @@ -What's New in IDLE 3.6.5 -Released on 2017-03-26? +What's New in IDLE 3.6.6 +Released on 2018-06-15? ====================================== +bpo-29706: IDLE now colors async and await as keywords in 3.6. +They become full keywords in 3.7. + bpo-21474: Update word/identifier definition from ascii to unicode. In text and entry boxes, this affects selection by double-click, movement left/right by control-left/right, and deletion left/right @@ -13,6 +16,11 @@ A 'u' string prefix cannot be paired with either 'r' or 'f'. IDLE now consistently colors as much of the prefix, starting at the right, as is valid. Revise and extend colorizer test. + +What's New in IDLE 3.6.5 +Released on 2018-03-28 +====================================== + bpo-32984: Set __file__ while running a startup file. Like Python, IDLE optionally runs 1 startup file in the Shell window before presenting the first interactive input prompt. For IDLE, From webhook-mailer at python.org Wed May 16 04:05:27 2018 From: webhook-mailer at python.org (Berker Peksag) Date: Wed, 16 May 2018 08:05:27 -0000 Subject: [Python-checkins] bpo-32384: Skip test when _testcapi isn't available (GH-4940) Message-ID: <mailman.71.1526457929.2757.python-checkins@python.org> https://github.com/python/cpython/commit/4cc3eb48e1e8289df5153db1c701cae263a1ef86 commit: 4cc3eb48e1e8289df5153db1c701cae263a1ef86 branch: master author: Isaiah Peng <isaiah at users.noreply.github.com> committer: Berker Peksag <berker.peksag at gmail.com> date: 2018-05-16T11:05:17+03:00 summary: bpo-32384: Skip test when _testcapi isn't available (GH-4940) files: M Lib/test/test_generators.py diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py index 7360b34023d3..7a21cb7e954a 100644 --- a/Lib/test/test_generators.py +++ b/Lib/test/test_generators.py @@ -9,12 +9,18 @@ from test import support -_testcapi = support.import_module('_testcapi') +try: + import _testcapi +except ImportError: + _testcapi = None # This tests to make sure that if a SIGINT arrives just before we send into a # yield from chain, the KeyboardInterrupt is raised in the innermost # generator (see bpo-30039). + at unittest.skipUnless(_testcapi is not None and + hasattr(_testcapi, "raise_SIGINT_then_send_None"), + "needs _testcapi.raise_SIGINT_then_send_None") class SignalAndYieldFromTest(unittest.TestCase): def generator1(self): From webhook-mailer at python.org Wed May 16 04:20:53 2018 From: webhook-mailer at python.org (Eric V. Smith) Date: Wed, 16 May 2018 08:20:53 -0000 Subject: [Python-checkins] bpo-32216: Add documentation for dataclasses (GH-6886) Message-ID: <mailman.72.1526458856.2757.python-checkins@python.org> https://github.com/python/cpython/commit/98d50cb8f57eb227c373cb94b8680b12ec8aade5 commit: 98d50cb8f57eb227c373cb94b8680b12ec8aade5 branch: master author: Eric V. Smith <ericvsmith at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-16T04:20:43-04:00 summary: bpo-32216: Add documentation for dataclasses (GH-6886) This is an initial version that likely requires much polishing. I'm adding it lay out the structure and so we have something to start working from. files: A Doc/library/dataclasses.rst M Doc/library/python.rst diff --git a/Doc/library/dataclasses.rst b/Doc/library/dataclasses.rst new file mode 100644 index 000000000000..489dece7ccf3 --- /dev/null +++ b/Doc/library/dataclasses.rst @@ -0,0 +1,588 @@ +:mod:`dataclasses` --- Dataclasses +========================================== + +.. module:: dataclasses + :synopsis: Generate special methods and add to user-defined classes. + +.. moduleauthor:: Eric V. Smith <eric at trueblade.com> +.. sectionauthor:: Eric V. Smith <eric at trueblade.com> + +**Source code:** :source:`Lib/dataclasses.py` + +-------------- + +This module provides a decorator and functions for automatically +adding generated :term:`special method`\s such as :meth:`__init__` and +:meth:`__repr__` to user-defined classes. It was originally described +in :pep:`557`. + +The member variables to use in these generated methods are defined +using :pep:`526` type annotations. For example this code:: + + @dataclass + class InventoryItem: + '''Class for keeping track of an item in inventory.''' + name: str + unit_price: float + quantity_on_hand: int = 0 + + def total_cost(self) -> float: + return self.unit_price * self.quantity_on_hand + +Will add, among other things, a :meth:`__init__` that looks like:: + + def __init__(self, name: str, unit_price: float, quantity_on_hand: int=0): + self.name = name + self.unit_price = unit_price + self.quantity_on_hand = quantity_on_hand + +Note that this method is automatically added to the class: it is not +directly specified in the ``InventoryItem`` definition shown above. + +.. versionadded:: 3.7 + +Module-level decorators, classes, and functions +----------------------------------------------- + +.. decorator:: dataclass(*, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False) + + This function is a :term:`decorator` that is used to add generated + :term:`special method`\s to classes, as described below. + + The :func:`dataclass` decorator examines the class to find + ``field``\s. A ``field`` is defined as class variable that has a + type annotation. With two exceptions described below, nothing in + :func:`dataclass` examines the type specified in the variable + annotation. + + The order of the fields in all of the generated methods is the + order in which they appear in the class definition. + + The :func:`dataclass` decorator will add various "dunder" methods to + the class, described below. If any of the added methods already + exist on the class, a :exc:`TypeError` will be raised. The decorator + returns the same class that is called on: no new class is created. + + If :func:`dataclass` is used just as a simple decorator with no parameters, + it acts as if it has the default values documented in this + signature. That is, these three uses of :func:`dataclass` are + equivalent:: + + @dataclass + class C: + ... + + @dataclass() + class C: + ... + + @dataclass(init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False) + class C: + ... + + The parameters to :func:`dataclass` are: + + - ``init``: If true (the default), a :meth:`__init__` method will be + generated. + + If the class already defines :meth:`__init__`, this parameter is + ignored. + + - ``repr``: If true (the default), a :meth:`__repr__` method will be + generated. The generated repr string will have the class name and + the name and repr of each field, in the order they are defined in + the class. Fields that are marked as being excluded from the repr + are not included. For example: + ``InventoryItem(name='widget', unit_price=3.0, quantity_on_hand=10)``. + + If the class already defines :meth:`__repr__`, this parameter is + ignored. + + - ``eq``: If true (the default), an :meth:`__eq__` method will be + generated. This method compares the class as if it were a tuple + of its fields, in order. Both instances in the comparison must + be of the identical type. + + If the class already defines :meth:`__eq__`, this parameter is + ignored. + + - ``order``: If true (the default is ``False``), :meth:`__lt__`, + :meth:`__le__`, :meth:`__gt__`, and :meth:`__ge__` methods will be + generated. These compare the class as if it were a tuple of its + fields, in order. Both instances in the comparison must be of the + identical type. If ``order`` is true and ``eq`` is false, a + :exc:`ValueError` is raised. + + If the class already defines any of :meth:`__lt__`, + :meth:`__le__`, :meth:`__gt__`, or :meth:`__ge__`, then + :exc:`ValueError` is raised. + + - ``unsafe_hash``: If ``False`` (the default), the :meth:`__hash__` method + is generated according to how ``eq`` and ``frozen`` are set. + + If ``eq`` and ``frozen`` are both true, :func:`dataclass` will + generate a :meth:`__hash__` method for you. If ``eq`` is true + and ``frozen`` is false, :meth:`__hash__` will be set to + ``None``, marking it unhashable (which it is, since it is + mutable). If ``eq`` is false, :meth:`__hash__` will be left + untouched meaning the :meth:`__hash__` method of the superclass + will be used (if the superclass is :class:`object`, this means it will + fall back to id-based hashing). + + Although not recommended, you can force :func:`dataclass` to + create a :meth:`__hash__` method with ``unsafe_hash=True``. This + might be the case if your class is logically immutable but can + nonetheless be mutated. This is a specialized use case and should + be considered carefully. + + If a class already has an explicitely defined :meth:`__hash__` + the behavior when adding :meth:`__hash__` is modified. An + expicitely defined :meth:`__hash__` is defined when: + + - :meth:`__eq__` is defined in the class and :meth:`__hash__` is defined + with any value other than ``None``. + + - :meth:`__eq__` is defined in the class and any non-``None`` + :meth:`__hash__` is defined. + + - :meth:`__eq__` is not defined on the class, and any :meth:`__hash__` is + defined. + + If ``unsafe_hash`` is true and an explicitely defined :meth:`__hash__` + is present, then :exc:`ValueError` is raised. + + If ``unsafe_hash`` is false and an explicitely defined :meth:`__hash__` + is present, then no :meth:`__hash__` is added. + + See the Python documentation for more information. + + - ``frozen``: If true (the default is False), assigning to fields will + generate an exception. This emulates read-only frozen instances. + If either :meth:`__getattr__` or :meth:`__setattr__` is defined in + the class, then :exc:`ValueError` is raised. See the discussion + below. + + ``field``\s may optionally specify a default value, using normal + Python syntax:: + + @dataclass + class C: + a: int # 'a' has no default value + b: int = 0 # assign a default value for 'b' + + In this example, both ``a`` and ``b`` will be included in the added + :meth:`__init__` method, which will be defined as:: + + def __init__(self, a: int, b: int = 0): + + :exc:`TypeError` will be raised if a field without a default value + follows a field with a default value. This is true either when this + occurs in a single class, or as a result of class inheritance. + +.. function:: field(*, default=MISSING, default_factory=MISSING, repr=True, hash=None, init=True, compare=True, metadata=None) + + For common and simple use cases, no other functionality is + required. There are, however, some Data Class features that + require additional per-field information. To satisfy this need for + additional information, you can replace the default field value + with a call to the provided :func:`field` function. For example:: + + @dataclass + class C: + l: List[int] = field(default_factory=list) + + c = C() + c.l += [1, 2, 3] + + As shown above, the ``MISSING`` value is a sentinel object used to + detect if the ``default`` and ``default_factory`` parameters are + provided. This sentinel is used because ``None`` is a valid value + for ``default``. No code should directly use the ``MISSING`` + value. + + The parameters to :func:`field` are: + + - ``default``: If provided, this will be the default value for this + field. This is needed because the :meth:`field` call itself + replaces the normal position of the default value. + + - ``default_factory``: If provided, it must be a zero-argument + callable that will be called when a default value is needed for + this field. Among other purposes, this can be used to specify + fields with mutable default values, as discussed below. It is an + error to specify both ``default`` and ``default_factory``. + + - ``init``: If true (the default), this field is included as a + parameter to the generated :meth:`__init__` method. + + - ``repr``: If true (the default), this field is included in the + string returned by the generated :meth:`__repr__` method. + + - ``compare``: If true (the default), this field is included in the + generated equality and comparison methods (:meth:`__eq__`, + :meth:`__gt__`, et al.). + + - ``hash``: This can be a bool or ``None``. If True, this field is + included in the generated :meth:`__hash__` method. If ``None`` (the + default), use the value of ``compare``: this would normally be + the expected behavior. A field should be considered in the hash + if it's used for comparisons. Setting this value to anything + other than ``None`` is discouraged. + + One possible reason to set ``hash=False`` but ``compare=True`` + would be if a field is expensive to compute a hash value for, + that field is needed for equality testing, and there are other + fields that contribute to the type's hash value. Even if a field + is excluded from the hash, it will still be used for comparisons. + + - ``metadata``: This can be a mapping or None. None is treated as + an empty dict. This value is wrapped in + :func:`~types.MappingProxyType` to make it read-only, and exposed + on the :class:`Field` object. It is not used at all by Data + Classes, and is provided as a third-party extension mechanism. + Multiple third-parties can each have their own key, to use as a + namespace in the metadata. + + If the default value of a field is specified by a call to + :func:`field()`, then the class attribute for this field will be + replaced by the specified ``default`` value. If no ``default`` is + provided, then the class attribute will be deleted. The intent is + that after the :func:`dataclass` decorator runs, the class + attributes will all contain the default values for the fields, just + as if the default value itself were specified. For example, + after:: + + @dataclass + class C: + x: int + y: int = field(repr=False) + z: int = field(repr=False, default=10) + t: int = 20 + + The class attribute ``C.z`` will be ``10``, the class attribute + ``C.t`` will be ``20``, and the class attributes ``C.x`` and + ``C.y`` will not be set. + +.. class:: Field + + :class:`Field` objects describe each defined field. These objects + are created internally, and are returned by the :func:`fields` + module-level method (see below). Users should never instantiate a + :class:`Field` object directly. Its documented attributes are: + + - ``name``: The name of the field. + + - ``type``: The type of the field. + + - ``default``, ``default_factory``, ``init``, ``repr``, ``hash``, + ``compare``, and ``metadata`` have the identical meaning and + values as they do in the :func:`field` declaration. + + Other attributes may exist, but they are private and must not be + inspected or relied on. + +.. function:: fields(class_or_instance) + + Returns a tuple of :class:`Field` objects + that define the fields for this Data Class. Accepts either a Data + Class, or an instance of a Data Class. Raises :exc:`ValueError` if + not passed a Data Class or instance of one. Does not return + pseudo-fields which are ``ClassVar`` or ``InitVar``. + +.. function:: asdict(instance, *, dict_factory=dict) + + Converts the Data Class ``instance`` to a dict (by using the + factory function ``dict_factory``). Each Data Class is converted + to a dict of its fields, as ``name: value`` pairs. Data Classes, dicts, + lists, and tuples are recursed into. For example:: + + @dataclass + class Point: + x: int + y: int + + @dataclass + class C: + l: List[Point] + + p = Point(10, 20) + assert asdict(p) == {'x': 10, 'y': 20} + + c = C([Point(0, 0), Point(10, 4)]) + assert asdict(c) == {'l': [{'x': 0, 'y': 0}, {'x': 10, 'y': 4}]} + + Raises :exc:`TypeError` if ``instance`` is not a Data Class instance. + +.. function:: astuple(*, tuple_factory=tuple) + + Converts the Data Class ``instance`` to a tuple (by using the + factory function ``tuple_factory``). Each Data Class is converted + to a tuple of its field values. Data Classes, dicts, lists, and + tuples are recursed into. + + Continuing from the previous example:: + + assert astuple(p) == (10, 20) + assert astuple(c) == ([(0, 0), (10, 4)],) + + Raises :exc:`TypeError` if ``instance`` is not a Data Class instance. + +.. function:: make_dataclass(cls_name, fields, *, bases=(), namespace=None, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False) + + Creates a new Data Class with name ``cls_name``, fields as defined + in ``fields``, base classes as given in ``bases``, and initialized + with a namespace as given in ``namespace``. ``fields`` is an + iterable whose elements are each either ``name``, ``(name, type)``, + or ``(name, type, Field)``. If just ``name`` is supplied, + ``typing.Any`` is used for ``type``. The values of ``init``, + ``repr``, ``eq``, ``order``, ``unsafe_hash``, and ``frozen`` have + the same meaning as they do in :func:`dataclass`. + + This function is not strictly required, because any Python + mechanism for creating a new class with ``__annotations__`` can + then apply the :func:`dataclass` function to convert that class to + a Data Class. This function is provided as a convenience. For + example:: + + C = make_dataclass('C', + [('x', int), + 'y', + ('z', int, field(default=5))], + namespace={'add_one': lambda self: self.x + 1}) + + Is equivalent to:: + + @dataclass + class C: + x: int + y: 'typing.Any' + z: int = 5 + + def add_one(self): + return self.x + 1 + +.. function:: replace(instance, **changes) + + Creates a new object of the same type of ``instance``, replacing + fields with values from ``changes``. If ``instance`` is not a Data + Class, raises :exc:`TypeError`. If values in ``changes`` do not + specify fields, raises :exc:`TypeError`. + + The newly returned object is created by calling the :meth:`__init__` + method of the Data Class. This ensures that + :meth:`__post_init__`, if present, is also called. + + Init-only variables without default values, if any exist, must be + specified on the call to :func:`replace` so that they can be passed to + :meth:`__init__` and :meth:`__post_init__`. + + It is an error for :func:`changes` to contain any fields that are + defined as having ``init=False``. A :exc:`ValueError` will be raised + in this case. + + Be forewarned about how ``init=False`` fields work during a call to + :func:`replace`. They are not copied from the source object, but + rather are initialized in :meth:`__post_init__`, if they're + initialized at all. It is expected that ``init=False`` fields will + be rarely and judiciously used. If they are used, it might be wise + to have alternate class constructors, or perhaps a custom + ``replace()`` (or similarly named) method which handles instance + copying. + +.. function:: is_dataclass(class_or_instance) + + Returns True if its parameter is a dataclass or an instance of one, + otherwise returns False. + + If you need to know if a class is an instance of a dataclass (and + not a dataclass itself), then add a further check for ``not + isinstance(obj, type)``:: + + def is_dataclass_instance(obj): + return is_dataclass(obj) and not isinstance(obj, type) + +Post-init processing +-------------------- + +The generated :meth:`__init__` code will call a method named +:meth:`__post_init__`, if :meth:`__post_init__` is defined on the +class. It will normally be called as ``self.__post_init__()``. +However, if any ``InitVar`` fields are defined, they will also be +passed to :meth:`__post_init` in the order they were defined in the +class. If no :meth:`__init__` method is generated, then +:meth:`__post_init__` will not automatically be called. + +Among other uses, this allows for initializing field values that +depend on one or more other fields. For example:: + + @dataclass + class C: + a: float + b: float + c: float = field(init=False) + + def __post_init__(self): + self.c = self.a + self.b + +See the section below on init-only variables for ways to pass +parameters to :meth:`__post_init__`. Also see the warning about how +:func:`replace` handles ``init=False`` fields. + +Class variables +--------------- + +One of two places where :func:`dataclass` actually inspects the type +of a field is to determine if a field is a class variable as defined +in :pep:`526`. It does this by checking if the type of the field is +``typing.ClassVar``. If a field is a ``ClassVar``, it is excluded +from consideration as a field and is ignored by the Data Class +mechanisms. Such ``ClassVar`` pseudo-fields are not returned by the +module-level :func:`fields` function. + +Init-only variables +------------------- + +The other place where :func:`dataclass` inspects a type annotation is to +determine if a field is an init-only variable. It does this by seeing +if the type of a field is of type ``dataclasses.InitVar``. If a field +is an ``InitVar``, it is considered a pseudo-field called an init-only +field. As it is not a true field, it is not returned by the +module-level :func:`fields` function. Init-only fields are added as +parameters to the generated :meth:`__init__` method, and are passed to +the optional :meth:`__post_init__` method. They are not otherwise used +by Data Classes. + +For example, suppose a field will be initialzed from a database, if a +value is not provided when creating the class:: + + @dataclass + class C: + i: int + j: int = None + database: InitVar[DatabaseType] = None + + def __post_init__(self, database): + if self.j is None and database is not None: + self.j = database.lookup('j') + + c = C(10, database=my_database) + +In this case, :func:`fields` will return :class:`Field` objects for ``i`` and +``j``, but not for ``database``. + +Frozen instances +---------------- + +It is not possible to create truly immutable Python objects. However, +by passing ``frozen=True`` to the :meth:`dataclass` decorator you can +emulate immutability. In that case, Data Classes will add +:meth:`__setattr__` and :meth:`__delattr__` methods to the class. These +methods will raise a :exc:`FrozenInstanceError` when invoked. + +There is a tiny performance penalty when using ``frozen=True``: +:meth:`__init__` cannot use simple assignment to initialize fields, and +must use :meth:`object.__setattr__`. + +Inheritance +----------- + +When the Data Class is being created by the :meth:`dataclass` decorator, +it looks through all of the class's base classes in reverse MRO (that +is, starting at :class:`object`) and, for each Data Class that it finds, +adds the fields from that base class to an ordered mapping of fields. +After all of the base class fields are added, it adds its own fields +to the ordered mapping. All of the generated methods will use this +combined, calculated ordered mapping of fields. Because the fields +are in insertion order, derived classes override base classes. An +example:: + + @dataclass + class Base: + x: Any = 15.0 + y: int = 0 + + @dataclass + class C(Base): + z: int = 10 + x: int = 15 + +The final list of fields is, in order, ``x``, ``y``, ``z``. The final +type of ``x`` is ``int``, as specified in class ``C``. + +The generated :meth:`__init__` method for ``C`` will look like:: + + def __init__(self, x: int = 15, y: int = 0, z: int = 10): + +Default factory functions +------------------------- + + If a :func:`field` specifies a ``default_factory``, it is called with + zero arguments when a default value for the field is needed. For + example, to create a new instance of a list, use:: + + l: list = field(default_factory=list) + + If a field is excluded from :meth:`__init__` (using ``init=False``) + and the field also specifies ``default_factory``, then the default + factory function will always be called from the generated + :meth:`__init__` function. This happens because there is no other + way to give the field an initial value. + +Mutable default values +---------------------- + + Python stores default member variable values in class attributes. + Consider this example, not using Data Classes:: + + class C: + x = [] + def add(self, element): + self.x += element + + o1 = C() + o2 = C() + o1.add(1) + o2.add(2) + assert o1.x == [1, 2] + assert o1.x is o2.x + + Note that the two instances of class ``C`` share the same class + variable ``x``, as expected. + + Using Data Classes, *if* this code was valid:: + + @dataclass + class D: + x: List = [] + def add(self, element): + self.x += element + + it would generate code similar to:: + + class D: + x = [] + def __init__(self, x=x): + self.x = x + def add(self, element): + self.x += element + + assert D().x is D().x + + This has the same issue as the original example using class ``C``. + That is, two instances of class ``D`` that do not specify a value for + ``x`` when creating a class instance will share the same copy of + ``x``. Because Data Classes just use normal Python class creation + they also share this problem. There is no general way for Data + Classes to detect this condition. Instead, Data Classes will raise a + :exc:`TypeError` if it detects a default parameter of type ``list``, + ``dict``, or ``set``. This is a partial solution, but it does protect + against many common errors. + + Using default factory functions is a way to create new instances of + mutable types as default values for fields:: + + @dataclass + class D: + x: list = field(default_factory=list) + + assert D().x is not D().x diff --git a/Doc/library/python.rst b/Doc/library/python.rst index 440dc6632b83..f39613f57288 100644 --- a/Doc/library/python.rst +++ b/Doc/library/python.rst @@ -16,6 +16,7 @@ overview: builtins.rst __main__.rst warnings.rst + dataclasses.rst contextlib.rst abc.rst atexit.rst From webhook-mailer at python.org Wed May 16 04:35:09 2018 From: webhook-mailer at python.org (Berker Peksag) Date: Wed, 16 May 2018 08:35:09 -0000 Subject: [Python-checkins] bpo-32384: Skip test when _testcapi isn't available (GH-4940) Message-ID: <mailman.73.1526459711.2757.python-checkins@python.org> https://github.com/python/cpython/commit/4af6110f77e141779492995fd168d4f027fcf3cf commit: 4af6110f77e141779492995fd168d4f027fcf3cf branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Berker Peksag <berker.peksag at gmail.com> date: 2018-05-16T11:35:06+03:00 summary: bpo-32384: Skip test when _testcapi isn't available (GH-4940) (cherry picked from commit 4cc3eb48e1e8289df5153db1c701cae263a1ef86) Co-authored-by: Isaiah Peng <isaiah at users.noreply.github.com> files: M Lib/test/test_generators.py diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py index 7360b34023d3..7a21cb7e954a 100644 --- a/Lib/test/test_generators.py +++ b/Lib/test/test_generators.py @@ -9,12 +9,18 @@ from test import support -_testcapi = support.import_module('_testcapi') +try: + import _testcapi +except ImportError: + _testcapi = None # This tests to make sure that if a SIGINT arrives just before we send into a # yield from chain, the KeyboardInterrupt is raised in the innermost # generator (see bpo-30039). + at unittest.skipUnless(_testcapi is not None and + hasattr(_testcapi, "raise_SIGINT_then_send_None"), + "needs _testcapi.raise_SIGINT_then_send_None") class SignalAndYieldFromTest(unittest.TestCase): def generator1(self): From webhook-mailer at python.org Wed May 16 05:14:59 2018 From: webhook-mailer at python.org (Eric V. Smith) Date: Wed, 16 May 2018 09:14:59 -0000 Subject: [Python-checkins] Reflow dataclasses comments (GH-6893) Message-ID: <mailman.74.1526462100.2757.python-checkins@python.org> https://github.com/python/cpython/commit/f8e7549490d61c92b34bf2de3e03ba2f7b0ac6e1 commit: f8e7549490d61c92b34bf2de3e03ba2f7b0ac6e1 branch: master author: Eric V. Smith <ericvsmith at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-16T05:14:53-04:00 summary: Reflow dataclasses comments (GH-6893) To be more consistent with other code (and so people stop hassling me!), reflow the dataclasses comments to not use a single space indentation when continuing a paragraph of text. files: M Lib/dataclasses.py diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index c93aadc95e0a..480c6f74165b 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -21,12 +21,12 @@ ] # Conditions for adding methods. The boxes indicate what action the -# dataclass decorator takes. For all of these tables, when I talk -# about init=, repr=, eq=, order=, unsafe_hash=, or frozen=, I'm -# referring to the arguments to the @dataclass decorator. When -# checking if a dunder method already exists, I mean check for an -# entry in the class's __dict__. I never check to see if an -# attribute is defined in a base class. +# dataclass decorator takes. For all of these tables, when I talk +# about init=, repr=, eq=, order=, unsafe_hash=, or frozen=, I'm +# referring to the arguments to the @dataclass decorator. When +# checking if a dunder method already exists, I mean check for an +# entry in the class's __dict__. I never check to see if an attribute +# is defined in a base class. # Key: # +=========+=========================================+ @@ -79,7 +79,7 @@ # | True | add | raise | # +=======+=======+=======+ # Raise because not adding these methods would break the "frozen-ness" -# of the class. +# of the class. # __eq__ # @@ -108,7 +108,7 @@ # | True | add | raise | # +=======+=======+=======+ # Raise because to allow this case would interfere with using -# functools.total_ordering. +# functools.total_ordering. # __hash__ @@ -136,34 +136,35 @@ # | True | True | True | add | raise | Frozen, so hashable # +=======+=======+=======+========+========+ # For boxes that are blank, __hash__ is untouched and therefore -# inherited from the base class. If the base is object, then -# id-based hashing is used. +# inherited from the base class. If the base is object, then +# id-based hashing is used. +# # Note that a class may already have __hash__=None if it specified an -# __eq__ method in the class body (not one that was created by -# @dataclass). +# __eq__ method in the class body (not one that was created by +# @dataclass). +# # See _hash_action (below) for a coded version of this table. # Raised when an attempt is made to modify a frozen class. class FrozenInstanceError(AttributeError): pass -# A sentinel object for default values to signal that a -# default factory will be used. -# This is given a nice repr() which will appear in the function -# signature of dataclasses' constructors. +# A sentinel object for default values to signal that a default +# factory will be used. This is given a nice repr() which will appear +# in the function signature of dataclasses' constructors. class _HAS_DEFAULT_FACTORY_CLASS: def __repr__(self): return '<factory>' _HAS_DEFAULT_FACTORY = _HAS_DEFAULT_FACTORY_CLASS() # A sentinel object to detect if a parameter is supplied or not. Use -# a class to give it a better repr. +# a class to give it a better repr. class _MISSING_TYPE: pass MISSING = _MISSING_TYPE() # Since most per-field metadata will be unused, create an empty -# read-only proxy that can be shared among all fields. +# read-only proxy that can be shared among all fields. _EMPTY_METADATA = types.MappingProxyType({}) # Markers for the various kinds of fields and pseudo-fields. @@ -177,7 +178,7 @@ def __repr__(self): _FIELD_INITVAR = _FIELD_BASE('_FIELD_INITVAR') # The name of an attribute on the class where we store the Field -# objects. Also used to check if a class is a Data Class. +# objects. Also used to check if a class is a Data Class. _FIELDS = '__dataclass_fields__' # The name of an attribute on the class that stores the parameters to @@ -202,13 +203,15 @@ class InitVar(metaclass=_InitVarMeta): # Instances of Field are only ever created from within this module, -# and only from the field() function, although Field instances are -# exposed externally as (conceptually) read-only objects. -# name and type are filled in after the fact, not in __init__. They're -# not known at the time this class is instantiated, but it's -# convenient if they're available later. +# and only from the field() function, although Field instances are +# exposed externally as (conceptually) read-only objects. +# +# name and type are filled in after the fact, not in __init__. +# They're not known at the time this class is instantiated, but it's +# convenient if they're available later. +# # When cls._FIELDS is filled in with a list of Field objects, the name -# and type fields will have been populated. +# and type fields will have been populated. class Field: __slots__ = ('name', 'type', @@ -252,17 +255,18 @@ def __repr__(self): ')') # This is used to support the PEP 487 __set_name__ protocol in the - # case where we're using a field that contains a descriptor as a - # defaul value. For details on __set_name__, see - # https://www.python.org/dev/peps/pep-0487/#implementation-details. - # Note that in _process_class, this Field object is overwritten with - # the default value, so the end result is a descriptor that had - # __set_name__ called on it at the right time. + # case where we're using a field that contains a descriptor as a + # defaul value. For details on __set_name__, see + # https://www.python.org/dev/peps/pep-0487/#implementation-details. + # + # Note that in _process_class, this Field object is overwritten + # with the default value, so the end result is a descriptor that + # had __set_name__ called on it at the right time. def __set_name__(self, owner, name): func = getattr(type(self.default), '__set_name__', None) if func: - # There is a __set_name__ method on the descriptor, - # call it. + # There is a __set_name__ method on the descriptor, call + # it. func(self.default, owner, name) @@ -295,20 +299,20 @@ def __repr__(self): # This function is used instead of exposing Field creation directly, -# so that a type checker can be told (via overloads) that this is a -# function whose type depends on its parameters. +# so that a type checker can be told (via overloads) that this is a +# function whose type depends on its parameters. def field(*, default=MISSING, default_factory=MISSING, init=True, repr=True, hash=None, compare=True, metadata=None): """Return an object to identify dataclass fields. - default is the default value of the field. default_factory is a - 0-argument function called to initialize a field's value. If init + default is the default value of the field. default_factory is a + 0-argument function called to initialize a field's value. If init is True, the field will be a parameter to the class's __init__() - function. If repr is True, the field will be included in the - object's repr(). If hash is True, the field will be included in - the object's hash(). If compare is True, the field will be used in - comparison functions. metadata, if specified, must be a mapping - which is stored but not otherwise examined by dataclass. + function. If repr is True, the field will be included in the + object's repr(). If hash is True, the field will be included in + the object's hash(). If compare is True, the field will be used + in comparison functions. metadata, if specified, must be a + mapping which is stored but not otherwise examined by dataclass. It is an error to specify both default and default_factory. """ @@ -321,8 +325,8 @@ def field(*, default=MISSING, default_factory=MISSING, init=True, repr=True, def _tuple_str(obj_name, fields): # Return a string representing each field of obj_name as a tuple - # member. So, if fields is ['x', 'y'] and obj_name is "self", - # return "(self.x,self.y)". + # member. So, if fields is ['x', 'y'] and obj_name is "self", + # return "(self.x,self.y)". # Special case for the 0-tuple. if not fields: @@ -333,9 +337,9 @@ def _tuple_str(obj_name, fields): def _create_fn(name, args, body, *, globals=None, locals=None, return_type=MISSING): - # Note that we mutate locals when exec() is called. Caller beware! - # The only callers are internal to this module, so no worries - # about external callers. + # Note that we mutate locals when exec() is called. Caller + # beware! The only callers are internal to this module, so no + # worries about external callers. if locals is None: locals = {} return_annotation = '' @@ -354,10 +358,11 @@ def _create_fn(name, args, body, *, globals=None, locals=None, def _field_assign(frozen, name, value, self_name): # If we're a frozen class, then assign to our fields in __init__ - # via object.__setattr__. Otherwise, just use a simple - # assignment. + # via object.__setattr__. Otherwise, just use a simple + # assignment. + # # self_name is what "self" is called in this function: don't - # hard-code "self", since that might be a field name. + # hard-code "self", since that might be a field name. if frozen: return f'object.__setattr__({self_name},{name!r},{value})' return f'{self_name}.{name}={value}' @@ -365,31 +370,31 @@ def _field_assign(frozen, name, value, self_name): def _field_init(f, frozen, globals, self_name): # Return the text of the line in the body of __init__ that will - # initialize this field. + # initialize this field. default_name = f'_dflt_{f.name}' if f.default_factory is not MISSING: if f.init: # This field has a default factory. If a parameter is - # given, use it. If not, call the factory. + # given, use it. If not, call the factory. globals[default_name] = f.default_factory value = (f'{default_name}() ' f'if {f.name} is _HAS_DEFAULT_FACTORY ' f'else {f.name}') else: # This is a field that's not in the __init__ params, but - # has a default factory function. It needs to be - # initialized here by calling the factory function, - # because there's no other way to initialize it. + # has a default factory function. It needs to be + # initialized here by calling the factory function, + # because there's no other way to initialize it. # For a field initialized with a default=defaultvalue, the - # class dict just has the default value - # (cls.fieldname=defaultvalue). But that won't work for a - # default factory, the factory must be called in __init__ - # and we must assign that to self.fieldname. We can't - # fall back to the class dict's value, both because it's - # not set, and because it might be different per-class - # (which, after all, is why we have a factory function!). + # class dict just has the default value + # (cls.fieldname=defaultvalue). But that won't work for a + # default factory, the factory must be called in __init__ + # and we must assign that to self.fieldname. We can't + # fall back to the class dict's value, both because it's + # not set, and because it might be different per-class + # (which, after all, is why we have a factory function!). globals[default_name] = f.default_factory value = f'{default_name}()' @@ -403,13 +408,13 @@ def _field_init(f, frozen, globals, self_name): globals[default_name] = f.default value = f.name else: - # This field does not need initialization. Signify that to - # the caller by returning None. + # This field does not need initialization. Signify that + # to the caller by returning None. return None # Only test this now, so that we can create variables for the - # default. However, return None to signify that we're not going - # to actually do the assignment statement for InitVars. + # default. However, return None to signify that we're not going + # to actually do the assignment statement for InitVars. if f._field_type == _FIELD_INITVAR: return None @@ -418,19 +423,20 @@ def _field_init(f, frozen, globals, self_name): def _init_param(f): - # Return the __init__ parameter string for this field. - # For example, the equivalent of 'x:int=3' (except instead of 'int', - # reference a variable set to int, and instead of '3', reference a - # variable set to 3). + # Return the __init__ parameter string for this field. For + # example, the equivalent of 'x:int=3' (except instead of 'int', + # reference a variable set to int, and instead of '3', reference a + # variable set to 3). if f.default is MISSING and f.default_factory is MISSING: - # There's no default, and no default_factory, just - # output the variable name and type. + # There's no default, and no default_factory, just output the + # variable name and type. default = '' elif f.default is not MISSING: - # There's a default, this will be the name that's used to look it up. + # There's a default, this will be the name that's used to look + # it up. default = f'=_dflt_{f.name}' elif f.default_factory is not MISSING: - # There's a factory function. Set a marker. + # There's a factory function. Set a marker. default = '=_HAS_DEFAULT_FACTORY' return f'{f.name}:_type_{f.name}{default}' @@ -439,10 +445,10 @@ def _init_fn(fields, frozen, has_post_init, self_name): # fields contains both real fields and InitVar pseudo-fields. # Make sure we don't have fields without defaults following fields - # with defaults. This actually would be caught when exec-ing the - # function source code, but catching it here gives a better error - # message, and future-proofs us in case we build up the function - # using ast. + # with defaults. This actually would be caught when exec-ing the + # function source code, but catching it here gives a better error + # message, and future-proofs us in case we build up the function + # using ast. seen_default = False for f in fields: # Only consider fields in the __init__ call. @@ -460,7 +466,7 @@ def _init_fn(fields, frozen, has_post_init, self_name): for f in fields: line = _field_init(f, frozen, globals, self_name) # line is None means that this field doesn't require - # initialization (it's a pseudo-field). Just skip it. + # initialization (it's a pseudo-field). Just skip it. if line: body_lines.append(line) @@ -493,8 +499,8 @@ def _repr_fn(fields): def _frozen_get_del_attr(cls, fields): - # XXX: globals is modified on the first call to _create_fn, then the - # modified version is used in the second call. Is this okay? + # XXX: globals is modified on the first call to _create_fn, then + # the modified version is used in the second call. Is this okay? globals = {'cls': cls, 'FrozenInstanceError': FrozenInstanceError} if fields: @@ -519,9 +525,9 @@ def _frozen_get_del_attr(cls, fields): def _cmp_fn(name, op, self_tuple, other_tuple): # Create a comparison function. If the fields in the object are - # named 'x' and 'y', then self_tuple is the string - # '(self.x,self.y)' and other_tuple is the string - # '(other.x,other.y)'. + # named 'x' and 'y', then self_tuple is the string + # '(self.x,self.y)' and other_tuple is the string + # '(other.x,other.y)'. return _create_fn(name, ('self', 'other'), @@ -540,7 +546,7 @@ def _hash_fn(fields): def _is_classvar(a_type, typing): if typing: # This test uses a typing internal class, but it's the best - # way to test if this is a ClassVar. + # way to test if this is a ClassVar. return (a_type is typing.ClassVar or (type(a_type) is typing._GenericAlias and a_type.__origin__ is typing.ClassVar)) @@ -573,25 +579,25 @@ def _is_type(annotation, cls, a_module, a_type, is_type_predicate): # instead only a module (global) lookup), there are some things it # gets wrong. - # With string annotations, this will work: + # With string annotations, cv0 will be detected as a ClassVar: # CV = ClassVar # @dataclass # class C0: # cv0: CV - # But this will not: + # But in this example cv1 will not be detected as a ClassVar: # @dataclass # class C1: # CV = ClassVar # cv1: CV - # In C1, the code in this function will look up "CV" in the module - # and not find it, so it will not consider cv1 as a ClassVar. - # This is a fairly obscure corner case, and the best way to fix it - # would be to eval() the string "CV" with the correct global and - # local namespaces. However that would involve a eval() penalty - # for every single field of every dataclass that's defined. It - # was judged not worth it. + # In C1, the code in this function (_is_type) will look up "CV" in + # the module and not find it, so it will not consider cv1 as a + # ClassVar. This is a fairly obscure corner case, and the best + # way to fix it would be to eval() the string "CV" with the + # correct global and local namespaces. However that would involve + # a eval() penalty for every single field of every dataclass + # that's defined. It was judged not worth it. match = _MODULE_IDENTIFIER_RE.match(annotation) if match: @@ -613,11 +619,11 @@ def _is_type(annotation, cls, a_module, a_type, is_type_predicate): def _get_field(cls, a_name, a_type): # Return a Field object for this field name and type. ClassVars - # and InitVars are also returned, but marked as such (see - # f._field_type). + # and InitVars are also returned, but marked as such (see + # f._field_type). - # If the default value isn't derived from Field, then it's - # only a normal default value. Convert it to a Field(). + # If the default value isn't derived from Field, then it's only a + # normal default value. Convert it to a Field(). default = getattr(cls, a_name, MISSING) if isinstance(default, Field): f = default @@ -627,33 +633,31 @@ def _get_field(cls, a_name, a_type): default = MISSING f = field(default=default) - # Only at this point do we know the name and the type. Set them. + # Only at this point do we know the name and the type. Set them. f.name = a_name f.type = a_type # Assume it's a normal field until proven otherwise. We're next - # going to decide if it's a ClassVar or InitVar, everything else - # is just a normal field. + # going to decide if it's a ClassVar or InitVar, everything else + # is just a normal field. f._field_type = _FIELD # In addition to checking for actual types here, also check for - # string annotations. get_type_hints() won't always work for us - # (see https://github.com/python/typing/issues/508 for example), - # plus it's expensive and would require an eval for every stirng - # annotation. So, make a best effort to see if this is a - # ClassVar or InitVar using regex's and checking that the thing - # referenced is actually of the correct type. + # string annotations. get_type_hints() won't always work for us + # (see https://github.com/python/typing/issues/508 for example), + # plus it's expensive and would require an eval for every stirng + # annotation. So, make a best effort to see if this is a ClassVar + # or InitVar using regex's and checking that the thing referenced + # is actually of the correct type. # For the complete discussion, see https://bugs.python.org/issue33453 # If typing has not been imported, then it's impossible for any - # annotation to be a ClassVar. So, only look for ClassVar if - # typing has been imported by any module (not necessarily cls's - # module). + # annotation to be a ClassVar. So, only look for ClassVar if + # typing has been imported by any module (not necessarily cls's + # module). typing = sys.modules.get('typing') if typing: - # This test uses a typing internal class, but it's the best - # way to test if this is a ClassVar. if (_is_classvar(a_type, typing) or (isinstance(f.type, str) and _is_type(f.type, cls, typing, typing.ClassVar, @@ -682,10 +686,10 @@ def _get_field(cls, a_name, a_type): raise TypeError(f'field {f.name} cannot have a ' 'default factory') # Should I check for other field settings? default_factory - # seems the most serious to check for. Maybe add others. - # For example, how about init=False (or really, - # init=<not-the-default-init-value>)? It makes no sense for - # ClassVar and InitVar to specify init=<anything>. + # seems the most serious to check for. Maybe add others. For + # example, how about init=False (or really, + # init=<not-the-default-init-value>)? It makes no sense for + # ClassVar and InitVar to specify init=<anything>. # For real fields, disallow mutable defaults for known types. if f._field_type is _FIELD and isinstance(f.default, (list, dict, set)): @@ -697,7 +701,7 @@ def _get_field(cls, a_name, a_type): def _set_new_attribute(cls, name, value): # Never overwrites an existing attribute. Returns True if the - # attribute already exists. + # attribute already exists. if name in cls.__dict__: return True setattr(cls, name, value) @@ -705,9 +709,9 @@ def _set_new_attribute(cls, name, value): # Decide if/how we're going to create a hash function. Key is -# (unsafe_hash, eq, frozen, does-hash-exist). Value is the action to -# take. The common case is to do nothing, so instead of providing a -# function that is a no-op, use None to signify that. +# (unsafe_hash, eq, frozen, does-hash-exist). Value is the action to +# take. The common case is to do nothing, so instead of providing a +# function that is a no-op, use None to signify that. def _hash_set_none(cls, fields): return None @@ -748,28 +752,28 @@ def _hash_exception(cls, fields): (True, True, True, True ): _hash_exception, } # See https://bugs.python.org/issue32929#msg312829 for an if-statement -# version of this table. +# version of this table. def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen): # Now that dicts retain insertion order, there's no reason to use - # an ordered dict. I am leveraging that ordering here, because - # derived class fields overwrite base class fields, but the order - # is defined by the base class, which is found first. + # an ordered dict. I am leveraging that ordering here, because + # derived class fields overwrite base class fields, but the order + # is defined by the base class, which is found first. fields = {} setattr(cls, _PARAMS, _DataclassParams(init, repr, eq, order, unsafe_hash, frozen)) # Find our base classes in reverse MRO order, and exclude - # ourselves. In reversed order so that more derived classes - # override earlier field definitions in base classes. - # As long as we're iterating over them, see if any are frozen. + # ourselves. In reversed order so that more derived classes + # override earlier field definitions in base classes. As long as + # we're iterating over them, see if any are frozen. any_frozen_base = False has_dataclass_bases = False for b in cls.__mro__[-1:0:-1]: # Only process classes that have been processed by our - # decorator. That is, they have a _FIELDS attribute. + # decorator. That is, they have a _FIELDS attribute. base_fields = getattr(b, _FIELDS, None) if base_fields: has_dataclass_bases = True @@ -779,38 +783,39 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen): any_frozen_base = True # Annotations that are defined in this class (not in base - # classes). If __annotations__ isn't present, then this class - # adds no new annotations. We use this to compute fields that - # are added by this class. + # classes). If __annotations__ isn't present, then this class + # adds no new annotations. We use this to compute fields that are + # added by this class. + # # Fields are found from cls_annotations, which is guaranteed to be - # ordered. Default values are from class attributes, if a field - # has a default. If the default value is a Field(), then it - # contains additional info beyond (and possibly including) the - # actual default value. Pseudo-fields ClassVars and InitVars are - # included, despite the fact that they're not real fields. - # That's dealt with later. + # ordered. Default values are from class attributes, if a field + # has a default. If the default value is a Field(), then it + # contains additional info beyond (and possibly including) the + # actual default value. Pseudo-fields ClassVars and InitVars are + # included, despite the fact that they're not real fields. That's + # dealt with later. cls_annotations = cls.__dict__.get('__annotations__', {}) # Now find fields in our class. While doing so, validate some - # things, and set the default values (as class attributes) - # where we can. + # things, and set the default values (as class attributes) where + # we can. cls_fields = [_get_field(cls, name, type) for name, type in cls_annotations.items()] for f in cls_fields: fields[f.name] = f - # If the class attribute (which is the default value for - # this field) exists and is of type 'Field', replace it - # with the real default. This is so that normal class - # introspection sees a real default value, not a Field. + # If the class attribute (which is the default value for this + # field) exists and is of type 'Field', replace it with the + # real default. This is so that normal class introspection + # sees a real default value, not a Field. if isinstance(getattr(cls, f.name, None), Field): if f.default is MISSING: # If there's no default, delete the class attribute. - # This happens if we specify field(repr=False), for - # example (that is, we specified a field object, but - # no default value). Also if we're using a default - # factory. The class attribute should not be set at - # all in the post-processed class. + # This happens if we specify field(repr=False), for + # example (that is, we specified a field object, but + # no default value). Also if we're using a default + # factory. The class attribute should not be set at + # all in the post-processed class. delattr(cls, f.name) else: setattr(cls, f.name, f.default) @@ -832,21 +837,21 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen): raise TypeError('cannot inherit frozen dataclass from a ' 'non-frozen one') - # Remember all of the fields on our class (including bases). This also - # marks this class as being a dataclass. + # Remember all of the fields on our class (including bases). This + # also marks this class as being a dataclass. setattr(cls, _FIELDS, fields) # Was this class defined with an explicit __hash__? Note that if - # __eq__ is defined in this class, then python will automatically - # set __hash__ to None. This is a heuristic, as it's possible - # that such a __hash__ == None was not auto-generated, but it - # close enough. + # __eq__ is defined in this class, then python will automatically + # set __hash__ to None. This is a heuristic, as it's possible + # that such a __hash__ == None was not auto-generated, but it + # close enough. class_hash = cls.__dict__.get('__hash__', MISSING) has_explicit_hash = not (class_hash is MISSING or (class_hash is None and '__eq__' in cls.__dict__)) - # If we're generating ordering methods, we must be generating - # the eq methods. + # If we're generating ordering methods, we must be generating the + # eq methods. if order and not eq: raise ValueError('eq must be true if order is true') @@ -861,14 +866,15 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen): _init_fn(flds, frozen, has_post_init, - # The name to use for the "self" param - # in __init__. Use "self" if possible. + # The name to use for the "self" + # param in __init__. Use "self" + # if possible. '__dataclass_self__' if 'self' in fields else 'self', )) # Get the fields as a list, and include only real fields. This is - # used in all of the following methods. + # used in all of the following methods. field_list = [f for f in fields.values() if f._field_type is _FIELD] if repr: @@ -877,7 +883,7 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen): if eq: # Create _eq__ method. There's no need for a __ne__ method, - # since python will call __eq__ and negate it. + # since python will call __eq__ and negate it. flds = [f for f in field_list if f.compare] self_tuple = _tuple_str('self', flds) other_tuple = _tuple_str('other', flds) @@ -914,7 +920,7 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen): has_explicit_hash] if hash_action: # No need to call _set_new_attribute here, since by the time - # we're here the overwriting is unconditional. + # we're here the overwriting is unconditional. cls.__hash__ = hash_action(cls, field_list) if not getattr(cls, '__doc__'): @@ -926,8 +932,8 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen): # _cls should never be specified by keyword, so start it with an -# underscore. The presence of _cls is used to detect if this -# decorator is being called with parameters or not. +# underscore. The presence of _cls is used to detect if this +# decorator is being called with parameters or not. def dataclass(_cls=None, *, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False): """Returns the same class as was passed in, with dunder methods @@ -968,7 +974,7 @@ def fields(class_or_instance): raise TypeError('must be called with a dataclass type or instance') # Exclude pseudo-fields. Note that fields is sorted by insertion - # order, so the order of the tuple is as the fields were defined. + # order, so the order of the tuple is as the fields were defined. return tuple(f for f in fields.values() if f._field_type is _FIELD) @@ -1130,8 +1136,8 @@ class C: assert c1.x == 3 and c1.y == 2 """ - # We're going to mutate 'changes', but that's okay because it's a new - # dict, even if called with 'replace(obj, **my_changes)'. + # We're going to mutate 'changes', but that's okay because it's a + # new dict, even if called with 'replace(obj, **my_changes)'. if not _is_dataclass_instance(obj): raise TypeError("replace() should be called on dataclass instances") @@ -1152,8 +1158,8 @@ class C: changes[f.name] = getattr(obj, f.name) # Create the new object, which calls __init__() and - # __post_init__() (if defined), using all of the init fields - # we've added and/or left in 'changes'. If there are values - # supplied in changes that aren't fields, this will correctly - # raise a TypeError. + # __post_init__() (if defined), using all of the init fields we've + # added and/or left in 'changes'. If there are values supplied in + # changes that aren't fields, this will correctly raise a + # TypeError. return obj.__class__(**changes) From webhook-mailer at python.org Wed May 16 05:17:06 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 16 May 2018 09:17:06 -0000 Subject: [Python-checkins] bpo-32216: Add documentation for dataclasses (GH-6886) Message-ID: <mailman.75.1526462228.2757.python-checkins@python.org> https://github.com/python/cpython/commit/04e96da5e4982afeb639d6a4d232c6c221fe3a9d commit: 04e96da5e4982afeb639d6a4d232c6c221fe3a9d branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-16T02:17:03-07:00 summary: bpo-32216: Add documentation for dataclasses (GH-6886) This is an initial version that likely requires much polishing. I'm adding it lay out the structure and so we have something to start working from. (cherry picked from commit 98d50cb8f57eb227c373cb94b8680b12ec8aade5) Co-authored-by: Eric V. Smith <ericvsmith at users.noreply.github.com> files: A Doc/library/dataclasses.rst M Doc/library/python.rst diff --git a/Doc/library/dataclasses.rst b/Doc/library/dataclasses.rst new file mode 100644 index 000000000000..489dece7ccf3 --- /dev/null +++ b/Doc/library/dataclasses.rst @@ -0,0 +1,588 @@ +:mod:`dataclasses` --- Dataclasses +========================================== + +.. module:: dataclasses + :synopsis: Generate special methods and add to user-defined classes. + +.. moduleauthor:: Eric V. Smith <eric at trueblade.com> +.. sectionauthor:: Eric V. Smith <eric at trueblade.com> + +**Source code:** :source:`Lib/dataclasses.py` + +-------------- + +This module provides a decorator and functions for automatically +adding generated :term:`special method`\s such as :meth:`__init__` and +:meth:`__repr__` to user-defined classes. It was originally described +in :pep:`557`. + +The member variables to use in these generated methods are defined +using :pep:`526` type annotations. For example this code:: + + @dataclass + class InventoryItem: + '''Class for keeping track of an item in inventory.''' + name: str + unit_price: float + quantity_on_hand: int = 0 + + def total_cost(self) -> float: + return self.unit_price * self.quantity_on_hand + +Will add, among other things, a :meth:`__init__` that looks like:: + + def __init__(self, name: str, unit_price: float, quantity_on_hand: int=0): + self.name = name + self.unit_price = unit_price + self.quantity_on_hand = quantity_on_hand + +Note that this method is automatically added to the class: it is not +directly specified in the ``InventoryItem`` definition shown above. + +.. versionadded:: 3.7 + +Module-level decorators, classes, and functions +----------------------------------------------- + +.. decorator:: dataclass(*, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False) + + This function is a :term:`decorator` that is used to add generated + :term:`special method`\s to classes, as described below. + + The :func:`dataclass` decorator examines the class to find + ``field``\s. A ``field`` is defined as class variable that has a + type annotation. With two exceptions described below, nothing in + :func:`dataclass` examines the type specified in the variable + annotation. + + The order of the fields in all of the generated methods is the + order in which they appear in the class definition. + + The :func:`dataclass` decorator will add various "dunder" methods to + the class, described below. If any of the added methods already + exist on the class, a :exc:`TypeError` will be raised. The decorator + returns the same class that is called on: no new class is created. + + If :func:`dataclass` is used just as a simple decorator with no parameters, + it acts as if it has the default values documented in this + signature. That is, these three uses of :func:`dataclass` are + equivalent:: + + @dataclass + class C: + ... + + @dataclass() + class C: + ... + + @dataclass(init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False) + class C: + ... + + The parameters to :func:`dataclass` are: + + - ``init``: If true (the default), a :meth:`__init__` method will be + generated. + + If the class already defines :meth:`__init__`, this parameter is + ignored. + + - ``repr``: If true (the default), a :meth:`__repr__` method will be + generated. The generated repr string will have the class name and + the name and repr of each field, in the order they are defined in + the class. Fields that are marked as being excluded from the repr + are not included. For example: + ``InventoryItem(name='widget', unit_price=3.0, quantity_on_hand=10)``. + + If the class already defines :meth:`__repr__`, this parameter is + ignored. + + - ``eq``: If true (the default), an :meth:`__eq__` method will be + generated. This method compares the class as if it were a tuple + of its fields, in order. Both instances in the comparison must + be of the identical type. + + If the class already defines :meth:`__eq__`, this parameter is + ignored. + + - ``order``: If true (the default is ``False``), :meth:`__lt__`, + :meth:`__le__`, :meth:`__gt__`, and :meth:`__ge__` methods will be + generated. These compare the class as if it were a tuple of its + fields, in order. Both instances in the comparison must be of the + identical type. If ``order`` is true and ``eq`` is false, a + :exc:`ValueError` is raised. + + If the class already defines any of :meth:`__lt__`, + :meth:`__le__`, :meth:`__gt__`, or :meth:`__ge__`, then + :exc:`ValueError` is raised. + + - ``unsafe_hash``: If ``False`` (the default), the :meth:`__hash__` method + is generated according to how ``eq`` and ``frozen`` are set. + + If ``eq`` and ``frozen`` are both true, :func:`dataclass` will + generate a :meth:`__hash__` method for you. If ``eq`` is true + and ``frozen`` is false, :meth:`__hash__` will be set to + ``None``, marking it unhashable (which it is, since it is + mutable). If ``eq`` is false, :meth:`__hash__` will be left + untouched meaning the :meth:`__hash__` method of the superclass + will be used (if the superclass is :class:`object`, this means it will + fall back to id-based hashing). + + Although not recommended, you can force :func:`dataclass` to + create a :meth:`__hash__` method with ``unsafe_hash=True``. This + might be the case if your class is logically immutable but can + nonetheless be mutated. This is a specialized use case and should + be considered carefully. + + If a class already has an explicitely defined :meth:`__hash__` + the behavior when adding :meth:`__hash__` is modified. An + expicitely defined :meth:`__hash__` is defined when: + + - :meth:`__eq__` is defined in the class and :meth:`__hash__` is defined + with any value other than ``None``. + + - :meth:`__eq__` is defined in the class and any non-``None`` + :meth:`__hash__` is defined. + + - :meth:`__eq__` is not defined on the class, and any :meth:`__hash__` is + defined. + + If ``unsafe_hash`` is true and an explicitely defined :meth:`__hash__` + is present, then :exc:`ValueError` is raised. + + If ``unsafe_hash`` is false and an explicitely defined :meth:`__hash__` + is present, then no :meth:`__hash__` is added. + + See the Python documentation for more information. + + - ``frozen``: If true (the default is False), assigning to fields will + generate an exception. This emulates read-only frozen instances. + If either :meth:`__getattr__` or :meth:`__setattr__` is defined in + the class, then :exc:`ValueError` is raised. See the discussion + below. + + ``field``\s may optionally specify a default value, using normal + Python syntax:: + + @dataclass + class C: + a: int # 'a' has no default value + b: int = 0 # assign a default value for 'b' + + In this example, both ``a`` and ``b`` will be included in the added + :meth:`__init__` method, which will be defined as:: + + def __init__(self, a: int, b: int = 0): + + :exc:`TypeError` will be raised if a field without a default value + follows a field with a default value. This is true either when this + occurs in a single class, or as a result of class inheritance. + +.. function:: field(*, default=MISSING, default_factory=MISSING, repr=True, hash=None, init=True, compare=True, metadata=None) + + For common and simple use cases, no other functionality is + required. There are, however, some Data Class features that + require additional per-field information. To satisfy this need for + additional information, you can replace the default field value + with a call to the provided :func:`field` function. For example:: + + @dataclass + class C: + l: List[int] = field(default_factory=list) + + c = C() + c.l += [1, 2, 3] + + As shown above, the ``MISSING`` value is a sentinel object used to + detect if the ``default`` and ``default_factory`` parameters are + provided. This sentinel is used because ``None`` is a valid value + for ``default``. No code should directly use the ``MISSING`` + value. + + The parameters to :func:`field` are: + + - ``default``: If provided, this will be the default value for this + field. This is needed because the :meth:`field` call itself + replaces the normal position of the default value. + + - ``default_factory``: If provided, it must be a zero-argument + callable that will be called when a default value is needed for + this field. Among other purposes, this can be used to specify + fields with mutable default values, as discussed below. It is an + error to specify both ``default`` and ``default_factory``. + + - ``init``: If true (the default), this field is included as a + parameter to the generated :meth:`__init__` method. + + - ``repr``: If true (the default), this field is included in the + string returned by the generated :meth:`__repr__` method. + + - ``compare``: If true (the default), this field is included in the + generated equality and comparison methods (:meth:`__eq__`, + :meth:`__gt__`, et al.). + + - ``hash``: This can be a bool or ``None``. If True, this field is + included in the generated :meth:`__hash__` method. If ``None`` (the + default), use the value of ``compare``: this would normally be + the expected behavior. A field should be considered in the hash + if it's used for comparisons. Setting this value to anything + other than ``None`` is discouraged. + + One possible reason to set ``hash=False`` but ``compare=True`` + would be if a field is expensive to compute a hash value for, + that field is needed for equality testing, and there are other + fields that contribute to the type's hash value. Even if a field + is excluded from the hash, it will still be used for comparisons. + + - ``metadata``: This can be a mapping or None. None is treated as + an empty dict. This value is wrapped in + :func:`~types.MappingProxyType` to make it read-only, and exposed + on the :class:`Field` object. It is not used at all by Data + Classes, and is provided as a third-party extension mechanism. + Multiple third-parties can each have their own key, to use as a + namespace in the metadata. + + If the default value of a field is specified by a call to + :func:`field()`, then the class attribute for this field will be + replaced by the specified ``default`` value. If no ``default`` is + provided, then the class attribute will be deleted. The intent is + that after the :func:`dataclass` decorator runs, the class + attributes will all contain the default values for the fields, just + as if the default value itself were specified. For example, + after:: + + @dataclass + class C: + x: int + y: int = field(repr=False) + z: int = field(repr=False, default=10) + t: int = 20 + + The class attribute ``C.z`` will be ``10``, the class attribute + ``C.t`` will be ``20``, and the class attributes ``C.x`` and + ``C.y`` will not be set. + +.. class:: Field + + :class:`Field` objects describe each defined field. These objects + are created internally, and are returned by the :func:`fields` + module-level method (see below). Users should never instantiate a + :class:`Field` object directly. Its documented attributes are: + + - ``name``: The name of the field. + + - ``type``: The type of the field. + + - ``default``, ``default_factory``, ``init``, ``repr``, ``hash``, + ``compare``, and ``metadata`` have the identical meaning and + values as they do in the :func:`field` declaration. + + Other attributes may exist, but they are private and must not be + inspected or relied on. + +.. function:: fields(class_or_instance) + + Returns a tuple of :class:`Field` objects + that define the fields for this Data Class. Accepts either a Data + Class, or an instance of a Data Class. Raises :exc:`ValueError` if + not passed a Data Class or instance of one. Does not return + pseudo-fields which are ``ClassVar`` or ``InitVar``. + +.. function:: asdict(instance, *, dict_factory=dict) + + Converts the Data Class ``instance`` to a dict (by using the + factory function ``dict_factory``). Each Data Class is converted + to a dict of its fields, as ``name: value`` pairs. Data Classes, dicts, + lists, and tuples are recursed into. For example:: + + @dataclass + class Point: + x: int + y: int + + @dataclass + class C: + l: List[Point] + + p = Point(10, 20) + assert asdict(p) == {'x': 10, 'y': 20} + + c = C([Point(0, 0), Point(10, 4)]) + assert asdict(c) == {'l': [{'x': 0, 'y': 0}, {'x': 10, 'y': 4}]} + + Raises :exc:`TypeError` if ``instance`` is not a Data Class instance. + +.. function:: astuple(*, tuple_factory=tuple) + + Converts the Data Class ``instance`` to a tuple (by using the + factory function ``tuple_factory``). Each Data Class is converted + to a tuple of its field values. Data Classes, dicts, lists, and + tuples are recursed into. + + Continuing from the previous example:: + + assert astuple(p) == (10, 20) + assert astuple(c) == ([(0, 0), (10, 4)],) + + Raises :exc:`TypeError` if ``instance`` is not a Data Class instance. + +.. function:: make_dataclass(cls_name, fields, *, bases=(), namespace=None, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False) + + Creates a new Data Class with name ``cls_name``, fields as defined + in ``fields``, base classes as given in ``bases``, and initialized + with a namespace as given in ``namespace``. ``fields`` is an + iterable whose elements are each either ``name``, ``(name, type)``, + or ``(name, type, Field)``. If just ``name`` is supplied, + ``typing.Any`` is used for ``type``. The values of ``init``, + ``repr``, ``eq``, ``order``, ``unsafe_hash``, and ``frozen`` have + the same meaning as they do in :func:`dataclass`. + + This function is not strictly required, because any Python + mechanism for creating a new class with ``__annotations__`` can + then apply the :func:`dataclass` function to convert that class to + a Data Class. This function is provided as a convenience. For + example:: + + C = make_dataclass('C', + [('x', int), + 'y', + ('z', int, field(default=5))], + namespace={'add_one': lambda self: self.x + 1}) + + Is equivalent to:: + + @dataclass + class C: + x: int + y: 'typing.Any' + z: int = 5 + + def add_one(self): + return self.x + 1 + +.. function:: replace(instance, **changes) + + Creates a new object of the same type of ``instance``, replacing + fields with values from ``changes``. If ``instance`` is not a Data + Class, raises :exc:`TypeError`. If values in ``changes`` do not + specify fields, raises :exc:`TypeError`. + + The newly returned object is created by calling the :meth:`__init__` + method of the Data Class. This ensures that + :meth:`__post_init__`, if present, is also called. + + Init-only variables without default values, if any exist, must be + specified on the call to :func:`replace` so that they can be passed to + :meth:`__init__` and :meth:`__post_init__`. + + It is an error for :func:`changes` to contain any fields that are + defined as having ``init=False``. A :exc:`ValueError` will be raised + in this case. + + Be forewarned about how ``init=False`` fields work during a call to + :func:`replace`. They are not copied from the source object, but + rather are initialized in :meth:`__post_init__`, if they're + initialized at all. It is expected that ``init=False`` fields will + be rarely and judiciously used. If they are used, it might be wise + to have alternate class constructors, or perhaps a custom + ``replace()`` (or similarly named) method which handles instance + copying. + +.. function:: is_dataclass(class_or_instance) + + Returns True if its parameter is a dataclass or an instance of one, + otherwise returns False. + + If you need to know if a class is an instance of a dataclass (and + not a dataclass itself), then add a further check for ``not + isinstance(obj, type)``:: + + def is_dataclass_instance(obj): + return is_dataclass(obj) and not isinstance(obj, type) + +Post-init processing +-------------------- + +The generated :meth:`__init__` code will call a method named +:meth:`__post_init__`, if :meth:`__post_init__` is defined on the +class. It will normally be called as ``self.__post_init__()``. +However, if any ``InitVar`` fields are defined, they will also be +passed to :meth:`__post_init` in the order they were defined in the +class. If no :meth:`__init__` method is generated, then +:meth:`__post_init__` will not automatically be called. + +Among other uses, this allows for initializing field values that +depend on one or more other fields. For example:: + + @dataclass + class C: + a: float + b: float + c: float = field(init=False) + + def __post_init__(self): + self.c = self.a + self.b + +See the section below on init-only variables for ways to pass +parameters to :meth:`__post_init__`. Also see the warning about how +:func:`replace` handles ``init=False`` fields. + +Class variables +--------------- + +One of two places where :func:`dataclass` actually inspects the type +of a field is to determine if a field is a class variable as defined +in :pep:`526`. It does this by checking if the type of the field is +``typing.ClassVar``. If a field is a ``ClassVar``, it is excluded +from consideration as a field and is ignored by the Data Class +mechanisms. Such ``ClassVar`` pseudo-fields are not returned by the +module-level :func:`fields` function. + +Init-only variables +------------------- + +The other place where :func:`dataclass` inspects a type annotation is to +determine if a field is an init-only variable. It does this by seeing +if the type of a field is of type ``dataclasses.InitVar``. If a field +is an ``InitVar``, it is considered a pseudo-field called an init-only +field. As it is not a true field, it is not returned by the +module-level :func:`fields` function. Init-only fields are added as +parameters to the generated :meth:`__init__` method, and are passed to +the optional :meth:`__post_init__` method. They are not otherwise used +by Data Classes. + +For example, suppose a field will be initialzed from a database, if a +value is not provided when creating the class:: + + @dataclass + class C: + i: int + j: int = None + database: InitVar[DatabaseType] = None + + def __post_init__(self, database): + if self.j is None and database is not None: + self.j = database.lookup('j') + + c = C(10, database=my_database) + +In this case, :func:`fields` will return :class:`Field` objects for ``i`` and +``j``, but not for ``database``. + +Frozen instances +---------------- + +It is not possible to create truly immutable Python objects. However, +by passing ``frozen=True`` to the :meth:`dataclass` decorator you can +emulate immutability. In that case, Data Classes will add +:meth:`__setattr__` and :meth:`__delattr__` methods to the class. These +methods will raise a :exc:`FrozenInstanceError` when invoked. + +There is a tiny performance penalty when using ``frozen=True``: +:meth:`__init__` cannot use simple assignment to initialize fields, and +must use :meth:`object.__setattr__`. + +Inheritance +----------- + +When the Data Class is being created by the :meth:`dataclass` decorator, +it looks through all of the class's base classes in reverse MRO (that +is, starting at :class:`object`) and, for each Data Class that it finds, +adds the fields from that base class to an ordered mapping of fields. +After all of the base class fields are added, it adds its own fields +to the ordered mapping. All of the generated methods will use this +combined, calculated ordered mapping of fields. Because the fields +are in insertion order, derived classes override base classes. An +example:: + + @dataclass + class Base: + x: Any = 15.0 + y: int = 0 + + @dataclass + class C(Base): + z: int = 10 + x: int = 15 + +The final list of fields is, in order, ``x``, ``y``, ``z``. The final +type of ``x`` is ``int``, as specified in class ``C``. + +The generated :meth:`__init__` method for ``C`` will look like:: + + def __init__(self, x: int = 15, y: int = 0, z: int = 10): + +Default factory functions +------------------------- + + If a :func:`field` specifies a ``default_factory``, it is called with + zero arguments when a default value for the field is needed. For + example, to create a new instance of a list, use:: + + l: list = field(default_factory=list) + + If a field is excluded from :meth:`__init__` (using ``init=False``) + and the field also specifies ``default_factory``, then the default + factory function will always be called from the generated + :meth:`__init__` function. This happens because there is no other + way to give the field an initial value. + +Mutable default values +---------------------- + + Python stores default member variable values in class attributes. + Consider this example, not using Data Classes:: + + class C: + x = [] + def add(self, element): + self.x += element + + o1 = C() + o2 = C() + o1.add(1) + o2.add(2) + assert o1.x == [1, 2] + assert o1.x is o2.x + + Note that the two instances of class ``C`` share the same class + variable ``x``, as expected. + + Using Data Classes, *if* this code was valid:: + + @dataclass + class D: + x: List = [] + def add(self, element): + self.x += element + + it would generate code similar to:: + + class D: + x = [] + def __init__(self, x=x): + self.x = x + def add(self, element): + self.x += element + + assert D().x is D().x + + This has the same issue as the original example using class ``C``. + That is, two instances of class ``D`` that do not specify a value for + ``x`` when creating a class instance will share the same copy of + ``x``. Because Data Classes just use normal Python class creation + they also share this problem. There is no general way for Data + Classes to detect this condition. Instead, Data Classes will raise a + :exc:`TypeError` if it detects a default parameter of type ``list``, + ``dict``, or ``set``. This is a partial solution, but it does protect + against many common errors. + + Using default factory functions is a way to create new instances of + mutable types as default values for fields:: + + @dataclass + class D: + x: list = field(default_factory=list) + + assert D().x is not D().x diff --git a/Doc/library/python.rst b/Doc/library/python.rst index 440dc6632b83..f39613f57288 100644 --- a/Doc/library/python.rst +++ b/Doc/library/python.rst @@ -16,6 +16,7 @@ overview: builtins.rst __main__.rst warnings.rst + dataclasses.rst contextlib.rst abc.rst atexit.rst From webhook-mailer at python.org Wed May 16 05:17:28 2018 From: webhook-mailer at python.org (Berker Peksag) Date: Wed, 16 May 2018 09:17:28 -0000 Subject: [Python-checkins] bpo-32384: Skip test when _testcapi isn't available (GH-4940) Message-ID: <mailman.76.1526462250.2757.python-checkins@python.org> https://github.com/python/cpython/commit/5e8c52680450b67a116d3d555db8416c40576fdb commit: 5e8c52680450b67a116d3d555db8416c40576fdb branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Berker Peksag <berker.peksag at gmail.com> date: 2018-05-16T12:17:25+03:00 summary: bpo-32384: Skip test when _testcapi isn't available (GH-4940) (cherry picked from commit 4cc3eb48e1e8289df5153db1c701cae263a1ef86) Co-authored-by: Isaiah Peng <isaiah at users.noreply.github.com> files: M Lib/test/test_generators.py diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py index d9ceeb54038c..67c2a6de4657 100644 --- a/Lib/test/test_generators.py +++ b/Lib/test/test_generators.py @@ -10,12 +10,18 @@ from test import support -_testcapi = support.import_module('_testcapi') +try: + import _testcapi +except ImportError: + _testcapi = None # This tests to make sure that if a SIGINT arrives just before we send into a # yield from chain, the KeyboardInterrupt is raised in the innermost # generator (see bpo-30039). + at unittest.skipUnless(_testcapi is not None and + hasattr(_testcapi, "raise_SIGINT_then_send_None"), + "needs _testcapi.raise_SIGINT_then_send_None") class SignalAndYieldFromTest(unittest.TestCase): def generator1(self): From solipsis at pitrou.net Wed May 16 05:24:52 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 16 May 2018 09:24:52 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=4 Message-ID: <20180516092452.1.93BD5001B167A8CE@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_collections leaked [0, 7, -7] memory blocks, sum=0 test_functools leaked [0, 3, 1] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogcOQA4L', '--timeout', '7200'] From webhook-mailer at python.org Wed May 16 05:49:33 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 16 May 2018 09:49:33 -0000 Subject: [Python-checkins] Reflow dataclasses comments (GH-6893) Message-ID: <mailman.77.1526464174.2757.python-checkins@python.org> https://github.com/python/cpython/commit/8d486fb93aad343dbcf6075ed95e68845d9ca09b commit: 8d486fb93aad343dbcf6075ed95e68845d9ca09b branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-16T02:49:29-07:00 summary: Reflow dataclasses comments (GH-6893) To be more consistent with other code (and so people stop hassling me!), reflow the dataclasses comments to not use a single space indentation when continuing a paragraph of text. (cherry picked from commit f8e7549490d61c92b34bf2de3e03ba2f7b0ac6e1) Co-authored-by: Eric V. Smith <ericvsmith at users.noreply.github.com> files: M Lib/dataclasses.py diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index c93aadc95e0a..480c6f74165b 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -21,12 +21,12 @@ ] # Conditions for adding methods. The boxes indicate what action the -# dataclass decorator takes. For all of these tables, when I talk -# about init=, repr=, eq=, order=, unsafe_hash=, or frozen=, I'm -# referring to the arguments to the @dataclass decorator. When -# checking if a dunder method already exists, I mean check for an -# entry in the class's __dict__. I never check to see if an -# attribute is defined in a base class. +# dataclass decorator takes. For all of these tables, when I talk +# about init=, repr=, eq=, order=, unsafe_hash=, or frozen=, I'm +# referring to the arguments to the @dataclass decorator. When +# checking if a dunder method already exists, I mean check for an +# entry in the class's __dict__. I never check to see if an attribute +# is defined in a base class. # Key: # +=========+=========================================+ @@ -79,7 +79,7 @@ # | True | add | raise | # +=======+=======+=======+ # Raise because not adding these methods would break the "frozen-ness" -# of the class. +# of the class. # __eq__ # @@ -108,7 +108,7 @@ # | True | add | raise | # +=======+=======+=======+ # Raise because to allow this case would interfere with using -# functools.total_ordering. +# functools.total_ordering. # __hash__ @@ -136,34 +136,35 @@ # | True | True | True | add | raise | Frozen, so hashable # +=======+=======+=======+========+========+ # For boxes that are blank, __hash__ is untouched and therefore -# inherited from the base class. If the base is object, then -# id-based hashing is used. +# inherited from the base class. If the base is object, then +# id-based hashing is used. +# # Note that a class may already have __hash__=None if it specified an -# __eq__ method in the class body (not one that was created by -# @dataclass). +# __eq__ method in the class body (not one that was created by +# @dataclass). +# # See _hash_action (below) for a coded version of this table. # Raised when an attempt is made to modify a frozen class. class FrozenInstanceError(AttributeError): pass -# A sentinel object for default values to signal that a -# default factory will be used. -# This is given a nice repr() which will appear in the function -# signature of dataclasses' constructors. +# A sentinel object for default values to signal that a default +# factory will be used. This is given a nice repr() which will appear +# in the function signature of dataclasses' constructors. class _HAS_DEFAULT_FACTORY_CLASS: def __repr__(self): return '<factory>' _HAS_DEFAULT_FACTORY = _HAS_DEFAULT_FACTORY_CLASS() # A sentinel object to detect if a parameter is supplied or not. Use -# a class to give it a better repr. +# a class to give it a better repr. class _MISSING_TYPE: pass MISSING = _MISSING_TYPE() # Since most per-field metadata will be unused, create an empty -# read-only proxy that can be shared among all fields. +# read-only proxy that can be shared among all fields. _EMPTY_METADATA = types.MappingProxyType({}) # Markers for the various kinds of fields and pseudo-fields. @@ -177,7 +178,7 @@ def __repr__(self): _FIELD_INITVAR = _FIELD_BASE('_FIELD_INITVAR') # The name of an attribute on the class where we store the Field -# objects. Also used to check if a class is a Data Class. +# objects. Also used to check if a class is a Data Class. _FIELDS = '__dataclass_fields__' # The name of an attribute on the class that stores the parameters to @@ -202,13 +203,15 @@ class InitVar(metaclass=_InitVarMeta): # Instances of Field are only ever created from within this module, -# and only from the field() function, although Field instances are -# exposed externally as (conceptually) read-only objects. -# name and type are filled in after the fact, not in __init__. They're -# not known at the time this class is instantiated, but it's -# convenient if they're available later. +# and only from the field() function, although Field instances are +# exposed externally as (conceptually) read-only objects. +# +# name and type are filled in after the fact, not in __init__. +# They're not known at the time this class is instantiated, but it's +# convenient if they're available later. +# # When cls._FIELDS is filled in with a list of Field objects, the name -# and type fields will have been populated. +# and type fields will have been populated. class Field: __slots__ = ('name', 'type', @@ -252,17 +255,18 @@ def __repr__(self): ')') # This is used to support the PEP 487 __set_name__ protocol in the - # case where we're using a field that contains a descriptor as a - # defaul value. For details on __set_name__, see - # https://www.python.org/dev/peps/pep-0487/#implementation-details. - # Note that in _process_class, this Field object is overwritten with - # the default value, so the end result is a descriptor that had - # __set_name__ called on it at the right time. + # case where we're using a field that contains a descriptor as a + # defaul value. For details on __set_name__, see + # https://www.python.org/dev/peps/pep-0487/#implementation-details. + # + # Note that in _process_class, this Field object is overwritten + # with the default value, so the end result is a descriptor that + # had __set_name__ called on it at the right time. def __set_name__(self, owner, name): func = getattr(type(self.default), '__set_name__', None) if func: - # There is a __set_name__ method on the descriptor, - # call it. + # There is a __set_name__ method on the descriptor, call + # it. func(self.default, owner, name) @@ -295,20 +299,20 @@ def __repr__(self): # This function is used instead of exposing Field creation directly, -# so that a type checker can be told (via overloads) that this is a -# function whose type depends on its parameters. +# so that a type checker can be told (via overloads) that this is a +# function whose type depends on its parameters. def field(*, default=MISSING, default_factory=MISSING, init=True, repr=True, hash=None, compare=True, metadata=None): """Return an object to identify dataclass fields. - default is the default value of the field. default_factory is a - 0-argument function called to initialize a field's value. If init + default is the default value of the field. default_factory is a + 0-argument function called to initialize a field's value. If init is True, the field will be a parameter to the class's __init__() - function. If repr is True, the field will be included in the - object's repr(). If hash is True, the field will be included in - the object's hash(). If compare is True, the field will be used in - comparison functions. metadata, if specified, must be a mapping - which is stored but not otherwise examined by dataclass. + function. If repr is True, the field will be included in the + object's repr(). If hash is True, the field will be included in + the object's hash(). If compare is True, the field will be used + in comparison functions. metadata, if specified, must be a + mapping which is stored but not otherwise examined by dataclass. It is an error to specify both default and default_factory. """ @@ -321,8 +325,8 @@ def field(*, default=MISSING, default_factory=MISSING, init=True, repr=True, def _tuple_str(obj_name, fields): # Return a string representing each field of obj_name as a tuple - # member. So, if fields is ['x', 'y'] and obj_name is "self", - # return "(self.x,self.y)". + # member. So, if fields is ['x', 'y'] and obj_name is "self", + # return "(self.x,self.y)". # Special case for the 0-tuple. if not fields: @@ -333,9 +337,9 @@ def _tuple_str(obj_name, fields): def _create_fn(name, args, body, *, globals=None, locals=None, return_type=MISSING): - # Note that we mutate locals when exec() is called. Caller beware! - # The only callers are internal to this module, so no worries - # about external callers. + # Note that we mutate locals when exec() is called. Caller + # beware! The only callers are internal to this module, so no + # worries about external callers. if locals is None: locals = {} return_annotation = '' @@ -354,10 +358,11 @@ def _create_fn(name, args, body, *, globals=None, locals=None, def _field_assign(frozen, name, value, self_name): # If we're a frozen class, then assign to our fields in __init__ - # via object.__setattr__. Otherwise, just use a simple - # assignment. + # via object.__setattr__. Otherwise, just use a simple + # assignment. + # # self_name is what "self" is called in this function: don't - # hard-code "self", since that might be a field name. + # hard-code "self", since that might be a field name. if frozen: return f'object.__setattr__({self_name},{name!r},{value})' return f'{self_name}.{name}={value}' @@ -365,31 +370,31 @@ def _field_assign(frozen, name, value, self_name): def _field_init(f, frozen, globals, self_name): # Return the text of the line in the body of __init__ that will - # initialize this field. + # initialize this field. default_name = f'_dflt_{f.name}' if f.default_factory is not MISSING: if f.init: # This field has a default factory. If a parameter is - # given, use it. If not, call the factory. + # given, use it. If not, call the factory. globals[default_name] = f.default_factory value = (f'{default_name}() ' f'if {f.name} is _HAS_DEFAULT_FACTORY ' f'else {f.name}') else: # This is a field that's not in the __init__ params, but - # has a default factory function. It needs to be - # initialized here by calling the factory function, - # because there's no other way to initialize it. + # has a default factory function. It needs to be + # initialized here by calling the factory function, + # because there's no other way to initialize it. # For a field initialized with a default=defaultvalue, the - # class dict just has the default value - # (cls.fieldname=defaultvalue). But that won't work for a - # default factory, the factory must be called in __init__ - # and we must assign that to self.fieldname. We can't - # fall back to the class dict's value, both because it's - # not set, and because it might be different per-class - # (which, after all, is why we have a factory function!). + # class dict just has the default value + # (cls.fieldname=defaultvalue). But that won't work for a + # default factory, the factory must be called in __init__ + # and we must assign that to self.fieldname. We can't + # fall back to the class dict's value, both because it's + # not set, and because it might be different per-class + # (which, after all, is why we have a factory function!). globals[default_name] = f.default_factory value = f'{default_name}()' @@ -403,13 +408,13 @@ def _field_init(f, frozen, globals, self_name): globals[default_name] = f.default value = f.name else: - # This field does not need initialization. Signify that to - # the caller by returning None. + # This field does not need initialization. Signify that + # to the caller by returning None. return None # Only test this now, so that we can create variables for the - # default. However, return None to signify that we're not going - # to actually do the assignment statement for InitVars. + # default. However, return None to signify that we're not going + # to actually do the assignment statement for InitVars. if f._field_type == _FIELD_INITVAR: return None @@ -418,19 +423,20 @@ def _field_init(f, frozen, globals, self_name): def _init_param(f): - # Return the __init__ parameter string for this field. - # For example, the equivalent of 'x:int=3' (except instead of 'int', - # reference a variable set to int, and instead of '3', reference a - # variable set to 3). + # Return the __init__ parameter string for this field. For + # example, the equivalent of 'x:int=3' (except instead of 'int', + # reference a variable set to int, and instead of '3', reference a + # variable set to 3). if f.default is MISSING and f.default_factory is MISSING: - # There's no default, and no default_factory, just - # output the variable name and type. + # There's no default, and no default_factory, just output the + # variable name and type. default = '' elif f.default is not MISSING: - # There's a default, this will be the name that's used to look it up. + # There's a default, this will be the name that's used to look + # it up. default = f'=_dflt_{f.name}' elif f.default_factory is not MISSING: - # There's a factory function. Set a marker. + # There's a factory function. Set a marker. default = '=_HAS_DEFAULT_FACTORY' return f'{f.name}:_type_{f.name}{default}' @@ -439,10 +445,10 @@ def _init_fn(fields, frozen, has_post_init, self_name): # fields contains both real fields and InitVar pseudo-fields. # Make sure we don't have fields without defaults following fields - # with defaults. This actually would be caught when exec-ing the - # function source code, but catching it here gives a better error - # message, and future-proofs us in case we build up the function - # using ast. + # with defaults. This actually would be caught when exec-ing the + # function source code, but catching it here gives a better error + # message, and future-proofs us in case we build up the function + # using ast. seen_default = False for f in fields: # Only consider fields in the __init__ call. @@ -460,7 +466,7 @@ def _init_fn(fields, frozen, has_post_init, self_name): for f in fields: line = _field_init(f, frozen, globals, self_name) # line is None means that this field doesn't require - # initialization (it's a pseudo-field). Just skip it. + # initialization (it's a pseudo-field). Just skip it. if line: body_lines.append(line) @@ -493,8 +499,8 @@ def _repr_fn(fields): def _frozen_get_del_attr(cls, fields): - # XXX: globals is modified on the first call to _create_fn, then the - # modified version is used in the second call. Is this okay? + # XXX: globals is modified on the first call to _create_fn, then + # the modified version is used in the second call. Is this okay? globals = {'cls': cls, 'FrozenInstanceError': FrozenInstanceError} if fields: @@ -519,9 +525,9 @@ def _frozen_get_del_attr(cls, fields): def _cmp_fn(name, op, self_tuple, other_tuple): # Create a comparison function. If the fields in the object are - # named 'x' and 'y', then self_tuple is the string - # '(self.x,self.y)' and other_tuple is the string - # '(other.x,other.y)'. + # named 'x' and 'y', then self_tuple is the string + # '(self.x,self.y)' and other_tuple is the string + # '(other.x,other.y)'. return _create_fn(name, ('self', 'other'), @@ -540,7 +546,7 @@ def _hash_fn(fields): def _is_classvar(a_type, typing): if typing: # This test uses a typing internal class, but it's the best - # way to test if this is a ClassVar. + # way to test if this is a ClassVar. return (a_type is typing.ClassVar or (type(a_type) is typing._GenericAlias and a_type.__origin__ is typing.ClassVar)) @@ -573,25 +579,25 @@ def _is_type(annotation, cls, a_module, a_type, is_type_predicate): # instead only a module (global) lookup), there are some things it # gets wrong. - # With string annotations, this will work: + # With string annotations, cv0 will be detected as a ClassVar: # CV = ClassVar # @dataclass # class C0: # cv0: CV - # But this will not: + # But in this example cv1 will not be detected as a ClassVar: # @dataclass # class C1: # CV = ClassVar # cv1: CV - # In C1, the code in this function will look up "CV" in the module - # and not find it, so it will not consider cv1 as a ClassVar. - # This is a fairly obscure corner case, and the best way to fix it - # would be to eval() the string "CV" with the correct global and - # local namespaces. However that would involve a eval() penalty - # for every single field of every dataclass that's defined. It - # was judged not worth it. + # In C1, the code in this function (_is_type) will look up "CV" in + # the module and not find it, so it will not consider cv1 as a + # ClassVar. This is a fairly obscure corner case, and the best + # way to fix it would be to eval() the string "CV" with the + # correct global and local namespaces. However that would involve + # a eval() penalty for every single field of every dataclass + # that's defined. It was judged not worth it. match = _MODULE_IDENTIFIER_RE.match(annotation) if match: @@ -613,11 +619,11 @@ def _is_type(annotation, cls, a_module, a_type, is_type_predicate): def _get_field(cls, a_name, a_type): # Return a Field object for this field name and type. ClassVars - # and InitVars are also returned, but marked as such (see - # f._field_type). + # and InitVars are also returned, but marked as such (see + # f._field_type). - # If the default value isn't derived from Field, then it's - # only a normal default value. Convert it to a Field(). + # If the default value isn't derived from Field, then it's only a + # normal default value. Convert it to a Field(). default = getattr(cls, a_name, MISSING) if isinstance(default, Field): f = default @@ -627,33 +633,31 @@ def _get_field(cls, a_name, a_type): default = MISSING f = field(default=default) - # Only at this point do we know the name and the type. Set them. + # Only at this point do we know the name and the type. Set them. f.name = a_name f.type = a_type # Assume it's a normal field until proven otherwise. We're next - # going to decide if it's a ClassVar or InitVar, everything else - # is just a normal field. + # going to decide if it's a ClassVar or InitVar, everything else + # is just a normal field. f._field_type = _FIELD # In addition to checking for actual types here, also check for - # string annotations. get_type_hints() won't always work for us - # (see https://github.com/python/typing/issues/508 for example), - # plus it's expensive and would require an eval for every stirng - # annotation. So, make a best effort to see if this is a - # ClassVar or InitVar using regex's and checking that the thing - # referenced is actually of the correct type. + # string annotations. get_type_hints() won't always work for us + # (see https://github.com/python/typing/issues/508 for example), + # plus it's expensive and would require an eval for every stirng + # annotation. So, make a best effort to see if this is a ClassVar + # or InitVar using regex's and checking that the thing referenced + # is actually of the correct type. # For the complete discussion, see https://bugs.python.org/issue33453 # If typing has not been imported, then it's impossible for any - # annotation to be a ClassVar. So, only look for ClassVar if - # typing has been imported by any module (not necessarily cls's - # module). + # annotation to be a ClassVar. So, only look for ClassVar if + # typing has been imported by any module (not necessarily cls's + # module). typing = sys.modules.get('typing') if typing: - # This test uses a typing internal class, but it's the best - # way to test if this is a ClassVar. if (_is_classvar(a_type, typing) or (isinstance(f.type, str) and _is_type(f.type, cls, typing, typing.ClassVar, @@ -682,10 +686,10 @@ def _get_field(cls, a_name, a_type): raise TypeError(f'field {f.name} cannot have a ' 'default factory') # Should I check for other field settings? default_factory - # seems the most serious to check for. Maybe add others. - # For example, how about init=False (or really, - # init=<not-the-default-init-value>)? It makes no sense for - # ClassVar and InitVar to specify init=<anything>. + # seems the most serious to check for. Maybe add others. For + # example, how about init=False (or really, + # init=<not-the-default-init-value>)? It makes no sense for + # ClassVar and InitVar to specify init=<anything>. # For real fields, disallow mutable defaults for known types. if f._field_type is _FIELD and isinstance(f.default, (list, dict, set)): @@ -697,7 +701,7 @@ def _get_field(cls, a_name, a_type): def _set_new_attribute(cls, name, value): # Never overwrites an existing attribute. Returns True if the - # attribute already exists. + # attribute already exists. if name in cls.__dict__: return True setattr(cls, name, value) @@ -705,9 +709,9 @@ def _set_new_attribute(cls, name, value): # Decide if/how we're going to create a hash function. Key is -# (unsafe_hash, eq, frozen, does-hash-exist). Value is the action to -# take. The common case is to do nothing, so instead of providing a -# function that is a no-op, use None to signify that. +# (unsafe_hash, eq, frozen, does-hash-exist). Value is the action to +# take. The common case is to do nothing, so instead of providing a +# function that is a no-op, use None to signify that. def _hash_set_none(cls, fields): return None @@ -748,28 +752,28 @@ def _hash_exception(cls, fields): (True, True, True, True ): _hash_exception, } # See https://bugs.python.org/issue32929#msg312829 for an if-statement -# version of this table. +# version of this table. def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen): # Now that dicts retain insertion order, there's no reason to use - # an ordered dict. I am leveraging that ordering here, because - # derived class fields overwrite base class fields, but the order - # is defined by the base class, which is found first. + # an ordered dict. I am leveraging that ordering here, because + # derived class fields overwrite base class fields, but the order + # is defined by the base class, which is found first. fields = {} setattr(cls, _PARAMS, _DataclassParams(init, repr, eq, order, unsafe_hash, frozen)) # Find our base classes in reverse MRO order, and exclude - # ourselves. In reversed order so that more derived classes - # override earlier field definitions in base classes. - # As long as we're iterating over them, see if any are frozen. + # ourselves. In reversed order so that more derived classes + # override earlier field definitions in base classes. As long as + # we're iterating over them, see if any are frozen. any_frozen_base = False has_dataclass_bases = False for b in cls.__mro__[-1:0:-1]: # Only process classes that have been processed by our - # decorator. That is, they have a _FIELDS attribute. + # decorator. That is, they have a _FIELDS attribute. base_fields = getattr(b, _FIELDS, None) if base_fields: has_dataclass_bases = True @@ -779,38 +783,39 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen): any_frozen_base = True # Annotations that are defined in this class (not in base - # classes). If __annotations__ isn't present, then this class - # adds no new annotations. We use this to compute fields that - # are added by this class. + # classes). If __annotations__ isn't present, then this class + # adds no new annotations. We use this to compute fields that are + # added by this class. + # # Fields are found from cls_annotations, which is guaranteed to be - # ordered. Default values are from class attributes, if a field - # has a default. If the default value is a Field(), then it - # contains additional info beyond (and possibly including) the - # actual default value. Pseudo-fields ClassVars and InitVars are - # included, despite the fact that they're not real fields. - # That's dealt with later. + # ordered. Default values are from class attributes, if a field + # has a default. If the default value is a Field(), then it + # contains additional info beyond (and possibly including) the + # actual default value. Pseudo-fields ClassVars and InitVars are + # included, despite the fact that they're not real fields. That's + # dealt with later. cls_annotations = cls.__dict__.get('__annotations__', {}) # Now find fields in our class. While doing so, validate some - # things, and set the default values (as class attributes) - # where we can. + # things, and set the default values (as class attributes) where + # we can. cls_fields = [_get_field(cls, name, type) for name, type in cls_annotations.items()] for f in cls_fields: fields[f.name] = f - # If the class attribute (which is the default value for - # this field) exists and is of type 'Field', replace it - # with the real default. This is so that normal class - # introspection sees a real default value, not a Field. + # If the class attribute (which is the default value for this + # field) exists and is of type 'Field', replace it with the + # real default. This is so that normal class introspection + # sees a real default value, not a Field. if isinstance(getattr(cls, f.name, None), Field): if f.default is MISSING: # If there's no default, delete the class attribute. - # This happens if we specify field(repr=False), for - # example (that is, we specified a field object, but - # no default value). Also if we're using a default - # factory. The class attribute should not be set at - # all in the post-processed class. + # This happens if we specify field(repr=False), for + # example (that is, we specified a field object, but + # no default value). Also if we're using a default + # factory. The class attribute should not be set at + # all in the post-processed class. delattr(cls, f.name) else: setattr(cls, f.name, f.default) @@ -832,21 +837,21 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen): raise TypeError('cannot inherit frozen dataclass from a ' 'non-frozen one') - # Remember all of the fields on our class (including bases). This also - # marks this class as being a dataclass. + # Remember all of the fields on our class (including bases). This + # also marks this class as being a dataclass. setattr(cls, _FIELDS, fields) # Was this class defined with an explicit __hash__? Note that if - # __eq__ is defined in this class, then python will automatically - # set __hash__ to None. This is a heuristic, as it's possible - # that such a __hash__ == None was not auto-generated, but it - # close enough. + # __eq__ is defined in this class, then python will automatically + # set __hash__ to None. This is a heuristic, as it's possible + # that such a __hash__ == None was not auto-generated, but it + # close enough. class_hash = cls.__dict__.get('__hash__', MISSING) has_explicit_hash = not (class_hash is MISSING or (class_hash is None and '__eq__' in cls.__dict__)) - # If we're generating ordering methods, we must be generating - # the eq methods. + # If we're generating ordering methods, we must be generating the + # eq methods. if order and not eq: raise ValueError('eq must be true if order is true') @@ -861,14 +866,15 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen): _init_fn(flds, frozen, has_post_init, - # The name to use for the "self" param - # in __init__. Use "self" if possible. + # The name to use for the "self" + # param in __init__. Use "self" + # if possible. '__dataclass_self__' if 'self' in fields else 'self', )) # Get the fields as a list, and include only real fields. This is - # used in all of the following methods. + # used in all of the following methods. field_list = [f for f in fields.values() if f._field_type is _FIELD] if repr: @@ -877,7 +883,7 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen): if eq: # Create _eq__ method. There's no need for a __ne__ method, - # since python will call __eq__ and negate it. + # since python will call __eq__ and negate it. flds = [f for f in field_list if f.compare] self_tuple = _tuple_str('self', flds) other_tuple = _tuple_str('other', flds) @@ -914,7 +920,7 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen): has_explicit_hash] if hash_action: # No need to call _set_new_attribute here, since by the time - # we're here the overwriting is unconditional. + # we're here the overwriting is unconditional. cls.__hash__ = hash_action(cls, field_list) if not getattr(cls, '__doc__'): @@ -926,8 +932,8 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen): # _cls should never be specified by keyword, so start it with an -# underscore. The presence of _cls is used to detect if this -# decorator is being called with parameters or not. +# underscore. The presence of _cls is used to detect if this +# decorator is being called with parameters or not. def dataclass(_cls=None, *, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False): """Returns the same class as was passed in, with dunder methods @@ -968,7 +974,7 @@ def fields(class_or_instance): raise TypeError('must be called with a dataclass type or instance') # Exclude pseudo-fields. Note that fields is sorted by insertion - # order, so the order of the tuple is as the fields were defined. + # order, so the order of the tuple is as the fields were defined. return tuple(f for f in fields.values() if f._field_type is _FIELD) @@ -1130,8 +1136,8 @@ class C: assert c1.x == 3 and c1.y == 2 """ - # We're going to mutate 'changes', but that's okay because it's a new - # dict, even if called with 'replace(obj, **my_changes)'. + # We're going to mutate 'changes', but that's okay because it's a + # new dict, even if called with 'replace(obj, **my_changes)'. if not _is_dataclass_instance(obj): raise TypeError("replace() should be called on dataclass instances") @@ -1152,8 +1158,8 @@ class C: changes[f.name] = getattr(obj, f.name) # Create the new object, which calls __init__() and - # __post_init__() (if defined), using all of the init fields - # we've added and/or left in 'changes'. If there are values - # supplied in changes that aren't fields, this will correctly - # raise a TypeError. + # __post_init__() (if defined), using all of the init fields we've + # added and/or left in 'changes'. If there are values supplied in + # changes that aren't fields, this will correctly raise a + # TypeError. return obj.__class__(**changes) From webhook-mailer at python.org Wed May 16 07:24:11 2018 From: webhook-mailer at python.org (Eric V. Smith) Date: Wed, 16 May 2018 11:24:11 -0000 Subject: [Python-checkins] bpo-33534: Remove unneeded test. (GH-6897) Message-ID: <mailman.78.1526469852.2757.python-checkins@python.org> https://github.com/python/cpython/commit/9285835a05ad0319acef111340266c0f85ed549c commit: 9285835a05ad0319acef111340266c0f85ed549c branch: master author: Eric V. Smith <ericvsmith at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-16T07:24:00-04:00 summary: bpo-33534: Remove unneeded test. (GH-6897) This condition as already tested before this code is called. files: M Lib/dataclasses.py diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index 480c6f74165b..bb77d3b4052b 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -544,12 +544,11 @@ def _hash_fn(fields): def _is_classvar(a_type, typing): - if typing: - # This test uses a typing internal class, but it's the best - # way to test if this is a ClassVar. - return (a_type is typing.ClassVar - or (type(a_type) is typing._GenericAlias - and a_type.__origin__ is typing.ClassVar)) + # This test uses a typing internal class, but it's the best way to + # test if this is a ClassVar. + return (a_type is typing.ClassVar + or (type(a_type) is typing._GenericAlias + and a_type.__origin__ is typing.ClassVar)) def _is_initvar(a_type, dataclasses): From webhook-mailer at python.org Wed May 16 07:46:40 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 16 May 2018 11:46:40 -0000 Subject: [Python-checkins] bpo-33534: Remove unneeded test. (GH-6897) Message-ID: <mailman.79.1526471201.2757.python-checkins@python.org> https://github.com/python/cpython/commit/8e20fc388f1f1e6b2b38bf11995322c274b4d43a commit: 8e20fc388f1f1e6b2b38bf11995322c274b4d43a branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-16T04:46:32-07:00 summary: bpo-33534: Remove unneeded test. (GH-6897) This condition as already tested before this code is called. (cherry picked from commit 9285835a05ad0319acef111340266c0f85ed549c) Co-authored-by: Eric V. Smith <ericvsmith at users.noreply.github.com> files: M Lib/dataclasses.py diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index 480c6f74165b..bb77d3b4052b 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -544,12 +544,11 @@ def _hash_fn(fields): def _is_classvar(a_type, typing): - if typing: - # This test uses a typing internal class, but it's the best - # way to test if this is a ClassVar. - return (a_type is typing.ClassVar - or (type(a_type) is typing._GenericAlias - and a_type.__origin__ is typing.ClassVar)) + # This test uses a typing internal class, but it's the best way to + # test if this is a ClassVar. + return (a_type is typing.ClassVar + or (type(a_type) is typing._GenericAlias + and a_type.__origin__ is typing.ClassVar)) def _is_initvar(a_type, dataclasses): From webhook-mailer at python.org Wed May 16 09:29:08 2018 From: webhook-mailer at python.org (Eric V. Smith) Date: Wed, 16 May 2018 13:29:08 -0000 Subject: [Python-checkins] Minor tweaks to dataclasses docs. (GH-6903) Message-ID: <mailman.80.1526477350.2757.python-checkins@python.org> https://github.com/python/cpython/commit/7a1c02750171d9895754da5d560700aaba93da56 commit: 7a1c02750171d9895754da5d560700aaba93da56 branch: master author: Eric V. Smith <ericvsmith at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-16T09:29:05-04:00 summary: Minor tweaks to dataclasses docs. (GH-6903) files: M Doc/library/dataclasses.rst diff --git a/Doc/library/dataclasses.rst b/Doc/library/dataclasses.rst index 489dece7ccf3..a90fcf78348a 100644 --- a/Doc/library/dataclasses.rst +++ b/Doc/library/dataclasses.rst @@ -1,8 +1,8 @@ -:mod:`dataclasses` --- Dataclasses -========================================== +:mod:`dataclasses` --- Data Classes +=================================== .. module:: dataclasses - :synopsis: Generate special methods and add to user-defined classes. + :synopsis: Generate special methods on user-defined classes. .. moduleauthor:: Eric V. Smith <eric at trueblade.com> .. sectionauthor:: Eric V. Smith <eric at trueblade.com> From webhook-mailer at python.org Wed May 16 09:48:02 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 16 May 2018 13:48:02 -0000 Subject: [Python-checkins] Minor tweaks to dataclasses docs. (GH-6903) Message-ID: <mailman.81.1526478483.2757.python-checkins@python.org> https://github.com/python/cpython/commit/81defcc92c8512d933547fdc65769c79065df533 commit: 81defcc92c8512d933547fdc65769c79065df533 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-16T06:47:59-07:00 summary: Minor tweaks to dataclasses docs. (GH-6903) (cherry picked from commit 7a1c02750171d9895754da5d560700aaba93da56) Co-authored-by: Eric V. Smith <ericvsmith at users.noreply.github.com> files: M Doc/library/dataclasses.rst diff --git a/Doc/library/dataclasses.rst b/Doc/library/dataclasses.rst index 489dece7ccf3..a90fcf78348a 100644 --- a/Doc/library/dataclasses.rst +++ b/Doc/library/dataclasses.rst @@ -1,8 +1,8 @@ -:mod:`dataclasses` --- Dataclasses -========================================== +:mod:`dataclasses` --- Data Classes +=================================== .. module:: dataclasses - :synopsis: Generate special methods and add to user-defined classes. + :synopsis: Generate special methods on user-defined classes. .. moduleauthor:: Eric V. Smith <eric at trueblade.com> .. sectionauthor:: Eric V. Smith <eric at trueblade.com> From webhook-mailer at python.org Wed May 16 10:05:49 2018 From: webhook-mailer at python.org (Petr Viktorin) Date: Wed, 16 May 2018 14:05:49 -0000 Subject: [Python-checkins] bpo-33503: Fix the broken pypi link in the source and the documentation (GH-6814) (GH-6872) Message-ID: <mailman.82.1526479551.2757.python-checkins@python.org> https://github.com/python/cpython/commit/51b2f6d3a3d6433b832f30d03382653f92a31cdf commit: 51b2f6d3a3d6433b832f30d03382653f92a31cdf branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Petr Viktorin <encukou at gmail.com> date: 2018-05-16T10:05:46-04:00 summary: bpo-33503: Fix the broken pypi link in the source and the documentation (GH-6814) (GH-6872) (cherry picked from commit 19177fbd5d6d9b29ccc302d65f9d9417ece082ce) Co-authored-by: St?phane Wirtel <stephane at wirtel.be> files: A Misc/NEWS.d/next/Documentation/2018-05-14-20-08-58.bpo-33503.Wvt0qg.rst M Doc/distributing/index.rst M Doc/distutils/apiref.rst M Doc/distutils/packageindex.rst M Doc/distutils/setupscript.rst M Doc/faq/general.rst M Doc/faq/library.rst M Doc/howto/curses.rst M Doc/howto/pyporting.rst M Doc/installing/index.rst M Doc/library/distribution.rst M Doc/library/index.rst M Doc/library/pprint.rst M Doc/library/re.rst M Doc/library/ssl.rst M Doc/library/unittest.mock.rst M Doc/library/xml.rst M Doc/tutorial/venv.rst M Doc/tutorial/whatnow.rst M Doc/using/windows.rst M Doc/whatsnew/2.3.rst M Doc/whatsnew/2.5.rst M Doc/whatsnew/2.7.rst M Doc/whatsnew/3.5.rst diff --git a/Doc/distributing/index.rst b/Doc/distributing/index.rst index aedbe712d3db..5dd14b1f7a60 100644 --- a/Doc/distributing/index.rst +++ b/Doc/distributing/index.rst @@ -31,7 +31,7 @@ installing other Python projects, refer to the Key terms ========= -* the `Python Packaging Index <https://pypi.python.org/pypi>`__ is a public +* the `Python Packaging Index <https://pypi.org>`__ is a public repository of open source licensed packages made available for use by other Python users * the `Python Packaging Authority diff --git a/Doc/distutils/apiref.rst b/Doc/distutils/apiref.rst index 9fce46ad2669..3c89468220a4 100644 --- a/Doc/distutils/apiref.rst +++ b/Doc/distutils/apiref.rst @@ -78,7 +78,7 @@ setup script). Indirectly provides the :class:`distutils.dist.Distribution` and | | be built | :class:`distutils.core.Extension` | +--------------------+--------------------------------+-------------------------------------------------------------+ | *classifiers* | A list of categories for the | a list of strings; valid classifiers are listed on `PyPI | - | | package | <https://pypi.python.org/pypi?:action=list_classifiers>`_. | + | | package | <https://pypi.org/classifiers>`_. | +--------------------+--------------------------------+-------------------------------------------------------------+ | *distclass* | the :class:`Distribution` | a subclass of | | | class to use | :class:`distutils.core.Distribution` | diff --git a/Doc/distutils/packageindex.rst b/Doc/distutils/packageindex.rst index 086e14eb255a..50cb74f2b6ca 100644 --- a/Doc/distutils/packageindex.rst +++ b/Doc/distutils/packageindex.rst @@ -250,4 +250,4 @@ without warnings does not guarantee that PyPI will convert the content successfully. -.. _Python Package Index (PyPI): https://pypi.python.org/pypi +.. _Python Package Index (PyPI): https://pypi.org diff --git a/Doc/distutils/setupscript.rst b/Doc/distutils/setupscript.rst index 952607a4073b..1d96acbe98f6 100644 --- a/Doc/distutils/setupscript.rst +++ b/Doc/distutils/setupscript.rst @@ -625,7 +625,7 @@ Notes: (7) The valid classifiers are listed on - `PyPI <https://pypi.python.org/pypi?:action=list_classifiers>`_. + `PyPI <https://pypi.org/classifiers>`_. (8) To preserve backward compatibility, this field also accepts a string. If diff --git a/Doc/faq/general.rst b/Doc/faq/general.rst index 0d1cb198da87..9d3e199fca6b 100644 --- a/Doc/faq/general.rst +++ b/Doc/faq/general.rst @@ -117,7 +117,7 @@ programming), software engineering (unit testing, logging, profiling, parsing Python code), and operating system interfaces (system calls, filesystems, TCP/IP sockets). Look at the table of contents for :ref:`library-index` to get an idea of what's available. A wide variety of third-party extensions are also -available. Consult `the Python Package Index <https://pypi.python.org/pypi>`_ to +available. Consult `the Python Package Index <https://pypi.org>`_ to find packages of interest to you. diff --git a/Doc/faq/library.rst b/Doc/faq/library.rst index aec4bf9b85d5..ab92a879a885 100644 --- a/Doc/faq/library.rst +++ b/Doc/faq/library.rst @@ -19,7 +19,7 @@ standard library module. (Eventually you'll learn what's in the standard library and will be able to skip this step.) For third-party packages, search the `Python Package Index -<https://pypi.python.org/pypi>`_ or try `Google <https://www.google.com>`_ or +<https://pypi.org>`_ or try `Google <https://www.google.com>`_ or another Web search engine. Searching for "Python" plus a keyword or two for your topic of interest will usually find something helpful. @@ -611,7 +611,7 @@ use ``p.read(n)``. "expect" library. A Python extension that interfaces to expect is called "expy" and available from http://expectpy.sourceforge.net. A pure Python solution that works like expect is `pexpect - <https://pypi.python.org/pypi/pexpect/>`_. + <https://pypi.org/project/pexpect/>`_. How do I access the serial (RS232) port? diff --git a/Doc/howto/curses.rst b/Doc/howto/curses.rst index 19d65d6996b7..cc4b4785b122 100644 --- a/Doc/howto/curses.rst +++ b/Doc/howto/curses.rst @@ -41,7 +41,7 @@ appearance---and the curses library will figure out what control codes need to be sent to the terminal to produce the right output. curses doesn't provide many user-interface concepts such as buttons, checkboxes, or dialogs; if you need such features, consider a user interface library such as -`Urwid <https://pypi.python.org/pypi/urwid/>`_. +`Urwid <https://pypi.org/project/urwid/>`_. The curses library was originally written for BSD Unix; the later System V versions of Unix from AT&T added many enhancements and new functions. BSD curses @@ -55,7 +55,7 @@ everything, though. The Windows version of Python doesn't include the :mod:`curses` module. A ported version called `UniCurses -<https://pypi.python.org/pypi/UniCurses>`_ is available. You could +<https://pypi.org/project/UniCurses>`_ is available. You could also try `the Console module <http://effbot.org/zone/console-index.htm>`_ written by Fredrik Lundh, which doesn't use the same API as curses but provides cursor-addressable text output @@ -432,7 +432,7 @@ User Input The C curses library offers only very simple input mechanisms. Python's :mod:`curses` module adds a basic text-input widget. (Other libraries -such as `Urwid <https://pypi.python.org/pypi/urwid/>`_ have more extensive +such as `Urwid <https://pypi.org/project/urwid/>`_ have more extensive collections of widgets.) There are two methods for getting input from a window: diff --git a/Doc/howto/pyporting.rst b/Doc/howto/pyporting.rst index 98c81206741a..3be6bb380d66 100644 --- a/Doc/howto/pyporting.rst +++ b/Doc/howto/pyporting.rst @@ -427,25 +427,25 @@ to make sure everything functions as expected in both versions of Python. .. _2to3: https://docs.python.org/3/library/2to3.html -.. _caniusepython3: https://pypi.python.org/pypi/caniusepython3 +.. _caniusepython3: https://pypi.org/project/caniusepython3 .. _cheat sheet: http://python-future.org/compatible_idioms.html -.. _coverage.py: https://pypi.python.org/pypi/coverage +.. _coverage.py: https://pypi.org/project/coverage .. _Futurize: http://python-future.org/automatic_conversion.html .. _importlib: https://docs.python.org/3/library/importlib.html#module-importlib -.. _importlib2: https://pypi.python.org/pypi/importlib2 +.. _importlib2: https://pypi.org/project/importlib2 .. _Modernize: https://python-modernize.readthedocs.io/ .. _mypy: http://mypy-lang.org/ .. _Porting to Python 3: http://python3porting.com/ -.. _Pylint: https://pypi.python.org/pypi/pylint +.. _Pylint: https://pypi.org/project/pylint .. _Python 3 Q & A: https://ncoghlan-devs-python-notes.readthedocs.io/en/latest/python3/questions_and_answers.html .. _pytype: https://github.com/google/pytype .. _python-future: http://python-future.org/ .. _python-porting: https://mail.python.org/mailman/listinfo/python-porting -.. _six: https://pypi.python.org/pypi/six -.. _tox: https://pypi.python.org/pypi/tox -.. _trove classifier: https://pypi.python.org/pypi?%3Aaction=list_classifiers +.. _six: https://pypi.org/project/six +.. _tox: https://pypi.org/project/tox +.. _trove classifier: https://pypi.org/classifiers .. _"What's New": https://docs.python.org/3/whatsnew/index.html diff --git a/Doc/installing/index.rst b/Doc/installing/index.rst index f9a224be92b8..7a69869fb508 100644 --- a/Doc/installing/index.rst +++ b/Doc/installing/index.rst @@ -44,7 +44,7 @@ Key terms ``venv``. It allows virtual environments to be used on versions of Python prior to 3.4, which either don't provide ``venv`` at all, or aren't able to automatically install ``pip`` into created environments. -* The `Python Packaging Index <https://pypi.python.org/pypi>`__ is a public +* The `Python Packaging Index <https://pypi.org>`__ is a public repository of open source licensed packages made available for use by other Python users. * the `Python Packaging Authority diff --git a/Doc/library/distribution.rst b/Doc/library/distribution.rst index 3e6e84b42a2e..8d4befe41b32 100644 --- a/Doc/library/distribution.rst +++ b/Doc/library/distribution.rst @@ -4,7 +4,7 @@ Software Packaging and Distribution These libraries help you with publishing and installing Python software. While these modules are designed to work in conjunction with the -`Python Package Index <https://pypi.python.org/pypi>`__, they can also be used +`Python Package Index <https://pypi.org>`__, they can also be used with a local index server, or without any index server at all. .. toctree:: diff --git a/Doc/library/index.rst b/Doc/library/index.rst index da6a460e2c31..b8fbf44ae49f 100644 --- a/Doc/library/index.rst +++ b/Doc/library/index.rst @@ -30,7 +30,7 @@ optional components. In addition to the standard library, there is a growing collection of several thousand components (from individual programs and modules to packages and entire application development frameworks), available from -the `Python Package Index <https://pypi.python.org/pypi>`_. +the `Python Package Index <https://pypi.org>`_. .. toctree:: diff --git a/Doc/library/pprint.rst b/Doc/library/pprint.rst index 65d94fe386c8..aa97d3eabafa 100644 --- a/Doc/library/pprint.rst +++ b/Doc/library/pprint.rst @@ -212,12 +212,12 @@ Example ------- To demonstrate several uses of the :func:`pprint` function and its parameters, -let's fetch information about a project from `PyPI <https://pypi.python.org/pypi>`_:: +let's fetch information about a project from `PyPI <https://pypi.org>`_:: >>> import json >>> import pprint >>> from urllib.request import urlopen - >>> with urlopen('http://pypi.python.org/pypi/Twisted/json') as url: + >>> with urlopen('http://pypi.org/project/Twisted/json') as url: ... http_info = url.info() ... raw_data = url.read().decode(http_info.get_content_charset()) >>> project_info = json.loads(raw_data) @@ -248,9 +248,9 @@ In its basic form, :func:`pprint` shows the whole object:: 'maintainer': '', 'maintainer_email': '', 'name': 'Twisted', - 'package_url': 'http://pypi.python.org/pypi/Twisted', + 'package_url': 'http://pypi.org/project/Twisted', 'platform': 'UNKNOWN', - 'release_url': 'http://pypi.python.org/pypi/Twisted/12.3.0', + 'release_url': 'http://pypi.org/project/Twisted/12.3.0', 'requires_python': None, 'stable_version': None, 'summary': 'An asynchronous networking framework written in Python', @@ -264,7 +264,7 @@ In its basic form, :func:`pprint` shows the whole object:: 'python_version': 'source', 'size': 2615733, 'upload_time': '2012-12-26T12:47:03', - 'url': 'https://pypi.python.org/packages/source/T/Twisted/Twisted-12.3.0.tar.bz2'}, + 'url': 'https://pypi.org/packages/source/T/Twisted/Twisted-12.3.0.tar.bz2'}, {'comment_text': '', 'downloads': 5224, 'filename': 'Twisted-12.3.0.win32-py2.7.msi', @@ -274,7 +274,7 @@ In its basic form, :func:`pprint` shows the whole object:: 'python_version': '2.7', 'size': 2916352, 'upload_time': '2012-12-26T12:48:15', - 'url': 'https://pypi.python.org/packages/2.7/T/Twisted/Twisted-12.3.0.win32-py2.7.msi'}]} + 'url': 'https://pypi.org/packages/2.7/T/Twisted/Twisted-12.3.0.win32-py2.7.msi'}]} The result can be limited to a certain *depth* (ellipsis is used for deeper contents):: @@ -301,9 +301,9 @@ contents):: 'maintainer': '', 'maintainer_email': '', 'name': 'Twisted', - 'package_url': 'http://pypi.python.org/pypi/Twisted', + 'package_url': 'http://pypi.org/project/Twisted', 'platform': 'UNKNOWN', - 'release_url': 'http://pypi.python.org/pypi/Twisted/12.3.0', + 'release_url': 'http://pypi.org/project/Twisted/12.3.0', 'requires_python': None, 'stable_version': None, 'summary': 'An asynchronous networking framework written in Python', @@ -339,9 +339,9 @@ cannot be split, the specified width will be exceeded:: 'maintainer': '', 'maintainer_email': '', 'name': 'Twisted', - 'package_url': 'http://pypi.python.org/pypi/Twisted', + 'package_url': 'http://pypi.org/project/Twisted', 'platform': 'UNKNOWN', - 'release_url': 'http://pypi.python.org/pypi/Twisted/12.3.0', + 'release_url': 'http://pypi.org/project/Twisted/12.3.0', 'requires_python': None, 'stable_version': None, 'summary': 'An asynchronous networking ' diff --git a/Doc/library/re.rst b/Doc/library/re.rst index d35aaf42f4ab..3a051dd0dde2 100644 --- a/Doc/library/re.rst +++ b/Doc/library/re.rst @@ -45,7 +45,7 @@ fine-tuning parameters. .. seealso:: - The third-party `regex <https://pypi.python.org/pypi/regex/>`_ module, + The third-party `regex <https://pypi.org/project/regex/>`_ module, which has an API compatible with the standard library :mod:`re` module, but offers additional functionality and a more thorough Unicode support. diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 8082a383d5ab..f96549427afc 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -2158,9 +2158,9 @@ Visual inspection shows that the certificate does identify the desired service (('commonName', 'www.python.org'),)), 'subjectAltName': (('DNS', 'www.python.org'), ('DNS', 'python.org'), - ('DNS', 'pypi.python.org'), + ('DNS', 'pypi.org'), ('DNS', 'docs.python.org'), - ('DNS', 'testpypi.python.org'), + ('DNS', 'testpypi.org'), ('DNS', 'bugs.python.org'), ('DNS', 'wiki.python.org'), ('DNS', 'hg.python.org'), diff --git a/Doc/library/unittest.mock.rst b/Doc/library/unittest.mock.rst index ac9dd3b6f793..bb647bb6a811 100644 --- a/Doc/library/unittest.mock.rst +++ b/Doc/library/unittest.mock.rst @@ -35,7 +35,7 @@ is based on the 'action -> assertion' pattern instead of 'record -> replay' used by many mocking frameworks. There is a backport of :mod:`unittest.mock` for earlier versions of Python, -available as `mock on PyPI <https://pypi.python.org/pypi/mock>`_. +available as `mock on PyPI <https://pypi.org/project/mock>`_. Quick Guide @@ -2085,7 +2085,7 @@ mock_open the start. If you need more control over the data that you are feeding to the tested code you will need to customize this mock for yourself. When that is insufficient, one of the in-memory filesystem packages on `PyPI - <https://pypi.python.org/pypi>`_ can offer a realistic filesystem for testing. + <https://pypi.org>`_ can offer a realistic filesystem for testing. .. versionchanged:: 3.4 Added :meth:`~io.IOBase.readline` and :meth:`~io.IOBase.readlines` support. diff --git a/Doc/library/xml.rst b/Doc/library/xml.rst index d833b7fe9977..63c24f80ac87 100644 --- a/Doc/library/xml.rst +++ b/Doc/library/xml.rst @@ -130,8 +130,8 @@ but will not be included in any bugfix releases of Python because they break backward compatibility. -.. _defusedxml: https://pypi.python.org/pypi/defusedxml/ -.. _defusedexpat: https://pypi.python.org/pypi/defusedexpat/ +.. _defusedxml: https://pypi.org/project/defusedxml/ +.. _defusedexpat: https://pypi.org/project/defusedexpat/ .. _Billion Laughs: https://en.wikipedia.org/wiki/Billion_laughs .. _ZIP bomb: https://en.wikipedia.org/wiki/Zip_bomb .. _DTD: https://en.wikipedia.org/wiki/Document_type_definition diff --git a/Doc/tutorial/venv.rst b/Doc/tutorial/venv.rst index e2dd57d48f22..dc4136e42a88 100644 --- a/Doc/tutorial/venv.rst +++ b/Doc/tutorial/venv.rst @@ -88,7 +88,7 @@ Managing Packages with pip You can install, upgrade, and remove packages using a program called :program:`pip`. By default ``pip`` will install packages from the Python -Package Index, <https://pypi.python.org/pypi>. You can browse the Python +Package Index, <https://pypi.org>. You can browse the Python Package Index by going to it in your web browser, or you can use ``pip``'s limited search feature: diff --git a/Doc/tutorial/whatnow.rst b/Doc/tutorial/whatnow.rst index 1ea22ae5cdcc..d876d0740d80 100644 --- a/Doc/tutorial/whatnow.rst +++ b/Doc/tutorial/whatnow.rst @@ -38,7 +38,7 @@ More Python resources: * https://docs.python.org: Fast access to Python's documentation. -* https://pypi.python.org/pypi: The Python Package Index, previously also nicknamed +* https://pypi.org: The Python Package Index, previously also nicknamed the Cheese Shop, is an index of user-created Python modules that are available for download. Once you begin releasing code, you can register it here so that others can find it. diff --git a/Doc/using/windows.rst b/Doc/using/windows.rst index 3bab6fe503ca..5cbf13f51081 100644 --- a/Doc/using/windows.rst +++ b/Doc/using/windows.rst @@ -848,7 +848,7 @@ The Windows-specific standard modules are documented in PyWin32 ------- -The `PyWin32 <https://pypi.python.org/pypi/pywin32>`_ module by Mark Hammond +The `PyWin32 <https://pypi.org/project/pywin32>`_ module by Mark Hammond is a collection of modules for advanced Windows-specific support. This includes utilities for: diff --git a/Doc/whatsnew/2.3.rst b/Doc/whatsnew/2.3.rst index b5628a910ae8..590015af98f1 100644 --- a/Doc/whatsnew/2.3.rst +++ b/Doc/whatsnew/2.3.rst @@ -659,7 +659,7 @@ The heart of the catalog is the new Distutils :command:`register` command. Running ``python setup.py register`` will collect the metadata describing a package, such as its name, version, maintainer, description, &c., and send it to a central catalog server. The resulting catalog is available from -https://pypi.python.org/pypi. +https://pypi.org. To make the catalog a bit more useful, a new optional *classifiers* keyword argument has been added to the Distutils :func:`setup` function. A list of diff --git a/Doc/whatsnew/2.5.rst b/Doc/whatsnew/2.5.rst index 15d35d384c40..79c5a73dcf2b 100644 --- a/Doc/whatsnew/2.5.rst +++ b/Doc/whatsnew/2.5.rst @@ -229,7 +229,7 @@ required packages. :: ) Another new enhancement to the Python package index at -https://pypi.python.org is storing source and binary archives for a +https://pypi.org is storing source and binary archives for a package. The new :command:`upload` Distutils command will upload a package to the repository. diff --git a/Doc/whatsnew/2.7.rst b/Doc/whatsnew/2.7.rst index 90ce06c32868..02525f4c4c9b 100644 --- a/Doc/whatsnew/2.7.rst +++ b/Doc/whatsnew/2.7.rst @@ -1828,7 +1828,7 @@ new features were added. Most of these features were implemented by Michael Foord, unless otherwise noted. The enhanced version of the module is downloadable separately for use with Python versions 2.4 to 2.6, packaged as the :mod:`unittest2` package, from -https://pypi.python.org/pypi/unittest2. +https://pypi.org/project/unittest2. When used from the command line, the module can automatically discover tests. It's not as fancy as `py.test <http://pytest.org>`__ or diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst index a6ba5bbb720c..3e3329a84cf4 100644 --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -951,7 +951,7 @@ New :class:`~collections.abc.Awaitable`, :class:`~collections.abc.Coroutine`, (Contributed by Yury Selivanov in :issue:`24184`.) For earlier Python versions, a backport of the new ABCs is available in an -external `PyPI package <https://pypi.python.org/pypi/backports_abc>`_. +external `PyPI package <https://pypi.org/project/backports_abc>`_. compileall diff --git a/Misc/NEWS.d/next/Documentation/2018-05-14-20-08-58.bpo-33503.Wvt0qg.rst b/Misc/NEWS.d/next/Documentation/2018-05-14-20-08-58.bpo-33503.Wvt0qg.rst new file mode 100644 index 000000000000..27025c31a036 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2018-05-14-20-08-58.bpo-33503.Wvt0qg.rst @@ -0,0 +1 @@ +Fix broken pypi link From webhook-mailer at python.org Wed May 16 10:08:26 2018 From: webhook-mailer at python.org (Petr Viktorin) Date: Wed, 16 May 2018 14:08:26 -0000 Subject: [Python-checkins] [3.6] bpo-33503: Fix the broken pypi link in the source and the documentation (GH-6814) (GH-6885) Message-ID: <mailman.83.1526479708.2757.python-checkins@python.org> https://github.com/python/cpython/commit/e4cd12d3d338e691ab0c12a2f2f90422eee04bda commit: e4cd12d3d338e691ab0c12a2f2f90422eee04bda branch: 3.6 author: St?phane Wirtel <stephane at wirtel.be> committer: Petr Viktorin <encukou at gmail.com> date: 2018-05-16T10:08:23-04:00 summary: [3.6] bpo-33503: Fix the broken pypi link in the source and the documentation (GH-6814) (GH-6885) (cherry picked from commit 19177fbd5d6d9b29ccc302d65f9d9417ece082ce) Co-authored-by: St?phane Wirtel <stephane at wirtel.be> files: A Misc/NEWS.d/next/Documentation/2018-05-14-20-08-58.bpo-33503.Wvt0qg.rst M Doc/distributing/index.rst M Doc/distutils/apiref.rst M Doc/distutils/packageindex.rst M Doc/faq/general.rst M Doc/faq/library.rst M Doc/howto/curses.rst M Doc/howto/pyporting.rst M Doc/installing/index.rst M Doc/library/distribution.rst M Doc/library/index.rst M Doc/library/pprint.rst M Doc/library/re.rst M Doc/library/ssl.rst M Doc/library/unittest.mock.rst M Doc/library/xml.rst M Doc/tutorial/venv.rst M Doc/tutorial/whatnow.rst M Doc/using/windows.rst M Doc/whatsnew/2.3.rst M Doc/whatsnew/2.5.rst M Doc/whatsnew/2.7.rst M Doc/whatsnew/3.5.rst diff --git a/Doc/distributing/index.rst b/Doc/distributing/index.rst index 82ecd2c1ef45..b0dccb3db1dd 100644 --- a/Doc/distributing/index.rst +++ b/Doc/distributing/index.rst @@ -31,7 +31,7 @@ installing other Python projects, refer to the Key terms ========= -* the `Python Packaging Index <https://pypi.python.org/pypi>`__ is a public +* the `Python Packaging Index <https://pypi.org>`__ is a public repository of open source licensed packages made available for use by other Python users * the `Python Packaging Authority diff --git a/Doc/distutils/apiref.rst b/Doc/distutils/apiref.rst index b5b7731074c2..f147bb236a70 100644 --- a/Doc/distutils/apiref.rst +++ b/Doc/distutils/apiref.rst @@ -78,7 +78,7 @@ setup script). Indirectly provides the :class:`distutils.dist.Distribution` and | | be built | :class:`distutils.core.Extension` | +--------------------+--------------------------------+-------------------------------------------------------------+ | *classifiers* | A list of categories for the | a list of strings; valid classifiers are listed on `PyPI | - | | package | <https://pypi.python.org/pypi?:action=list_classifiers>`_. | + | | package | <https://pypi.org/classifiers>`_. | +--------------------+--------------------------------+-------------------------------------------------------------+ | *distclass* | the :class:`Distribution` | a subclass of | | | class to use | :class:`distutils.core.Distribution` | diff --git a/Doc/distutils/packageindex.rst b/Doc/distutils/packageindex.rst index 086e14eb255a..50cb74f2b6ca 100644 --- a/Doc/distutils/packageindex.rst +++ b/Doc/distutils/packageindex.rst @@ -250,4 +250,4 @@ without warnings does not guarantee that PyPI will convert the content successfully. -.. _Python Package Index (PyPI): https://pypi.python.org/pypi +.. _Python Package Index (PyPI): https://pypi.org diff --git a/Doc/faq/general.rst b/Doc/faq/general.rst index d4a97fd81af9..4e842f5366ef 100644 --- a/Doc/faq/general.rst +++ b/Doc/faq/general.rst @@ -117,7 +117,7 @@ programming), software engineering (unit testing, logging, profiling, parsing Python code), and operating system interfaces (system calls, filesystems, TCP/IP sockets). Look at the table of contents for :ref:`library-index` to get an idea of what's available. A wide variety of third-party extensions are also -available. Consult `the Python Package Index <https://pypi.python.org/pypi>`_ to +available. Consult `the Python Package Index <https://pypi.org>`_ to find packages of interest to you. diff --git a/Doc/faq/library.rst b/Doc/faq/library.rst index 431772fa6106..1acfc26801ca 100644 --- a/Doc/faq/library.rst +++ b/Doc/faq/library.rst @@ -19,7 +19,7 @@ standard library module. (Eventually you'll learn what's in the standard library and will be able to skip this step.) For third-party packages, search the `Python Package Index -<https://pypi.python.org/pypi>`_ or try `Google <https://www.google.com>`_ or +<https://pypi.org>`_ or try `Google <https://www.google.com>`_ or another Web search engine. Searching for "Python" plus a keyword or two for your topic of interest will usually find something helpful. @@ -611,7 +611,7 @@ use ``p.read(n)``. "expect" library. A Python extension that interfaces to expect is called "expy" and available from http://expectpy.sourceforge.net. A pure Python solution that works like expect is `pexpect - <https://pypi.python.org/pypi/pexpect/>`_. + <https://pypi.org/project/pexpect/>`_. How do I access the serial (RS232) port? diff --git a/Doc/howto/curses.rst b/Doc/howto/curses.rst index 1d3bfb87dc04..d5c07714aded 100644 --- a/Doc/howto/curses.rst +++ b/Doc/howto/curses.rst @@ -41,7 +41,7 @@ appearance---and the curses library will figure out what control codes need to be sent to the terminal to produce the right output. curses doesn't provide many user-interface concepts such as buttons, checkboxes, or dialogs; if you need such features, consider a user interface library such as -`Urwid <https://pypi.python.org/pypi/urwid/>`_. +`Urwid <https://pypi.org/project/urwid/>`_. The curses library was originally written for BSD Unix; the later System V versions of Unix from AT&T added many enhancements and new functions. BSD curses @@ -55,7 +55,7 @@ everything, though. The Windows version of Python doesn't include the :mod:`curses` module. A ported version called `UniCurses -<https://pypi.python.org/pypi/UniCurses>`_ is available. You could +<https://pypi.org/project/UniCurses>`_ is available. You could also try `the Console module <http://effbot.org/zone/console-index.htm>`_ written by Fredrik Lundh, which doesn't use the same API as curses but provides cursor-addressable text output @@ -432,7 +432,7 @@ User Input The C curses library offers only very simple input mechanisms. Python's :mod:`curses` module adds a basic text-input widget. (Other libraries -such as `Urwid <https://pypi.python.org/pypi/urwid/>`_ have more extensive +such as `Urwid <https://pypi.org/project/urwid/>`_ have more extensive collections of widgets.) There are two methods for getting input from a window: diff --git a/Doc/howto/pyporting.rst b/Doc/howto/pyporting.rst index 8562d2373749..2a27041ab482 100644 --- a/Doc/howto/pyporting.rst +++ b/Doc/howto/pyporting.rst @@ -427,25 +427,25 @@ to make sure everything functions as expected in both versions of Python. .. _2to3: https://docs.python.org/3/library/2to3.html -.. _caniusepython3: https://pypi.python.org/pypi/caniusepython3 +.. _caniusepython3: https://pypi.org/project/caniusepython3 .. _cheat sheet: http://python-future.org/compatible_idioms.html -.. _coverage.py: https://pypi.python.org/pypi/coverage +.. _coverage.py: https://pypi.org/project/coverage .. _Futurize: http://python-future.org/automatic_conversion.html .. _importlib: https://docs.python.org/3/library/importlib.html#module-importlib .. _importlib2: https://pypi.python.org/pypi/importlib2 .. _Modernize: https://python-modernize.readthedocs.org/en/latest/ .. _mypy: http://mypy-lang.org/ .. _Porting to Python 3: http://python3porting.com/ -.. _Pylint: https://pypi.python.org/pypi/pylint +.. _Pylint: https://pypi.org/project/pylint .. _Python 3 Q & A: https://ncoghlan-devs-python-notes.readthedocs.org/en/latest/python3/questions_and_answers.html .. _pytype: https://github.com/google/pytype .. _python-future: http://python-future.org/ .. _python-porting: https://mail.python.org/mailman/listinfo/python-porting -.. _six: https://pypi.python.org/pypi/six -.. _tox: https://pypi.python.org/pypi/tox -.. _trove classifier: https://pypi.python.org/pypi?%3Aaction=list_classifiers +.. _six: https://pypi.org/project/six +.. _tox: https://pypi.org/project/tox +.. _trove classifier: https://pypi.org/classifiers .. _"What's New": https://docs.python.org/3/whatsnew/index.html diff --git a/Doc/installing/index.rst b/Doc/installing/index.rst index 09bb8251c35d..18f5b29396c9 100644 --- a/Doc/installing/index.rst +++ b/Doc/installing/index.rst @@ -44,7 +44,7 @@ Key terms ``venv``. It allows virtual environments to be used on versions of Python prior to 3.4, which either don't provide ``venv`` at all, or aren't able to automatically install ``pip`` into created environments. -* The `Python Packaging Index <https://pypi.python.org/pypi>`__ is a public +* The `Python Packaging Index <https://pypi.org>`__ is a public repository of open source licensed packages made available for use by other Python users. * the `Python Packaging Authority diff --git a/Doc/library/distribution.rst b/Doc/library/distribution.rst index 3e6e84b42a2e..8d4befe41b32 100644 --- a/Doc/library/distribution.rst +++ b/Doc/library/distribution.rst @@ -4,7 +4,7 @@ Software Packaging and Distribution These libraries help you with publishing and installing Python software. While these modules are designed to work in conjunction with the -`Python Package Index <https://pypi.python.org/pypi>`__, they can also be used +`Python Package Index <https://pypi.org>`__, they can also be used with a local index server, or without any index server at all. .. toctree:: diff --git a/Doc/library/index.rst b/Doc/library/index.rst index a925e10ee498..eadd0e43d707 100644 --- a/Doc/library/index.rst +++ b/Doc/library/index.rst @@ -30,7 +30,7 @@ optional components. In addition to the standard library, there is a growing collection of several thousand components (from individual programs and modules to packages and entire application development frameworks), available from -the `Python Package Index <https://pypi.python.org/pypi>`_. +the `Python Package Index <https://pypi.org>`_. .. toctree:: diff --git a/Doc/library/pprint.rst b/Doc/library/pprint.rst index 65d94fe386c8..aa97d3eabafa 100644 --- a/Doc/library/pprint.rst +++ b/Doc/library/pprint.rst @@ -212,12 +212,12 @@ Example ------- To demonstrate several uses of the :func:`pprint` function and its parameters, -let's fetch information about a project from `PyPI <https://pypi.python.org/pypi>`_:: +let's fetch information about a project from `PyPI <https://pypi.org>`_:: >>> import json >>> import pprint >>> from urllib.request import urlopen - >>> with urlopen('http://pypi.python.org/pypi/Twisted/json') as url: + >>> with urlopen('http://pypi.org/project/Twisted/json') as url: ... http_info = url.info() ... raw_data = url.read().decode(http_info.get_content_charset()) >>> project_info = json.loads(raw_data) @@ -248,9 +248,9 @@ In its basic form, :func:`pprint` shows the whole object:: 'maintainer': '', 'maintainer_email': '', 'name': 'Twisted', - 'package_url': 'http://pypi.python.org/pypi/Twisted', + 'package_url': 'http://pypi.org/project/Twisted', 'platform': 'UNKNOWN', - 'release_url': 'http://pypi.python.org/pypi/Twisted/12.3.0', + 'release_url': 'http://pypi.org/project/Twisted/12.3.0', 'requires_python': None, 'stable_version': None, 'summary': 'An asynchronous networking framework written in Python', @@ -264,7 +264,7 @@ In its basic form, :func:`pprint` shows the whole object:: 'python_version': 'source', 'size': 2615733, 'upload_time': '2012-12-26T12:47:03', - 'url': 'https://pypi.python.org/packages/source/T/Twisted/Twisted-12.3.0.tar.bz2'}, + 'url': 'https://pypi.org/packages/source/T/Twisted/Twisted-12.3.0.tar.bz2'}, {'comment_text': '', 'downloads': 5224, 'filename': 'Twisted-12.3.0.win32-py2.7.msi', @@ -274,7 +274,7 @@ In its basic form, :func:`pprint` shows the whole object:: 'python_version': '2.7', 'size': 2916352, 'upload_time': '2012-12-26T12:48:15', - 'url': 'https://pypi.python.org/packages/2.7/T/Twisted/Twisted-12.3.0.win32-py2.7.msi'}]} + 'url': 'https://pypi.org/packages/2.7/T/Twisted/Twisted-12.3.0.win32-py2.7.msi'}]} The result can be limited to a certain *depth* (ellipsis is used for deeper contents):: @@ -301,9 +301,9 @@ contents):: 'maintainer': '', 'maintainer_email': '', 'name': 'Twisted', - 'package_url': 'http://pypi.python.org/pypi/Twisted', + 'package_url': 'http://pypi.org/project/Twisted', 'platform': 'UNKNOWN', - 'release_url': 'http://pypi.python.org/pypi/Twisted/12.3.0', + 'release_url': 'http://pypi.org/project/Twisted/12.3.0', 'requires_python': None, 'stable_version': None, 'summary': 'An asynchronous networking framework written in Python', @@ -339,9 +339,9 @@ cannot be split, the specified width will be exceeded:: 'maintainer': '', 'maintainer_email': '', 'name': 'Twisted', - 'package_url': 'http://pypi.python.org/pypi/Twisted', + 'package_url': 'http://pypi.org/project/Twisted', 'platform': 'UNKNOWN', - 'release_url': 'http://pypi.python.org/pypi/Twisted/12.3.0', + 'release_url': 'http://pypi.org/project/Twisted/12.3.0', 'requires_python': None, 'stable_version': None, 'summary': 'An asynchronous networking ' diff --git a/Doc/library/re.rst b/Doc/library/re.rst index 64d84e10d160..14360edc31ec 100644 --- a/Doc/library/re.rst +++ b/Doc/library/re.rst @@ -45,7 +45,7 @@ fine-tuning parameters. .. seealso:: - The third-party `regex <https://pypi.python.org/pypi/regex/>`_ module, + The third-party `regex <https://pypi.org/project/regex/>`_ module, which has an API compatible with the standard library :mod:`re` module, but offers additional functionality and a more thorough Unicode support. diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 677e94534702..cb17742bcc8b 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -1911,9 +1911,9 @@ Visual inspection shows that the certificate does identify the desired service (('commonName', 'www.python.org'),)), 'subjectAltName': (('DNS', 'www.python.org'), ('DNS', 'python.org'), - ('DNS', 'pypi.python.org'), + ('DNS', 'pypi.org'), ('DNS', 'docs.python.org'), - ('DNS', 'testpypi.python.org'), + ('DNS', 'testpypi.org'), ('DNS', 'bugs.python.org'), ('DNS', 'wiki.python.org'), ('DNS', 'hg.python.org'), diff --git a/Doc/library/unittest.mock.rst b/Doc/library/unittest.mock.rst index a552cbfc70ad..9d4d36fe005c 100644 --- a/Doc/library/unittest.mock.rst +++ b/Doc/library/unittest.mock.rst @@ -35,7 +35,7 @@ is based on the 'action -> assertion' pattern instead of 'record -> replay' used by many mocking frameworks. There is a backport of :mod:`unittest.mock` for earlier versions of Python, -available as `mock on PyPI <https://pypi.python.org/pypi/mock>`_. +available as `mock on PyPI <https://pypi.org/project/mock>`_. Quick Guide @@ -2084,7 +2084,7 @@ mock_open the start. If you need more control over the data that you are feeding to the tested code you will need to customize this mock for yourself. When that is insufficient, one of the in-memory filesystem packages on `PyPI - <https://pypi.python.org/pypi>`_ can offer a realistic filesystem for testing. + <https://pypi.org>`_ can offer a realistic filesystem for testing. .. versionchanged:: 3.4 Added :meth:`~io.IOBase.readline` and :meth:`~io.IOBase.readlines` support. diff --git a/Doc/library/xml.rst b/Doc/library/xml.rst index d833b7fe9977..63c24f80ac87 100644 --- a/Doc/library/xml.rst +++ b/Doc/library/xml.rst @@ -130,8 +130,8 @@ but will not be included in any bugfix releases of Python because they break backward compatibility. -.. _defusedxml: https://pypi.python.org/pypi/defusedxml/ -.. _defusedexpat: https://pypi.python.org/pypi/defusedexpat/ +.. _defusedxml: https://pypi.org/project/defusedxml/ +.. _defusedexpat: https://pypi.org/project/defusedexpat/ .. _Billion Laughs: https://en.wikipedia.org/wiki/Billion_laughs .. _ZIP bomb: https://en.wikipedia.org/wiki/Zip_bomb .. _DTD: https://en.wikipedia.org/wiki/Document_type_definition diff --git a/Doc/tutorial/venv.rst b/Doc/tutorial/venv.rst index e2dd57d48f22..dc4136e42a88 100644 --- a/Doc/tutorial/venv.rst +++ b/Doc/tutorial/venv.rst @@ -88,7 +88,7 @@ Managing Packages with pip You can install, upgrade, and remove packages using a program called :program:`pip`. By default ``pip`` will install packages from the Python -Package Index, <https://pypi.python.org/pypi>. You can browse the Python +Package Index, <https://pypi.org>. You can browse the Python Package Index by going to it in your web browser, or you can use ``pip``'s limited search feature: diff --git a/Doc/tutorial/whatnow.rst b/Doc/tutorial/whatnow.rst index 1ea22ae5cdcc..d876d0740d80 100644 --- a/Doc/tutorial/whatnow.rst +++ b/Doc/tutorial/whatnow.rst @@ -38,7 +38,7 @@ More Python resources: * https://docs.python.org: Fast access to Python's documentation. -* https://pypi.python.org/pypi: The Python Package Index, previously also nicknamed +* https://pypi.org: The Python Package Index, previously also nicknamed the Cheese Shop, is an index of user-created Python modules that are available for download. Once you begin releasing code, you can register it here so that others can find it. diff --git a/Doc/using/windows.rst b/Doc/using/windows.rst index 88fa73c61575..c6624fe446b0 100644 --- a/Doc/using/windows.rst +++ b/Doc/using/windows.rst @@ -848,7 +848,7 @@ The Windows-specific standard modules are documented in PyWin32 ------- -The `PyWin32 <https://pypi.python.org/pypi/pywin32>`_ module by Mark Hammond +The `PyWin32 <https://pypi.org/project/pywin32>`_ module by Mark Hammond is a collection of modules for advanced Windows-specific support. This includes utilities for: diff --git a/Doc/whatsnew/2.3.rst b/Doc/whatsnew/2.3.rst index cebfb21156bf..5cdd51b39b22 100644 --- a/Doc/whatsnew/2.3.rst +++ b/Doc/whatsnew/2.3.rst @@ -659,7 +659,7 @@ The heart of the catalog is the new Distutils :command:`register` command. Running ``python setup.py register`` will collect the metadata describing a package, such as its name, version, maintainer, description, &c., and send it to a central catalog server. The resulting catalog is available from -https://pypi.python.org/pypi. +https://pypi.org. To make the catalog a bit more useful, a new optional *classifiers* keyword argument has been added to the Distutils :func:`setup` function. A list of diff --git a/Doc/whatsnew/2.5.rst b/Doc/whatsnew/2.5.rst index 4d4829183132..b0defbacaee8 100644 --- a/Doc/whatsnew/2.5.rst +++ b/Doc/whatsnew/2.5.rst @@ -229,7 +229,7 @@ required packages. :: ) Another new enhancement to the Python package index at -https://pypi.python.org is storing source and binary archives for a +https://pypi.org is storing source and binary archives for a package. The new :command:`upload` Distutils command will upload a package to the repository. diff --git a/Doc/whatsnew/2.7.rst b/Doc/whatsnew/2.7.rst index 55392fc2be08..0f9529a1b496 100644 --- a/Doc/whatsnew/2.7.rst +++ b/Doc/whatsnew/2.7.rst @@ -1828,7 +1828,7 @@ new features were added. Most of these features were implemented by Michael Foord, unless otherwise noted. The enhanced version of the module is downloadable separately for use with Python versions 2.4 to 2.6, packaged as the :mod:`unittest2` package, from -https://pypi.python.org/pypi/unittest2. +https://pypi.org/project/unittest2. When used from the command line, the module can automatically discover tests. It's not as fancy as `py.test <http://pytest.org>`__ or diff --git a/Doc/whatsnew/3.5.rst b/Doc/whatsnew/3.5.rst index a6ba5bbb720c..3e3329a84cf4 100644 --- a/Doc/whatsnew/3.5.rst +++ b/Doc/whatsnew/3.5.rst @@ -951,7 +951,7 @@ New :class:`~collections.abc.Awaitable`, :class:`~collections.abc.Coroutine`, (Contributed by Yury Selivanov in :issue:`24184`.) For earlier Python versions, a backport of the new ABCs is available in an -external `PyPI package <https://pypi.python.org/pypi/backports_abc>`_. +external `PyPI package <https://pypi.org/project/backports_abc>`_. compileall diff --git a/Misc/NEWS.d/next/Documentation/2018-05-14-20-08-58.bpo-33503.Wvt0qg.rst b/Misc/NEWS.d/next/Documentation/2018-05-14-20-08-58.bpo-33503.Wvt0qg.rst new file mode 100644 index 000000000000..27025c31a036 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2018-05-14-20-08-58.bpo-33503.Wvt0qg.rst @@ -0,0 +1 @@ +Fix broken pypi link From webhook-mailer at python.org Wed May 16 10:26:22 2018 From: webhook-mailer at python.org (Christian Heimes) Date: Wed, 16 May 2018 14:26:22 -0000 Subject: [Python-checkins] [3.7] bpo-32257: Add ssl.OP_NO_RENEGOTIATION (GH-5904) (#6877) Message-ID: <mailman.84.1526480784.2757.python-checkins@python.org> https://github.com/python/cpython/commit/e2db6ad1d96ca3e8bd29178f7093785c5d550bb7 commit: e2db6ad1d96ca3e8bd29178f7093785c5d550bb7 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Christian Heimes <christian at python.org> date: 2018-05-16T10:26:19-04:00 summary: [3.7] bpo-32257: Add ssl.OP_NO_RENEGOTIATION (GH-5904) (#6877) The ssl module now contains OP_NO_RENEGOTIATION constant, available with OpenSSL 1.1.0h or 1.1.1. Note, OpenSSL 1.1.0h hasn't been released yet. Signed-off-by: Christian Heimes <christian at python.org> (cherry picked from commit 67c48016638aac9a15afe6fd6754d53d2bdd6b76) Co-authored-by: Christian Heimes <christian at python.org> files: A Misc/NEWS.d/next/Library/2018-02-26-09-08-07.bpo-32257.6ElnUt.rst M Doc/library/ssl.rst M Modules/_ssl.c diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index f96549427afc..dcb26664feae 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -803,6 +803,15 @@ Constants The option is deprecated since OpenSSL 1.1.0. It was added to 2.7.15, 3.6.3 and 3.7.0 for backwards compatibility with OpenSSL 1.0.2. +.. data:: OP_NO_RENEGOTIATION + + Disable all renegotiation in TLSv1.2 and earlier. Do not send + HelloRequest messages, and ignore renegotiation requests via ClientHello. + + This option is only available with OpenSSL 1.1.0h and later. + + .. versionadded:: 3.7 + .. data:: OP_CIPHER_SERVER_PREFERENCE Use the server's cipher ordering preference, rather than the client's. diff --git a/Misc/NEWS.d/next/Library/2018-02-26-09-08-07.bpo-32257.6ElnUt.rst b/Misc/NEWS.d/next/Library/2018-02-26-09-08-07.bpo-32257.6ElnUt.rst new file mode 100644 index 000000000000..e74c39b68100 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-26-09-08-07.bpo-32257.6ElnUt.rst @@ -0,0 +1,2 @@ +The ssl module now contains OP_NO_RENEGOTIATION constant, available with +OpenSSL 1.1.0h or 1.1.1. diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 7670833bf5f5..bf379f01a1d2 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -5845,6 +5845,10 @@ PyInit__ssl(void) PyModule_AddIntConstant(m, "OP_ENABLE_MIDDLEBOX_COMPAT", SSL_OP_ENABLE_MIDDLEBOX_COMPAT); #endif +#ifdef SSL_OP_NO_RENEGOTIATION + PyModule_AddIntConstant(m, "OP_NO_RENEGOTIATION", + SSL_OP_NO_RENEGOTIATION); +#endif #ifdef X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT PyModule_AddIntConstant(m, "HOSTFLAG_ALWAYS_CHECK_SUBJECT", From webhook-mailer at python.org Wed May 16 10:52:15 2018 From: webhook-mailer at python.org (Ned Deily) Date: Wed, 16 May 2018 14:52:15 -0000 Subject: [Python-checkins] bpo-21475: Support the Sitemap extension in robotparser (GH-6883) Message-ID: <mailman.85.1526482337.2757.python-checkins@python.org> https://github.com/python/cpython/commit/5db5c0669e624767375593cc1a01f32092c91c58 commit: 5db5c0669e624767375593cc1a01f32092c91c58 branch: master author: Christopher Beacham <mcscope at gmail.com> committer: Ned Deily <nad at python.org> date: 2018-05-16T10:52:07-04:00 summary: bpo-21475: Support the Sitemap extension in robotparser (GH-6883) files: A Misc/NEWS.d/next/Library/2018-05-15-15-03-48.bpo-28612.E9dz39.rst M Doc/library/urllib.robotparser.rst M Lib/test/test_robotparser.py M Lib/urllib/robotparser.py M Misc/ACKS diff --git a/Doc/library/urllib.robotparser.rst b/Doc/library/urllib.robotparser.rst index e3b90e673caa..544f50273dd1 100644 --- a/Doc/library/urllib.robotparser.rst +++ b/Doc/library/urllib.robotparser.rst @@ -76,6 +76,15 @@ structure of :file:`robots.txt` files, see http://www.robotstxt.org/orig.html. .. versionadded:: 3.6 + .. method:: site_maps() + + Returns the contents of the ``Sitemap`` parameter from + ``robots.txt`` in the form of a :func:`list`. If there is no such + parameter or the ``robots.txt`` entry for this parameter has + invalid syntax, return ``None``. + + .. versionadded:: 3.8 + The following example demonstrates basic use of the :class:`RobotFileParser` class:: diff --git a/Lib/test/test_robotparser.py b/Lib/test/test_robotparser.py index bee8d238be6b..84a267ad9567 100644 --- a/Lib/test/test_robotparser.py +++ b/Lib/test/test_robotparser.py @@ -12,6 +12,7 @@ class BaseRobotTest: agent = 'test_robotparser' good = [] bad = [] + site_maps = None def setUp(self): lines = io.StringIO(self.robots_txt).readlines() @@ -36,6 +37,9 @@ def test_bad_urls(self): with self.subTest(url=url, agent=agent): self.assertFalse(self.parser.can_fetch(agent, url)) + def test_site_maps(self): + self.assertEqual(self.parser.site_maps(), self.site_maps) + class UserAgentWildcardTest(BaseRobotTest, unittest.TestCase): robots_txt = """\ @@ -65,6 +69,23 @@ class CrawlDelayAndCustomAgentTest(BaseRobotTest, unittest.TestCase): bad = ['/cyberworld/map/index.html'] +class SitemapTest(BaseRobotTest, unittest.TestCase): + robots_txt = """\ +# robots.txt for http://www.example.com/ + +User-agent: * +Sitemap: http://www.gstatic.com/s2/sitemaps/profiles-sitemap.xml +Sitemap: http://www.google.com/hostednews/sitemap_index.xml +Request-rate: 3/15 +Disallow: /cyberworld/map/ # This is an infinite virtual URL space + + """ + good = ['/', '/test.html'] + bad = ['/cyberworld/map/index.html'] + site_maps = ['http://www.gstatic.com/s2/sitemaps/profiles-sitemap.xml', + 'http://www.google.com/hostednews/sitemap_index.xml'] + + class RejectAllRobotsTest(BaseRobotTest, unittest.TestCase): robots_txt = """\ # go away diff --git a/Lib/urllib/robotparser.py b/Lib/urllib/robotparser.py index 92e4efe6865e..7089916a4f81 100644 --- a/Lib/urllib/robotparser.py +++ b/Lib/urllib/robotparser.py @@ -27,6 +27,7 @@ class RobotFileParser: def __init__(self, url=''): self.entries = [] + self.sitemaps = [] self.default_entry = None self.disallow_all = False self.allow_all = False @@ -141,6 +142,12 @@ def parse(self, lines): and numbers[1].strip().isdigit()): entry.req_rate = RequestRate(int(numbers[0]), int(numbers[1])) state = 2 + elif line[0] == "sitemap": + # According to http://www.sitemaps.org/protocol.html + # "This directive is independent of the user-agent line, + # so it doesn't matter where you place it in your file." + # Therefore we do not change the state of the parser. + self.sitemaps.append(line[1]) if state == 2: self._add_entry(entry) @@ -189,6 +196,11 @@ def request_rate(self, useragent): return entry.req_rate return self.default_entry.req_rate + def site_maps(self): + if not self.sitemaps: + return None + return self.sitemaps + def __str__(self): entries = self.entries if self.default_entry is not None: diff --git a/Misc/ACKS b/Misc/ACKS index 665b4dd7f43f..5c05ee7d5aa1 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -109,6 +109,7 @@ Anthony Baxter Mike Bayer Samuel L. Bayer Bo Bayles +Christopher Beacham AKA Lady Red Tommy Beadle Donald Beaudry David Beazley @@ -1760,6 +1761,7 @@ Dik Winter Blake Winton Jean-Claude Wippler St?phane Wirtel +Peter Wirtz Lars Wirzenius John Wiseman Chris Withers diff --git a/Misc/NEWS.d/next/Library/2018-05-15-15-03-48.bpo-28612.E9dz39.rst b/Misc/NEWS.d/next/Library/2018-05-15-15-03-48.bpo-28612.E9dz39.rst new file mode 100644 index 000000000000..e3e8f16eef07 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-15-15-03-48.bpo-28612.E9dz39.rst @@ -0,0 +1,3 @@ +Added support for Site Maps to urllib's ``RobotFileParser`` as +:meth:`RobotFileParser.site_maps() <urllib.robotparser.RobotFileParser.site_maps>`. +Patch by Lady Red, based on patch by Peter Wirtz. From webhook-mailer at python.org Wed May 16 10:57:42 2018 From: webhook-mailer at python.org (Ned Deily) Date: Wed, 16 May 2018 14:57:42 -0000 Subject: [Python-checkins] [2.7] bpo-33503: Fix the broken pypi link in the source and the documentation (GH-6814). (GH-6905) Message-ID: <mailman.86.1526482664.2757.python-checkins@python.org> https://github.com/python/cpython/commit/ad65d09fd02512b2ccf500f6c11063f705c9cd28 commit: ad65d09fd02512b2ccf500f6c11063f705c9cd28 branch: 2.7 author: St?phane Wirtel <stephane at wirtel.be> committer: Ned Deily <nad at python.org> date: 2018-05-16T10:57:36-04:00 summary: [2.7] bpo-33503: Fix the broken pypi link in the source and the documentation (GH-6814). (GH-6905) (cherry picked from commit 19177fbd5d6d9b29ccc302d65f9d9417ece082ce) Co-authored-by: St?phane Wirtel <stephane at wirtel.be> files: A Misc/NEWS.d/next/Documentation/2018-05-14-20-08-58.bpo-33503.Wvt0qg.rst M Doc/README.txt M Doc/distributing/index.rst M Doc/distutils/apiref.rst M Doc/distutils/packageindex.rst M Doc/distutils/setupscript.rst M Doc/faq/general.rst M Doc/faq/library.rst M Doc/howto/pyporting.rst M Doc/howto/webservers.rst M Doc/installing/index.rst M Doc/library/bz2.rst M Doc/library/datetime.rst M Doc/library/distribution.rst M Doc/library/index.rst M Doc/library/pprint.rst M Doc/library/re.rst M Doc/library/ssl.rst M Doc/library/subprocess.rst M Doc/library/unittest.rst M Doc/library/xml.rst M Doc/tutorial/whatnow.rst M Doc/using/windows.rst M Doc/whatsnew/2.3.rst M Doc/whatsnew/2.5.rst M Doc/whatsnew/2.7.rst diff --git a/Doc/README.txt b/Doc/README.txt index 4f8e9f8f1417..a362ecca9427 100644 --- a/Doc/README.txt +++ b/Doc/README.txt @@ -15,7 +15,7 @@ Building the docs You need to have Sphinx <http://sphinx-doc.org/> installed; it is the toolset used to build the docs. It is not included in this tree, but maintained -separately and available from PyPI <https://pypi.python.org/pypi/Sphinx>. +separately and available from PyPI <https://pypi.org/project/Sphinx>. Using make diff --git a/Doc/distributing/index.rst b/Doc/distributing/index.rst index 82ecd2c1ef45..b0dccb3db1dd 100644 --- a/Doc/distributing/index.rst +++ b/Doc/distributing/index.rst @@ -31,7 +31,7 @@ installing other Python projects, refer to the Key terms ========= -* the `Python Packaging Index <https://pypi.python.org/pypi>`__ is a public +* the `Python Packaging Index <https://pypi.org>`__ is a public repository of open source licensed packages made available for use by other Python users * the `Python Packaging Authority diff --git a/Doc/distutils/apiref.rst b/Doc/distutils/apiref.rst index 18844dd7679c..34a3cb34af32 100644 --- a/Doc/distutils/apiref.rst +++ b/Doc/distutils/apiref.rst @@ -78,7 +78,7 @@ setup script). Indirectly provides the :class:`distutils.dist.Distribution` and | | be built | :class:`distutils.core.Extension` | +--------------------+--------------------------------+-------------------------------------------------------------+ | *classifiers* | A list of categories for the | a list of strings; valid classifiers are listed on `PyPI | - | | package | <https://pypi.python.org/pypi?:action=list_classifiers>`_. | + | | package | <https://pypi.org/classifiers>`_. | +--------------------+--------------------------------+-------------------------------------------------------------+ | *distclass* | the :class:`Distribution` | a subclass of | | | class to use | :class:`distutils.core.Distribution` | diff --git a/Doc/distutils/packageindex.rst b/Doc/distutils/packageindex.rst index 80875845f680..cd11f20df802 100644 --- a/Doc/distutils/packageindex.rst +++ b/Doc/distutils/packageindex.rst @@ -248,4 +248,4 @@ without warnings does not guarantee that PyPI will convert the content successfully. -.. _Python Package Index (PyPI): https://pypi.python.org/pypi +.. _Python Package Index (PyPI): https://pypi.org diff --git a/Doc/distutils/setupscript.rst b/Doc/distutils/setupscript.rst index 6b82c40546ca..92ab5732d2b5 100644 --- a/Doc/distutils/setupscript.rst +++ b/Doc/distutils/setupscript.rst @@ -606,7 +606,7 @@ Notes: (4) These fields should not be used if your package is to be compatible with Python versions prior to 2.2.3 or 2.3. The list is available from the `PyPI website - <https://pypi.python.org/pypi>`_. + <https://pypi.org>`_. (5) The ``long_description`` field is used by PyPI when you are diff --git a/Doc/faq/general.rst b/Doc/faq/general.rst index 35cad55c3a9e..eb1bd16b4b8b 100644 --- a/Doc/faq/general.rst +++ b/Doc/faq/general.rst @@ -117,7 +117,7 @@ programming), software engineering (unit testing, logging, profiling, parsing Python code), and operating system interfaces (system calls, filesystems, TCP/IP sockets). Look at the table of contents for :ref:`library-index` to get an idea of what's available. A wide variety of third-party extensions are also -available. Consult `the Python Package Index <https://pypi.python.org/pypi>`_ to +available. Consult `the Python Package Index <https://pypi.org>`_ to find packages of interest to you. diff --git a/Doc/faq/library.rst b/Doc/faq/library.rst index d1b3efb4d7fd..a25946538e45 100644 --- a/Doc/faq/library.rst +++ b/Doc/faq/library.rst @@ -19,7 +19,7 @@ standard library module. (Eventually you'll learn what's in the standard library and will be able to skip this step.) For third-party packages, search the `Python Package Index -<https://pypi.python.org/pypi>`_ or try `Google <https://www.google.com>`_ or +<https://pypi.org>`_ or try `Google <https://www.google.com>`_ or another Web search engine. Searching for "Python" plus a keyword or two for your topic of interest will usually find something helpful. @@ -585,7 +585,7 @@ substituted for standard input and output. You will have to use pseudo ttys ("ptys") instead of pipes. Or you can use a Python interface to Don Libes' "expect" library. A Python extension that interfaces to expect is called "expy" and available from http://expectpy.sourceforge.net. A pure Python solution that -works like expect is `pexpect <https://pypi.python.org/pypi/pexpect/>`_. +works like expect is `pexpect <https://pypi.org/project/pexpect/>`_. How do I access the serial (RS232) port? diff --git a/Doc/howto/pyporting.rst b/Doc/howto/pyporting.rst index 8562d2373749..88b01779d2a5 100644 --- a/Doc/howto/pyporting.rst +++ b/Doc/howto/pyporting.rst @@ -427,25 +427,25 @@ to make sure everything functions as expected in both versions of Python. .. _2to3: https://docs.python.org/3/library/2to3.html -.. _caniusepython3: https://pypi.python.org/pypi/caniusepython3 +.. _caniusepython3: https://pypi.org/project/caniusepython3 .. _cheat sheet: http://python-future.org/compatible_idioms.html -.. _coverage.py: https://pypi.python.org/pypi/coverage +.. _coverage.py: https://pypi.org/project/coverage .. _Futurize: http://python-future.org/automatic_conversion.html .. _importlib: https://docs.python.org/3/library/importlib.html#module-importlib -.. _importlib2: https://pypi.python.org/pypi/importlib2 +.. _importlib2: https://pypi.org/project/importlib2 .. _Modernize: https://python-modernize.readthedocs.org/en/latest/ .. _mypy: http://mypy-lang.org/ .. _Porting to Python 3: http://python3porting.com/ -.. _Pylint: https://pypi.python.org/pypi/pylint +.. _Pylint: https://pypi.org/project/pylint .. _Python 3 Q & A: https://ncoghlan-devs-python-notes.readthedocs.org/en/latest/python3/questions_and_answers.html .. _pytype: https://github.com/google/pytype .. _python-future: http://python-future.org/ .. _python-porting: https://mail.python.org/mailman/listinfo/python-porting -.. _six: https://pypi.python.org/pypi/six -.. _tox: https://pypi.python.org/pypi/tox -.. _trove classifier: https://pypi.python.org/pypi?%3Aaction=list_classifiers +.. _six: https://pypi.org/project/six +.. _tox: https://pypi.org/project/tox +.. _trove classifier: https://pypi.org/classifiers .. _"What's New": https://docs.python.org/3/whatsnew/index.html diff --git a/Doc/howto/webservers.rst b/Doc/howto/webservers.rst index a555083e3255..5071a8a33cb9 100644 --- a/Doc/howto/webservers.rst +++ b/Doc/howto/webservers.rst @@ -301,7 +301,7 @@ following WSGI-application:: WSGIServer(app).run() This is a simple WSGI application, but you need to install `flup -<https://pypi.python.org/pypi/flup/1.0>`_ first, as flup handles the low level +<https://pypi.org/project/flup/1.0>`_ first, as flup handles the low level FastCGI access. .. seealso:: @@ -583,7 +583,7 @@ alternate storage mechanism. helps with choosing a method for saving data * `SQLAlchemy <http://www.sqlalchemy.org/>`_, the most powerful OR-Mapper - for Python, and `Elixir <https://pypi.python.org/pypi/Elixir>`_, which makes + for Python, and `Elixir <https://pypi.org/project/Elixir>`_, which makes SQLAlchemy easier to use * `SQLObject <http://www.sqlobject.org/>`_, another popular OR-Mapper diff --git a/Doc/installing/index.rst b/Doc/installing/index.rst index cbbb88240680..9b89d083af3d 100644 --- a/Doc/installing/index.rst +++ b/Doc/installing/index.rst @@ -39,9 +39,8 @@ Key terms being installed system wide * ``virtualenv`` is a third party tools for creating virtual environments, it is defaults to installing ``pip`` into all created virtual environments. -* the `Python Packaging Index <https://pypi.python.org/pypi>`__ is a public - repository of open source licensed packages made available for use by - other Python users +* the `Python Packaging Index <https://pypi.org>`__ is a public repository of + open source licensed packages made available for use by other Python users * the `Python Packaging Authority <https://www.pypa.io/en/latest/>`__ are the group of developers and documentation authors responsible for the maintenance and diff --git a/Doc/library/bz2.rst b/Doc/library/bz2.rst index 71957ec06e58..e764f3939544 100644 --- a/Doc/library/bz2.rst +++ b/Doc/library/bz2.rst @@ -74,7 +74,7 @@ Handling of compressed files is offered by the :class:`BZ2File` class. input file, only the first stream will be accessible. If you require support for multi-stream files, consider using the third-party :mod:`bz2file` module (available from - `PyPI <https://pypi.python.org/pypi/bz2file>`_). This module provides a + `PyPI <https://pypi.org/project/bz2file>`_). This module provides a backport of Python 3.3's :class:`BZ2File` class, which does support multi-stream files. diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst index b8d86e3b5a73..d2c1c563863f 100644 --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -1566,7 +1566,7 @@ EST (fixed offset -5 hours), or only EDT (fixed offset -4 hours)). .. seealso:: - `pytz <https://pypi.python.org/pypi/pytz/>`_ + `pytz <https://pypi.org/project/pytz/>`_ The standard library has no :class:`tzinfo` instances, but there exists a third-party library which brings the *IANA timezone database* (also known as the Olson database) to Python: *pytz*. diff --git a/Doc/library/distribution.rst b/Doc/library/distribution.rst index b56099957279..21dd18d94a45 100644 --- a/Doc/library/distribution.rst +++ b/Doc/library/distribution.rst @@ -4,7 +4,7 @@ Software Packaging and Distribution These libraries help you with publishing and installing Python software. While these modules are designed to work in conjunction with the -`Python Package Index <https://pypi.python.org>`__, they can also be used +`Python Package Index <https://pypi.org>`__, they can also be used with a local index server, or without any index server at all. .. toctree:: diff --git a/Doc/library/index.rst b/Doc/library/index.rst index 97cf3ea75cc8..31ca6df1d157 100644 --- a/Doc/library/index.rst +++ b/Doc/library/index.rst @@ -30,7 +30,7 @@ optional components. In addition to the standard library, there is a growing collection of several thousand components (from individual programs and modules to packages and entire application development frameworks), available from -the `Python Package Index <https://pypi.python.org/pypi>`_. +the `Python Package Index <https://pypi.org>`_. .. toctree:: diff --git a/Doc/library/pprint.rst b/Doc/library/pprint.rst index ffa27d4255ff..3f09b21d8532 100644 --- a/Doc/library/pprint.rst +++ b/Doc/library/pprint.rst @@ -234,4 +234,3 @@ parameters. ['aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'], ['cccccccccccccccccccc', 'dddddddddddddddddddd']] - diff --git a/Doc/library/re.rst b/Doc/library/re.rst index c424230e13a4..228fcfedf4f3 100644 --- a/Doc/library/re.rst +++ b/Doc/library/re.rst @@ -35,7 +35,7 @@ fine-tuning parameters. .. seealso:: - The third-party `regex <https://pypi.python.org/pypi/regex/>`_ module, + The third-party `regex <https://pypi.org/project/regex/>`_ module, which has an API compatible with the standard library :mod:`re` module, but offers additional functionality and a more thorough Unicode support. diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 89b9ff3621f7..a612e6ebd392 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -1586,7 +1586,7 @@ Visual inspection shows that the certificate does identify the desired service (('commonName', 'www.python.org'),)), 'subjectAltName': (('DNS', 'www.python.org'), ('DNS', 'python.org'), - ('DNS', 'pypi.python.org'), + ('DNS', 'pypi.org'), ('DNS', 'docs.python.org'), ('DNS', 'testpypi.python.org'), ('DNS', 'bugs.python.org'), diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst index 284cf4465aac..53a0161d4b03 100644 --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -32,7 +32,7 @@ functions can be found in the subprocess-replacements_ section. :pep:`324` -- PEP proposing the subprocess module -.. _subprocess32: https://pypi.python.org/pypi/subprocess32/ +.. _subprocess32: https://pypi.org/project/subprocess32/ Using the :mod:`subprocess` Module ---------------------------------- diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst index b36126e1cc65..0915926ab7c1 100644 --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -78,7 +78,7 @@ need to derive from a specific class. Module :mod:`doctest` Another test-support module with a very different flavor. - `unittest2: A backport of new unittest features for Python 2.4-2.6 <https://pypi.python.org/pypi/unittest2>`_ + `unittest2: A backport of new unittest features for Python 2.4-2.6 <https://pypi.org/project/unittest2>`_ Many new features were added to unittest in Python 2.7, including test discovery. unittest2 allows you to use these features with earlier versions of Python. diff --git a/Doc/library/xml.rst b/Doc/library/xml.rst index a8f20cdbf488..b107c29c6405 100644 --- a/Doc/library/xml.rst +++ b/Doc/library/xml.rst @@ -129,8 +129,8 @@ break backward compatibility. After all inline DTD and entity expansion are well-defined XML features. -.. _defusedxml: https://pypi.python.org/pypi/defusedxml/ -.. _defusedexpat: https://pypi.python.org/pypi/defusedexpat/ +.. _defusedxml: https://pypi.org/project/defusedxml/ +.. _defusedexpat: https://pypi.org/project/defusedexpat/ .. _Billion Laughs: https://en.wikipedia.org/wiki/Billion_laughs .. _ZIP bomb: https://en.wikipedia.org/wiki/Zip_bomb .. _DTD: https://en.wikipedia.org/wiki/Document_type_definition diff --git a/Doc/tutorial/whatnow.rst b/Doc/tutorial/whatnow.rst index 89dfa6a15700..f6ce4f4617e8 100644 --- a/Doc/tutorial/whatnow.rst +++ b/Doc/tutorial/whatnow.rst @@ -38,7 +38,7 @@ More Python resources: * https://docs.python.org: Fast access to Python's documentation. -* https://pypi.python.org/pypi: The Python Package Index, previously also nicknamed +* https://pypi.org: The Python Package Index, previously also nicknamed the Cheese Shop, is an index of user-created Python modules that are available for download. Once you begin releasing code, you can register it here so that others can find it. diff --git a/Doc/using/windows.rst b/Doc/using/windows.rst index f597476e333c..778b8843f236 100644 --- a/Doc/using/windows.rst +++ b/Doc/using/windows.rst @@ -242,7 +242,7 @@ The Windows-specific standard modules are documented in PyWin32 ------- -The `PyWin32 <https://pypi.python.org/pypi/pywin32>`_ module by Mark Hammond +The `PyWin32 <https://pypi.org/project/pywin32>`_ module by Mark Hammond is a collection of modules for advanced Windows-specific support. This includes utilities for: diff --git a/Doc/whatsnew/2.3.rst b/Doc/whatsnew/2.3.rst index 838ca38f3186..1ef2cb5f986c 100644 --- a/Doc/whatsnew/2.3.rst +++ b/Doc/whatsnew/2.3.rst @@ -659,7 +659,7 @@ The heart of the catalog is the new Distutils :command:`register` command. Running ``python setup.py register`` will collect the metadata describing a package, such as its name, version, maintainer, description, &c., and send it to a central catalog server. The resulting catalog is available from -https://pypi.python.org/pypi. +https://pypi.org. To make the catalog a bit more useful, a new optional *classifiers* keyword argument has been added to the Distutils :func:`setup` function. A list of diff --git a/Doc/whatsnew/2.5.rst b/Doc/whatsnew/2.5.rst index d2395e7097a2..6400bb108610 100644 --- a/Doc/whatsnew/2.5.rst +++ b/Doc/whatsnew/2.5.rst @@ -229,7 +229,7 @@ required packages. :: ) Another new enhancement to the Python package index at -https://pypi.python.org is storing source and binary archives for a +https://pypi.org is storing source and binary archives for a package. The new :command:`upload` Distutils command will upload a package to the repository. diff --git a/Doc/whatsnew/2.7.rst b/Doc/whatsnew/2.7.rst index 53333ebf7c1a..a18abe8141e7 100644 --- a/Doc/whatsnew/2.7.rst +++ b/Doc/whatsnew/2.7.rst @@ -1809,7 +1809,7 @@ new features were added. Most of these features were implemented by Michael Foord, unless otherwise noted. The enhanced version of the module is downloadable separately for use with Python versions 2.4 to 2.6, packaged as the :mod:`unittest2` package, from -https://pypi.python.org/pypi/unittest2. +https://pypi.org/project/unittest2. When used from the command line, the module can automatically discover tests. It's not as fancy as `py.test <http://pytest.org>`__ or diff --git a/Misc/NEWS.d/next/Documentation/2018-05-14-20-08-58.bpo-33503.Wvt0qg.rst b/Misc/NEWS.d/next/Documentation/2018-05-14-20-08-58.bpo-33503.Wvt0qg.rst new file mode 100644 index 000000000000..27025c31a036 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2018-05-14-20-08-58.bpo-33503.Wvt0qg.rst @@ -0,0 +1 @@ +Fix broken pypi link From webhook-mailer at python.org Wed May 16 11:31:32 2018 From: webhook-mailer at python.org (Eric V. Smith) Date: Wed, 16 May 2018 15:31:32 -0000 Subject: [Python-checkins] bpo-33536: Validate make_dataclass() field names. (GH-6906) Message-ID: <mailman.87.1526484694.2757.python-checkins@python.org> https://github.com/python/cpython/commit/4e81296b1874829912c687eba4d39361ab51e145 commit: 4e81296b1874829912c687eba4d39361ab51e145 branch: master author: Eric V. Smith <ericvsmith at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-16T11:31:29-04:00 summary: bpo-33536: Validate make_dataclass() field names. (GH-6906) files: A Misc/NEWS.d/next/Library/2018-05-16-10-07-40.bpo-33536._s0TE8.rst M Lib/dataclasses.py M Lib/test/test_dataclasses.py diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index bb77d3b4052b..2c5593bfc50d 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -3,6 +3,7 @@ import copy import types import inspect +import keyword __all__ = ['dataclass', 'field', @@ -1100,6 +1101,9 @@ class C(Base): # Copy namespace since we're going to mutate it. namespace = namespace.copy() + # While we're looking through the field names, validate that they + # are identifiers, are not keywords, and not duplicates. + seen = set() anns = {} for item in fields: if isinstance(item, str): @@ -1110,6 +1114,17 @@ class C(Base): elif len(item) == 3: name, tp, spec = item namespace[name] = spec + else: + raise TypeError(f'Invalid field: {item!r}') + + if not isinstance(name, str) or not name.isidentifier(): + raise TypeError(f'Field names must be valid identifers: {name!r}') + if keyword.iskeyword(name): + raise TypeError(f'Field names must not be keywords: {name!r}') + if name in seen: + raise TypeError(f'Field name duplicated: {name!r}') + + seen.add(name) anns[name] = tp namespace['__annotations__'] = anns diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index b251c04cb9a1..7c39b79142b2 100755 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -1826,114 +1826,6 @@ class R: self.assertEqual(new_sample.x, another_new_sample.x) self.assertEqual(sample.y, another_new_sample.y) - def test_helper_make_dataclass(self): - C = make_dataclass('C', - [('x', int), - ('y', int, field(default=5))], - namespace={'add_one': lambda self: self.x + 1}) - c = C(10) - self.assertEqual((c.x, c.y), (10, 5)) - self.assertEqual(c.add_one(), 11) - - - def test_helper_make_dataclass_no_mutate_namespace(self): - # Make sure a provided namespace isn't mutated. - ns = {} - C = make_dataclass('C', - [('x', int), - ('y', int, field(default=5))], - namespace=ns) - self.assertEqual(ns, {}) - - def test_helper_make_dataclass_base(self): - class Base1: - pass - class Base2: - pass - C = make_dataclass('C', - [('x', int)], - bases=(Base1, Base2)) - c = C(2) - self.assertIsInstance(c, C) - self.assertIsInstance(c, Base1) - self.assertIsInstance(c, Base2) - - def test_helper_make_dataclass_base_dataclass(self): - @dataclass - class Base1: - x: int - class Base2: - pass - C = make_dataclass('C', - [('y', int)], - bases=(Base1, Base2)) - with self.assertRaisesRegex(TypeError, 'required positional'): - c = C(2) - c = C(1, 2) - self.assertIsInstance(c, C) - self.assertIsInstance(c, Base1) - self.assertIsInstance(c, Base2) - - self.assertEqual((c.x, c.y), (1, 2)) - - def test_helper_make_dataclass_init_var(self): - def post_init(self, y): - self.x *= y - - C = make_dataclass('C', - [('x', int), - ('y', InitVar[int]), - ], - namespace={'__post_init__': post_init}, - ) - c = C(2, 3) - self.assertEqual(vars(c), {'x': 6}) - self.assertEqual(len(fields(c)), 1) - - def test_helper_make_dataclass_class_var(self): - C = make_dataclass('C', - [('x', int), - ('y', ClassVar[int], 10), - ('z', ClassVar[int], field(default=20)), - ]) - c = C(1) - self.assertEqual(vars(c), {'x': 1}) - self.assertEqual(len(fields(c)), 1) - self.assertEqual(C.y, 10) - self.assertEqual(C.z, 20) - - def test_helper_make_dataclass_other_params(self): - C = make_dataclass('C', - [('x', int), - ('y', ClassVar[int], 10), - ('z', ClassVar[int], field(default=20)), - ], - init=False) - # Make sure we have a repr, but no init. - self.assertNotIn('__init__', vars(C)) - self.assertIn('__repr__', vars(C)) - - # Make sure random other params don't work. - with self.assertRaisesRegex(TypeError, 'unexpected keyword argument'): - C = make_dataclass('C', - [], - xxinit=False) - - def test_helper_make_dataclass_no_types(self): - C = make_dataclass('Point', ['x', 'y', 'z']) - c = C(1, 2, 3) - self.assertEqual(vars(c), {'x': 1, 'y': 2, 'z': 3}) - self.assertEqual(C.__annotations__, {'x': 'typing.Any', - 'y': 'typing.Any', - 'z': 'typing.Any'}) - - C = make_dataclass('Point', ['x', ('y', int), 'z']) - c = C(1, 2, 3) - self.assertEqual(vars(c), {'x': 1, 'y': 2, 'z': 3}) - self.assertEqual(C.__annotations__, {'x': 'typing.Any', - 'y': int, - 'z': 'typing.Any'}) - class TestFieldNoAnnotation(unittest.TestCase): def test_field_without_annotation(self): @@ -2947,5 +2839,170 @@ def test_classvar_module_level_import(self): self.assertNotIn('not_iv4', c.__dict__) +class TestMakeDataclass(unittest.TestCase): + def test_simple(self): + C = make_dataclass('C', + [('x', int), + ('y', int, field(default=5))], + namespace={'add_one': lambda self: self.x + 1}) + c = C(10) + self.assertEqual((c.x, c.y), (10, 5)) + self.assertEqual(c.add_one(), 11) + + + def test_no_mutate_namespace(self): + # Make sure a provided namespace isn't mutated. + ns = {} + C = make_dataclass('C', + [('x', int), + ('y', int, field(default=5))], + namespace=ns) + self.assertEqual(ns, {}) + + def test_base(self): + class Base1: + pass + class Base2: + pass + C = make_dataclass('C', + [('x', int)], + bases=(Base1, Base2)) + c = C(2) + self.assertIsInstance(c, C) + self.assertIsInstance(c, Base1) + self.assertIsInstance(c, Base2) + + def test_base_dataclass(self): + @dataclass + class Base1: + x: int + class Base2: + pass + C = make_dataclass('C', + [('y', int)], + bases=(Base1, Base2)) + with self.assertRaisesRegex(TypeError, 'required positional'): + c = C(2) + c = C(1, 2) + self.assertIsInstance(c, C) + self.assertIsInstance(c, Base1) + self.assertIsInstance(c, Base2) + + self.assertEqual((c.x, c.y), (1, 2)) + + def test_init_var(self): + def post_init(self, y): + self.x *= y + + C = make_dataclass('C', + [('x', int), + ('y', InitVar[int]), + ], + namespace={'__post_init__': post_init}, + ) + c = C(2, 3) + self.assertEqual(vars(c), {'x': 6}) + self.assertEqual(len(fields(c)), 1) + + def test_class_var(self): + C = make_dataclass('C', + [('x', int), + ('y', ClassVar[int], 10), + ('z', ClassVar[int], field(default=20)), + ]) + c = C(1) + self.assertEqual(vars(c), {'x': 1}) + self.assertEqual(len(fields(c)), 1) + self.assertEqual(C.y, 10) + self.assertEqual(C.z, 20) + + def test_other_params(self): + C = make_dataclass('C', + [('x', int), + ('y', ClassVar[int], 10), + ('z', ClassVar[int], field(default=20)), + ], + init=False) + # Make sure we have a repr, but no init. + self.assertNotIn('__init__', vars(C)) + self.assertIn('__repr__', vars(C)) + + # Make sure random other params don't work. + with self.assertRaisesRegex(TypeError, 'unexpected keyword argument'): + C = make_dataclass('C', + [], + xxinit=False) + + def test_no_types(self): + C = make_dataclass('Point', ['x', 'y', 'z']) + c = C(1, 2, 3) + self.assertEqual(vars(c), {'x': 1, 'y': 2, 'z': 3}) + self.assertEqual(C.__annotations__, {'x': 'typing.Any', + 'y': 'typing.Any', + 'z': 'typing.Any'}) + + C = make_dataclass('Point', ['x', ('y', int), 'z']) + c = C(1, 2, 3) + self.assertEqual(vars(c), {'x': 1, 'y': 2, 'z': 3}) + self.assertEqual(C.__annotations__, {'x': 'typing.Any', + 'y': int, + 'z': 'typing.Any'}) + + def test_invalid_type_specification(self): + for bad_field in [(), + (1, 2, 3, 4), + ]: + with self.subTest(bad_field=bad_field): + with self.assertRaisesRegex(TypeError, r'Invalid field: '): + make_dataclass('C', ['a', bad_field]) + + # And test for things with no len(). + for bad_field in [float, + lambda x:x, + ]: + with self.subTest(bad_field=bad_field): + with self.assertRaisesRegex(TypeError, r'has no len\(\)'): + make_dataclass('C', ['a', bad_field]) + + def test_duplicate_field_names(self): + for field in ['a', 'ab']: + with self.subTest(field=field): + with self.assertRaisesRegex(TypeError, 'Field name duplicated'): + make_dataclass('C', [field, 'a', field]) + + def test_keyword_field_names(self): + for field in ['for', 'async', 'await', 'as']: + with self.subTest(field=field): + with self.assertRaisesRegex(TypeError, 'must not be keywords'): + make_dataclass('C', ['a', field]) + with self.assertRaisesRegex(TypeError, 'must not be keywords'): + make_dataclass('C', [field]) + with self.assertRaisesRegex(TypeError, 'must not be keywords'): + make_dataclass('C', [field, 'a']) + + def test_non_identifier_field_names(self): + for field in ['()', 'x,y', '*', '2 at 3', '', 'little johnny tables']: + with self.subTest(field=field): + with self.assertRaisesRegex(TypeError, 'must be valid identifers'): + make_dataclass('C', ['a', field]) + with self.assertRaisesRegex(TypeError, 'must be valid identifers'): + make_dataclass('C', [field]) + with self.assertRaisesRegex(TypeError, 'must be valid identifers'): + make_dataclass('C', [field, 'a']) + + def test_underscore_field_names(self): + # Unlike namedtuple, it's okay if dataclass field names have + # an underscore. + make_dataclass('C', ['_', '_a', 'a_a', 'a_']) + + def test_funny_class_names_names(self): + # No reason to prevent weird class names, since + # types.new_class allows them. + for classname in ['()', 'x,y', '*', '2 at 3', '']: + with self.subTest(classname=classname): + C = make_dataclass(classname, ['a', 'b']) + self.assertEqual(C.__name__, classname) + + if __name__ == '__main__': unittest.main() diff --git a/Misc/NEWS.d/next/Library/2018-05-16-10-07-40.bpo-33536._s0TE8.rst b/Misc/NEWS.d/next/Library/2018-05-16-10-07-40.bpo-33536._s0TE8.rst new file mode 100644 index 000000000000..2c1024180d34 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-16-10-07-40.bpo-33536._s0TE8.rst @@ -0,0 +1,2 @@ +dataclasses.make_dataclass now checks for invalid field names and duplicate +fields. Also, added a check for invalid field specifications. From webhook-mailer at python.org Wed May 16 11:34:50 2018 From: webhook-mailer at python.org (Gregory P. Smith) Date: Wed, 16 May 2018 15:34:50 -0000 Subject: [Python-checkins] bpo-24318: Rewrite the README PGO section. (#6863) Message-ID: <mailman.88.1526484892.2757.python-checkins@python.org> https://github.com/python/cpython/commit/93f9a8a5afb58b1d2e4f27bb46d3d4e0fa8c08f0 commit: 93f9a8a5afb58b1d2e4f27bb46d3d4e0fa8c08f0 branch: master author: Gregory P. Smith <greg at krypto.org> committer: GitHub <noreply at github.com> date: 2018-05-16T10:34:47-05:00 summary: bpo-24318: Rewrite the README PGO section. (#6863) * bpo-24318: Rewrite the README PGO section. Merged from a phone on an airplane. :) files: M README.rst diff --git a/README.rst b/README.rst index 5420558f0dca..d30b237a0119 100644 --- a/README.rst +++ b/README.rst @@ -93,25 +93,26 @@ Profile Guided Optimization ^^^^^^^^^^^^^^^^^^^^^^^^^^^ PGO takes advantage of recent versions of the GCC or Clang compilers. If used, -either via ``configure --enable-optimizations`` above or by manually running -``make profile-opt`` regardless of configure flags it will do several steps. - -First, the entire Python directory is cleaned of temporary files that may have -resulted in a previous compilation. - -Then, an instrumented version of the interpreter is built, using suitable -compiler flags for each flavour. Note that this is just an intermediary step. -The binary resulting from this step is not good for real life workloads as -it has profiling instructions embedded inside. - -After this instrumented version of the interpreter is built, the Makefile will -automatically run a training workload. This is necessary in order to profile -the interpreter execution. Note also that any output, both stdout and stderr, -that may appear at this step is suppressed. - -Finally, the last step is to rebuild the interpreter, using the information -collected in the previous one. The end result will be a Python binary that is -optimized and suitable for distribution or production installation. +either via ``configure --enable-optimizations`` or by manually running +``make profile-opt`` regardless of configure flags, the optimized build +process will perform the following steps: + +The entire Python directory is cleaned of temporary files that may have +resulted from a previous compilation. + +An instrumented version of the interpreter is built, using suitable compiler +flags for each flavour. Note that this is just an intermediary step. The +binary resulting from this step is not good for real life workloads as it has +profiling instructions embedded inside. + +After the instrumented interpreter is built, the Makefile will run a training +workload. This is necessary in order to profile the interpreter execution. +Note also that any output, both stdout and stderr, that may appear at this step +is suppressed. + +The final step is to build the actual interpreter, using the information +collected from the instrumented one. The end result will be a Python binary +that is optimized; suitable for distribution or production installation. Link Time Optimization From webhook-mailer at python.org Wed May 16 11:51:24 2018 From: webhook-mailer at python.org (Petr Viktorin) Date: Wed, 16 May 2018 15:51:24 -0000 Subject: [Python-checkins] bpo-28167: Remove platform.linux_distribution (GH-6871) Message-ID: <mailman.89.1526485888.2757.python-checkins@python.org> https://github.com/python/cpython/commit/8b94b41ab7b12f745dea744e8940631318816935 commit: 8b94b41ab7b12f745dea744e8940631318816935 branch: master author: Petr Viktorin <encukou at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-16T11:51:18-04:00 summary: bpo-28167: Remove platform.linux_distribution (GH-6871) * test_ssl: Remove skip_if_broken_ubuntu_ssl We no longer support OpenSSL 0.9.8.15.15. * bpo-28167: Remove platform.linux_distribution files: A Misc/NEWS.d/next/Library/2018-05-15-13-49-13.bpo-28167.p4RdQt.rst M Doc/library/platform.rst M Lib/platform.py M Lib/test/test_platform.py M Lib/test/test_ssl.py diff --git a/Doc/library/platform.rst b/Doc/library/platform.rst index f5cb52cb4745..5b2ff1b497b0 100644 --- a/Doc/library/platform.rst +++ b/Doc/library/platform.rst @@ -243,33 +243,6 @@ Mac OS Platform Unix Platforms -------------- - -.. function:: dist(distname='', version='', id='', supported_dists=('SuSE','debian','redhat','mandrake',...)) - - This is another name for :func:`linux_distribution`. - - .. deprecated-removed:: 3.5 3.8 - See alternative like the `distro <https://pypi.org/project/distro>`_ package. - -.. function:: linux_distribution(distname='', version='', id='', supported_dists=('SuSE','debian','redhat','mandrake',...), full_distribution_name=1) - - Tries to determine the name of the Linux OS distribution name. - - ``supported_dists`` may be given to define the set of Linux distributions to - look for. It defaults to a list of currently supported Linux distributions - identified by their release file name. - - If ``full_distribution_name`` is true (default), the full distribution read - from the OS is returned. Otherwise the short name taken from - ``supported_dists`` is used. - - Returns a tuple ``(distname,version,id)`` which defaults to the args given as - parameters. ``id`` is the item in parentheses after the version number. It - is usually the version codename. - - .. deprecated-removed:: 3.5 3.8 - See alternative like the `distro <https://pypi.org/project/distro>`_ package. - .. function:: libc_ver(executable=sys.executable, lib='', version='', chunksize=2048) Tries to determine the libc version against which the file executable (defaults diff --git a/Lib/platform.py b/Lib/platform.py index 20f9817f4ffb..6051f2b59019 100755 --- a/Lib/platform.py +++ b/Lib/platform.py @@ -132,10 +132,6 @@ # Standard Unix uses /dev/null DEV_NULL = '/dev/null' -# Directory to search for configuration information on Unix. -# Constant used by test_platform to test linux_distribution(). -_UNIXCONFDIR = '/etc' - ### Platform specific APIs _libc_search = re.compile(b'(__libc_init)' @@ -249,138 +245,6 @@ def _dist_try_harder(distname, version, id): return distname, version, id -_release_filename = re.compile(r'(\w+)[-_](release|version)', re.ASCII) -_lsb_release_version = re.compile(r'(.+)' - r' release ' - r'([\d.]+)' - r'[^(]*(?:\((.+)\))?', re.ASCII) -_release_version = re.compile(r'([^0-9]+)' - r'(?: release )?' - r'([\d.]+)' - r'[^(]*(?:\((.+)\))?', re.ASCII) - -# See also http://www.novell.com/coolsolutions/feature/11251.html -# and http://linuxmafia.com/faq/Admin/release-files.html -# and http://data.linux-ntfs.org/rpm/whichrpm -# and http://www.die.net/doc/linux/man/man1/lsb_release.1.html - -_supported_dists = ( - 'SuSE', 'debian', 'fedora', 'redhat', 'centos', - 'mandrake', 'mandriva', 'rocks', 'slackware', 'yellowdog', 'gentoo', - 'UnitedLinux', 'turbolinux', 'arch', 'mageia') - -def _parse_release_file(firstline): - - # Default to empty 'version' and 'id' strings. Both defaults are used - # when 'firstline' is empty. 'id' defaults to empty when an id can not - # be deduced. - version = '' - id = '' - - # Parse the first line - m = _lsb_release_version.match(firstline) - if m is not None: - # LSB format: "distro release x.x (codename)" - return tuple(m.groups()) - - # Pre-LSB format: "distro x.x (codename)" - m = _release_version.match(firstline) - if m is not None: - return tuple(m.groups()) - - # Unknown format... take the first two words - l = firstline.strip().split() - if l: - version = l[0] - if len(l) > 1: - id = l[1] - return '', version, id - -def linux_distribution(distname='', version='', id='', - - supported_dists=_supported_dists, - full_distribution_name=1): - import warnings - warnings.warn("dist() and linux_distribution() functions are deprecated " - "in Python 3.5", DeprecationWarning, stacklevel=2) - return _linux_distribution(distname, version, id, supported_dists, - full_distribution_name) - -def _linux_distribution(distname, version, id, supported_dists, - full_distribution_name): - - """ Tries to determine the name of the Linux OS distribution name. - - The function first looks for a distribution release file in - /etc and then reverts to _dist_try_harder() in case no - suitable files are found. - - supported_dists may be given to define the set of Linux - distributions to look for. It defaults to a list of currently - supported Linux distributions identified by their release file - name. - - If full_distribution_name is true (default), the full - distribution read from the OS is returned. Otherwise the short - name taken from supported_dists is used. - - Returns a tuple (distname, version, id) which default to the - args given as parameters. - - """ - try: - etc = os.listdir(_UNIXCONFDIR) - except OSError: - # Probably not a Unix system - return distname, version, id - etc.sort() - for file in etc: - m = _release_filename.match(file) - if m is not None: - _distname, dummy = m.groups() - if _distname in supported_dists: - distname = _distname - break - else: - return _dist_try_harder(distname, version, id) - - # Read the first line - with open(os.path.join(_UNIXCONFDIR, file), 'r', - encoding='utf-8', errors='surrogateescape') as f: - firstline = f.readline() - _distname, _version, _id = _parse_release_file(firstline) - - if _distname and full_distribution_name: - distname = _distname - if _version: - version = _version - if _id: - id = _id - return distname, version, id - -# To maintain backwards compatibility: - -def dist(distname='', version='', id='', - - supported_dists=_supported_dists): - - """ Tries to determine the name of the Linux OS distribution name. - - The function first looks for a distribution release file in - /etc and then reverts to _dist_try_harder() in case no - suitable files are found. - - Returns a tuple (distname, version, id) which default to the - args given as parameters. - - """ - import warnings - warnings.warn("dist() and linux_distribution() functions are deprecated " - "in Python 3.5", DeprecationWarning, stacklevel=2) - return _linux_distribution(distname, version, id, - supported_dists=supported_dists, - full_distribution_name=0) - def popen(cmd, mode='r', bufsize=-1): """ Portable popen() interface. @@ -1338,26 +1202,11 @@ def platform(aliased=0, terse=0): platform = _platform(system, release, version, csd) elif system in ('Linux',): - # Linux based systems - with warnings.catch_warnings(): - # see issue #1322 for more information - warnings.filterwarnings( - 'ignore', - r'dist\(\) and linux_distribution\(\) ' - 'functions are deprecated .*', - DeprecationWarning, - ) - distname, distversion, distid = dist('') - if distname and not terse: - platform = _platform(system, release, machine, processor, - 'with', - distname, distversion, distid) - else: - # If the distribution name is unknown check for libc vs. glibc - libcname, libcversion = libc_ver(sys.executable) - platform = _platform(system, release, machine, processor, - 'with', - libcname+libcversion) + # check for libc vs. glibc + libcname, libcversion = libc_ver(sys.executable) + platform = _platform(system, release, machine, processor, + 'with', + libcname+libcversion) elif system == 'Java': # Java platforms r, v, vminfo, (os_name, os_version, os_arch) = java_ver() diff --git a/Lib/test/test_platform.py b/Lib/test/test_platform.py index 5f1e28a5d950..7e3e40114b47 100644 --- a/Lib/test/test_platform.py +++ b/Lib/test/test_platform.py @@ -259,16 +259,6 @@ def test_mac_ver_with_fork(self): self.assertEqual(cpid, pid) self.assertEqual(sts, 0) - def test_dist(self): - with warnings.catch_warnings(): - warnings.filterwarnings( - 'ignore', - r'dist\(\) and linux_distribution\(\) ' - 'functions are deprecated .*', - PendingDeprecationWarning, - ) - res = platform.dist() - def test_libc_ver(self): import os if os.path.isdir(sys.executable) and \ @@ -279,23 +269,6 @@ def test_libc_ver(self): executable = sys.executable res = platform.libc_ver(executable) - def test_parse_release_file(self): - - for input, output in ( - # Examples of release file contents: - ('SuSE Linux 9.3 (x86-64)', ('SuSE Linux ', '9.3', 'x86-64')), - ('SUSE LINUX 10.1 (X86-64)', ('SUSE LINUX ', '10.1', 'X86-64')), - ('SUSE LINUX 10.1 (i586)', ('SUSE LINUX ', '10.1', 'i586')), - ('Fedora Core release 5 (Bordeaux)', ('Fedora Core', '5', 'Bordeaux')), - ('Red Hat Linux release 8.0 (Psyche)', ('Red Hat Linux', '8.0', 'Psyche')), - ('Red Hat Linux release 9 (Shrike)', ('Red Hat Linux', '9', 'Shrike')), - ('Red Hat Enterprise Linux release 4 (Nahant)', ('Red Hat Enterprise Linux', '4', 'Nahant')), - ('CentOS release 4', ('CentOS', '4', None)), - ('Rocks release 4.2.1 (Cydonia)', ('Rocks', '4.2.1', 'Cydonia')), - ('', ('', '', '')), # If there's nothing there. - ): - self.assertEqual(platform._parse_release_file(input), output) - def test_popen(self): mswindows = (sys.platform == "win32") @@ -328,43 +301,5 @@ def test_popen(self): returncode = ret >> 8 self.assertEqual(returncode, len(data)) - def test_linux_distribution_encoding(self): - # Issue #17429 - with tempfile.TemporaryDirectory() as tempdir: - filename = os.path.join(tempdir, 'fedora-release') - with open(filename, 'w', encoding='utf-8') as f: - f.write('Fedora release 19 (Schr\xf6dinger\u2019s Cat)\n') - - with mock.patch('platform._UNIXCONFDIR', tempdir): - with warnings.catch_warnings(): - warnings.filterwarnings( - 'ignore', - r'dist\(\) and linux_distribution\(\) ' - 'functions are deprecated .*', - PendingDeprecationWarning, - ) - distname, version, distid = platform.linux_distribution() - - self.assertEqual(distname, 'Fedora') - self.assertEqual(version, '19') - self.assertEqual(distid, 'Schr\xf6dinger\u2019s Cat') - - -class DeprecationTest(unittest.TestCase): - - def test_dist_deprecation(self): - with self.assertWarns(DeprecationWarning) as cm: - platform.dist() - self.assertEqual(str(cm.warning), - 'dist() and linux_distribution() functions are ' - 'deprecated in Python 3.5') - - def test_linux_distribution_deprecation(self): - with self.assertWarns(DeprecationWarning) as cm: - platform.linux_distribution() - self.assertEqual(str(cm.warning), - 'dist() and linux_distribution() functions are ' - 'deprecated in Python 3.5') - if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 36580d55b9e2..71380797748e 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -181,22 +181,6 @@ def asn1time(cert_time): return cert_time -# Issue #9415: Ubuntu hijacks their OpenSSL and forcefully disables SSLv2 -def skip_if_broken_ubuntu_ssl(func): - if hasattr(ssl, 'PROTOCOL_SSLv2'): - @functools.wraps(func) - def f(*args, **kwargs): - try: - ssl.SSLContext(ssl.PROTOCOL_SSLv2) - except ssl.SSLError: - if (ssl.OPENSSL_VERSION_INFO == (0, 9, 8, 15, 15) and - platform.linux_distribution() == ('debian', 'squeeze/sid', '')): - raise unittest.SkipTest("Patched Ubuntu OpenSSL breaks behaviour") - return func(*args, **kwargs) - return f - else: - return func - needs_sni = unittest.skipUnless(ssl.HAS_SNI, "SNI support needed for this test") @@ -975,7 +959,6 @@ def test_connect_ex_error(self): class ContextTests(unittest.TestCase): - @skip_if_broken_ubuntu_ssl def test_constructor(self): for protocol in PROTOCOLS: ssl.SSLContext(protocol) @@ -984,7 +967,6 @@ def test_constructor(self): self.assertRaises(ValueError, ssl.SSLContext, -1) self.assertRaises(ValueError, ssl.SSLContext, 42) - @skip_if_broken_ubuntu_ssl def test_protocol(self): for proto in PROTOCOLS: ctx = ssl.SSLContext(proto) @@ -1018,7 +1000,6 @@ def test_get_ciphers(self): self.assertIn('AES256-GCM-SHA384', names) self.assertIn('AES128-GCM-SHA256', names) - @skip_if_broken_ubuntu_ssl def test_options(self): ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) # OP_ALL | OP_NO_SSLv2 | OP_NO_SSLv3 is the default value @@ -1333,7 +1314,6 @@ def test_load_dh_params(self): with self.assertRaises(ssl.SSLError) as cm: ctx.load_dh_params(CERTFILE) - @skip_if_broken_ubuntu_ssl def test_session_stats(self): for proto in PROTOCOLS: ctx = ssl.SSLContext(proto) @@ -2554,7 +2534,6 @@ def try_protocol_combo(server_protocol, client_protocol, expect_success, class ThreadedTests(unittest.TestCase): - @skip_if_broken_ubuntu_ssl def test_echo(self): """Basic test of an SSL client connecting to a server""" if support.verbose: @@ -2923,7 +2902,6 @@ def test_ssl_cert_verify_error(self): self.assertIn(msg, repr(e)) self.assertIn('certificate verify failed', repr(e)) - @skip_if_broken_ubuntu_ssl @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv2'), "OpenSSL is compiled without SSLv2 support") def test_protocol_sslv2(self): @@ -2947,7 +2925,6 @@ def test_protocol_sslv2(self): try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_TLS, False, client_options=ssl.OP_NO_TLSv1) - @skip_if_broken_ubuntu_ssl def test_PROTOCOL_TLS(self): """Connecting to an SSLv23 server with various client options""" if support.verbose: @@ -2987,7 +2964,6 @@ def test_PROTOCOL_TLS(self): server_options=ssl.OP_NO_TLSv1) - @skip_if_broken_ubuntu_ssl @unittest.skipUnless(hasattr(ssl, 'PROTOCOL_SSLv3'), "OpenSSL is compiled without SSLv3 support") def test_protocol_sslv3(self): @@ -3007,7 +2983,6 @@ def test_protocol_sslv3(self): try_protocol_combo(ssl.PROTOCOL_SSLv3, ssl.PROTOCOL_TLS, False, client_options=ssl.OP_NO_SSLv2) - @skip_if_broken_ubuntu_ssl def test_protocol_tlsv1(self): """Connecting to a TLSv1 server with various client options""" if support.verbose: @@ -3022,7 +2997,6 @@ def test_protocol_tlsv1(self): try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLS, False, client_options=ssl.OP_NO_TLSv1) - @skip_if_broken_ubuntu_ssl @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_1"), "TLS version 1.1 not supported.") def test_protocol_tlsv1_1(self): @@ -3042,7 +3016,6 @@ def test_protocol_tlsv1_1(self): try_protocol_combo(ssl.PROTOCOL_TLSv1_1, ssl.PROTOCOL_TLSv1, False) try_protocol_combo(ssl.PROTOCOL_TLSv1, ssl.PROTOCOL_TLSv1_1, False) - @skip_if_broken_ubuntu_ssl @unittest.skipUnless(hasattr(ssl, "PROTOCOL_TLSv1_2"), "TLS version 1.2 not supported.") def test_protocol_tlsv1_2(self): @@ -4087,24 +4060,16 @@ def test_main(verbose=False): if support.verbose: import warnings plats = { - 'Linux': platform.linux_distribution, 'Mac': platform.mac_ver, 'Windows': platform.win32_ver, } - with warnings.catch_warnings(): - warnings.filterwarnings( - 'ignore', - r'dist\(\) and linux_distribution\(\) ' - 'functions are deprecated .*', - PendingDeprecationWarning, - ) - for name, func in plats.items(): - plat = func() - if plat and plat[0]: - plat = '%s %r' % (name, plat) - break - else: - plat = repr(platform.platform()) + for name, func in plats.items(): + plat = func() + if plat and plat[0]: + plat = '%s %r' % (name, plat) + break + else: + plat = repr(platform.platform()) print("test_ssl: testing with %r %r" % (ssl.OPENSSL_VERSION, ssl.OPENSSL_VERSION_INFO)) print(" under %s" % plat) diff --git a/Misc/NEWS.d/next/Library/2018-05-15-13-49-13.bpo-28167.p4RdQt.rst b/Misc/NEWS.d/next/Library/2018-05-15-13-49-13.bpo-28167.p4RdQt.rst new file mode 100644 index 000000000000..0079c8a09ced --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-15-13-49-13.bpo-28167.p4RdQt.rst @@ -0,0 +1 @@ +Remove platform.linux_distribution, which was deprecated since 3.5. From webhook-mailer at python.org Wed May 16 12:27:06 2018 From: webhook-mailer at python.org (=?utf-8?q?=C5=81ukasz?= Langa) Date: Wed, 16 May 2018 16:27:06 -0000 Subject: [Python-checkins] Fix ClassVar as string fails when getting type hints (GH-6824) Message-ID: <mailman.90.1526488027.2757.python-checkins@python.org> https://github.com/python/cpython/commit/2d2d3b170bdebc085900bfa2a3bc81b5d132d0a8 commit: 2d2d3b170bdebc085900bfa2a3bc81b5d132d0a8 branch: master author: Nina Zakharenko <nzakharenko at gmail.com> committer: ?ukasz Langa <lukasz at langa.pl> date: 2018-05-16T12:27:03-04:00 summary: Fix ClassVar as string fails when getting type hints (GH-6824) files: A Misc/NEWS.d/next/Library/2018-05-15-18-02-03.bpo-0.pj2Mbb.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 314716cd7de3..be768f12fb4c 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -1599,6 +1599,30 @@ class D(C): # verify that @no_type_check never affects bases self.assertEqual(get_type_hints(C.meth), {'x': int}) + def test_no_type_check_forward_ref_as_string(self): + class C: + foo: typing.ClassVar[int] = 7 + class D: + foo: ClassVar[int] = 7 + class E: + foo: 'typing.ClassVar[int]' = 7 + class F: + foo: 'ClassVar[int]' = 7 + + expected_result = {'foo': typing.ClassVar[int]} + for clazz in [C, D, E, F]: + self.assertEqual(get_type_hints(clazz), expected_result) + + def test_nested_classvar_fails_forward_ref_check(self): + class E: + foo: 'typing.ClassVar[typing.ClassVar[int]]' = 7 + class F: + foo: ClassVar['ClassVar[int]'] = 7 + + for clazz in [E, F]: + with self.assertRaises(TypeError): + get_type_hints(clazz) + def test_meta_no_type_check(self): @no_type_check_decorator diff --git a/Lib/typing.py b/Lib/typing.py index 8025dfd93262..b10615c07fbd 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -106,7 +106,7 @@ # legitimate imports of those modules. -def _type_check(arg, msg): +def _type_check(arg, msg, is_argument=False): """Check that the argument is a type, and return it (internal helper). As a special case, accept None and return type(None) instead. Also wrap strings @@ -118,12 +118,16 @@ def _type_check(arg, msg): We append the repr() of the actual value (truncated to 100 chars). """ + invalid_generic_forms = (Generic, _Protocol) + if not is_argument: + invalid_generic_forms = invalid_generic_forms + (ClassVar, ) + if arg is None: return type(None) if isinstance(arg, str): return ForwardRef(arg) if (isinstance(arg, _GenericAlias) and - arg.__origin__ in (Generic, _Protocol, ClassVar)): + arg.__origin__ in invalid_generic_forms): raise TypeError(f"{arg} is not valid as type argument") if (isinstance(arg, _SpecialForm) and arg is not Any or arg in (Generic, _Protocol)): @@ -464,9 +468,10 @@ class ForwardRef(_Final, _root=True): """Internal wrapper to hold a forward reference.""" __slots__ = ('__forward_arg__', '__forward_code__', - '__forward_evaluated__', '__forward_value__') + '__forward_evaluated__', '__forward_value__', + '__forward_is_argument__') - def __init__(self, arg): + def __init__(self, arg, is_argument=False): if not isinstance(arg, str): raise TypeError(f"Forward reference must be a string -- got {arg!r}") try: @@ -477,6 +482,7 @@ def __init__(self, arg): self.__forward_code__ = code self.__forward_evaluated__ = False self.__forward_value__ = None + self.__forward_is_argument__ = is_argument def _evaluate(self, globalns, localns): if not self.__forward_evaluated__ or localns is not globalns: @@ -488,7 +494,8 @@ def _evaluate(self, globalns, localns): localns = globalns self.__forward_value__ = _type_check( eval(self.__forward_code__, globalns, localns), - "Forward references must evaluate to types.") + "Forward references must evaluate to types.", + is_argument=self.__forward_is_argument__) self.__forward_evaluated__ = True return self.__forward_value__ @@ -998,7 +1005,7 @@ def get_type_hints(obj, globalns=None, localns=None): if value is None: value = type(None) if isinstance(value, str): - value = ForwardRef(value) + value = ForwardRef(value, is_argument=True) value = _eval_type(value, base_globals, localns) hints[name] = value return hints diff --git a/Misc/NEWS.d/next/Library/2018-05-15-18-02-03.bpo-0.pj2Mbb.rst b/Misc/NEWS.d/next/Library/2018-05-15-18-02-03.bpo-0.pj2Mbb.rst new file mode 100644 index 000000000000..ba8514cdd895 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-15-18-02-03.bpo-0.pj2Mbb.rst @@ -0,0 +1 @@ +Fix failure in `typing.get_type_hints()` when ClassVar was provided as a string forward reference. From webhook-mailer at python.org Wed May 16 12:28:25 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 16 May 2018 16:28:25 -0000 Subject: [Python-checkins] bpo-33536: Validate make_dataclass() field names. (GH-6906) Message-ID: <mailman.91.1526488107.2757.python-checkins@python.org> https://github.com/python/cpython/commit/6409e759df0654f4a081eb4a50aadde995382043 commit: 6409e759df0654f4a081eb4a50aadde995382043 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-16T09:28:22-07:00 summary: bpo-33536: Validate make_dataclass() field names. (GH-6906) (cherry picked from commit 4e81296b1874829912c687eba4d39361ab51e145) Co-authored-by: Eric V. Smith <ericvsmith at users.noreply.github.com> files: A Misc/NEWS.d/next/Library/2018-05-16-10-07-40.bpo-33536._s0TE8.rst M Lib/dataclasses.py M Lib/test/test_dataclasses.py diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index bb77d3b4052b..2c5593bfc50d 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -3,6 +3,7 @@ import copy import types import inspect +import keyword __all__ = ['dataclass', 'field', @@ -1100,6 +1101,9 @@ class C(Base): # Copy namespace since we're going to mutate it. namespace = namespace.copy() + # While we're looking through the field names, validate that they + # are identifiers, are not keywords, and not duplicates. + seen = set() anns = {} for item in fields: if isinstance(item, str): @@ -1110,6 +1114,17 @@ class C(Base): elif len(item) == 3: name, tp, spec = item namespace[name] = spec + else: + raise TypeError(f'Invalid field: {item!r}') + + if not isinstance(name, str) or not name.isidentifier(): + raise TypeError(f'Field names must be valid identifers: {name!r}') + if keyword.iskeyword(name): + raise TypeError(f'Field names must not be keywords: {name!r}') + if name in seen: + raise TypeError(f'Field name duplicated: {name!r}') + + seen.add(name) anns[name] = tp namespace['__annotations__'] = anns diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index b251c04cb9a1..7c39b79142b2 100755 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -1826,114 +1826,6 @@ class R: self.assertEqual(new_sample.x, another_new_sample.x) self.assertEqual(sample.y, another_new_sample.y) - def test_helper_make_dataclass(self): - C = make_dataclass('C', - [('x', int), - ('y', int, field(default=5))], - namespace={'add_one': lambda self: self.x + 1}) - c = C(10) - self.assertEqual((c.x, c.y), (10, 5)) - self.assertEqual(c.add_one(), 11) - - - def test_helper_make_dataclass_no_mutate_namespace(self): - # Make sure a provided namespace isn't mutated. - ns = {} - C = make_dataclass('C', - [('x', int), - ('y', int, field(default=5))], - namespace=ns) - self.assertEqual(ns, {}) - - def test_helper_make_dataclass_base(self): - class Base1: - pass - class Base2: - pass - C = make_dataclass('C', - [('x', int)], - bases=(Base1, Base2)) - c = C(2) - self.assertIsInstance(c, C) - self.assertIsInstance(c, Base1) - self.assertIsInstance(c, Base2) - - def test_helper_make_dataclass_base_dataclass(self): - @dataclass - class Base1: - x: int - class Base2: - pass - C = make_dataclass('C', - [('y', int)], - bases=(Base1, Base2)) - with self.assertRaisesRegex(TypeError, 'required positional'): - c = C(2) - c = C(1, 2) - self.assertIsInstance(c, C) - self.assertIsInstance(c, Base1) - self.assertIsInstance(c, Base2) - - self.assertEqual((c.x, c.y), (1, 2)) - - def test_helper_make_dataclass_init_var(self): - def post_init(self, y): - self.x *= y - - C = make_dataclass('C', - [('x', int), - ('y', InitVar[int]), - ], - namespace={'__post_init__': post_init}, - ) - c = C(2, 3) - self.assertEqual(vars(c), {'x': 6}) - self.assertEqual(len(fields(c)), 1) - - def test_helper_make_dataclass_class_var(self): - C = make_dataclass('C', - [('x', int), - ('y', ClassVar[int], 10), - ('z', ClassVar[int], field(default=20)), - ]) - c = C(1) - self.assertEqual(vars(c), {'x': 1}) - self.assertEqual(len(fields(c)), 1) - self.assertEqual(C.y, 10) - self.assertEqual(C.z, 20) - - def test_helper_make_dataclass_other_params(self): - C = make_dataclass('C', - [('x', int), - ('y', ClassVar[int], 10), - ('z', ClassVar[int], field(default=20)), - ], - init=False) - # Make sure we have a repr, but no init. - self.assertNotIn('__init__', vars(C)) - self.assertIn('__repr__', vars(C)) - - # Make sure random other params don't work. - with self.assertRaisesRegex(TypeError, 'unexpected keyword argument'): - C = make_dataclass('C', - [], - xxinit=False) - - def test_helper_make_dataclass_no_types(self): - C = make_dataclass('Point', ['x', 'y', 'z']) - c = C(1, 2, 3) - self.assertEqual(vars(c), {'x': 1, 'y': 2, 'z': 3}) - self.assertEqual(C.__annotations__, {'x': 'typing.Any', - 'y': 'typing.Any', - 'z': 'typing.Any'}) - - C = make_dataclass('Point', ['x', ('y', int), 'z']) - c = C(1, 2, 3) - self.assertEqual(vars(c), {'x': 1, 'y': 2, 'z': 3}) - self.assertEqual(C.__annotations__, {'x': 'typing.Any', - 'y': int, - 'z': 'typing.Any'}) - class TestFieldNoAnnotation(unittest.TestCase): def test_field_without_annotation(self): @@ -2947,5 +2839,170 @@ def test_classvar_module_level_import(self): self.assertNotIn('not_iv4', c.__dict__) +class TestMakeDataclass(unittest.TestCase): + def test_simple(self): + C = make_dataclass('C', + [('x', int), + ('y', int, field(default=5))], + namespace={'add_one': lambda self: self.x + 1}) + c = C(10) + self.assertEqual((c.x, c.y), (10, 5)) + self.assertEqual(c.add_one(), 11) + + + def test_no_mutate_namespace(self): + # Make sure a provided namespace isn't mutated. + ns = {} + C = make_dataclass('C', + [('x', int), + ('y', int, field(default=5))], + namespace=ns) + self.assertEqual(ns, {}) + + def test_base(self): + class Base1: + pass + class Base2: + pass + C = make_dataclass('C', + [('x', int)], + bases=(Base1, Base2)) + c = C(2) + self.assertIsInstance(c, C) + self.assertIsInstance(c, Base1) + self.assertIsInstance(c, Base2) + + def test_base_dataclass(self): + @dataclass + class Base1: + x: int + class Base2: + pass + C = make_dataclass('C', + [('y', int)], + bases=(Base1, Base2)) + with self.assertRaisesRegex(TypeError, 'required positional'): + c = C(2) + c = C(1, 2) + self.assertIsInstance(c, C) + self.assertIsInstance(c, Base1) + self.assertIsInstance(c, Base2) + + self.assertEqual((c.x, c.y), (1, 2)) + + def test_init_var(self): + def post_init(self, y): + self.x *= y + + C = make_dataclass('C', + [('x', int), + ('y', InitVar[int]), + ], + namespace={'__post_init__': post_init}, + ) + c = C(2, 3) + self.assertEqual(vars(c), {'x': 6}) + self.assertEqual(len(fields(c)), 1) + + def test_class_var(self): + C = make_dataclass('C', + [('x', int), + ('y', ClassVar[int], 10), + ('z', ClassVar[int], field(default=20)), + ]) + c = C(1) + self.assertEqual(vars(c), {'x': 1}) + self.assertEqual(len(fields(c)), 1) + self.assertEqual(C.y, 10) + self.assertEqual(C.z, 20) + + def test_other_params(self): + C = make_dataclass('C', + [('x', int), + ('y', ClassVar[int], 10), + ('z', ClassVar[int], field(default=20)), + ], + init=False) + # Make sure we have a repr, but no init. + self.assertNotIn('__init__', vars(C)) + self.assertIn('__repr__', vars(C)) + + # Make sure random other params don't work. + with self.assertRaisesRegex(TypeError, 'unexpected keyword argument'): + C = make_dataclass('C', + [], + xxinit=False) + + def test_no_types(self): + C = make_dataclass('Point', ['x', 'y', 'z']) + c = C(1, 2, 3) + self.assertEqual(vars(c), {'x': 1, 'y': 2, 'z': 3}) + self.assertEqual(C.__annotations__, {'x': 'typing.Any', + 'y': 'typing.Any', + 'z': 'typing.Any'}) + + C = make_dataclass('Point', ['x', ('y', int), 'z']) + c = C(1, 2, 3) + self.assertEqual(vars(c), {'x': 1, 'y': 2, 'z': 3}) + self.assertEqual(C.__annotations__, {'x': 'typing.Any', + 'y': int, + 'z': 'typing.Any'}) + + def test_invalid_type_specification(self): + for bad_field in [(), + (1, 2, 3, 4), + ]: + with self.subTest(bad_field=bad_field): + with self.assertRaisesRegex(TypeError, r'Invalid field: '): + make_dataclass('C', ['a', bad_field]) + + # And test for things with no len(). + for bad_field in [float, + lambda x:x, + ]: + with self.subTest(bad_field=bad_field): + with self.assertRaisesRegex(TypeError, r'has no len\(\)'): + make_dataclass('C', ['a', bad_field]) + + def test_duplicate_field_names(self): + for field in ['a', 'ab']: + with self.subTest(field=field): + with self.assertRaisesRegex(TypeError, 'Field name duplicated'): + make_dataclass('C', [field, 'a', field]) + + def test_keyword_field_names(self): + for field in ['for', 'async', 'await', 'as']: + with self.subTest(field=field): + with self.assertRaisesRegex(TypeError, 'must not be keywords'): + make_dataclass('C', ['a', field]) + with self.assertRaisesRegex(TypeError, 'must not be keywords'): + make_dataclass('C', [field]) + with self.assertRaisesRegex(TypeError, 'must not be keywords'): + make_dataclass('C', [field, 'a']) + + def test_non_identifier_field_names(self): + for field in ['()', 'x,y', '*', '2 at 3', '', 'little johnny tables']: + with self.subTest(field=field): + with self.assertRaisesRegex(TypeError, 'must be valid identifers'): + make_dataclass('C', ['a', field]) + with self.assertRaisesRegex(TypeError, 'must be valid identifers'): + make_dataclass('C', [field]) + with self.assertRaisesRegex(TypeError, 'must be valid identifers'): + make_dataclass('C', [field, 'a']) + + def test_underscore_field_names(self): + # Unlike namedtuple, it's okay if dataclass field names have + # an underscore. + make_dataclass('C', ['_', '_a', 'a_a', 'a_']) + + def test_funny_class_names_names(self): + # No reason to prevent weird class names, since + # types.new_class allows them. + for classname in ['()', 'x,y', '*', '2 at 3', '']: + with self.subTest(classname=classname): + C = make_dataclass(classname, ['a', 'b']) + self.assertEqual(C.__name__, classname) + + if __name__ == '__main__': unittest.main() diff --git a/Misc/NEWS.d/next/Library/2018-05-16-10-07-40.bpo-33536._s0TE8.rst b/Misc/NEWS.d/next/Library/2018-05-16-10-07-40.bpo-33536._s0TE8.rst new file mode 100644 index 000000000000..2c1024180d34 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-16-10-07-40.bpo-33536._s0TE8.rst @@ -0,0 +1,2 @@ +dataclasses.make_dataclass now checks for invalid field names and duplicate +fields. Also, added a check for invalid field specifications. From webhook-mailer at python.org Wed May 16 12:35:00 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 16 May 2018 16:35:00 -0000 Subject: [Python-checkins] bpo-24318: Rewrite the README PGO section. (GH-6863) Message-ID: <mailman.92.1526488503.2757.python-checkins@python.org> https://github.com/python/cpython/commit/447fdd178f1007294db38bf0392a0cf74a49d460 commit: 447fdd178f1007294db38bf0392a0cf74a49d460 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-16T09:34:57-07:00 summary: bpo-24318: Rewrite the README PGO section. (GH-6863) * bpo-24318: Rewrite the README PGO section. Merged from a phone on an airplane. :) (cherry picked from commit 93f9a8a5afb58b1d2e4f27bb46d3d4e0fa8c08f0) Co-authored-by: Gregory P. Smith <greg at krypto.org> files: M README.rst diff --git a/README.rst b/README.rst index ffa9631b0287..2341b53c7102 100644 --- a/README.rst +++ b/README.rst @@ -93,25 +93,26 @@ Profile Guided Optimization ^^^^^^^^^^^^^^^^^^^^^^^^^^^ PGO takes advantage of recent versions of the GCC or Clang compilers. If used, -either via ``configure --enable-optimizations`` above or by manually running -``make profile-opt`` regardless of configure flags it will do several steps. - -First, the entire Python directory is cleaned of temporary files that may have -resulted in a previous compilation. - -Then, an instrumented version of the interpreter is built, using suitable -compiler flags for each flavour. Note that this is just an intermediary step. -The binary resulting from this step is not good for real life workloads as -it has profiling instructions embedded inside. - -After this instrumented version of the interpreter is built, the Makefile will -automatically run a training workload. This is necessary in order to profile -the interpreter execution. Note also that any output, both stdout and stderr, -that may appear at this step is suppressed. - -Finally, the last step is to rebuild the interpreter, using the information -collected in the previous one. The end result will be a Python binary that is -optimized and suitable for distribution or production installation. +either via ``configure --enable-optimizations`` or by manually running +``make profile-opt`` regardless of configure flags, the optimized build +process will perform the following steps: + +The entire Python directory is cleaned of temporary files that may have +resulted from a previous compilation. + +An instrumented version of the interpreter is built, using suitable compiler +flags for each flavour. Note that this is just an intermediary step. The +binary resulting from this step is not good for real life workloads as it has +profiling instructions embedded inside. + +After the instrumented interpreter is built, the Makefile will run a training +workload. This is necessary in order to profile the interpreter execution. +Note also that any output, both stdout and stderr, that may appear at this step +is suppressed. + +The final step is to build the actual interpreter, using the information +collected from the instrumented one. The end result will be a Python binary +that is optimized; suitable for distribution or production installation. Link Time Optimization From webhook-mailer at python.org Wed May 16 13:02:12 2018 From: webhook-mailer at python.org (Alex Gaynor) Date: Wed, 16 May 2018 17:02:12 -0000 Subject: [Python-checkins] Remove an unneeded call into OpenSSL (GH-6887) Message-ID: <mailman.93.1526490133.2757.python-checkins@python.org> https://github.com/python/cpython/commit/55e53c309359327e54eb74b101c5a3240ea9cd45 commit: 55e53c309359327e54eb74b101c5a3240ea9cd45 branch: master author: Alex Gaynor <alex.gaynor at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-16T13:02:06-04:00 summary: Remove an unneeded call into OpenSSL (GH-6887) files: M Modules/_ssl.c diff --git a/Modules/_ssl.c b/Modules/_ssl.c index bf379f01a1d2..2bce4816d26f 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -901,7 +901,6 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock, #endif /* Make sure the SSL error state is initialized */ - (void) ERR_get_state(); ERR_clear_error(); PySSL_BEGIN_ALLOW_THREADS From webhook-mailer at python.org Wed May 16 15:05:01 2018 From: webhook-mailer at python.org (Eric Snow) Date: Wed, 16 May 2018 19:05:01 -0000 Subject: [Python-checkins] bpo-32604: Improve subinterpreter tests. (#6914) Message-ID: <mailman.94.1526497503.2757.python-checkins@python.org> https://github.com/python/cpython/commit/6d2cd9036c0ab78a83de43d1511befb7a7fc0ade commit: 6d2cd9036c0ab78a83de43d1511befb7a7fc0ade branch: master author: Eric Snow <ericsnowcurrently at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-16T15:04:57-04:00 summary: bpo-32604: Improve subinterpreter tests. (#6914) Add more tests for subinterpreters. This patch also fixes a few small defects in the channel implementation. files: M Lib/test/test__xxsubinterpreters.py M Modules/_xxsubinterpretersmodule.c M Python/pystate.c diff --git a/Lib/test/test__xxsubinterpreters.py b/Lib/test/test__xxsubinterpreters.py index 4ef77716c662..118f2e4895fe 100644 --- a/Lib/test/test__xxsubinterpreters.py +++ b/Lib/test/test__xxsubinterpreters.py @@ -1,6 +1,9 @@ +from collections import namedtuple import contextlib +import itertools import os import pickle +import sys from textwrap import dedent, indent import threading import time @@ -12,23 +15,32 @@ interpreters = support.import_module('_xxsubinterpreters') +################################## +# helpers + +def powerset(*sets): + return itertools.chain.from_iterable( + combinations(sets, r) + for r in range(len(sets)+1)) + + def _captured_script(script): r, w = os.pipe() indented = script.replace('\n', '\n ') wrapped = dedent(f""" import contextlib - with open({w}, 'w') as chan: - with contextlib.redirect_stdout(chan): + with open({w}, 'w') as spipe: + with contextlib.redirect_stdout(spipe): {indented} """) return wrapped, open(r) def _run_output(interp, request, shared=None): - script, chan = _captured_script(request) - with chan: + script, rpipe = _captured_script(request) + with rpipe: interpreters.run_string(interp, script, shared) - return chan.read() + return rpipe.read() @contextlib.contextmanager @@ -37,8 +49,8 @@ def _running(interp): def run(): interpreters.run_string(interp, dedent(f""" # wait for "signal" - with open({r}) as chan: - chan.read() + with open({r}) as rpipe: + rpipe.read() """)) t = threading.Thread(target=run) @@ -46,11 +58,248 @@ def run(): yield - with open(w, 'w') as chan: - chan.write('done') + with open(w, 'w') as spipe: + spipe.write('done') t.join() +#@contextmanager +#def run_threaded(id, source, **shared): +# def run(): +# run_interp(id, source, **shared) +# t = threading.Thread(target=run) +# t.start() +# yield +# t.join() + + +def run_interp(id, source, **shared): + _run_interp(id, source, shared) + + +def _run_interp(id, source, shared, _mainns={}): + source = dedent(source) + main = interpreters.get_main() + if main == id: + if interpreters.get_current() != main: + raise RuntimeError + # XXX Run a func? + exec(source, _mainns) + else: + interpreters.run_string(id, source, shared) + + +def run_interp_threaded(id, source, **shared): + def run(): + _run(id, source, shared) + t = threading.Thread(target=run) + t.start() + t.join() + + +class Interpreter(namedtuple('Interpreter', 'name id')): + + @classmethod + def from_raw(cls, raw): + if isinstance(raw, cls): + return raw + elif isinstance(raw, str): + return cls(raw) + else: + raise NotImplementedError + + def __new__(cls, name=None, id=None): + main = interpreters.get_main() + if id == main: + if not name: + name = 'main' + elif name != 'main': + raise ValueError( + 'name mismatch (expected "main", got "{}")'.format(name)) + id = main + elif id is not None: + if not name: + name = 'interp' + elif name == 'main': + raise ValueError('name mismatch (unexpected "main")') + if not isinstance(id, interpreters.InterpreterID): + id = interpreters.InterpreterID(id) + elif not name or name == 'main': + name = 'main' + id = main + else: + id = interpreters.create() + self = super().__new__(cls, name, id) + return self + + +# XXX expect_channel_closed() is unnecessary once we improve exc propagation. + + at contextlib.contextmanager +def expect_channel_closed(): + try: + yield + except interpreters.ChannelClosedError: + pass + else: + assert False, 'channel not closed' + + +class ChannelAction(namedtuple('ChannelAction', 'action end interp')): + + def __new__(cls, action, end=None, interp=None): + if not end: + end = 'both' + if not interp: + interp = 'main' + self = super().__new__(cls, action, end, interp) + return self + + def __init__(self, *args, **kwargs): + if self.action == 'use': + if self.end not in ('same', 'opposite', 'send', 'recv'): + raise ValueError(self.end) + elif self.action in ('close', 'force-close'): + if self.end not in ('both', 'same', 'opposite', 'send', 'recv'): + raise ValueError(self.end) + else: + raise ValueError(self.action) + if self.interp not in ('main', 'same', 'other', 'extra'): + raise ValueError(self.interp) + + def resolve_end(self, end): + if self.end == 'same': + return end + elif self.end == 'opposite': + return 'recv' if end == 'send' else 'send' + else: + return self.end + + def resolve_interp(self, interp, other, extra): + if self.interp == 'same': + return interp + elif self.interp == 'other': + if other is None: + raise RuntimeError + return other + elif self.interp == 'extra': + if extra is None: + raise RuntimeError + return extra + elif self.interp == 'main': + if interp.name == 'main': + return interp + elif other and other.name == 'main': + return other + else: + raise RuntimeError + # Per __init__(), there aren't any others. + + +class ChannelState(namedtuple('ChannelState', 'pending closed')): + + def __new__(cls, pending=0, *, closed=False): + self = super().__new__(cls, pending, closed) + return self + + def incr(self): + return type(self)(self.pending + 1, closed=self.closed) + + def decr(self): + return type(self)(self.pending - 1, closed=self.closed) + + def close(self, *, force=True): + if self.closed: + if not force or self.pending == 0: + return self + return type(self)(0 if force else self.pending, closed=True) + + +def run_action(cid, action, end, state, *, hideclosed=True): + if state.closed: + if action == 'use' and end == 'recv' and state.pending: + expectfail = False + else: + expectfail = True + else: + expectfail = False + + try: + result = _run_action(cid, action, end, state) + except interpreters.ChannelClosedError: + if not hideclosed and not expectfail: + raise + result = state.close() + else: + if expectfail: + raise ... # XXX + return result + + +def _run_action(cid, action, end, state): + if action == 'use': + if end == 'send': + interpreters.channel_send(cid, b'spam') + return state.incr() + elif end == 'recv': + if not state.pending: + try: + interpreters.channel_recv(cid) + except interpreters.ChannelEmptyError: + return state + else: + raise Exception('expected ChannelEmptyError') + else: + interpreters.channel_recv(cid) + return state.decr() + else: + raise ValueError(end) + elif action == 'close': + kwargs = {} + if end in ('recv', 'send'): + kwargs[end] = True + interpreters.channel_close(cid, **kwargs) + return state.close() + elif action == 'force-close': + kwargs = { + 'force': True, + } + if end in ('recv', 'send'): + kwargs[end] = True + interpreters.channel_close(cid, **kwargs) + return state.close(force=True) + else: + raise ValueError(action) + + +def clean_up_interpreters(): + for id in interpreters.list_all(): + if id == 0: # main + continue + try: + interpreters.destroy(id) + except RuntimeError: + pass # already destroyed + + +def clean_up_channels(): + for cid in interpreters.channel_list_all(): + try: + interpreters.channel_destroy(cid) + except interpreters.ChannelNotFoundError: + pass # already destroyed + + +class TestBase(unittest.TestCase): + + def tearDown(self): + clean_up_interpreters() + clean_up_channels() + + +################################## +# misc. tests + class IsShareableTests(unittest.TestCase): def test_default_shareables(self): @@ -59,6 +308,9 @@ def test_default_shareables(self): None, # builtin objects b'spam', + 'spam', + 10, + -10, ] for obj in shareables: with self.subTest(obj): @@ -86,37 +338,65 @@ class SubBytes(bytes): object, object(), Exception(), - 42, 100.0, - 'spam', # user-defined types and objects Cheese, Cheese('Wensleydale'), SubBytes(b'spam'), ] for obj in not_shareables: - with self.subTest(obj): + with self.subTest(repr(obj)): self.assertFalse( interpreters.is_shareable(obj)) -class TestBase(unittest.TestCase): +class ShareableTypeTests(unittest.TestCase): + + def setUp(self): + super().setUp() + self.cid = interpreters.channel_create() def tearDown(self): - for id in interpreters.list_all(): - if id == 0: # main - continue - try: - interpreters.destroy(id) - except RuntimeError: - pass # already destroyed + interpreters.channel_destroy(self.cid) + super().tearDown() - for cid in interpreters.channel_list_all(): - try: - interpreters.channel_destroy(cid) - except interpreters.ChannelNotFoundError: - pass # already destroyed + def _assert_values(self, values): + for obj in values: + with self.subTest(obj): + interpreters.channel_send(self.cid, obj) + got = interpreters.channel_recv(self.cid) + + self.assertEqual(got, obj) + self.assertIs(type(got), type(obj)) + # XXX Check the following in the channel tests? + #self.assertIsNot(got, obj) + + def test_singletons(self): + for obj in [None]: + with self.subTest(obj): + interpreters.channel_send(self.cid, obj) + got = interpreters.channel_recv(self.cid) + + # XXX What about between interpreters? + self.assertIs(got, obj) + + def test_types(self): + self._assert_values([ + b'spam', + 9999, + self.cid, + ]) + + def test_bytes(self): + self._assert_values(i.to_bytes(2, 'little', signed=True) + for i in range(-1, 258)) + def test_int(self): + self._assert_values(range(-1, 258)) + + +################################## +# interpreter tests class ListAllTests(TestBase): @@ -147,13 +427,16 @@ def test_main(self): main = interpreters.get_main() cur = interpreters.get_current() self.assertEqual(cur, main) + self.assertIsInstance(cur, interpreters.InterpreterID) def test_subinterpreter(self): main = interpreters.get_main() interp = interpreters.create() out = _run_output(interp, dedent(""" import _xxsubinterpreters as _interpreters - print(int(_interpreters.get_current())) + cur = _interpreters.get_current() + print(cur) + assert isinstance(cur, _interpreters.InterpreterID) """)) cur = int(out.strip()) _, expected = interpreters.list_all() @@ -167,13 +450,16 @@ def test_from_main(self): [expected] = interpreters.list_all() main = interpreters.get_main() self.assertEqual(main, expected) + self.assertIsInstance(main, interpreters.InterpreterID) def test_from_subinterpreter(self): [expected] = interpreters.list_all() interp = interpreters.create() out = _run_output(interp, dedent(""" import _xxsubinterpreters as _interpreters - print(int(_interpreters.get_main())) + main = _interpreters.get_main() + print(main) + assert isinstance(main, _interpreters.InterpreterID) """)) main = int(out.strip()) self.assertEqual(main, expected) @@ -197,7 +483,7 @@ def test_from_subinterpreter(self): interp = interpreters.create() out = _run_output(interp, dedent(f""" import _xxsubinterpreters as _interpreters - if _interpreters.is_running({int(interp)}): + if _interpreters.is_running({interp}): print(True) else: print(False) @@ -257,6 +543,10 @@ def test_does_not_exist(self): with self.assertRaises(RuntimeError): interpreters.InterpreterID(int(id) + 1) # unforced + def test_str(self): + id = interpreters.InterpreterID(10, force=True) + self.assertEqual(str(id), '10') + def test_repr(self): id = interpreters.InterpreterID(10, force=True) self.assertEqual(repr(id), 'InterpreterID(10)') @@ -280,6 +570,7 @@ class CreateTests(TestBase): def test_in_main(self): id = interpreters.create() + self.assertIsInstance(id, interpreters.InterpreterID) self.assertIn(id, interpreters.list_all()) @@ -314,7 +605,8 @@ def test_in_subinterpreter(self): out = _run_output(id1, dedent(""" import _xxsubinterpreters as _interpreters id = _interpreters.create() - print(int(id)) + print(id) + assert isinstance(id, _interpreters.InterpreterID) """)) id2 = int(out.strip()) @@ -329,7 +621,7 @@ def f(): out = _run_output(id1, dedent(""" import _xxsubinterpreters as _interpreters id = _interpreters.create() - print(int(id)) + print(id) """)) id2 = int(out.strip()) @@ -423,7 +715,7 @@ def test_from_current(self): script = dedent(f""" import _xxsubinterpreters as _interpreters try: - _interpreters.destroy({int(id)}) + _interpreters.destroy({id}) except RuntimeError: pass """) @@ -437,7 +729,7 @@ def test_from_sibling(self): id2 = interpreters.create() script = dedent(f""" import _xxsubinterpreters as _interpreters - _interpreters.destroy({int(id2)}) + _interpreters.destroy({id2}) """) interpreters.run_string(id1, script) @@ -783,6 +1075,9 @@ def f(): self.assertEqual(retcode, 0) +################################## +# channel tests + class ChannelIDTests(TestBase): def test_default_kwargs(self): @@ -842,6 +1137,10 @@ def test_does_not_exist(self): with self.assertRaises(interpreters.ChannelNotFoundError): interpreters._channel_id(int(cid) + 1) # unforced + def test_str(self): + cid = interpreters._channel_id(10, force=True) + self.assertEqual(str(cid), '10') + def test_repr(self): cid = interpreters._channel_id(10, force=True) self.assertEqual(repr(cid), 'ChannelID(10)') @@ -872,6 +1171,10 @@ def test_equality(self): class ChannelTests(TestBase): + def test_create_cid(self): + cid = interpreters.channel_create() + self.assertIsInstance(cid, interpreters.ChannelID) + def test_sequential_ids(self): before = interpreters.channel_list_all() id1 = interpreters.channel_create() @@ -888,7 +1191,7 @@ def test_ids_global(self): out = _run_output(id1, dedent(""" import _xxsubinterpreters as _interpreters cid = _interpreters.channel_create() - print(int(cid)) + print(cid) """)) cid1 = int(out.strip()) @@ -896,7 +1199,7 @@ def test_ids_global(self): out = _run_output(id2, dedent(""" import _xxsubinterpreters as _interpreters cid = _interpreters.channel_create() - print(int(cid)) + print(cid) """)) cid2 = int(out.strip()) @@ -904,127 +1207,133 @@ def test_ids_global(self): #################### - def test_drop_single_user(self): + def test_send_recv_main(self): cid = interpreters.channel_create() - interpreters.channel_send(cid, b'spam') - interpreters.channel_recv(cid) - interpreters.channel_drop_interpreter(cid, send=True, recv=True) + orig = b'spam' + interpreters.channel_send(cid, orig) + obj = interpreters.channel_recv(cid) - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_send(cid, b'eggs') - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_recv(cid) + self.assertEqual(obj, orig) + self.assertIsNot(obj, orig) - def test_drop_multiple_users(self): - cid = interpreters.channel_create() + def test_send_recv_same_interpreter(self): id1 = interpreters.create() - id2 = interpreters.create() - interpreters.run_string(id1, dedent(f""" + out = _run_output(id1, dedent(""" import _xxsubinterpreters as _interpreters - _interpreters.channel_send({int(cid)}, b'spam') + cid = _interpreters.channel_create() + orig = b'spam' + _interpreters.channel_send(cid, orig) + obj = _interpreters.channel_recv(cid) + assert obj is not orig + assert obj == orig """)) - out = _run_output(id2, dedent(f""" + + def test_send_recv_different_interpreters(self): + cid = interpreters.channel_create() + id1 = interpreters.create() + out = _run_output(id1, dedent(f""" import _xxsubinterpreters as _interpreters - obj = _interpreters.channel_recv({int(cid)}) - _interpreters.channel_drop_interpreter({int(cid)}) - print(repr(obj)) - """)) - interpreters.run_string(id1, dedent(f""" - _interpreters.channel_drop_interpreter({int(cid)}) + _interpreters.channel_send({cid}, b'spam') """)) + obj = interpreters.channel_recv(cid) - self.assertEqual(out.strip(), "b'spam'") + self.assertEqual(obj, b'spam') - def test_drop_no_kwargs(self): + def test_send_recv_different_threads(self): cid = interpreters.channel_create() - interpreters.channel_send(cid, b'spam') - interpreters.channel_recv(cid) - interpreters.channel_drop_interpreter(cid) - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_send(cid, b'eggs') - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_recv(cid) + def f(): + while True: + try: + obj = interpreters.channel_recv(cid) + break + except interpreters.ChannelEmptyError: + time.sleep(0.1) + interpreters.channel_send(cid, obj) + t = threading.Thread(target=f) + t.start() - def test_drop_multiple_times(self): - cid = interpreters.channel_create() interpreters.channel_send(cid, b'spam') - interpreters.channel_recv(cid) - interpreters.channel_drop_interpreter(cid, send=True, recv=True) + t.join() + obj = interpreters.channel_recv(cid) - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_drop_interpreter(cid, send=True, recv=True) + self.assertEqual(obj, b'spam') - def test_drop_with_unused_items(self): + def test_send_recv_different_interpreters_and_threads(self): cid = interpreters.channel_create() + id1 = interpreters.create() + out = None + + def f(): + nonlocal out + out = _run_output(id1, dedent(f""" + import time + import _xxsubinterpreters as _interpreters + while True: + try: + obj = _interpreters.channel_recv({cid}) + break + except _interpreters.ChannelEmptyError: + time.sleep(0.1) + assert(obj == b'spam') + _interpreters.channel_send({cid}, b'eggs') + """)) + t = threading.Thread(target=f) + t.start() + interpreters.channel_send(cid, b'spam') - interpreters.channel_send(cid, b'ham') - interpreters.channel_drop_interpreter(cid, send=True, recv=True) + t.join() + obj = interpreters.channel_recv(cid) - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_recv(cid) + self.assertEqual(obj, b'eggs') - def test_drop_never_used(self): - cid = interpreters.channel_create() - interpreters.channel_drop_interpreter(cid) + def test_send_not_found(self): + with self.assertRaises(interpreters.ChannelNotFoundError): + interpreters.channel_send(10, b'spam') - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_send(cid, b'spam') - with self.assertRaises(interpreters.ChannelClosedError): + def test_recv_not_found(self): + with self.assertRaises(interpreters.ChannelNotFoundError): + interpreters.channel_recv(10) + + def test_recv_empty(self): + cid = interpreters.channel_create() + with self.assertRaises(interpreters.ChannelEmptyError): interpreters.channel_recv(cid) - def test_drop_by_unassociated_interp(self): + def test_run_string_arg_unresolved(self): cid = interpreters.channel_create() - interpreters.channel_send(cid, b'spam') interp = interpreters.create() - interpreters.run_string(interp, dedent(f""" + + out = _run_output(interp, dedent(""" import _xxsubinterpreters as _interpreters - _interpreters.channel_drop_interpreter({int(cid)}) - """)) + print(cid.end) + _interpreters.channel_send(cid, b'spam') + """), + dict(cid=cid.send)) obj = interpreters.channel_recv(cid) - interpreters.channel_drop_interpreter(cid) - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_send(cid, b'eggs') self.assertEqual(obj, b'spam') + self.assertEqual(out.strip(), 'send') - def test_drop_close_if_unassociated(self): + def test_run_string_arg_resolved(self): cid = interpreters.channel_create() + cid = interpreters._channel_id(cid, _resolve=True) interp = interpreters.create() - interpreters.run_string(interp, dedent(f""" - import _xxsubinterpreters as _interpreters - obj = _interpreters.channel_send({int(cid)}, b'spam') - _interpreters.channel_drop_interpreter({int(cid)}) - """)) - - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_recv(cid) - def test_drop_partially(self): - # XXX Is partial close too weird/confusing? - cid = interpreters.channel_create() - interpreters.channel_send(cid, None) - interpreters.channel_recv(cid) - interpreters.channel_send(cid, b'spam') - interpreters.channel_drop_interpreter(cid, send=True) + out = _run_output(interp, dedent(""" + import _xxsubinterpreters as _interpreters + print(chan.end) + _interpreters.channel_send(chan, b'spam') + #print(chan.id.end) + #_interpreters.channel_send(chan.id, b'spam') + """), + dict(chan=cid.send)) obj = interpreters.channel_recv(cid) self.assertEqual(obj, b'spam') + self.assertEqual(out.strip(), 'send') - def test_drop_used_multiple_times_by_single_user(self): - cid = interpreters.channel_create() - interpreters.channel_send(cid, b'spam') - interpreters.channel_send(cid, b'spam') - interpreters.channel_send(cid, b'spam') - interpreters.channel_recv(cid) - interpreters.channel_drop_interpreter(cid, send=True, recv=True) - - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_send(cid, b'eggs') - with self.assertRaises(interpreters.ChannelClosedError): - interpreters.channel_recv(cid) - - #################### + # close def test_close_single_user(self): cid = interpreters.channel_create() @@ -1043,21 +1352,21 @@ def test_close_multiple_users(self): id2 = interpreters.create() interpreters.run_string(id1, dedent(f""" import _xxsubinterpreters as _interpreters - _interpreters.channel_send({int(cid)}, b'spam') + _interpreters.channel_send({cid}, b'spam') """)) interpreters.run_string(id2, dedent(f""" import _xxsubinterpreters as _interpreters - _interpreters.channel_recv({int(cid)}) + _interpreters.channel_recv({cid}) """)) interpreters.channel_close(cid) with self.assertRaises(interpreters.RunFailedError) as cm: interpreters.run_string(id1, dedent(f""" - _interpreters.channel_send({int(cid)}, b'spam') + _interpreters.channel_send({cid}, b'spam') """)) self.assertIn('ChannelClosedError', str(cm.exception)) with self.assertRaises(interpreters.RunFailedError) as cm: interpreters.run_string(id2, dedent(f""" - _interpreters.channel_send({int(cid)}, b'spam') + _interpreters.channel_send({cid}, b'spam') """)) self.assertIn('ChannelClosedError', str(cm.exception)) @@ -1094,7 +1403,7 @@ def test_close_by_unassociated_interp(self): interp = interpreters.create() interpreters.run_string(interp, dedent(f""" import _xxsubinterpreters as _interpreters - _interpreters.channel_close({int(cid)}) + _interpreters.channel_close({cid}) """)) with self.assertRaises(interpreters.ChannelClosedError): interpreters.channel_recv(cid) @@ -1114,115 +1423,602 @@ def test_close_used_multiple_times_by_single_user(self): with self.assertRaises(interpreters.ChannelClosedError): interpreters.channel_recv(cid) - #################### - def test_send_recv_main(self): +class ChannelReleaseTests(TestBase): + + # XXX Add more test coverage a la the tests for close(). + + """ + - main / interp / other + - run in: current thread / new thread / other thread / different threads + - end / opposite + - force / no force + - used / not used (associated / not associated) + - empty / emptied / never emptied / partly emptied + - closed / not closed + - released / not released + - creator (interp) / other + - associated interpreter not running + - associated interpreter destroyed + """ + + """ + use + pre-release + release + after + check + """ + + """ + release in: main, interp1 + creator: same, other (incl. interp2) + + use: None,send,recv,send/recv in None,same,other(incl. interp2),same+other(incl. interp2),all + pre-release: None,send,recv,both in None,same,other(incl. interp2),same+other(incl. interp2),all + pre-release forced: None,send,recv,both in None,same,other(incl. interp2),same+other(incl. interp2),all + + release: same + release forced: same + + use after: None,send,recv,send/recv in None,same,other(incl. interp2),same+other(incl. interp2),all + release after: None,send,recv,send/recv in None,same,other(incl. interp2),same+other(incl. interp2),all + check released: send/recv for same/other(incl. interp2) + check closed: send/recv for same/other(incl. interp2) + """ + + def test_single_user(self): cid = interpreters.channel_create() - orig = b'spam' - interpreters.channel_send(cid, orig) - obj = interpreters.channel_recv(cid) + interpreters.channel_send(cid, b'spam') + interpreters.channel_recv(cid) + interpreters.channel_release(cid, send=True, recv=True) - self.assertEqual(obj, orig) - self.assertIsNot(obj, orig) + with self.assertRaises(interpreters.ChannelClosedError): + interpreters.channel_send(cid, b'eggs') + with self.assertRaises(interpreters.ChannelClosedError): + interpreters.channel_recv(cid) - def test_send_recv_same_interpreter(self): + def test_multiple_users(self): + cid = interpreters.channel_create() id1 = interpreters.create() - out = _run_output(id1, dedent(""" + id2 = interpreters.create() + interpreters.run_string(id1, dedent(f""" import _xxsubinterpreters as _interpreters - cid = _interpreters.channel_create() - orig = b'spam' - _interpreters.channel_send(cid, orig) - obj = _interpreters.channel_recv(cid) - assert obj is not orig - assert obj == orig + _interpreters.channel_send({cid}, b'spam') + """)) + out = _run_output(id2, dedent(f""" + import _xxsubinterpreters as _interpreters + obj = _interpreters.channel_recv({cid}) + _interpreters.channel_release({cid}) + print(repr(obj)) + """)) + interpreters.run_string(id1, dedent(f""" + _interpreters.channel_release({cid}) """)) - def test_send_recv_different_interpreters(self): + self.assertEqual(out.strip(), "b'spam'") + + def test_no_kwargs(self): cid = interpreters.channel_create() - id1 = interpreters.create() - out = _run_output(id1, dedent(f""" + interpreters.channel_send(cid, b'spam') + interpreters.channel_recv(cid) + interpreters.channel_release(cid) + + with self.assertRaises(interpreters.ChannelClosedError): + interpreters.channel_send(cid, b'eggs') + with self.assertRaises(interpreters.ChannelClosedError): + interpreters.channel_recv(cid) + + def test_multiple_times(self): + cid = interpreters.channel_create() + interpreters.channel_send(cid, b'spam') + interpreters.channel_recv(cid) + interpreters.channel_release(cid, send=True, recv=True) + + with self.assertRaises(interpreters.ChannelClosedError): + interpreters.channel_release(cid, send=True, recv=True) + + def test_with_unused_items(self): + cid = interpreters.channel_create() + interpreters.channel_send(cid, b'spam') + interpreters.channel_send(cid, b'ham') + interpreters.channel_release(cid, send=True, recv=True) + + with self.assertRaises(interpreters.ChannelClosedError): + interpreters.channel_recv(cid) + + def test_never_used(self): + cid = interpreters.channel_create() + interpreters.channel_release(cid) + + with self.assertRaises(interpreters.ChannelClosedError): + interpreters.channel_send(cid, b'spam') + with self.assertRaises(interpreters.ChannelClosedError): + interpreters.channel_recv(cid) + + def test_by_unassociated_interp(self): + cid = interpreters.channel_create() + interpreters.channel_send(cid, b'spam') + interp = interpreters.create() + interpreters.run_string(interp, dedent(f""" import _xxsubinterpreters as _interpreters - _interpreters.channel_send({int(cid)}, b'spam') + _interpreters.channel_release({cid}) """)) obj = interpreters.channel_recv(cid) + interpreters.channel_release(cid) + with self.assertRaises(interpreters.ChannelClosedError): + interpreters.channel_send(cid, b'eggs') self.assertEqual(obj, b'spam') - def test_send_recv_different_threads(self): + def test_close_if_unassociated(self): + # XXX Something's not right with this test... cid = interpreters.channel_create() + interp = interpreters.create() + interpreters.run_string(interp, dedent(f""" + import _xxsubinterpreters as _interpreters + obj = _interpreters.channel_send({cid}, b'spam') + _interpreters.channel_release({cid}) + """)) - def f(): - while True: - try: - obj = interpreters.channel_recv(cid) - break - except interpreters.ChannelEmptyError: - time.sleep(0.1) - interpreters.channel_send(cid, obj) - t = threading.Thread(target=f) - t.start() + with self.assertRaises(interpreters.ChannelClosedError): + interpreters.channel_recv(cid) + def test_partially(self): + # XXX Is partial close too weird/confusing? + cid = interpreters.channel_create() + interpreters.channel_send(cid, None) + interpreters.channel_recv(cid) interpreters.channel_send(cid, b'spam') - t.join() + interpreters.channel_release(cid, send=True) obj = interpreters.channel_recv(cid) self.assertEqual(obj, b'spam') - def test_send_recv_different_interpreters_and_threads(self): + def test_used_multiple_times_by_single_user(self): cid = interpreters.channel_create() - id1 = interpreters.create() - out = None + interpreters.channel_send(cid, b'spam') + interpreters.channel_send(cid, b'spam') + interpreters.channel_send(cid, b'spam') + interpreters.channel_recv(cid) + interpreters.channel_release(cid, send=True, recv=True) - def f(): - nonlocal out - out = _run_output(id1, dedent(f""" - import time - import _xxsubinterpreters as _interpreters - while True: - try: - obj = _interpreters.channel_recv({int(cid)}) - break - except _interpreters.ChannelEmptyError: - time.sleep(0.1) - assert(obj == b'spam') - _interpreters.channel_send({int(cid)}, b'eggs') - """)) - t = threading.Thread(target=f) - t.start() + with self.assertRaises(interpreters.ChannelClosedError): + interpreters.channel_send(cid, b'eggs') + with self.assertRaises(interpreters.ChannelClosedError): + interpreters.channel_recv(cid) - interpreters.channel_send(cid, b'spam') - t.join() - obj = interpreters.channel_recv(cid) - self.assertEqual(obj, b'eggs') +class ChannelCloseFixture(namedtuple('ChannelCloseFixture', + 'end interp other extra creator')): - def test_send_not_found(self): - with self.assertRaises(interpreters.ChannelNotFoundError): - interpreters.channel_send(10, b'spam') + # Set this to True to avoid creating interpreters, e.g. when + # scanning through test permutations without running them. + QUICK = False - def test_recv_not_found(self): - with self.assertRaises(interpreters.ChannelNotFoundError): - interpreters.channel_recv(10) + def __new__(cls, end, interp, other, extra, creator): + assert end in ('send', 'recv') + if cls.QUICK: + known = {} + else: + interp = Interpreter.from_raw(interp) + other = Interpreter.from_raw(other) + extra = Interpreter.from_raw(extra) + known = { + interp.name: interp, + other.name: other, + extra.name: extra, + } + if not creator: + creator = 'same' + self = super().__new__(cls, end, interp, other, extra, creator) + self._prepped = set() + self._state = ChannelState() + self._known = known + return self - def test_recv_empty(self): - cid = interpreters.channel_create() - with self.assertRaises(interpreters.ChannelEmptyError): - interpreters.channel_recv(cid) + @property + def state(self): + return self._state - def test_run_string_arg(self): - cid = interpreters.channel_create() - interp = interpreters.create() + @property + def cid(self): + try: + return self._cid + except AttributeError: + creator = self._get_interpreter(self.creator) + self._cid = self._new_channel(creator) + return self._cid + + def get_interpreter(self, interp): + interp = self._get_interpreter(interp) + self._prep_interpreter(interp) + return interp + + def expect_closed_error(self, end=None): + if end is None: + end = self.end + if end == 'recv' and self.state.closed == 'send': + return False + return bool(self.state.closed) + + def prep_interpreter(self, interp): + self._prep_interpreter(interp) + + def record_action(self, action, result): + self._state = result + + def clean_up(self): + clean_up_interpreters() + clean_up_channels() + + # internal methods + + def _new_channel(self, creator): + if creator.name == 'main': + return interpreters.channel_create() + else: + ch = interpreters.channel_create() + run_interp(creator.id, f""" + import _xxsubinterpreters + cid = _xxsubinterpreters.channel_create() + # We purposefully send back an int to avoid tying the + # channel to the other interpreter. + _xxsubinterpreters.channel_send({ch}, int(cid)) + del _xxsubinterpreters + """) + self._cid = interpreters.channel_recv(ch) + return self._cid + + def _get_interpreter(self, interp): + if interp in ('same', 'interp'): + return self.interp + elif interp == 'other': + return self.other + elif interp == 'extra': + return self.extra + else: + name = interp + try: + interp = self._known[name] + except KeyError: + interp = self._known[name] = Interpreter(name) + return interp + + def _prep_interpreter(self, interp): + if interp.id in self._prepped: + return + self._prepped.add(interp.id) + if interp.name == 'main': + return + run_interp(interp.id, f""" + import _xxsubinterpreters as interpreters + import test.test__xxsubinterpreters as helpers + ChannelState = helpers.ChannelState + try: + cid + except NameError: + cid = interpreters._channel_id({self.cid}) + """) - out = _run_output(interp, dedent(""" - import _xxsubinterpreters as _interpreters - print(cid.end) - _interpreters.channel_send(cid, b'spam') - """), - dict(cid=cid.send)) - obj = interpreters.channel_recv(cid) - self.assertEqual(obj, b'spam') - self.assertEqual(out.strip(), 'send') + at unittest.skip('these tests take several hours to run') +class ExhaustiveChannelTests(TestBase): + + """ + - main / interp / other + - run in: current thread / new thread / other thread / different threads + - end / opposite + - force / no force + - used / not used (associated / not associated) + - empty / emptied / never emptied / partly emptied + - closed / not closed + - released / not released + - creator (interp) / other + - associated interpreter not running + - associated interpreter destroyed + + - close after unbound + """ + + """ + use + pre-close + close + after + check + """ + + """ + close in: main, interp1 + creator: same, other, extra + + use: None,send,recv,send/recv in None,same,other,same+other,all + pre-close: None,send,recv in None,same,other,same+other,all + pre-close forced: None,send,recv in None,same,other,same+other,all + + close: same + close forced: same + + use after: None,send,recv,send/recv in None,same,other,extra,same+other,all + close after: None,send,recv,send/recv in None,same,other,extra,same+other,all + check closed: send/recv for same/other(incl. interp2) + """ + + def iter_action_sets(self): + # - used / not used (associated / not associated) + # - empty / emptied / never emptied / partly emptied + # - closed / not closed + # - released / not released + + # never used + yield [] + + # only pre-closed (and possible used after) + for closeactions in self._iter_close_action_sets('same', 'other'): + yield closeactions + for postactions in self._iter_post_close_action_sets(): + yield closeactions + postactions + for closeactions in self._iter_close_action_sets('other', 'extra'): + yield closeactions + for postactions in self._iter_post_close_action_sets(): + yield closeactions + postactions + + # used + for useactions in self._iter_use_action_sets('same', 'other'): + yield useactions + for closeactions in self._iter_close_action_sets('same', 'other'): + actions = useactions + closeactions + yield actions + for postactions in self._iter_post_close_action_sets(): + yield actions + postactions + for closeactions in self._iter_close_action_sets('other', 'extra'): + actions = useactions + closeactions + yield actions + for postactions in self._iter_post_close_action_sets(): + yield actions + postactions + for useactions in self._iter_use_action_sets('other', 'extra'): + yield useactions + for closeactions in self._iter_close_action_sets('same', 'other'): + actions = useactions + closeactions + yield actions + for postactions in self._iter_post_close_action_sets(): + yield actions + postactions + for closeactions in self._iter_close_action_sets('other', 'extra'): + actions = useactions + closeactions + yield actions + for postactions in self._iter_post_close_action_sets(): + yield actions + postactions + + def _iter_use_action_sets(self, interp1, interp2): + interps = (interp1, interp2) + + # only recv end used + yield [ + ChannelAction('use', 'recv', interp1), + ] + yield [ + ChannelAction('use', 'recv', interp2), + ] + yield [ + ChannelAction('use', 'recv', interp1), + ChannelAction('use', 'recv', interp2), + ] + + # never emptied + yield [ + ChannelAction('use', 'send', interp1), + ] + yield [ + ChannelAction('use', 'send', interp2), + ] + yield [ + ChannelAction('use', 'send', interp1), + ChannelAction('use', 'send', interp2), + ] + + # partially emptied + for interp1 in interps: + for interp2 in interps: + for interp3 in interps: + yield [ + ChannelAction('use', 'send', interp1), + ChannelAction('use', 'send', interp2), + ChannelAction('use', 'recv', interp3), + ] + + # fully emptied + for interp1 in interps: + for interp2 in interps: + for interp3 in interps: + for interp4 in interps: + yield [ + ChannelAction('use', 'send', interp1), + ChannelAction('use', 'send', interp2), + ChannelAction('use', 'recv', interp3), + ChannelAction('use', 'recv', interp4), + ] + + def _iter_close_action_sets(self, interp1, interp2): + ends = ('recv', 'send') + interps = (interp1, interp2) + for force in (True, False): + op = 'force-close' if force else 'close' + for interp in interps: + for end in ends: + yield [ + ChannelAction(op, end, interp), + ] + for recvop in ('close', 'force-close'): + for sendop in ('close', 'force-close'): + for recv in interps: + for send in interps: + yield [ + ChannelAction(recvop, 'recv', recv), + ChannelAction(sendop, 'send', send), + ] + + def _iter_post_close_action_sets(self): + for interp in ('same', 'extra', 'other'): + yield [ + ChannelAction('use', 'recv', interp), + ] + yield [ + ChannelAction('use', 'send', interp), + ] + + def run_actions(self, fix, actions): + for action in actions: + self.run_action(fix, action) + + def run_action(self, fix, action, *, hideclosed=True): + end = action.resolve_end(fix.end) + interp = action.resolve_interp(fix.interp, fix.other, fix.extra) + fix.prep_interpreter(interp) + if interp.name == 'main': + result = run_action( + fix.cid, + action.action, + end, + fix.state, + hideclosed=hideclosed, + ) + fix.record_action(action, result) + else: + _cid = interpreters.channel_create() + run_interp(interp.id, f""" + result = helpers.run_action( + {fix.cid}, + {repr(action.action)}, + {repr(end)}, + {repr(fix.state)}, + hideclosed={hideclosed}, + ) + interpreters.channel_send({_cid}, result.pending.to_bytes(1, 'little')) + interpreters.channel_send({_cid}, b'X' if result.closed else b'') + """) + result = ChannelState( + pending=int.from_bytes(interpreters.channel_recv(_cid), 'little'), + closed=bool(interpreters.channel_recv(_cid)), + ) + fix.record_action(action, result) + + def iter_fixtures(self): + # XXX threads? + interpreters = [ + ('main', 'interp', 'extra'), + ('interp', 'main', 'extra'), + ('interp1', 'interp2', 'extra'), + ('interp1', 'interp2', 'main'), + ] + for interp, other, extra in interpreters: + for creator in ('same', 'other', 'creator'): + for end in ('send', 'recv'): + yield ChannelCloseFixture(end, interp, other, extra, creator) + + def _close(self, fix, *, force): + op = 'force-close' if force else 'close' + close = ChannelAction(op, fix.end, 'same') + if not fix.expect_closed_error(): + self.run_action(fix, close, hideclosed=False) + else: + with self.assertRaises(interpreters.ChannelClosedError): + self.run_action(fix, close, hideclosed=False) + + def _assert_closed_in_interp(self, fix, interp=None): + if interp is None or interp.name == 'main': + with self.assertRaises(interpreters.ChannelClosedError): + interpreters.channel_recv(fix.cid) + with self.assertRaises(interpreters.ChannelClosedError): + interpreters.channel_send(fix.cid, b'spam') + with self.assertRaises(interpreters.ChannelClosedError): + interpreters.channel_close(fix.cid) + with self.assertRaises(interpreters.ChannelClosedError): + interpreters.channel_close(fix.cid, force=True) + else: + run_interp(interp.id, f""" + with helpers.expect_channel_closed(): + interpreters.channel_recv(cid) + """) + run_interp(interp.id, f""" + with helpers.expect_channel_closed(): + interpreters.channel_send(cid, b'spam') + """) + run_interp(interp.id, f""" + with helpers.expect_channel_closed(): + interpreters.channel_close(cid) + """) + run_interp(interp.id, f""" + with helpers.expect_channel_closed(): + interpreters.channel_close(cid, force=True) + """) + + def _assert_closed(self, fix): + self.assertTrue(fix.state.closed) + + for _ in range(fix.state.pending): + interpreters.channel_recv(fix.cid) + self._assert_closed_in_interp(fix) + + for interp in ('same', 'other'): + interp = fix.get_interpreter(interp) + if interp.name == 'main': + continue + self._assert_closed_in_interp(fix, interp) + + interp = fix.get_interpreter('fresh') + self._assert_closed_in_interp(fix, interp) + + def _iter_close_tests(self, verbose=False): + i = 0 + for actions in self.iter_action_sets(): + print() + for fix in self.iter_fixtures(): + i += 1 + if i > 1000: + return + if verbose: + if (i - 1) % 6 == 0: + print() + print(i, fix, '({} actions)'.format(len(actions))) + else: + if (i - 1) % 6 == 0: + print(' ', end='') + print('.', end=''); sys.stdout.flush() + yield i, fix, actions + if verbose: + print('---') + print() + + # This is useful for scanning through the possible tests. + def _skim_close_tests(self): + ChannelCloseFixture.QUICK = True + for i, fix, actions in self._iter_close_tests(): + pass + + def test_close(self): + for i, fix, actions in self._iter_close_tests(): + with self.subTest('{} {} {}'.format(i, fix, actions)): + fix.prep_interpreter(fix.interp) + self.run_actions(fix, actions) + + self._close(fix, force=False) + + self._assert_closed(fix) + # XXX Things slow down if we have too many interpreters. + fix.clean_up() + + def test_force_close(self): + for i, fix, actions in self._iter_close_tests(): + with self.subTest('{} {} {}'.format(i, fix, actions)): + fix.prep_interpreter(fix.interp) + self.run_actions(fix, actions) + + self._close(fix, force=True) + + self._assert_closed(fix) + # XXX Things slow down if we have too many interpreters. + fix.clean_up() if __name__ == '__main__': diff --git a/Modules/_xxsubinterpretersmodule.c b/Modules/_xxsubinterpretersmodule.c index f5e2ea3c79d6..5184f6593db1 100644 --- a/Modules/_xxsubinterpretersmodule.c +++ b/Modules/_xxsubinterpretersmodule.c @@ -1250,7 +1250,9 @@ _channel_recv(_channels *channels, int64_t id) _PyCrossInterpreterData *data = _channel_next(chan, interp->id); PyThread_release_lock(mutex); if (data == NULL) { - PyErr_Format(ChannelEmptyError, "channel %d is empty", id); + if (!PyErr_Occurred()) { + PyErr_Format(ChannelEmptyError, "channel %d is empty", id); + } return NULL; } @@ -1304,12 +1306,13 @@ typedef struct channelid { PyObject_HEAD int64_t id; int end; + int resolve; _channels *channels; } channelid; static channelid * newchannelid(PyTypeObject *cls, int64_t cid, int end, _channels *channels, - int force) + int force, int resolve) { channelid *self = PyObject_New(channelid, cls); if (self == NULL) { @@ -1317,6 +1320,7 @@ newchannelid(PyTypeObject *cls, int64_t cid, int end, _channels *channels, } self->id = cid; self->end = end; + self->resolve = resolve; self->channels = channels; if (_channels_add_id_object(channels, cid) != 0) { @@ -1337,14 +1341,15 @@ static _channels * _global_channels(void); static PyObject * channelid_new(PyTypeObject *cls, PyObject *args, PyObject *kwds) { - static char *kwlist[] = {"id", "send", "recv", "force", NULL}; + static char *kwlist[] = {"id", "send", "recv", "force", "_resolve", NULL}; PyObject *id; int send = -1; int recv = -1; int force = 0; + int resolve = 0; if (!PyArg_ParseTupleAndKeywords(args, kwds, - "O|$ppp:ChannelID.__init__", kwlist, - &id, &send, &recv, &force)) + "O|$pppp:ChannelID.__new__", kwlist, + &id, &send, &recv, &force, &resolve)) return NULL; // Coerce and check the ID. @@ -1376,7 +1381,8 @@ channelid_new(PyTypeObject *cls, PyObject *args, PyObject *kwds) end = CHANNEL_RECV; } - return (PyObject *)newchannelid(cls, cid, end, _global_channels(), force); + return (PyObject *)newchannelid(cls, cid, end, _global_channels(), + force, resolve); } static void @@ -1409,6 +1415,13 @@ channelid_repr(PyObject *self) return PyUnicode_FromFormat(fmt, name, cid->id); } +static PyObject * +channelid_str(PyObject *self) +{ + channelid *cid = (channelid *)self; + return PyUnicode_FromFormat("%d", cid->id); +} + PyObject * channelid_int(PyObject *self) { @@ -1519,14 +1532,49 @@ channelid_richcompare(PyObject *self, PyObject *other, int op) struct _channelid_xid { int64_t id; int end; + int resolve; }; static PyObject * _channelid_from_xid(_PyCrossInterpreterData *data) { struct _channelid_xid *xid = (struct _channelid_xid *)data->data; - return (PyObject *)newchannelid(&ChannelIDtype, xid->id, xid->end, - _global_channels(), 0); + // Note that we do not preserve the "resolve" flag. + PyObject *cid = (PyObject *)newchannelid(&ChannelIDtype, xid->id, xid->end, + _global_channels(), 0, 0); + if (xid->end == 0) { + return cid; + } + if (!xid->resolve) { + return cid; + } + + /* Try returning a high-level channel end but fall back to the ID. */ + PyObject *highlevel = PyImport_ImportModule("interpreters"); + if (highlevel == NULL) { + PyErr_Clear(); + highlevel = PyImport_ImportModule("test.support.interpreters"); + if (highlevel == NULL) { + goto error; + } + } + const char *clsname = (xid->end == CHANNEL_RECV) ? "RecvChannel" : + "SendChannel"; + PyObject *cls = PyObject_GetAttrString(highlevel, clsname); + Py_DECREF(highlevel); + if (cls == NULL) { + goto error; + } + PyObject *chan = PyObject_CallFunctionObjArgs(cls, cid, NULL); + if (chan == NULL) { + goto error; + } + Py_DECREF(cid); + return chan; + +error: + PyErr_Clear(); + return cid; } static int @@ -1538,6 +1586,7 @@ _channelid_shared(PyObject *obj, _PyCrossInterpreterData *data) } xid->id = ((channelid *)obj)->id; xid->end = ((channelid *)obj)->end; + xid->resolve = ((channelid *)obj)->resolve; data->data = xid; data->obj = obj; @@ -1553,7 +1602,7 @@ channelid_end(PyObject *self, void *end) channelid *cid = (channelid *)self; if (end != NULL) { return (PyObject *)newchannelid(Py_TYPE(self), cid->id, *(int *)end, - cid->channels, force); + cid->channels, force, cid->resolve); } if (cid->end == CHANNEL_SEND) { @@ -1597,7 +1646,7 @@ static PyTypeObject ChannelIDtype = { 0, /* tp_as_mapping */ channelid_hash, /* tp_hash */ 0, /* tp_call */ - 0, /* tp_str */ + (reprfunc)channelid_str, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ @@ -1878,6 +1927,13 @@ interpid_repr(PyObject *self) return PyUnicode_FromFormat("%s(%d)", name, id->id); } +static PyObject * +interpid_str(PyObject *self) +{ + interpid *id = (interpid *)self; + return PyUnicode_FromFormat("%d", id->id); +} + PyObject * interpid_int(PyObject *self) { @@ -1999,7 +2055,7 @@ static PyTypeObject InterpreterIDtype = { 0, /* tp_as_mapping */ interpid_hash, /* tp_hash */ 0, /* tp_call */ - 0, /* tp_str */ + (reprfunc)interpid_str, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ @@ -2115,10 +2171,13 @@ Create a new interpreter and return a unique generated ID."); static PyObject * -interp_destroy(PyObject *self, PyObject *args) +interp_destroy(PyObject *self, PyObject *args, PyObject *kwds) { + static char *kwlist[] = {"id", NULL}; PyObject *id; - if (!PyArg_UnpackTuple(args, "destroy", 1, 1, &id)) { + // XXX Use "L" for id? + if (!PyArg_ParseTupleAndKeywords(args, kwds, + "O:destroy", kwlist, &id)) { return NULL; } if (!PyLong_Check(id)) { @@ -2162,7 +2221,7 @@ interp_destroy(PyObject *self, PyObject *args) } PyDoc_STRVAR(destroy_doc, -"destroy(ID)\n\ +"destroy(id)\n\ \n\ Destroy the identified interpreter.\n\ \n\ @@ -2228,7 +2287,8 @@ static PyObject * interp_get_main(PyObject *self, PyObject *Py_UNUSED(ignored)) { // Currently, 0 is always the main interpreter. - return PyLong_FromLongLong(0); + PY_INT64_T id = 0; + return (PyObject *)newinterpid(&InterpreterIDtype, id, 0); } PyDoc_STRVAR(get_main_doc, @@ -2238,22 +2298,20 @@ Return the ID of main interpreter."); static PyObject * -interp_run_string(PyObject *self, PyObject *args) +interp_run_string(PyObject *self, PyObject *args, PyObject *kwds) { + static char *kwlist[] = {"id", "script", "shared", NULL}; PyObject *id, *code; PyObject *shared = NULL; - if (!PyArg_UnpackTuple(args, "run_string", 2, 3, &id, &code, &shared)) { + if (!PyArg_ParseTupleAndKeywords(args, kwds, + "OU|O:run_string", kwlist, + &id, &code, &shared)) { return NULL; } if (!PyLong_Check(id)) { PyErr_SetString(PyExc_TypeError, "first arg (ID) must be an int"); return NULL; } - if (!PyUnicode_Check(code)) { - PyErr_SetString(PyExc_TypeError, - "second arg (code) must be a string"); - return NULL; - } // Look up the interpreter. PyInterpreterState *interp = _look_up(id); @@ -2281,7 +2339,7 @@ interp_run_string(PyObject *self, PyObject *args) } PyDoc_STRVAR(run_string_doc, -"run_string(ID, sourcetext)\n\ +"run_string(id, script, shared)\n\ \n\ Execute the provided string in the identified interpreter.\n\ \n\ @@ -2289,12 +2347,15 @@ See PyRun_SimpleStrings."); static PyObject * -object_is_shareable(PyObject *self, PyObject *args) +object_is_shareable(PyObject *self, PyObject *args, PyObject *kwds) { + static char *kwlist[] = {"obj", NULL}; PyObject *obj; - if (!PyArg_UnpackTuple(args, "is_shareable", 1, 1, &obj)) { + if (!PyArg_ParseTupleAndKeywords(args, kwds, + "O:is_shareable", kwlist, &obj)) { return NULL; } + if (_PyObject_CheckCrossInterpreterData(obj) == 0) { Py_RETURN_TRUE; } @@ -2310,10 +2371,12 @@ False otherwise."); static PyObject * -interp_is_running(PyObject *self, PyObject *args) +interp_is_running(PyObject *self, PyObject *args, PyObject *kwds) { + static char *kwlist[] = {"id", NULL}; PyObject *id; - if (!PyArg_UnpackTuple(args, "is_running", 1, 1, &id)) { + if (!PyArg_ParseTupleAndKeywords(args, kwds, + "O:is_running", kwlist, &id)) { return NULL; } if (!PyLong_Check(id)) { @@ -2348,7 +2411,7 @@ channel_create(PyObject *self, PyObject *Py_UNUSED(ignored)) return NULL; } PyObject *id = (PyObject *)newchannelid(&ChannelIDtype, cid, 0, - &_globals.channels, 0); + &_globals.channels, 0, 0); if (id == NULL) { if (_channel_destroy(&_globals.channels, cid) != 0) { // XXX issue a warning? @@ -2360,15 +2423,17 @@ channel_create(PyObject *self, PyObject *Py_UNUSED(ignored)) } PyDoc_STRVAR(channel_create_doc, -"channel_create() -> ID\n\ +"channel_create() -> cid\n\ \n\ Create a new cross-interpreter channel and return a unique generated ID."); static PyObject * -channel_destroy(PyObject *self, PyObject *args) +channel_destroy(PyObject *self, PyObject *args, PyObject *kwds) { + static char *kwlist[] = {"cid", NULL}; PyObject *id; - if (!PyArg_UnpackTuple(args, "channel_destroy", 1, 1, &id)) { + if (!PyArg_ParseTupleAndKeywords(args, kwds, + "O:channel_destroy", kwlist, &id)) { return NULL; } int64_t cid = _coerce_id(id); @@ -2383,7 +2448,7 @@ channel_destroy(PyObject *self, PyObject *args) } PyDoc_STRVAR(channel_destroy_doc, -"channel_destroy(ID)\n\ +"channel_destroy(cid)\n\ \n\ Close and finalize the channel. Afterward attempts to use the channel\n\ will behave as though it never existed."); @@ -2406,7 +2471,7 @@ channel_list_all(PyObject *self, PyObject *Py_UNUSED(ignored)) int64_t *cur = cids; for (int64_t i=0; i < count; cur++, i++) { PyObject *id = (PyObject *)newchannelid(&ChannelIDtype, *cur, 0, - &_globals.channels, 0); + &_globals.channels, 0, 0); if (id == NULL) { Py_DECREF(ids); ids = NULL; @@ -2421,16 +2486,18 @@ channel_list_all(PyObject *self, PyObject *Py_UNUSED(ignored)) } PyDoc_STRVAR(channel_list_all_doc, -"channel_list_all() -> [ID]\n\ +"channel_list_all() -> [cid]\n\ \n\ Return the list of all IDs for active channels."); static PyObject * -channel_send(PyObject *self, PyObject *args) +channel_send(PyObject *self, PyObject *args, PyObject *kwds) { + static char *kwlist[] = {"cid", "obj", NULL}; PyObject *id; PyObject *obj; - if (!PyArg_UnpackTuple(args, "channel_send", 2, 2, &id, &obj)) { + if (!PyArg_ParseTupleAndKeywords(args, kwds, + "OO:channel_send", kwlist, &id, &obj)) { return NULL; } int64_t cid = _coerce_id(id); @@ -2445,15 +2512,17 @@ channel_send(PyObject *self, PyObject *args) } PyDoc_STRVAR(channel_send_doc, -"channel_send(ID, obj)\n\ +"channel_send(cid, obj)\n\ \n\ Add the object's data to the channel's queue."); static PyObject * -channel_recv(PyObject *self, PyObject *args) +channel_recv(PyObject *self, PyObject *args, PyObject *kwds) { + static char *kwlist[] = {"cid", NULL}; PyObject *id; - if (!PyArg_UnpackTuple(args, "channel_recv", 1, 1, &id)) { + if (!PyArg_ParseTupleAndKeywords(args, kwds, + "O:channel_recv", kwlist, &id)) { return NULL; } int64_t cid = _coerce_id(id); @@ -2465,17 +2534,34 @@ channel_recv(PyObject *self, PyObject *args) } PyDoc_STRVAR(channel_recv_doc, -"channel_recv(ID) -> obj\n\ +"channel_recv(cid) -> obj\n\ \n\ Return a new object from the data at the from of the channel's queue."); static PyObject * -channel_close(PyObject *self, PyObject *id) +channel_close(PyObject *self, PyObject *args, PyObject *kwds) { + static char *kwlist[] = {"cid", "send", "recv", "force", NULL}; + PyObject *id; + int send = 0; + int recv = 0; + int force = 0; + if (!PyArg_ParseTupleAndKeywords(args, kwds, + "O|$ppp:channel_close", kwlist, + &id, &send, &recv, &force)) { + return NULL; + } int64_t cid = _coerce_id(id); if (cid < 0) { return NULL; } + if (send == 0 && recv == 0) { + send = 1; + recv = 1; + } + + // XXX Handle the ends. + // XXX Handle force is True. if (_channel_close(&_globals.channels, cid) != 0) { return NULL; @@ -2484,48 +2570,66 @@ channel_close(PyObject *self, PyObject *id) } PyDoc_STRVAR(channel_close_doc, -"channel_close(ID)\n\ +"channel_close(cid, *, send=None, recv=None, force=False)\n\ +\n\ +Close the channel for all interpreters.\n\ \n\ -Close the channel for all interpreters. Once the channel's ID has\n\ -no more ref counts the channel will be destroyed."); +If the channel is empty then the keyword args are ignored and both\n\ +ends are immediately closed. Otherwise, if 'force' is True then\n\ +all queued items are released and both ends are immediately\n\ +closed.\n\ +\n\ +If the channel is not empty *and* 'force' is False then following\n\ +happens:\n\ +\n\ + * recv is True (regardless of send):\n\ + - raise ChannelNotEmptyError\n\ + * recv is None and send is None:\n\ + - raise ChannelNotEmptyError\n\ + * send is True and recv is not True:\n\ + - fully close the 'send' end\n\ + - close the 'recv' end to interpreters not already receiving\n\ + - fully close it once empty\n\ +\n\ +Closing an already closed channel results in a ChannelClosedError.\n\ +\n\ +Once the channel's ID has no more ref counts in any interpreter\n\ +the channel will be destroyed."); static PyObject * -channel_drop_interpreter(PyObject *self, PyObject *args, PyObject *kwds) +channel_release(PyObject *self, PyObject *args, PyObject *kwds) { // Note that only the current interpreter is affected. - static char *kwlist[] = {"id", "send", "recv", NULL}; + static char *kwlist[] = {"cid", "send", "recv", "force", NULL}; PyObject *id; - int send = -1; - int recv = -1; + int send = 0; + int recv = 0; + int force = 0; if (!PyArg_ParseTupleAndKeywords(args, kwds, - "O|$pp:channel_drop_interpreter", kwlist, - &id, &send, &recv)) + "O|$ppp:channel_release", kwlist, + &id, &send, &recv, &force)) { return NULL; - + } int64_t cid = _coerce_id(id); if (cid < 0) { return NULL; } - if (send < 0 && recv < 0) { + if (send == 0 && recv == 0) { send = 1; recv = 1; } - else { - if (send < 0) { - send = 0; - } - if (recv < 0) { - recv = 0; - } - } + + // XXX Handle force is True. + // XXX Fix implicit release. + if (_channel_drop(&_globals.channels, cid, send, recv) != 0) { return NULL; } Py_RETURN_NONE; } -PyDoc_STRVAR(channel_drop_interpreter_doc, -"channel_drop_interpreter(ID, *, send=None, recv=None)\n\ +PyDoc_STRVAR(channel_release_doc, +"channel_release(cid, *, send=None, recv=None, force=True)\n\ \n\ Close the channel for the current interpreter. 'send' and 'recv'\n\ (bool) may be used to indicate the ends to close. By default both\n\ @@ -2541,7 +2645,7 @@ static PyMethodDef module_functions[] = { {"create", (PyCFunction)interp_create, METH_VARARGS, create_doc}, {"destroy", (PyCFunction)interp_destroy, - METH_VARARGS, destroy_doc}, + METH_VARARGS | METH_KEYWORDS, destroy_doc}, {"list_all", interp_list_all, METH_NOARGS, list_all_doc}, {"get_current", interp_get_current, @@ -2549,27 +2653,27 @@ static PyMethodDef module_functions[] = { {"get_main", interp_get_main, METH_NOARGS, get_main_doc}, {"is_running", (PyCFunction)interp_is_running, - METH_VARARGS, is_running_doc}, + METH_VARARGS | METH_KEYWORDS, is_running_doc}, {"run_string", (PyCFunction)interp_run_string, - METH_VARARGS, run_string_doc}, + METH_VARARGS | METH_KEYWORDS, run_string_doc}, {"is_shareable", (PyCFunction)object_is_shareable, - METH_VARARGS, is_shareable_doc}, + METH_VARARGS | METH_KEYWORDS, is_shareable_doc}, {"channel_create", channel_create, METH_NOARGS, channel_create_doc}, {"channel_destroy", (PyCFunction)channel_destroy, - METH_VARARGS, channel_destroy_doc}, + METH_VARARGS | METH_KEYWORDS, channel_destroy_doc}, {"channel_list_all", channel_list_all, METH_NOARGS, channel_list_all_doc}, {"channel_send", (PyCFunction)channel_send, - METH_VARARGS, channel_send_doc}, + METH_VARARGS | METH_KEYWORDS, channel_send_doc}, {"channel_recv", (PyCFunction)channel_recv, - METH_VARARGS, channel_recv_doc}, - {"channel_close", channel_close, - METH_O, channel_close_doc}, - {"channel_drop_interpreter", (PyCFunction)channel_drop_interpreter, - METH_VARARGS | METH_KEYWORDS, channel_drop_interpreter_doc}, + METH_VARARGS | METH_KEYWORDS, channel_recv_doc}, + {"channel_close", (PyCFunction)channel_close, + METH_VARARGS | METH_KEYWORDS, channel_close_doc}, + {"channel_release", (PyCFunction)channel_release, + METH_VARARGS | METH_KEYWORDS, channel_release_doc}, {"_channel_id", (PyCFunction)channel__channel_id, METH_VARARGS | METH_KEYWORDS, NULL}, diff --git a/Python/pystate.c b/Python/pystate.c index 140d2fba8efd..d276bfc7e8af 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -1308,6 +1308,10 @@ _PyCrossInterpreterData_Register_Class(PyTypeObject *cls, return res; } +/* Cross-interpreter objects are looked up by exact match on the class. + We can reassess this policy when we move from a global registry to a + tp_* slot. */ + crossinterpdatafunc _PyCrossInterpreterData_Lookup(PyObject *obj) { @@ -1332,19 +1336,79 @@ _PyCrossInterpreterData_Lookup(PyObject *obj) /* cross-interpreter data for builtin types */ +struct _shared_bytes_data { + char *bytes; + Py_ssize_t len; +}; + static PyObject * _new_bytes_object(_PyCrossInterpreterData *data) { - return PyBytes_FromString((char *)(data->data)); + struct _shared_bytes_data *shared = (struct _shared_bytes_data *)(data->data); + return PyBytes_FromStringAndSize(shared->bytes, shared->len); } static int _bytes_shared(PyObject *obj, _PyCrossInterpreterData *data) { - data->data = (void *)(PyBytes_AS_STRING(obj)); + struct _shared_bytes_data *shared = PyMem_NEW(struct _shared_bytes_data, 1); + if (PyBytes_AsStringAndSize(obj, &shared->bytes, &shared->len) < 0) { + return -1; + } + data->data = (void *)shared; data->obj = obj; // Will be "released" (decref'ed) when data released. data->new_object = _new_bytes_object; - data->free = NULL; // Do not free the data (it belongs to the object). + data->free = PyMem_Free; + return 0; +} + +struct _shared_str_data { + int kind; + const void *buffer; + Py_ssize_t len; +}; + +static PyObject * +_new_str_object(_PyCrossInterpreterData *data) +{ + struct _shared_str_data *shared = (struct _shared_str_data *)(data->data); + return PyUnicode_FromKindAndData(shared->kind, shared->buffer, shared->len); +} + +static int +_str_shared(PyObject *obj, _PyCrossInterpreterData *data) +{ + struct _shared_str_data *shared = PyMem_NEW(struct _shared_str_data, 1); + shared->kind = PyUnicode_KIND(obj); + shared->buffer = PyUnicode_DATA(obj); + shared->len = PyUnicode_GET_LENGTH(obj) - 1; + data->data = (void *)shared; + data->obj = obj; // Will be "released" (decref'ed) when data released. + data->new_object = _new_str_object; + data->free = PyMem_Free; + return 0; +} + +static PyObject * +_new_long_object(_PyCrossInterpreterData *data) +{ + return PyLong_FromLongLong((int64_t)(data->data)); +} + +static int +_long_shared(PyObject *obj, _PyCrossInterpreterData *data) +{ + int64_t value = PyLong_AsLongLong(obj); + if (value == -1 && PyErr_Occurred()) { + if (PyErr_ExceptionMatches(PyExc_OverflowError)) { + PyErr_SetString(PyExc_OverflowError, "try sending as bytes"); + } + return -1; + } + data->data = (void *)value; + data->obj = NULL; + data->new_object = _new_long_object; + data->free = NULL; return 0; } @@ -1374,10 +1438,20 @@ _register_builtins_for_crossinterpreter_data(void) Py_FatalError("could not register None for cross-interpreter sharing"); } + // int + if (_register_xidata(&PyLong_Type, _long_shared) != 0) { + Py_FatalError("could not register int for cross-interpreter sharing"); + } + // bytes if (_register_xidata(&PyBytes_Type, _bytes_shared) != 0) { Py_FatalError("could not register bytes for cross-interpreter sharing"); } + + // str + if (_register_xidata(&PyUnicode_Type, _str_shared) != 0) { + Py_FatalError("could not register str for cross-interpreter sharing"); + } } From webhook-mailer at python.org Wed May 16 15:50:10 2018 From: webhook-mailer at python.org (Barry Warsaw) Date: Wed, 16 May 2018 19:50:10 -0000 Subject: [Python-checkins] bpo-32216: Update dataclasses documentation (#6913) Message-ID: <mailman.95.1526500213.2757.python-checkins@python.org> https://github.com/python/cpython/commit/713a9367366c88662c39ed20dd6bce22399299f1 commit: 713a9367366c88662c39ed20dd6bce22399299f1 branch: master author: Barry Warsaw <barry at python.org> committer: GitHub <noreply at github.com> date: 2018-05-16T15:50:07-04:00 summary: bpo-32216: Update dataclasses documentation (#6913) files: M Doc/library/dataclasses.rst diff --git a/Doc/library/dataclasses.rst b/Doc/library/dataclasses.rst index a90fcf78348a..b26f6422db91 100644 --- a/Doc/library/dataclasses.rst +++ b/Doc/library/dataclasses.rst @@ -117,50 +117,46 @@ Module-level decorators, classes, and functions :meth:`__le__`, :meth:`__gt__`, or :meth:`__ge__`, then :exc:`ValueError` is raised. - - ``unsafe_hash``: If ``False`` (the default), the :meth:`__hash__` method + - ``unsafe_hash``: If ``False`` (the default), a :meth:`__hash__` method is generated according to how ``eq`` and ``frozen`` are set. - If ``eq`` and ``frozen`` are both true, :func:`dataclass` will - generate a :meth:`__hash__` method for you. If ``eq`` is true - and ``frozen`` is false, :meth:`__hash__` will be set to - ``None``, marking it unhashable (which it is, since it is - mutable). If ``eq`` is false, :meth:`__hash__` will be left - untouched meaning the :meth:`__hash__` method of the superclass - will be used (if the superclass is :class:`object`, this means it will - fall back to id-based hashing). - - Although not recommended, you can force :func:`dataclass` to - create a :meth:`__hash__` method with ``unsafe_hash=True``. This - might be the case if your class is logically immutable but can - nonetheless be mutated. This is a specialized use case and should - be considered carefully. - - If a class already has an explicitely defined :meth:`__hash__` - the behavior when adding :meth:`__hash__` is modified. An - expicitely defined :meth:`__hash__` is defined when: - - - :meth:`__eq__` is defined in the class and :meth:`__hash__` is defined - with any value other than ``None``. - - - :meth:`__eq__` is defined in the class and any non-``None`` - :meth:`__hash__` is defined. - - - :meth:`__eq__` is not defined on the class, and any :meth:`__hash__` is - defined. - - If ``unsafe_hash`` is true and an explicitely defined :meth:`__hash__` - is present, then :exc:`ValueError` is raised. - - If ``unsafe_hash`` is false and an explicitely defined :meth:`__hash__` - is present, then no :meth:`__hash__` is added. - - See the Python documentation for more information. + :meth:`__hash__` is used by built-in :meth:`hash()`, and when objects are + added to hashed collections such as dictionaries and sets. Having a + :meth:`__hash__` implies that instances of the class are immutable. + Mutability is a complicated property that depends on the programmer's + intent, the existence and behavior of :meth:`__eq__`, and the values of + the ``eq`` and ``frozen`` flags in the :func:`dataclass` decorator. + + By default, :func:`dataclass` will not implicitly add a :meth:`__hash__` + method unless it is safe to do so. Neither will it add or change an + existing explicitly defined :meth:`__hash__` method. Setting the class + attribute ``__hash__ = None`` has a specific meaning to Python, as + described in the :meth:`__hash__` documentation. + + If :meth:`__hash__` is not explicit defined, or if it is set to ``None``, + then :func:`dataclass` *may* add an implicit :meth:`__hash__` method. + Although not recommended, you can force :func:`dataclass` to create a + :meth:`__hash__` method with ``unsafe_hash=True``. This might be the case + if your class is logically immutable but can nonetheless be mutated. + This is a specialized use case and should be considered carefully. + + Here are the rules governing implicit creation of a :meth:`__hash__` + method. Note that you cannot both have an explicit :meth:`__hash__` + method in your dataclass and set ``unsafe_hash=True``; this will result + in a :exc:`TypeError`. + + If ``eq`` and ``frozen`` are both true, by default :func:`dataclass` will + generate a :meth:`__hash__` method for you. If ``eq`` is true and + ``frozen`` is false, :meth:`__hash__` will be set to ``None``, marking it + unhashable (which it is, since it is mutable). If ``eq`` is false, + :meth:`__hash__` will be left untouched meaning the :meth:`__hash__` + method of the superclass will be used (if the superclass is + :class:`object`, this means it will fall back to id-based hashing). - ``frozen``: If true (the default is False), assigning to fields will - generate an exception. This emulates read-only frozen instances. - If either :meth:`__getattr__` or :meth:`__setattr__` is defined in - the class, then :exc:`ValueError` is raised. See the discussion - below. + generate an exception. This emulates read-only frozen instances. If + :meth:`__setattr__` or :meth:`__delattr__` is defined in the class, then + :exc:`TypeError` is raised. See the discussion below. ``field``\s may optionally specify a default value, using normal Python syntax:: @@ -182,17 +178,17 @@ Module-level decorators, classes, and functions .. function:: field(*, default=MISSING, default_factory=MISSING, repr=True, hash=None, init=True, compare=True, metadata=None) For common and simple use cases, no other functionality is - required. There are, however, some Data Class features that + required. There are, however, some dataclass features that require additional per-field information. To satisfy this need for additional information, you can replace the default field value with a call to the provided :func:`field` function. For example:: @dataclass class C: - l: List[int] = field(default_factory=list) + mylist: List[int] = field(default_factory=list) c = C() - c.l += [1, 2, 3] + c.mylist += [1, 2, 3] As shown above, the ``MISSING`` value is a sentinel object used to detect if the ``default`` and ``default_factory`` parameters are @@ -222,7 +218,7 @@ Module-level decorators, classes, and functions generated equality and comparison methods (:meth:`__eq__`, :meth:`__gt__`, et al.). - - ``hash``: This can be a bool or ``None``. If True, this field is + - ``hash``: This can be a bool or ``None``. If true, this field is included in the generated :meth:`__hash__` method. If ``None`` (the default), use the value of ``compare``: this would normally be the expected behavior. A field should be considered in the hash @@ -283,17 +279,16 @@ Module-level decorators, classes, and functions .. function:: fields(class_or_instance) - Returns a tuple of :class:`Field` objects - that define the fields for this Data Class. Accepts either a Data - Class, or an instance of a Data Class. Raises :exc:`ValueError` if - not passed a Data Class or instance of one. Does not return - pseudo-fields which are ``ClassVar`` or ``InitVar``. + Returns a tuple of :class:`Field` objects that define the fields for this + dataclass. Accepts either a dataclass, or an instance of a dataclass. + Raises :exc:`TypeError` if not passed a dataclass or instance of one. + Does not return pseudo-fields which are ``ClassVar`` or ``InitVar``. .. function:: asdict(instance, *, dict_factory=dict) - Converts the Data Class ``instance`` to a dict (by using the - factory function ``dict_factory``). Each Data Class is converted - to a dict of its fields, as ``name: value`` pairs. Data Classes, dicts, + Converts the dataclass ``instance`` to a dict (by using the + factory function ``dict_factory``). Each dataclass is converted + to a dict of its fields, as ``name: value`` pairs. dataclasses, dicts, lists, and tuples are recursed into. For example:: @dataclass @@ -303,21 +298,21 @@ Module-level decorators, classes, and functions @dataclass class C: - l: List[Point] + mylist: List[Point] p = Point(10, 20) assert asdict(p) == {'x': 10, 'y': 20} c = C([Point(0, 0), Point(10, 4)]) - assert asdict(c) == {'l': [{'x': 0, 'y': 0}, {'x': 10, 'y': 4}]} + assert asdict(c) == {'mylist': [{'x': 0, 'y': 0}, {'x': 10, 'y': 4}]} - Raises :exc:`TypeError` if ``instance`` is not a Data Class instance. + Raises :exc:`TypeError` if ``instance`` is not a dataclass instance. .. function:: astuple(*, tuple_factory=tuple) - Converts the Data Class ``instance`` to a tuple (by using the - factory function ``tuple_factory``). Each Data Class is converted - to a tuple of its field values. Data Classes, dicts, lists, and + Converts the dataclass ``instance`` to a tuple (by using the + factory function ``tuple_factory``). Each dataclass is converted + to a tuple of its field values. dataclasses, dicts, lists, and tuples are recursed into. Continuing from the previous example:: @@ -325,11 +320,11 @@ Module-level decorators, classes, and functions assert astuple(p) == (10, 20) assert astuple(c) == ([(0, 0), (10, 4)],) - Raises :exc:`TypeError` if ``instance`` is not a Data Class instance. + Raises :exc:`TypeError` if ``instance`` is not a dataclass instance. .. function:: make_dataclass(cls_name, fields, *, bases=(), namespace=None, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False) - Creates a new Data Class with name ``cls_name``, fields as defined + Creates a new dataclass with name ``cls_name``, fields as defined in ``fields``, base classes as given in ``bases``, and initialized with a namespace as given in ``namespace``. ``fields`` is an iterable whose elements are each either ``name``, ``(name, type)``, @@ -341,7 +336,7 @@ Module-level decorators, classes, and functions This function is not strictly required, because any Python mechanism for creating a new class with ``__annotations__`` can then apply the :func:`dataclass` function to convert that class to - a Data Class. This function is provided as a convenience. For + a dataclass. This function is provided as a convenience. For example:: C = make_dataclass('C', @@ -369,14 +364,14 @@ Module-level decorators, classes, and functions specify fields, raises :exc:`TypeError`. The newly returned object is created by calling the :meth:`__init__` - method of the Data Class. This ensures that + method of the dataclass. This ensures that :meth:`__post_init__`, if present, is also called. Init-only variables without default values, if any exist, must be specified on the call to :func:`replace` so that they can be passed to :meth:`__init__` and :meth:`__post_init__`. - It is an error for :func:`changes` to contain any fields that are + It is an error for ``changes`` to contain any fields that are defined as having ``init=False``. A :exc:`ValueError` will be raised in this case. @@ -408,7 +403,7 @@ The generated :meth:`__init__` code will call a method named :meth:`__post_init__`, if :meth:`__post_init__` is defined on the class. It will normally be called as ``self.__post_init__()``. However, if any ``InitVar`` fields are defined, they will also be -passed to :meth:`__post_init` in the order they were defined in the +passed to :meth:`__post_init__` in the order they were defined in the class. If no :meth:`__init__` method is generated, then :meth:`__post_init__` will not automatically be called. @@ -435,7 +430,7 @@ One of two places where :func:`dataclass` actually inspects the type of a field is to determine if a field is a class variable as defined in :pep:`526`. It does this by checking if the type of the field is ``typing.ClassVar``. If a field is a ``ClassVar``, it is excluded -from consideration as a field and is ignored by the Data Class +from consideration as a field and is ignored by the dataclass mechanisms. Such ``ClassVar`` pseudo-fields are not returned by the module-level :func:`fields` function. @@ -450,7 +445,7 @@ field. As it is not a true field, it is not returned by the module-level :func:`fields` function. Init-only fields are added as parameters to the generated :meth:`__init__` method, and are passed to the optional :meth:`__post_init__` method. They are not otherwise used -by Data Classes. +by dataclasses. For example, suppose a field will be initialzed from a database, if a value is not provided when creating the class:: @@ -475,7 +470,7 @@ Frozen instances It is not possible to create truly immutable Python objects. However, by passing ``frozen=True`` to the :meth:`dataclass` decorator you can -emulate immutability. In that case, Data Classes will add +emulate immutability. In that case, dataclasses will add :meth:`__setattr__` and :meth:`__delattr__` methods to the class. These methods will raise a :exc:`FrozenInstanceError` when invoked. @@ -486,9 +481,9 @@ must use :meth:`object.__setattr__`. Inheritance ----------- -When the Data Class is being created by the :meth:`dataclass` decorator, +When the dataclass is being created by the :meth:`dataclass` decorator, it looks through all of the class's base classes in reverse MRO (that -is, starting at :class:`object`) and, for each Data Class that it finds, +is, starting at :class:`object`) and, for each dataclass that it finds, adds the fields from that base class to an ordered mapping of fields. After all of the base class fields are added, it adds its own fields to the ordered mapping. All of the generated methods will use this @@ -520,7 +515,7 @@ Default factory functions zero arguments when a default value for the field is needed. For example, to create a new instance of a list, use:: - l: list = field(default_factory=list) + mylist: list = field(default_factory=list) If a field is excluded from :meth:`__init__` (using ``init=False``) and the field also specifies ``default_factory``, then the default @@ -532,7 +527,7 @@ Mutable default values ---------------------- Python stores default member variable values in class attributes. - Consider this example, not using Data Classes:: + Consider this example, not using dataclasses:: class C: x = [] @@ -549,7 +544,7 @@ Mutable default values Note that the two instances of class ``C`` share the same class variable ``x``, as expected. - Using Data Classes, *if* this code was valid:: + Using dataclasses, *if* this code was valid:: @dataclass class D: @@ -571,9 +566,9 @@ Mutable default values This has the same issue as the original example using class ``C``. That is, two instances of class ``D`` that do not specify a value for ``x`` when creating a class instance will share the same copy of - ``x``. Because Data Classes just use normal Python class creation - they also share this problem. There is no general way for Data - Classes to detect this condition. Instead, Data Classes will raise a + ``x``. Because dataclasses just use normal Python class creation + they also share this behavior. There is no general way for Data + Classes to detect this condition. Instead, dataclasses will raise a :exc:`TypeError` if it detects a default parameter of type ``list``, ``dict``, or ``set``. This is a partial solution, but it does protect against many common errors. @@ -586,3 +581,12 @@ Mutable default values x: list = field(default_factory=list) assert D().x is not D().x + +Exceptions +---------- + +.. exception:: FrozenInstanceError + + Raised when an implicitly defined :meth:`__setattr__` or + :meth:`__delattr__` is called on a dataclass which was defined with + ``frozen=True``. From webhook-mailer at python.org Wed May 16 16:37:17 2018 From: webhook-mailer at python.org (Barry Warsaw) Date: Wed, 16 May 2018 20:37:17 -0000 Subject: [Python-checkins] bpo-32216: Update dataclasses documentation (GH-6913) (#6918) Message-ID: <mailman.96.1526503039.2757.python-checkins@python.org> https://github.com/python/cpython/commit/0c62e09774e445a185fd192524454ce697ca123b commit: 0c62e09774e445a185fd192524454ce697ca123b branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Barry Warsaw <barry at python.org> date: 2018-05-16T16:37:14-04:00 summary: bpo-32216: Update dataclasses documentation (GH-6913) (#6918) (cherry picked from commit 713a9367366c88662c39ed20dd6bce22399299f1) Co-authored-by: Barry Warsaw <barry at python.org> files: M Doc/library/dataclasses.rst diff --git a/Doc/library/dataclasses.rst b/Doc/library/dataclasses.rst index a90fcf78348a..b26f6422db91 100644 --- a/Doc/library/dataclasses.rst +++ b/Doc/library/dataclasses.rst @@ -117,50 +117,46 @@ Module-level decorators, classes, and functions :meth:`__le__`, :meth:`__gt__`, or :meth:`__ge__`, then :exc:`ValueError` is raised. - - ``unsafe_hash``: If ``False`` (the default), the :meth:`__hash__` method + - ``unsafe_hash``: If ``False`` (the default), a :meth:`__hash__` method is generated according to how ``eq`` and ``frozen`` are set. - If ``eq`` and ``frozen`` are both true, :func:`dataclass` will - generate a :meth:`__hash__` method for you. If ``eq`` is true - and ``frozen`` is false, :meth:`__hash__` will be set to - ``None``, marking it unhashable (which it is, since it is - mutable). If ``eq`` is false, :meth:`__hash__` will be left - untouched meaning the :meth:`__hash__` method of the superclass - will be used (if the superclass is :class:`object`, this means it will - fall back to id-based hashing). - - Although not recommended, you can force :func:`dataclass` to - create a :meth:`__hash__` method with ``unsafe_hash=True``. This - might be the case if your class is logically immutable but can - nonetheless be mutated. This is a specialized use case and should - be considered carefully. - - If a class already has an explicitely defined :meth:`__hash__` - the behavior when adding :meth:`__hash__` is modified. An - expicitely defined :meth:`__hash__` is defined when: - - - :meth:`__eq__` is defined in the class and :meth:`__hash__` is defined - with any value other than ``None``. - - - :meth:`__eq__` is defined in the class and any non-``None`` - :meth:`__hash__` is defined. - - - :meth:`__eq__` is not defined on the class, and any :meth:`__hash__` is - defined. - - If ``unsafe_hash`` is true and an explicitely defined :meth:`__hash__` - is present, then :exc:`ValueError` is raised. - - If ``unsafe_hash`` is false and an explicitely defined :meth:`__hash__` - is present, then no :meth:`__hash__` is added. - - See the Python documentation for more information. + :meth:`__hash__` is used by built-in :meth:`hash()`, and when objects are + added to hashed collections such as dictionaries and sets. Having a + :meth:`__hash__` implies that instances of the class are immutable. + Mutability is a complicated property that depends on the programmer's + intent, the existence and behavior of :meth:`__eq__`, and the values of + the ``eq`` and ``frozen`` flags in the :func:`dataclass` decorator. + + By default, :func:`dataclass` will not implicitly add a :meth:`__hash__` + method unless it is safe to do so. Neither will it add or change an + existing explicitly defined :meth:`__hash__` method. Setting the class + attribute ``__hash__ = None`` has a specific meaning to Python, as + described in the :meth:`__hash__` documentation. + + If :meth:`__hash__` is not explicit defined, or if it is set to ``None``, + then :func:`dataclass` *may* add an implicit :meth:`__hash__` method. + Although not recommended, you can force :func:`dataclass` to create a + :meth:`__hash__` method with ``unsafe_hash=True``. This might be the case + if your class is logically immutable but can nonetheless be mutated. + This is a specialized use case and should be considered carefully. + + Here are the rules governing implicit creation of a :meth:`__hash__` + method. Note that you cannot both have an explicit :meth:`__hash__` + method in your dataclass and set ``unsafe_hash=True``; this will result + in a :exc:`TypeError`. + + If ``eq`` and ``frozen`` are both true, by default :func:`dataclass` will + generate a :meth:`__hash__` method for you. If ``eq`` is true and + ``frozen`` is false, :meth:`__hash__` will be set to ``None``, marking it + unhashable (which it is, since it is mutable). If ``eq`` is false, + :meth:`__hash__` will be left untouched meaning the :meth:`__hash__` + method of the superclass will be used (if the superclass is + :class:`object`, this means it will fall back to id-based hashing). - ``frozen``: If true (the default is False), assigning to fields will - generate an exception. This emulates read-only frozen instances. - If either :meth:`__getattr__` or :meth:`__setattr__` is defined in - the class, then :exc:`ValueError` is raised. See the discussion - below. + generate an exception. This emulates read-only frozen instances. If + :meth:`__setattr__` or :meth:`__delattr__` is defined in the class, then + :exc:`TypeError` is raised. See the discussion below. ``field``\s may optionally specify a default value, using normal Python syntax:: @@ -182,17 +178,17 @@ Module-level decorators, classes, and functions .. function:: field(*, default=MISSING, default_factory=MISSING, repr=True, hash=None, init=True, compare=True, metadata=None) For common and simple use cases, no other functionality is - required. There are, however, some Data Class features that + required. There are, however, some dataclass features that require additional per-field information. To satisfy this need for additional information, you can replace the default field value with a call to the provided :func:`field` function. For example:: @dataclass class C: - l: List[int] = field(default_factory=list) + mylist: List[int] = field(default_factory=list) c = C() - c.l += [1, 2, 3] + c.mylist += [1, 2, 3] As shown above, the ``MISSING`` value is a sentinel object used to detect if the ``default`` and ``default_factory`` parameters are @@ -222,7 +218,7 @@ Module-level decorators, classes, and functions generated equality and comparison methods (:meth:`__eq__`, :meth:`__gt__`, et al.). - - ``hash``: This can be a bool or ``None``. If True, this field is + - ``hash``: This can be a bool or ``None``. If true, this field is included in the generated :meth:`__hash__` method. If ``None`` (the default), use the value of ``compare``: this would normally be the expected behavior. A field should be considered in the hash @@ -283,17 +279,16 @@ Module-level decorators, classes, and functions .. function:: fields(class_or_instance) - Returns a tuple of :class:`Field` objects - that define the fields for this Data Class. Accepts either a Data - Class, or an instance of a Data Class. Raises :exc:`ValueError` if - not passed a Data Class or instance of one. Does not return - pseudo-fields which are ``ClassVar`` or ``InitVar``. + Returns a tuple of :class:`Field` objects that define the fields for this + dataclass. Accepts either a dataclass, or an instance of a dataclass. + Raises :exc:`TypeError` if not passed a dataclass or instance of one. + Does not return pseudo-fields which are ``ClassVar`` or ``InitVar``. .. function:: asdict(instance, *, dict_factory=dict) - Converts the Data Class ``instance`` to a dict (by using the - factory function ``dict_factory``). Each Data Class is converted - to a dict of its fields, as ``name: value`` pairs. Data Classes, dicts, + Converts the dataclass ``instance`` to a dict (by using the + factory function ``dict_factory``). Each dataclass is converted + to a dict of its fields, as ``name: value`` pairs. dataclasses, dicts, lists, and tuples are recursed into. For example:: @dataclass @@ -303,21 +298,21 @@ Module-level decorators, classes, and functions @dataclass class C: - l: List[Point] + mylist: List[Point] p = Point(10, 20) assert asdict(p) == {'x': 10, 'y': 20} c = C([Point(0, 0), Point(10, 4)]) - assert asdict(c) == {'l': [{'x': 0, 'y': 0}, {'x': 10, 'y': 4}]} + assert asdict(c) == {'mylist': [{'x': 0, 'y': 0}, {'x': 10, 'y': 4}]} - Raises :exc:`TypeError` if ``instance`` is not a Data Class instance. + Raises :exc:`TypeError` if ``instance`` is not a dataclass instance. .. function:: astuple(*, tuple_factory=tuple) - Converts the Data Class ``instance`` to a tuple (by using the - factory function ``tuple_factory``). Each Data Class is converted - to a tuple of its field values. Data Classes, dicts, lists, and + Converts the dataclass ``instance`` to a tuple (by using the + factory function ``tuple_factory``). Each dataclass is converted + to a tuple of its field values. dataclasses, dicts, lists, and tuples are recursed into. Continuing from the previous example:: @@ -325,11 +320,11 @@ Module-level decorators, classes, and functions assert astuple(p) == (10, 20) assert astuple(c) == ([(0, 0), (10, 4)],) - Raises :exc:`TypeError` if ``instance`` is not a Data Class instance. + Raises :exc:`TypeError` if ``instance`` is not a dataclass instance. .. function:: make_dataclass(cls_name, fields, *, bases=(), namespace=None, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False) - Creates a new Data Class with name ``cls_name``, fields as defined + Creates a new dataclass with name ``cls_name``, fields as defined in ``fields``, base classes as given in ``bases``, and initialized with a namespace as given in ``namespace``. ``fields`` is an iterable whose elements are each either ``name``, ``(name, type)``, @@ -341,7 +336,7 @@ Module-level decorators, classes, and functions This function is not strictly required, because any Python mechanism for creating a new class with ``__annotations__`` can then apply the :func:`dataclass` function to convert that class to - a Data Class. This function is provided as a convenience. For + a dataclass. This function is provided as a convenience. For example:: C = make_dataclass('C', @@ -369,14 +364,14 @@ Module-level decorators, classes, and functions specify fields, raises :exc:`TypeError`. The newly returned object is created by calling the :meth:`__init__` - method of the Data Class. This ensures that + method of the dataclass. This ensures that :meth:`__post_init__`, if present, is also called. Init-only variables without default values, if any exist, must be specified on the call to :func:`replace` so that they can be passed to :meth:`__init__` and :meth:`__post_init__`. - It is an error for :func:`changes` to contain any fields that are + It is an error for ``changes`` to contain any fields that are defined as having ``init=False``. A :exc:`ValueError` will be raised in this case. @@ -408,7 +403,7 @@ The generated :meth:`__init__` code will call a method named :meth:`__post_init__`, if :meth:`__post_init__` is defined on the class. It will normally be called as ``self.__post_init__()``. However, if any ``InitVar`` fields are defined, they will also be -passed to :meth:`__post_init` in the order they were defined in the +passed to :meth:`__post_init__` in the order they were defined in the class. If no :meth:`__init__` method is generated, then :meth:`__post_init__` will not automatically be called. @@ -435,7 +430,7 @@ One of two places where :func:`dataclass` actually inspects the type of a field is to determine if a field is a class variable as defined in :pep:`526`. It does this by checking if the type of the field is ``typing.ClassVar``. If a field is a ``ClassVar``, it is excluded -from consideration as a field and is ignored by the Data Class +from consideration as a field and is ignored by the dataclass mechanisms. Such ``ClassVar`` pseudo-fields are not returned by the module-level :func:`fields` function. @@ -450,7 +445,7 @@ field. As it is not a true field, it is not returned by the module-level :func:`fields` function. Init-only fields are added as parameters to the generated :meth:`__init__` method, and are passed to the optional :meth:`__post_init__` method. They are not otherwise used -by Data Classes. +by dataclasses. For example, suppose a field will be initialzed from a database, if a value is not provided when creating the class:: @@ -475,7 +470,7 @@ Frozen instances It is not possible to create truly immutable Python objects. However, by passing ``frozen=True`` to the :meth:`dataclass` decorator you can -emulate immutability. In that case, Data Classes will add +emulate immutability. In that case, dataclasses will add :meth:`__setattr__` and :meth:`__delattr__` methods to the class. These methods will raise a :exc:`FrozenInstanceError` when invoked. @@ -486,9 +481,9 @@ must use :meth:`object.__setattr__`. Inheritance ----------- -When the Data Class is being created by the :meth:`dataclass` decorator, +When the dataclass is being created by the :meth:`dataclass` decorator, it looks through all of the class's base classes in reverse MRO (that -is, starting at :class:`object`) and, for each Data Class that it finds, +is, starting at :class:`object`) and, for each dataclass that it finds, adds the fields from that base class to an ordered mapping of fields. After all of the base class fields are added, it adds its own fields to the ordered mapping. All of the generated methods will use this @@ -520,7 +515,7 @@ Default factory functions zero arguments when a default value for the field is needed. For example, to create a new instance of a list, use:: - l: list = field(default_factory=list) + mylist: list = field(default_factory=list) If a field is excluded from :meth:`__init__` (using ``init=False``) and the field also specifies ``default_factory``, then the default @@ -532,7 +527,7 @@ Mutable default values ---------------------- Python stores default member variable values in class attributes. - Consider this example, not using Data Classes:: + Consider this example, not using dataclasses:: class C: x = [] @@ -549,7 +544,7 @@ Mutable default values Note that the two instances of class ``C`` share the same class variable ``x``, as expected. - Using Data Classes, *if* this code was valid:: + Using dataclasses, *if* this code was valid:: @dataclass class D: @@ -571,9 +566,9 @@ Mutable default values This has the same issue as the original example using class ``C``. That is, two instances of class ``D`` that do not specify a value for ``x`` when creating a class instance will share the same copy of - ``x``. Because Data Classes just use normal Python class creation - they also share this problem. There is no general way for Data - Classes to detect this condition. Instead, Data Classes will raise a + ``x``. Because dataclasses just use normal Python class creation + they also share this behavior. There is no general way for Data + Classes to detect this condition. Instead, dataclasses will raise a :exc:`TypeError` if it detects a default parameter of type ``list``, ``dict``, or ``set``. This is a partial solution, but it does protect against many common errors. @@ -586,3 +581,12 @@ Mutable default values x: list = field(default_factory=list) assert D().x is not D().x + +Exceptions +---------- + +.. exception:: FrozenInstanceError + + Raised when an implicitly defined :meth:`__setattr__` or + :meth:`__delattr__` is called on a dataclass which was defined with + ``frozen=True``. From webhook-mailer at python.org Wed May 16 17:50:39 2018 From: webhook-mailer at python.org (Steve Dower) Date: Wed, 16 May 2018 21:50:39 -0000 Subject: [Python-checkins] bpo-33522: Enable CI builds on Visual Studio Team Services (#6865) Message-ID: <mailman.97.1526507442.2757.python-checkins@python.org> https://github.com/python/cpython/commit/e5f41d2f1e0b8b8e61d5fa427c19bd1ea90fd9a3 commit: e5f41d2f1e0b8b8e61d5fa427c19bd1ea90fd9a3 branch: master author: Steve Dower <steve.dower at microsoft.com> committer: GitHub <noreply at github.com> date: 2018-05-16T17:50:29-04:00 summary: bpo-33522: Enable CI builds on Visual Studio Team Services (#6865) files: A .vsts/docs-release.yml A .vsts/docs.yml A .vsts/linux-buildbot.yml A .vsts/linux-coverage.yml A .vsts/linux-deps.yml A .vsts/linux-pr.yml A .vsts/macos-buildbot.yml A .vsts/macos-pr.yml A .vsts/windows-buildbot.yml A .vsts/windows-pr.yml A Misc/NEWS.d/next/Build/2018-05-15-12-44-50.bpo-33522.mJoNcA.rst A Misc/NEWS.d/next/Library/2018-05-16-17-05-48.bpo-33548.xWslmx.rst M Doc/make.bat M Lib/tempfile.py M Lib/test/support/__init__.py M Lib/test/test_asyncio/test_base_events.py M Lib/test/test_bdb.py M Lib/test/test_pathlib.py M Lib/test/test_poplib.py M Lib/test/test_selectors.py M PCbuild/rt.bat M Tools/ssl/multissltests.py diff --git a/.vsts/docs-release.yml b/.vsts/docs-release.yml new file mode 100644 index 000000000000..e90428a42494 --- /dev/null +++ b/.vsts/docs-release.yml @@ -0,0 +1,43 @@ +# Current docs for the syntax of this file are at: +# https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md + +name: $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.rr) + +queue: + name: Hosted Linux Preview + +#variables: + +steps: +- checkout: self + clean: true + fetchDepth: 5 + +- script: sudo apt-get update && sudo apt-get install -qy --force-yes texlive-full + displayName: 'Install LaTeX' + +- task: UsePythonVersion at 0 + displayName: 'Use Python 3.6 or later' + inputs: + versionSpec: '>=3.6' + +- script: python -m pip install sphinx blurb python-docs-theme + displayName: 'Install build dependencies' + +- script: make dist PYTHON=python SPHINXBUILD='python -m sphinx' BLURB='python -m blurb' + workingDirectory: '$(build.sourcesDirectory)/Doc' + displayName: 'Build documentation' + +- task: PublishBuildArtifacts at 1 + displayName: 'Publish build' + inputs: + PathToPublish: '$(build.sourcesDirectory)/Doc/build' + ArtifactName: build + publishLocation: Container + +- task: PublishBuildArtifacts at 1 + displayName: 'Publish dist' + inputs: + PathToPublish: '$(build.sourcesDirectory)/Doc/dist' + ArtifactName: dist + publishLocation: Container diff --git a/.vsts/docs.yml b/.vsts/docs.yml new file mode 100644 index 000000000000..efa1e871656d --- /dev/null +++ b/.vsts/docs.yml @@ -0,0 +1,43 @@ +# Current docs for the syntax of this file are at: +# https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md + +name: $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.rr) + +queue: + name: Hosted Linux Preview + +trigger: + branches: + include: + - master + - 3.7 + - 3.6 + paths: + include: + - Doc/* + +#variables: + +steps: +- checkout: self + clean: true + fetchDepth: 5 + +- task: UsePythonVersion at 0 + displayName: 'Use Python 3.6 or later' + inputs: + versionSpec: '>=3.6' + +- script: python -m pip install sphinx~=1.6.1 blurb python-docs-theme + displayName: 'Install build dependencies' + +- script: make check suspicious html PYTHON=python + workingDirectory: '$(build.sourcesDirectory)/Doc' + displayName: 'Build documentation' + +- task: PublishBuildArtifacts at 1 + displayName: 'Publish build' + inputs: + PathToPublish: '$(build.sourcesDirectory)/Doc/build' + ArtifactName: build + publishLocation: Container diff --git a/.vsts/linux-buildbot.yml b/.vsts/linux-buildbot.yml new file mode 100644 index 000000000000..d75d7f57650e --- /dev/null +++ b/.vsts/linux-buildbot.yml @@ -0,0 +1,71 @@ +# Current docs for the syntax of this file are at: +# https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md + +name: $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.rr) + +queue: + name: Hosted Linux Preview + +trigger: + branches: + include: + - master + - 3.7 + - 3.6 + paths: + exclude: + - Doc/* + - Tools/* + +variables: + # Copy-pasted from linux-deps.yml until template support arrives + OPENSSL: 1.1.0g + OPENSSL_DIR: "$(build.sourcesDirectory)/multissl/openssl/$(OPENSSL)" + + +steps: +- checkout: self + clean: true + fetchDepth: 5 + +#- template: linux-deps.yml + +# See https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted-templates.md +# For now, we copy/paste the steps +- script: echo "deb-src http://archive.ubuntu.com/ubuntu/ xenial main" > /etc/apt/sources.list.d/python.list && sudo apt-get update + displayName: 'Update apt-get lists' + +- script: echo ##vso[task.prependpath]$(OPENSSL_DIR) + displayName: 'Add $(OPENSSL_DIR) to PATH' +- script: > + sudo apt-get -yq install + build-essential + zlib1g-dev + libbz2-dev + liblzma-dev + libncurses5-dev + libreadline6-dev + libsqlite3-dev + libssl-dev + libgdbm-dev + tk-dev + lzma + lzma-dev + liblzma-dev + libffi-dev + uuid-dev + displayName: 'Install dependencies' +- script: python3 Tools/ssl/multissltests.py --steps=library --base-directory $(build.sourcesDirectory)/multissl --openssl $(OPENSSL) --system Linux + displayName: 'python multissltests.py' + +- script: ./configure --with-pydebug + displayName: 'Configure CPython (debug)' + +- script: make -s -j4 + displayName: 'Build CPython' + +- script: make pythoninfo + displayName: 'Display build info' + +- script: make buildbottest TESTOPTS="-j4 -uall,-cpu" + displayName: 'Tests' diff --git a/.vsts/linux-coverage.yml b/.vsts/linux-coverage.yml new file mode 100644 index 000000000000..3657b1720ee2 --- /dev/null +++ b/.vsts/linux-coverage.yml @@ -0,0 +1,77 @@ +# Current docs for the syntax of this file are at: +# https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md + +name: $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.rr) + +queue: + name: Hosted Linux Preview + +trigger: + branches: + include: + - master + - 3.7 + - 3.6 + paths: + exclude: + - Doc/* + - Tools/* + +variables: + # Copy-pasted from linux-deps.yml until template support arrives + OPENSSL: 1.1.0g + OPENSSL_DIR: "$(build.sourcesDirectory)/multissl/openssl/$(OPENSSL)" + +steps: +- checkout: self + clean: true + fetchDepth: 5 + +#- template: linux-deps.yml + +# See https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted-templates.md +# For now, we copy/paste the steps +- script: echo "deb-src http://archive.ubuntu.com/ubuntu/ xenial main" > /etc/apt/sources.list.d/python.list && sudo apt-get update + displayName: 'Update apt-get lists' + +- script: echo ##vso[task.prependpath]$(OPENSSL_DIR) + displayName: 'Add $(OPENSSL_DIR) to PATH' +- script: > + sudo apt-get -yq install + build-essential + zlib1g-dev + libbz2-dev + liblzma-dev + libncurses5-dev + libreadline6-dev + libsqlite3-dev + libssl-dev + libgdbm-dev + tk-dev + lzma + lzma-dev + liblzma-dev + libffi-dev + uuid-dev + displayName: 'Install dependencies' +- script: python3 Tools/ssl/multissltests.py --steps=library --base-directory $(build.sourcesDirectory)/multissl --openssl $(OPENSSL) --system Linux + displayName: 'python multissltests.py' + + +- script: ./configure --with-pydebug + displayName: 'Configure CPython (debug)' + +- script: make -s -j4 + displayName: 'Build CPython' + +- script: ./python -m venv venv && ./venv/bin/python -m pip install -U coverage + displayName: 'Set up virtual environment' + +- script: ./venv/bin/python -m test.pythoninfo + displayName: 'Display build info' + +- script: ./venv/bin/python -m coverage run --pylib -m test --fail-env-changed -uall,-cpu -x test_multiprocessing_fork -x test_multiprocessing_forkserver -x test_multiprocessing_spawn -x test_concurrent_futures + displayName: 'Tests with coverage' + +- script: source ./venv/bin/activate && bash <(curl -s https://codecov.io/bash) + displayName: 'Publish code coverage results' diff --git a/.vsts/linux-deps.yml b/.vsts/linux-deps.yml new file mode 100644 index 000000000000..b6c8a3690ea1 --- /dev/null +++ b/.vsts/linux-deps.yml @@ -0,0 +1,36 @@ +# Note: this file is not currently used, but when template support comes to VSTS it +# will be referenced from the other scripts.. + +# Current docs for the syntax of this file are at: +# https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md + +parameters: + OPENSSL: 1.1.0g + OPENSSL_DIR: "$(build.sourcesDirectory)/multissl/openssl/$(OPENSSL)" + +steps: +- script: echo "deb-src http://archive.ubuntu.com/ubuntu/ xenial main" > /etc/apt/sources.list.d/python.list && sudo apt-get update + displayName: 'Update apt-get lists' + +- script: echo ##vso[task.prependpath]$(OPENSSL_DIR) + displayName: 'Add $(OPENSSL_DIR) to PATH' +- script: > + sudo apt-get -yq install + build-essential + zlib1g-dev + libbz2-dev + liblzma-dev + libncurses5-dev + libreadline6-dev + libsqlite3-dev + libssl-dev + libgdbm-dev + tk-dev + lzma + lzma-dev + liblzma-dev + libffi-dev + uuid-dev + displayName: 'Install dependencies' +- script: python3 Tools/ssl/multissltests.py --steps=library --base-directory $(build.sourcesDirectory)/multissl --openssl $(OPENSSL) --system Linux + displayName: 'python multissltests.py' diff --git a/.vsts/linux-pr.yml b/.vsts/linux-pr.yml new file mode 100644 index 000000000000..7f4d458f5a7c --- /dev/null +++ b/.vsts/linux-pr.yml @@ -0,0 +1,75 @@ +# Current docs for the syntax of this file are at: +# https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md + +name: $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.rr) + +queue: + name: Hosted Linux Preview + +trigger: + branches: + include: + - master + - 3.7 + - 3.6 + paths: + exclude: + - Doc/* + - Tools/* + +variables: + # Copy-pasted from linux-deps.yml until template support arrives + OPENSSL: 1.1.0g + OPENSSL_DIR: "$(build.sourcesDirectory)/multissl/openssl/$(OPENSSL)" + +steps: +- checkout: self + clean: true + fetchDepth: 5 + +#- template: linux-deps.yml + +# See https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted-templates.md +# For now, we copy/paste the steps +- script: echo "deb-src http://archive.ubuntu.com/ubuntu/ xenial main" > /etc/apt/sources.list.d/python.list && sudo apt-get update + displayName: 'Update apt-get lists' + +- script: echo ##vso[task.prependpath]$(OPENSSL_DIR) + displayName: 'Add $(OPENSSL_DIR) to PATH' +- script: > + sudo apt-get -yq install + build-essential + zlib1g-dev + libbz2-dev + liblzma-dev + libncurses5-dev + libreadline6-dev + libsqlite3-dev + libssl-dev + libgdbm-dev + tk-dev + lzma + lzma-dev + liblzma-dev + libffi-dev + uuid-dev + displayName: 'Install dependencies' +- script: python3 Tools/ssl/multissltests.py --steps=library --base-directory $(build.sourcesDirectory)/multissl --openssl $(OPENSSL) --system Linux + displayName: 'python multissltests.py' + + +- script: ./configure --with-pydebug + displayName: 'Configure CPython (debug)' + +- script: make -s -j4 + displayName: 'Build CPython' + +- script: make pythoninfo + displayName: 'Display build info' + +# Run patchcheck and fail if anything is discovered +- script: ./python Tools/scripts/patchcheck.py --travis true + displayName: 'Run patchcheck.py' + +- script: make buildbottest TESTOPTS="-j4 -uall,-cpu" + displayName: 'Tests' diff --git a/.vsts/macos-buildbot.yml b/.vsts/macos-buildbot.yml new file mode 100644 index 000000000000..8a4f6ba8cb8b --- /dev/null +++ b/.vsts/macos-buildbot.yml @@ -0,0 +1,37 @@ +# Current docs for the syntax of this file are at: +# https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md + +name: $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.rr) + +queue: + name: Hosted macOS Preview + +trigger: + branches: + include: + - master + - 3.7 + - 3.6 + paths: + exclude: + - Doc/* + - Tools/* + +#variables: + +steps: +- checkout: self + clean: true + fetchDepth: 5 + +- script: ./configure --with-pydebug --with-openssl=/usr/local/opt/openssl + displayName: 'Configure CPython (debug)' + +- script: make -s -j4 + displayName: 'Build CPython' + +- script: make pythoninfo + displayName: 'Display build info' + +- script: make buildbottest TESTOPTS="-j4 -uall,-cpu" + displayName: 'Tests' diff --git a/.vsts/macos-pr.yml b/.vsts/macos-pr.yml new file mode 100644 index 000000000000..8a4f6ba8cb8b --- /dev/null +++ b/.vsts/macos-pr.yml @@ -0,0 +1,37 @@ +# Current docs for the syntax of this file are at: +# https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md + +name: $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.rr) + +queue: + name: Hosted macOS Preview + +trigger: + branches: + include: + - master + - 3.7 + - 3.6 + paths: + exclude: + - Doc/* + - Tools/* + +#variables: + +steps: +- checkout: self + clean: true + fetchDepth: 5 + +- script: ./configure --with-pydebug --with-openssl=/usr/local/opt/openssl + displayName: 'Configure CPython (debug)' + +- script: make -s -j4 + displayName: 'Build CPython' + +- script: make pythoninfo + displayName: 'Display build info' + +- script: make buildbottest TESTOPTS="-j4 -uall,-cpu" + displayName: 'Tests' diff --git a/.vsts/windows-buildbot.yml b/.vsts/windows-buildbot.yml new file mode 100644 index 000000000000..5ec4522796ce --- /dev/null +++ b/.vsts/windows-buildbot.yml @@ -0,0 +1,49 @@ +# Current docs for the syntax of this file are at: +# https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md + +name: $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.rr) + +queue: + name: Hosted VS2017 + parallel: 2 + matrix: + amd64: + buildOpt: -p x64 + outDirSuffix: amd64 + win32: + buildOpt: + outDirSuffix: win32 + +trigger: + branches: + include: + - master + - 3.7 + - 3.6 + paths: + exclude: + - Doc/* + - Tools/* + +variables: + # Relocate build outputs outside of source directory to make cleaning faster + Py_IntDir: $(Build.BinariesDirectory)\obj + # UNDONE: Do not build to a different directory because of broken tests + Py_OutDir: $(Build.SourcesDirectory)\PCbuild + EXTERNAL_DIR: $(Build.BinariesDirectory)\externals + +steps: +- checkout: self + clean: true + fetchDepth: 5 + +- script: PCbuild\build.bat -e $(buildOpt) + displayName: 'Build CPython' + +- script: python.bat -m test.pythoninfo + displayName: 'Display build info' + +- script: PCbuild\rt.bat -q -uall -u-cpu -rwW --slowest --timeout=1200 -j0 + displayName: 'Tests' + env: + PREFIX: $(Py_OutDir)\$(outDirSuffix) diff --git a/.vsts/windows-pr.yml b/.vsts/windows-pr.yml new file mode 100644 index 000000000000..5ec4522796ce --- /dev/null +++ b/.vsts/windows-pr.yml @@ -0,0 +1,49 @@ +# Current docs for the syntax of this file are at: +# https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md + +name: $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.rr) + +queue: + name: Hosted VS2017 + parallel: 2 + matrix: + amd64: + buildOpt: -p x64 + outDirSuffix: amd64 + win32: + buildOpt: + outDirSuffix: win32 + +trigger: + branches: + include: + - master + - 3.7 + - 3.6 + paths: + exclude: + - Doc/* + - Tools/* + +variables: + # Relocate build outputs outside of source directory to make cleaning faster + Py_IntDir: $(Build.BinariesDirectory)\obj + # UNDONE: Do not build to a different directory because of broken tests + Py_OutDir: $(Build.SourcesDirectory)\PCbuild + EXTERNAL_DIR: $(Build.BinariesDirectory)\externals + +steps: +- checkout: self + clean: true + fetchDepth: 5 + +- script: PCbuild\build.bat -e $(buildOpt) + displayName: 'Build CPython' + +- script: python.bat -m test.pythoninfo + displayName: 'Display build info' + +- script: PCbuild\rt.bat -q -uall -u-cpu -rwW --slowest --timeout=1200 -j0 + displayName: 'Tests' + env: + PREFIX: $(Py_OutDir)\$(outDirSuffix) diff --git a/Doc/make.bat b/Doc/make.bat index 3f201de1db79..c69cfae31941 100644 --- a/Doc/make.bat +++ b/Doc/make.bat @@ -6,17 +6,20 @@ pushd %~dp0 set this=%~n0 call ..\PCbuild\find_python.bat %PYTHON% -if not defined SPHINXBUILD if defined PYTHON ( + +if not defined PYTHON set PYTHON=py + +if not defined SPHINXBUILD ( %PYTHON% -c "import sphinx" > nul 2> nul if errorlevel 1 ( echo Installing sphinx with %PYTHON% - %PYTHON% -m pip install sphinx + %PYTHON% -m pip install sphinx python-docs-theme if errorlevel 1 exit /B ) set SPHINXBUILD=%PYTHON% -c "import sphinx, sys; sys.argv[0] = 'sphinx-build'; sphinx.main()" ) -if not defined BLURB if defined PYTHON ( +if not defined BLURB ( %PYTHON% -c "import blurb" > nul 2> nul if errorlevel 1 ( echo Installing blurb with %PYTHON% @@ -26,7 +29,6 @@ if not defined BLURB if defined PYTHON ( set BLURB=%PYTHON% -m blurb ) -if not defined PYTHON set PYTHON=py if not defined SPHINXBUILD set SPHINXBUILD=sphinx-build if not defined BLURB set BLURB=blurb diff --git a/Lib/tempfile.py b/Lib/tempfile.py index e5b7a92fad7b..214322416963 100644 --- a/Lib/tempfile.py +++ b/Lib/tempfile.py @@ -169,7 +169,9 @@ def _candidate_tempdir_list(): # Failing that, try OS-specific locations. if _os.name == 'nt': - dirlist.extend([ r'c:\temp', r'c:\tmp', r'\temp', r'\tmp' ]) + dirlist.extend([ _os.path.expanduser(r'~\AppData\Local\Temp'), + _os.path.expandvars(r'%SYSTEMROOT%\Temp'), + r'c:\temp', r'c:\tmp', r'\temp', r'\tmp' ]) else: dirlist.extend([ '/tmp', '/var/tmp', '/usr/tmp' ]) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index f1c4c952eff3..a6fcb1bc1437 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -363,6 +363,20 @@ def _rmtree_inner(path): _force_run(fullname, os.unlink, fullname) _waitfor(_rmtree_inner, path, waitall=True) _waitfor(lambda p: _force_run(p, os.rmdir, p), path) + + def _longpath(path): + try: + import ctypes + except ImportError: + # No ctypes means we can't expands paths. + pass + else: + buffer = ctypes.create_unicode_buffer(len(path) * 2) + length = ctypes.windll.kernel32.GetLongPathNameW(path, buffer, + len(buffer)) + if length: + return buffer[:length] + return path else: _unlink = os.unlink _rmdir = os.rmdir @@ -389,6 +403,9 @@ def _rmtree_inner(path): _rmtree_inner(path) os.rmdir(path) + def _longpath(path): + return path + def unlink(filename): try: _unlink(filename) @@ -2381,13 +2398,15 @@ def can_xattr(): if not hasattr(os, "setxattr"): can = False else: - tmp_fp, tmp_name = tempfile.mkstemp() + tmp_dir = tempfile.mkdtemp() + tmp_fp, tmp_name = tempfile.mkstemp(dir=tmp_dir) try: with open(TESTFN, "wb") as fp: try: # TESTFN & tempfile may use different file systems with # different capabilities os.setxattr(tmp_fp, b"user.test", b"") + os.setxattr(tmp_name, b"trusted.foo", b"42") os.setxattr(fp.fileno(), b"user.test", b"") # Kernels < 2.6.39 don't respect setxattr flags. kernel_version = platform.release() @@ -2398,6 +2417,7 @@ def can_xattr(): finally: unlink(TESTFN) unlink(tmp_name) + rmdir(tmp_dir) _can_xattr = can return can diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index ab6560c70b90..72c63df91070 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -1848,10 +1848,22 @@ def run_loop(self, coro): def prepare(self): sock = self.make_socket() proto = self.MyProto(self.loop) - port = support.find_unused_port() + af = socket.AF_UNSPEC if support.IPV6_ENABLED else socket.AF_INET server = self.run_loop(self.loop.create_server( - lambda: proto, support.HOST, port)) - self.run_loop(self.loop.sock_connect(sock, (support.HOST, port))) + lambda: proto, support.HOST, 0, family=af)) + port = server.sockets[0].getsockname()[1] + + for _ in range(10): + try: + self.run_loop(self.loop.sock_connect(sock, (support.HOST, port))) + except OSError: + time.sleep(0.5) + continue + else: + break + else: + # One last try, so we get the exception + self.run_loop(self.loop.sock_connect(sock, (support.HOST, port))) def cleanup(): server.close() diff --git a/Lib/test/test_bdb.py b/Lib/test/test_bdb.py index bda74a2be775..616c3a864984 100644 --- a/Lib/test/test_bdb.py +++ b/Lib/test/test_bdb.py @@ -417,15 +417,17 @@ def __init__(self, test_case, skip=None): self.dry_run = test_case.dry_run self.tracer = Tracer(test_case.expect_set, skip=skip, dry_run=self.dry_run, test_case=test_case.id()) + self._original_tracer = None def __enter__(self): # test_pdb does not reset Breakpoint class attributes on exit :-( reset_Breakpoint() + self._original_tracer = sys.gettrace() return self.tracer def __exit__(self, type_=None, value=None, traceback=None): reset_Breakpoint() - sys.settrace(None) + sys.settrace(self._original_tracer) not_empty = '' if self.tracer.set_list: diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index d1a3fba2ded9..d95a831b7b62 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -1516,7 +1516,7 @@ def test_resolve_common(self): # resolves to 'dirB/..' first before resolving to parent of dirB. self._check_resolve_relative(p, P(BASE, 'foo', 'in', 'spam'), False) # Now create absolute symlinks - d = tempfile.mkdtemp(suffix='-dirD') + d = support._longpath(tempfile.mkdtemp(suffix='-dirD')) self.addCleanup(support.rmtree, d) os.symlink(os.path.join(d), join('dirA', 'linkX')) os.symlink(join('dirB'), os.path.join(d, 'linkY')) diff --git a/Lib/test/test_poplib.py b/Lib/test/test_poplib.py index bf568bd77bff..bbedbbdb10a1 100644 --- a/Lib/test/test_poplib.py +++ b/Lib/test/test_poplib.py @@ -179,7 +179,8 @@ def _do_tls_handshake(self): elif err.args[0] == ssl.SSL_ERROR_EOF: return self.handle_close() # TODO: SSLError does not expose alert information - elif "SSLV3_ALERT_BAD_CERTIFICATE" in err.args[1]: + elif ("SSLV3_ALERT_BAD_CERTIFICATE" in err.args[1] or + "SSLV3_ALERT_CERTIFICATE_UNKNOWN" in err.args[1]): return self.handle_close() raise except OSError as err: @@ -222,11 +223,12 @@ def start(self): def run(self): self.active = True self.__flag.set() - while self.active and asyncore.socket_map: - self.active_lock.acquire() - asyncore.loop(timeout=0.1, count=1) - self.active_lock.release() - asyncore.close_all(ignore_all=True) + try: + while self.active and asyncore.socket_map: + with self.active_lock: + asyncore.loop(timeout=0.1, count=1) + finally: + asyncore.close_all(ignore_all=True) def stop(self): assert self.active diff --git a/Lib/test/test_selectors.py b/Lib/test/test_selectors.py index 79ac25c12d4a..31611224dc71 100644 --- a/Lib/test/test_selectors.py +++ b/Lib/test/test_selectors.py @@ -481,7 +481,14 @@ def test_above_fd_setsize(self): self.skipTest("FD limit reached") raise - self.assertEqual(NUM_FDS // 2, len(s.select())) + try: + fds = s.select() + except OSError as e: + if e.errno == errno.EINVAL and sys.platform == 'darwin': + # unexplainable errors on macOS don't need to fail the test + self.skipTest("Invalid argument error calling poll()") + raise + self.assertEqual(NUM_FDS // 2, len(fds)) class DefaultSelectorTestCase(BaseSelectorTestCase): diff --git a/Misc/NEWS.d/next/Build/2018-05-15-12-44-50.bpo-33522.mJoNcA.rst b/Misc/NEWS.d/next/Build/2018-05-15-12-44-50.bpo-33522.mJoNcA.rst new file mode 100644 index 000000000000..f44862f0c454 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2018-05-15-12-44-50.bpo-33522.mJoNcA.rst @@ -0,0 +1,2 @@ +Enable CI builds on Visual Studio Team Services at +https://python.visualstudio.com/cpython diff --git a/Misc/NEWS.d/next/Library/2018-05-16-17-05-48.bpo-33548.xWslmx.rst b/Misc/NEWS.d/next/Library/2018-05-16-17-05-48.bpo-33548.xWslmx.rst new file mode 100644 index 000000000000..65585c152987 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-16-17-05-48.bpo-33548.xWslmx.rst @@ -0,0 +1 @@ +tempfile._candidate_tempdir_list should consider common TEMP locations diff --git a/PCbuild/rt.bat b/PCbuild/rt.bat index 575cdc858fda..212befc95b06 100644 --- a/PCbuild/rt.bat +++ b/PCbuild/rt.bat @@ -7,7 +7,7 @@ rem -q "quick" -- normally the tests are run twice, the first time rem after deleting all the .pyc files reachable from Lib/. rem -q runs the tests just once, and without deleting .pyc files. rem -x64 Run the 64-bit build of python (or python_d if -d was specified) -rem from the 'amd64' dir instead of the 32-bit build in this dir. +rem When omitted, uses %PREFIX% if set or the 32-bit build rem All leading instances of these switches are shifted off, and rem whatever remains (up to 9 arguments) is passed to regrtest.py. rem For example, @@ -28,20 +28,21 @@ rem rt -u "network,largefile" setlocal set pcbuild=%~dp0 -set prefix=%pcbuild%win32\ set suffix= set qmode= set dashO= set regrtestargs= +set exe= :CheckOpts if "%1"=="-O" (set dashO=-O) & shift & goto CheckOpts if "%1"=="-q" (set qmode=yes) & shift & goto CheckOpts if "%1"=="-d" (set suffix=_d) & shift & goto CheckOpts -if "%1"=="-x64" (set prefix=%pcbuild%amd64\) & shift & goto CheckOpts +if "%1"=="-x64" (set prefix=%pcbuild%amd64) & shift & goto CheckOpts if NOT "%1"=="" (set regrtestargs=%regrtestargs% %1) & shift & goto CheckOpts -set exe=%prefix%python%suffix%.exe +if not defined prefix set prefix=%pcbuild%win32 +set exe=%prefix%\python%suffix%.exe set cmd="%exe%" %dashO% -u -Wd -E -bb -m test %regrtestargs% if defined qmode goto Qmode @@ -49,7 +50,7 @@ echo Deleting .pyc files ... "%exe%" "%pcbuild%rmpyc.py" echo Cleaning _pth files ... -if exist %prefix%*._pth del %prefix%*._pth +if exist %prefix%\*._pth del %prefix%\*._pth echo on %cmd% diff --git a/Tools/ssl/multissltests.py b/Tools/ssl/multissltests.py index a51566c5069d..2efc4258de91 100755 --- a/Tools/ssl/multissltests.py +++ b/Tools/ssl/multissltests.py @@ -125,6 +125,11 @@ "all and runs the test suite." ) ) +parser.add_argument( + '--system', + default='', + help="Override the automatic system type detection." +) class AbstractBuilder(object): @@ -152,6 +157,7 @@ def __init__(self, version, args): # build directory (removed after install) self.build_dir = os.path.join( self.src_dir, self.build_template.format(version)) + self.system = args.system def __str__(self): return "<{0.__class__.__name__} for {0.version}>".format(self) @@ -255,9 +261,13 @@ def _build_src(self): log.info("Running build in {}".format(self.build_dir)) cwd = self.build_dir cmd = ["./config", "shared", "--prefix={}".format(self.install_dir)] - self._subprocess_call(cmd, cwd=cwd) + env = None + if self.system: + env = os.environ.copy() + env['SYSTEM'] = self.system + self._subprocess_call(cmd, cwd=cwd, env=env) # Old OpenSSL versions do not support parallel builds. - self._subprocess_call(["make", "-j1"], cwd=cwd) + self._subprocess_call(["make", "-j1"], cwd=cwd, env=env) def _make_install(self, remove=True): self._subprocess_call( From webhook-mailer at python.org Wed May 16 18:04:42 2018 From: webhook-mailer at python.org (=?utf-8?q?=C5=81ukasz?= Langa) Date: Wed, 16 May 2018 22:04:42 -0000 Subject: [Python-checkins] Fix ClassVar as string fails when getting type hints (GH-6824) (#6912) Message-ID: <mailman.98.1526508283.2757.python-checkins@python.org> https://github.com/python/cpython/commit/9c17cd3214987c35a60dd4076fc3530f2b79bf52 commit: 9c17cd3214987c35a60dd4076fc3530f2b79bf52 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: ?ukasz Langa <lukasz at langa.pl> date: 2018-05-16T18:04:39-04:00 summary: Fix ClassVar as string fails when getting type hints (GH-6824) (#6912) (cherry picked from commit 2d2d3b170bdebc085900bfa2a3bc81b5d132d0a8) Co-authored-by: Nina Zakharenko <nzakharenko at gmail.com> files: A Misc/NEWS.d/next/Library/2018-05-15-18-02-03.bpo-0.pj2Mbb.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 314716cd7de3..be768f12fb4c 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -1599,6 +1599,30 @@ class D(C): # verify that @no_type_check never affects bases self.assertEqual(get_type_hints(C.meth), {'x': int}) + def test_no_type_check_forward_ref_as_string(self): + class C: + foo: typing.ClassVar[int] = 7 + class D: + foo: ClassVar[int] = 7 + class E: + foo: 'typing.ClassVar[int]' = 7 + class F: + foo: 'ClassVar[int]' = 7 + + expected_result = {'foo': typing.ClassVar[int]} + for clazz in [C, D, E, F]: + self.assertEqual(get_type_hints(clazz), expected_result) + + def test_nested_classvar_fails_forward_ref_check(self): + class E: + foo: 'typing.ClassVar[typing.ClassVar[int]]' = 7 + class F: + foo: ClassVar['ClassVar[int]'] = 7 + + for clazz in [E, F]: + with self.assertRaises(TypeError): + get_type_hints(clazz) + def test_meta_no_type_check(self): @no_type_check_decorator diff --git a/Lib/typing.py b/Lib/typing.py index 8025dfd93262..b10615c07fbd 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -106,7 +106,7 @@ # legitimate imports of those modules. -def _type_check(arg, msg): +def _type_check(arg, msg, is_argument=False): """Check that the argument is a type, and return it (internal helper). As a special case, accept None and return type(None) instead. Also wrap strings @@ -118,12 +118,16 @@ def _type_check(arg, msg): We append the repr() of the actual value (truncated to 100 chars). """ + invalid_generic_forms = (Generic, _Protocol) + if not is_argument: + invalid_generic_forms = invalid_generic_forms + (ClassVar, ) + if arg is None: return type(None) if isinstance(arg, str): return ForwardRef(arg) if (isinstance(arg, _GenericAlias) and - arg.__origin__ in (Generic, _Protocol, ClassVar)): + arg.__origin__ in invalid_generic_forms): raise TypeError(f"{arg} is not valid as type argument") if (isinstance(arg, _SpecialForm) and arg is not Any or arg in (Generic, _Protocol)): @@ -464,9 +468,10 @@ class ForwardRef(_Final, _root=True): """Internal wrapper to hold a forward reference.""" __slots__ = ('__forward_arg__', '__forward_code__', - '__forward_evaluated__', '__forward_value__') + '__forward_evaluated__', '__forward_value__', + '__forward_is_argument__') - def __init__(self, arg): + def __init__(self, arg, is_argument=False): if not isinstance(arg, str): raise TypeError(f"Forward reference must be a string -- got {arg!r}") try: @@ -477,6 +482,7 @@ def __init__(self, arg): self.__forward_code__ = code self.__forward_evaluated__ = False self.__forward_value__ = None + self.__forward_is_argument__ = is_argument def _evaluate(self, globalns, localns): if not self.__forward_evaluated__ or localns is not globalns: @@ -488,7 +494,8 @@ def _evaluate(self, globalns, localns): localns = globalns self.__forward_value__ = _type_check( eval(self.__forward_code__, globalns, localns), - "Forward references must evaluate to types.") + "Forward references must evaluate to types.", + is_argument=self.__forward_is_argument__) self.__forward_evaluated__ = True return self.__forward_value__ @@ -998,7 +1005,7 @@ def get_type_hints(obj, globalns=None, localns=None): if value is None: value = type(None) if isinstance(value, str): - value = ForwardRef(value) + value = ForwardRef(value, is_argument=True) value = _eval_type(value, base_globals, localns) hints[name] = value return hints diff --git a/Misc/NEWS.d/next/Library/2018-05-15-18-02-03.bpo-0.pj2Mbb.rst b/Misc/NEWS.d/next/Library/2018-05-15-18-02-03.bpo-0.pj2Mbb.rst new file mode 100644 index 000000000000..ba8514cdd895 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-15-18-02-03.bpo-0.pj2Mbb.rst @@ -0,0 +1 @@ +Fix failure in `typing.get_type_hints()` when ClassVar was provided as a string forward reference. From lp_benchmark_robot at intel.com Wed May 16 21:17:44 2018 From: lp_benchmark_robot at intel.com (lp_benchmark_robot at intel.com) Date: Wed, 16 May 2018 18:17:44 -0700 Subject: [Python-checkins] [65 flat] Results for Python (master branch) 2018-05-16 Message-ID: <3b116a04-5fbd-4030-bab5-e2b7234fe02b@orsmsx101.amr.corp.intel.com> Results for project python/master, build date: 2018-05-16 03:03:19-07:00. - commit: f8e7549 - previous commit: 5401622 - revision date: 2018-05-16 05:14:53-04:00 - environment: Broadwell-EP - cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores, stepping 1, LLC 55 MB - mem: 128 GB - os: Ubuntu 16.04.2 LTS - kernel: 4.4.0-62-generic x86_64 GNU/Linux Baseline results were generated using release v3.6.0, with hash 5c4568a from 2016-12-22 23:38:47+00:00. +-----+------------------------+--------+------------+------------+------------+ | | |relative|change since|change since|current rev | | | benchmark|std_dev*| last run | baseline |run with PGO| +-----+------------------------+--------+------------+------------+------------+ | :-| | 2to3| 0.639% | +0.152% | +9.039% | +6.893% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method| 1.074% | +0.415% | +24.080% | +13.905% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_slots| 1.525% | -0.138% | +25.694% | +12.766% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_unknown| 1.056% | -0.289% | +22.466% | +13.628% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_simple| 3.993% | +1.146% | +11.732% | +12.181% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chameleon| 2.082% | -0.085% | +11.948% | +10.110% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chaos| 0.930% | -0.002% | +9.143% | +9.763% | +-----+------------------------+--------+------------+------------+------------+ | :-| | crypto_pyaes| 0.853% | -0.221% | +0.048% | +7.525% | +-----+------------------------+--------+------------+------------+------------+ | :-| | deltablue| 3.039% | +0.996% | +12.440% | +15.918% | +-----+------------------------+--------+------------+------------+------------+ | :-| | django_template| 1.722% | +1.638% | +21.862% | +12.906% | +-----+------------------------+--------+------------+------------+------------+ | :-| | dulwich_log| 0.974% | +0.517% | +6.070% | +6.743% | +-----+------------------------+--------+------------+------------+------------+ | :-| | fannkuch| 0.338% | +0.159% | +7.083% | +4.087% | +-----+------------------------+--------+------------+------------+------------+ | :-| | float| 1.320% | -0.195% | +2.236% | +7.917% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_text| 1.386% | -0.559% | +14.526% | +9.595% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_xml| 1.430% | +0.530% | +11.918% | +8.545% | +-----+------------------------+--------+------------+------------+------------+ | :-| | go| 5.799% | +0.691% | +5.503% | +10.649% | +-----+------------------------+--------+------------+------------+------------+ | :-| | hexiom| 0.622% | +0.134% | +12.140% | +11.519% | +-----+------------------------+--------+------------+------------+------------+ | :-| | html5lib| 2.756% | +0.381% | +11.796% | +9.805% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_dumps| 1.116% | +1.008% | +3.375% | +8.802% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_loads| 5.267% | +0.420% | -3.703% | +15.192% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_format| 1.466% | +0.756% | +17.870% | +12.101% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_silent| 3.920% | -0.882% | +47.851% | +14.162% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_simple| 1.506% | +0.519% | +12.963% | +11.849% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mako| 0.579% | -0.368% | +17.000% | +12.624% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mdp| 6.084% | +0.296% | +1.120% | +17.234% | +-----+------------------------+--------+------------+------------+------------+ | :-| | meteor_contest| 0.652% | +0.484% | +4.465% | +6.529% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nbody| 0.575% | -0.188% | +0.171% | -0.390% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nqueens| 0.633% | -0.506% | +5.670% | +8.249% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pathlib| 1.298% | +2.195% | +0.791% | +11.390% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle| 1.485% | +0.012% | -0.920% | +22.875% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_dict| 0.475% | -0.039% | +7.493% | +18.306% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_list| 0.834% | +0.878% | +7.567% | +17.806% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_pure_python| 4.736% | +0.777% | +11.861% | +9.619% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pidigits| 0.116% | -0.087% | +0.049% | +10.580% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup| 0.121% | +0.283% | +18.924% | +5.005% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup_no_site| 0.091% | +0.277% | +5.948% | +5.263% | +-----+------------------------+--------+------------+------------+------------+ | :-| | raytrace| 1.110% | +0.501% | +10.671% | +13.623% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_compile| 4.348% | -0.506% | +6.609% | +8.190% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_dna| 0.454% | +0.081% | -2.042% | +11.819% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_effbot| 3.202% | -2.445% | -5.174% | +5.716% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_v8| 1.146% | -0.413% | +3.975% | +5.799% | +-----+------------------------+--------+------------+------------+------------+ | :-| | richards| 1.382% | -0.327% | +9.280% | +16.207% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_fft| 0.563% | +0.711% | -1.362% | +3.578% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_lu| 6.021% | -0.040% | +21.760% | +12.710% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_monte_carlo| 2.031% | +0.825% | +5.567% | +4.803% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sor| 1.593% | +0.244% | +15.205% | +8.353% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sparse_mat_mult| 2.979% | -1.025% | -3.893% | -0.489% | +-----+------------------------+--------+------------+------------+------------+ | :-| | spectral_norm| 0.415% | -1.408% | +4.889% | +4.715% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_declarative| 1.303% | +0.398% | +6.787% | +6.790% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_imperative| 3.483% | -0.024% | +7.721% | +4.806% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlite_synth| 4.812% | +0.372% | -0.538% | +10.505% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_expand| 2.860% | -0.149% | +17.762% | +6.625% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_integrate| 1.436% | -0.024% | +18.417% | +5.803% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_str| 3.754% | +0.861% | +19.668% | +6.148% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_sum| 6.136% | +0.906% | +16.361% | +9.647% | +-----+------------------------+--------+------------+------------+------------+ | :-| | telco| 3.710% | +0.793% | +20.127% | +9.430% | +-----+------------------------+--------+------------+------------+------------+ | :-| | tornado_http| 1.086% | -0.207% | +7.099% | +6.519% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpack_sequence| 6.625% | -1.485% | +1.497% | +3.447% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle| 4.836% | +1.954% | +9.971% | +20.462% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_list| 1.462% | +0.358% | -3.347% | +14.400% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_pure_python| 2.267% | +0.675% | +7.741% | +7.606% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_generate| 1.066% | -0.054% | +2.494% | +12.883% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_iterparse| 1.802% | -0.604% | +4.121% | +7.656% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_parse| 2.974% | -0.032% | -6.767% | +11.222% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_process| 1.057% | -0.483% | +4.598% | +11.219% | +-----+------------------------+--------+------------+------------+------------+ * Relative Standard Deviation (Standard Deviation/Average) If this is not displayed properly please visit our results page here: http://languagesperformance.intel.com/65-flat-results-for-python-master-branch-2018-05-16 Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. From webhook-mailer at python.org Wed May 16 22:07:24 2018 From: webhook-mailer at python.org (INADA Naoki) Date: Thu, 17 May 2018 02:07:24 -0000 Subject: [Python-checkins] Replace _PyGC_REFS macros with higher level macros (GH-6852) Message-ID: <mailman.100.1526522845.2757.python-checkins@python.org> https://github.com/python/cpython/commit/d852142cd728f45372ba6137bd87e29ba7b5b4d2 commit: d852142cd728f45372ba6137bd87e29ba7b5b4d2 branch: master author: INADA Naoki <methane at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-17T11:07:21+09:00 summary: Replace _PyGC_REFS macros with higher level macros (GH-6852) Only gcmodule.c uses _PyGC_REFS* macros now. This makes easy to read GC code. files: M Modules/_testcapimodule.c M Objects/object.c diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 0e48463976e4..3086aab4063d 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -3215,8 +3215,7 @@ slot_tp_del(PyObject *self) _Py_NewReference(self); self->ob_refcnt = refcnt; } - assert(!PyType_IS_GC(Py_TYPE(self)) || - _Py_AS_GC(self)->gc.gc_refs != _PyGC_REFS_UNTRACKED); + assert(!PyType_IS_GC(Py_TYPE(self)) || _PyObject_GC_IS_TRACKED(self)); /* If Py_REF_DEBUG, _Py_NewReference bumped _Py_RefTotal, so * we need to undo that. */ _Py_DEC_REFTOTAL; diff --git a/Objects/object.c b/Objects/object.c index 6532c3b287e7..3eb4810bd9ac 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -316,9 +316,7 @@ PyObject_CallFinalizerFromDealloc(PyObject *self) _Py_NewReference(self); self->ob_refcnt = refcnt; - if (PyType_IS_GC(Py_TYPE(self))) { - assert(_PyGC_REFS(self) != _PyGC_REFS_UNTRACKED); - } + assert(!PyType_IS_GC(Py_TYPE(self)) || _PyObject_GC_IS_TRACKED(self)); /* If Py_REF_DEBUG, _Py_NewReference bumped _Py_RefTotal, so * we need to undo that. */ _Py_DEC_REFTOTAL; @@ -2095,7 +2093,7 @@ void _PyTrash_deposit_object(PyObject *op) { assert(PyObject_IS_GC(op)); - assert(_PyGC_REFS(op) == _PyGC_REFS_UNTRACKED); + assert(!_PyObject_GC_IS_TRACKED(op)); assert(op->ob_refcnt == 0); _Py_AS_GC(op)->gc.gc_prev = (PyGC_Head *)_PyRuntime.gc.trash_delete_later; _PyRuntime.gc.trash_delete_later = op; @@ -2107,7 +2105,7 @@ _PyTrash_thread_deposit_object(PyObject *op) { PyThreadState *tstate = PyThreadState_GET(); assert(PyObject_IS_GC(op)); - assert(_PyGC_REFS(op) == _PyGC_REFS_UNTRACKED); + assert(!_PyObject_GC_IS_TRACKED(op)); assert(op->ob_refcnt == 0); _Py_AS_GC(op)->gc.gc_prev = (PyGC_Head *) tstate->trash_delete_later; tstate->trash_delete_later = op; From webhook-mailer at python.org Wed May 16 23:17:54 2018 From: webhook-mailer at python.org (=?utf-8?q?=C5=81ukasz?= Langa) Date: Thu, 17 May 2018 03:17:54 -0000 Subject: [Python-checkins] bpo-33475: Fix and improve converting annotations to strings. (GH-6774) Message-ID: <mailman.101.1526527076.2757.python-checkins@python.org> https://github.com/python/cpython/commit/64fddc423fcbe90b8088446c63385ec0aaf3077c commit: 64fddc423fcbe90b8088446c63385ec0aaf3077c branch: master author: Serhiy Storchaka <storchaka at gmail.com> committer: ?ukasz Langa <lukasz at langa.pl> date: 2018-05-16T23:17:48-04:00 summary: bpo-33475: Fix and improve converting annotations to strings. (GH-6774) files: A Misc/NEWS.d/next/Core and Builtins/2018-05-13-01-26-18.bpo-33475.rI0y1U.rst M Include/ast.h M Lib/test/test_future.py M Python/ast_unparse.c M Python/compile.c diff --git a/Include/ast.h b/Include/ast.h index 639c4f82325a..5bc2b05b3e94 100644 --- a/Include/ast.h +++ b/Include/ast.h @@ -19,9 +19,7 @@ PyAPI_FUNC(mod_ty) PyAST_FromNodeObject( #ifndef Py_LIMITED_API /* _PyAST_ExprAsUnicode is defined in ast_unparse.c */ -PyAPI_FUNC(PyObject *) _PyAST_ExprAsUnicode( - expr_ty e, - int omit_parens); +PyAPI_FUNC(PyObject *) _PyAST_ExprAsUnicode(expr_ty); #endif /* !Py_LIMITED_API */ diff --git a/Lib/test/test_future.py b/Lib/test/test_future.py index 29c4632e7e50..61cd63479d85 100644 --- a/Lib/test/test_future.py +++ b/Lib/test/test_future.py @@ -157,55 +157,76 @@ def test_annotations(self): eq('True or False or None') eq('True and False') eq('True and False and None') - eq('(Name1 and Name2) or Name3') - eq('Name1 or (Name2 and Name3)') - eq('(Name1 and Name2) or (Name3 and Name4)') - eq('Name1 or (Name2 and Name3) or Name4') + eq('Name1 and Name2 or Name3') + eq('Name1 and (Name2 or Name3)') + eq('Name1 or Name2 and Name3') + eq('(Name1 or Name2) and Name3') + eq('Name1 and Name2 or Name3 and Name4') + eq('Name1 or Name2 and Name3 or Name4') + eq('a + b + (c + d)') + eq('a * b * (c * d)') + eq('(a ** b) ** c ** d') eq('v1 << 2') eq('1 >> v2') - eq(r'1 % finished') - eq('((1 + v2) - (v3 * 4)) ^ (((5 ** v6) / 7) // 8)') + eq('1 % finished') + eq('1 + v2 - v3 * 4 ^ 5 ** v6 / 7 // 8') eq('not great') + eq('not not great') eq('~great') eq('+value') + eq('++value') eq('-1') - eq('(~int) and (not ((v1 ^ (123 + v2)) | True))') + eq('~int and not v1 ^ 123 + v2 | True') + eq('a + (not b)') eq('lambda arg: None') eq('lambda a=True: a') eq('lambda a, b, c=True: a') - eq("lambda a, b, c=True, *, d=(1 << v2), e='str': a") - eq("lambda a, b, c=True, *vararg, d=(v1 << 2), e='str', **kwargs: a + b") + eq("lambda a, b, c=True, *, d=1 << v2, e='str': a") + eq("lambda a, b, c=True, *vararg, d=v1 << 2, e='str', **kwargs: a + b") + eq('lambda x: lambda y: x + y') eq('1 if True else 2') - eq('(str or None) if True else (str or bytes or None)') - eq('(str or None) if (1 if True else 2) else (str or bytes or None)') - eq("{'2.7': dead, '3.7': (long_live or die_hard)}") - eq("{'2.7': dead, '3.7': (long_live or die_hard), **{'3.6': verygood}}") + eq('str or None if int or True else str or bytes or None') + eq('str or None if (1 if True else 2) else str or bytes or None') + eq("0 if not x else 1 if x > 0 else -1") + eq("(1 if x > 0 else -1) if x else 0") + eq("{'2.7': dead, '3.7': long_live or die_hard}") + eq("{'2.7': dead, '3.7': long_live or die_hard, **{'3.6': verygood}}") eq("{**a, **b, **c}") - eq("{'2.7', '3.6', '3.7', '3.8', '3.9', ('4.0' if gilectomy else '3.10')}") - eq("({'a': 'b'}, (True or False), (+value), 'string', b'bytes') or None") + eq("{'2.7', '3.6', '3.7', '3.8', '3.9', '4.0' if gilectomy else '3.10'}") + eq("{*a, *b, *c}") + eq("({'a': 'b'}, True or False, +value, 'string', b'bytes') or None") eq("()") - eq("(1,)") - eq("(1, 2)") - eq("(1, 2, 3)") + eq("(a,)") + eq("(a, b)") + eq("(a, b, c)") + eq("(*a, *b, *c)") eq("[]") - eq("[1, 2, 3, 4, 5, 6, 7, 8, 9, (10 or A), (11 or B), (12 or C)]") + eq("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10 or A, 11 or B, 12 or C]") + eq("[*a, *b, *c]") eq("{i for i in (1, 2, 3)}") - eq("{(i ** 2) for i in (1, 2, 3)}") - eq("{(i ** 2) for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))}") - eq("{((i ** 2) + j) for i in (1, 2, 3) for j in (1, 2, 3)}") + eq("{i ** 2 for i in (1, 2, 3)}") + eq("{i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))}") + eq("{i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3)}") eq("[i for i in (1, 2, 3)]") - eq("[(i ** 2) for i in (1, 2, 3)]") - eq("[(i ** 2) for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))]") - eq("[((i ** 2) + j) for i in (1, 2, 3) for j in (1, 2, 3)]") - eq(r"{i: 0 for i in (1, 2, 3)}") + eq("[i ** 2 for i in (1, 2, 3)]") + eq("[i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))]") + eq("[i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3)]") + eq("(i for i in (1, 2, 3))") + eq("(i ** 2 for i in (1, 2, 3))") + eq("(i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c')))") + eq("(i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3))") + eq("{i: 0 for i in (1, 2, 3)}") eq("{i: j for i, j in ((1, 'a'), (2, 'b'), (3, 'c'))}") + eq("[(x, y) for x, y in (a, b)]") + eq("[(x,) for x, in (a,)]") eq("Python3 > Python2 > COBOL") eq("Life is Life") eq("call()") eq("call(arg)") eq("call(kwarg='hey')") eq("call(arg, kwarg='hey')") - eq("call(arg, another, kwarg='hey', **kwargs)") + eq("call(arg, *args, another, kwarg='hey')") + eq("call(arg, another, kwarg='hey', **kwargs, kwarg2='ho')") eq("lukasz.langa.pl") eq("call.me(maybe)") eq("1 .real") @@ -213,6 +234,7 @@ def test_annotations(self): eq("....__class__") eq("list[str]") eq("dict[str, int]") + eq("set[str,]") eq("tuple[str, ...]") eq("tuple[str, int, float, dict[str, int]]") eq("slice[0]") @@ -222,49 +244,28 @@ def test_annotations(self): eq("slice[:-1]") eq("slice[1:]") eq("slice[::-1]") - eq('(str or None) if (sys.version_info[0] > (3,)) else (str or bytes or None)') + eq("slice[()]") + eq("slice[a, b:c, d:e:f]") + eq("slice[(x for x in a)]") + eq('str or None if sys.version_info[0] > (3,) else str or bytes or None') eq("f'f-string without formatted values is just a string'") eq("f'{{NOT a formatted value}}'") eq("f'some f-string with {a} {few():.2f} {formatted.values!r}'") eq('''f"{f'{nested} inner'} outer"''') eq("f'space between opening braces: { {a for a in (1, 2, 3)}}'") - - def test_annotations_inexact(self): - """Source formatting is not always preserved - - This is due to reconstruction from AST. We *need to* put the parens - in nested expressions because we don't know if the source code - had them in the first place or not. - """ - eq = partial(self.assertAnnotationEqual, drop_parens=True) - eq('Name1 and Name2 or Name3') - eq('Name1 or Name2 and Name3') - eq('Name1 and Name2 or Name3 and Name4') - eq('Name1 or Name2 and Name3 or Name4') - eq('1 + v2 - v3 * 4 ^ v5 ** 6 / 7 // 8') - eq('~int and not v1 ^ 123 + v2 | True') - eq('str or None if True else str or bytes or None') - eq("{'2.7': dead, '3.7': long_live or die_hard}") - eq("{'2.7', '3.6', '3.7', '3.8', '3.9', '4.0' if gilectomy else '3.10'}") - eq("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10 or A, 11 or B, 12 or C]") - # Consequently, we always drop unnecessary parens if they were given in - # the outer scope: - some_name = self.getActual("(SomeName)") - self.assertEqual(some_name, 'SomeName') - # Interestingly, in the case of tuples (and generator expressions) the - # parens are *required* by the Python syntax in the annotation context. - # But there's no point storing that detail in __annotations__ so we're - # fine with the parens-less form. - eq = partial(self.assertAnnotationEqual, is_tuple=True) - eq("(Good, Bad, Ugly)") - eq("(i for i in (1, 2, 3))") - eq("((i ** 2) for i in (1, 2, 3))") - eq("((i ** 2) for i, _ in ((1, 'a'), (2, 'b'), (3, 'c')))") - eq("(((i ** 2) + j) for i in (1, 2, 3) for j in (1, 2, 3))") - eq("(*starred)") + eq("f'{(lambda x: x)}'") + eq("f'{(None if a else lambda x: x)}'") eq('(yield from outside_of_generator)') eq('(yield)') - eq('(await some.complicated[0].call(with_args=(True or (1 is not 1))))') + eq('(yield a + b)') + eq('await some.complicated[0].call(with_args=True or 1 is not 1)') + eq('[x for x in (a if b else c)]') + eq('[x for x in a if (b if c else d)]') + eq('f(x for x in a)') + eq('f(1, (x for x in a))') + eq('f((x for x in a), 2)') + eq('(((a)))', 'a') + eq('(((a, b)))', '(a, b)') if __name__ == "__main__": diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-05-13-01-26-18.bpo-33475.rI0y1U.rst b/Misc/NEWS.d/next/Core and Builtins/2018-05-13-01-26-18.bpo-33475.rI0y1U.rst new file mode 100644 index 000000000000..cd714b9d1e89 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-05-13-01-26-18.bpo-33475.rI0y1U.rst @@ -0,0 +1,2 @@ +Fixed miscellaneous bugs in converting annotations to strings and optimized +parentheses in the string representation. diff --git a/Python/ast_unparse.c b/Python/ast_unparse.c index 1345271e599b..725ce31fe3c0 100644 --- a/Python/ast_unparse.c +++ b/Python/ast_unparse.c @@ -9,13 +9,15 @@ static PyObject *_str_dbl_close_br; /* Forward declarations for recursion via helper functions. */ static PyObject * -expr_as_unicode(expr_ty e, bool omit_parens); +expr_as_unicode(expr_ty e, int level); static int -append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens); +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); +static int +append_ast_slice(_PyUnicodeWriter *writer, slice_ty slice); static int append_charp(_PyUnicodeWriter *writer, const char *charp) @@ -23,6 +25,39 @@ append_charp(_PyUnicodeWriter *writer, const char *charp) return _PyUnicodeWriter_WriteASCIIString(writer, charp, -1); } +#define APPEND_STR_FINISH(str) do { \ + return append_charp(writer, (str)); \ + } while (0) + +#define APPEND_STR(str) do { \ + if (-1 == append_charp(writer, (str))) { \ + return -1; \ + } \ + } while (0) + +#define APPEND_STR_IF(cond, str) do { \ + if ((cond) && -1 == append_charp(writer, (str))) { \ + return -1; \ + } \ + } while (0) + +#define APPEND_STR_IF_NOT_FIRST(str) do { \ + APPEND_STR_IF(!first, (str)); \ + first = false; \ + } while (0) + +#define APPEND_EXPR(expr, pr) do { \ + if (-1 == append_ast_expr(writer, (expr), (pr))) { \ + return -1; \ + } \ + } while (0) + +#define APPEND(type, value) do { \ + if (-1 == append_ast_ ## type(writer, (value))) { \ + return -1; \ + } \ + } while (0) + static int append_repr(_PyUnicodeWriter *writer, PyObject *obj) { @@ -37,111 +72,108 @@ append_repr(_PyUnicodeWriter *writer, PyObject *obj) return ret; } -static int -append_ast_boolop(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) +/* Priority levels */ + +enum { + PR_TUPLE, + PR_TEST, /* 'if'-'else', 'lambda' */ + PR_OR, /* 'or' */ + PR_AND, /* 'and' */ + PR_NOT, /* 'not' */ + PR_CMP, /* '<', '>', '==', '>=', '<=', '!=', + 'in', 'not in', 'is', 'is not' */ + PR_EXPR, + PR_BOR = PR_EXPR, /* '|' */ + PR_BXOR, /* '^' */ + PR_BAND, /* '&' */ + PR_SHIFT, /* '<<', '>>' */ + PR_ARITH, /* '+', '-' */ + PR_TERM, /* '*', '@', '/', '%', '//' */ + PR_FACTOR, /* unary '+', '-', '~' */ + PR_POWER, /* '**' */ + PR_AWAIT, /* 'await' */ + PR_ATOM, +}; + +static int +append_ast_boolop(_PyUnicodeWriter *writer, expr_ty e, int level) { Py_ssize_t i, value_count; asdl_seq *values; + const char *op = (e->v.BoolOp.op == And) ? " and " : " or "; + int pr = (e->v.BoolOp.op == And) ? PR_AND : PR_OR; - if (!omit_parens && -1 == append_charp(writer, "(")) { - return -1; - } + APPEND_STR_IF(level > pr, "("); values = e->v.BoolOp.values; - value_count = asdl_seq_LEN(values) - 1; - assert(value_count >= 0); + value_count = asdl_seq_LEN(values); - if (-1 == append_ast_expr(writer, - (expr_ty)asdl_seq_GET(values, 0), - false)) { - return -1; - } - - const char *op = (e->v.BoolOp.op == And) ? " and " : " or "; - for (i = 1; i <= value_count; ++i) { - if (-1 == append_charp(writer, op)) { - return -1; - } - - if (-1 == append_ast_expr(writer, - (expr_ty)asdl_seq_GET(values, i), - false)) { - return -1; - } + for (i = 0; i < value_count; ++i) { + APPEND_STR_IF(i > 0, op); + APPEND_EXPR((expr_ty)asdl_seq_GET(values, i), pr + 1); } - return omit_parens ? 0 : append_charp(writer, ")"); + APPEND_STR_IF(level > pr, ")"); + return 0; } static int -append_ast_binop(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) +append_ast_binop(_PyUnicodeWriter *writer, expr_ty e, int level) { const char *op; - - if (!omit_parens && -1 == append_charp(writer, "(")) { - return -1; - } - - if (-1 == append_ast_expr(writer, e->v.BinOp.left, false)) { - return -1; - } - - switch(e->v.BinOp.op) { - case Add: op = " + "; break; - case Sub: op = " - "; break; - case Mult: op = " * "; break; - case MatMult: op = " @ "; break; - case Div: op = " / "; break; - case Mod: op = " % "; break; - case LShift: op = " << "; break; - case RShift: op = " >> "; break; - case BitOr: op = " | "; break; - case BitXor: op = " ^ "; break; - case BitAnd: op = " & "; break; - case FloorDiv: op = " // "; break; - case Pow: op = " ** "; break; + int pr; + bool rassoc = false; /* is right-associative? */ + + switch (e->v.BinOp.op) { + case Add: op = " + "; pr = PR_ARITH; break; + case Sub: op = " - "; pr = PR_ARITH; break; + case Mult: op = " * "; pr = PR_TERM; break; + case MatMult: op = " @ "; pr = PR_TERM; break; + case Div: op = " / "; pr = PR_TERM; break; + case Mod: op = " % "; pr = PR_TERM; break; + case LShift: op = " << "; pr = PR_SHIFT; break; + case RShift: op = " >> "; pr = PR_SHIFT; break; + case BitOr: op = " | "; pr = PR_BOR; break; + case BitXor: op = " ^ "; pr = PR_BXOR; break; + case BitAnd: op = " & "; pr = PR_BAND; break; + case FloorDiv: op = " // "; pr = PR_TERM; break; + case Pow: op = " ** "; pr = PR_POWER; rassoc = true; break; default: - Py_UNREACHABLE(); - } - - if (-1 == append_charp(writer, op)) { - return -1; - } - - if (-1 == append_ast_expr(writer, e->v.BinOp.right, false)) { + PyErr_SetString(PyExc_SystemError, + "unknown binary operator"); return -1; } - return omit_parens ? 0 : append_charp(writer, ")"); + APPEND_STR_IF(level > pr, "("); + APPEND_EXPR(e->v.BinOp.left, pr + rassoc); + APPEND_STR(op); + APPEND_EXPR(e->v.BinOp.right, pr + !rassoc); + APPEND_STR_IF(level > pr, ")"); + return 0; } static int -append_ast_unaryop(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) +append_ast_unaryop(_PyUnicodeWriter *writer, expr_ty e, int level) { const char *op; + int pr; - if (!omit_parens && -1 == append_charp(writer, "(")) { - return -1; - } - - switch(e->v.UnaryOp.op) { - case Invert: op = "~"; break; - case Not: op = "not "; break; - case UAdd: op = "+"; break; - case USub: op = "-"; break; + switch (e->v.UnaryOp.op) { + case Invert: op = "~"; pr = PR_FACTOR; break; + case Not: op = "not "; pr = PR_NOT; break; + case UAdd: op = "+"; pr = PR_FACTOR; break; + case USub: op = "-"; pr = PR_FACTOR; break; default: - Py_UNREACHABLE(); - } - - if (-1 == append_charp(writer, op)) { - return -1; - } - - if (-1 == append_ast_expr(writer, e->v.UnaryOp.operand, false)) { + PyErr_SetString(PyExc_SystemError, + "unknown unary operator"); return -1; } - return omit_parens ? 0 : append_charp(writer, ")"); + APPEND_STR_IF(level > pr, "("); + APPEND_STR(op); + APPEND_EXPR(e->v.UnaryOp.operand, pr); + APPEND_STR_IF(level > pr, ")"); + return 0; } static int @@ -151,12 +183,8 @@ append_ast_arg(_PyUnicodeWriter *writer, arg_ty arg) return -1; } if (arg->annotation) { - if (-1 == append_charp(writer, ": ")) { - return -1; - } - if (-1 == append_ast_expr(writer, arg->annotation, true)) { - return -1; - } + APPEND_STR(": "); + APPEND_EXPR(arg->annotation, PR_TEST); } return 0; } @@ -166,8 +194,6 @@ append_ast_args(_PyUnicodeWriter *writer, arguments_ty args) { bool first; Py_ssize_t i, di, arg_count, default_count; - arg_ty arg; - expr_ty default_; first = true; @@ -175,47 +201,22 @@ append_ast_args(_PyUnicodeWriter *writer, arguments_ty args) arg_count = asdl_seq_LEN(args->args); default_count = asdl_seq_LEN(args->defaults); for (i = 0; i < arg_count; i++) { - if (first) { - first = false; - } - else if (-1 == append_charp(writer, ", ")) { - return -1; - } - - arg = (arg_ty)asdl_seq_GET(args->args, i); - if (-1 == append_ast_arg(writer, arg)) { - return -1; - } + APPEND_STR_IF_NOT_FIRST(", "); + APPEND(arg, (arg_ty)asdl_seq_GET(args->args, i)); di = i - arg_count + default_count; if (di >= 0) { - if (-1 == append_charp(writer, "=")) { - return -1; - } - default_ = (expr_ty)asdl_seq_GET(args->defaults, di); - if (-1 == append_ast_expr(writer, default_, false)) { - return -1; - } + APPEND_STR("="); + APPEND_EXPR((expr_ty)asdl_seq_GET(args->defaults, di), PR_TEST); } } /* vararg, or bare '*' if no varargs but keyword-only arguments present */ if (args->vararg || args->kwonlyargs) { - if (first) { - first = false; - } - else if (-1 == append_charp(writer, ", ")) { - return -1; - } - - if (-1 == append_charp(writer, "*")) { - return -1; - } - + APPEND_STR_IF_NOT_FIRST(", "); + APPEND_STR("*"); if (args->vararg) { - if (-1 == append_ast_arg(writer, args->vararg)) { - return -1; - } + APPEND(arg, args->vararg); } } @@ -223,223 +224,127 @@ append_ast_args(_PyUnicodeWriter *writer, arguments_ty args) arg_count = asdl_seq_LEN(args->kwonlyargs); default_count = asdl_seq_LEN(args->kw_defaults); for (i = 0; i < arg_count; i++) { - if (first) { - first = false; - } - else if (-1 == append_charp(writer, ", ")) { - return -1; - } - - arg = (arg_ty)asdl_seq_GET(args->kwonlyargs, i); - if (-1 == append_ast_arg(writer, arg)) { - return -1; - } + APPEND_STR_IF_NOT_FIRST(", "); + APPEND(arg, (arg_ty)asdl_seq_GET(args->kwonlyargs, i)); di = i - arg_count + default_count; if (di >= 0) { - if (-1 == append_charp(writer, "=")) { - return -1; - } - default_ = (expr_ty)asdl_seq_GET(args->kw_defaults, di); - if (-1 == append_ast_expr(writer, default_, false)) { - return -1; - } + APPEND_STR("="); + APPEND_EXPR((expr_ty)asdl_seq_GET(args->kw_defaults, di), PR_TEST); } } /* **kwargs */ if (args->kwarg) { - if (first) { - first = false; - } - else if (-1 == append_charp(writer, ", ")) { - return -1; - } - - if (-1 == append_charp(writer, "**")) { - return -1; - } - - if (-1 == append_ast_arg(writer, args->kwarg)) { - return -1; - } + APPEND_STR_IF_NOT_FIRST(", "); + APPEND_STR("**"); + APPEND(arg, args->kwarg); } return 0; } static int -append_ast_lambda(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) +append_ast_lambda(_PyUnicodeWriter *writer, expr_ty e, int level) { - if (!omit_parens && -1 == append_charp(writer, "(")) { - return -1; - } - - if (-1 == append_charp(writer, "lambda ")) { - return -1; - } - - if (-1 == append_ast_args(writer, e->v.Lambda.args)) { - return -1; - } - - if (-1 == append_charp(writer, ": ")) { - return -1; - } - - if (-1 == append_ast_expr(writer, e->v.Lambda.body, true)) { - return -1; - } - - return omit_parens ? 0 : append_charp(writer, ")"); + APPEND_STR_IF(level > PR_TEST, "("); + APPEND_STR("lambda "); + APPEND(args, e->v.Lambda.args); + APPEND_STR(": "); + APPEND_EXPR(e->v.Lambda.body, PR_TEST); + APPEND_STR_IF(level > PR_TEST, ")"); + return 0; } static int -append_ast_ifexp(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) +append_ast_ifexp(_PyUnicodeWriter *writer, expr_ty e, int level) { - if (!omit_parens && -1 == append_charp(writer, "(")) { - return -1; - } - - if (-1 == append_ast_expr(writer, e->v.IfExp.body, false)) { - return -1; - } - - if (-1 == append_charp(writer, " if ")) { - return -1; - } - - if (-1 == append_ast_expr(writer, e->v.IfExp.test, false)) { - return -1; - } - - if (-1 == append_charp(writer, " else ")) { - return -1; - } - - if (-1 == append_ast_expr(writer, e->v.IfExp.orelse, false)) { - return -1; - } - - return omit_parens ? 0 : append_charp(writer, ")"); + APPEND_STR_IF(level > PR_TEST, "("); + APPEND_EXPR(e->v.IfExp.body, PR_TEST + 1); + APPEND_STR(" if "); + APPEND_EXPR(e->v.IfExp.test, PR_TEST + 1); + APPEND_STR(" else "); + APPEND_EXPR(e->v.IfExp.orelse, PR_TEST); + APPEND_STR_IF(level > PR_TEST, ")"); + return 0; } static int append_ast_dict(_PyUnicodeWriter *writer, expr_ty e) { Py_ssize_t i, value_count; - expr_ty key_node, value_node; - - if (-1 == append_charp(writer, "{")) { - return -1; - } + expr_ty key_node; + APPEND_STR("{"); value_count = asdl_seq_LEN(e->v.Dict.values); for (i = 0; i < value_count; i++) { - if (i > 0 && -1 == append_charp(writer, ", ")) { - return -1; - } + APPEND_STR_IF(i > 0, ", "); key_node = (expr_ty)asdl_seq_GET(e->v.Dict.keys, i); if (key_node != NULL) { - if (-1 == append_ast_expr(writer, key_node, false)) { - return -1; - } - - if (-1 == append_charp(writer, ": ")) { - return -1; - } - } - else if (-1 == append_charp(writer, "**")) { - return -1; + APPEND_EXPR(key_node, PR_TEST); + APPEND_STR(": "); + APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Dict.values, i), PR_TEST); } - - value_node = (expr_ty)asdl_seq_GET(e->v.Dict.values, i); - if (-1 == append_ast_expr(writer, value_node, false)) { - return -1; + else { + APPEND_STR("**"); + APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Dict.values, i), PR_EXPR); } } - return append_charp(writer, "}"); + APPEND_STR_FINISH("}"); } static int append_ast_set(_PyUnicodeWriter *writer, expr_ty e) { Py_ssize_t i, elem_count; - expr_ty elem_node; - - if (-1 == append_charp(writer, "{")) { - return -1; - } + APPEND_STR("{"); elem_count = asdl_seq_LEN(e->v.Set.elts); for (i = 0; i < elem_count; i++) { - if (i > 0 && -1 == append_charp(writer, ", ")) { - return -1; - } - - elem_node = (expr_ty)asdl_seq_GET(e->v.Set.elts, i); - if (-1 == append_ast_expr(writer, elem_node, false)) { - return -1; - } + APPEND_STR_IF(i > 0, ", "); + APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Set.elts, i), PR_TEST); } - return append_charp(writer, "}"); + APPEND_STR_FINISH("}"); } static int append_ast_list(_PyUnicodeWriter *writer, expr_ty e) { Py_ssize_t i, elem_count; - expr_ty elem_node; - - if (-1 == append_charp(writer, "[")) { - return -1; - } + APPEND_STR("["); elem_count = asdl_seq_LEN(e->v.List.elts); for (i = 0; i < elem_count; i++) { - if (i > 0 && -1 == append_charp(writer, ", ")) { - return -1; - } - elem_node = (expr_ty)asdl_seq_GET(e->v.List.elts, i); - if (-1 == append_ast_expr(writer, elem_node, false)) { - return -1; - } + APPEND_STR_IF(i > 0, ", "); + APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.List.elts, i), PR_TEST); } - return append_charp(writer, "]"); + APPEND_STR_FINISH("]"); } static int -append_ast_tuple(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) +append_ast_tuple(_PyUnicodeWriter *writer, expr_ty e, int level) { Py_ssize_t i, elem_count; - expr_ty elem_node; elem_count = asdl_seq_LEN(e->v.Tuple.elts); - if (!omit_parens || elem_count < 2) { - if (-1 == append_charp(writer, "(")) { - return -1; - } + if (elem_count == 0) { + APPEND_STR_FINISH("()"); } - for (i = 0; i < elem_count; i++) { - if ((i > 0 || elem_count == 1) && -1 == append_charp(writer, ", ")) { - return -1; - } - elem_node = (expr_ty)asdl_seq_GET(e->v.Tuple.elts, i); - if (-1 == append_ast_expr(writer, elem_node, false)) { - return -1; - } - } + APPEND_STR_IF(level > PR_TUPLE, "("); - if (!omit_parens || elem_count < 2) { - return append_charp(writer, ")"); + for (i = 0; i < elem_count; i++) { + APPEND_STR_IF(i > 0, ", "); + APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Tuple.elts, i), PR_TEST); } + APPEND_STR_IF(elem_count == 1, ","); + APPEND_STR_IF(level > PR_TUPLE, ")"); return 0; } @@ -448,33 +353,15 @@ append_ast_comprehension(_PyUnicodeWriter *writer, comprehension_ty gen) { Py_ssize_t i, if_count; - if (-1 == append_charp(writer, gen->is_async ? " async for " : " for ")) { - return -1; - } - - if (-1 == append_ast_expr(writer, gen->target, true)) { - return -1; - } - - if (-1 == append_charp(writer, " in ")) { - return -1; - } - - if (-1 == append_ast_expr(writer, gen->iter, false)) { - return -1; - } + APPEND_STR(gen->is_async ? " async for " : " for "); + APPEND_EXPR(gen->target, PR_TUPLE); + APPEND_STR(" in "); + APPEND_EXPR(gen->iter, PR_TEST + 1); if_count = asdl_seq_LEN(gen->ifs); for (i = 0; i < if_count; i++) { - if (-1 == append_charp(writer, " if ")) { - return -1; - } - - if (-1 == append_ast_expr(writer, - (expr_ty)asdl_seq_GET(gen->ifs, i), - false)) { - return -1; - } + APPEND_STR(" if "); + APPEND_EXPR((expr_ty)asdl_seq_GET(gen->ifs, i), PR_TEST + 1); } return 0; } @@ -483,110 +370,62 @@ static int append_ast_comprehensions(_PyUnicodeWriter *writer, asdl_seq *comprehensions) { Py_ssize_t i, gen_count; - comprehension_ty comp_node; gen_count = asdl_seq_LEN(comprehensions); for (i = 0; i < gen_count; i++) { - comp_node = (comprehension_ty)asdl_seq_GET(comprehensions, i); - if (-1 == append_ast_comprehension(writer, comp_node)) { - return -1; - } + APPEND(comprehension, (comprehension_ty)asdl_seq_GET(comprehensions, i)); } return 0; } static int -append_ast_genexp(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) +append_ast_genexp(_PyUnicodeWriter *writer, expr_ty e) { - if (!omit_parens && -1 == append_charp(writer, "(")) { - return -1; - } - - if (-1 == append_ast_expr(writer, e->v.GeneratorExp.elt, false)) { - return -1; - } - - if (-1 == append_ast_comprehensions(writer, e->v.GeneratorExp.generators)) { - return -1; - } - - return omit_parens ? 0 : append_charp(writer, ")"); + APPEND_STR("("); + APPEND_EXPR(e->v.GeneratorExp.elt, PR_TEST); + APPEND(comprehensions, e->v.GeneratorExp.generators); + APPEND_STR_FINISH(")"); } static int append_ast_listcomp(_PyUnicodeWriter *writer, expr_ty e) { - if (-1 == append_charp(writer, "[")) { - return -1; - } - - if (-1 == append_ast_expr(writer, e->v.ListComp.elt, false)) { - return -1; - } - - if (-1 == append_ast_comprehensions(writer, e->v.ListComp.generators)) { - return -1; - } - - return append_charp(writer, "]"); + APPEND_STR("["); + APPEND_EXPR(e->v.ListComp.elt, PR_TEST); + APPEND(comprehensions, e->v.ListComp.generators); + APPEND_STR_FINISH("]"); } static int append_ast_setcomp(_PyUnicodeWriter *writer, expr_ty e) { - if (-1 == append_charp(writer, "{")) { - return -1; - } - - if (-1 == append_ast_expr(writer, e->v.SetComp.elt, false)) { - return -1; - } - - if (-1 == append_ast_comprehensions(writer, e->v.SetComp.generators)) { - return -1; - } - - return append_charp(writer, "}"); + APPEND_STR("{"); + APPEND_EXPR(e->v.SetComp.elt, PR_TEST); + APPEND(comprehensions, e->v.SetComp.generators); + APPEND_STR_FINISH("}"); } static int append_ast_dictcomp(_PyUnicodeWriter *writer, expr_ty e) { - if (-1 == append_charp(writer, "{")) { - return -1; - } - - if (-1 == append_ast_expr(writer, e->v.DictComp.key, false)) { - return -1; - } - - if (-1 == append_charp(writer, ": ")) { - return -1; - } - - if (-1 == append_ast_expr(writer, e->v.DictComp.value, false)) { - return -1; - } - - if (-1 == append_ast_comprehensions(writer, e->v.DictComp.generators)) { - return -1; - } - - return append_charp(writer, "}"); + APPEND_STR("{"); + APPEND_EXPR(e->v.DictComp.key, PR_TEST); + APPEND_STR(": "); + APPEND_EXPR(e->v.DictComp.value, PR_TEST); + APPEND(comprehensions, e->v.DictComp.generators); + APPEND_STR_FINISH("}"); } static int -append_ast_compare(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) +append_ast_compare(_PyUnicodeWriter *writer, expr_ty e, int level) { const char *op; Py_ssize_t i, comparator_count; asdl_seq *comparators; asdl_int_seq *ops; - if (!omit_parens && -1 == append_charp(writer, "(")) { - return -1; - } + APPEND_STR_IF(level > PR_CMP, "("); comparators = e->v.Compare.comparators; ops = e->v.Compare.ops; @@ -594,9 +433,7 @@ append_ast_compare(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) assert(comparator_count > 0); assert(comparator_count == asdl_seq_LEN(ops)); - if (-1 == append_ast_expr(writer, e->v.Compare.left, false)) { - return -1; - } + APPEND_EXPR(e->v.Compare.left, PR_CMP + 1); for (i = 0; i < comparator_count; i++) { switch ((cmpop_ty)asdl_seq_GET(ops, i)) { @@ -636,39 +473,30 @@ append_ast_compare(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) return -1; } - if (-1 == append_charp(writer, op)) { - return -1; - } - - if (-1 == append_ast_expr(writer, - (expr_ty)asdl_seq_GET(comparators, i), - false)) { - return -1; - } + APPEND_STR(op); + APPEND_EXPR((expr_ty)asdl_seq_GET(comparators, i), PR_CMP + 1); } - return omit_parens ? 0 : append_charp(writer, ")"); + APPEND_STR_IF(level > PR_CMP, ")"); + return 0; } static int append_ast_keyword(_PyUnicodeWriter *writer, keyword_ty kw) { if (kw->arg == NULL) { - if (-1 == append_charp(writer, "**")) { - return -1; - } + APPEND_STR("**"); } else { if (-1 == _PyUnicodeWriter_WriteStr(writer, kw->arg)) { return -1; } - if (-1 == append_charp(writer, "=")) { - return -1; - } + APPEND_STR("="); } - return append_ast_expr(writer, kw->value, false); + APPEND_EXPR(kw->value, PR_TEST); + return 0; } static int @@ -677,48 +505,33 @@ append_ast_call(_PyUnicodeWriter *writer, expr_ty e) bool first; Py_ssize_t i, arg_count, kw_count; expr_ty expr; - keyword_ty kw; - if (-1 == append_ast_expr(writer, e->v.Call.func, false)) { - return -1; - } + APPEND_EXPR(e->v.Call.func, PR_ATOM); - if (-1 == append_charp(writer, "(")) { - return -1; + arg_count = asdl_seq_LEN(e->v.Call.args); + kw_count = asdl_seq_LEN(e->v.Call.keywords); + if (arg_count == 1 && kw_count == 0) { + expr = (expr_ty)asdl_seq_GET(e->v.Call.args, 0); + if (expr->kind == GeneratorExp_kind) { + /* Special case: a single generator expression. */ + return append_ast_genexp(writer, expr); + } } + APPEND_STR("("); + first = true; - arg_count = asdl_seq_LEN(e->v.Call.args); for (i = 0; i < arg_count; i++) { - if (first) { - first = false; - } - else if (-1 == append_charp(writer, ", ")) { - return -1; - } - - expr = (expr_ty)asdl_seq_GET(e->v.Call.args, i); - if (-1 == append_ast_expr(writer, expr, false)) { - return -1; - } + APPEND_STR_IF_NOT_FIRST(", "); + APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Call.args, i), PR_TEST); } - kw_count = asdl_seq_LEN(e->v.Call.keywords); for (i = 0; i < kw_count; i++) { - if (first) { - first = false; - } - else if (-1 == append_charp(writer, ", ")) { - return -1; - } - - kw = (keyword_ty)asdl_seq_GET(e->v.Call.keywords, i); - if (-1 == append_ast_keyword(writer, kw)) { - return -1; - } + APPEND_STR_IF_NOT_FIRST(", "); + APPEND(keyword, (keyword_ty)asdl_seq_GET(e->v.Call.keywords, i)); } - return append_charp(writer, ")"); + APPEND_STR_FINISH(")"); } static PyObject * @@ -778,9 +591,8 @@ build_fstring_body(asdl_seq *values, bool is_format_spec) body_writer.min_length = 256; body_writer.overallocate = 1; - value_count = asdl_seq_LEN(values) - 1; - assert(value_count >= 0); - for (i = 0; i <= value_count; ++i) { + value_count = asdl_seq_LEN(values); + for (i = 0; i < value_count; ++i) { if (-1 == append_fstring_element(&body_writer, (expr_ty)asdl_seq_GET(values, i), is_format_spec @@ -819,9 +631,11 @@ append_joinedstr(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec) static int append_formattedvalue(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec) { - char *conversion; - char *outer_brace = "{"; - PyObject *temp_fv_str = expr_as_unicode(e->v.FormattedValue.value, true); + const char *conversion; + const char *outer_brace = "{"; + /* Grammar allows PR_TUPLE, but use >PR_TEST for adding parenthesis + around a lambda with ':' */ + PyObject *temp_fv_str = expr_as_unicode(e->v.FormattedValue.value, PR_TEST + 1); if (!temp_fv_str) { return -1; } @@ -842,13 +656,13 @@ append_formattedvalue(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec) if (e->v.FormattedValue.conversion > 0) { switch (e->v.FormattedValue.conversion) { - case 97: + case 'a': conversion = "!a"; break; - case 114: + case 'r': conversion = "!r"; break; - case 115: + case 's': conversion = "!s"; break; default: @@ -856,9 +670,7 @@ append_formattedvalue(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec) "unknown f-value conversion kind"); return -1; } - if (-1 == append_charp(writer, conversion)) { - return -1; - } + APPEND_STR(conversion); } if (e->v.FormattedValue.format_spec) { if (-1 == _PyUnicodeWriter_WriteASCIIString(writer, ":", 1) || @@ -870,16 +682,15 @@ append_formattedvalue(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec) return -1; } } - return append_charp(writer, "}"); + + APPEND_STR_FINISH("}"); } static int append_ast_attribute(_PyUnicodeWriter *writer, expr_ty e) { const char *period; - if (-1 == append_ast_expr(writer, e->v.Attribute.value, false)) { - return -1; - } + APPEND_EXPR(e->v.Attribute.value, PR_ATOM); /* Special case: integers require a space for attribute access to be unambiguous. Floats and complex numbers don't but work with it, too. */ @@ -891,9 +702,7 @@ append_ast_attribute(_PyUnicodeWriter *writer, expr_ty e) else { period = "."; } - if (-1 == append_charp(writer, period)) { - return -1; - } + APPEND_STR(period); return _PyUnicodeWriter_WriteStr(writer, e->v.Attribute.attr); } @@ -902,28 +711,18 @@ static int append_ast_simple_slice(_PyUnicodeWriter *writer, slice_ty slice) { if (slice->v.Slice.lower) { - if (-1 == append_ast_expr(writer, slice->v.Slice.lower, false)) { - return -1; - } + APPEND_EXPR(slice->v.Slice.lower, PR_TEST); } - if (-1 == append_charp(writer, ":")) { - return -1; - } + APPEND_STR(":"); if (slice->v.Slice.upper) { - if (-1 == append_ast_expr(writer, slice->v.Slice.upper, false)) { - return -1; - } + APPEND_EXPR(slice->v.Slice.upper, PR_TEST); } if (slice->v.Slice.step) { - if (-1 == append_charp(writer, ":")) { - return -1; - } - if (-1 == append_ast_expr(writer, slice->v.Slice.step, false)) { - return -1; - } + APPEND_STR(":"); + APPEND_EXPR(slice->v.Slice.step, PR_TEST); } return 0; } @@ -934,28 +733,23 @@ append_ast_ext_slice(_PyUnicodeWriter *writer, slice_ty slice) Py_ssize_t i, dims_count; dims_count = asdl_seq_LEN(slice->v.ExtSlice.dims); for (i = 0; i < dims_count; i++) { - if (i > 0 && -1 == append_charp(writer, ", ")) { - return -1; - } - if (-1 == append_ast_expr(writer, - (expr_ty)asdl_seq_GET(slice->v.ExtSlice.dims, i), - false)) { - return -1; - } + APPEND_STR_IF(i > 0, ", "); + APPEND(slice, (slice_ty)asdl_seq_GET(slice->v.ExtSlice.dims, i)); } return 0; } static int -append_ast_slice(_PyUnicodeWriter *writer, slice_ty slice, bool omit_parens) +append_ast_slice(_PyUnicodeWriter *writer, slice_ty slice) { - switch(slice->kind) { + switch (slice->kind) { case Slice_kind: return append_ast_simple_slice(writer, slice); case ExtSlice_kind: return append_ast_ext_slice(writer, slice); case Index_kind: - return append_ast_expr(writer, slice->v.Index.value, omit_parens); + APPEND_EXPR(slice->v.Index.value, PR_TUPLE); + return 0; default: PyErr_SetString(PyExc_SystemError, "unexpected slice kind"); @@ -966,109 +760,70 @@ append_ast_slice(_PyUnicodeWriter *writer, slice_ty slice, bool omit_parens) static int append_ast_subscript(_PyUnicodeWriter *writer, expr_ty e) { - if (-1 == append_ast_expr(writer, e->v.Subscript.value, false)) { - return -1; - } - - if (-1 == append_charp(writer, "[")) { - return -1; - } - - if (-1 == append_ast_slice(writer, e->v.Subscript.slice, true)) { - return -1; - } - - return append_charp(writer, "]"); + APPEND_EXPR(e->v.Subscript.value, PR_ATOM); + APPEND_STR("["); + APPEND(slice, e->v.Subscript.slice); + APPEND_STR_FINISH("]"); } static int append_ast_starred(_PyUnicodeWriter *writer, expr_ty e) { - if (-1 == append_charp(writer, "*")) { - return -1; - } - - return append_ast_expr(writer, e->v.Starred.value, false); + APPEND_STR("*"); + APPEND_EXPR(e->v.Starred.value, PR_EXPR); + return 0; } static int -append_ast_yield(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) +append_ast_yield(_PyUnicodeWriter *writer, expr_ty e) { - if (!omit_parens && -1 == append_charp(writer, "(")) { - return -1; - } - - if (-1 == append_charp(writer, e->v.Yield.value ? "yield " : "yield")) { - return -1; + if (!e->v.Yield.value) { + APPEND_STR_FINISH("(yield)"); } - if (e->v.Yield.value) { - if (-1 == append_ast_expr(writer, e->v.Yield.value, false)) { - return -1; - } - } - return omit_parens ? 0 : append_charp(writer, ")"); + APPEND_STR("(yield "); + APPEND_EXPR(e->v.Yield.value, PR_TEST); + APPEND_STR_FINISH(")"); } static int -append_ast_yield_from(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) +append_ast_yield_from(_PyUnicodeWriter *writer, expr_ty e) { - if (!omit_parens && -1 == append_charp(writer, "(")) { - return -1; - } - - if (-1 == append_charp(writer, - e->v.YieldFrom.value ? "yield from " : "yield from")) { - return -1; - } - - if (e->v.YieldFrom.value) { - if (-1 == append_ast_expr(writer, e->v.YieldFrom.value, false)) { - return -1; - } - } - return omit_parens ? 0 : append_charp(writer, ")"); + APPEND_STR("(yield from "); + APPEND_EXPR(e->v.YieldFrom.value, PR_TEST); + APPEND_STR_FINISH(")"); } static int -append_ast_await(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) +append_ast_await(_PyUnicodeWriter *writer, expr_ty e, int level) { - if (!omit_parens && -1 == append_charp(writer, "(")) { - return -1; - } - - if (-1 == append_charp(writer, e->v.Await.value ? "await " : "await")) { - return -1; - } - - if (e->v.Await.value) { - if (-1 == append_ast_expr(writer, e->v.Await.value, false)) { - return -1; - } - } - return omit_parens ? 0 : append_charp(writer, ")"); + APPEND_STR_IF(level > PR_AWAIT, "("); + APPEND_STR("await "); + APPEND_EXPR(e->v.Await.value, PR_ATOM); + APPEND_STR_IF(level > PR_AWAIT, ")"); + return 0; } static int -append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) +append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, int level) { switch (e->kind) { case BoolOp_kind: - return append_ast_boolop(writer, e, omit_parens); + return append_ast_boolop(writer, e, level); case BinOp_kind: - return append_ast_binop(writer, e, omit_parens); + return append_ast_binop(writer, e, level); case UnaryOp_kind: - return append_ast_unaryop(writer, e, omit_parens); + return append_ast_unaryop(writer, e, level); case Lambda_kind: - return append_ast_lambda(writer, e, omit_parens); + return append_ast_lambda(writer, e, level); case IfExp_kind: - return append_ast_ifexp(writer, e, omit_parens); + return append_ast_ifexp(writer, e, level); case Dict_kind: return append_ast_dict(writer, e); case Set_kind: return append_ast_set(writer, e); case GeneratorExp_kind: - return append_ast_genexp(writer, e, omit_parens); + return append_ast_genexp(writer, e); case ListComp_kind: return append_ast_listcomp(writer, e); case SetComp_kind: @@ -1076,13 +831,13 @@ append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) case DictComp_kind: return append_ast_dictcomp(writer, e); case Yield_kind: - return append_ast_yield(writer, e, omit_parens); + return append_ast_yield(writer, e); case YieldFrom_kind: - return append_ast_yield_from(writer, e, omit_parens); + return append_ast_yield_from(writer, e); case Await_kind: - return append_ast_await(writer, e, omit_parens); + return append_ast_await(writer, e, level); case Compare_kind: - return append_ast_compare(writer, e, omit_parens); + return append_ast_compare(writer, e, level); case Call_kind: return append_ast_call(writer, e); case Constant_kind: @@ -1098,7 +853,7 @@ append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) case Bytes_kind: return append_repr(writer, e->v.Bytes.s); case Ellipsis_kind: - return append_charp(writer, "..."); + APPEND_STR_FINISH("..."); case NameConstant_kind: return append_repr(writer, e->v.NameConstant.value); /* The following exprs can be assignment targets. */ @@ -1110,11 +865,10 @@ append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) return append_ast_starred(writer, e); case Name_kind: return _PyUnicodeWriter_WriteStr(writer, e->v.Name.id); - /* child nodes of List and Tuple will have expr_context set */ case List_kind: return append_ast_list(writer, e); case Tuple_kind: - return append_ast_tuple(writer, e, omit_parens); + return append_ast_tuple(writer, e, level); default: PyErr_SetString(PyExc_SystemError, "unknown expression kind"); @@ -1145,14 +899,14 @@ maybe_init_static_strings(void) } static PyObject * -expr_as_unicode(expr_ty e, bool omit_parens) +expr_as_unicode(expr_ty e, int level) { _PyUnicodeWriter writer; _PyUnicodeWriter_Init(&writer); writer.min_length = 256; writer.overallocate = 1; if (-1 == maybe_init_static_strings() || - -1 == append_ast_expr(&writer, e, omit_parens)) + -1 == append_ast_expr(&writer, e, level)) { _PyUnicodeWriter_Dealloc(&writer); return NULL; @@ -1161,7 +915,7 @@ expr_as_unicode(expr_ty e, bool omit_parens) } PyObject * -_PyAST_ExprAsUnicode(expr_ty e, bool omit_parens) +_PyAST_ExprAsUnicode(expr_ty e) { - return expr_as_unicode(e, omit_parens); + return expr_as_unicode(e, PR_TEST); } diff --git a/Python/compile.c b/Python/compile.c index 7960f09319e7..c3397f0c455d 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1822,7 +1822,7 @@ compiler_visit_kwonlydefaults(struct compiler *c, asdl_seq *kwonlyargs, static int compiler_visit_annexpr(struct compiler *c, expr_ty annotation) { - ADDOP_LOAD_CONST_NEW(c, _PyAST_ExprAsUnicode(annotation, 1)); + ADDOP_LOAD_CONST_NEW(c, _PyAST_ExprAsUnicode(annotation)); return 1; } From webhook-mailer at python.org Thu May 17 02:45:13 2018 From: webhook-mailer at python.org (Ned Deily) Date: Thu, 17 May 2018 06:45:13 -0000 Subject: [Python-checkins] bpo-13631: Fix the order of initialization for readline libedit on macOS. (GH-6915) Message-ID: <mailman.102.1526539516.2757.python-checkins@python.org> https://github.com/python/cpython/commit/c2f082e9d164acfa8f96de9526f0f47ae92c426a commit: c2f082e9d164acfa8f96de9526f0f47ae92c426a branch: master author: Zvezdan Petkovic <zpetkovic at acm.org> committer: Ned Deily <nad at python.org> date: 2018-05-17T02:45:10-04:00 summary: bpo-13631: Fix the order of initialization for readline libedit on macOS. (GH-6915) The editline emulation needs to be initialized *after* the name is defined. This fixes the long open issue. files: A Misc/NEWS.d/next/macOS/2018-05-16-13-25-58.bpo-13631.UIjDyY.rst M Doc/library/readline.rst M Doc/tools/susp-ignored.csv M Misc/ACKS M Modules/readline.c diff --git a/Doc/library/readline.rst b/Doc/library/readline.rst index 837816e952ad..16c28cf7d02f 100644 --- a/Doc/library/readline.rst +++ b/Doc/library/readline.rst @@ -17,11 +17,18 @@ made using this module affect the behaviour of both the interpreter's interactive prompt and the prompts offered by the built-in :func:`input` function. +Readline keybindings may be configured via an initialization file, typically +``.inputrc`` in your home directory. See `Readline Init File +<https://cnswww.cns.cwru.edu/php/chet/readline/rluserman.html#SEC9>`_ +in the GNU Readline manual for information about the format and +allowable constructs of that file, and the capabilities of the +Readline library in general. + .. note:: The underlying Readline library API may be implemented by the ``libedit`` library instead of GNU readline. - On MacOS X the :mod:`readline` module detects which library is being used + On macOS the :mod:`readline` module detects which library is being used at run time. The configuration file for ``libedit`` is different from that @@ -29,12 +36,13 @@ function. you can check for the text "libedit" in :const:`readline.__doc__` to differentiate between GNU readline and libedit. -Readline keybindings may be configured via an initialization file, typically -``.inputrc`` in your home directory. See `Readline Init File -<https://cnswww.cns.cwru.edu/php/chet/readline/rluserman.html#SEC9>`_ -in the GNU Readline manual for information about the format and -allowable constructs of that file, and the capabilities of the -Readline library in general. + If you use *editline*/``libedit`` readline emulation on macOS, the + initialization file located in your home directory is named + ``.editrc``. For example, the following content in ``~/.editrc`` will + turn ON *vi* keybindings and TAB completion:: + + python:bind -v + python:bind ^I rl_complete Init file diff --git a/Doc/tools/susp-ignored.csv b/Doc/tools/susp-ignored.csv index cfdd5266c51c..33cd48f3d81e 100644 --- a/Doc/tools/susp-ignored.csv +++ b/Doc/tools/susp-ignored.csv @@ -187,6 +187,8 @@ library/profile,,:lineno,filename:lineno(function) library/pyexpat,,:elem1,<py:elem1 /> library/pyexpat,,:py,"xmlns:py = ""http://www.python.org/ns/"">" library/random,,:len,new_diff = mean(combined[:len(drug)]) - mean(combined[len(drug):]) +library/readline,,:bind,"python:bind -v" +library/readline,,:bind,"python:bind ^I rl_complete" library/smtplib,,:port,method must support that as well as a regular host:port library/socket,,::,'5aef:2b::8' library/socket,,:can,"return (can_id, can_dlc, data[:can_dlc])" diff --git a/Misc/ACKS b/Misc/ACKS index 5c05ee7d5aa1..b1f1e8a4b8de 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1229,6 +1229,7 @@ Gabriel de Perthuis Tim Peters Benjamin Peterson Joe Peterson +Zvezdan Petkovic Ulrich Petri Chris Petrilli Roumen Petrov diff --git a/Misc/NEWS.d/next/macOS/2018-05-16-13-25-58.bpo-13631.UIjDyY.rst b/Misc/NEWS.d/next/macOS/2018-05-16-13-25-58.bpo-13631.UIjDyY.rst new file mode 100644 index 000000000000..d9d505e937a8 --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2018-05-16-13-25-58.bpo-13631.UIjDyY.rst @@ -0,0 +1,2 @@ +The .editrc file in user's home directory is now processed correctly during +the readline initialization through editline emulation on macOS. diff --git a/Modules/readline.c b/Modules/readline.c index 811fca8cd92a..7756e6b2bc75 100644 --- a/Modules/readline.c +++ b/Modules/readline.c @@ -1078,6 +1078,9 @@ setup_readline(readlinestate *mod_state) Py_FatalError("not enough memory to save locale"); #endif + /* The name must be defined before initialization */ + rl_readline_name = "python"; + #ifdef __APPLE__ /* the libedit readline emulation resets key bindings etc * when calling rl_initialize. So call it upfront @@ -1099,7 +1102,6 @@ setup_readline(readlinestate *mod_state) using_history(); - rl_readline_name = "python"; /* Force rebind of TAB to insert-tab */ rl_bind_key('\t', rl_insert); /* Bind both ESC-TAB and ESC-ESC to the completion function */ From webhook-mailer at python.org Thu May 17 03:27:36 2018 From: webhook-mailer at python.org (Ned Deily) Date: Thu, 17 May 2018 07:27:36 -0000 Subject: [Python-checkins] bpo-13631: Fix the order of initialization for readline libedit on macOS. (GH-6915) (GH-6928) Message-ID: <mailman.103.1526542057.2757.python-checkins@python.org> https://github.com/python/cpython/commit/d504108a88bd14a560dec875df682f4e581490e5 commit: d504108a88bd14a560dec875df682f4e581490e5 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Ned Deily <nad at python.org> date: 2018-05-17T03:27:33-04:00 summary: bpo-13631: Fix the order of initialization for readline libedit on macOS. (GH-6915) (GH-6928) The editline emulation needs to be initialized *after* the name is defined. This fixes the long open issue. (cherry picked from commit c2f082e9d164acfa8f96de9526f0f47ae92c426a) Co-authored-by: Zvezdan Petkovic <zpetkovic at acm.org> files: A Misc/NEWS.d/next/macOS/2018-05-16-13-25-58.bpo-13631.UIjDyY.rst M Doc/library/readline.rst M Doc/tools/susp-ignored.csv M Misc/ACKS M Modules/readline.c diff --git a/Doc/library/readline.rst b/Doc/library/readline.rst index 837816e952ad..16c28cf7d02f 100644 --- a/Doc/library/readline.rst +++ b/Doc/library/readline.rst @@ -17,11 +17,18 @@ made using this module affect the behaviour of both the interpreter's interactive prompt and the prompts offered by the built-in :func:`input` function. +Readline keybindings may be configured via an initialization file, typically +``.inputrc`` in your home directory. See `Readline Init File +<https://cnswww.cns.cwru.edu/php/chet/readline/rluserman.html#SEC9>`_ +in the GNU Readline manual for information about the format and +allowable constructs of that file, and the capabilities of the +Readline library in general. + .. note:: The underlying Readline library API may be implemented by the ``libedit`` library instead of GNU readline. - On MacOS X the :mod:`readline` module detects which library is being used + On macOS the :mod:`readline` module detects which library is being used at run time. The configuration file for ``libedit`` is different from that @@ -29,12 +36,13 @@ function. you can check for the text "libedit" in :const:`readline.__doc__` to differentiate between GNU readline and libedit. -Readline keybindings may be configured via an initialization file, typically -``.inputrc`` in your home directory. See `Readline Init File -<https://cnswww.cns.cwru.edu/php/chet/readline/rluserman.html#SEC9>`_ -in the GNU Readline manual for information about the format and -allowable constructs of that file, and the capabilities of the -Readline library in general. + If you use *editline*/``libedit`` readline emulation on macOS, the + initialization file located in your home directory is named + ``.editrc``. For example, the following content in ``~/.editrc`` will + turn ON *vi* keybindings and TAB completion:: + + python:bind -v + python:bind ^I rl_complete Init file diff --git a/Doc/tools/susp-ignored.csv b/Doc/tools/susp-ignored.csv index cfdd5266c51c..33cd48f3d81e 100644 --- a/Doc/tools/susp-ignored.csv +++ b/Doc/tools/susp-ignored.csv @@ -187,6 +187,8 @@ library/profile,,:lineno,filename:lineno(function) library/pyexpat,,:elem1,<py:elem1 /> library/pyexpat,,:py,"xmlns:py = ""http://www.python.org/ns/"">" library/random,,:len,new_diff = mean(combined[:len(drug)]) - mean(combined[len(drug):]) +library/readline,,:bind,"python:bind -v" +library/readline,,:bind,"python:bind ^I rl_complete" library/smtplib,,:port,method must support that as well as a regular host:port library/socket,,::,'5aef:2b::8' library/socket,,:can,"return (can_id, can_dlc, data[:can_dlc])" diff --git a/Misc/ACKS b/Misc/ACKS index 9d6a9238c8a5..ffc932b08607 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1225,6 +1225,7 @@ Gabriel de Perthuis Tim Peters Benjamin Peterson Joe Peterson +Zvezdan Petkovic Ulrich Petri Chris Petrilli Roumen Petrov diff --git a/Misc/NEWS.d/next/macOS/2018-05-16-13-25-58.bpo-13631.UIjDyY.rst b/Misc/NEWS.d/next/macOS/2018-05-16-13-25-58.bpo-13631.UIjDyY.rst new file mode 100644 index 000000000000..d9d505e937a8 --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2018-05-16-13-25-58.bpo-13631.UIjDyY.rst @@ -0,0 +1,2 @@ +The .editrc file in user's home directory is now processed correctly during +the readline initialization through editline emulation on macOS. diff --git a/Modules/readline.c b/Modules/readline.c index 811fca8cd92a..7756e6b2bc75 100644 --- a/Modules/readline.c +++ b/Modules/readline.c @@ -1078,6 +1078,9 @@ setup_readline(readlinestate *mod_state) Py_FatalError("not enough memory to save locale"); #endif + /* The name must be defined before initialization */ + rl_readline_name = "python"; + #ifdef __APPLE__ /* the libedit readline emulation resets key bindings etc * when calling rl_initialize. So call it upfront @@ -1099,7 +1102,6 @@ setup_readline(readlinestate *mod_state) using_history(); - rl_readline_name = "python"; /* Force rebind of TAB to insert-tab */ rl_bind_key('\t', rl_insert); /* Bind both ESC-TAB and ESC-ESC to the completion function */ From webhook-mailer at python.org Thu May 17 03:52:00 2018 From: webhook-mailer at python.org (Victor Stinner) Date: Thu, 17 May 2018 07:52:00 -0000 Subject: [Python-checkins] bpo-33518: Add PEP entry to documentation glossary (GH-6860) Message-ID: <mailman.104.1526543521.2757.python-checkins@python.org> https://github.com/python/cpython/commit/d5f144260886959c1fe06bc4506a23fd10f92348 commit: d5f144260886959c1fe06bc4506a23fd10f92348 branch: master author: Andr?s Delfino <adelfino at gmail.com> committer: Victor Stinner <vstinner at redhat.com> date: 2018-05-17T09:51:50+02:00 summary: bpo-33518: Add PEP entry to documentation glossary (GH-6860) files: M Doc/glossary.rst diff --git a/Doc/glossary.rst b/Doc/glossary.rst index 16b52670ef20..13d0b9e90b39 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -861,6 +861,21 @@ Glossary :class:`str` or :class:`bytes` result instead, respectively. Introduced by :pep:`519`. + PEP + Python Enhancement Proposal. A PEP is a design document + providing information to the Python community, or describing a new + feature for Python or its processes or environment. PEPs should + provide a concise technical specification and a rationale for proposed + features. + + PEPs are intended to be the primary mechanisms for proposing major new + features, for collecting community input on an issue, and for documenting + the design decisions that have gone into Python. The PEP author is + responsible for building consensus within the community and documenting + dissenting opinions. + + See :pep:`1`. + portion A set of files in a single directory (possibly stored in a zip file) that contribute to a namespace package, as defined in :pep:`420`. From webhook-mailer at python.org Thu May 17 04:16:15 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Thu, 17 May 2018 08:16:15 -0000 Subject: [Python-checkins] bpo-33549: Remove shim and deprecation warning to access DocumentLS.async. (GH-6924) Message-ID: <mailman.105.1526544977.2757.python-checkins@python.org> https://github.com/python/cpython/commit/f90f5d5c1d95721e0ca0b1c302e3d13ed34753a8 commit: f90f5d5c1d95721e0ca0b1c302e3d13ed34753a8 branch: master author: Matthias Bussonnier <bussonniermatthias at gmail.com> committer: Serhiy Storchaka <storchaka at gmail.com> date: 2018-05-17T11:16:12+03:00 summary: bpo-33549: Remove shim and deprecation warning to access DocumentLS.async. (GH-6924) `obj.async` is now a syntax error, so the warning/shim is quasi-unnecessary. files: M Lib/test/test_minidom.py M Lib/xml/dom/xmlbuilder.py diff --git a/Lib/test/test_minidom.py b/Lib/test/test_minidom.py index ee8c04160ab7..a2cc8828461d 100644 --- a/Lib/test/test_minidom.py +++ b/Lib/test/test_minidom.py @@ -60,17 +60,7 @@ def checkWholeText(self, node, s): def testDocumentAsyncAttr(self): doc = Document() self.assertFalse(doc.async_) - with self.assertWarns(DeprecationWarning): - self.assertFalse(getattr(doc, 'async', True)) - with self.assertWarns(DeprecationWarning): - setattr(doc, 'async', True) - with self.assertWarns(DeprecationWarning): - self.assertTrue(getattr(doc, 'async', False)) - self.assertTrue(doc.async_) - self.assertFalse(Document.async_) - with self.assertWarns(DeprecationWarning): - self.assertFalse(getattr(Document, 'async', True)) def testParseFromBinaryFile(self): with open(tstfile, 'rb') as file: diff --git a/Lib/xml/dom/xmlbuilder.py b/Lib/xml/dom/xmlbuilder.py index 60a2bc36e3c2..213ab14551c6 100644 --- a/Lib/xml/dom/xmlbuilder.py +++ b/Lib/xml/dom/xmlbuilder.py @@ -332,29 +332,10 @@ def startContainer(self, element): del NodeFilter -class _AsyncDeprecatedProperty: - def warn(self, cls): - clsname = cls.__name__ - warnings.warn( - "{cls}.async is deprecated; use {cls}.async_".format(cls=clsname), - DeprecationWarning) - - def __get__(self, instance, cls): - self.warn(cls) - if instance is not None: - return instance.async_ - return False - - def __set__(self, instance, value): - self.warn(type(instance)) - setattr(instance, 'async_', value) - - class DocumentLS: """Mixin to create documents that conform to the load/save spec.""" async_ = False - locals()['async'] = _AsyncDeprecatedProperty() # Avoid DeprecationWarning def _get_async(self): return False @@ -384,9 +365,6 @@ def saveXML(self, snode): return snode.toxml() -del _AsyncDeprecatedProperty - - class DOMImplementationLS: MODE_SYNCHRONOUS = 1 MODE_ASYNCHRONOUS = 2 From webhook-mailer at python.org Thu May 17 05:01:05 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Thu, 17 May 2018 09:01:05 -0000 Subject: [Python-checkins] bpo-33549: Remove shim and deprecation warning to access DocumentLS.async. (GH-6924) (GH-6929) Message-ID: <mailman.106.1526547667.2757.python-checkins@python.org> https://github.com/python/cpython/commit/216a27766fab59f4dfecfae0c453f7f3fd478989 commit: 216a27766fab59f4dfecfae0c453f7f3fd478989 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Serhiy Storchaka <storchaka at gmail.com> date: 2018-05-17T12:01:02+03:00 summary: bpo-33549: Remove shim and deprecation warning to access DocumentLS.async. (GH-6924) (GH-6929) `obj.async` is now a syntax error, so the warning/shim is quasi-unnecessary. (cherry picked from commit f90f5d5c1d95721e0ca0b1c302e3d13ed34753a8) Co-authored-by: Matthias Bussonnier <bussonniermatthias at gmail.com> files: M Lib/test/test_minidom.py M Lib/xml/dom/xmlbuilder.py diff --git a/Lib/test/test_minidom.py b/Lib/test/test_minidom.py index ee8c04160ab7..a2cc8828461d 100644 --- a/Lib/test/test_minidom.py +++ b/Lib/test/test_minidom.py @@ -60,17 +60,7 @@ def checkWholeText(self, node, s): def testDocumentAsyncAttr(self): doc = Document() self.assertFalse(doc.async_) - with self.assertWarns(DeprecationWarning): - self.assertFalse(getattr(doc, 'async', True)) - with self.assertWarns(DeprecationWarning): - setattr(doc, 'async', True) - with self.assertWarns(DeprecationWarning): - self.assertTrue(getattr(doc, 'async', False)) - self.assertTrue(doc.async_) - self.assertFalse(Document.async_) - with self.assertWarns(DeprecationWarning): - self.assertFalse(getattr(Document, 'async', True)) def testParseFromBinaryFile(self): with open(tstfile, 'rb') as file: diff --git a/Lib/xml/dom/xmlbuilder.py b/Lib/xml/dom/xmlbuilder.py index 60a2bc36e3c2..213ab14551c6 100644 --- a/Lib/xml/dom/xmlbuilder.py +++ b/Lib/xml/dom/xmlbuilder.py @@ -332,29 +332,10 @@ def startContainer(self, element): del NodeFilter -class _AsyncDeprecatedProperty: - def warn(self, cls): - clsname = cls.__name__ - warnings.warn( - "{cls}.async is deprecated; use {cls}.async_".format(cls=clsname), - DeprecationWarning) - - def __get__(self, instance, cls): - self.warn(cls) - if instance is not None: - return instance.async_ - return False - - def __set__(self, instance, value): - self.warn(type(instance)) - setattr(instance, 'async_', value) - - class DocumentLS: """Mixin to create documents that conform to the load/save spec.""" async_ = False - locals()['async'] = _AsyncDeprecatedProperty() # Avoid DeprecationWarning def _get_async(self): return False @@ -384,9 +365,6 @@ def saveXML(self, snode): return snode.toxml() -del _AsyncDeprecatedProperty - - class DOMImplementationLS: MODE_SYNCHRONOUS = 1 MODE_ASYNCHRONOUS = 2 From solipsis at pitrou.net Thu May 17 05:08:35 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 17 May 2018 09:08:35 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=9 Message-ID: <20180517090835.1.DDA932E335300D39@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_collections leaked [0, 0, 7] memory blocks, sum=7 test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_spawn leaked [0, 0, -2] memory blocks, sum=-2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogTWzHr5', '--timeout', '7200'] From webhook-mailer at python.org Thu May 17 05:14:35 2018 From: webhook-mailer at python.org (Ned Deily) Date: Thu, 17 May 2018 09:14:35 -0000 Subject: [Python-checkins] Update Python Folder.icns icon file to match new macOS look (GH-1780) Message-ID: <mailman.107.1526548475.2757.python-checkins@python.org> https://github.com/python/cpython/commit/74fc9c0c09ba72de39f9b71a61ac8506304b6266 commit: 74fc9c0c09ba72de39f9b71a61ac8506304b6266 branch: master author: Thomas Jones <thomas at tomtecsolutions.com> committer: Ned Deily <nad at python.org> date: 2018-05-17T05:14:30-04:00 summary: Update Python Folder.icns icon file to match new macOS look (GH-1780) Patch by Thomas Jones. files: M Mac/Icons/Python Folder.icns diff --git a/Mac/Icons/Python Folder.icns b/Mac/Icons/Python Folder.icns index ae766ee15898..3658f5e88a2b 100644 Binary files a/Mac/Icons/Python Folder.icns and b/Mac/Icons/Python Folder.icns differ From webhook-mailer at python.org Thu May 17 05:17:38 2018 From: webhook-mailer at python.org (Ned Deily) Date: Thu, 17 May 2018 09:17:38 -0000 Subject: [Python-checkins] Update Python Folder.icns icon file to match new macOS look (GH-1780) (GH-6930) Message-ID: <mailman.108.1526548659.2757.python-checkins@python.org> https://github.com/python/cpython/commit/54a5247837a97d8833dc6eba72df0826afe4558d commit: 54a5247837a97d8833dc6eba72df0826afe4558d branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Ned Deily <nad at python.org> date: 2018-05-17T05:17:35-04:00 summary: Update Python Folder.icns icon file to match new macOS look (GH-1780) (GH-6930) (cherry picked from commit 74fc9c0c09ba72de39f9b71a61ac8506304b6266) Co-authored-by: Thomas Jones <thomas at tomtecsolutions.com> files: M Mac/Icons/Python Folder.icns diff --git a/Mac/Icons/Python Folder.icns b/Mac/Icons/Python Folder.icns index ae766ee15898..3658f5e88a2b 100644 Binary files a/Mac/Icons/Python Folder.icns and b/Mac/Icons/Python Folder.icns differ From webhook-mailer at python.org Thu May 17 08:49:07 2018 From: webhook-mailer at python.org (Steve Dower) Date: Thu, 17 May 2018 12:49:07 -0000 Subject: [Python-checkins] bpo-33522: Enable CI builds on Visual Studio Team Services (GH-6865) (GH-6926) Message-ID: <mailman.109.1526561348.2757.python-checkins@python.org> https://github.com/python/cpython/commit/8965d75c90e80b6983b36f3ae9601d6a257d782b commit: 8965d75c90e80b6983b36f3ae9601d6a257d782b branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Steve Dower <steve.dower at microsoft.com> date: 2018-05-17T08:49:01-04:00 summary: bpo-33522: Enable CI builds on Visual Studio Team Services (GH-6865) (GH-6926) (cherry picked from commit e5f41d2f1e0b8b8e61d5fa427c19bd1ea90fd9a3) Co-authored-by: Steve Dower <steve.dower at microsoft.com> files: A .vsts/docs-release.yml A .vsts/docs.yml A .vsts/linux-buildbot.yml A .vsts/linux-coverage.yml A .vsts/linux-deps.yml A .vsts/linux-pr.yml A .vsts/macos-buildbot.yml A .vsts/macos-pr.yml A .vsts/windows-buildbot.yml A .vsts/windows-pr.yml A Misc/NEWS.d/next/Build/2018-05-15-12-44-50.bpo-33522.mJoNcA.rst A Misc/NEWS.d/next/Library/2018-05-16-17-05-48.bpo-33548.xWslmx.rst M Doc/make.bat M Lib/tempfile.py M Lib/test/support/__init__.py M Lib/test/test_asyncio/test_base_events.py M Lib/test/test_bdb.py M Lib/test/test_pathlib.py M Lib/test/test_poplib.py M Lib/test/test_selectors.py M PCbuild/rt.bat M Tools/ssl/multissltests.py diff --git a/.vsts/docs-release.yml b/.vsts/docs-release.yml new file mode 100644 index 000000000000..e90428a42494 --- /dev/null +++ b/.vsts/docs-release.yml @@ -0,0 +1,43 @@ +# Current docs for the syntax of this file are at: +# https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md + +name: $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.rr) + +queue: + name: Hosted Linux Preview + +#variables: + +steps: +- checkout: self + clean: true + fetchDepth: 5 + +- script: sudo apt-get update && sudo apt-get install -qy --force-yes texlive-full + displayName: 'Install LaTeX' + +- task: UsePythonVersion at 0 + displayName: 'Use Python 3.6 or later' + inputs: + versionSpec: '>=3.6' + +- script: python -m pip install sphinx blurb python-docs-theme + displayName: 'Install build dependencies' + +- script: make dist PYTHON=python SPHINXBUILD='python -m sphinx' BLURB='python -m blurb' + workingDirectory: '$(build.sourcesDirectory)/Doc' + displayName: 'Build documentation' + +- task: PublishBuildArtifacts at 1 + displayName: 'Publish build' + inputs: + PathToPublish: '$(build.sourcesDirectory)/Doc/build' + ArtifactName: build + publishLocation: Container + +- task: PublishBuildArtifacts at 1 + displayName: 'Publish dist' + inputs: + PathToPublish: '$(build.sourcesDirectory)/Doc/dist' + ArtifactName: dist + publishLocation: Container diff --git a/.vsts/docs.yml b/.vsts/docs.yml new file mode 100644 index 000000000000..efa1e871656d --- /dev/null +++ b/.vsts/docs.yml @@ -0,0 +1,43 @@ +# Current docs for the syntax of this file are at: +# https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md + +name: $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.rr) + +queue: + name: Hosted Linux Preview + +trigger: + branches: + include: + - master + - 3.7 + - 3.6 + paths: + include: + - Doc/* + +#variables: + +steps: +- checkout: self + clean: true + fetchDepth: 5 + +- task: UsePythonVersion at 0 + displayName: 'Use Python 3.6 or later' + inputs: + versionSpec: '>=3.6' + +- script: python -m pip install sphinx~=1.6.1 blurb python-docs-theme + displayName: 'Install build dependencies' + +- script: make check suspicious html PYTHON=python + workingDirectory: '$(build.sourcesDirectory)/Doc' + displayName: 'Build documentation' + +- task: PublishBuildArtifacts at 1 + displayName: 'Publish build' + inputs: + PathToPublish: '$(build.sourcesDirectory)/Doc/build' + ArtifactName: build + publishLocation: Container diff --git a/.vsts/linux-buildbot.yml b/.vsts/linux-buildbot.yml new file mode 100644 index 000000000000..d75d7f57650e --- /dev/null +++ b/.vsts/linux-buildbot.yml @@ -0,0 +1,71 @@ +# Current docs for the syntax of this file are at: +# https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md + +name: $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.rr) + +queue: + name: Hosted Linux Preview + +trigger: + branches: + include: + - master + - 3.7 + - 3.6 + paths: + exclude: + - Doc/* + - Tools/* + +variables: + # Copy-pasted from linux-deps.yml until template support arrives + OPENSSL: 1.1.0g + OPENSSL_DIR: "$(build.sourcesDirectory)/multissl/openssl/$(OPENSSL)" + + +steps: +- checkout: self + clean: true + fetchDepth: 5 + +#- template: linux-deps.yml + +# See https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted-templates.md +# For now, we copy/paste the steps +- script: echo "deb-src http://archive.ubuntu.com/ubuntu/ xenial main" > /etc/apt/sources.list.d/python.list && sudo apt-get update + displayName: 'Update apt-get lists' + +- script: echo ##vso[task.prependpath]$(OPENSSL_DIR) + displayName: 'Add $(OPENSSL_DIR) to PATH' +- script: > + sudo apt-get -yq install + build-essential + zlib1g-dev + libbz2-dev + liblzma-dev + libncurses5-dev + libreadline6-dev + libsqlite3-dev + libssl-dev + libgdbm-dev + tk-dev + lzma + lzma-dev + liblzma-dev + libffi-dev + uuid-dev + displayName: 'Install dependencies' +- script: python3 Tools/ssl/multissltests.py --steps=library --base-directory $(build.sourcesDirectory)/multissl --openssl $(OPENSSL) --system Linux + displayName: 'python multissltests.py' + +- script: ./configure --with-pydebug + displayName: 'Configure CPython (debug)' + +- script: make -s -j4 + displayName: 'Build CPython' + +- script: make pythoninfo + displayName: 'Display build info' + +- script: make buildbottest TESTOPTS="-j4 -uall,-cpu" + displayName: 'Tests' diff --git a/.vsts/linux-coverage.yml b/.vsts/linux-coverage.yml new file mode 100644 index 000000000000..3657b1720ee2 --- /dev/null +++ b/.vsts/linux-coverage.yml @@ -0,0 +1,77 @@ +# Current docs for the syntax of this file are at: +# https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md + +name: $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.rr) + +queue: + name: Hosted Linux Preview + +trigger: + branches: + include: + - master + - 3.7 + - 3.6 + paths: + exclude: + - Doc/* + - Tools/* + +variables: + # Copy-pasted from linux-deps.yml until template support arrives + OPENSSL: 1.1.0g + OPENSSL_DIR: "$(build.sourcesDirectory)/multissl/openssl/$(OPENSSL)" + +steps: +- checkout: self + clean: true + fetchDepth: 5 + +#- template: linux-deps.yml + +# See https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted-templates.md +# For now, we copy/paste the steps +- script: echo "deb-src http://archive.ubuntu.com/ubuntu/ xenial main" > /etc/apt/sources.list.d/python.list && sudo apt-get update + displayName: 'Update apt-get lists' + +- script: echo ##vso[task.prependpath]$(OPENSSL_DIR) + displayName: 'Add $(OPENSSL_DIR) to PATH' +- script: > + sudo apt-get -yq install + build-essential + zlib1g-dev + libbz2-dev + liblzma-dev + libncurses5-dev + libreadline6-dev + libsqlite3-dev + libssl-dev + libgdbm-dev + tk-dev + lzma + lzma-dev + liblzma-dev + libffi-dev + uuid-dev + displayName: 'Install dependencies' +- script: python3 Tools/ssl/multissltests.py --steps=library --base-directory $(build.sourcesDirectory)/multissl --openssl $(OPENSSL) --system Linux + displayName: 'python multissltests.py' + + +- script: ./configure --with-pydebug + displayName: 'Configure CPython (debug)' + +- script: make -s -j4 + displayName: 'Build CPython' + +- script: ./python -m venv venv && ./venv/bin/python -m pip install -U coverage + displayName: 'Set up virtual environment' + +- script: ./venv/bin/python -m test.pythoninfo + displayName: 'Display build info' + +- script: ./venv/bin/python -m coverage run --pylib -m test --fail-env-changed -uall,-cpu -x test_multiprocessing_fork -x test_multiprocessing_forkserver -x test_multiprocessing_spawn -x test_concurrent_futures + displayName: 'Tests with coverage' + +- script: source ./venv/bin/activate && bash <(curl -s https://codecov.io/bash) + displayName: 'Publish code coverage results' diff --git a/.vsts/linux-deps.yml b/.vsts/linux-deps.yml new file mode 100644 index 000000000000..b6c8a3690ea1 --- /dev/null +++ b/.vsts/linux-deps.yml @@ -0,0 +1,36 @@ +# Note: this file is not currently used, but when template support comes to VSTS it +# will be referenced from the other scripts.. + +# Current docs for the syntax of this file are at: +# https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md + +parameters: + OPENSSL: 1.1.0g + OPENSSL_DIR: "$(build.sourcesDirectory)/multissl/openssl/$(OPENSSL)" + +steps: +- script: echo "deb-src http://archive.ubuntu.com/ubuntu/ xenial main" > /etc/apt/sources.list.d/python.list && sudo apt-get update + displayName: 'Update apt-get lists' + +- script: echo ##vso[task.prependpath]$(OPENSSL_DIR) + displayName: 'Add $(OPENSSL_DIR) to PATH' +- script: > + sudo apt-get -yq install + build-essential + zlib1g-dev + libbz2-dev + liblzma-dev + libncurses5-dev + libreadline6-dev + libsqlite3-dev + libssl-dev + libgdbm-dev + tk-dev + lzma + lzma-dev + liblzma-dev + libffi-dev + uuid-dev + displayName: 'Install dependencies' +- script: python3 Tools/ssl/multissltests.py --steps=library --base-directory $(build.sourcesDirectory)/multissl --openssl $(OPENSSL) --system Linux + displayName: 'python multissltests.py' diff --git a/.vsts/linux-pr.yml b/.vsts/linux-pr.yml new file mode 100644 index 000000000000..7f4d458f5a7c --- /dev/null +++ b/.vsts/linux-pr.yml @@ -0,0 +1,75 @@ +# Current docs for the syntax of this file are at: +# https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md + +name: $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.rr) + +queue: + name: Hosted Linux Preview + +trigger: + branches: + include: + - master + - 3.7 + - 3.6 + paths: + exclude: + - Doc/* + - Tools/* + +variables: + # Copy-pasted from linux-deps.yml until template support arrives + OPENSSL: 1.1.0g + OPENSSL_DIR: "$(build.sourcesDirectory)/multissl/openssl/$(OPENSSL)" + +steps: +- checkout: self + clean: true + fetchDepth: 5 + +#- template: linux-deps.yml + +# See https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted-templates.md +# For now, we copy/paste the steps +- script: echo "deb-src http://archive.ubuntu.com/ubuntu/ xenial main" > /etc/apt/sources.list.d/python.list && sudo apt-get update + displayName: 'Update apt-get lists' + +- script: echo ##vso[task.prependpath]$(OPENSSL_DIR) + displayName: 'Add $(OPENSSL_DIR) to PATH' +- script: > + sudo apt-get -yq install + build-essential + zlib1g-dev + libbz2-dev + liblzma-dev + libncurses5-dev + libreadline6-dev + libsqlite3-dev + libssl-dev + libgdbm-dev + tk-dev + lzma + lzma-dev + liblzma-dev + libffi-dev + uuid-dev + displayName: 'Install dependencies' +- script: python3 Tools/ssl/multissltests.py --steps=library --base-directory $(build.sourcesDirectory)/multissl --openssl $(OPENSSL) --system Linux + displayName: 'python multissltests.py' + + +- script: ./configure --with-pydebug + displayName: 'Configure CPython (debug)' + +- script: make -s -j4 + displayName: 'Build CPython' + +- script: make pythoninfo + displayName: 'Display build info' + +# Run patchcheck and fail if anything is discovered +- script: ./python Tools/scripts/patchcheck.py --travis true + displayName: 'Run patchcheck.py' + +- script: make buildbottest TESTOPTS="-j4 -uall,-cpu" + displayName: 'Tests' diff --git a/.vsts/macos-buildbot.yml b/.vsts/macos-buildbot.yml new file mode 100644 index 000000000000..8a4f6ba8cb8b --- /dev/null +++ b/.vsts/macos-buildbot.yml @@ -0,0 +1,37 @@ +# Current docs for the syntax of this file are at: +# https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md + +name: $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.rr) + +queue: + name: Hosted macOS Preview + +trigger: + branches: + include: + - master + - 3.7 + - 3.6 + paths: + exclude: + - Doc/* + - Tools/* + +#variables: + +steps: +- checkout: self + clean: true + fetchDepth: 5 + +- script: ./configure --with-pydebug --with-openssl=/usr/local/opt/openssl + displayName: 'Configure CPython (debug)' + +- script: make -s -j4 + displayName: 'Build CPython' + +- script: make pythoninfo + displayName: 'Display build info' + +- script: make buildbottest TESTOPTS="-j4 -uall,-cpu" + displayName: 'Tests' diff --git a/.vsts/macos-pr.yml b/.vsts/macos-pr.yml new file mode 100644 index 000000000000..8a4f6ba8cb8b --- /dev/null +++ b/.vsts/macos-pr.yml @@ -0,0 +1,37 @@ +# Current docs for the syntax of this file are at: +# https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md + +name: $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.rr) + +queue: + name: Hosted macOS Preview + +trigger: + branches: + include: + - master + - 3.7 + - 3.6 + paths: + exclude: + - Doc/* + - Tools/* + +#variables: + +steps: +- checkout: self + clean: true + fetchDepth: 5 + +- script: ./configure --with-pydebug --with-openssl=/usr/local/opt/openssl + displayName: 'Configure CPython (debug)' + +- script: make -s -j4 + displayName: 'Build CPython' + +- script: make pythoninfo + displayName: 'Display build info' + +- script: make buildbottest TESTOPTS="-j4 -uall,-cpu" + displayName: 'Tests' diff --git a/.vsts/windows-buildbot.yml b/.vsts/windows-buildbot.yml new file mode 100644 index 000000000000..5ec4522796ce --- /dev/null +++ b/.vsts/windows-buildbot.yml @@ -0,0 +1,49 @@ +# Current docs for the syntax of this file are at: +# https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md + +name: $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.rr) + +queue: + name: Hosted VS2017 + parallel: 2 + matrix: + amd64: + buildOpt: -p x64 + outDirSuffix: amd64 + win32: + buildOpt: + outDirSuffix: win32 + +trigger: + branches: + include: + - master + - 3.7 + - 3.6 + paths: + exclude: + - Doc/* + - Tools/* + +variables: + # Relocate build outputs outside of source directory to make cleaning faster + Py_IntDir: $(Build.BinariesDirectory)\obj + # UNDONE: Do not build to a different directory because of broken tests + Py_OutDir: $(Build.SourcesDirectory)\PCbuild + EXTERNAL_DIR: $(Build.BinariesDirectory)\externals + +steps: +- checkout: self + clean: true + fetchDepth: 5 + +- script: PCbuild\build.bat -e $(buildOpt) + displayName: 'Build CPython' + +- script: python.bat -m test.pythoninfo + displayName: 'Display build info' + +- script: PCbuild\rt.bat -q -uall -u-cpu -rwW --slowest --timeout=1200 -j0 + displayName: 'Tests' + env: + PREFIX: $(Py_OutDir)\$(outDirSuffix) diff --git a/.vsts/windows-pr.yml b/.vsts/windows-pr.yml new file mode 100644 index 000000000000..5ec4522796ce --- /dev/null +++ b/.vsts/windows-pr.yml @@ -0,0 +1,49 @@ +# Current docs for the syntax of this file are at: +# https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md + +name: $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.rr) + +queue: + name: Hosted VS2017 + parallel: 2 + matrix: + amd64: + buildOpt: -p x64 + outDirSuffix: amd64 + win32: + buildOpt: + outDirSuffix: win32 + +trigger: + branches: + include: + - master + - 3.7 + - 3.6 + paths: + exclude: + - Doc/* + - Tools/* + +variables: + # Relocate build outputs outside of source directory to make cleaning faster + Py_IntDir: $(Build.BinariesDirectory)\obj + # UNDONE: Do not build to a different directory because of broken tests + Py_OutDir: $(Build.SourcesDirectory)\PCbuild + EXTERNAL_DIR: $(Build.BinariesDirectory)\externals + +steps: +- checkout: self + clean: true + fetchDepth: 5 + +- script: PCbuild\build.bat -e $(buildOpt) + displayName: 'Build CPython' + +- script: python.bat -m test.pythoninfo + displayName: 'Display build info' + +- script: PCbuild\rt.bat -q -uall -u-cpu -rwW --slowest --timeout=1200 -j0 + displayName: 'Tests' + env: + PREFIX: $(Py_OutDir)\$(outDirSuffix) diff --git a/Doc/make.bat b/Doc/make.bat index 3f201de1db79..c69cfae31941 100644 --- a/Doc/make.bat +++ b/Doc/make.bat @@ -6,17 +6,20 @@ pushd %~dp0 set this=%~n0 call ..\PCbuild\find_python.bat %PYTHON% -if not defined SPHINXBUILD if defined PYTHON ( + +if not defined PYTHON set PYTHON=py + +if not defined SPHINXBUILD ( %PYTHON% -c "import sphinx" > nul 2> nul if errorlevel 1 ( echo Installing sphinx with %PYTHON% - %PYTHON% -m pip install sphinx + %PYTHON% -m pip install sphinx python-docs-theme if errorlevel 1 exit /B ) set SPHINXBUILD=%PYTHON% -c "import sphinx, sys; sys.argv[0] = 'sphinx-build'; sphinx.main()" ) -if not defined BLURB if defined PYTHON ( +if not defined BLURB ( %PYTHON% -c "import blurb" > nul 2> nul if errorlevel 1 ( echo Installing blurb with %PYTHON% @@ -26,7 +29,6 @@ if not defined BLURB if defined PYTHON ( set BLURB=%PYTHON% -m blurb ) -if not defined PYTHON set PYTHON=py if not defined SPHINXBUILD set SPHINXBUILD=sphinx-build if not defined BLURB set BLURB=blurb diff --git a/Lib/tempfile.py b/Lib/tempfile.py index e5b7a92fad7b..214322416963 100644 --- a/Lib/tempfile.py +++ b/Lib/tempfile.py @@ -169,7 +169,9 @@ def _candidate_tempdir_list(): # Failing that, try OS-specific locations. if _os.name == 'nt': - dirlist.extend([ r'c:\temp', r'c:\tmp', r'\temp', r'\tmp' ]) + dirlist.extend([ _os.path.expanduser(r'~\AppData\Local\Temp'), + _os.path.expandvars(r'%SYSTEMROOT%\Temp'), + r'c:\temp', r'c:\tmp', r'\temp', r'\tmp' ]) else: dirlist.extend([ '/tmp', '/var/tmp', '/usr/tmp' ]) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 2389d58d706e..1024ab6ab922 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -363,6 +363,20 @@ def _rmtree_inner(path): _force_run(fullname, os.unlink, fullname) _waitfor(_rmtree_inner, path, waitall=True) _waitfor(lambda p: _force_run(p, os.rmdir, p), path) + + def _longpath(path): + try: + import ctypes + except ImportError: + # No ctypes means we can't expands paths. + pass + else: + buffer = ctypes.create_unicode_buffer(len(path) * 2) + length = ctypes.windll.kernel32.GetLongPathNameW(path, buffer, + len(buffer)) + if length: + return buffer[:length] + return path else: _unlink = os.unlink _rmdir = os.rmdir @@ -389,6 +403,9 @@ def _rmtree_inner(path): _rmtree_inner(path) os.rmdir(path) + def _longpath(path): + return path + def unlink(filename): try: _unlink(filename) @@ -2381,13 +2398,15 @@ def can_xattr(): if not hasattr(os, "setxattr"): can = False else: - tmp_fp, tmp_name = tempfile.mkstemp() + tmp_dir = tempfile.mkdtemp() + tmp_fp, tmp_name = tempfile.mkstemp(dir=tmp_dir) try: with open(TESTFN, "wb") as fp: try: # TESTFN & tempfile may use different file systems with # different capabilities os.setxattr(tmp_fp, b"user.test", b"") + os.setxattr(tmp_name, b"trusted.foo", b"42") os.setxattr(fp.fileno(), b"user.test", b"") # Kernels < 2.6.39 don't respect setxattr flags. kernel_version = platform.release() @@ -2398,6 +2417,7 @@ def can_xattr(): finally: unlink(TESTFN) unlink(tmp_name) + rmdir(tmp_dir) _can_xattr = can return can diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index ab6560c70b90..72c63df91070 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -1848,10 +1848,22 @@ def run_loop(self, coro): def prepare(self): sock = self.make_socket() proto = self.MyProto(self.loop) - port = support.find_unused_port() + af = socket.AF_UNSPEC if support.IPV6_ENABLED else socket.AF_INET server = self.run_loop(self.loop.create_server( - lambda: proto, support.HOST, port)) - self.run_loop(self.loop.sock_connect(sock, (support.HOST, port))) + lambda: proto, support.HOST, 0, family=af)) + port = server.sockets[0].getsockname()[1] + + for _ in range(10): + try: + self.run_loop(self.loop.sock_connect(sock, (support.HOST, port))) + except OSError: + time.sleep(0.5) + continue + else: + break + else: + # One last try, so we get the exception + self.run_loop(self.loop.sock_connect(sock, (support.HOST, port))) def cleanup(): server.close() diff --git a/Lib/test/test_bdb.py b/Lib/test/test_bdb.py index bda74a2be775..616c3a864984 100644 --- a/Lib/test/test_bdb.py +++ b/Lib/test/test_bdb.py @@ -417,15 +417,17 @@ def __init__(self, test_case, skip=None): self.dry_run = test_case.dry_run self.tracer = Tracer(test_case.expect_set, skip=skip, dry_run=self.dry_run, test_case=test_case.id()) + self._original_tracer = None def __enter__(self): # test_pdb does not reset Breakpoint class attributes on exit :-( reset_Breakpoint() + self._original_tracer = sys.gettrace() return self.tracer def __exit__(self, type_=None, value=None, traceback=None): reset_Breakpoint() - sys.settrace(None) + sys.settrace(self._original_tracer) not_empty = '' if self.tracer.set_list: diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index d1a3fba2ded9..d95a831b7b62 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -1516,7 +1516,7 @@ def test_resolve_common(self): # resolves to 'dirB/..' first before resolving to parent of dirB. self._check_resolve_relative(p, P(BASE, 'foo', 'in', 'spam'), False) # Now create absolute symlinks - d = tempfile.mkdtemp(suffix='-dirD') + d = support._longpath(tempfile.mkdtemp(suffix='-dirD')) self.addCleanup(support.rmtree, d) os.symlink(os.path.join(d), join('dirA', 'linkX')) os.symlink(join('dirB'), os.path.join(d, 'linkY')) diff --git a/Lib/test/test_poplib.py b/Lib/test/test_poplib.py index bf568bd77bff..bbedbbdb10a1 100644 --- a/Lib/test/test_poplib.py +++ b/Lib/test/test_poplib.py @@ -179,7 +179,8 @@ def _do_tls_handshake(self): elif err.args[0] == ssl.SSL_ERROR_EOF: return self.handle_close() # TODO: SSLError does not expose alert information - elif "SSLV3_ALERT_BAD_CERTIFICATE" in err.args[1]: + elif ("SSLV3_ALERT_BAD_CERTIFICATE" in err.args[1] or + "SSLV3_ALERT_CERTIFICATE_UNKNOWN" in err.args[1]): return self.handle_close() raise except OSError as err: @@ -222,11 +223,12 @@ def start(self): def run(self): self.active = True self.__flag.set() - while self.active and asyncore.socket_map: - self.active_lock.acquire() - asyncore.loop(timeout=0.1, count=1) - self.active_lock.release() - asyncore.close_all(ignore_all=True) + try: + while self.active and asyncore.socket_map: + with self.active_lock: + asyncore.loop(timeout=0.1, count=1) + finally: + asyncore.close_all(ignore_all=True) def stop(self): assert self.active diff --git a/Lib/test/test_selectors.py b/Lib/test/test_selectors.py index 79ac25c12d4a..31611224dc71 100644 --- a/Lib/test/test_selectors.py +++ b/Lib/test/test_selectors.py @@ -481,7 +481,14 @@ def test_above_fd_setsize(self): self.skipTest("FD limit reached") raise - self.assertEqual(NUM_FDS // 2, len(s.select())) + try: + fds = s.select() + except OSError as e: + if e.errno == errno.EINVAL and sys.platform == 'darwin': + # unexplainable errors on macOS don't need to fail the test + self.skipTest("Invalid argument error calling poll()") + raise + self.assertEqual(NUM_FDS // 2, len(fds)) class DefaultSelectorTestCase(BaseSelectorTestCase): diff --git a/Misc/NEWS.d/next/Build/2018-05-15-12-44-50.bpo-33522.mJoNcA.rst b/Misc/NEWS.d/next/Build/2018-05-15-12-44-50.bpo-33522.mJoNcA.rst new file mode 100644 index 000000000000..f44862f0c454 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2018-05-15-12-44-50.bpo-33522.mJoNcA.rst @@ -0,0 +1,2 @@ +Enable CI builds on Visual Studio Team Services at +https://python.visualstudio.com/cpython diff --git a/Misc/NEWS.d/next/Library/2018-05-16-17-05-48.bpo-33548.xWslmx.rst b/Misc/NEWS.d/next/Library/2018-05-16-17-05-48.bpo-33548.xWslmx.rst new file mode 100644 index 000000000000..65585c152987 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-16-17-05-48.bpo-33548.xWslmx.rst @@ -0,0 +1 @@ +tempfile._candidate_tempdir_list should consider common TEMP locations diff --git a/PCbuild/rt.bat b/PCbuild/rt.bat index 575cdc858fda..212befc95b06 100644 --- a/PCbuild/rt.bat +++ b/PCbuild/rt.bat @@ -7,7 +7,7 @@ rem -q "quick" -- normally the tests are run twice, the first time rem after deleting all the .pyc files reachable from Lib/. rem -q runs the tests just once, and without deleting .pyc files. rem -x64 Run the 64-bit build of python (or python_d if -d was specified) -rem from the 'amd64' dir instead of the 32-bit build in this dir. +rem When omitted, uses %PREFIX% if set or the 32-bit build rem All leading instances of these switches are shifted off, and rem whatever remains (up to 9 arguments) is passed to regrtest.py. rem For example, @@ -28,20 +28,21 @@ rem rt -u "network,largefile" setlocal set pcbuild=%~dp0 -set prefix=%pcbuild%win32\ set suffix= set qmode= set dashO= set regrtestargs= +set exe= :CheckOpts if "%1"=="-O" (set dashO=-O) & shift & goto CheckOpts if "%1"=="-q" (set qmode=yes) & shift & goto CheckOpts if "%1"=="-d" (set suffix=_d) & shift & goto CheckOpts -if "%1"=="-x64" (set prefix=%pcbuild%amd64\) & shift & goto CheckOpts +if "%1"=="-x64" (set prefix=%pcbuild%amd64) & shift & goto CheckOpts if NOT "%1"=="" (set regrtestargs=%regrtestargs% %1) & shift & goto CheckOpts -set exe=%prefix%python%suffix%.exe +if not defined prefix set prefix=%pcbuild%win32 +set exe=%prefix%\python%suffix%.exe set cmd="%exe%" %dashO% -u -Wd -E -bb -m test %regrtestargs% if defined qmode goto Qmode @@ -49,7 +50,7 @@ echo Deleting .pyc files ... "%exe%" "%pcbuild%rmpyc.py" echo Cleaning _pth files ... -if exist %prefix%*._pth del %prefix%*._pth +if exist %prefix%\*._pth del %prefix%\*._pth echo on %cmd% diff --git a/Tools/ssl/multissltests.py b/Tools/ssl/multissltests.py index a51566c5069d..2efc4258de91 100755 --- a/Tools/ssl/multissltests.py +++ b/Tools/ssl/multissltests.py @@ -125,6 +125,11 @@ "all and runs the test suite." ) ) +parser.add_argument( + '--system', + default='', + help="Override the automatic system type detection." +) class AbstractBuilder(object): @@ -152,6 +157,7 @@ def __init__(self, version, args): # build directory (removed after install) self.build_dir = os.path.join( self.src_dir, self.build_template.format(version)) + self.system = args.system def __str__(self): return "<{0.__class__.__name__} for {0.version}>".format(self) @@ -255,9 +261,13 @@ def _build_src(self): log.info("Running build in {}".format(self.build_dir)) cwd = self.build_dir cmd = ["./config", "shared", "--prefix={}".format(self.install_dir)] - self._subprocess_call(cmd, cwd=cwd) + env = None + if self.system: + env = os.environ.copy() + env['SYSTEM'] = self.system + self._subprocess_call(cmd, cwd=cwd, env=env) # Old OpenSSL versions do not support parallel builds. - self._subprocess_call(["make", "-j1"], cwd=cwd) + self._subprocess_call(["make", "-j1"], cwd=cwd, env=env) def _make_install(self, remove=True): self._subprocess_call( From webhook-mailer at python.org Thu May 17 09:46:03 2018 From: webhook-mailer at python.org (Steve Dower) Date: Thu, 17 May 2018 13:46:03 -0000 Subject: [Python-checkins] bpo-33522: Enable CI builds on Visual Studio Team Services (GH-6865) (GH-6925) Message-ID: <mailman.110.1526564764.2757.python-checkins@python.org> https://github.com/python/cpython/commit/0d8f83f59c8f4cc7fe125434ca4ecdcac111810f commit: 0d8f83f59c8f4cc7fe125434ca4ecdcac111810f branch: 3.6 author: Steve Dower <steve.dower at microsoft.com> committer: GitHub <noreply at github.com> date: 2018-05-17T09:46:00-04:00 summary: bpo-33522: Enable CI builds on Visual Studio Team Services (GH-6865) (GH-6925) files: A .vsts/docs-release.yml A .vsts/docs.yml A .vsts/linux-buildbot.yml A .vsts/linux-coverage.yml A .vsts/linux-deps.yml A .vsts/linux-pr.yml A .vsts/macos-buildbot.yml A .vsts/macos-pr.yml A .vsts/windows-buildbot.yml A .vsts/windows-pr.yml A Misc/NEWS.d/next/Build/2018-05-15-12-44-50.bpo-33522.mJoNcA.rst A Misc/NEWS.d/next/Library/2018-05-16-17-05-48.bpo-33548.xWslmx.rst M Doc/make.bat M Lib/tempfile.py M Lib/test/support/__init__.py M Lib/test/test_asyncio/test_base_events.py M Lib/test/test_bdb.py M Lib/test/test_pathlib.py M Lib/test/test_poplib.py M Lib/test/test_selectors.py M PCbuild/rt.bat M Tools/ssl/multissltests.py diff --git a/.vsts/docs-release.yml b/.vsts/docs-release.yml new file mode 100644 index 000000000000..e90428a42494 --- /dev/null +++ b/.vsts/docs-release.yml @@ -0,0 +1,43 @@ +# Current docs for the syntax of this file are at: +# https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md + +name: $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.rr) + +queue: + name: Hosted Linux Preview + +#variables: + +steps: +- checkout: self + clean: true + fetchDepth: 5 + +- script: sudo apt-get update && sudo apt-get install -qy --force-yes texlive-full + displayName: 'Install LaTeX' + +- task: UsePythonVersion at 0 + displayName: 'Use Python 3.6 or later' + inputs: + versionSpec: '>=3.6' + +- script: python -m pip install sphinx blurb python-docs-theme + displayName: 'Install build dependencies' + +- script: make dist PYTHON=python SPHINXBUILD='python -m sphinx' BLURB='python -m blurb' + workingDirectory: '$(build.sourcesDirectory)/Doc' + displayName: 'Build documentation' + +- task: PublishBuildArtifacts at 1 + displayName: 'Publish build' + inputs: + PathToPublish: '$(build.sourcesDirectory)/Doc/build' + ArtifactName: build + publishLocation: Container + +- task: PublishBuildArtifacts at 1 + displayName: 'Publish dist' + inputs: + PathToPublish: '$(build.sourcesDirectory)/Doc/dist' + ArtifactName: dist + publishLocation: Container diff --git a/.vsts/docs.yml b/.vsts/docs.yml new file mode 100644 index 000000000000..efa1e871656d --- /dev/null +++ b/.vsts/docs.yml @@ -0,0 +1,43 @@ +# Current docs for the syntax of this file are at: +# https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md + +name: $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.rr) + +queue: + name: Hosted Linux Preview + +trigger: + branches: + include: + - master + - 3.7 + - 3.6 + paths: + include: + - Doc/* + +#variables: + +steps: +- checkout: self + clean: true + fetchDepth: 5 + +- task: UsePythonVersion at 0 + displayName: 'Use Python 3.6 or later' + inputs: + versionSpec: '>=3.6' + +- script: python -m pip install sphinx~=1.6.1 blurb python-docs-theme + displayName: 'Install build dependencies' + +- script: make check suspicious html PYTHON=python + workingDirectory: '$(build.sourcesDirectory)/Doc' + displayName: 'Build documentation' + +- task: PublishBuildArtifacts at 1 + displayName: 'Publish build' + inputs: + PathToPublish: '$(build.sourcesDirectory)/Doc/build' + ArtifactName: build + publishLocation: Container diff --git a/.vsts/linux-buildbot.yml b/.vsts/linux-buildbot.yml new file mode 100644 index 000000000000..d75d7f57650e --- /dev/null +++ b/.vsts/linux-buildbot.yml @@ -0,0 +1,71 @@ +# Current docs for the syntax of this file are at: +# https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md + +name: $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.rr) + +queue: + name: Hosted Linux Preview + +trigger: + branches: + include: + - master + - 3.7 + - 3.6 + paths: + exclude: + - Doc/* + - Tools/* + +variables: + # Copy-pasted from linux-deps.yml until template support arrives + OPENSSL: 1.1.0g + OPENSSL_DIR: "$(build.sourcesDirectory)/multissl/openssl/$(OPENSSL)" + + +steps: +- checkout: self + clean: true + fetchDepth: 5 + +#- template: linux-deps.yml + +# See https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted-templates.md +# For now, we copy/paste the steps +- script: echo "deb-src http://archive.ubuntu.com/ubuntu/ xenial main" > /etc/apt/sources.list.d/python.list && sudo apt-get update + displayName: 'Update apt-get lists' + +- script: echo ##vso[task.prependpath]$(OPENSSL_DIR) + displayName: 'Add $(OPENSSL_DIR) to PATH' +- script: > + sudo apt-get -yq install + build-essential + zlib1g-dev + libbz2-dev + liblzma-dev + libncurses5-dev + libreadline6-dev + libsqlite3-dev + libssl-dev + libgdbm-dev + tk-dev + lzma + lzma-dev + liblzma-dev + libffi-dev + uuid-dev + displayName: 'Install dependencies' +- script: python3 Tools/ssl/multissltests.py --steps=library --base-directory $(build.sourcesDirectory)/multissl --openssl $(OPENSSL) --system Linux + displayName: 'python multissltests.py' + +- script: ./configure --with-pydebug + displayName: 'Configure CPython (debug)' + +- script: make -s -j4 + displayName: 'Build CPython' + +- script: make pythoninfo + displayName: 'Display build info' + +- script: make buildbottest TESTOPTS="-j4 -uall,-cpu" + displayName: 'Tests' diff --git a/.vsts/linux-coverage.yml b/.vsts/linux-coverage.yml new file mode 100644 index 000000000000..3657b1720ee2 --- /dev/null +++ b/.vsts/linux-coverage.yml @@ -0,0 +1,77 @@ +# Current docs for the syntax of this file are at: +# https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md + +name: $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.rr) + +queue: + name: Hosted Linux Preview + +trigger: + branches: + include: + - master + - 3.7 + - 3.6 + paths: + exclude: + - Doc/* + - Tools/* + +variables: + # Copy-pasted from linux-deps.yml until template support arrives + OPENSSL: 1.1.0g + OPENSSL_DIR: "$(build.sourcesDirectory)/multissl/openssl/$(OPENSSL)" + +steps: +- checkout: self + clean: true + fetchDepth: 5 + +#- template: linux-deps.yml + +# See https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted-templates.md +# For now, we copy/paste the steps +- script: echo "deb-src http://archive.ubuntu.com/ubuntu/ xenial main" > /etc/apt/sources.list.d/python.list && sudo apt-get update + displayName: 'Update apt-get lists' + +- script: echo ##vso[task.prependpath]$(OPENSSL_DIR) + displayName: 'Add $(OPENSSL_DIR) to PATH' +- script: > + sudo apt-get -yq install + build-essential + zlib1g-dev + libbz2-dev + liblzma-dev + libncurses5-dev + libreadline6-dev + libsqlite3-dev + libssl-dev + libgdbm-dev + tk-dev + lzma + lzma-dev + liblzma-dev + libffi-dev + uuid-dev + displayName: 'Install dependencies' +- script: python3 Tools/ssl/multissltests.py --steps=library --base-directory $(build.sourcesDirectory)/multissl --openssl $(OPENSSL) --system Linux + displayName: 'python multissltests.py' + + +- script: ./configure --with-pydebug + displayName: 'Configure CPython (debug)' + +- script: make -s -j4 + displayName: 'Build CPython' + +- script: ./python -m venv venv && ./venv/bin/python -m pip install -U coverage + displayName: 'Set up virtual environment' + +- script: ./venv/bin/python -m test.pythoninfo + displayName: 'Display build info' + +- script: ./venv/bin/python -m coverage run --pylib -m test --fail-env-changed -uall,-cpu -x test_multiprocessing_fork -x test_multiprocessing_forkserver -x test_multiprocessing_spawn -x test_concurrent_futures + displayName: 'Tests with coverage' + +- script: source ./venv/bin/activate && bash <(curl -s https://codecov.io/bash) + displayName: 'Publish code coverage results' diff --git a/.vsts/linux-deps.yml b/.vsts/linux-deps.yml new file mode 100644 index 000000000000..b6c8a3690ea1 --- /dev/null +++ b/.vsts/linux-deps.yml @@ -0,0 +1,36 @@ +# Note: this file is not currently used, but when template support comes to VSTS it +# will be referenced from the other scripts.. + +# Current docs for the syntax of this file are at: +# https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md + +parameters: + OPENSSL: 1.1.0g + OPENSSL_DIR: "$(build.sourcesDirectory)/multissl/openssl/$(OPENSSL)" + +steps: +- script: echo "deb-src http://archive.ubuntu.com/ubuntu/ xenial main" > /etc/apt/sources.list.d/python.list && sudo apt-get update + displayName: 'Update apt-get lists' + +- script: echo ##vso[task.prependpath]$(OPENSSL_DIR) + displayName: 'Add $(OPENSSL_DIR) to PATH' +- script: > + sudo apt-get -yq install + build-essential + zlib1g-dev + libbz2-dev + liblzma-dev + libncurses5-dev + libreadline6-dev + libsqlite3-dev + libssl-dev + libgdbm-dev + tk-dev + lzma + lzma-dev + liblzma-dev + libffi-dev + uuid-dev + displayName: 'Install dependencies' +- script: python3 Tools/ssl/multissltests.py --steps=library --base-directory $(build.sourcesDirectory)/multissl --openssl $(OPENSSL) --system Linux + displayName: 'python multissltests.py' diff --git a/.vsts/linux-pr.yml b/.vsts/linux-pr.yml new file mode 100644 index 000000000000..7f4d458f5a7c --- /dev/null +++ b/.vsts/linux-pr.yml @@ -0,0 +1,75 @@ +# Current docs for the syntax of this file are at: +# https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md + +name: $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.rr) + +queue: + name: Hosted Linux Preview + +trigger: + branches: + include: + - master + - 3.7 + - 3.6 + paths: + exclude: + - Doc/* + - Tools/* + +variables: + # Copy-pasted from linux-deps.yml until template support arrives + OPENSSL: 1.1.0g + OPENSSL_DIR: "$(build.sourcesDirectory)/multissl/openssl/$(OPENSSL)" + +steps: +- checkout: self + clean: true + fetchDepth: 5 + +#- template: linux-deps.yml + +# See https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted-templates.md +# For now, we copy/paste the steps +- script: echo "deb-src http://archive.ubuntu.com/ubuntu/ xenial main" > /etc/apt/sources.list.d/python.list && sudo apt-get update + displayName: 'Update apt-get lists' + +- script: echo ##vso[task.prependpath]$(OPENSSL_DIR) + displayName: 'Add $(OPENSSL_DIR) to PATH' +- script: > + sudo apt-get -yq install + build-essential + zlib1g-dev + libbz2-dev + liblzma-dev + libncurses5-dev + libreadline6-dev + libsqlite3-dev + libssl-dev + libgdbm-dev + tk-dev + lzma + lzma-dev + liblzma-dev + libffi-dev + uuid-dev + displayName: 'Install dependencies' +- script: python3 Tools/ssl/multissltests.py --steps=library --base-directory $(build.sourcesDirectory)/multissl --openssl $(OPENSSL) --system Linux + displayName: 'python multissltests.py' + + +- script: ./configure --with-pydebug + displayName: 'Configure CPython (debug)' + +- script: make -s -j4 + displayName: 'Build CPython' + +- script: make pythoninfo + displayName: 'Display build info' + +# Run patchcheck and fail if anything is discovered +- script: ./python Tools/scripts/patchcheck.py --travis true + displayName: 'Run patchcheck.py' + +- script: make buildbottest TESTOPTS="-j4 -uall,-cpu" + displayName: 'Tests' diff --git a/.vsts/macos-buildbot.yml b/.vsts/macos-buildbot.yml new file mode 100644 index 000000000000..8a4f6ba8cb8b --- /dev/null +++ b/.vsts/macos-buildbot.yml @@ -0,0 +1,37 @@ +# Current docs for the syntax of this file are at: +# https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md + +name: $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.rr) + +queue: + name: Hosted macOS Preview + +trigger: + branches: + include: + - master + - 3.7 + - 3.6 + paths: + exclude: + - Doc/* + - Tools/* + +#variables: + +steps: +- checkout: self + clean: true + fetchDepth: 5 + +- script: ./configure --with-pydebug --with-openssl=/usr/local/opt/openssl + displayName: 'Configure CPython (debug)' + +- script: make -s -j4 + displayName: 'Build CPython' + +- script: make pythoninfo + displayName: 'Display build info' + +- script: make buildbottest TESTOPTS="-j4 -uall,-cpu" + displayName: 'Tests' diff --git a/.vsts/macos-pr.yml b/.vsts/macos-pr.yml new file mode 100644 index 000000000000..8a4f6ba8cb8b --- /dev/null +++ b/.vsts/macos-pr.yml @@ -0,0 +1,37 @@ +# Current docs for the syntax of this file are at: +# https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md + +name: $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.rr) + +queue: + name: Hosted macOS Preview + +trigger: + branches: + include: + - master + - 3.7 + - 3.6 + paths: + exclude: + - Doc/* + - Tools/* + +#variables: + +steps: +- checkout: self + clean: true + fetchDepth: 5 + +- script: ./configure --with-pydebug --with-openssl=/usr/local/opt/openssl + displayName: 'Configure CPython (debug)' + +- script: make -s -j4 + displayName: 'Build CPython' + +- script: make pythoninfo + displayName: 'Display build info' + +- script: make buildbottest TESTOPTS="-j4 -uall,-cpu" + displayName: 'Tests' diff --git a/.vsts/windows-buildbot.yml b/.vsts/windows-buildbot.yml new file mode 100644 index 000000000000..5ec4522796ce --- /dev/null +++ b/.vsts/windows-buildbot.yml @@ -0,0 +1,49 @@ +# Current docs for the syntax of this file are at: +# https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md + +name: $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.rr) + +queue: + name: Hosted VS2017 + parallel: 2 + matrix: + amd64: + buildOpt: -p x64 + outDirSuffix: amd64 + win32: + buildOpt: + outDirSuffix: win32 + +trigger: + branches: + include: + - master + - 3.7 + - 3.6 + paths: + exclude: + - Doc/* + - Tools/* + +variables: + # Relocate build outputs outside of source directory to make cleaning faster + Py_IntDir: $(Build.BinariesDirectory)\obj + # UNDONE: Do not build to a different directory because of broken tests + Py_OutDir: $(Build.SourcesDirectory)\PCbuild + EXTERNAL_DIR: $(Build.BinariesDirectory)\externals + +steps: +- checkout: self + clean: true + fetchDepth: 5 + +- script: PCbuild\build.bat -e $(buildOpt) + displayName: 'Build CPython' + +- script: python.bat -m test.pythoninfo + displayName: 'Display build info' + +- script: PCbuild\rt.bat -q -uall -u-cpu -rwW --slowest --timeout=1200 -j0 + displayName: 'Tests' + env: + PREFIX: $(Py_OutDir)\$(outDirSuffix) diff --git a/.vsts/windows-pr.yml b/.vsts/windows-pr.yml new file mode 100644 index 000000000000..5ec4522796ce --- /dev/null +++ b/.vsts/windows-pr.yml @@ -0,0 +1,49 @@ +# Current docs for the syntax of this file are at: +# https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md + +name: $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.rr) + +queue: + name: Hosted VS2017 + parallel: 2 + matrix: + amd64: + buildOpt: -p x64 + outDirSuffix: amd64 + win32: + buildOpt: + outDirSuffix: win32 + +trigger: + branches: + include: + - master + - 3.7 + - 3.6 + paths: + exclude: + - Doc/* + - Tools/* + +variables: + # Relocate build outputs outside of source directory to make cleaning faster + Py_IntDir: $(Build.BinariesDirectory)\obj + # UNDONE: Do not build to a different directory because of broken tests + Py_OutDir: $(Build.SourcesDirectory)\PCbuild + EXTERNAL_DIR: $(Build.BinariesDirectory)\externals + +steps: +- checkout: self + clean: true + fetchDepth: 5 + +- script: PCbuild\build.bat -e $(buildOpt) + displayName: 'Build CPython' + +- script: python.bat -m test.pythoninfo + displayName: 'Display build info' + +- script: PCbuild\rt.bat -q -uall -u-cpu -rwW --slowest --timeout=1200 -j0 + displayName: 'Tests' + env: + PREFIX: $(Py_OutDir)\$(outDirSuffix) diff --git a/Doc/make.bat b/Doc/make.bat index 6cb315fda405..c69cfae31941 100644 --- a/Doc/make.bat +++ b/Doc/make.bat @@ -5,18 +5,21 @@ pushd %~dp0 set this=%~n0 -call ..\PCBuild\find_python.bat %PYTHON% -if not defined SPHINXBUILD if defined PYTHON ( +call ..\PCbuild\find_python.bat %PYTHON% + +if not defined PYTHON set PYTHON=py + +if not defined SPHINXBUILD ( %PYTHON% -c "import sphinx" > nul 2> nul if errorlevel 1 ( echo Installing sphinx with %PYTHON% - %PYTHON% -m pip install sphinx + %PYTHON% -m pip install sphinx python-docs-theme if errorlevel 1 exit /B ) set SPHINXBUILD=%PYTHON% -c "import sphinx, sys; sys.argv[0] = 'sphinx-build'; sphinx.main()" ) -if not defined BLURB if defined PYTHON ( +if not defined BLURB ( %PYTHON% -c "import blurb" > nul 2> nul if errorlevel 1 ( echo Installing blurb with %PYTHON% @@ -26,7 +29,6 @@ if not defined BLURB if defined PYTHON ( set BLURB=%PYTHON% -m blurb ) -if not defined PYTHON set PYTHON=py if not defined SPHINXBUILD set SPHINXBUILD=sphinx-build if not defined BLURB set BLURB=blurb diff --git a/Lib/tempfile.py b/Lib/tempfile.py index 38738082b996..2cb5434ba7b5 100644 --- a/Lib/tempfile.py +++ b/Lib/tempfile.py @@ -173,7 +173,9 @@ def _candidate_tempdir_list(): # Failing that, try OS-specific locations. if _os.name == 'nt': - dirlist.extend([ r'c:\temp', r'c:\tmp', r'\temp', r'\tmp' ]) + dirlist.extend([ _os.path.expanduser(r'~\AppData\Local\Temp'), + _os.path.expandvars(r'%SYSTEMROOT%\Temp'), + r'c:\temp', r'c:\tmp', r'\temp', r'\tmp' ]) else: dirlist.extend([ '/tmp', '/var/tmp', '/usr/tmp' ]) diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 867124b63e24..e46394e89d1f 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -366,6 +366,20 @@ def _rmtree_inner(path): _force_run(fullname, os.unlink, fullname) _waitfor(_rmtree_inner, path, waitall=True) _waitfor(lambda p: _force_run(p, os.rmdir, p), path) + + def _longpath(path): + try: + import ctypes + except ImportError: + # No ctypes means we can't expands paths. + pass + else: + buffer = ctypes.create_unicode_buffer(len(path) * 2) + length = ctypes.windll.kernel32.GetLongPathNameW(path, buffer, + len(buffer)) + if length: + return buffer[:length] + return path else: _unlink = os.unlink _rmdir = os.rmdir @@ -392,6 +406,9 @@ def _rmtree_inner(path): _rmtree_inner(path) os.rmdir(path) + def _longpath(path): + return path + def unlink(filename): try: _unlink(filename) @@ -2333,13 +2350,15 @@ def can_xattr(): if not hasattr(os, "setxattr"): can = False else: - tmp_fp, tmp_name = tempfile.mkstemp() + tmp_dir = tempfile.mkdtemp() + tmp_fp, tmp_name = tempfile.mkstemp(dir=tmp_dir) try: with open(TESTFN, "wb") as fp: try: # TESTFN & tempfile may use different file systems with # different capabilities os.setxattr(tmp_fp, b"user.test", b"") + os.setxattr(tmp_name, b"trusted.foo", b"42") os.setxattr(fp.fileno(), b"user.test", b"") # Kernels < 2.6.39 don't respect setxattr flags. kernel_version = platform.release() @@ -2350,6 +2369,7 @@ def can_xattr(): finally: unlink(TESTFN) unlink(tmp_name) + rmdir(tmp_dir) _can_xattr = can return can diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index 830f0d84a9d4..42c0707e8f21 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -1750,5 +1750,6 @@ def runner(loop): outer_loop.close() + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_bdb.py b/Lib/test/test_bdb.py index abefe6c4e57a..a36667869718 100644 --- a/Lib/test/test_bdb.py +++ b/Lib/test/test_bdb.py @@ -417,15 +417,17 @@ def __init__(self, test_case, skip=None): self.dry_run = test_case.dry_run self.tracer = Tracer(test_case.expect_set, skip=skip, dry_run=self.dry_run, test_case=test_case.id()) + self._original_tracer = None def __enter__(self): # test_pdb does not reset Breakpoint class attributes on exit :-( reset_Breakpoint() + self._original_tracer = sys.gettrace() return self.tracer def __exit__(self, type_=None, value=None, traceback=None): reset_Breakpoint() - sys.settrace(None) + sys.settrace(self._original_tracer) not_empty = '' if self.tracer.set_list: diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py index db53a8f202dc..bf9467e96e09 100644 --- a/Lib/test/test_pathlib.py +++ b/Lib/test/test_pathlib.py @@ -1531,7 +1531,7 @@ def test_resolve_common(self): # resolves to 'dirB/..' first before resolving to parent of dirB. self._check_resolve_relative(p, P(BASE, 'foo', 'in', 'spam'), False) # Now create absolute symlinks - d = tempfile.mkdtemp(suffix='-dirD') + d = support._longpath(tempfile.mkdtemp(suffix='-dirD')) self.addCleanup(support.rmtree, d) os.symlink(os.path.join(d), join('dirA', 'linkX')) os.symlink(join('dirB'), os.path.join(d, 'linkY')) diff --git a/Lib/test/test_poplib.py b/Lib/test/test_poplib.py index ca9bc6217509..234c855545c2 100644 --- a/Lib/test/test_poplib.py +++ b/Lib/test/test_poplib.py @@ -217,11 +217,12 @@ def start(self): def run(self): self.active = True self.__flag.set() - while self.active and asyncore.socket_map: - self.active_lock.acquire() - asyncore.loop(timeout=0.1, count=1) - self.active_lock.release() - asyncore.close_all(ignore_all=True) + try: + while self.active and asyncore.socket_map: + with self.active_lock: + asyncore.loop(timeout=0.1, count=1) + finally: + asyncore.close_all(ignore_all=True) def stop(self): assert self.active diff --git a/Lib/test/test_selectors.py b/Lib/test/test_selectors.py index 852b2feb45fd..14ce91f3768c 100644 --- a/Lib/test/test_selectors.py +++ b/Lib/test/test_selectors.py @@ -450,7 +450,14 @@ def test_above_fd_setsize(self): self.skipTest("FD limit reached") raise - self.assertEqual(NUM_FDS // 2, len(s.select())) + try: + fds = s.select() + except OSError as e: + if e.errno == errno.EINVAL and sys.platform == 'darwin': + # unexplainable errors on macOS don't need to fail the test + self.skipTest("Invalid argument error calling poll()") + raise + self.assertEqual(NUM_FDS // 2, len(fds)) class DefaultSelectorTestCase(BaseSelectorTestCase): diff --git a/Misc/NEWS.d/next/Build/2018-05-15-12-44-50.bpo-33522.mJoNcA.rst b/Misc/NEWS.d/next/Build/2018-05-15-12-44-50.bpo-33522.mJoNcA.rst new file mode 100644 index 000000000000..f44862f0c454 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2018-05-15-12-44-50.bpo-33522.mJoNcA.rst @@ -0,0 +1,2 @@ +Enable CI builds on Visual Studio Team Services at +https://python.visualstudio.com/cpython diff --git a/Misc/NEWS.d/next/Library/2018-05-16-17-05-48.bpo-33548.xWslmx.rst b/Misc/NEWS.d/next/Library/2018-05-16-17-05-48.bpo-33548.xWslmx.rst new file mode 100644 index 000000000000..65585c152987 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-16-17-05-48.bpo-33548.xWslmx.rst @@ -0,0 +1 @@ +tempfile._candidate_tempdir_list should consider common TEMP locations diff --git a/PCbuild/rt.bat b/PCbuild/rt.bat index 808102f826d3..212befc95b06 100644 --- a/PCbuild/rt.bat +++ b/PCbuild/rt.bat @@ -7,7 +7,7 @@ rem -q "quick" -- normally the tests are run twice, the first time rem after deleting all the .pyc files reachable from Lib/. rem -q runs the tests just once, and without deleting .pyc files. rem -x64 Run the 64-bit build of python (or python_d if -d was specified) -rem from the 'amd64' dir instead of the 32-bit build in this dir. +rem When omitted, uses %PREFIX% if set or the 32-bit build rem All leading instances of these switches are shifted off, and rem whatever remains (up to 9 arguments) is passed to regrtest.py. rem For example, @@ -28,28 +28,29 @@ rem rt -u "network,largefile" setlocal set pcbuild=%~dp0 -set prefix=%pcbuild%win32\ set suffix= set qmode= set dashO= set regrtestargs= +set exe= :CheckOpts if "%1"=="-O" (set dashO=-O) & shift & goto CheckOpts if "%1"=="-q" (set qmode=yes) & shift & goto CheckOpts if "%1"=="-d" (set suffix=_d) & shift & goto CheckOpts -if "%1"=="-x64" (set prefix=%pcbuild%amd64\) & shift & goto CheckOpts +if "%1"=="-x64" (set prefix=%pcbuild%amd64) & shift & goto CheckOpts if NOT "%1"=="" (set regrtestargs=%regrtestargs% %1) & shift & goto CheckOpts -set exe=%prefix%python%suffix%.exe -set cmd="%exe%" %dashO% -Wd -E -bb -m test %regrtestargs% +if not defined prefix set prefix=%pcbuild%win32 +set exe=%prefix%\python%suffix%.exe +set cmd="%exe%" %dashO% -u -Wd -E -bb -m test %regrtestargs% if defined qmode goto Qmode echo Deleting .pyc files ... "%exe%" "%pcbuild%rmpyc.py" echo Cleaning _pth files ... -if exist %prefix%*._pth del %prefix%*._pth +if exist %prefix%\*._pth del %prefix%\*._pth echo on %cmd% diff --git a/Tools/ssl/multissltests.py b/Tools/ssl/multissltests.py index ba4529ae0611..f3241cd6071c 100755 --- a/Tools/ssl/multissltests.py +++ b/Tools/ssl/multissltests.py @@ -123,6 +123,11 @@ action='store_true', help="Don't run tests, only compile _ssl.c and _hashopenssl.c." ) +parser.add_argument( + '--system', + default='', + help="Override the automatic system type detection." +) class AbstractBuilder(object): @@ -150,6 +155,7 @@ def __init__(self, version, compile_args=(), # build directory (removed after install) self.build_dir = os.path.join( self.src_dir, self.build_template.format(version)) + self.system = args.system def __str__(self): return "<{0.__class__.__name__} for {0.version}>".format(self) @@ -254,9 +260,13 @@ def _build_src(self): cwd = self.build_dir cmd = ["./config", "shared", "--prefix={}".format(self.install_dir)] cmd.extend(self.compile_args) - self._subprocess_call(cmd, cwd=cwd) + env = None + if self.system: + env = os.environ.copy() + env['SYSTEM'] = self.system + self._subprocess_call(cmd, cwd=cwd, env=env) # Old OpenSSL versions do not support parallel builds. - self._subprocess_call(["make", "-j1"], cwd=cwd) + self._subprocess_call(["make", "-j1"], cwd=cwd, env=env) def _make_install(self, remove=True): self._subprocess_call(["make", "-j1", "install"], cwd=self.build_dir) From webhook-mailer at python.org Thu May 17 10:27:19 2018 From: webhook-mailer at python.org (Eric Snow) Date: Thu, 17 May 2018 14:27:19 -0000 Subject: [Python-checkins] bpo-32604: Implement force-closing channels. (gh-6937) Message-ID: <mailman.111.1526567240.2757.python-checkins@python.org> https://github.com/python/cpython/commit/3ab0136ac5d6059ce96d4debca89c5f5ab0356f5 commit: 3ab0136ac5d6059ce96d4debca89c5f5ab0356f5 branch: master author: Eric Snow <ericsnowcurrently at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-17T10:27:09-04:00 summary: bpo-32604: Implement force-closing channels. (gh-6937) This will make it easier to clean up channels (e.g. when used in tests). files: M Lib/test/test__xxsubinterpreters.py M Modules/_xxsubinterpretersmodule.c diff --git a/Lib/test/test__xxsubinterpreters.py b/Lib/test/test__xxsubinterpreters.py index 118f2e4895fe..f66cc9516926 100644 --- a/Lib/test/test__xxsubinterpreters.py +++ b/Lib/test/test__xxsubinterpreters.py @@ -1379,12 +1379,104 @@ def test_close_multiple_times(self): with self.assertRaises(interpreters.ChannelClosedError): interpreters.channel_close(cid) - def test_close_with_unused_items(self): + def test_close_empty(self): + tests = [ + (False, False), + (True, False), + (False, True), + (True, True), + ] + for send, recv in tests: + with self.subTest((send, recv)): + cid = interpreters.channel_create() + interpreters.channel_send(cid, b'spam') + interpreters.channel_recv(cid) + interpreters.channel_close(cid, send=send, recv=recv) + + with self.assertRaises(interpreters.ChannelClosedError): + interpreters.channel_send(cid, b'eggs') + with self.assertRaises(interpreters.ChannelClosedError): + interpreters.channel_recv(cid) + + def test_close_defaults_with_unused_items(self): + cid = interpreters.channel_create() + interpreters.channel_send(cid, b'spam') + interpreters.channel_send(cid, b'ham') + + with self.assertRaises(interpreters.ChannelNotEmptyError): + interpreters.channel_close(cid) + interpreters.channel_recv(cid) + interpreters.channel_send(cid, b'eggs') + + def test_close_recv_with_unused_items_unforced(self): cid = interpreters.channel_create() interpreters.channel_send(cid, b'spam') interpreters.channel_send(cid, b'ham') - interpreters.channel_close(cid) + + with self.assertRaises(interpreters.ChannelNotEmptyError): + interpreters.channel_close(cid, recv=True) + interpreters.channel_recv(cid) + interpreters.channel_send(cid, b'eggs') + interpreters.channel_recv(cid) + interpreters.channel_recv(cid) + interpreters.channel_close(cid, recv=True) + + def test_close_send_with_unused_items_unforced(self): + cid = interpreters.channel_create() + interpreters.channel_send(cid, b'spam') + interpreters.channel_send(cid, b'ham') + interpreters.channel_close(cid, send=True) + with self.assertRaises(interpreters.ChannelClosedError): + interpreters.channel_send(cid, b'eggs') + interpreters.channel_recv(cid) + interpreters.channel_recv(cid) + with self.assertRaises(interpreters.ChannelClosedError): + interpreters.channel_recv(cid) + + def test_close_both_with_unused_items_unforced(self): + cid = interpreters.channel_create() + interpreters.channel_send(cid, b'spam') + interpreters.channel_send(cid, b'ham') + + with self.assertRaises(interpreters.ChannelNotEmptyError): + interpreters.channel_close(cid, recv=True, send=True) + interpreters.channel_recv(cid) + interpreters.channel_send(cid, b'eggs') + interpreters.channel_recv(cid) + interpreters.channel_recv(cid) + interpreters.channel_close(cid, recv=True) + + def test_close_recv_with_unused_items_forced(self): + cid = interpreters.channel_create() + interpreters.channel_send(cid, b'spam') + interpreters.channel_send(cid, b'ham') + interpreters.channel_close(cid, recv=True, force=True) + + with self.assertRaises(interpreters.ChannelClosedError): + interpreters.channel_send(cid, b'eggs') + with self.assertRaises(interpreters.ChannelClosedError): + interpreters.channel_recv(cid) + + def test_close_send_with_unused_items_forced(self): + cid = interpreters.channel_create() + interpreters.channel_send(cid, b'spam') + interpreters.channel_send(cid, b'ham') + interpreters.channel_close(cid, send=True, force=True) + + with self.assertRaises(interpreters.ChannelClosedError): + interpreters.channel_send(cid, b'eggs') + with self.assertRaises(interpreters.ChannelClosedError): + interpreters.channel_recv(cid) + + def test_close_both_with_unused_items_forced(self): + cid = interpreters.channel_create() + interpreters.channel_send(cid, b'spam') + interpreters.channel_send(cid, b'ham') + interpreters.channel_close(cid, send=True, recv=True, force=True) + + with self.assertRaises(interpreters.ChannelClosedError): + interpreters.channel_send(cid, b'eggs') with self.assertRaises(interpreters.ChannelClosedError): interpreters.channel_recv(cid) @@ -1403,7 +1495,7 @@ def test_close_by_unassociated_interp(self): interp = interpreters.create() interpreters.run_string(interp, dedent(f""" import _xxsubinterpreters as _interpreters - _interpreters.channel_close({cid}) + _interpreters.channel_close({cid}, force=True) """)) with self.assertRaises(interpreters.ChannelClosedError): interpreters.channel_recv(cid) @@ -1416,7 +1508,7 @@ def test_close_used_multiple_times_by_single_user(self): interpreters.channel_send(cid, b'spam') interpreters.channel_send(cid, b'spam') interpreters.channel_recv(cid) - interpreters.channel_close(cid) + interpreters.channel_close(cid, force=True) with self.assertRaises(interpreters.ChannelClosedError): interpreters.channel_send(cid, b'eggs') diff --git a/Modules/_xxsubinterpretersmodule.c b/Modules/_xxsubinterpretersmodule.c index 5184f6593db1..72387d8da56b 100644 --- a/Modules/_xxsubinterpretersmodule.c +++ b/Modules/_xxsubinterpretersmodule.c @@ -306,10 +306,15 @@ _sharedexception_apply(_sharedexception *exc, PyObject *wrapperclass) /* channel-specific code ****************************************************/ +#define CHANNEL_SEND 1 +#define CHANNEL_BOTH 0 +#define CHANNEL_RECV -1 + static PyObject *ChannelError; static PyObject *ChannelNotFoundError; static PyObject *ChannelClosedError; static PyObject *ChannelEmptyError; +static PyObject *ChannelNotEmptyError; static int channel_exceptions_init(PyObject *ns) @@ -356,6 +361,16 @@ channel_exceptions_init(PyObject *ns) return -1; } + // An operation tried to close a non-empty channel. + ChannelNotEmptyError = PyErr_NewException( + "_xxsubinterpreters.ChannelNotEmptyError", ChannelError, NULL); + if (ChannelNotEmptyError == NULL) { + return -1; + } + if (PyDict_SetItemString(ns, "ChannelNotEmptyError", ChannelNotEmptyError) != 0) { + return -1; + } + return 0; } @@ -696,8 +711,11 @@ _channelends_close_interpreter(_channelends *ends, int64_t interp, int which) } static void -_channelends_close_all(_channelends *ends) +_channelends_close_all(_channelends *ends, int which, int force) { + // XXX Handle the ends. + // XXX Handle force is True. + // Ensure all the "send"-associated interpreters are closed. _channelend *end; for (end = ends->send; end != NULL; end = end->next) { @@ -713,12 +731,16 @@ _channelends_close_all(_channelends *ends) /* channels */ struct _channel; +struct _channel_closing; +static void _channel_clear_closing(struct _channel *); +static void _channel_finish_closing(struct _channel *); typedef struct _channel { PyThread_type_lock mutex; _channelqueue *queue; _channelends *ends; int open; + struct _channel_closing *closing; } _PyChannelState; static _PyChannelState * @@ -747,12 +769,14 @@ _channel_new(void) return NULL; } chan->open = 1; + chan->closing = NULL; return chan; } static void _channel_free(_PyChannelState *chan) { + _channel_clear_closing(chan); PyThread_acquire_lock(chan->mutex, WAIT_LOCK); _channelqueue_free(chan->queue); _channelends_free(chan->ends); @@ -802,13 +826,20 @@ _channel_next(_PyChannelState *chan, int64_t interp) } data = _channelqueue_get(chan->queue); + if (data == NULL && !PyErr_Occurred() && chan->closing != NULL) { + chan->open = 0; + } + done: PyThread_release_lock(chan->mutex); + if (chan->queue->count == 0) { + _channel_finish_closing(chan); + } return data; } static int -_channel_close_interpreter(_PyChannelState *chan, int64_t interp, int which) +_channel_close_interpreter(_PyChannelState *chan, int64_t interp, int end) { PyThread_acquire_lock(chan->mutex, WAIT_LOCK); @@ -818,7 +849,7 @@ _channel_close_interpreter(_PyChannelState *chan, int64_t interp, int which) goto done; } - if (_channelends_close_interpreter(chan->ends, interp, which) != 0) { + if (_channelends_close_interpreter(chan->ends, interp, end) != 0) { goto done; } chan->open = _channelends_is_open(chan->ends); @@ -830,7 +861,7 @@ _channel_close_interpreter(_PyChannelState *chan, int64_t interp, int which) } static int -_channel_close_all(_PyChannelState *chan) +_channel_close_all(_PyChannelState *chan, int end, int force) { int res = -1; PyThread_acquire_lock(chan->mutex, WAIT_LOCK); @@ -840,11 +871,17 @@ _channel_close_all(_PyChannelState *chan) goto done; } + if (!force && chan->queue->count > 0) { + PyErr_SetString(ChannelNotEmptyError, + "may not be closed if not empty (try force=True)"); + goto done; + } + chan->open = 0; // We *could* also just leave these in place, since we've marked // the channel as closed already. - _channelends_close_all(chan->ends); + _channelends_close_all(chan->ends, end, force); res = 0; done: @@ -889,6 +926,9 @@ _channelref_new(int64_t id, _PyChannelState *chan) static void _channelref_free(_channelref *ref) { + if (ref->chan != NULL) { + _channel_clear_closing(ref->chan); + } //_channelref_clear(ref); PyMem_Free(ref); } @@ -1009,8 +1049,12 @@ _channels_add(_channels *channels, _PyChannelState *chan) return cid; } +/* forward */ +static int _channel_set_closing(struct _channelref *, PyThread_type_lock); + static int -_channels_close(_channels *channels, int64_t cid, _PyChannelState **pchan) +_channels_close(_channels *channels, int64_t cid, _PyChannelState **pchan, + int end, int force) { int res = -1; PyThread_acquire_lock(channels->mutex, WAIT_LOCK); @@ -1028,14 +1072,35 @@ _channels_close(_channels *channels, int64_t cid, _PyChannelState **pchan) PyErr_Format(ChannelClosedError, "channel %d closed", cid); goto done; } + else if (!force && end == CHANNEL_SEND && ref->chan->closing != NULL) { + PyErr_Format(ChannelClosedError, "channel %d closed", cid); + goto done; + } else { - if (_channel_close_all(ref->chan) != 0) { + if (_channel_close_all(ref->chan, end, force) != 0) { + if (end == CHANNEL_SEND && + PyErr_ExceptionMatches(ChannelNotEmptyError)) { + if (ref->chan->closing != NULL) { + PyErr_Format(ChannelClosedError, "channel %d closed", cid); + goto done; + } + // Mark the channel as closing and return. The channel + // will be cleaned up in _channel_next(). + PyErr_Clear(); + if (_channel_set_closing(ref, channels->mutex) != 0) { + goto done; + } + if (pchan != NULL) { + *pchan = ref->chan; + } + res = 0; + } goto done; } if (pchan != NULL) { *pchan = ref->chan; } - else { + else { _channel_free(ref->chan); } ref->chan = NULL; @@ -1161,6 +1226,60 @@ _channels_list_all(_channels *channels, int64_t *count) return cids; } +/* support for closing non-empty channels */ + +struct _channel_closing { + struct _channelref *ref; +}; + +static int +_channel_set_closing(struct _channelref *ref, PyThread_type_lock mutex) { + struct _channel *chan = ref->chan; + if (chan == NULL) { + // already closed + return 0; + } + int res = -1; + PyThread_acquire_lock(chan->mutex, WAIT_LOCK); + if (chan->closing != NULL) { + PyErr_SetString(ChannelClosedError, "channel closed"); + goto done; + } + chan->closing = PyMem_NEW(struct _channel_closing, 1); + if (chan->closing == NULL) { + goto done; + } + chan->closing->ref = ref; + + res = 0; +done: + PyThread_release_lock(chan->mutex); + return res; +} + +static void +_channel_clear_closing(struct _channel *chan) { + PyThread_acquire_lock(chan->mutex, WAIT_LOCK); + if (chan->closing != NULL) { + PyMem_Free(chan->closing); + chan->closing = NULL; + } + PyThread_release_lock(chan->mutex); +} + +static void +_channel_finish_closing(struct _channel *chan) { + struct _channel_closing *closing = chan->closing; + if (closing == NULL) { + return; + } + _channelref *ref = closing->ref; + _channel_clear_closing(chan); + // Do the things that would have been done in _channels_close(). + ref->chan = NULL; + _channel_free(chan); +}; + /* "high"-level channel-related functions */ static int64_t @@ -1207,6 +1326,12 @@ _channel_send(_channels *channels, int64_t id, PyObject *obj) } // Past this point we are responsible for releasing the mutex. + if (chan->closing != NULL) { + PyErr_Format(ChannelClosedError, "channel %d closed", id); + PyThread_release_lock(mutex); + return -1; + } + // Convert the object to cross-interpreter data. _PyCrossInterpreterData *data = PyMem_NEW(_PyCrossInterpreterData, 1); if (data == NULL) { @@ -1290,16 +1415,13 @@ _channel_drop(_channels *channels, int64_t id, int send, int recv) } static int -_channel_close(_channels *channels, int64_t id) +_channel_close(_channels *channels, int64_t id, int end, int force) { - return _channels_close(channels, id, NULL); + return _channels_close(channels, id, NULL, end, force); } /* ChannelID class */ -#define CHANNEL_SEND 1 -#define CHANNEL_RECV -1 - static PyTypeObject ChannelIDtype; typedef struct channelid { @@ -2555,15 +2677,8 @@ channel_close(PyObject *self, PyObject *args, PyObject *kwds) if (cid < 0) { return NULL; } - if (send == 0 && recv == 0) { - send = 1; - recv = 1; - } - - // XXX Handle the ends. - // XXX Handle force is True. - if (_channel_close(&_globals.channels, cid) != 0) { + if (_channel_close(&_globals.channels, cid, send-recv, force) != 0) { return NULL; } Py_RETURN_NONE; From webhook-mailer at python.org Thu May 17 11:08:48 2018 From: webhook-mailer at python.org (Gregory P. Smith) Date: Thu, 17 May 2018 15:08:48 -0000 Subject: [Python-checkins] bpo-19950: Clarify unittest TestCase instance use. (GH-6875) Message-ID: <mailman.112.1526569730.2757.python-checkins@python.org> https://github.com/python/cpython/commit/dff46758f267ad6c13096c69c4e1dee17f9969aa commit: dff46758f267ad6c13096c69c4e1dee17f9969aa branch: master author: Gregory P. Smith <greg at krypto.org> committer: GitHub <noreply at github.com> date: 2018-05-17T10:08:45-05:00 summary: bpo-19950: Clarify unittest TestCase instance use. (GH-6875) files: M Doc/library/unittest.rst diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst index af71be40b89f..086d93782562 100644 --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -361,8 +361,9 @@ testing code:: Note that in order to test something, we use one of the :meth:`assert\*` methods provided by the :class:`TestCase` base class. If the test fails, an -exception will be raised, and :mod:`unittest` will identify the test case as a -:dfn:`failure`. Any other exceptions will be treated as :dfn:`errors`. +exception will be raised with an explanatory message, and :mod:`unittest` +will identify the test case as a :dfn:`failure`. Any other exceptions will be +treated as :dfn:`errors`. Tests can be numerous, and their set-up can be repetitive. Luckily, we can factor out set-up code by implementing a method called @@ -408,13 +409,18 @@ after the test method has been run:: If :meth:`~TestCase.setUp` succeeded, :meth:`~TestCase.tearDown` will be run whether the test method succeeded or not. -Such a working environment for the testing code is called a :dfn:`fixture`. - -Test case instances are grouped together according to the features they test. -:mod:`unittest` provides a mechanism for this: the :dfn:`test suite`, -represented by :mod:`unittest`'s :class:`TestSuite` class. In most cases, -calling :func:`unittest.main` will do the right thing and collect all the -module's test cases for you, and then execute them. +Such a working environment for the testing code is called a +:dfn:`test fixture`. A new TestCase instance is created as a unique +test fixture used to execute each individual test method. Thus +`~TestCase.setUp`, `~TestCase.tearDown`, and `~TestCase.__init__` +will be called once per test. + +It is recommended that you use TestCase implementations to group tests together +according to the features they test. :mod:`unittest` provides a mechanism for +this: the :dfn:`test suite`, represented by :mod:`unittest`'s +:class:`TestSuite` class. In most cases, calling :func:`unittest.main` will do +the right thing and collect all the module's test cases for you and execute +them. However, should you want to customize the building of your test suite, you can do it yourself:: From webhook-mailer at python.org Thu May 17 11:41:56 2018 From: webhook-mailer at python.org (Barry Warsaw) Date: Thu, 17 May 2018 15:41:56 -0000 Subject: [Python-checkins] bpo-33537: Add an __all__ to importlib.resources (#6920) Message-ID: <mailman.113.1526571718.2757.python-checkins@python.org> https://github.com/python/cpython/commit/0ed66df5242138fc599b4735749e55f953d9a1e4 commit: 0ed66df5242138fc599b4735749e55f953d9a1e4 branch: master author: Barry Warsaw <barry at python.org> committer: GitHub <noreply at github.com> date: 2018-05-17T11:41:53-04:00 summary: bpo-33537: Add an __all__ to importlib.resources (#6920) files: M Lib/importlib/resources.py diff --git a/Lib/importlib/resources.py b/Lib/importlib/resources.py index 4d70186c1a43..cbefdd540e9e 100644 --- a/Lib/importlib/resources.py +++ b/Lib/importlib/resources.py @@ -2,7 +2,6 @@ import tempfile from . import abc as resources_abc -from builtins import open as builtins_open from contextlib import contextmanager, suppress from importlib import import_module from importlib.abc import ResourceLoader @@ -15,6 +14,19 @@ from zipimport import ZipImportError +__all__ = [ + 'Package', + 'Resource', + 'contents', + 'is_resource', + 'open_binary', + 'open_text', + 'path', + 'read_binary', + 'read_text', + ] + + Package = Union[str, ModuleType] Resource = Union[str, os.PathLike] @@ -82,7 +94,7 @@ def open_binary(package: Package, resource: Resource) -> BinaryIO: package_path = os.path.dirname(absolute_package_path) full_path = os.path.join(package_path, resource) try: - return builtins_open(full_path, mode='rb') + return open(full_path, mode='rb') except OSError: # Just assume the loader is a resource loader; all the relevant # importlib.machinery loaders are and an AttributeError for @@ -116,8 +128,7 @@ def open_text(package: Package, package_path = os.path.dirname(absolute_package_path) full_path = os.path.join(package_path, resource) try: - return builtins_open( - full_path, mode='r', encoding=encoding, errors=errors) + return open(full_path, mode='r', encoding=encoding, errors=errors) except OSError: # Just assume the loader is a resource loader; all the relevant # importlib.machinery loaders are and an AttributeError for @@ -248,10 +259,10 @@ def contents(package: Package) -> Iterable[str]: return os.listdir(package_directory) -# Private implementation of ResourceReader and get_resource_reader() for -# zipimport. Don't use these directly! We're implementing these in Python -# because 1) it's easier, 2) zipimport will likely get rewritten in Python -# itself at some point, so doing this all in C would just be a waste of +# Private implementation of ResourceReader and get_resource_reader() called +# from zipimport.c. Don't use these directly! We're implementing these in +# Python because 1) it's easier, 2) zipimport may get rewritten in Python +# itself at some point, so doing this all in C would difficult and a waste of # effort. class _ZipImportResourceReader(resources_abc.ResourceReader): @@ -322,6 +333,7 @@ def contents(self): yield parent_name +# Called from zipimport.c def _zipimport_get_resource_reader(zipimporter, fullname): try: if not zipimporter.is_package(fullname): From webhook-mailer at python.org Thu May 17 11:54:11 2018 From: webhook-mailer at python.org (Barry Warsaw) Date: Thu, 17 May 2018 15:54:11 -0000 Subject: [Python-checkins] Provide a little better debug output (#6940) Message-ID: <mailman.114.1526572451.2757.python-checkins@python.org> https://github.com/python/cpython/commit/273f51f5ca9dd0420d327c95281b24078f8feeef commit: 273f51f5ca9dd0420d327c95281b24078f8feeef branch: master author: Barry Warsaw <barry at python.org> committer: GitHub <noreply at github.com> date: 2018-05-17T11:54:01-04:00 summary: Provide a little better debug output (#6940) files: M Lib/test/test_socket.py diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index 44501d922ad3..f377ebcb27b2 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -893,7 +893,7 @@ def test_host_resolution_bad_address(self): ) for addr in ['0.1.1.~1', '1+.1.1.1', '::1q', '::1::2', '1:1:1:1:1:1:1:1:1']: - with self.assertRaises(OSError): + with self.assertRaises(OSError, msg=addr): socket.gethostbyname(addr) with self.assertRaises(OSError, msg=explanation): socket.gethostbyaddr(addr) From webhook-mailer at python.org Thu May 17 12:27:52 2018 From: webhook-mailer at python.org (Barry Warsaw) Date: Thu, 17 May 2018 16:27:52 -0000 Subject: [Python-checkins] bpo-33537: Add an __all__ to importlib.resources (GH-6920) (#6941) Message-ID: <mailman.115.1526574474.2757.python-checkins@python.org> https://github.com/python/cpython/commit/6417d33633a3979d996015e52e4ff6c7a88e93e5 commit: 6417d33633a3979d996015e52e4ff6c7a88e93e5 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Barry Warsaw <barry at python.org> date: 2018-05-17T12:27:49-04:00 summary: bpo-33537: Add an __all__ to importlib.resources (GH-6920) (#6941) (cherry picked from commit 0ed66df5242138fc599b4735749e55f953d9a1e4) Co-authored-by: Barry Warsaw <barry at python.org> files: M Lib/importlib/resources.py diff --git a/Lib/importlib/resources.py b/Lib/importlib/resources.py index 4d70186c1a43..cbefdd540e9e 100644 --- a/Lib/importlib/resources.py +++ b/Lib/importlib/resources.py @@ -2,7 +2,6 @@ import tempfile from . import abc as resources_abc -from builtins import open as builtins_open from contextlib import contextmanager, suppress from importlib import import_module from importlib.abc import ResourceLoader @@ -15,6 +14,19 @@ from zipimport import ZipImportError +__all__ = [ + 'Package', + 'Resource', + 'contents', + 'is_resource', + 'open_binary', + 'open_text', + 'path', + 'read_binary', + 'read_text', + ] + + Package = Union[str, ModuleType] Resource = Union[str, os.PathLike] @@ -82,7 +94,7 @@ def open_binary(package: Package, resource: Resource) -> BinaryIO: package_path = os.path.dirname(absolute_package_path) full_path = os.path.join(package_path, resource) try: - return builtins_open(full_path, mode='rb') + return open(full_path, mode='rb') except OSError: # Just assume the loader is a resource loader; all the relevant # importlib.machinery loaders are and an AttributeError for @@ -116,8 +128,7 @@ def open_text(package: Package, package_path = os.path.dirname(absolute_package_path) full_path = os.path.join(package_path, resource) try: - return builtins_open( - full_path, mode='r', encoding=encoding, errors=errors) + return open(full_path, mode='r', encoding=encoding, errors=errors) except OSError: # Just assume the loader is a resource loader; all the relevant # importlib.machinery loaders are and an AttributeError for @@ -248,10 +259,10 @@ def contents(package: Package) -> Iterable[str]: return os.listdir(package_directory) -# Private implementation of ResourceReader and get_resource_reader() for -# zipimport. Don't use these directly! We're implementing these in Python -# because 1) it's easier, 2) zipimport will likely get rewritten in Python -# itself at some point, so doing this all in C would just be a waste of +# Private implementation of ResourceReader and get_resource_reader() called +# from zipimport.c. Don't use these directly! We're implementing these in +# Python because 1) it's easier, 2) zipimport may get rewritten in Python +# itself at some point, so doing this all in C would difficult and a waste of # effort. class _ZipImportResourceReader(resources_abc.ResourceReader): @@ -322,6 +333,7 @@ def contents(self): yield parent_name +# Called from zipimport.c def _zipimport_get_resource_reader(zipimporter, fullname): try: if not zipimporter.is_package(fullname): From webhook-mailer at python.org Thu May 17 12:53:29 2018 From: webhook-mailer at python.org (Barry Warsaw) Date: Thu, 17 May 2018 16:53:29 -0000 Subject: [Python-checkins] Provide a little better debug output (GH-6940) (#6942) Message-ID: <mailman.116.1526576010.2757.python-checkins@python.org> https://github.com/python/cpython/commit/56882db4f7e7ee14ed37d5234c8a06a5a50a7593 commit: 56882db4f7e7ee14ed37d5234c8a06a5a50a7593 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Barry Warsaw <barry at python.org> date: 2018-05-17T12:53:24-04:00 summary: Provide a little better debug output (GH-6940) (#6942) (cherry picked from commit 273f51f5ca9dd0420d327c95281b24078f8feeef) Co-authored-by: Barry Warsaw <barry at python.org> files: M Lib/test/test_socket.py diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index 44501d922ad3..f377ebcb27b2 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -893,7 +893,7 @@ def test_host_resolution_bad_address(self): ) for addr in ['0.1.1.~1', '1+.1.1.1', '::1q', '::1::2', '1:1:1:1:1:1:1:1:1']: - with self.assertRaises(OSError): + with self.assertRaises(OSError, msg=addr): socket.gethostbyname(addr) with self.assertRaises(OSError, msg=explanation): socket.gethostbyaddr(addr) From webhook-mailer at python.org Thu May 17 13:38:21 2018 From: webhook-mailer at python.org (Steve Dower) Date: Thu, 17 May 2018 17:38:21 -0000 Subject: [Python-checkins] Only upload docs for CI build and not pull requests (GH-6945) Message-ID: <mailman.117.1526578702.2757.python-checkins@python.org> https://github.com/python/cpython/commit/48b1f3773cecb0aec2b14d972bf8453e4e8f807f commit: 48b1f3773cecb0aec2b14d972bf8453e4e8f807f branch: master author: Steve Dower <steve.dower at microsoft.com> committer: GitHub <noreply at github.com> date: 2018-05-17T13:38:15-04:00 summary: Only upload docs for CI build and not pull requests (GH-6945) files: M .vsts/docs.yml diff --git a/.vsts/docs.yml b/.vsts/docs.yml index efa1e871656d..62f6123adb31 100644 --- a/.vsts/docs.yml +++ b/.vsts/docs.yml @@ -37,6 +37,7 @@ steps: - task: PublishBuildArtifacts at 1 displayName: 'Publish build' + condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) inputs: PathToPublish: '$(build.sourcesDirectory)/Doc/build' ArtifactName: build From webhook-mailer at python.org Thu May 17 13:44:03 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Thu, 17 May 2018 17:44:03 -0000 Subject: [Python-checkins] asyncio/docs: Mark asyncio.run() as provisional in 3.7. (#6946) Message-ID: <mailman.118.1526579044.2757.python-checkins@python.org> https://github.com/python/cpython/commit/d8d715f5148d0c10e93a79bc4172fbd9c5b3a86e commit: d8d715f5148d0c10e93a79bc4172fbd9c5b3a86e branch: master author: Yury Selivanov <yury at magic.io> committer: GitHub <noreply at github.com> date: 2018-05-17T13:44:00-04:00 summary: asyncio/docs: Mark asyncio.run() as provisional in 3.7. (#6946) files: M Doc/library/asyncio-task.rst diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index 364323d5ca8b..db0e04a4a1d1 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -108,6 +108,8 @@ Coroutines (and tasks) can only run when the event loop is running. programs, and should ideally only be called once. .. versionadded:: 3.7 + **Important:** this has been been added to asyncio in Python 3.7 + on a :term:`provisional basis <provisional api>`. .. _asyncio-hello-world-coroutine: From webhook-mailer at python.org Thu May 17 13:44:56 2018 From: webhook-mailer at python.org (Steve Dower) Date: Thu, 17 May 2018 17:44:56 -0000 Subject: [Python-checkins] bpo-33559: Document changed repr of exceptions (GH-6943) Message-ID: <mailman.119.1526579098.2757.python-checkins@python.org> https://github.com/python/cpython/commit/631753fcc5e88bbbad402933e77295675cfe1fee commit: 631753fcc5e88bbbad402933e77295675cfe1fee branch: master author: Miro Hron?ok <miro at hroncok.cz> committer: Steve Dower <steve.dower at microsoft.com> date: 2018-05-17T13:44:53-04:00 summary: bpo-33559: Document changed repr of exceptions (GH-6943) files: M Doc/whatsnew/3.7.rst diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index cc762736a0c7..b22e9143437f 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -1238,6 +1238,9 @@ Changes in the Python API :func:`socket.fromshare` a socket :func:`~socket.socket.share`-ed in older Python versions. +* ``repr`` for :exc:`BaseException` has changed not to include trailing comma + in the output. Mind that most exceptions are affected by this change. + * ``repr`` for :class:`datetime.timedelta` has changed to include keyword arguments in the output. (Contributed by Utkarsh Upadhyay in :issue:`30302`.) From webhook-mailer at python.org Thu May 17 14:04:02 2018 From: webhook-mailer at python.org (Steve Dower) Date: Thu, 17 May 2018 18:04:02 -0000 Subject: [Python-checkins] Fix Windows build of Python for latest WinSDK. (GH-6874) Message-ID: <mailman.120.1526580243.2757.python-checkins@python.org> https://github.com/python/cpython/commit/c0ee341b29bd7d978b49272a2c0e2dcfa77404d5 commit: c0ee341b29bd7d978b49272a2c0e2dcfa77404d5 branch: master author: Carl Meyer <carl at oddbird.net> committer: Steve Dower <steve.dower at microsoft.com> date: 2018-05-17T14:03:59-04:00 summary: Fix Windows build of Python for latest WinSDK. (GH-6874) files: M Modules/_io/_iomodule.c M PCbuild/python.props diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index 11d7b0188311..667446526a0b 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -21,7 +21,7 @@ #endif /* HAVE_SYS_STAT_H */ #ifdef MS_WINDOWS -#include <consoleapi.h> +#include <Windows.h> #endif /* Various interned strings */ diff --git a/PCbuild/python.props b/PCbuild/python.props index f7adaf47db66..fc0b6618ca73 100644 --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -77,7 +77,8 @@ --> <_RegistryVersion>$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v10.0 at ProductVersion)</_RegistryVersion> <_RegistryVersion Condition="$(_RegistryVersion) == ''">$(Registry:HKEY_LOCAL_MACHINE\WOW6432Node\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v10.0 at ProductVersion)</_RegistryVersion> - <DefaultWindowsSDKVersion>10.0.16299.0</DefaultWindowsSDKVersion> + <DefaultWindowsSDKVersion>10.0.17134.0</DefaultWindowsSDKVersion> + <DefaultWindowsSDKVersion Condition="$(_RegistryVersion) == '10.0.16299'">10.0.16299.0</DefaultWindowsSDKVersion> <DefaultWindowsSDKVersion Condition="$(_RegistryVersion) == '10.0.15063'">10.0.15063.0</DefaultWindowsSDKVersion> <DefaultWindowsSDKVersion Condition="$(_RegistryVersion) == '10.0.14393'">10.0.14393.0</DefaultWindowsSDKVersion> <DefaultWindowsSDKVersion Condition="$(_RegistryVersion) == '10.0.10586'">10.0.10586.0</DefaultWindowsSDKVersion> From webhook-mailer at python.org Thu May 17 14:06:06 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 17 May 2018 18:06:06 -0000 Subject: [Python-checkins] Only upload docs for CI build and not pull requests (GH-6945) Message-ID: <mailman.121.1526580368.2757.python-checkins@python.org> https://github.com/python/cpython/commit/d27bc910b503b732cac094338528642e86d4ee00 commit: d27bc910b503b732cac094338528642e86d4ee00 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-17T11:06:03-07:00 summary: Only upload docs for CI build and not pull requests (GH-6945) (cherry picked from commit 48b1f3773cecb0aec2b14d972bf8453e4e8f807f) Co-authored-by: Steve Dower <steve.dower at microsoft.com> files: M .vsts/docs.yml diff --git a/.vsts/docs.yml b/.vsts/docs.yml index efa1e871656d..62f6123adb31 100644 --- a/.vsts/docs.yml +++ b/.vsts/docs.yml @@ -37,6 +37,7 @@ steps: - task: PublishBuildArtifacts at 1 displayName: 'Publish build' + condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) inputs: PathToPublish: '$(build.sourcesDirectory)/Doc/build' ArtifactName: build From webhook-mailer at python.org Thu May 17 14:30:13 2018 From: webhook-mailer at python.org (Steve Dower) Date: Thu, 17 May 2018 18:30:13 -0000 Subject: [Python-checkins] Only upload docs for CI build and not pull requests (GH-6945) (GH-6948) Message-ID: <mailman.122.1526581814.2757.python-checkins@python.org> https://github.com/python/cpython/commit/346762698cc6a5e9a47fa6a9e5dbb0491112e508 commit: 346762698cc6a5e9a47fa6a9e5dbb0491112e508 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Steve Dower <steve.dower at microsoft.com> date: 2018-05-17T14:30:09-04:00 summary: Only upload docs for CI build and not pull requests (GH-6945) (GH-6948) (cherry picked from commit 48b1f3773cecb0aec2b14d972bf8453e4e8f807f) Co-authored-by: Steve Dower <steve.dower at microsoft.com> files: M .vsts/docs.yml diff --git a/.vsts/docs.yml b/.vsts/docs.yml index efa1e871656d..62f6123adb31 100644 --- a/.vsts/docs.yml +++ b/.vsts/docs.yml @@ -37,6 +37,7 @@ steps: - task: PublishBuildArtifacts at 1 displayName: 'Publish build' + condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) inputs: PathToPublish: '$(build.sourcesDirectory)/Doc/build' ArtifactName: build From webhook-mailer at python.org Thu May 17 14:41:14 2018 From: webhook-mailer at python.org (Steve Dower) Date: Thu, 17 May 2018 18:41:14 -0000 Subject: [Python-checkins] bpo-33559: Document changed repr of exceptions (GH-6943) (GH-6950) Message-ID: <mailman.123.1526582475.2757.python-checkins@python.org> https://github.com/python/cpython/commit/54fc49737a6a79f6e2ece16e22b233858b836567 commit: 54fc49737a6a79f6e2ece16e22b233858b836567 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Steve Dower <steve.dower at microsoft.com> date: 2018-05-17T14:41:07-04:00 summary: bpo-33559: Document changed repr of exceptions (GH-6943) (GH-6950) (cherry picked from commit 631753fcc5e88bbbad402933e77295675cfe1fee) Co-authored-by: Miro Hron?ok <miro at hroncok.cz> files: M Doc/whatsnew/3.7.rst diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 0a0c7d3659f1..30aeb3a0e49e 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -1240,6 +1240,9 @@ Changes in the Python API :func:`socket.fromshare` a socket :func:`~socket.socket.share`-ed in older Python versions. +* ``repr`` for :exc:`BaseException` has changed not to include trailing comma + in the output. Mind that most exceptions are affected by this change. + * ``repr`` for :class:`datetime.timedelta` has changed to include keyword arguments in the output. (Contributed by Utkarsh Upadhyay in :issue:`30302`.) From webhook-mailer at python.org Thu May 17 15:05:10 2018 From: webhook-mailer at python.org (Steve Dower) Date: Thu, 17 May 2018 19:05:10 -0000 Subject: [Python-checkins] bpo-33559: Attribute changed repr of exceptions (GH-6954) Message-ID: <mailman.124.1526583911.2757.python-checkins@python.org> https://github.com/python/cpython/commit/fb9dd8915314d857161de89fcbbb041f2b49fc22 commit: fb9dd8915314d857161de89fcbbb041f2b49fc22 branch: master author: Miro Hron?ok <miro at hroncok.cz> committer: Steve Dower <steve.dower at microsoft.com> date: 2018-05-17T15:04:57-04:00 summary: bpo-33559: Attribute changed repr of exceptions (GH-6954) files: M Doc/whatsnew/3.7.rst diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index b22e9143437f..24a5b3daf92a 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -1240,6 +1240,7 @@ Changes in the Python API * ``repr`` for :exc:`BaseException` has changed not to include trailing comma in the output. Mind that most exceptions are affected by this change. + (Contributed by Serhiy Storchaka in :issue:`30399`.) * ``repr`` for :class:`datetime.timedelta` has changed to include keyword arguments in the output. (Contributed by Utkarsh Upadhyay in :issue:`30302`.) From webhook-mailer at python.org Thu May 17 15:10:59 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Thu, 17 May 2018 19:10:59 -0000 Subject: [Python-checkins] asyncio/docs: Mark asyncio.run() as provisional in 3.7. (GH-6946) (GH-6949) Message-ID: <mailman.125.1526584261.2757.python-checkins@python.org> https://github.com/python/cpython/commit/f34ade33ee307434bb73fd1853da3295047f0076 commit: f34ade33ee307434bb73fd1853da3295047f0076 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Yury Selivanov <yury at magic.io> date: 2018-05-17T15:10:56-04:00 summary: asyncio/docs: Mark asyncio.run() as provisional in 3.7. (GH-6946) (GH-6949) (cherry picked from commit d8d715f5148d0c10e93a79bc4172fbd9c5b3a86e) Co-authored-by: Yury Selivanov <yury at magic.io> files: M Doc/library/asyncio-task.rst diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index 364323d5ca8b..db0e04a4a1d1 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -108,6 +108,8 @@ Coroutines (and tasks) can only run when the event loop is running. programs, and should ideally only be called once. .. versionadded:: 3.7 + **Important:** this has been been added to asyncio in Python 3.7 + on a :term:`provisional basis <provisional api>`. .. _asyncio-hello-world-coroutine: From webhook-mailer at python.org Thu May 17 15:35:30 2018 From: webhook-mailer at python.org (Steve Dower) Date: Thu, 17 May 2018 19:35:30 -0000 Subject: [Python-checkins] Fix Windows build of Python for latest WinSDK. (GH-6874) (GH-6952) Message-ID: <mailman.126.1526585730.2757.python-checkins@python.org> https://github.com/python/cpython/commit/df4852cbe4b757e8b79506d73a09ec8a1b595970 commit: df4852cbe4b757e8b79506d73a09ec8a1b595970 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Steve Dower <steve.dower at microsoft.com> date: 2018-05-17T15:35:27-04:00 summary: Fix Windows build of Python for latest WinSDK. (GH-6874) (GH-6952) (cherry picked from commit c0ee341b29bd7d978b49272a2c0e2dcfa77404d5) Co-authored-by: Carl Meyer <carl at oddbird.net> files: M Modules/_io/_iomodule.c M PCbuild/python.props diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c index 11d7b0188311..667446526a0b 100644 --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -21,7 +21,7 @@ #endif /* HAVE_SYS_STAT_H */ #ifdef MS_WINDOWS -#include <consoleapi.h> +#include <Windows.h> #endif /* Various interned strings */ diff --git a/PCbuild/python.props b/PCbuild/python.props index f7adaf47db66..fc0b6618ca73 100644 --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -77,7 +77,8 @@ --> <_RegistryVersion>$(Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v10.0 at ProductVersion)</_RegistryVersion> <_RegistryVersion Condition="$(_RegistryVersion) == ''">$(Registry:HKEY_LOCAL_MACHINE\WOW6432Node\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v10.0 at ProductVersion)</_RegistryVersion> - <DefaultWindowsSDKVersion>10.0.16299.0</DefaultWindowsSDKVersion> + <DefaultWindowsSDKVersion>10.0.17134.0</DefaultWindowsSDKVersion> + <DefaultWindowsSDKVersion Condition="$(_RegistryVersion) == '10.0.16299'">10.0.16299.0</DefaultWindowsSDKVersion> <DefaultWindowsSDKVersion Condition="$(_RegistryVersion) == '10.0.15063'">10.0.15063.0</DefaultWindowsSDKVersion> <DefaultWindowsSDKVersion Condition="$(_RegistryVersion) == '10.0.14393'">10.0.14393.0</DefaultWindowsSDKVersion> <DefaultWindowsSDKVersion Condition="$(_RegistryVersion) == '10.0.10586'">10.0.10586.0</DefaultWindowsSDKVersion> From webhook-mailer at python.org Thu May 17 16:10:07 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 17 May 2018 20:10:07 -0000 Subject: [Python-checkins] bpo-33559: Attribute changed repr of exceptions (GH-6954) Message-ID: <mailman.127.1526587809.2757.python-checkins@python.org> https://github.com/python/cpython/commit/efa642779739b5af028b0f6ebb9033395e124273 commit: efa642779739b5af028b0f6ebb9033395e124273 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-17T13:09:57-07:00 summary: bpo-33559: Attribute changed repr of exceptions (GH-6954) (cherry picked from commit fb9dd8915314d857161de89fcbbb041f2b49fc22) Co-authored-by: Miro Hron?ok <miro at hroncok.cz> files: M Doc/whatsnew/3.7.rst diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 30aeb3a0e49e..dfe6c90d3a38 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -1242,6 +1242,7 @@ Changes in the Python API * ``repr`` for :exc:`BaseException` has changed not to include trailing comma in the output. Mind that most exceptions are affected by this change. + (Contributed by Serhiy Storchaka in :issue:`30399`.) * ``repr`` for :class:`datetime.timedelta` has changed to include keyword arguments in the output. (Contributed by Utkarsh Upadhyay in :issue:`30302`.) From webhook-mailer at python.org Thu May 17 16:12:25 2018 From: webhook-mailer at python.org (Brett Cannon) Date: Thu, 17 May 2018 20:12:25 -0000 Subject: [Python-checkins] Disable multissltests.py under VSTS (GH-6955) Message-ID: <mailman.128.1526587946.2757.python-checkins@python.org> https://github.com/python/cpython/commit/950d0911524fbd700c7c7c787f038cd8113f70e7 commit: 950d0911524fbd700c7c7c787f038cd8113f70e7 branch: 3.6 author: Steve Dower <steve.dower at microsoft.com> committer: Brett Cannon <brettcannon at users.noreply.github.com> date: 2018-05-17T16:12:20-04:00 summary: Disable multissltests.py under VSTS (GH-6955) files: M .vsts/linux-buildbot.yml M .vsts/linux-coverage.yml M .vsts/linux-deps.yml M .vsts/linux-pr.yml diff --git a/.vsts/linux-buildbot.yml b/.vsts/linux-buildbot.yml index d75d7f57650e..76222d10c48e 100644 --- a/.vsts/linux-buildbot.yml +++ b/.vsts/linux-buildbot.yml @@ -17,10 +17,7 @@ trigger: - Doc/* - Tools/* -variables: - # Copy-pasted from linux-deps.yml until template support arrives - OPENSSL: 1.1.0g - OPENSSL_DIR: "$(build.sourcesDirectory)/multissl/openssl/$(OPENSSL)" +#variables: steps: @@ -35,8 +32,6 @@ steps: - script: echo "deb-src http://archive.ubuntu.com/ubuntu/ xenial main" > /etc/apt/sources.list.d/python.list && sudo apt-get update displayName: 'Update apt-get lists' -- script: echo ##vso[task.prependpath]$(OPENSSL_DIR) - displayName: 'Add $(OPENSSL_DIR) to PATH' - script: > sudo apt-get -yq install build-essential @@ -55,8 +50,6 @@ steps: libffi-dev uuid-dev displayName: 'Install dependencies' -- script: python3 Tools/ssl/multissltests.py --steps=library --base-directory $(build.sourcesDirectory)/multissl --openssl $(OPENSSL) --system Linux - displayName: 'python multissltests.py' - script: ./configure --with-pydebug displayName: 'Configure CPython (debug)' diff --git a/.vsts/linux-coverage.yml b/.vsts/linux-coverage.yml index 3657b1720ee2..930c9c6b76dc 100644 --- a/.vsts/linux-coverage.yml +++ b/.vsts/linux-coverage.yml @@ -17,10 +17,7 @@ trigger: - Doc/* - Tools/* -variables: - # Copy-pasted from linux-deps.yml until template support arrives - OPENSSL: 1.1.0g - OPENSSL_DIR: "$(build.sourcesDirectory)/multissl/openssl/$(OPENSSL)" +#variables: steps: - checkout: self @@ -34,8 +31,6 @@ steps: - script: echo "deb-src http://archive.ubuntu.com/ubuntu/ xenial main" > /etc/apt/sources.list.d/python.list && sudo apt-get update displayName: 'Update apt-get lists' -- script: echo ##vso[task.prependpath]$(OPENSSL_DIR) - displayName: 'Add $(OPENSSL_DIR) to PATH' - script: > sudo apt-get -yq install build-essential @@ -54,8 +49,6 @@ steps: libffi-dev uuid-dev displayName: 'Install dependencies' -- script: python3 Tools/ssl/multissltests.py --steps=library --base-directory $(build.sourcesDirectory)/multissl --openssl $(OPENSSL) --system Linux - displayName: 'python multissltests.py' - script: ./configure --with-pydebug diff --git a/.vsts/linux-deps.yml b/.vsts/linux-deps.yml index b6c8a3690ea1..540b76ec54c3 100644 --- a/.vsts/linux-deps.yml +++ b/.vsts/linux-deps.yml @@ -4,16 +4,12 @@ # Current docs for the syntax of this file are at: # https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md -parameters: - OPENSSL: 1.1.0g - OPENSSL_DIR: "$(build.sourcesDirectory)/multissl/openssl/$(OPENSSL)" +#parameters: steps: - script: echo "deb-src http://archive.ubuntu.com/ubuntu/ xenial main" > /etc/apt/sources.list.d/python.list && sudo apt-get update displayName: 'Update apt-get lists' -- script: echo ##vso[task.prependpath]$(OPENSSL_DIR) - displayName: 'Add $(OPENSSL_DIR) to PATH' - script: > sudo apt-get -yq install build-essential @@ -32,5 +28,3 @@ steps: libffi-dev uuid-dev displayName: 'Install dependencies' -- script: python3 Tools/ssl/multissltests.py --steps=library --base-directory $(build.sourcesDirectory)/multissl --openssl $(OPENSSL) --system Linux - displayName: 'python multissltests.py' diff --git a/.vsts/linux-pr.yml b/.vsts/linux-pr.yml index 7f4d458f5a7c..83df9b436881 100644 --- a/.vsts/linux-pr.yml +++ b/.vsts/linux-pr.yml @@ -17,10 +17,7 @@ trigger: - Doc/* - Tools/* -variables: - # Copy-pasted from linux-deps.yml until template support arrives - OPENSSL: 1.1.0g - OPENSSL_DIR: "$(build.sourcesDirectory)/multissl/openssl/$(OPENSSL)" +#variables: steps: - checkout: self @@ -34,8 +31,6 @@ steps: - script: echo "deb-src http://archive.ubuntu.com/ubuntu/ xenial main" > /etc/apt/sources.list.d/python.list && sudo apt-get update displayName: 'Update apt-get lists' -- script: echo ##vso[task.prependpath]$(OPENSSL_DIR) - displayName: 'Add $(OPENSSL_DIR) to PATH' - script: > sudo apt-get -yq install build-essential @@ -54,8 +49,6 @@ steps: libffi-dev uuid-dev displayName: 'Install dependencies' -- script: python3 Tools/ssl/multissltests.py --steps=library --base-directory $(build.sourcesDirectory)/multissl --openssl $(OPENSSL) --system Linux - displayName: 'python multissltests.py' - script: ./configure --with-pydebug From webhook-mailer at python.org Thu May 17 20:38:51 2018 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Fri, 18 May 2018 00:38:51 -0000 Subject: [Python-checkins] bpo-33564: Add async to IDLE's code context block openers. (GH-6960) Message-ID: <mailman.129.1526603933.2757.python-checkins@python.org> https://github.com/python/cpython/commit/d89ca94847d943b883ebcc68e4f0a18cb042ed0d commit: d89ca94847d943b883ebcc68e4f0a18cb042ed0d branch: master author: Terry Jan Reedy <tjreedy at udel.edu> committer: GitHub <noreply at github.com> date: 2018-05-17T20:38:41-04:00 summary: bpo-33564: Add async to IDLE's code context block openers. (GH-6960) files: A Misc/NEWS.d/next/IDLE/2018-05-17-19-41-12.bpo-33564.XzHZJe.rst M Lib/idlelib/codecontext.py diff --git a/Lib/idlelib/codecontext.py b/Lib/idlelib/codecontext.py index 316e5109e6cd..2bfb2e988ff4 100644 --- a/Lib/idlelib/codecontext.py +++ b/Lib/idlelib/codecontext.py @@ -18,7 +18,7 @@ from idlelib.config import idleConf BLOCKOPENERS = {"class", "def", "elif", "else", "except", "finally", "for", - "if", "try", "while", "with"} + "if", "try", "while", "with", "async"} UPDATEINTERVAL = 100 # millisec FONTUPDATEINTERVAL = 1000 # millisec diff --git a/Misc/NEWS.d/next/IDLE/2018-05-17-19-41-12.bpo-33564.XzHZJe.rst b/Misc/NEWS.d/next/IDLE/2018-05-17-19-41-12.bpo-33564.XzHZJe.rst new file mode 100644 index 000000000000..df828485f69e --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2018-05-17-19-41-12.bpo-33564.XzHZJe.rst @@ -0,0 +1 @@ +IDLE's code context now recognizes async as a block opener. From webhook-mailer at python.org Thu May 17 21:25:35 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 18 May 2018 01:25:35 -0000 Subject: [Python-checkins] bpo-33564: Add async to IDLE's code context block openers. (GH-6960) Message-ID: <mailman.130.1526606737.2757.python-checkins@python.org> https://github.com/python/cpython/commit/eb4590e4d9abecdbbc91c3531df83e1f9bed50f1 commit: eb4590e4d9abecdbbc91c3531df83e1f9bed50f1 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-17T18:25:25-07:00 summary: bpo-33564: Add async to IDLE's code context block openers. (GH-6960) (cherry picked from commit d89ca94847d943b883ebcc68e4f0a18cb042ed0d) Co-authored-by: Terry Jan Reedy <tjreedy at udel.edu> files: A Misc/NEWS.d/next/IDLE/2018-05-17-19-41-12.bpo-33564.XzHZJe.rst M Lib/idlelib/codecontext.py diff --git a/Lib/idlelib/codecontext.py b/Lib/idlelib/codecontext.py index 316e5109e6cd..2bfb2e988ff4 100644 --- a/Lib/idlelib/codecontext.py +++ b/Lib/idlelib/codecontext.py @@ -18,7 +18,7 @@ from idlelib.config import idleConf BLOCKOPENERS = {"class", "def", "elif", "else", "except", "finally", "for", - "if", "try", "while", "with"} + "if", "try", "while", "with", "async"} UPDATEINTERVAL = 100 # millisec FONTUPDATEINTERVAL = 1000 # millisec diff --git a/Misc/NEWS.d/next/IDLE/2018-05-17-19-41-12.bpo-33564.XzHZJe.rst b/Misc/NEWS.d/next/IDLE/2018-05-17-19-41-12.bpo-33564.XzHZJe.rst new file mode 100644 index 000000000000..df828485f69e --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2018-05-17-19-41-12.bpo-33564.XzHZJe.rst @@ -0,0 +1 @@ +IDLE's code context now recognizes async as a block opener. From webhook-mailer at python.org Thu May 17 22:04:33 2018 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Fri, 18 May 2018 02:04:33 -0000 Subject: [Python-checkins] bpo-33564: Add async to IDLE's code context block openers. (GH-6960) (#6961) Message-ID: <mailman.131.1526609074.2757.python-checkins@python.org> https://github.com/python/cpython/commit/b2a02b9d88db04c12f800bc088afea0ef6862673 commit: b2a02b9d88db04c12f800bc088afea0ef6862673 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Terry Jan Reedy <tjreedy at udel.edu> date: 2018-05-17T22:04:23-04:00 summary: bpo-33564: Add async to IDLE's code context block openers. (GH-6960) (#6961) (cherry picked from commit d89ca94847d943b883ebcc68e4f0a18cb042ed0d) Co-authored-by: Terry Jan Reedy <tjreedy at udel.edu> files: A Misc/NEWS.d/next/IDLE/2018-05-17-19-41-12.bpo-33564.XzHZJe.rst M Lib/idlelib/codecontext.py diff --git a/Lib/idlelib/codecontext.py b/Lib/idlelib/codecontext.py index 316e5109e6cd..2bfb2e988ff4 100644 --- a/Lib/idlelib/codecontext.py +++ b/Lib/idlelib/codecontext.py @@ -18,7 +18,7 @@ from idlelib.config import idleConf BLOCKOPENERS = {"class", "def", "elif", "else", "except", "finally", "for", - "if", "try", "while", "with"} + "if", "try", "while", "with", "async"} UPDATEINTERVAL = 100 # millisec FONTUPDATEINTERVAL = 1000 # millisec diff --git a/Misc/NEWS.d/next/IDLE/2018-05-17-19-41-12.bpo-33564.XzHZJe.rst b/Misc/NEWS.d/next/IDLE/2018-05-17-19-41-12.bpo-33564.XzHZJe.rst new file mode 100644 index 000000000000..df828485f69e --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2018-05-17-19-41-12.bpo-33564.XzHZJe.rst @@ -0,0 +1 @@ +IDLE's code context now recognizes async as a block opener. From lp_benchmark_robot at intel.com Thu May 17 23:05:26 2018 From: lp_benchmark_robot at intel.com (lp_benchmark_robot at intel.com) Date: Thu, 17 May 2018 20:05:26 -0700 Subject: [Python-checkins] [65 flat] Results for Python (master branch) 2018-05-17 Message-ID: <f85516d2-ba54-48d4-9932-20843168632b@orsmsx107.amr.corp.intel.com> Results for project python/master, build date: 2018-05-17 03:03:18-07:00. - commit: 74fc9c0 - previous commit: f8e7549 - revision date: 2018-05-17 05:14:30-04:00 - environment: Broadwell-EP - cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores, stepping 1, LLC 55 MB - mem: 128 GB - os: Ubuntu 16.04.2 LTS - kernel: 4.4.0-62-generic x86_64 GNU/Linux Baseline results were generated using release v3.6.0, with hash 5c4568a from 2016-12-22 23:38:47+00:00. +-----+------------------------+--------+------------+------------+------------+ | | |relative|change since|change since|current rev | | | benchmark|std_dev*| last run | baseline |run with PGO| +-----+------------------------+--------+------------+------------+------------+ | :-| | 2to3| 0.666% | +0.120% | +9.148% | +6.391% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method| 2.352% | -0.613% | +23.615% | +13.388% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_slots| 1.404% | -0.373% | +25.417% | +11.942% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_unknown| 0.838% | +0.180% | +22.605% | +14.027% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_simple| 3.236% | -0.381% | +11.396% | +11.824% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chameleon| 2.100% | -0.760% | +11.279% | +12.016% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chaos| 1.079% | -0.348% | +8.827% | +9.714% | +-----+------------------------+--------+------------+------------+------------+ | :-| | crypto_pyaes| 0.690% | -0.348% | -0.300% | +8.154% | +-----+------------------------+--------+------------+------------+------------+ | :-| | deltablue| 3.182% | -0.479% | +12.020% | +17.221% | +-----+------------------------+--------+------------+------------+------------+ | :-| | django_template| 1.246% | -0.439% | +21.519% | +11.222% | +-----+------------------------+--------+------------+------------+------------+ | :-| | dulwich_log| 1.003% | -1.034% | +5.098% | +7.171% | +-----+------------------------+--------+------------+------------+------------+ | :-| | fannkuch| 0.369% | +0.473% | +7.523% | +5.723% | +-----+------------------------+--------+------------+------------+------------+ | :-| | float| 1.258% | +0.441% | +2.668% | +7.173% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_text| 1.180% | -0.149% | +14.399% | +9.784% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_xml| 1.765% | +0.319% | +12.199% | +7.686% | +-----+------------------------+--------+------------+------------+------------+ | :-| | go| 5.828% | +0.023% | +5.525% | +10.906% | +-----+------------------------+--------+------------+------------+------------+ | :-| | hexiom| 0.790% | -0.007% | +12.134% | +11.029% | +-----+------------------------+--------+------------+------------+------------+ | :-| | html5lib| 3.113% | -0.982% | +10.930% | +10.627% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_dumps| 1.928% | +0.007% | +3.382% | +8.771% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_loads| 4.640% | -0.155% | -3.864% | +14.129% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_format| 1.646% | -0.845% | +17.176% | +13.025% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_silent| 2.711% | +0.281% | +47.998% | +12.955% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_simple| 1.310% | -0.406% | +12.609% | +13.782% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mako| 0.489% | -0.141% | +16.883% | +14.487% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mdp| 7.035% | -1.392% | -0.257% | +18.273% | +-----+------------------------+--------+------------+------------+------------+ | :-| | meteor_contest| 0.789% | -0.163% | +4.309% | +7.310% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nbody| 1.141% | -1.077% | -0.904% | +0.554% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nqueens| 0.522% | +0.869% | +6.490% | +8.551% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pathlib| 1.154% | +0.903% | +1.687% | +8.439% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle| 7.377% | -0.891% | -1.819% | +21.594% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_dict| 0.400% | +0.107% | +7.593% | +15.504% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_list| 0.836% | -0.489% | +7.114% | +17.412% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_pure_python| 3.864% | -0.836% | +11.124% | +10.765% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pidigits| 0.051% | +0.270% | +0.319% | +10.049% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup| 0.125% | -0.095% | +18.847% | +5.013% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup_no_site| 0.086% | -0.116% | +5.840% | +5.252% | +-----+------------------------+--------+------------+------------+------------+ | :-| | raytrace| 0.958% | +0.126% | +10.784% | +13.052% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_compile| 5.611% | -2.743% | +4.047% | +13.016% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_dna| 0.377% | -0.072% | -2.115% | +12.013% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_effbot| 1.907% | -2.349% | -7.645% | +8.467% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_v8| 2.571% | -0.208% | +3.775% | +8.500% | +-----+------------------------+--------+------------+------------+------------+ | :-| | richards| 1.395% | +0.516% | +9.748% | +14.633% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_fft| 0.916% | +1.073% | -0.275% | +3.108% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_lu| 3.319% | +1.451% | +22.895% | +12.343% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_monte_carlo| 2.884% | -0.546% | +5.051% | +6.437% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sor| 3.116% | -0.022% | +15.186% | +8.210% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sparse_mat_mult| 6.515% | -0.222% | -4.124% | +0.260% | +-----+------------------------+--------+------------+------------+------------+ | :-| | spectral_norm| 0.624% | +0.564% | +5.425% | +4.348% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_declarative| 1.923% | +0.434% | +7.191% | +7.215% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_imperative| 3.704% | +0.251% | +7.953% | +4.561% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlite_synth| 3.357% | +1.092% | +0.560% | +7.787% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_expand| 2.950% | +0.444% | +18.128% | +7.067% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_integrate| 2.257% | -0.163% | +18.284% | +6.662% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_str| 3.652% | +0.158% | +19.795% | +7.895% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_sum| 6.050% | +0.614% | +16.874% | +10.922% | +-----+------------------------+--------+------------+------------+------------+ | :-| | telco| 2.576% | +1.003% | +20.928% | +9.115% | +-----+------------------------+--------+------------+------------+------------+ | :-| | tornado_http| 1.052% | +0.414% | +7.483% | +6.690% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpack_sequence| 1.929% | +1.001% | +2.483% | +0.044% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle| 7.764% | -3.318% | +6.984% | +21.282% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_list| 1.385% | -0.375% | -3.735% | +18.286% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_pure_python| 1.853% | -0.337% | +7.430% | +8.062% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_generate| 0.913% | +0.398% | +2.882% | +12.200% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_iterparse| 1.937% | +0.026% | +4.146% | +7.623% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_parse| 2.420% | +0.609% | -6.118% | +11.833% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_process| 1.267% | +0.273% | +4.859% | +11.326% | +-----+------------------------+--------+------------+------------+------------+ * Relative Standard Deviation (Standard Deviation/Average) If this is not displayed properly please visit our results page here: http://languagesperformance.intel.com/65-flat-results-for-python-master-branch-2018-05-17 Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. From greg at krypto.org Fri May 18 00:29:11 2018 From: greg at krypto.org (Gregory P. Smith) Date: Thu, 17 May 2018 21:29:11 -0700 Subject: [Python-checkins] bpo-33522: Enable CI builds on Visual Studio Team Services (GH-6865) (GH-6925) In-Reply-To: <40mt4J0QJ1zFr2Z@mail.python.org> References: <40mt4J0QJ1zFr2Z@mail.python.org> Message-ID: <CAGE7PN+rAsGwyhBfvae93TgeDEe_AvPmK+nHxcwyGF58-B6w5Q@mail.gmail.com> Why did this commit modify .py files, unittests, and test.support? That is inappropriate for something claiming to merely enable a CI platform. -gps On Thu, May 17, 2018 at 6:50 AM Steve Dower <webhook-mailer at python.org> wrote: > > https://github.com/python/cpython/commit/0d8f83f59c8f4cc7fe125434ca4ecdcac111810f > commit: 0d8f83f59c8f4cc7fe125434ca4ecdcac111810f > branch: 3.6 > author: Steve Dower <steve.dower at microsoft.com> > committer: GitHub <noreply at github.com> > date: 2018-05-17T09:46:00-04:00 > summary: > > bpo-33522: Enable CI builds on Visual Studio Team Services (GH-6865) > (GH-6925) > > files: > A .vsts/docs-release.yml > A .vsts/docs.yml > A .vsts/linux-buildbot.yml > A .vsts/linux-coverage.yml > A .vsts/linux-deps.yml > A .vsts/linux-pr.yml > A .vsts/macos-buildbot.yml > A .vsts/macos-pr.yml > A .vsts/windows-buildbot.yml > A .vsts/windows-pr.yml > A Misc/NEWS.d/next/Build/2018-05-15-12-44-50.bpo-33522.mJoNcA.rst > A Misc/NEWS.d/next/Library/2018-05-16-17-05-48.bpo-33548.xWslmx.rst > M Doc/make.bat > M Lib/tempfile.py > M Lib/test/support/__init__.py > M Lib/test/test_asyncio/test_base_events.py > M Lib/test/test_bdb.py > M Lib/test/test_pathlib.py > M Lib/test/test_poplib.py > M Lib/test/test_selectors.py > M PCbuild/rt.bat > M Tools/ssl/multissltests.py > > diff --git a/.vsts/docs-release.yml b/.vsts/docs-release.yml > new file mode 100644 > index 000000000000..e90428a42494 > --- /dev/null > +++ b/.vsts/docs-release.yml > @@ -0,0 +1,43 @@ > +# Current docs for the syntax of this file are at: > +# > https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md > + > +name: $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.rr) > + > +queue: > + name: Hosted Linux Preview > + > +#variables: > + > +steps: > +- checkout: self > + clean: true > + fetchDepth: 5 > + > +- script: sudo apt-get update && sudo apt-get install -qy --force-yes > texlive-full > + displayName: 'Install LaTeX' > + > +- task: UsePythonVersion at 0 > + displayName: 'Use Python 3.6 or later' > + inputs: > + versionSpec: '>=3.6' > + > +- script: python -m pip install sphinx blurb python-docs-theme > + displayName: 'Install build dependencies' > + > +- script: make dist PYTHON=python SPHINXBUILD='python -m sphinx' > BLURB='python -m blurb' > + workingDirectory: '$(build.sourcesDirectory)/Doc' > + displayName: 'Build documentation' > + > +- task: PublishBuildArtifacts at 1 > + displayName: 'Publish build' > + inputs: > + PathToPublish: '$(build.sourcesDirectory)/Doc/build' > + ArtifactName: build > + publishLocation: Container > + > +- task: PublishBuildArtifacts at 1 > + displayName: 'Publish dist' > + inputs: > + PathToPublish: '$(build.sourcesDirectory)/Doc/dist' > + ArtifactName: dist > + publishLocation: Container > diff --git a/.vsts/docs.yml b/.vsts/docs.yml > new file mode 100644 > index 000000000000..efa1e871656d > --- /dev/null > +++ b/.vsts/docs.yml > @@ -0,0 +1,43 @@ > +# Current docs for the syntax of this file are at: > +# > https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md > + > +name: $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.rr) > + > +queue: > + name: Hosted Linux Preview > + > +trigger: > + branches: > + include: > + - master > + - 3.7 > + - 3.6 > + paths: > + include: > + - Doc/* > + > +#variables: > + > +steps: > +- checkout: self > + clean: true > + fetchDepth: 5 > + > +- task: UsePythonVersion at 0 > + displayName: 'Use Python 3.6 or later' > + inputs: > + versionSpec: '>=3.6' > + > +- script: python -m pip install sphinx~=1.6.1 blurb python-docs-theme > + displayName: 'Install build dependencies' > + > +- script: make check suspicious html PYTHON=python > + workingDirectory: '$(build.sourcesDirectory)/Doc' > + displayName: 'Build documentation' > + > +- task: PublishBuildArtifacts at 1 > + displayName: 'Publish build' > + inputs: > + PathToPublish: '$(build.sourcesDirectory)/Doc/build' > + ArtifactName: build > + publishLocation: Container > diff --git a/.vsts/linux-buildbot.yml b/.vsts/linux-buildbot.yml > new file mode 100644 > index 000000000000..d75d7f57650e > --- /dev/null > +++ b/.vsts/linux-buildbot.yml > @@ -0,0 +1,71 @@ > +# Current docs for the syntax of this file are at: > +# > https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md > + > +name: $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.rr) > + > +queue: > + name: Hosted Linux Preview > + > +trigger: > + branches: > + include: > + - master > + - 3.7 > + - 3.6 > + paths: > + exclude: > + - Doc/* > + - Tools/* > + > +variables: > + # Copy-pasted from linux-deps.yml until template support arrives > + OPENSSL: 1.1.0g > + OPENSSL_DIR: "$(build.sourcesDirectory)/multissl/openssl/$(OPENSSL)" > + > + > +steps: > +- checkout: self > + clean: true > + fetchDepth: 5 > + > +#- template: linux-deps.yml > + > +# See > https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted-templates.md > +# For now, we copy/paste the steps > +- script: echo "deb-src http://archive.ubuntu.com/ubuntu/ xenial main" > > /etc/apt/sources.list.d/python.list && sudo apt-get update > + displayName: 'Update apt-get lists' > + > +- script: echo ##vso[task.prependpath]$(OPENSSL_DIR) > + displayName: 'Add $(OPENSSL_DIR) to PATH' > +- script: > > + sudo apt-get -yq install > + build-essential > + zlib1g-dev > + libbz2-dev > + liblzma-dev > + libncurses5-dev > + libreadline6-dev > + libsqlite3-dev > + libssl-dev > + libgdbm-dev > + tk-dev > + lzma > + lzma-dev > + liblzma-dev > + libffi-dev > + uuid-dev > + displayName: 'Install dependencies' > +- script: python3 Tools/ssl/multissltests.py --steps=library > --base-directory $(build.sourcesDirectory)/multissl --openssl $(OPENSSL) > --system Linux > + displayName: 'python multissltests.py' > + > +- script: ./configure --with-pydebug > + displayName: 'Configure CPython (debug)' > + > +- script: make -s -j4 > + displayName: 'Build CPython' > + > +- script: make pythoninfo > + displayName: 'Display build info' > + > +- script: make buildbottest TESTOPTS="-j4 -uall,-cpu" > + displayName: 'Tests' > diff --git a/.vsts/linux-coverage.yml b/.vsts/linux-coverage.yml > new file mode 100644 > index 000000000000..3657b1720ee2 > --- /dev/null > +++ b/.vsts/linux-coverage.yml > @@ -0,0 +1,77 @@ > +# Current docs for the syntax of this file are at: > +# > https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md > + > +name: $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.rr) > + > +queue: > + name: Hosted Linux Preview > + > +trigger: > + branches: > + include: > + - master > + - 3.7 > + - 3.6 > + paths: > + exclude: > + - Doc/* > + - Tools/* > + > +variables: > + # Copy-pasted from linux-deps.yml until template support arrives > + OPENSSL: 1.1.0g > + OPENSSL_DIR: "$(build.sourcesDirectory)/multissl/openssl/$(OPENSSL)" > + > +steps: > +- checkout: self > + clean: true > + fetchDepth: 5 > + > +#- template: linux-deps.yml > + > +# See > https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted-templates.md > +# For now, we copy/paste the steps > +- script: echo "deb-src http://archive.ubuntu.com/ubuntu/ xenial main" > > /etc/apt/sources.list.d/python.list && sudo apt-get update > + displayName: 'Update apt-get lists' > + > +- script: echo ##vso[task.prependpath]$(OPENSSL_DIR) > + displayName: 'Add $(OPENSSL_DIR) to PATH' > +- script: > > + sudo apt-get -yq install > + build-essential > + zlib1g-dev > + libbz2-dev > + liblzma-dev > + libncurses5-dev > + libreadline6-dev > + libsqlite3-dev > + libssl-dev > + libgdbm-dev > + tk-dev > + lzma > + lzma-dev > + liblzma-dev > + libffi-dev > + uuid-dev > + displayName: 'Install dependencies' > +- script: python3 Tools/ssl/multissltests.py --steps=library > --base-directory $(build.sourcesDirectory)/multissl --openssl $(OPENSSL) > --system Linux > + displayName: 'python multissltests.py' > + > + > +- script: ./configure --with-pydebug > + displayName: 'Configure CPython (debug)' > + > +- script: make -s -j4 > + displayName: 'Build CPython' > + > +- script: ./python -m venv venv && ./venv/bin/python -m pip install -U > coverage > + displayName: 'Set up virtual environment' > + > +- script: ./venv/bin/python -m test.pythoninfo > + displayName: 'Display build info' > + > +- script: ./venv/bin/python -m coverage run --pylib -m test > --fail-env-changed -uall,-cpu -x test_multiprocessing_fork -x > test_multiprocessing_forkserver -x test_multiprocessing_spawn -x > test_concurrent_futures > + displayName: 'Tests with coverage' > + > +- script: source ./venv/bin/activate && bash <(curl -s > https://codecov.io/bash) > + displayName: 'Publish code coverage results' > diff --git a/.vsts/linux-deps.yml b/.vsts/linux-deps.yml > new file mode 100644 > index 000000000000..b6c8a3690ea1 > --- /dev/null > +++ b/.vsts/linux-deps.yml > @@ -0,0 +1,36 @@ > +# Note: this file is not currently used, but when template support comes > to VSTS it > +# will be referenced from the other scripts.. > + > +# Current docs for the syntax of this file are at: > +# > https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md > + > +parameters: > + OPENSSL: 1.1.0g > + OPENSSL_DIR: "$(build.sourcesDirectory)/multissl/openssl/$(OPENSSL)" > + > +steps: > +- script: echo "deb-src http://archive.ubuntu.com/ubuntu/ xenial main" > > /etc/apt/sources.list.d/python.list && sudo apt-get update > + displayName: 'Update apt-get lists' > + > +- script: echo ##vso[task.prependpath]$(OPENSSL_DIR) > + displayName: 'Add $(OPENSSL_DIR) to PATH' > +- script: > > + sudo apt-get -yq install > + build-essential > + zlib1g-dev > + libbz2-dev > + liblzma-dev > + libncurses5-dev > + libreadline6-dev > + libsqlite3-dev > + libssl-dev > + libgdbm-dev > + tk-dev > + lzma > + lzma-dev > + liblzma-dev > + libffi-dev > + uuid-dev > + displayName: 'Install dependencies' > +- script: python3 Tools/ssl/multissltests.py --steps=library > --base-directory $(build.sourcesDirectory)/multissl --openssl $(OPENSSL) > --system Linux > + displayName: 'python multissltests.py' > diff --git a/.vsts/linux-pr.yml b/.vsts/linux-pr.yml > new file mode 100644 > index 000000000000..7f4d458f5a7c > --- /dev/null > +++ b/.vsts/linux-pr.yml > @@ -0,0 +1,75 @@ > +# Current docs for the syntax of this file are at: > +# > https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md > + > +name: $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.rr) > + > +queue: > + name: Hosted Linux Preview > + > +trigger: > + branches: > + include: > + - master > + - 3.7 > + - 3.6 > + paths: > + exclude: > + - Doc/* > + - Tools/* > + > +variables: > + # Copy-pasted from linux-deps.yml until template support arrives > + OPENSSL: 1.1.0g > + OPENSSL_DIR: "$(build.sourcesDirectory)/multissl/openssl/$(OPENSSL)" > + > +steps: > +- checkout: self > + clean: true > + fetchDepth: 5 > + > +#- template: linux-deps.yml > + > +# See > https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted-templates.md > +# For now, we copy/paste the steps > +- script: echo "deb-src http://archive.ubuntu.com/ubuntu/ xenial main" > > /etc/apt/sources.list.d/python.list && sudo apt-get update > + displayName: 'Update apt-get lists' > + > +- script: echo ##vso[task.prependpath]$(OPENSSL_DIR) > + displayName: 'Add $(OPENSSL_DIR) to PATH' > +- script: > > + sudo apt-get -yq install > + build-essential > + zlib1g-dev > + libbz2-dev > + liblzma-dev > + libncurses5-dev > + libreadline6-dev > + libsqlite3-dev > + libssl-dev > + libgdbm-dev > + tk-dev > + lzma > + lzma-dev > + liblzma-dev > + libffi-dev > + uuid-dev > + displayName: 'Install dependencies' > +- script: python3 Tools/ssl/multissltests.py --steps=library > --base-directory $(build.sourcesDirectory)/multissl --openssl $(OPENSSL) > --system Linux > + displayName: 'python multissltests.py' > + > + > +- script: ./configure --with-pydebug > + displayName: 'Configure CPython (debug)' > + > +- script: make -s -j4 > + displayName: 'Build CPython' > + > +- script: make pythoninfo > + displayName: 'Display build info' > + > +# Run patchcheck and fail if anything is discovered > +- script: ./python Tools/scripts/patchcheck.py --travis true > + displayName: 'Run patchcheck.py' > + > +- script: make buildbottest TESTOPTS="-j4 -uall,-cpu" > + displayName: 'Tests' > diff --git a/.vsts/macos-buildbot.yml b/.vsts/macos-buildbot.yml > new file mode 100644 > index 000000000000..8a4f6ba8cb8b > --- /dev/null > +++ b/.vsts/macos-buildbot.yml > @@ -0,0 +1,37 @@ > +# Current docs for the syntax of this file are at: > +# > https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md > + > +name: $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.rr) > + > +queue: > + name: Hosted macOS Preview > + > +trigger: > + branches: > + include: > + - master > + - 3.7 > + - 3.6 > + paths: > + exclude: > + - Doc/* > + - Tools/* > + > +#variables: > + > +steps: > +- checkout: self > + clean: true > + fetchDepth: 5 > + > +- script: ./configure --with-pydebug --with-openssl=/usr/local/opt/openssl > + displayName: 'Configure CPython (debug)' > + > +- script: make -s -j4 > + displayName: 'Build CPython' > + > +- script: make pythoninfo > + displayName: 'Display build info' > + > +- script: make buildbottest TESTOPTS="-j4 -uall,-cpu" > + displayName: 'Tests' > diff --git a/.vsts/macos-pr.yml b/.vsts/macos-pr.yml > new file mode 100644 > index 000000000000..8a4f6ba8cb8b > --- /dev/null > +++ b/.vsts/macos-pr.yml > @@ -0,0 +1,37 @@ > +# Current docs for the syntax of this file are at: > +# > https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md > + > +name: $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.rr) > + > +queue: > + name: Hosted macOS Preview > + > +trigger: > + branches: > + include: > + - master > + - 3.7 > + - 3.6 > + paths: > + exclude: > + - Doc/* > + - Tools/* > + > +#variables: > + > +steps: > +- checkout: self > + clean: true > + fetchDepth: 5 > + > +- script: ./configure --with-pydebug --with-openssl=/usr/local/opt/openssl > + displayName: 'Configure CPython (debug)' > + > +- script: make -s -j4 > + displayName: 'Build CPython' > + > +- script: make pythoninfo > + displayName: 'Display build info' > + > +- script: make buildbottest TESTOPTS="-j4 -uall,-cpu" > + displayName: 'Tests' > diff --git a/.vsts/windows-buildbot.yml b/.vsts/windows-buildbot.yml > new file mode 100644 > index 000000000000..5ec4522796ce > --- /dev/null > +++ b/.vsts/windows-buildbot.yml > @@ -0,0 +1,49 @@ > +# Current docs for the syntax of this file are at: > +# > https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md > + > +name: $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.rr) > + > +queue: > + name: Hosted VS2017 > + parallel: 2 > + matrix: > + amd64: > + buildOpt: -p x64 > + outDirSuffix: amd64 > + win32: > + buildOpt: > + outDirSuffix: win32 > + > +trigger: > + branches: > + include: > + - master > + - 3.7 > + - 3.6 > + paths: > + exclude: > + - Doc/* > + - Tools/* > + > +variables: > + # Relocate build outputs outside of source directory to make cleaning > faster > + Py_IntDir: $(Build.BinariesDirectory)\obj > + # UNDONE: Do not build to a different directory because of broken tests > + Py_OutDir: $(Build.SourcesDirectory)\PCbuild > + EXTERNAL_DIR: $(Build.BinariesDirectory)\externals > + > +steps: > +- checkout: self > + clean: true > + fetchDepth: 5 > + > +- script: PCbuild\build.bat -e $(buildOpt) > + displayName: 'Build CPython' > + > +- script: python.bat -m test.pythoninfo > + displayName: 'Display build info' > + > +- script: PCbuild\rt.bat -q -uall -u-cpu -rwW --slowest --timeout=1200 -j0 > + displayName: 'Tests' > + env: > + PREFIX: $(Py_OutDir)\$(outDirSuffix) > diff --git a/.vsts/windows-pr.yml b/.vsts/windows-pr.yml > new file mode 100644 > index 000000000000..5ec4522796ce > --- /dev/null > +++ b/.vsts/windows-pr.yml > @@ -0,0 +1,49 @@ > +# Current docs for the syntax of this file are at: > +# > https://github.com/Microsoft/vsts-agent/blob/master/docs/preview/yamlgettingstarted.md > + > +name: $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.rr) > + > +queue: > + name: Hosted VS2017 > + parallel: 2 > + matrix: > + amd64: > + buildOpt: -p x64 > + outDirSuffix: amd64 > + win32: > + buildOpt: > + outDirSuffix: win32 > + > +trigger: > + branches: > + include: > + - master > + - 3.7 > + - 3.6 > + paths: > + exclude: > + - Doc/* > + - Tools/* > + > +variables: > + # Relocate build outputs outside of source directory to make cleaning > faster > + Py_IntDir: $(Build.BinariesDirectory)\obj > + # UNDONE: Do not build to a different directory because of broken tests > + Py_OutDir: $(Build.SourcesDirectory)\PCbuild > + EXTERNAL_DIR: $(Build.BinariesDirectory)\externals > + > +steps: > +- checkout: self > + clean: true > + fetchDepth: 5 > + > +- script: PCbuild\build.bat -e $(buildOpt) > + displayName: 'Build CPython' > + > +- script: python.bat -m test.pythoninfo > + displayName: 'Display build info' > + > +- script: PCbuild\rt.bat -q -uall -u-cpu -rwW --slowest --timeout=1200 -j0 > + displayName: 'Tests' > + env: > + PREFIX: $(Py_OutDir)\$(outDirSuffix) > diff --git a/Doc/make.bat b/Doc/make.bat > index 6cb315fda405..c69cfae31941 100644 > --- a/Doc/make.bat > +++ b/Doc/make.bat > @@ -5,18 +5,21 @@ pushd %~dp0 > > set this=%~n0 > > -call ..\PCBuild\find_python.bat %PYTHON% > -if not defined SPHINXBUILD if defined PYTHON ( > +call ..\PCbuild\find_python.bat %PYTHON% > + > +if not defined PYTHON set PYTHON=py > + > +if not defined SPHINXBUILD ( > %PYTHON% -c "import sphinx" > nul 2> nul > if errorlevel 1 ( > echo Installing sphinx with %PYTHON% > - %PYTHON% -m pip install sphinx > + %PYTHON% -m pip install sphinx python-docs-theme > if errorlevel 1 exit /B > ) > set SPHINXBUILD=%PYTHON% -c "import sphinx, sys; sys.argv[0] = > 'sphinx-build'; sphinx.main()" > ) > > -if not defined BLURB if defined PYTHON ( > +if not defined BLURB ( > %PYTHON% -c "import blurb" > nul 2> nul > if errorlevel 1 ( > echo Installing blurb with %PYTHON% > @@ -26,7 +29,6 @@ if not defined BLURB if defined PYTHON ( > set BLURB=%PYTHON% -m blurb > ) > > -if not defined PYTHON set PYTHON=py > if not defined SPHINXBUILD set SPHINXBUILD=sphinx-build > if not defined BLURB set BLURB=blurb > > diff --git a/Lib/tempfile.py b/Lib/tempfile.py > index 38738082b996..2cb5434ba7b5 100644 > --- a/Lib/tempfile.py > +++ b/Lib/tempfile.py > @@ -173,7 +173,9 @@ def _candidate_tempdir_list(): > > # Failing that, try OS-specific locations. > if _os.name == 'nt': > - dirlist.extend([ r'c:\temp', r'c:\tmp', r'\temp', r'\tmp' ]) > + dirlist.extend([ _os.path.expanduser(r'~\AppData\Local\Temp'), > + _os.path.expandvars(r'%SYSTEMROOT%\Temp'), > + r'c:\temp', r'c:\tmp', r'\temp', r'\tmp' ]) > else: > dirlist.extend([ '/tmp', '/var/tmp', '/usr/tmp' ]) > > diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py > index 867124b63e24..e46394e89d1f 100644 > --- a/Lib/test/support/__init__.py > +++ b/Lib/test/support/__init__.py > @@ -366,6 +366,20 @@ def _rmtree_inner(path): > _force_run(fullname, os.unlink, fullname) > _waitfor(_rmtree_inner, path, waitall=True) > _waitfor(lambda p: _force_run(p, os.rmdir, p), path) > + > + def _longpath(path): > + try: > + import ctypes > + except ImportError: > + # No ctypes means we can't expands paths. > + pass > + else: > + buffer = ctypes.create_unicode_buffer(len(path) * 2) > + length = ctypes.windll.kernel32.GetLongPathNameW(path, buffer, > + len(buffer)) > + if length: > + return buffer[:length] > + return path > else: > _unlink = os.unlink > _rmdir = os.rmdir > @@ -392,6 +406,9 @@ def _rmtree_inner(path): > _rmtree_inner(path) > os.rmdir(path) > > + def _longpath(path): > + return path > + > def unlink(filename): > try: > _unlink(filename) > @@ -2333,13 +2350,15 @@ def can_xattr(): > if not hasattr(os, "setxattr"): > can = False > else: > - tmp_fp, tmp_name = tempfile.mkstemp() > + tmp_dir = tempfile.mkdtemp() > + tmp_fp, tmp_name = tempfile.mkstemp(dir=tmp_dir) > try: > with open(TESTFN, "wb") as fp: > try: > # TESTFN & tempfile may use different file systems > with > # different capabilities > os.setxattr(tmp_fp, b"user.test", b"") > + os.setxattr(tmp_name, b"trusted.foo", b"42") > os.setxattr(fp.fileno(), b"user.test", b"") > # Kernels < 2.6.39 don't respect setxattr flags. > kernel_version = platform.release() > @@ -2350,6 +2369,7 @@ def can_xattr(): > finally: > unlink(TESTFN) > unlink(tmp_name) > + rmdir(tmp_dir) > _can_xattr = can > return can > > diff --git a/Lib/test/test_asyncio/test_base_events.py > b/Lib/test/test_asyncio/test_base_events.py > index 830f0d84a9d4..42c0707e8f21 100644 > --- a/Lib/test/test_asyncio/test_base_events.py > +++ b/Lib/test/test_asyncio/test_base_events.py > @@ -1750,5 +1750,6 @@ def runner(loop): > outer_loop.close() > > > + > if __name__ == '__main__': > unittest.main() > diff --git a/Lib/test/test_bdb.py b/Lib/test/test_bdb.py > index abefe6c4e57a..a36667869718 100644 > --- a/Lib/test/test_bdb.py > +++ b/Lib/test/test_bdb.py > @@ -417,15 +417,17 @@ def __init__(self, test_case, skip=None): > self.dry_run = test_case.dry_run > self.tracer = Tracer(test_case.expect_set, skip=skip, > dry_run=self.dry_run, test_case=test_case.id > ()) > + self._original_tracer = None > > def __enter__(self): > # test_pdb does not reset Breakpoint class attributes on exit :-( > reset_Breakpoint() > + self._original_tracer = sys.gettrace() > return self.tracer > > def __exit__(self, type_=None, value=None, traceback=None): > reset_Breakpoint() > - sys.settrace(None) > + sys.settrace(self._original_tracer) > > not_empty = '' > if self.tracer.set_list: > diff --git a/Lib/test/test_pathlib.py b/Lib/test/test_pathlib.py > index db53a8f202dc..bf9467e96e09 100644 > --- a/Lib/test/test_pathlib.py > +++ b/Lib/test/test_pathlib.py > @@ -1531,7 +1531,7 @@ def test_resolve_common(self): > # resolves to 'dirB/..' first before resolving to parent of > dirB. > self._check_resolve_relative(p, P(BASE, 'foo', 'in', 'spam'), > False) > # Now create absolute symlinks > - d = tempfile.mkdtemp(suffix='-dirD') > + d = support._longpath(tempfile.mkdtemp(suffix='-dirD')) > self.addCleanup(support.rmtree, d) > os.symlink(os.path.join(d), join('dirA', 'linkX')) > os.symlink(join('dirB'), os.path.join(d, 'linkY')) > diff --git a/Lib/test/test_poplib.py b/Lib/test/test_poplib.py > index ca9bc6217509..234c855545c2 100644 > --- a/Lib/test/test_poplib.py > +++ b/Lib/test/test_poplib.py > @@ -217,11 +217,12 @@ def start(self): > def run(self): > self.active = True > self.__flag.set() > - while self.active and asyncore.socket_map: > - self.active_lock.acquire() > - asyncore.loop(timeout=0.1, count=1) > - self.active_lock.release() > - asyncore.close_all(ignore_all=True) > + try: > + while self.active and asyncore.socket_map: > + with self.active_lock: > + asyncore.loop(timeout=0.1, count=1) > + finally: > + asyncore.close_all(ignore_all=True) > > def stop(self): > assert self.active > diff --git a/Lib/test/test_selectors.py b/Lib/test/test_selectors.py > index 852b2feb45fd..14ce91f3768c 100644 > --- a/Lib/test/test_selectors.py > +++ b/Lib/test/test_selectors.py > @@ -450,7 +450,14 @@ def test_above_fd_setsize(self): > self.skipTest("FD limit reached") > raise > > - self.assertEqual(NUM_FDS // 2, len(s.select())) > + try: > + fds = s.select() > + except OSError as e: > + if e.errno == errno.EINVAL and sys.platform == 'darwin': > + # unexplainable errors on macOS don't need to fail the > test > + self.skipTest("Invalid argument error calling poll()") > + raise > + self.assertEqual(NUM_FDS // 2, len(fds)) > > > class DefaultSelectorTestCase(BaseSelectorTestCase): > diff --git > a/Misc/NEWS.d/next/Build/2018-05-15-12-44-50.bpo-33522.mJoNcA.rst > b/Misc/NEWS.d/next/Build/2018-05-15-12-44-50.bpo-33522.mJoNcA.rst > new file mode 100644 > index 000000000000..f44862f0c454 > --- /dev/null > +++ b/Misc/NEWS.d/next/Build/2018-05-15-12-44-50.bpo-33522.mJoNcA.rst > @@ -0,0 +1,2 @@ > +Enable CI builds on Visual Studio Team Services at > +https://python.visualstudio.com/cpython > diff --git > a/Misc/NEWS.d/next/Library/2018-05-16-17-05-48.bpo-33548.xWslmx.rst > b/Misc/NEWS.d/next/Library/2018-05-16-17-05-48.bpo-33548.xWslmx.rst > new file mode 100644 > index 000000000000..65585c152987 > --- /dev/null > +++ b/Misc/NEWS.d/next/Library/2018-05-16-17-05-48.bpo-33548.xWslmx.rst > @@ -0,0 +1 @@ > +tempfile._candidate_tempdir_list should consider common TEMP locations > diff --git a/PCbuild/rt.bat b/PCbuild/rt.bat > index 808102f826d3..212befc95b06 100644 > --- a/PCbuild/rt.bat > +++ b/PCbuild/rt.bat > @@ -7,7 +7,7 @@ rem -q "quick" -- normally the tests are run twice, the > first time > rem after deleting all the .pyc files reachable from Lib/. > rem -q runs the tests just once, and without deleting .pyc files. > rem -x64 Run the 64-bit build of python (or python_d if -d was specified) > -rem from the 'amd64' dir instead of the 32-bit build in this dir. > +rem When omitted, uses %PREFIX% if set or the 32-bit build > rem All leading instances of these switches are shifted off, and > rem whatever remains (up to 9 arguments) is passed to regrtest.py. > rem For example, > @@ -28,28 +28,29 @@ rem rt -u "network,largefile" > setlocal > > set pcbuild=%~dp0 > -set prefix=%pcbuild%win32\ > set suffix= > set qmode= > set dashO= > set regrtestargs= > +set exe= > > :CheckOpts > if "%1"=="-O" (set dashO=-O) & shift & goto CheckOpts > if "%1"=="-q" (set qmode=yes) & shift & goto CheckOpts > if "%1"=="-d" (set suffix=_d) & shift & goto CheckOpts > -if "%1"=="-x64" (set prefix=%pcbuild%amd64\) & shift & goto CheckOpts > +if "%1"=="-x64" (set prefix=%pcbuild%amd64) & shift & goto CheckOpts > if NOT "%1"=="" (set regrtestargs=%regrtestargs% %1) & shift & goto > CheckOpts > > -set exe=%prefix%python%suffix%.exe > -set cmd="%exe%" %dashO% -Wd -E -bb -m test %regrtestargs% > +if not defined prefix set prefix=%pcbuild%win32 > +set exe=%prefix%\python%suffix%.exe > +set cmd="%exe%" %dashO% -u -Wd -E -bb -m test %regrtestargs% > if defined qmode goto Qmode > > echo Deleting .pyc files ... > "%exe%" "%pcbuild%rmpyc.py" > > echo Cleaning _pth files ... > -if exist %prefix%*._pth del %prefix%*._pth > +if exist %prefix%\*._pth del %prefix%\*._pth > > echo on > %cmd% > diff --git a/Tools/ssl/multissltests.py b/Tools/ssl/multissltests.py > index ba4529ae0611..f3241cd6071c 100755 > --- a/Tools/ssl/multissltests.py > +++ b/Tools/ssl/multissltests.py > @@ -123,6 +123,11 @@ > action='store_true', > help="Don't run tests, only compile _ssl.c and _hashopenssl.c." > ) > +parser.add_argument( > + '--system', > + default='', > + help="Override the automatic system type detection." > +) > > > class AbstractBuilder(object): > @@ -150,6 +155,7 @@ def __init__(self, version, compile_args=(), > # build directory (removed after install) > self.build_dir = os.path.join( > self.src_dir, self.build_template.format(version)) > + self.system = args.system > > def __str__(self): > return "<{0.__class__.__name__} for {0.version}>".format(self) > @@ -254,9 +260,13 @@ def _build_src(self): > cwd = self.build_dir > cmd = ["./config", "shared", > "--prefix={}".format(self.install_dir)] > cmd.extend(self.compile_args) > - self._subprocess_call(cmd, cwd=cwd) > + env = None > + if self.system: > + env = os.environ.copy() > + env['SYSTEM'] = self.system > + self._subprocess_call(cmd, cwd=cwd, env=env) > # Old OpenSSL versions do not support parallel builds. > - self._subprocess_call(["make", "-j1"], cwd=cwd) > + self._subprocess_call(["make", "-j1"], cwd=cwd, env=env) > > def _make_install(self, remove=True): > self._subprocess_call(["make", "-j1", "install"], > cwd=self.build_dir) > > _______________________________________________ > Python-checkins mailing list > Python-checkins at python.org > https://mail.python.org/mailman/listinfo/python-checkins > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.python.org/pipermail/python-checkins/attachments/20180517/5fca457e/attachment-0001.html> From solipsis at pitrou.net Fri May 18 05:19:00 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 18 May 2018 09:19:00 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=4 Message-ID: <20180518091900.1.A9FB4224D1C23E25@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_asyncio leaked [3, 0, 0] memory blocks, sum=3 test_collections leaked [0, -7, 1] memory blocks, sum=-6 test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_fork leaked [1, -2, 2] memory blocks, sum=1 test_multiprocessing_spawn leaked [2, -1, 1] memory blocks, sum=2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflog4ZJ9UB', '--timeout', '7200'] From webhook-mailer at python.org Fri May 18 09:33:04 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Fri, 18 May 2018 13:33:04 -0000 Subject: [Python-checkins] Fix C API docs: PyCapsule_Import always set an exception on failure. (GH-6967) Message-ID: <mailman.133.1526650386.2757.python-checkins@python.org> https://github.com/python/cpython/commit/bde3e0bf096219234321ca9898fc3d3aed598453 commit: bde3e0bf096219234321ca9898fc3d3aed598453 branch: master author: Serhiy Storchaka <storchaka at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-18T16:32:54+03:00 summary: Fix C API docs: PyCapsule_Import always set an exception on failure. (GH-6967) files: M Doc/c-api/capsule.rst diff --git a/Doc/c-api/capsule.rst b/Doc/c-api/capsule.rst index b8642d0aba92..8eb6695e22de 100644 --- a/Doc/c-api/capsule.rst +++ b/Doc/c-api/capsule.rst @@ -9,6 +9,8 @@ Capsules Refer to :ref:`using-capsules` for more information on using these objects. +.. versionadded:: 3.1 + .. c:type:: PyCapsule @@ -19,6 +21,7 @@ Refer to :ref:`using-capsules` for more information on using these objects. regular import mechanism can be used to access C APIs defined in dynamically loaded modules. + .. c:type:: PyCapsule_Destructor The type of a destructor callback for a capsule. Defined as:: @@ -104,8 +107,8 @@ Refer to :ref:`using-capsules` for more information on using these objects. import the module conventionally (using :c:func:`PyImport_ImportModule`). Return the capsule's internal *pointer* on success. On failure, set an - exception and return *NULL*. However, if :c:func:`PyCapsule_Import` failed to - import the module, and *no_block* was true, no exception is set. + exception and return *NULL*. + .. c:function:: int PyCapsule_IsValid(PyObject *capsule, const char *name) @@ -122,18 +125,21 @@ Refer to :ref:`using-capsules` for more information on using these objects. Return a nonzero value if the object is valid and matches the name passed in. Return ``0`` otherwise. This function will not fail. + .. c:function:: int PyCapsule_SetContext(PyObject *capsule, void *context) Set the context pointer inside *capsule* to *context*. Return ``0`` on success. Return nonzero and set an exception on failure. + .. c:function:: int PyCapsule_SetDestructor(PyObject *capsule, PyCapsule_Destructor destructor) Set the destructor inside *capsule* to *destructor*. Return ``0`` on success. Return nonzero and set an exception on failure. + .. c:function:: int PyCapsule_SetName(PyObject *capsule, const char *name) Set the name inside *capsule* to *name*. If non-*NULL*, the name must @@ -142,6 +148,7 @@ Refer to :ref:`using-capsules` for more information on using these objects. Return ``0`` on success. Return nonzero and set an exception on failure. + .. c:function:: int PyCapsule_SetPointer(PyObject *capsule, void *pointer) Set the void pointer inside *capsule* to *pointer*. The pointer may not be From webhook-mailer at python.org Fri May 18 09:48:40 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 18 May 2018 13:48:40 -0000 Subject: [Python-checkins] Fix C API docs: PyCapsule_Import always set an exception on failure. (GH-6967) Message-ID: <mailman.134.1526651321.2757.python-checkins@python.org> https://github.com/python/cpython/commit/bef703107d9e5d48e6609f2f037abe0b56081afc commit: bef703107d9e5d48e6609f2f037abe0b56081afc branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-18T06:48:36-07:00 summary: Fix C API docs: PyCapsule_Import always set an exception on failure. (GH-6967) (cherry picked from commit bde3e0bf096219234321ca9898fc3d3aed598453) Co-authored-by: Serhiy Storchaka <storchaka at gmail.com> files: M Doc/c-api/capsule.rst diff --git a/Doc/c-api/capsule.rst b/Doc/c-api/capsule.rst index b8642d0aba92..8eb6695e22de 100644 --- a/Doc/c-api/capsule.rst +++ b/Doc/c-api/capsule.rst @@ -9,6 +9,8 @@ Capsules Refer to :ref:`using-capsules` for more information on using these objects. +.. versionadded:: 3.1 + .. c:type:: PyCapsule @@ -19,6 +21,7 @@ Refer to :ref:`using-capsules` for more information on using these objects. regular import mechanism can be used to access C APIs defined in dynamically loaded modules. + .. c:type:: PyCapsule_Destructor The type of a destructor callback for a capsule. Defined as:: @@ -104,8 +107,8 @@ Refer to :ref:`using-capsules` for more information on using these objects. import the module conventionally (using :c:func:`PyImport_ImportModule`). Return the capsule's internal *pointer* on success. On failure, set an - exception and return *NULL*. However, if :c:func:`PyCapsule_Import` failed to - import the module, and *no_block* was true, no exception is set. + exception and return *NULL*. + .. c:function:: int PyCapsule_IsValid(PyObject *capsule, const char *name) @@ -122,18 +125,21 @@ Refer to :ref:`using-capsules` for more information on using these objects. Return a nonzero value if the object is valid and matches the name passed in. Return ``0`` otherwise. This function will not fail. + .. c:function:: int PyCapsule_SetContext(PyObject *capsule, void *context) Set the context pointer inside *capsule* to *context*. Return ``0`` on success. Return nonzero and set an exception on failure. + .. c:function:: int PyCapsule_SetDestructor(PyObject *capsule, PyCapsule_Destructor destructor) Set the destructor inside *capsule* to *destructor*. Return ``0`` on success. Return nonzero and set an exception on failure. + .. c:function:: int PyCapsule_SetName(PyObject *capsule, const char *name) Set the name inside *capsule* to *name*. If non-*NULL*, the name must @@ -142,6 +148,7 @@ Refer to :ref:`using-capsules` for more information on using these objects. Return ``0`` on success. Return nonzero and set an exception on failure. + .. c:function:: int PyCapsule_SetPointer(PyObject *capsule, void *pointer) Set the void pointer inside *capsule* to *pointer*. The pointer may not be From webhook-mailer at python.org Fri May 18 09:53:52 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 18 May 2018 13:53:52 -0000 Subject: [Python-checkins] Fix C API docs: PyCapsule_Import always set an exception on failure. (GH-6967) Message-ID: <mailman.135.1526651632.2757.python-checkins@python.org> https://github.com/python/cpython/commit/e6e440ad5cf327c663224094f3efee1cedc39d89 commit: e6e440ad5cf327c663224094f3efee1cedc39d89 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-18T06:53:42-07:00 summary: Fix C API docs: PyCapsule_Import always set an exception on failure. (GH-6967) (cherry picked from commit bde3e0bf096219234321ca9898fc3d3aed598453) Co-authored-by: Serhiy Storchaka <storchaka at gmail.com> files: M Doc/c-api/capsule.rst diff --git a/Doc/c-api/capsule.rst b/Doc/c-api/capsule.rst index b8642d0aba92..8eb6695e22de 100644 --- a/Doc/c-api/capsule.rst +++ b/Doc/c-api/capsule.rst @@ -9,6 +9,8 @@ Capsules Refer to :ref:`using-capsules` for more information on using these objects. +.. versionadded:: 3.1 + .. c:type:: PyCapsule @@ -19,6 +21,7 @@ Refer to :ref:`using-capsules` for more information on using these objects. regular import mechanism can be used to access C APIs defined in dynamically loaded modules. + .. c:type:: PyCapsule_Destructor The type of a destructor callback for a capsule. Defined as:: @@ -104,8 +107,8 @@ Refer to :ref:`using-capsules` for more information on using these objects. import the module conventionally (using :c:func:`PyImport_ImportModule`). Return the capsule's internal *pointer* on success. On failure, set an - exception and return *NULL*. However, if :c:func:`PyCapsule_Import` failed to - import the module, and *no_block* was true, no exception is set. + exception and return *NULL*. + .. c:function:: int PyCapsule_IsValid(PyObject *capsule, const char *name) @@ -122,18 +125,21 @@ Refer to :ref:`using-capsules` for more information on using these objects. Return a nonzero value if the object is valid and matches the name passed in. Return ``0`` otherwise. This function will not fail. + .. c:function:: int PyCapsule_SetContext(PyObject *capsule, void *context) Set the context pointer inside *capsule* to *context*. Return ``0`` on success. Return nonzero and set an exception on failure. + .. c:function:: int PyCapsule_SetDestructor(PyObject *capsule, PyCapsule_Destructor destructor) Set the destructor inside *capsule* to *destructor*. Return ``0`` on success. Return nonzero and set an exception on failure. + .. c:function:: int PyCapsule_SetName(PyObject *capsule, const char *name) Set the name inside *capsule* to *name*. If non-*NULL*, the name must @@ -142,6 +148,7 @@ Refer to :ref:`using-capsules` for more information on using these objects. Return ``0`` on success. Return nonzero and set an exception on failure. + .. c:function:: int PyCapsule_SetPointer(PyObject *capsule, void *pointer) Set the void pointer inside *capsule* to *pointer*. The pointer may not be From webhook-mailer at python.org Fri May 18 10:19:24 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Fri, 18 May 2018 14:19:24 -0000 Subject: [Python-checkins] [2.7] Fix C API docs: PyCapsule_Import always set an exception on failure. (GH-6967) (GH-6970) Message-ID: <mailman.137.1526653164.2757.python-checkins@python.org> https://github.com/python/cpython/commit/6a8954a91a30954b5c4aa469ced9d14702cf2c58 commit: 6a8954a91a30954b5c4aa469ced9d14702cf2c58 branch: 2.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Serhiy Storchaka <storchaka at gmail.com> date: 2018-05-18T17:19:21+03:00 summary: [2.7] Fix C API docs: PyCapsule_Import always set an exception on failure. (GH-6967) (GH-6970) (cherry picked from commit bde3e0bf096219234321ca9898fc3d3aed598453) files: M Doc/c-api/capsule.rst diff --git a/Doc/c-api/capsule.rst b/Doc/c-api/capsule.rst index b8642d0aba92..fd4279cd9622 100644 --- a/Doc/c-api/capsule.rst +++ b/Doc/c-api/capsule.rst @@ -9,6 +9,8 @@ Capsules Refer to :ref:`using-capsules` for more information on using these objects. +.. versionadded:: 2.7 + .. c:type:: PyCapsule @@ -19,6 +21,7 @@ Refer to :ref:`using-capsules` for more information on using these objects. regular import mechanism can be used to access C APIs defined in dynamically loaded modules. + .. c:type:: PyCapsule_Destructor The type of a destructor callback for a capsule. Defined as:: @@ -104,8 +107,8 @@ Refer to :ref:`using-capsules` for more information on using these objects. import the module conventionally (using :c:func:`PyImport_ImportModule`). Return the capsule's internal *pointer* on success. On failure, set an - exception and return *NULL*. However, if :c:func:`PyCapsule_Import` failed to - import the module, and *no_block* was true, no exception is set. + exception and return *NULL*. + .. c:function:: int PyCapsule_IsValid(PyObject *capsule, const char *name) @@ -122,18 +125,21 @@ Refer to :ref:`using-capsules` for more information on using these objects. Return a nonzero value if the object is valid and matches the name passed in. Return ``0`` otherwise. This function will not fail. + .. c:function:: int PyCapsule_SetContext(PyObject *capsule, void *context) Set the context pointer inside *capsule* to *context*. Return ``0`` on success. Return nonzero and set an exception on failure. + .. c:function:: int PyCapsule_SetDestructor(PyObject *capsule, PyCapsule_Destructor destructor) Set the destructor inside *capsule* to *destructor*. Return ``0`` on success. Return nonzero and set an exception on failure. + .. c:function:: int PyCapsule_SetName(PyObject *capsule, const char *name) Set the name inside *capsule* to *name*. If non-*NULL*, the name must @@ -142,6 +148,7 @@ Refer to :ref:`using-capsules` for more information on using these objects. Return ``0`` on success. Return nonzero and set an exception on failure. + .. c:function:: int PyCapsule_SetPointer(PyObject *capsule, void *pointer) Set the void pointer inside *capsule* to *pointer*. The pointer may not be From webhook-mailer at python.org Fri May 18 13:38:30 2018 From: webhook-mailer at python.org (Berker Peksag) Date: Fri, 18 May 2018 17:38:30 -0000 Subject: [Python-checkins] bpo-32282: Remove unnecessary check for `VersionHelpers.h` in `socketmodule.c` on Windows (GH-5120) Message-ID: <mailman.138.1526665112.2757.python-checkins@python.org> https://github.com/python/cpython/commit/09eb6fe8fdd2515546b933902aef36b72d417ace commit: 09eb6fe8fdd2515546b933902aef36b72d417ace branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Berker Peksag <berker.peksag at gmail.com> date: 2018-05-18T20:38:19+03:00 summary: bpo-32282: Remove unnecessary check for `VersionHelpers.h` in `socketmodule.c` on Windows (GH-5120) (cherry picked from commit af11a15c586e980a157c04ee60b6e33dc7228f3f) files: A Misc/NEWS.d/next/Core and Builtins/2017-12-12-14-02-28.bpo-32282.xFVMTn.rst M Modules/socketmodule.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-12-12-14-02-28.bpo-32282.xFVMTn.rst b/Misc/NEWS.d/next/Core and Builtins/2017-12-12-14-02-28.bpo-32282.xFVMTn.rst new file mode 100644 index 000000000000..1c833c5439b1 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-12-12-14-02-28.bpo-32282.xFVMTn.rst @@ -0,0 +1,2 @@ +Fix an unnecessary ifdef in the include of VersionHelpers.h in socketmodule +on Windows. diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 36920f7f8633..ff73a3fbfa2b 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -312,10 +312,8 @@ if_indextoname(index) -- return the corresponding interface name\n\ # include <fcntl.h> # endif -#if defined(_MSC_VER) && _MSC_VER >= 1800 /* Provides the IsWindows7SP1OrGreater() function */ #include <VersionHelpers.h> -#endif /* remove some flags on older version Windows during run-time. https://msdn.microsoft.com/en-us/library/windows/desktop/ms738596.aspx */ @@ -6571,15 +6569,7 @@ PyInit__socket(void) #ifdef MS_WINDOWS if (support_wsa_no_inherit == -1) { -#if defined(_MSC_VER) && _MSC_VER >= 1800 support_wsa_no_inherit = IsWindows7SP1OrGreater(); -#else - DWORD version = GetVersion(); - DWORD major = (DWORD)LOBYTE(LOWORD(version)); - DWORD minor = (DWORD)HIBYTE(LOWORD(version)); - /* need Windows 7 SP1, 2008 R2 SP1 or later */ - support_wsa_no_inherit = major > 6 || (major == 6 && minor >= 1); -#endif } #endif From webhook-mailer at python.org Fri May 18 14:38:43 2018 From: webhook-mailer at python.org (Zachary Ware) Date: Fri, 18 May 2018 18:38:43 -0000 Subject: [Python-checkins] bpo-33556: Remove reference to thread module from docstring (GH-6963) Message-ID: <mailman.139.1526668725.2757.python-checkins@python.org> https://github.com/python/cpython/commit/5634331a76dfe9fbe4b76475e11307a0922d6a15 commit: 5634331a76dfe9fbe4b76475e11307a0922d6a15 branch: master author: Skip Montanaro <skip.montanaro at gmail.com> committer: Zachary Ware <zachary.ware at gmail.com> date: 2018-05-18T13:38:36-05:00 summary: bpo-33556: Remove reference to thread module from docstring (GH-6963) files: M Lib/threading.py diff --git a/Lib/threading.py b/Lib/threading.py index 418116faceb7..bb41456fb141 100644 --- a/Lib/threading.py +++ b/Lib/threading.py @@ -1069,7 +1069,7 @@ def name(self, name): def ident(self): """Thread identifier of this thread or None if it has not been started. - This is a nonzero integer. See the thread.get_ident() function. Thread + This is a nonzero integer. See the get_ident() function. Thread identifiers may be recycled when a thread exits and another thread is created. The identifier is available even after the thread has exited. From webhook-mailer at python.org Fri May 18 15:32:22 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 18 May 2018 19:32:22 -0000 Subject: [Python-checkins] bpo-33556: Remove reference to thread module from docstring (GH-6963) Message-ID: <mailman.140.1526671945.2757.python-checkins@python.org> https://github.com/python/cpython/commit/c6a5cc8f244ee71ce932003366411aacadda8dd0 commit: c6a5cc8f244ee71ce932003366411aacadda8dd0 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-18T12:32:12-07:00 summary: bpo-33556: Remove reference to thread module from docstring (GH-6963) (cherry picked from commit 5634331a76dfe9fbe4b76475e11307a0922d6a15) Co-authored-by: Skip Montanaro <skip.montanaro at gmail.com> files: M Lib/threading.py diff --git a/Lib/threading.py b/Lib/threading.py index bb2556544b07..0ab1e462f0f0 100644 --- a/Lib/threading.py +++ b/Lib/threading.py @@ -1093,7 +1093,7 @@ def name(self, name): def ident(self): """Thread identifier of this thread or None if it has not been started. - This is a nonzero integer. See the thread.get_ident() function. Thread + This is a nonzero integer. See the get_ident() function. Thread identifiers may be recycled when a thread exits and another thread is created. The identifier is available even after the thread has exited. From webhook-mailer at python.org Fri May 18 15:46:53 2018 From: webhook-mailer at python.org (Zachary Ware) Date: Fri, 18 May 2018 19:46:53 -0000 Subject: [Python-checkins] bpo-33556: Remove reference to thread module from docstring (GH-6963) Message-ID: <mailman.141.1526672816.2757.python-checkins@python.org> https://github.com/python/cpython/commit/abde17e663edd6437cc7eb0405fe418449a25d72 commit: abde17e663edd6437cc7eb0405fe418449a25d72 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Zachary Ware <zachary.ware at gmail.com> date: 2018-05-18T14:46:43-05:00 summary: bpo-33556: Remove reference to thread module from docstring (GH-6963) (cherry picked from commit 5634331a76dfe9fbe4b76475e11307a0922d6a15) Co-authored-by: Skip Montanaro <skip.montanaro at gmail.com> files: M Lib/threading.py diff --git a/Lib/threading.py b/Lib/threading.py index 418116faceb7..bb41456fb141 100644 --- a/Lib/threading.py +++ b/Lib/threading.py @@ -1069,7 +1069,7 @@ def name(self, name): def ident(self): """Thread identifier of this thread or None if it has not been started. - This is a nonzero integer. See the thread.get_ident() function. Thread + This is a nonzero integer. See the get_ident() function. Thread identifiers may be recycled when a thread exits and another thread is created. The identifier is available even after the thread has exited. From webhook-mailer at python.org Fri May 18 19:00:49 2018 From: webhook-mailer at python.org (Ivan Levkivskyi) Date: Fri, 18 May 2018 23:00:49 -0000 Subject: [Python-checkins] bpo-28556: Don't simplify unions at runtime (GH-6841) Message-ID: <mailman.143.1526684453.2757.python-checkins@python.org> https://github.com/python/cpython/commit/f65e31fee3b55dfb6ed5398179d5c5d6b502dee5 commit: f65e31fee3b55dfb6ed5398179d5c5d6b502dee5 branch: master author: Ivan Levkivskyi <levkivskyi at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-18T16:00:38-07:00 summary: bpo-28556: Don't simplify unions at runtime (GH-6841) files: A Misc/NEWS.d/next/Library/2018-05-17-22-53-08.bpo-28556.C6Hnd1.rst M Doc/library/typing.rst M Lib/test/test_typing.py M Lib/typing.py diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index 142e169b89c4..be6636eea08f 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -961,16 +961,15 @@ The module defines the following classes, functions and decorators: Union[int, str] == Union[str, int] - * When a class and its subclass are present, the latter is skipped, e.g.:: - - Union[int, object] == object - * You cannot subclass or instantiate a union. * You cannot write ``Union[X][Y]``. * You can use ``Optional[X]`` as a shorthand for ``Union[X, None]``. + .. versionchanged:: 3.7 + Don't remove explicit subclasses from unions at runtime. + .. data:: Optional Optional type. diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index be768f12fb4c..904cd93691a1 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -253,10 +253,11 @@ def test_union_any(self): def test_union_object(self): u = Union[object] self.assertEqual(u, object) - u = Union[int, object] - self.assertEqual(u, object) - u = Union[object, int] - self.assertEqual(u, object) + u1 = Union[int, object] + u2 = Union[object, int] + self.assertEqual(u1, u2) + self.assertNotEqual(u1, object) + self.assertNotEqual(u2, object) def test_unordered(self): u1 = Union[int, float] @@ -267,13 +268,11 @@ def test_single_class_disappears(self): t = Union[Employee] self.assertIs(t, Employee) - def test_base_class_disappears(self): - u = Union[Employee, Manager, int] - self.assertEqual(u, Union[int, Employee]) - u = Union[Manager, int, Employee] - self.assertEqual(u, Union[int, Employee]) + def test_base_class_kept(self): u = Union[Employee, Manager] - self.assertIs(u, Employee) + self.assertNotEqual(u, Employee) + self.assertIn(Employee, u.__args__) + self.assertIn(Manager, u.__args__) def test_union_union(self): u = Union[int, float] @@ -317,7 +316,8 @@ def test_cannot_instantiate(self): def test_union_generalization(self): self.assertFalse(Union[str, typing.Iterable[int]] == str) self.assertFalse(Union[str, typing.Iterable[int]] == typing.Iterable[int]) - self.assertTrue(Union[str, typing.Iterable] == typing.Iterable) + self.assertIn(str, Union[str, typing.Iterable[int]].__args__) + self.assertIn(typing.Iterable[int], Union[str, typing.Iterable[int]].__args__) def test_union_compare_other(self): self.assertNotEqual(Union, object) @@ -917,7 +917,7 @@ def test_extended_generic_rules_eq(self): self.assertEqual(Union[T, U][int, Union[int, str]], Union[int, str]) class Base: ... class Derived(Base): ... - self.assertEqual(Union[T, Base][Derived], Base) + self.assertEqual(Union[T, Base][Union[Base, Derived]], Union[Base, Derived]) with self.assertRaises(TypeError): Union[T, int][1] diff --git a/Lib/typing.py b/Lib/typing.py index b10615c07fbd..3e82c6b1bb21 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -206,8 +206,8 @@ def _check_generic(cls, parameters): def _remove_dups_flatten(parameters): - """An internal helper for Union creation and substitution: flatten Union's - among parameters, then remove duplicates and strict subclasses. + """An internal helper for Union creation and substitution: flatten Unions + among parameters, then remove duplicates. """ # Flatten out Union[Union[...], ...]. params = [] @@ -228,20 +228,7 @@ def _remove_dups_flatten(parameters): all_params.remove(t) params = new_params assert not all_params, all_params - # Weed out subclasses. - # E.g. Union[int, Employee, Manager] == Union[int, Employee]. - # If object is present it will be sole survivor among proper classes. - # Never discard type variables. - # (In particular, Union[str, AnyStr] != AnyStr.) - all_params = set(params) - for t1 in params: - if not isinstance(t1, type): - continue - if any((isinstance(t2, type) or - isinstance(t2, _GenericAlias) and t2._special) and issubclass(t1, t2) - for t2 in all_params - {t1}): - all_params.remove(t1) - return tuple(t for t in params if t in all_params) + return tuple(params) _cleanups = [] @@ -440,19 +427,6 @@ class Starship: Union[int, str] == Union[str, int] - - When two arguments have a subclass relationship, the least - derived argument is kept, e.g.:: - - class Employee: pass - class Manager(Employee): pass - Union[int, Employee, Manager] == Union[int, Employee] - Union[Manager, int, Employee] == Union[int, Employee] - Union[Employee, Manager] == Employee - - - Similar for object:: - - Union[int, object] == object - - You cannot subclass or instantiate a union. - You can use Optional[X] as a shorthand for Union[X, None]. """) diff --git a/Misc/NEWS.d/next/Library/2018-05-17-22-53-08.bpo-28556.C6Hnd1.rst b/Misc/NEWS.d/next/Library/2018-05-17-22-53-08.bpo-28556.C6Hnd1.rst new file mode 100644 index 000000000000..35e13bde1897 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-17-22-53-08.bpo-28556.C6Hnd1.rst @@ -0,0 +1,3 @@ +Do not simplify arguments to `typing.Union`. Now `Union[Manager, Employee]` +is not simplified to `Employee` at runtime. Such simplification previously +caused several bugs and limited possibilities for introspection. From webhook-mailer at python.org Fri May 18 19:27:21 2018 From: webhook-mailer at python.org (Ivan Levkivskyi) Date: Fri, 18 May 2018 23:27:21 -0000 Subject: [Python-checkins] bpo-28556: Don't simplify unions at runtime (GH-6841) (GH-6979) Message-ID: <mailman.144.1526686044.2757.python-checkins@python.org> https://github.com/python/cpython/commit/09ca5906b7d1619b7efed0bebb6f3c424fe3d83b commit: 09ca5906b7d1619b7efed0bebb6f3c424fe3d83b branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Ivan Levkivskyi <levkivskyi at gmail.com> date: 2018-05-18T16:27:14-07:00 summary: bpo-28556: Don't simplify unions at runtime (GH-6841) (GH-6979) (cherry picked from commit f65e31fee3b55dfb6ed5398179d5c5d6b502dee5) Co-authored-by: Ivan Levkivskyi <levkivskyi at gmail.com> files: A Misc/NEWS.d/next/Library/2018-05-17-22-53-08.bpo-28556.C6Hnd1.rst M Doc/library/typing.rst M Lib/test/test_typing.py M Lib/typing.py diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index 142e169b89c4..be6636eea08f 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -961,16 +961,15 @@ The module defines the following classes, functions and decorators: Union[int, str] == Union[str, int] - * When a class and its subclass are present, the latter is skipped, e.g.:: - - Union[int, object] == object - * You cannot subclass or instantiate a union. * You cannot write ``Union[X][Y]``. * You can use ``Optional[X]`` as a shorthand for ``Union[X, None]``. + .. versionchanged:: 3.7 + Don't remove explicit subclasses from unions at runtime. + .. data:: Optional Optional type. diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index be768f12fb4c..904cd93691a1 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -253,10 +253,11 @@ def test_union_any(self): def test_union_object(self): u = Union[object] self.assertEqual(u, object) - u = Union[int, object] - self.assertEqual(u, object) - u = Union[object, int] - self.assertEqual(u, object) + u1 = Union[int, object] + u2 = Union[object, int] + self.assertEqual(u1, u2) + self.assertNotEqual(u1, object) + self.assertNotEqual(u2, object) def test_unordered(self): u1 = Union[int, float] @@ -267,13 +268,11 @@ def test_single_class_disappears(self): t = Union[Employee] self.assertIs(t, Employee) - def test_base_class_disappears(self): - u = Union[Employee, Manager, int] - self.assertEqual(u, Union[int, Employee]) - u = Union[Manager, int, Employee] - self.assertEqual(u, Union[int, Employee]) + def test_base_class_kept(self): u = Union[Employee, Manager] - self.assertIs(u, Employee) + self.assertNotEqual(u, Employee) + self.assertIn(Employee, u.__args__) + self.assertIn(Manager, u.__args__) def test_union_union(self): u = Union[int, float] @@ -317,7 +316,8 @@ def test_cannot_instantiate(self): def test_union_generalization(self): self.assertFalse(Union[str, typing.Iterable[int]] == str) self.assertFalse(Union[str, typing.Iterable[int]] == typing.Iterable[int]) - self.assertTrue(Union[str, typing.Iterable] == typing.Iterable) + self.assertIn(str, Union[str, typing.Iterable[int]].__args__) + self.assertIn(typing.Iterable[int], Union[str, typing.Iterable[int]].__args__) def test_union_compare_other(self): self.assertNotEqual(Union, object) @@ -917,7 +917,7 @@ def test_extended_generic_rules_eq(self): self.assertEqual(Union[T, U][int, Union[int, str]], Union[int, str]) class Base: ... class Derived(Base): ... - self.assertEqual(Union[T, Base][Derived], Base) + self.assertEqual(Union[T, Base][Union[Base, Derived]], Union[Base, Derived]) with self.assertRaises(TypeError): Union[T, int][1] diff --git a/Lib/typing.py b/Lib/typing.py index b10615c07fbd..3e82c6b1bb21 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -206,8 +206,8 @@ def _check_generic(cls, parameters): def _remove_dups_flatten(parameters): - """An internal helper for Union creation and substitution: flatten Union's - among parameters, then remove duplicates and strict subclasses. + """An internal helper for Union creation and substitution: flatten Unions + among parameters, then remove duplicates. """ # Flatten out Union[Union[...], ...]. params = [] @@ -228,20 +228,7 @@ def _remove_dups_flatten(parameters): all_params.remove(t) params = new_params assert not all_params, all_params - # Weed out subclasses. - # E.g. Union[int, Employee, Manager] == Union[int, Employee]. - # If object is present it will be sole survivor among proper classes. - # Never discard type variables. - # (In particular, Union[str, AnyStr] != AnyStr.) - all_params = set(params) - for t1 in params: - if not isinstance(t1, type): - continue - if any((isinstance(t2, type) or - isinstance(t2, _GenericAlias) and t2._special) and issubclass(t1, t2) - for t2 in all_params - {t1}): - all_params.remove(t1) - return tuple(t for t in params if t in all_params) + return tuple(params) _cleanups = [] @@ -440,19 +427,6 @@ class Starship: Union[int, str] == Union[str, int] - - When two arguments have a subclass relationship, the least - derived argument is kept, e.g.:: - - class Employee: pass - class Manager(Employee): pass - Union[int, Employee, Manager] == Union[int, Employee] - Union[Manager, int, Employee] == Union[int, Employee] - Union[Employee, Manager] == Employee - - - Similar for object:: - - Union[int, object] == object - - You cannot subclass or instantiate a union. - You can use Optional[X] as a shorthand for Union[X, None]. """) diff --git a/Misc/NEWS.d/next/Library/2018-05-17-22-53-08.bpo-28556.C6Hnd1.rst b/Misc/NEWS.d/next/Library/2018-05-17-22-53-08.bpo-28556.C6Hnd1.rst new file mode 100644 index 000000000000..35e13bde1897 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-17-22-53-08.bpo-28556.C6Hnd1.rst @@ -0,0 +1,3 @@ +Do not simplify arguments to `typing.Union`. Now `Union[Manager, Employee]` +is not simplified to `Employee` at runtime. Such simplification previously +caused several bugs and limited possibilities for introspection. From webhook-mailer at python.org Fri May 18 19:44:25 2018 From: webhook-mailer at python.org (Victor Stinner) Date: Fri, 18 May 2018 23:44:25 -0000 Subject: [Python-checkins] [3.7] bpo-33518: Add PEP entry to documentation glossary (GH-6860) (#6934) Message-ID: <mailman.145.1526687066.2757.python-checkins@python.org> https://github.com/python/cpython/commit/a3a554a536599189166843cd80e62d02b2b68aa8 commit: a3a554a536599189166843cd80e62d02b2b68aa8 branch: 3.7 author: Andr?s Delfino <adelfino at gmail.com> committer: Victor Stinner <vstinner at redhat.com> date: 2018-05-19T01:44:18+02:00 summary: [3.7] bpo-33518: Add PEP entry to documentation glossary (GH-6860) (#6934) (cherry picked from commit d5f144260886959c1fe06bc4506a23fd10f92348) Co-authored-by: Andr?s Delfino <adelfino at gmail.com> files: M Doc/glossary.rst diff --git a/Doc/glossary.rst b/Doc/glossary.rst index 2eab00314682..a90f176db7ba 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -837,6 +837,21 @@ Glossary :class:`str` or :class:`bytes` result instead, respectively. Introduced by :pep:`519`. + PEP + Python Enhancement Proposal. A PEP is a design document + providing information to the Python community, or describing a new + feature for Python or its processes or environment. PEPs should + provide a concise technical specification and a rationale for proposed + features. + + PEPs are intended to be the primary mechanisms for proposing major new + features, for collecting community input on an issue, and for documenting + the design decisions that have gone into Python. The PEP author is + responsible for building consensus within the community and documenting + dissenting opinions. + + See :pep:`1`. + portion A set of files in a single directory (possibly stored in a zip file) that contribute to a namespace package, as defined in :pep:`420`. From webhook-mailer at python.org Fri May 18 19:44:25 2018 From: webhook-mailer at python.org (Victor Stinner) Date: Fri, 18 May 2018 23:44:25 -0000 Subject: [Python-checkins] [3.6] bpo-33518: Add PEP entry to documentation glossary (GH-6860) (#6935) Message-ID: <mailman.146.1526687067.2757.python-checkins@python.org> https://github.com/python/cpython/commit/fb5d0aa116125dfb29a3c4d8819a38dfb2760bb9 commit: fb5d0aa116125dfb29a3c4d8819a38dfb2760bb9 branch: 3.6 author: Andr?s Delfino <adelfino at gmail.com> committer: Victor Stinner <vstinner at redhat.com> date: 2018-05-19T01:44:21+02:00 summary: [3.6] bpo-33518: Add PEP entry to documentation glossary (GH-6860) (#6935) (cherry picked from commit d5f144260886959c1fe06bc4506a23fd10f92348) Co-authored-by: Andr?s Delfino <adelfino at gmail.com> files: M Doc/glossary.rst diff --git a/Doc/glossary.rst b/Doc/glossary.rst index aa5f47ed99aa..425ab81a9090 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -829,6 +829,21 @@ Glossary :class:`str` or :class:`bytes` result instead, respectively. Introduced by :pep:`519`. + PEP + Python Enhancement Proposal. A PEP is a design document + providing information to the Python community, or describing a new + feature for Python or its processes or environment. PEPs should + provide a concise technical specification and a rationale for proposed + features. + + PEPs are intended to be the primary mechanisms for proposing major new + features, for collecting community input on an issue, and for documenting + the design decisions that have gone into Python. The PEP author is + responsible for building consensus within the community and documenting + dissenting opinions. + + See :pep:`1`. + portion A set of files in a single directory (possibly stored in a zip file) that contribute to a namespace package, as defined in :pep:`420`. From webhook-mailer at python.org Fri May 18 19:53:17 2018 From: webhook-mailer at python.org (Victor Stinner) Date: Fri, 18 May 2018 23:53:17 -0000 Subject: [Python-checkins] bpo-16055: Fixes incorrect error text for int('1', base=1000) (#6980) Message-ID: <mailman.147.1526687597.2757.python-checkins@python.org> https://github.com/python/cpython/commit/d13169fc5ac7572a272cbcff830c3d96ba27cc7c commit: d13169fc5ac7572a272cbcff830c3d96ba27cc7c branch: 2.7 author: Victor Stinner <vstinner at redhat.com> committer: GitHub <noreply at github.com> date: 2018-05-19T01:53:13+02:00 summary: bpo-16055: Fixes incorrect error text for int('1', base=1000) (#6980) Fixes incorrect error text for int('1', base=1000) and long('1', base=1000). files: M Objects/intobject.c M Objects/longobject.c diff --git a/Objects/intobject.c b/Objects/intobject.c index 3ab00af1e28c..9b27c35d88d0 100644 --- a/Objects/intobject.c +++ b/Objects/intobject.c @@ -358,7 +358,7 @@ PyInt_FromString(char *s, char **pend, int base) if ((base != 0 && base < 2) || base > 36) { PyErr_SetString(PyExc_ValueError, - "int() base must be >= 2 and <= 36"); + "int() base must be >= 2 and <= 36, or 0"); return NULL; } diff --git a/Objects/longobject.c b/Objects/longobject.c index 5d6ce70d537d..f40ad7ab1b8c 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -1722,7 +1722,7 @@ PyLong_FromString(char *str, char **pend, int base) if ((base != 0 && base < 2) || base > 36) { PyErr_SetString(PyExc_ValueError, - "long() arg 2 must be >= 2 and <= 36"); + "long() base must be >= 2 and <= 36, or 0"); return NULL; } while (*str != '\0' && isspace(Py_CHARMASK(*str))) From lp_benchmark_robot at intel.com Fri May 18 20:43:40 2018 From: lp_benchmark_robot at intel.com (lp_benchmark_robot at intel.com) Date: Fri, 18 May 2018 17:43:40 -0700 Subject: [Python-checkins] [65 flat] Results for Python (master branch) 2018-05-18 Message-ID: <acffecd1-b385-4465-95dc-bfd51a8f04a9@orsmsx104.amr.corp.intel.com> Results for project python/master, build date: 2018-05-18 03:03:23-07:00. - commit: d89ca94 - previous commit: 74fc9c0 - revision date: 2018-05-17 20:38:41-04:00 - environment: Broadwell-EP - cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores, stepping 1, LLC 55 MB - mem: 128 GB - os: Ubuntu 16.04.2 LTS - kernel: 4.4.0-62-generic x86_64 GNU/Linux Baseline results were generated using release v3.6.0, with hash 5c4568a from 2016-12-22 23:38:47+00:00. +-----+------------------------+--------+------------+------------+------------+ | | |relative|change since|change since|current rev | | | benchmark|std_dev*| last run | baseline |run with PGO| +-----+------------------------+--------+------------+------------+------------+ | :-| | 2to3| 0.686% | -0.255% | +8.916% | +6.548% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method| 1.605% | +0.234% | +23.794% | +11.977% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_slots| 2.434% | -0.214% | +25.257% | +11.018% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_unknown| 1.258% | -0.158% | +22.483% | +12.106% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_simple| 2.738% | +0.433% | +11.779% | +11.174% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chameleon| 2.175% | +0.152% | +11.414% | +10.907% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chaos| 0.709% | -0.052% | +8.780% | +9.201% | +-----+------------------------+--------+------------+------------+------------+ | :-| | crypto_pyaes| 0.525% | +0.330% | +0.031% | +7.893% | +-----+------------------------+--------+------------+------------+------------+ | :-| | deltablue| 3.311% | -0.097% | +11.935% | +16.910% | +-----+------------------------+--------+------------+------------+------------+ | :-| | django_template| 2.259% | -0.285% | +21.296% | +11.882% | +-----+------------------------+--------+------------+------------+------------+ | :-| | dulwich_log| 1.281% | -0.447% | +4.674% | +6.557% | +-----+------------------------+--------+------------+------------+------------+ | :-| | fannkuch| 0.426% | +0.031% | +7.552% | +4.920% | +-----+------------------------+--------+------------+------------+------------+ | :-| | float| 1.225% | -0.044% | +2.625% | +7.667% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_text| 0.945% | +0.281% | +14.639% | +8.731% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_xml| 1.906% | +0.053% | +12.246% | +9.300% | +-----+------------------------+--------+------------+------------+------------+ | :-| | go| 6.213% | -0.169% | +5.365% | +10.807% | +-----+------------------------+--------+------------+------------+------------+ | :-| | hexiom| 0.308% | +0.157% | +12.272% | +11.284% | +-----+------------------------+--------+------------+------------+------------+ | :-| | html5lib| 2.729% | -0.195% | +10.756% | +10.986% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_dumps| 2.849% | -0.041% | +3.342% | +9.749% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_loads| 7.721% | -2.234% | -6.184% | +17.419% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_format| 1.495% | +0.718% | +17.771% | +10.943% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_silent| 2.691% | -0.364% | +47.809% | +12.226% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_simple| 1.545% | -0.138% | +12.489% | +12.271% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mako| 0.664% | -0.007% | +16.877% | +14.283% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mdp| 6.300% | +2.023% | +1.771% | +18.052% | +-----+------------------------+--------+------------+------------+------------+ | :-| | meteor_contest| 0.619% | +0.249% | +4.547% | +5.908% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nbody| 1.117% | -0.020% | -0.924% | +2.031% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nqueens| 0.603% | -0.001% | +6.489% | +6.127% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pathlib| 1.328% | -0.708% | +0.991% | +7.177% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle| 1.307% | +1.544% | -0.247% | +21.888% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_dict| 0.553% | -0.029% | +7.566% | +15.877% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_list| 0.852% | +0.034% | +7.146% | +18.463% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_pure_python| 3.430% | +0.694% | +11.741% | +10.103% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pidigits| 0.079% | -0.021% | +0.298% | +9.943% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup| 0.122% | +0.032% | +18.873% | +5.132% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup_no_site| 0.082% | +0.101% | +5.934% | +5.375% | +-----+------------------------+--------+------------+------------+------------+ | :-| | raytrace| 1.051% | +0.025% | +10.807% | +12.497% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_compile| 5.403% | -0.331% | +3.730% | +12.255% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_dna| 0.240% | +0.020% | -2.095% | +13.621% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_effbot| 1.936% | -0.558% | -8.245% | +10.582% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_v8| 2.447% | +0.836% | +4.579% | +9.343% | +-----+------------------------+--------+------------+------------+------------+ | :-| | richards| 1.133% | +0.387% | +10.097% | +14.767% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_fft| 1.631% | -0.163% | -0.439% | +3.106% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_lu| 4.054% | -0.973% | +22.145% | +11.855% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_monte_carlo| 2.037% | -0.305% | +4.761% | +4.583% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sor| 3.011% | -0.317% | +14.917% | +8.986% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sparse_mat_mult| 1.200% | +1.163% | -2.913% | -0.678% | +-----+------------------------+--------+------------+------------+------------+ | :-| | spectral_norm| 0.923% | -0.021% | +5.406% | +5.726% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_declarative| 1.764% | -0.272% | +6.939% | +5.620% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_imperative| 3.639% | +0.525% | +8.437% | +4.490% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlite_synth| 4.548% | -0.844% | -0.279% | +10.450% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_expand| 3.369% | -0.495% | +17.722% | +6.615% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_integrate| 1.574% | +0.316% | +18.543% | +5.775% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_str| 4.644% | -0.624% | +19.294% | +5.812% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_sum| 6.564% | -0.912% | +16.116% | +9.767% | +-----+------------------------+--------+------------+------------+------------+ | :-| | telco| 2.860% | -0.421% | +20.595% | +7.033% | +-----+------------------------+--------+------------+------------+------------+ | :-| | tornado_http| 1.074% | -0.171% | +7.325% | +6.380% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpack_sequence| 1.206% | +0.317% | +2.792% | +2.439% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle| 8.172% | -0.525% | +6.496% | +22.534% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_list| 0.571% | +0.081% | -3.650% | +15.967% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_pure_python| 0.816% | +0.426% | +7.824% | +6.920% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_generate| 1.134% | -0.288% | +2.603% | +12.577% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_iterparse| 1.798% | +0.161% | +4.300% | +7.533% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_parse| 1.989% | +0.442% | -5.649% | +11.396% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_process| 1.140% | +0.072% | +4.927% | +10.826% | +-----+------------------------+--------+------------+------------+------------+ * Relative Standard Deviation (Standard Deviation/Average) If this is not displayed properly please visit our results page here: http://languagesperformance.intel.com/65-flat-results-for-python-master-branch-2018-05-18 Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. From webhook-mailer at python.org Fri May 18 20:55:08 2018 From: webhook-mailer at python.org (Gregory P. Smith) Date: Sat, 19 May 2018 00:55:08 -0000 Subject: [Python-checkins] bpo-19950: Clarify unittest TestCase instance use. (GH-6875) (GH-6939) Message-ID: <mailman.149.1526691309.2757.python-checkins@python.org> https://github.com/python/cpython/commit/a5f33a899f6450de96f5e4cd154de4486d50bdd7 commit: a5f33a899f6450de96f5e4cd154de4486d50bdd7 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Gregory P. Smith <greg at krypto.org> date: 2018-05-18T17:55:05-07:00 summary: bpo-19950: Clarify unittest TestCase instance use. (GH-6875) (GH-6939) (cherry picked from commit dff46758f267ad6c13096c69c4e1dee17f9969aa) Co-authored-by: Gregory P. Smith <greg at krypto.org> Google files: M Doc/library/unittest.rst diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst index a4c4c5c64a6e..f0de85f76157 100644 --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -342,8 +342,9 @@ testing code:: Note that in order to test something, we use one of the :meth:`assert\*` methods provided by the :class:`TestCase` base class. If the test fails, an -exception will be raised, and :mod:`unittest` will identify the test case as a -:dfn:`failure`. Any other exceptions will be treated as :dfn:`errors`. +exception will be raised with an explanatory message, and :mod:`unittest` +will identify the test case as a :dfn:`failure`. Any other exceptions will be +treated as :dfn:`errors`. Tests can be numerous, and their set-up can be repetitive. Luckily, we can factor out set-up code by implementing a method called @@ -389,13 +390,18 @@ after the test method has been run:: If :meth:`~TestCase.setUp` succeeded, :meth:`~TestCase.tearDown` will be run whether the test method succeeded or not. -Such a working environment for the testing code is called a :dfn:`fixture`. - -Test case instances are grouped together according to the features they test. -:mod:`unittest` provides a mechanism for this: the :dfn:`test suite`, -represented by :mod:`unittest`'s :class:`TestSuite` class. In most cases, -calling :func:`unittest.main` will do the right thing and collect all the -module's test cases for you, and then execute them. +Such a working environment for the testing code is called a +:dfn:`test fixture`. A new TestCase instance is created as a unique +test fixture used to execute each individual test method. Thus +`~TestCase.setUp`, `~TestCase.tearDown`, and `~TestCase.__init__` +will be called once per test. + +It is recommended that you use TestCase implementations to group tests together +according to the features they test. :mod:`unittest` provides a mechanism for +this: the :dfn:`test suite`, represented by :mod:`unittest`'s +:class:`TestSuite` class. In most cases, calling :func:`unittest.main` will do +the right thing and collect all the module's test cases for you and execute +them. However, should you want to customize the building of your test suite, you can do it yourself:: From webhook-mailer at python.org Fri May 18 20:55:48 2018 From: webhook-mailer at python.org (Gregory P. Smith) Date: Sat, 19 May 2018 00:55:48 -0000 Subject: [Python-checkins] bpo-19950: Clarify unittest TestCase instance use. (GH-6875) (GH-6938) Message-ID: <mailman.150.1526691350.2757.python-checkins@python.org> https://github.com/python/cpython/commit/436972e295f5057fe7cdd7312f543c2fa884705d commit: 436972e295f5057fe7cdd7312f543c2fa884705d branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Gregory P. Smith <greg at krypto.org> date: 2018-05-18T17:55:45-07:00 summary: bpo-19950: Clarify unittest TestCase instance use. (GH-6875) (GH-6938) (cherry picked from commit dff46758f267ad6c13096c69c4e1dee17f9969aa) Co-authored-by: Gregory P. Smith <greg at krypto.org> Google files: M Doc/library/unittest.rst diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst index af71be40b89f..086d93782562 100644 --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -361,8 +361,9 @@ testing code:: Note that in order to test something, we use one of the :meth:`assert\*` methods provided by the :class:`TestCase` base class. If the test fails, an -exception will be raised, and :mod:`unittest` will identify the test case as a -:dfn:`failure`. Any other exceptions will be treated as :dfn:`errors`. +exception will be raised with an explanatory message, and :mod:`unittest` +will identify the test case as a :dfn:`failure`. Any other exceptions will be +treated as :dfn:`errors`. Tests can be numerous, and their set-up can be repetitive. Luckily, we can factor out set-up code by implementing a method called @@ -408,13 +409,18 @@ after the test method has been run:: If :meth:`~TestCase.setUp` succeeded, :meth:`~TestCase.tearDown` will be run whether the test method succeeded or not. -Such a working environment for the testing code is called a :dfn:`fixture`. - -Test case instances are grouped together according to the features they test. -:mod:`unittest` provides a mechanism for this: the :dfn:`test suite`, -represented by :mod:`unittest`'s :class:`TestSuite` class. In most cases, -calling :func:`unittest.main` will do the right thing and collect all the -module's test cases for you, and then execute them. +Such a working environment for the testing code is called a +:dfn:`test fixture`. A new TestCase instance is created as a unique +test fixture used to execute each individual test method. Thus +`~TestCase.setUp`, `~TestCase.tearDown`, and `~TestCase.__init__` +will be called once per test. + +It is recommended that you use TestCase implementations to group tests together +according to the features they test. :mod:`unittest` provides a mechanism for +this: the :dfn:`test suite`, represented by :mod:`unittest`'s +:class:`TestSuite` class. In most cases, calling :func:`unittest.main` will do +the right thing and collect all the module's test cases for you and execute +them. However, should you want to customize the building of your test suite, you can do it yourself:: From webhook-mailer at python.org Sat May 19 03:28:37 2018 From: webhook-mailer at python.org (Julien Palard) Date: Sat, 19 May 2018 07:28:37 -0000 Subject: [Python-checkins] [3.6] Fix typos '.::' should typically just be '::'. (GH-6165). (GH-6895) Message-ID: <mailman.151.1526714918.2757.python-checkins@python.org> https://github.com/python/cpython/commit/66b3f53db910d71b2cd75209fd3d9ff24d7797ba commit: 66b3f53db910d71b2cd75209fd3d9ff24d7797ba branch: 3.6 author: Julien Palard <julien at palard.fr> committer: GitHub <noreply at github.com> date: 2018-05-19T09:28:28+02:00 summary: [3.6] Fix typos '.::' should typically just be '::'. (GH-6165). (GH-6895) (cherry picked from commit 78553138be3b38d361bded8e641a2a4fd65a9d16) files: M Doc/library/argparse.rst M Doc/library/mmap.rst diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst index c5bc1eebd7de..a9cb5c5357b6 100644 --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -981,7 +981,7 @@ is used when no command-line argument was present:: Providing ``default=argparse.SUPPRESS`` causes no attribute to be added if the -command-line argument was not present.:: +command-line argument was not present:: >>> parser = argparse.ArgumentParser() >>> parser.add_argument('--foo', default=argparse.SUPPRESS) diff --git a/Doc/library/mmap.rst b/Doc/library/mmap.rst index f46bf66db2ff..d965fa36b47a 100644 --- a/Doc/library/mmap.rst +++ b/Doc/library/mmap.rst @@ -123,7 +123,7 @@ To map anonymous memory, -1 should be passed as the fileno along with the length :class:`~mmap.mmap` can also be used as a context manager in a :keyword:`with` - statement.:: + statement:: import mmap From solipsis at pitrou.net Sat May 19 05:13:51 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 19 May 2018 09:13:51 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=-2 Message-ID: <20180519091351.1.E55AA195C52A1A5B@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_collections leaked [0, 0, -7] memory blocks, sum=-7 test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_fork leaked [-1, 2, -1] memory blocks, sum=0 test_multiprocessing_forkserver leaked [-1, 2, 0] memory blocks, sum=1 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogzcTm06', '--timeout', '7200'] From webhook-mailer at python.org Sat May 19 11:02:00 2018 From: webhook-mailer at python.org (stevendaprano) Date: Sat, 19 May 2018 15:02:00 -0000 Subject: [Python-checkins] import secrets module in secrets recipes (#6705) Message-ID: <mailman.152.1526742121.2757.python-checkins@python.org> https://github.com/python/cpython/commit/cf8abcbe0310ab4b3eb8b66ae795878b9df1a8ac commit: cf8abcbe0310ab4b3eb8b66ae795878b9df1a8ac branch: master author: Daniel Chimeno <daniel at chimeno.me> committer: stevendaprano <steve+python at pearwood.info> date: 2018-05-20T01:01:49+10:00 summary: import secrets module in secrets recipes (#6705) files: M Doc/library/secrets.rst diff --git a/Doc/library/secrets.rst b/Doc/library/secrets.rst index 28ce472c7e7e..bc4766da2785 100644 --- a/Doc/library/secrets.rst +++ b/Doc/library/secrets.rst @@ -145,8 +145,9 @@ Generate an eight-character alphanumeric password: .. testcode:: import string + import secrets alphabet = string.ascii_letters + string.digits - password = ''.join(choice(alphabet) for i in range(8)) + password = ''.join(secrets.choice(alphabet) for i in range(8)) .. note:: @@ -164,9 +165,10 @@ three digits: .. testcode:: import string + import secrets alphabet = string.ascii_letters + string.digits while True: - password = ''.join(choice(alphabet) for i in range(10)) + password = ''.join(secrets.choice(alphabet) for i in range(10)) if (any(c.islower() for c in password) and any(c.isupper() for c in password) and sum(c.isdigit() for c in password) >= 3): @@ -177,11 +179,12 @@ Generate an `XKCD-style passphrase <https://xkcd.com/936/>`_: .. testcode:: + import secrets # On standard Linux systems, use a convenient dictionary file. # Other platforms may need to provide their own word-list. with open('/usr/share/dict/words') as f: words = [word.strip() for word in f] - password = ' '.join(choice(words) for i in range(4)) + password = ' '.join(secrets.choice(words) for i in range(4)) Generate a hard-to-guess temporary URL containing a security token @@ -189,7 +192,8 @@ suitable for password recovery applications: .. testcode:: - url = 'https://mydomain.com/reset=' + token_urlsafe() + import secrets + url = 'https://mydomain.com/reset=' + secrets.token_urlsafe() From webhook-mailer at python.org Sat May 19 15:34:14 2018 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Sat, 19 May 2018 19:34:14 -0000 Subject: [Python-checkins] bpo-32831: IDLE: Add docstrings and tests for codecontext (GH-5638) Message-ID: <mailman.153.1526758457.2757.python-checkins@python.org> https://github.com/python/cpython/commit/654038d896d78a8373b60184f335acd516215acd commit: 654038d896d78a8373b60184f335acd516215acd branch: master author: Cheryl Sabella <cheryl.sabella at gmail.com> committer: Terry Jan Reedy <tjreedy at udel.edu> date: 2018-05-19T15:34:03-04:00 summary: bpo-32831: IDLE: Add docstrings and tests for codecontext (GH-5638) files: A Lib/idlelib/idle_test/test_codecontext.py A Misc/NEWS.d/next/IDLE/2018-02-12-08-08-45.bpo-32831.srDRvU.rst M Lib/idlelib/codecontext.py diff --git a/Lib/idlelib/codecontext.py b/Lib/idlelib/codecontext.py index 2bfb2e988ff4..efd163ed265e 100644 --- a/Lib/idlelib/codecontext.py +++ b/Lib/idlelib/codecontext.py @@ -22,32 +22,49 @@ UPDATEINTERVAL = 100 # millisec FONTUPDATEINTERVAL = 1000 # millisec + def getspacesfirstword(s, c=re.compile(r"^(\s*)(\w*)")): + "Extract the beginning whitespace and first word from s." return c.match(s).groups() class CodeContext: + "Display block context above the edit window." + bgcolor = "LightGray" fgcolor = "Black" def __init__(self, editwin): + """Initialize settings for context block. + + editwin is the Editor window for the context block. + self.text is the editor window text widget. + self.textfont is the editor window font. + + self.label displays the code context text above the editor text. + Initially None it is toggled via <<toggle-code-context>>. + self.topvisible is the number of the top text line displayed. + self.info is a list of (line number, indent level, line text, + block keyword) tuples for the block structure above topvisible. + s self.info[0] is initialized a 'dummy' line which + # starts the toplevel 'block' of the module. + + self.t1 and self.t2 are two timer events on the editor text widget to + monitor for changes to the context text or editor font. + """ self.editwin = editwin self.text = editwin.text self.textfont = self.text["font"] self.label = None - # self.info is a list of (line number, indent level, line text, block - # keyword) tuples providing the block structure associated with - # self.topvisible (the linenumber of the line displayed at the top of - # the edit window). self.info[0] is initialized as a 'dummy' line which - # starts the toplevel 'block' of the module. - self.info = [(0, -1, "", False)] self.topvisible = 1 + self.info = [(0, -1, "", False)] # Start two update cycles, one for context lines, one for font changes. self.t1 = self.text.after(UPDATEINTERVAL, self.timer_event) self.t2 = self.text.after(FONTUPDATEINTERVAL, self.font_timer_event) @classmethod def reload(cls): + "Load class variables from config." cls.context_depth = idleConf.GetOption("extensions", "CodeContext", "numlines", type="int", default=3) ## cls.bgcolor = idleConf.GetOption("extensions", "CodeContext", @@ -56,6 +73,7 @@ def reload(cls): ## "fgcolor", type="str", default="Black") def __del__(self): + "Cancel scheduled events." try: self.text.after_cancel(self.t1) self.text.after_cancel(self.t2) @@ -63,6 +81,12 @@ def __del__(self): pass def toggle_code_context_event(self, event=None): + """Toggle code context display. + + If self.label doesn't exist, create it to match the size of the editor + window text (toggle on). If it does exist, destroy it (toggle off). + Return 'break' to complete the processing of the binding. + """ if not self.label: # Calculate the border width and horizontal padding required to # align the context with the text in the main Text widget. @@ -95,11 +119,10 @@ def toggle_code_context_event(self, event=None): return "break" def get_line_info(self, linenum): - """Get the line indent value, text, and any block start keyword + """Return tuple of (line indent value, text, and block start keyword). If the line does not start a block, the keyword value is False. The indentation of empty lines (or comment lines) is INFINITY. - """ text = self.text.get("%d.0" % linenum, "%d.end" % linenum) spaces, firstword = getspacesfirstword(text) @@ -111,11 +134,13 @@ def get_line_info(self, linenum): return indent, text, opener def get_context(self, new_topvisible, stopline=1, stopindent=0): - """Get context lines, starting at new_topvisible and working backwards. - - Stop when stopline or stopindent is reached. Return a tuple of context - data and the indent level at the top of the region inspected. + """Return a list of block line tuples and the 'last' indent. + The tuple fields are (linenum, indent, text, opener). + The list represents header lines from new_topvisible back to + stopline with successively shorter indents > stopindent. + The list is returned ordered by line number. + Last indent returned is the smallest indent observed. """ assert stopline > 0 lines = [] @@ -140,6 +165,11 @@ def get_context(self, new_topvisible, stopline=1, stopindent=0): def update_code_context(self): """Update context information and lines visible in the context pane. + No update is done if the text hasn't been scrolled. If the text + was scrolled, the lines that should be shown in the context will + be retrieved and the label widget will be updated with the code, + padded with blank lines so that the code appears on the bottom of + the context label. """ new_topvisible = int(self.text.index("@0,0").split('.')[0]) if self.topvisible == new_topvisible: # haven't scrolled @@ -151,7 +181,7 @@ def update_code_context(self): # between topvisible and new_topvisible: while self.info[-1][1] >= lastindent: del self.info[-1] - elif self.topvisible > new_topvisible: # scroll up + else: # self.topvisible > new_topvisible: # scroll up stopindent = self.info[-1][1] + 1 # retain only context info associated # with lines above new_topvisible: @@ -170,11 +200,13 @@ def update_code_context(self): self.label["text"] = '\n'.join(context_strings) def timer_event(self): + "Event on editor text widget triggered every UPDATEINTERVAL ms." if self.label: self.update_code_context() self.t1 = self.text.after(UPDATEINTERVAL, self.timer_event) def font_timer_event(self): + "Event on editor text widget triggered every FONTUPDATEINTERVAL ms." newtextfont = self.text["font"] if self.label and newtextfont != self.textfont: self.textfont = newtextfont @@ -183,3 +215,8 @@ def font_timer_event(self): CodeContext.reload() + + +if __name__ == "__main__": # pragma: no cover + import unittest + unittest.main('idlelib.idle_test.test_codecontext', verbosity=2, exit=False) diff --git a/Lib/idlelib/idle_test/test_codecontext.py b/Lib/idlelib/idle_test/test_codecontext.py new file mode 100644 index 000000000000..448094eda7ef --- /dev/null +++ b/Lib/idlelib/idle_test/test_codecontext.py @@ -0,0 +1,347 @@ +"""Test idlelib.codecontext. + +Coverage: 100% +""" + +import re + +import unittest +from unittest import mock +from test.support import requires +from tkinter import Tk, Frame, Text, TclError + +import idlelib.codecontext as codecontext +from idlelib import config + + +usercfg = codecontext.idleConf.userCfg +testcfg = { + 'main': config.IdleUserConfParser(''), + 'highlight': config.IdleUserConfParser(''), + 'keys': config.IdleUserConfParser(''), + 'extensions': config.IdleUserConfParser(''), +} +code_sample = """\ + +class C1(): + # Class comment. + def __init__(self, a, b): + self.a = a + self.b = b + def compare(self): + if a > b: + return a + elif a < b: + return b + else: + return None +""" + + +class DummyEditwin: + def __init__(self, root, frame, text): + self.root = root + self.top = root + self.text_frame = frame + self.text = text + + +class CodeContextTest(unittest.TestCase): + + @classmethod + def setUpClass(cls): + requires('gui') + root = cls.root = Tk() + root.withdraw() + frame = cls.frame = Frame(root) + text = cls.text = Text(frame) + text.insert('1.0', code_sample) + # Need to pack for creation of code context label widget. + frame.pack(side='left', fill='both', expand=1) + text.pack(side='top', fill='both', expand=1) + cls.editor = DummyEditwin(root, frame, text) + codecontext.idleConf.userCfg = testcfg + + @classmethod + def tearDownClass(cls): + codecontext.idleConf.userCfg = usercfg + cls.editor.text.delete('1.0', 'end') + del cls.editor, cls.frame, cls.text + cls.root.update_idletasks() + cls.root.destroy() + del cls.root + + def setUp(self): + self.cc = codecontext.CodeContext(self.editor) + + def tearDown(self): + if self.cc.label: + self.cc.label.destroy() + # Explicitly call __del__ to remove scheduled scripts. + self.cc.__del__() + del self.cc.label, self.cc + + def test_init(self): + eq = self.assertEqual + ed = self.editor + cc = self.cc + + eq(cc.editwin, ed) + eq(cc.text, ed.text) + eq(cc.textfont, ed.text['font']) + self.assertIsNone(cc.label) + eq(cc.info, [(0, -1, '', False)]) + eq(cc.topvisible, 1) + eq(self.root.tk.call('after', 'info', self.cc.t1)[1], 'timer') + eq(self.root.tk.call('after', 'info', self.cc.t2)[1], 'timer') + + def test_del(self): + self.root.tk.call('after', 'info', self.cc.t1) + self.root.tk.call('after', 'info', self.cc.t2) + self.cc.__del__() + with self.assertRaises(TclError) as msg: + self.root.tk.call('after', 'info', self.cc.t1) + self.assertIn("doesn't exist", msg) + with self.assertRaises(TclError) as msg: + self.root.tk.call('after', 'info', self.cc.t2) + self.assertIn("doesn't exist", msg) + # For coverage on the except. Have to delete because the + # above Tcl error is caught by after_cancel. + del self.cc.t1, self.cc.t2 + self.cc.__del__() + + def test_reload(self): + codecontext.CodeContext.reload() + self.assertEqual(self.cc.context_depth, 3) + + def test_toggle_code_context_event(self): + eq = self.assertEqual + cc = self.cc + toggle = cc.toggle_code_context_event + + # Make sure code context is off. + if cc.label: + toggle() + + # Toggle on. + eq(toggle(), 'break') + self.assertIsNotNone(cc.label) + eq(cc.label['font'], cc.textfont) + eq(cc.label['fg'], cc.fgcolor) + eq(cc.label['bg'], cc.bgcolor) + eq(cc.label['text'], '\n' * 2) + + # Toggle off. + eq(toggle(), 'break') + self.assertIsNone(cc.label) + + def test_get_line_info(self): + eq = self.assertEqual + gli = self.cc.get_line_info + + # Line 1 is not a BLOCKOPENER. + eq(gli(1), (codecontext.INFINITY, '', False)) + # Line 2 is a BLOCKOPENER without an indent. + eq(gli(2), (0, 'class C1():', 'class')) + # Line 3 is not a BLOCKOPENER and does not return the indent level. + eq(gli(3), (codecontext.INFINITY, ' # Class comment.', False)) + # Line 4 is a BLOCKOPENER and is indented. + eq(gli(4), (4, ' def __init__(self, a, b):', 'def')) + # Line 8 is a different BLOCKOPENER and is indented. + eq(gli(8), (8, ' if a > b:', 'if')) + + def test_get_context(self): + eq = self.assertEqual + gc = self.cc.get_context + + # stopline must be greater than 0. + with self.assertRaises(AssertionError): + gc(1, stopline=0) + + eq(gc(3), ([(2, 0, 'class C1():', 'class')], 0)) + + # Don't return comment. + eq(gc(4), ([(2, 0, 'class C1():', 'class')], 0)) + + # Two indentation levels and no comment. + eq(gc(5), ([(2, 0, 'class C1():', 'class'), + (4, 4, ' def __init__(self, a, b):', 'def')], 0)) + + # Only one 'def' is returned, not both at the same indent level. + eq(gc(10), ([(2, 0, 'class C1():', 'class'), + (7, 4, ' def compare(self):', 'def'), + (8, 8, ' if a > b:', 'if')], 0)) + + # With 'elif', also show the 'if' even though it's at the same level. + eq(gc(11), ([(2, 0, 'class C1():', 'class'), + (7, 4, ' def compare(self):', 'def'), + (8, 8, ' if a > b:', 'if'), + (10, 8, ' elif a < b:', 'elif')], 0)) + + # Set stop_line to not go back to first line in source code. + # Return includes stop_line. + eq(gc(11, stopline=2), ([(2, 0, 'class C1():', 'class'), + (7, 4, ' def compare(self):', 'def'), + (8, 8, ' if a > b:', 'if'), + (10, 8, ' elif a < b:', 'elif')], 0)) + eq(gc(11, stopline=3), ([(7, 4, ' def compare(self):', 'def'), + (8, 8, ' if a > b:', 'if'), + (10, 8, ' elif a < b:', 'elif')], 4)) + eq(gc(11, stopline=8), ([(8, 8, ' if a > b:', 'if'), + (10, 8, ' elif a < b:', 'elif')], 8)) + + # Set stop_indent to test indent level to stop at. + eq(gc(11, stopindent=4), ([(7, 4, ' def compare(self):', 'def'), + (8, 8, ' if a > b:', 'if'), + (10, 8, ' elif a < b:', 'elif')], 4)) + # Check that the 'if' is included. + eq(gc(11, stopindent=8), ([(8, 8, ' if a > b:', 'if'), + (10, 8, ' elif a < b:', 'elif')], 8)) + + def test_update_code_context(self): + eq = self.assertEqual + cc = self.cc + # Ensure code context is active. + if not cc.label: + cc.toggle_code_context_event() + + # Invoke update_code_context without scrolling - nothing happens. + self.assertIsNone(cc.update_code_context()) + eq(cc.info, [(0, -1, '', False)]) + eq(cc.topvisible, 1) + + # Scroll down to line 2. + cc.text.yview(2) + cc.update_code_context() + eq(cc.info, [(0, -1, '', False), (2, 0, 'class C1():', 'class')]) + eq(cc.topvisible, 3) + # context_depth is 3 so it pads with blank lines. + eq(cc.label['text'], '\n' + '\n' + 'class C1():') + + # Scroll down to line 3. Since it's a comment, nothing changes. + cc.text.yview(3) + cc.update_code_context() + eq(cc.info, [(0, -1, '', False), (2, 0, 'class C1():', 'class')]) + eq(cc.topvisible, 4) + eq(cc.label['text'], '\n' + '\n' + 'class C1():') + + # Scroll down to line 4. + cc.text.yview(4) + cc.update_code_context() + eq(cc.info, [(0, -1, '', False), + (2, 0, 'class C1():', 'class'), + (4, 4, ' def __init__(self, a, b):', 'def')]) + eq(cc.topvisible, 5) + eq(cc.label['text'], '\n' + 'class C1():\n' + ' def __init__(self, a, b):') + + # Scroll down to line 11. Last 'def' is removed. + cc.text.yview(11) + cc.update_code_context() + eq(cc.info, [(0, -1, '', False), + (2, 0, 'class C1():', 'class'), + (7, 4, ' def compare(self):', 'def'), + (8, 8, ' if a > b:', 'if'), + (10, 8, ' elif a < b:', 'elif')]) + eq(cc.topvisible, 12) + eq(cc.label['text'], ' def compare(self):\n' + ' if a > b:\n' + ' elif a < b:') + + # No scroll. No update, even though context_depth changed. + cc.update_code_context() + cc.context_depth = 1 + eq(cc.info, [(0, -1, '', False), + (2, 0, 'class C1():', 'class'), + (7, 4, ' def compare(self):', 'def'), + (8, 8, ' if a > b:', 'if'), + (10, 8, ' elif a < b:', 'elif')]) + eq(cc.topvisible, 12) + eq(cc.label['text'], ' def compare(self):\n' + ' if a > b:\n' + ' elif a < b:') + + # Scroll up. + cc.text.yview(5) + cc.update_code_context() + eq(cc.info, [(0, -1, '', False), + (2, 0, 'class C1():', 'class'), + (4, 4, ' def __init__(self, a, b):', 'def')]) + eq(cc.topvisible, 6) + # context_depth is 1. + eq(cc.label['text'], ' def __init__(self, a, b):') + + @mock.patch.object(codecontext.CodeContext, 'update_code_context') + def test_timer_event(self, mock_update): + # Ensure code context is not active. + if self.cc.label: + self.cc.toggle_code_context_event() + self.cc.timer_event() + mock_update.assert_not_called() + + # Activate code context. + self.cc.toggle_code_context_event() + self.cc.timer_event() + mock_update.assert_called() + + def test_font_timer_event(self): + eq = self.assertEqual + cc = self.cc + save_font = cc.text['font'] + test_font = 'FakeFont' + + # Ensure code context is not active. + if cc.label: + cc.toggle_code_context_event() + + # Nothing updates on inactive code context. + cc.text['font'] = test_font + cc.font_timer_event() + eq(cc.textfont, save_font) + + # Activate code context, but no change to font. + cc.toggle_code_context_event() + cc.text['font'] = save_font + cc.font_timer_event() + eq(cc.textfont, save_font) + eq(cc.label['font'], save_font) + + # Active code context, change font. + cc.text['font'] = test_font + cc.font_timer_event() + eq(cc.textfont, test_font) + eq(cc.label['font'], test_font) + + cc.text['font'] = save_font + cc.font_timer_event() + + +class HelperFunctionText(unittest.TestCase): + + def test_getspacesfirstword(self): + get = codecontext.getspacesfirstword + test_lines = ( + (' first word', (' ', 'first')), + ('\tfirst word', ('\t', 'first')), + (' \u19D4\u19D2: ', (' ', '\u19D4\u19D2')), + ('no spaces', ('', 'no')), + ('', ('', '')), + ('# TEST COMMENT', ('', '')), + (' (continuation)', (' ', '')) + ) + for line, expected_output in test_lines: + self.assertEqual(get(line), expected_output) + + # Send the pattern in the call. + self.assertEqual(get(' (continuation)', + c=re.compile(r'^(\s*)([^\s]*)')), + (' ', '(continuation)')) + + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/Misc/NEWS.d/next/IDLE/2018-02-12-08-08-45.bpo-32831.srDRvU.rst b/Misc/NEWS.d/next/IDLE/2018-02-12-08-08-45.bpo-32831.srDRvU.rst new file mode 100644 index 000000000000..583e341f94f0 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2018-02-12-08-08-45.bpo-32831.srDRvU.rst @@ -0,0 +1 @@ +Add docstrings and tests for codecontext. From webhook-mailer at python.org Sat May 19 16:17:23 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 19 May 2018 20:17:23 -0000 Subject: [Python-checkins] bpo-32831: IDLE: Add docstrings and tests for codecontext (GH-5638) Message-ID: <mailman.154.1526761044.2757.python-checkins@python.org> https://github.com/python/cpython/commit/83aedc4d9ae36fb7bc05fd8b2caec55697b3efd2 commit: 83aedc4d9ae36fb7bc05fd8b2caec55697b3efd2 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-19T13:17:18-07:00 summary: bpo-32831: IDLE: Add docstrings and tests for codecontext (GH-5638) (cherry picked from commit 654038d896d78a8373b60184f335acd516215acd) Co-authored-by: Cheryl Sabella <cheryl.sabella at gmail.com> files: A Lib/idlelib/idle_test/test_codecontext.py A Misc/NEWS.d/next/IDLE/2018-02-12-08-08-45.bpo-32831.srDRvU.rst M Lib/idlelib/codecontext.py diff --git a/Lib/idlelib/codecontext.py b/Lib/idlelib/codecontext.py index 2bfb2e988ff4..efd163ed265e 100644 --- a/Lib/idlelib/codecontext.py +++ b/Lib/idlelib/codecontext.py @@ -22,32 +22,49 @@ UPDATEINTERVAL = 100 # millisec FONTUPDATEINTERVAL = 1000 # millisec + def getspacesfirstword(s, c=re.compile(r"^(\s*)(\w*)")): + "Extract the beginning whitespace and first word from s." return c.match(s).groups() class CodeContext: + "Display block context above the edit window." + bgcolor = "LightGray" fgcolor = "Black" def __init__(self, editwin): + """Initialize settings for context block. + + editwin is the Editor window for the context block. + self.text is the editor window text widget. + self.textfont is the editor window font. + + self.label displays the code context text above the editor text. + Initially None it is toggled via <<toggle-code-context>>. + self.topvisible is the number of the top text line displayed. + self.info is a list of (line number, indent level, line text, + block keyword) tuples for the block structure above topvisible. + s self.info[0] is initialized a 'dummy' line which + # starts the toplevel 'block' of the module. + + self.t1 and self.t2 are two timer events on the editor text widget to + monitor for changes to the context text or editor font. + """ self.editwin = editwin self.text = editwin.text self.textfont = self.text["font"] self.label = None - # self.info is a list of (line number, indent level, line text, block - # keyword) tuples providing the block structure associated with - # self.topvisible (the linenumber of the line displayed at the top of - # the edit window). self.info[0] is initialized as a 'dummy' line which - # starts the toplevel 'block' of the module. - self.info = [(0, -1, "", False)] self.topvisible = 1 + self.info = [(0, -1, "", False)] # Start two update cycles, one for context lines, one for font changes. self.t1 = self.text.after(UPDATEINTERVAL, self.timer_event) self.t2 = self.text.after(FONTUPDATEINTERVAL, self.font_timer_event) @classmethod def reload(cls): + "Load class variables from config." cls.context_depth = idleConf.GetOption("extensions", "CodeContext", "numlines", type="int", default=3) ## cls.bgcolor = idleConf.GetOption("extensions", "CodeContext", @@ -56,6 +73,7 @@ def reload(cls): ## "fgcolor", type="str", default="Black") def __del__(self): + "Cancel scheduled events." try: self.text.after_cancel(self.t1) self.text.after_cancel(self.t2) @@ -63,6 +81,12 @@ def __del__(self): pass def toggle_code_context_event(self, event=None): + """Toggle code context display. + + If self.label doesn't exist, create it to match the size of the editor + window text (toggle on). If it does exist, destroy it (toggle off). + Return 'break' to complete the processing of the binding. + """ if not self.label: # Calculate the border width and horizontal padding required to # align the context with the text in the main Text widget. @@ -95,11 +119,10 @@ def toggle_code_context_event(self, event=None): return "break" def get_line_info(self, linenum): - """Get the line indent value, text, and any block start keyword + """Return tuple of (line indent value, text, and block start keyword). If the line does not start a block, the keyword value is False. The indentation of empty lines (or comment lines) is INFINITY. - """ text = self.text.get("%d.0" % linenum, "%d.end" % linenum) spaces, firstword = getspacesfirstword(text) @@ -111,11 +134,13 @@ def get_line_info(self, linenum): return indent, text, opener def get_context(self, new_topvisible, stopline=1, stopindent=0): - """Get context lines, starting at new_topvisible and working backwards. - - Stop when stopline or stopindent is reached. Return a tuple of context - data and the indent level at the top of the region inspected. + """Return a list of block line tuples and the 'last' indent. + The tuple fields are (linenum, indent, text, opener). + The list represents header lines from new_topvisible back to + stopline with successively shorter indents > stopindent. + The list is returned ordered by line number. + Last indent returned is the smallest indent observed. """ assert stopline > 0 lines = [] @@ -140,6 +165,11 @@ def get_context(self, new_topvisible, stopline=1, stopindent=0): def update_code_context(self): """Update context information and lines visible in the context pane. + No update is done if the text hasn't been scrolled. If the text + was scrolled, the lines that should be shown in the context will + be retrieved and the label widget will be updated with the code, + padded with blank lines so that the code appears on the bottom of + the context label. """ new_topvisible = int(self.text.index("@0,0").split('.')[0]) if self.topvisible == new_topvisible: # haven't scrolled @@ -151,7 +181,7 @@ def update_code_context(self): # between topvisible and new_topvisible: while self.info[-1][1] >= lastindent: del self.info[-1] - elif self.topvisible > new_topvisible: # scroll up + else: # self.topvisible > new_topvisible: # scroll up stopindent = self.info[-1][1] + 1 # retain only context info associated # with lines above new_topvisible: @@ -170,11 +200,13 @@ def update_code_context(self): self.label["text"] = '\n'.join(context_strings) def timer_event(self): + "Event on editor text widget triggered every UPDATEINTERVAL ms." if self.label: self.update_code_context() self.t1 = self.text.after(UPDATEINTERVAL, self.timer_event) def font_timer_event(self): + "Event on editor text widget triggered every FONTUPDATEINTERVAL ms." newtextfont = self.text["font"] if self.label and newtextfont != self.textfont: self.textfont = newtextfont @@ -183,3 +215,8 @@ def font_timer_event(self): CodeContext.reload() + + +if __name__ == "__main__": # pragma: no cover + import unittest + unittest.main('idlelib.idle_test.test_codecontext', verbosity=2, exit=False) diff --git a/Lib/idlelib/idle_test/test_codecontext.py b/Lib/idlelib/idle_test/test_codecontext.py new file mode 100644 index 000000000000..448094eda7ef --- /dev/null +++ b/Lib/idlelib/idle_test/test_codecontext.py @@ -0,0 +1,347 @@ +"""Test idlelib.codecontext. + +Coverage: 100% +""" + +import re + +import unittest +from unittest import mock +from test.support import requires +from tkinter import Tk, Frame, Text, TclError + +import idlelib.codecontext as codecontext +from idlelib import config + + +usercfg = codecontext.idleConf.userCfg +testcfg = { + 'main': config.IdleUserConfParser(''), + 'highlight': config.IdleUserConfParser(''), + 'keys': config.IdleUserConfParser(''), + 'extensions': config.IdleUserConfParser(''), +} +code_sample = """\ + +class C1(): + # Class comment. + def __init__(self, a, b): + self.a = a + self.b = b + def compare(self): + if a > b: + return a + elif a < b: + return b + else: + return None +""" + + +class DummyEditwin: + def __init__(self, root, frame, text): + self.root = root + self.top = root + self.text_frame = frame + self.text = text + + +class CodeContextTest(unittest.TestCase): + + @classmethod + def setUpClass(cls): + requires('gui') + root = cls.root = Tk() + root.withdraw() + frame = cls.frame = Frame(root) + text = cls.text = Text(frame) + text.insert('1.0', code_sample) + # Need to pack for creation of code context label widget. + frame.pack(side='left', fill='both', expand=1) + text.pack(side='top', fill='both', expand=1) + cls.editor = DummyEditwin(root, frame, text) + codecontext.idleConf.userCfg = testcfg + + @classmethod + def tearDownClass(cls): + codecontext.idleConf.userCfg = usercfg + cls.editor.text.delete('1.0', 'end') + del cls.editor, cls.frame, cls.text + cls.root.update_idletasks() + cls.root.destroy() + del cls.root + + def setUp(self): + self.cc = codecontext.CodeContext(self.editor) + + def tearDown(self): + if self.cc.label: + self.cc.label.destroy() + # Explicitly call __del__ to remove scheduled scripts. + self.cc.__del__() + del self.cc.label, self.cc + + def test_init(self): + eq = self.assertEqual + ed = self.editor + cc = self.cc + + eq(cc.editwin, ed) + eq(cc.text, ed.text) + eq(cc.textfont, ed.text['font']) + self.assertIsNone(cc.label) + eq(cc.info, [(0, -1, '', False)]) + eq(cc.topvisible, 1) + eq(self.root.tk.call('after', 'info', self.cc.t1)[1], 'timer') + eq(self.root.tk.call('after', 'info', self.cc.t2)[1], 'timer') + + def test_del(self): + self.root.tk.call('after', 'info', self.cc.t1) + self.root.tk.call('after', 'info', self.cc.t2) + self.cc.__del__() + with self.assertRaises(TclError) as msg: + self.root.tk.call('after', 'info', self.cc.t1) + self.assertIn("doesn't exist", msg) + with self.assertRaises(TclError) as msg: + self.root.tk.call('after', 'info', self.cc.t2) + self.assertIn("doesn't exist", msg) + # For coverage on the except. Have to delete because the + # above Tcl error is caught by after_cancel. + del self.cc.t1, self.cc.t2 + self.cc.__del__() + + def test_reload(self): + codecontext.CodeContext.reload() + self.assertEqual(self.cc.context_depth, 3) + + def test_toggle_code_context_event(self): + eq = self.assertEqual + cc = self.cc + toggle = cc.toggle_code_context_event + + # Make sure code context is off. + if cc.label: + toggle() + + # Toggle on. + eq(toggle(), 'break') + self.assertIsNotNone(cc.label) + eq(cc.label['font'], cc.textfont) + eq(cc.label['fg'], cc.fgcolor) + eq(cc.label['bg'], cc.bgcolor) + eq(cc.label['text'], '\n' * 2) + + # Toggle off. + eq(toggle(), 'break') + self.assertIsNone(cc.label) + + def test_get_line_info(self): + eq = self.assertEqual + gli = self.cc.get_line_info + + # Line 1 is not a BLOCKOPENER. + eq(gli(1), (codecontext.INFINITY, '', False)) + # Line 2 is a BLOCKOPENER without an indent. + eq(gli(2), (0, 'class C1():', 'class')) + # Line 3 is not a BLOCKOPENER and does not return the indent level. + eq(gli(3), (codecontext.INFINITY, ' # Class comment.', False)) + # Line 4 is a BLOCKOPENER and is indented. + eq(gli(4), (4, ' def __init__(self, a, b):', 'def')) + # Line 8 is a different BLOCKOPENER and is indented. + eq(gli(8), (8, ' if a > b:', 'if')) + + def test_get_context(self): + eq = self.assertEqual + gc = self.cc.get_context + + # stopline must be greater than 0. + with self.assertRaises(AssertionError): + gc(1, stopline=0) + + eq(gc(3), ([(2, 0, 'class C1():', 'class')], 0)) + + # Don't return comment. + eq(gc(4), ([(2, 0, 'class C1():', 'class')], 0)) + + # Two indentation levels and no comment. + eq(gc(5), ([(2, 0, 'class C1():', 'class'), + (4, 4, ' def __init__(self, a, b):', 'def')], 0)) + + # Only one 'def' is returned, not both at the same indent level. + eq(gc(10), ([(2, 0, 'class C1():', 'class'), + (7, 4, ' def compare(self):', 'def'), + (8, 8, ' if a > b:', 'if')], 0)) + + # With 'elif', also show the 'if' even though it's at the same level. + eq(gc(11), ([(2, 0, 'class C1():', 'class'), + (7, 4, ' def compare(self):', 'def'), + (8, 8, ' if a > b:', 'if'), + (10, 8, ' elif a < b:', 'elif')], 0)) + + # Set stop_line to not go back to first line in source code. + # Return includes stop_line. + eq(gc(11, stopline=2), ([(2, 0, 'class C1():', 'class'), + (7, 4, ' def compare(self):', 'def'), + (8, 8, ' if a > b:', 'if'), + (10, 8, ' elif a < b:', 'elif')], 0)) + eq(gc(11, stopline=3), ([(7, 4, ' def compare(self):', 'def'), + (8, 8, ' if a > b:', 'if'), + (10, 8, ' elif a < b:', 'elif')], 4)) + eq(gc(11, stopline=8), ([(8, 8, ' if a > b:', 'if'), + (10, 8, ' elif a < b:', 'elif')], 8)) + + # Set stop_indent to test indent level to stop at. + eq(gc(11, stopindent=4), ([(7, 4, ' def compare(self):', 'def'), + (8, 8, ' if a > b:', 'if'), + (10, 8, ' elif a < b:', 'elif')], 4)) + # Check that the 'if' is included. + eq(gc(11, stopindent=8), ([(8, 8, ' if a > b:', 'if'), + (10, 8, ' elif a < b:', 'elif')], 8)) + + def test_update_code_context(self): + eq = self.assertEqual + cc = self.cc + # Ensure code context is active. + if not cc.label: + cc.toggle_code_context_event() + + # Invoke update_code_context without scrolling - nothing happens. + self.assertIsNone(cc.update_code_context()) + eq(cc.info, [(0, -1, '', False)]) + eq(cc.topvisible, 1) + + # Scroll down to line 2. + cc.text.yview(2) + cc.update_code_context() + eq(cc.info, [(0, -1, '', False), (2, 0, 'class C1():', 'class')]) + eq(cc.topvisible, 3) + # context_depth is 3 so it pads with blank lines. + eq(cc.label['text'], '\n' + '\n' + 'class C1():') + + # Scroll down to line 3. Since it's a comment, nothing changes. + cc.text.yview(3) + cc.update_code_context() + eq(cc.info, [(0, -1, '', False), (2, 0, 'class C1():', 'class')]) + eq(cc.topvisible, 4) + eq(cc.label['text'], '\n' + '\n' + 'class C1():') + + # Scroll down to line 4. + cc.text.yview(4) + cc.update_code_context() + eq(cc.info, [(0, -1, '', False), + (2, 0, 'class C1():', 'class'), + (4, 4, ' def __init__(self, a, b):', 'def')]) + eq(cc.topvisible, 5) + eq(cc.label['text'], '\n' + 'class C1():\n' + ' def __init__(self, a, b):') + + # Scroll down to line 11. Last 'def' is removed. + cc.text.yview(11) + cc.update_code_context() + eq(cc.info, [(0, -1, '', False), + (2, 0, 'class C1():', 'class'), + (7, 4, ' def compare(self):', 'def'), + (8, 8, ' if a > b:', 'if'), + (10, 8, ' elif a < b:', 'elif')]) + eq(cc.topvisible, 12) + eq(cc.label['text'], ' def compare(self):\n' + ' if a > b:\n' + ' elif a < b:') + + # No scroll. No update, even though context_depth changed. + cc.update_code_context() + cc.context_depth = 1 + eq(cc.info, [(0, -1, '', False), + (2, 0, 'class C1():', 'class'), + (7, 4, ' def compare(self):', 'def'), + (8, 8, ' if a > b:', 'if'), + (10, 8, ' elif a < b:', 'elif')]) + eq(cc.topvisible, 12) + eq(cc.label['text'], ' def compare(self):\n' + ' if a > b:\n' + ' elif a < b:') + + # Scroll up. + cc.text.yview(5) + cc.update_code_context() + eq(cc.info, [(0, -1, '', False), + (2, 0, 'class C1():', 'class'), + (4, 4, ' def __init__(self, a, b):', 'def')]) + eq(cc.topvisible, 6) + # context_depth is 1. + eq(cc.label['text'], ' def __init__(self, a, b):') + + @mock.patch.object(codecontext.CodeContext, 'update_code_context') + def test_timer_event(self, mock_update): + # Ensure code context is not active. + if self.cc.label: + self.cc.toggle_code_context_event() + self.cc.timer_event() + mock_update.assert_not_called() + + # Activate code context. + self.cc.toggle_code_context_event() + self.cc.timer_event() + mock_update.assert_called() + + def test_font_timer_event(self): + eq = self.assertEqual + cc = self.cc + save_font = cc.text['font'] + test_font = 'FakeFont' + + # Ensure code context is not active. + if cc.label: + cc.toggle_code_context_event() + + # Nothing updates on inactive code context. + cc.text['font'] = test_font + cc.font_timer_event() + eq(cc.textfont, save_font) + + # Activate code context, but no change to font. + cc.toggle_code_context_event() + cc.text['font'] = save_font + cc.font_timer_event() + eq(cc.textfont, save_font) + eq(cc.label['font'], save_font) + + # Active code context, change font. + cc.text['font'] = test_font + cc.font_timer_event() + eq(cc.textfont, test_font) + eq(cc.label['font'], test_font) + + cc.text['font'] = save_font + cc.font_timer_event() + + +class HelperFunctionText(unittest.TestCase): + + def test_getspacesfirstword(self): + get = codecontext.getspacesfirstword + test_lines = ( + (' first word', (' ', 'first')), + ('\tfirst word', ('\t', 'first')), + (' \u19D4\u19D2: ', (' ', '\u19D4\u19D2')), + ('no spaces', ('', 'no')), + ('', ('', '')), + ('# TEST COMMENT', ('', '')), + (' (continuation)', (' ', '')) + ) + for line, expected_output in test_lines: + self.assertEqual(get(line), expected_output) + + # Send the pattern in the call. + self.assertEqual(get(' (continuation)', + c=re.compile(r'^(\s*)([^\s]*)')), + (' ', '(continuation)')) + + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/Misc/NEWS.d/next/IDLE/2018-02-12-08-08-45.bpo-32831.srDRvU.rst b/Misc/NEWS.d/next/IDLE/2018-02-12-08-08-45.bpo-32831.srDRvU.rst new file mode 100644 index 000000000000..583e341f94f0 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2018-02-12-08-08-45.bpo-32831.srDRvU.rst @@ -0,0 +1 @@ +Add docstrings and tests for codecontext. From webhook-mailer at python.org Sat May 19 16:28:06 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 19 May 2018 20:28:06 -0000 Subject: [Python-checkins] bpo-32831: IDLE: Add docstrings and tests for codecontext (GH-5638) Message-ID: <mailman.155.1526761688.2757.python-checkins@python.org> https://github.com/python/cpython/commit/0efa1353b756bd61d4e852ff4ef146735bef5522 commit: 0efa1353b756bd61d4e852ff4ef146735bef5522 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-19T13:28:03-07:00 summary: bpo-32831: IDLE: Add docstrings and tests for codecontext (GH-5638) (cherry picked from commit 654038d896d78a8373b60184f335acd516215acd) Co-authored-by: Cheryl Sabella <cheryl.sabella at gmail.com> files: A Lib/idlelib/idle_test/test_codecontext.py A Misc/NEWS.d/next/IDLE/2018-02-12-08-08-45.bpo-32831.srDRvU.rst M Lib/idlelib/codecontext.py diff --git a/Lib/idlelib/codecontext.py b/Lib/idlelib/codecontext.py index 2bfb2e988ff4..efd163ed265e 100644 --- a/Lib/idlelib/codecontext.py +++ b/Lib/idlelib/codecontext.py @@ -22,32 +22,49 @@ UPDATEINTERVAL = 100 # millisec FONTUPDATEINTERVAL = 1000 # millisec + def getspacesfirstword(s, c=re.compile(r"^(\s*)(\w*)")): + "Extract the beginning whitespace and first word from s." return c.match(s).groups() class CodeContext: + "Display block context above the edit window." + bgcolor = "LightGray" fgcolor = "Black" def __init__(self, editwin): + """Initialize settings for context block. + + editwin is the Editor window for the context block. + self.text is the editor window text widget. + self.textfont is the editor window font. + + self.label displays the code context text above the editor text. + Initially None it is toggled via <<toggle-code-context>>. + self.topvisible is the number of the top text line displayed. + self.info is a list of (line number, indent level, line text, + block keyword) tuples for the block structure above topvisible. + s self.info[0] is initialized a 'dummy' line which + # starts the toplevel 'block' of the module. + + self.t1 and self.t2 are two timer events on the editor text widget to + monitor for changes to the context text or editor font. + """ self.editwin = editwin self.text = editwin.text self.textfont = self.text["font"] self.label = None - # self.info is a list of (line number, indent level, line text, block - # keyword) tuples providing the block structure associated with - # self.topvisible (the linenumber of the line displayed at the top of - # the edit window). self.info[0] is initialized as a 'dummy' line which - # starts the toplevel 'block' of the module. - self.info = [(0, -1, "", False)] self.topvisible = 1 + self.info = [(0, -1, "", False)] # Start two update cycles, one for context lines, one for font changes. self.t1 = self.text.after(UPDATEINTERVAL, self.timer_event) self.t2 = self.text.after(FONTUPDATEINTERVAL, self.font_timer_event) @classmethod def reload(cls): + "Load class variables from config." cls.context_depth = idleConf.GetOption("extensions", "CodeContext", "numlines", type="int", default=3) ## cls.bgcolor = idleConf.GetOption("extensions", "CodeContext", @@ -56,6 +73,7 @@ def reload(cls): ## "fgcolor", type="str", default="Black") def __del__(self): + "Cancel scheduled events." try: self.text.after_cancel(self.t1) self.text.after_cancel(self.t2) @@ -63,6 +81,12 @@ def __del__(self): pass def toggle_code_context_event(self, event=None): + """Toggle code context display. + + If self.label doesn't exist, create it to match the size of the editor + window text (toggle on). If it does exist, destroy it (toggle off). + Return 'break' to complete the processing of the binding. + """ if not self.label: # Calculate the border width and horizontal padding required to # align the context with the text in the main Text widget. @@ -95,11 +119,10 @@ def toggle_code_context_event(self, event=None): return "break" def get_line_info(self, linenum): - """Get the line indent value, text, and any block start keyword + """Return tuple of (line indent value, text, and block start keyword). If the line does not start a block, the keyword value is False. The indentation of empty lines (or comment lines) is INFINITY. - """ text = self.text.get("%d.0" % linenum, "%d.end" % linenum) spaces, firstword = getspacesfirstword(text) @@ -111,11 +134,13 @@ def get_line_info(self, linenum): return indent, text, opener def get_context(self, new_topvisible, stopline=1, stopindent=0): - """Get context lines, starting at new_topvisible and working backwards. - - Stop when stopline or stopindent is reached. Return a tuple of context - data and the indent level at the top of the region inspected. + """Return a list of block line tuples and the 'last' indent. + The tuple fields are (linenum, indent, text, opener). + The list represents header lines from new_topvisible back to + stopline with successively shorter indents > stopindent. + The list is returned ordered by line number. + Last indent returned is the smallest indent observed. """ assert stopline > 0 lines = [] @@ -140,6 +165,11 @@ def get_context(self, new_topvisible, stopline=1, stopindent=0): def update_code_context(self): """Update context information and lines visible in the context pane. + No update is done if the text hasn't been scrolled. If the text + was scrolled, the lines that should be shown in the context will + be retrieved and the label widget will be updated with the code, + padded with blank lines so that the code appears on the bottom of + the context label. """ new_topvisible = int(self.text.index("@0,0").split('.')[0]) if self.topvisible == new_topvisible: # haven't scrolled @@ -151,7 +181,7 @@ def update_code_context(self): # between topvisible and new_topvisible: while self.info[-1][1] >= lastindent: del self.info[-1] - elif self.topvisible > new_topvisible: # scroll up + else: # self.topvisible > new_topvisible: # scroll up stopindent = self.info[-1][1] + 1 # retain only context info associated # with lines above new_topvisible: @@ -170,11 +200,13 @@ def update_code_context(self): self.label["text"] = '\n'.join(context_strings) def timer_event(self): + "Event on editor text widget triggered every UPDATEINTERVAL ms." if self.label: self.update_code_context() self.t1 = self.text.after(UPDATEINTERVAL, self.timer_event) def font_timer_event(self): + "Event on editor text widget triggered every FONTUPDATEINTERVAL ms." newtextfont = self.text["font"] if self.label and newtextfont != self.textfont: self.textfont = newtextfont @@ -183,3 +215,8 @@ def font_timer_event(self): CodeContext.reload() + + +if __name__ == "__main__": # pragma: no cover + import unittest + unittest.main('idlelib.idle_test.test_codecontext', verbosity=2, exit=False) diff --git a/Lib/idlelib/idle_test/test_codecontext.py b/Lib/idlelib/idle_test/test_codecontext.py new file mode 100644 index 000000000000..448094eda7ef --- /dev/null +++ b/Lib/idlelib/idle_test/test_codecontext.py @@ -0,0 +1,347 @@ +"""Test idlelib.codecontext. + +Coverage: 100% +""" + +import re + +import unittest +from unittest import mock +from test.support import requires +from tkinter import Tk, Frame, Text, TclError + +import idlelib.codecontext as codecontext +from idlelib import config + + +usercfg = codecontext.idleConf.userCfg +testcfg = { + 'main': config.IdleUserConfParser(''), + 'highlight': config.IdleUserConfParser(''), + 'keys': config.IdleUserConfParser(''), + 'extensions': config.IdleUserConfParser(''), +} +code_sample = """\ + +class C1(): + # Class comment. + def __init__(self, a, b): + self.a = a + self.b = b + def compare(self): + if a > b: + return a + elif a < b: + return b + else: + return None +""" + + +class DummyEditwin: + def __init__(self, root, frame, text): + self.root = root + self.top = root + self.text_frame = frame + self.text = text + + +class CodeContextTest(unittest.TestCase): + + @classmethod + def setUpClass(cls): + requires('gui') + root = cls.root = Tk() + root.withdraw() + frame = cls.frame = Frame(root) + text = cls.text = Text(frame) + text.insert('1.0', code_sample) + # Need to pack for creation of code context label widget. + frame.pack(side='left', fill='both', expand=1) + text.pack(side='top', fill='both', expand=1) + cls.editor = DummyEditwin(root, frame, text) + codecontext.idleConf.userCfg = testcfg + + @classmethod + def tearDownClass(cls): + codecontext.idleConf.userCfg = usercfg + cls.editor.text.delete('1.0', 'end') + del cls.editor, cls.frame, cls.text + cls.root.update_idletasks() + cls.root.destroy() + del cls.root + + def setUp(self): + self.cc = codecontext.CodeContext(self.editor) + + def tearDown(self): + if self.cc.label: + self.cc.label.destroy() + # Explicitly call __del__ to remove scheduled scripts. + self.cc.__del__() + del self.cc.label, self.cc + + def test_init(self): + eq = self.assertEqual + ed = self.editor + cc = self.cc + + eq(cc.editwin, ed) + eq(cc.text, ed.text) + eq(cc.textfont, ed.text['font']) + self.assertIsNone(cc.label) + eq(cc.info, [(0, -1, '', False)]) + eq(cc.topvisible, 1) + eq(self.root.tk.call('after', 'info', self.cc.t1)[1], 'timer') + eq(self.root.tk.call('after', 'info', self.cc.t2)[1], 'timer') + + def test_del(self): + self.root.tk.call('after', 'info', self.cc.t1) + self.root.tk.call('after', 'info', self.cc.t2) + self.cc.__del__() + with self.assertRaises(TclError) as msg: + self.root.tk.call('after', 'info', self.cc.t1) + self.assertIn("doesn't exist", msg) + with self.assertRaises(TclError) as msg: + self.root.tk.call('after', 'info', self.cc.t2) + self.assertIn("doesn't exist", msg) + # For coverage on the except. Have to delete because the + # above Tcl error is caught by after_cancel. + del self.cc.t1, self.cc.t2 + self.cc.__del__() + + def test_reload(self): + codecontext.CodeContext.reload() + self.assertEqual(self.cc.context_depth, 3) + + def test_toggle_code_context_event(self): + eq = self.assertEqual + cc = self.cc + toggle = cc.toggle_code_context_event + + # Make sure code context is off. + if cc.label: + toggle() + + # Toggle on. + eq(toggle(), 'break') + self.assertIsNotNone(cc.label) + eq(cc.label['font'], cc.textfont) + eq(cc.label['fg'], cc.fgcolor) + eq(cc.label['bg'], cc.bgcolor) + eq(cc.label['text'], '\n' * 2) + + # Toggle off. + eq(toggle(), 'break') + self.assertIsNone(cc.label) + + def test_get_line_info(self): + eq = self.assertEqual + gli = self.cc.get_line_info + + # Line 1 is not a BLOCKOPENER. + eq(gli(1), (codecontext.INFINITY, '', False)) + # Line 2 is a BLOCKOPENER without an indent. + eq(gli(2), (0, 'class C1():', 'class')) + # Line 3 is not a BLOCKOPENER and does not return the indent level. + eq(gli(3), (codecontext.INFINITY, ' # Class comment.', False)) + # Line 4 is a BLOCKOPENER and is indented. + eq(gli(4), (4, ' def __init__(self, a, b):', 'def')) + # Line 8 is a different BLOCKOPENER and is indented. + eq(gli(8), (8, ' if a > b:', 'if')) + + def test_get_context(self): + eq = self.assertEqual + gc = self.cc.get_context + + # stopline must be greater than 0. + with self.assertRaises(AssertionError): + gc(1, stopline=0) + + eq(gc(3), ([(2, 0, 'class C1():', 'class')], 0)) + + # Don't return comment. + eq(gc(4), ([(2, 0, 'class C1():', 'class')], 0)) + + # Two indentation levels and no comment. + eq(gc(5), ([(2, 0, 'class C1():', 'class'), + (4, 4, ' def __init__(self, a, b):', 'def')], 0)) + + # Only one 'def' is returned, not both at the same indent level. + eq(gc(10), ([(2, 0, 'class C1():', 'class'), + (7, 4, ' def compare(self):', 'def'), + (8, 8, ' if a > b:', 'if')], 0)) + + # With 'elif', also show the 'if' even though it's at the same level. + eq(gc(11), ([(2, 0, 'class C1():', 'class'), + (7, 4, ' def compare(self):', 'def'), + (8, 8, ' if a > b:', 'if'), + (10, 8, ' elif a < b:', 'elif')], 0)) + + # Set stop_line to not go back to first line in source code. + # Return includes stop_line. + eq(gc(11, stopline=2), ([(2, 0, 'class C1():', 'class'), + (7, 4, ' def compare(self):', 'def'), + (8, 8, ' if a > b:', 'if'), + (10, 8, ' elif a < b:', 'elif')], 0)) + eq(gc(11, stopline=3), ([(7, 4, ' def compare(self):', 'def'), + (8, 8, ' if a > b:', 'if'), + (10, 8, ' elif a < b:', 'elif')], 4)) + eq(gc(11, stopline=8), ([(8, 8, ' if a > b:', 'if'), + (10, 8, ' elif a < b:', 'elif')], 8)) + + # Set stop_indent to test indent level to stop at. + eq(gc(11, stopindent=4), ([(7, 4, ' def compare(self):', 'def'), + (8, 8, ' if a > b:', 'if'), + (10, 8, ' elif a < b:', 'elif')], 4)) + # Check that the 'if' is included. + eq(gc(11, stopindent=8), ([(8, 8, ' if a > b:', 'if'), + (10, 8, ' elif a < b:', 'elif')], 8)) + + def test_update_code_context(self): + eq = self.assertEqual + cc = self.cc + # Ensure code context is active. + if not cc.label: + cc.toggle_code_context_event() + + # Invoke update_code_context without scrolling - nothing happens. + self.assertIsNone(cc.update_code_context()) + eq(cc.info, [(0, -1, '', False)]) + eq(cc.topvisible, 1) + + # Scroll down to line 2. + cc.text.yview(2) + cc.update_code_context() + eq(cc.info, [(0, -1, '', False), (2, 0, 'class C1():', 'class')]) + eq(cc.topvisible, 3) + # context_depth is 3 so it pads with blank lines. + eq(cc.label['text'], '\n' + '\n' + 'class C1():') + + # Scroll down to line 3. Since it's a comment, nothing changes. + cc.text.yview(3) + cc.update_code_context() + eq(cc.info, [(0, -1, '', False), (2, 0, 'class C1():', 'class')]) + eq(cc.topvisible, 4) + eq(cc.label['text'], '\n' + '\n' + 'class C1():') + + # Scroll down to line 4. + cc.text.yview(4) + cc.update_code_context() + eq(cc.info, [(0, -1, '', False), + (2, 0, 'class C1():', 'class'), + (4, 4, ' def __init__(self, a, b):', 'def')]) + eq(cc.topvisible, 5) + eq(cc.label['text'], '\n' + 'class C1():\n' + ' def __init__(self, a, b):') + + # Scroll down to line 11. Last 'def' is removed. + cc.text.yview(11) + cc.update_code_context() + eq(cc.info, [(0, -1, '', False), + (2, 0, 'class C1():', 'class'), + (7, 4, ' def compare(self):', 'def'), + (8, 8, ' if a > b:', 'if'), + (10, 8, ' elif a < b:', 'elif')]) + eq(cc.topvisible, 12) + eq(cc.label['text'], ' def compare(self):\n' + ' if a > b:\n' + ' elif a < b:') + + # No scroll. No update, even though context_depth changed. + cc.update_code_context() + cc.context_depth = 1 + eq(cc.info, [(0, -1, '', False), + (2, 0, 'class C1():', 'class'), + (7, 4, ' def compare(self):', 'def'), + (8, 8, ' if a > b:', 'if'), + (10, 8, ' elif a < b:', 'elif')]) + eq(cc.topvisible, 12) + eq(cc.label['text'], ' def compare(self):\n' + ' if a > b:\n' + ' elif a < b:') + + # Scroll up. + cc.text.yview(5) + cc.update_code_context() + eq(cc.info, [(0, -1, '', False), + (2, 0, 'class C1():', 'class'), + (4, 4, ' def __init__(self, a, b):', 'def')]) + eq(cc.topvisible, 6) + # context_depth is 1. + eq(cc.label['text'], ' def __init__(self, a, b):') + + @mock.patch.object(codecontext.CodeContext, 'update_code_context') + def test_timer_event(self, mock_update): + # Ensure code context is not active. + if self.cc.label: + self.cc.toggle_code_context_event() + self.cc.timer_event() + mock_update.assert_not_called() + + # Activate code context. + self.cc.toggle_code_context_event() + self.cc.timer_event() + mock_update.assert_called() + + def test_font_timer_event(self): + eq = self.assertEqual + cc = self.cc + save_font = cc.text['font'] + test_font = 'FakeFont' + + # Ensure code context is not active. + if cc.label: + cc.toggle_code_context_event() + + # Nothing updates on inactive code context. + cc.text['font'] = test_font + cc.font_timer_event() + eq(cc.textfont, save_font) + + # Activate code context, but no change to font. + cc.toggle_code_context_event() + cc.text['font'] = save_font + cc.font_timer_event() + eq(cc.textfont, save_font) + eq(cc.label['font'], save_font) + + # Active code context, change font. + cc.text['font'] = test_font + cc.font_timer_event() + eq(cc.textfont, test_font) + eq(cc.label['font'], test_font) + + cc.text['font'] = save_font + cc.font_timer_event() + + +class HelperFunctionText(unittest.TestCase): + + def test_getspacesfirstword(self): + get = codecontext.getspacesfirstword + test_lines = ( + (' first word', (' ', 'first')), + ('\tfirst word', ('\t', 'first')), + (' \u19D4\u19D2: ', (' ', '\u19D4\u19D2')), + ('no spaces', ('', 'no')), + ('', ('', '')), + ('# TEST COMMENT', ('', '')), + (' (continuation)', (' ', '')) + ) + for line, expected_output in test_lines: + self.assertEqual(get(line), expected_output) + + # Send the pattern in the call. + self.assertEqual(get(' (continuation)', + c=re.compile(r'^(\s*)([^\s]*)')), + (' ', '(continuation)')) + + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/Misc/NEWS.d/next/IDLE/2018-02-12-08-08-45.bpo-32831.srDRvU.rst b/Misc/NEWS.d/next/IDLE/2018-02-12-08-08-45.bpo-32831.srDRvU.rst new file mode 100644 index 000000000000..583e341f94f0 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2018-02-12-08-08-45.bpo-32831.srDRvU.rst @@ -0,0 +1 @@ +Add docstrings and tests for codecontext. From webhook-mailer at python.org Sat May 19 18:48:33 2018 From: webhook-mailer at python.org (Ned Deily) Date: Sat, 19 May 2018 22:48:33 -0000 Subject: [Python-checkins] Fix typo in error message when decoding PYTHONPATH. (GH-6981) Message-ID: <mailman.156.1526770114.2757.python-checkins@python.org> https://github.com/python/cpython/commit/4857543a090c6c1ad20e935b2d7e88bbf2cbcc01 commit: 4857543a090c6c1ad20e935b2d7e88bbf2cbcc01 branch: master author: Carl Meyer <carl at oddbird.net> committer: Ned Deily <nad at python.org> date: 2018-05-19T18:48:22-04:00 summary: Fix typo in error message when decoding PYTHONPATH. (GH-6981) files: M Modules/main.c diff --git a/Modules/main.c b/Modules/main.c index f6b51043007b..9cbb3f1ce003 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -1831,7 +1831,7 @@ config_read_env_vars(_PyCoreConfig *config) wchar_t *path; int res = config_get_env_var_dup(&path, L"PYTHONPATH", "PYTHONPATH"); if (res < 0) { - return DECODE_LOCALE_ERR("PYTHONHOME", res); + return DECODE_LOCALE_ERR("PYTHONPATH", res); } config->module_search_path_env = path; From webhook-mailer at python.org Sat May 19 19:14:45 2018 From: webhook-mailer at python.org (Ned Deily) Date: Sat, 19 May 2018 23:14:45 -0000 Subject: [Python-checkins] Fix typo in error message when decoding PYTHONPATH. (GH-6981) (GH-6993) Message-ID: <mailman.157.1526771687.2757.python-checkins@python.org> https://github.com/python/cpython/commit/6414da93ed870116f97b846cb252388d9cc0f10b commit: 6414da93ed870116f97b846cb252388d9cc0f10b branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Ned Deily <nad at python.org> date: 2018-05-19T19:14:42-04:00 summary: Fix typo in error message when decoding PYTHONPATH. (GH-6981) (GH-6993) (cherry picked from commit 4857543a090c6c1ad20e935b2d7e88bbf2cbcc01) Co-authored-by: Carl Meyer <carl at oddbird.net> files: M Modules/main.c diff --git a/Modules/main.c b/Modules/main.c index f6b51043007b..9cbb3f1ce003 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -1831,7 +1831,7 @@ config_read_env_vars(_PyCoreConfig *config) wchar_t *path; int res = config_get_env_var_dup(&path, L"PYTHONPATH", "PYTHONPATH"); if (res < 0) { - return DECODE_LOCALE_ERR("PYTHONHOME", res); + return DECODE_LOCALE_ERR("PYTHONPATH", res); } config->module_search_path_env = path; From webhook-mailer at python.org Sat May 19 21:38:49 2018 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Sun, 20 May 2018 01:38:49 -0000 Subject: [Python-checkins] bpo-30928: Update idlelib/NEWS.txt. (#6995) Message-ID: <mailman.158.1526780330.2757.python-checkins@python.org> https://github.com/python/cpython/commit/6b0d09b8f06e6967fa3d41425cecf6499a353a6d commit: 6b0d09b8f06e6967fa3d41425cecf6499a353a6d branch: master author: Terry Jan Reedy <tjreedy at udel.edu> committer: GitHub <noreply at github.com> date: 2018-05-19T21:38:46-04:00 summary: bpo-30928: Update idlelib/NEWS.txt. (#6995) files: M Lib/idlelib/NEWS.txt diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index e255b0402d42..786378e2a632 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -3,6 +3,11 @@ Released on 2018-06-18? ====================================== +bpo-32831: Add docstrings and tests for codecontext.py. +Coverage is 100%. Patch by Cheryl Sabella. + +bpo-33564: Code context now recognizes async as a block opener. + bpo-21474: Update word/identifier definition from ascii to unicode. In text and entry boxes, this affects selection by double-click, movement left/right by control-left/right, and deletion left/right From webhook-mailer at python.org Sat May 19 22:01:29 2018 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Sun, 20 May 2018 02:01:29 -0000 Subject: [Python-checkins] bpo-30928: Update idlelib/NEWS.txt. (GH-6995) (#6996) Message-ID: <mailman.159.1526781692.2757.python-checkins@python.org> https://github.com/python/cpython/commit/222ae1eccc819d82fcadbb3c9e1fba83339cc5c6 commit: 222ae1eccc819d82fcadbb3c9e1fba83339cc5c6 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Terry Jan Reedy <tjreedy at udel.edu> date: 2018-05-19T22:01:26-04:00 summary: bpo-30928: Update idlelib/NEWS.txt. (GH-6995) (#6996) (cherry picked from commit 6b0d09b8f06e6967fa3d41425cecf6499a353a6d) Co-authored-by: Terry Jan Reedy <tjreedy at udel.edu> files: M Lib/idlelib/NEWS.txt diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index e255b0402d42..786378e2a632 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -3,6 +3,11 @@ Released on 2018-06-18? ====================================== +bpo-32831: Add docstrings and tests for codecontext.py. +Coverage is 100%. Patch by Cheryl Sabella. + +bpo-33564: Code context now recognizes async as a block opener. + bpo-21474: Update word/identifier definition from ascii to unicode. In text and entry boxes, this affects selection by double-click, movement left/right by control-left/right, and deletion left/right From webhook-mailer at python.org Sat May 19 23:15:11 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Sun, 20 May 2018 03:15:11 -0000 Subject: [Python-checkins] bpo-32996: The bulk of What's New in Python 3.7 (GH-6978) Message-ID: <mailman.160.1526786112.2757.python-checkins@python.org> https://github.com/python/cpython/commit/63536bd286097e770909052052a21804a5e09b66 commit: 63536bd286097e770909052052a21804a5e09b66 branch: master author: Elvis Pranskevichus <elvis at magic.io> committer: Yury Selivanov <yury at magic.io> date: 2018-05-19T23:15:06-04:00 summary: bpo-32996: The bulk of What's New in Python 3.7 (GH-6978) files: M Doc/library/asyncio-task.rst M Doc/library/ensurepip.rst M Doc/reference/compound_stmts.rst M Doc/whatsnew/3.7.rst diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index db0e04a4a1d1..2488a909ec00 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -92,7 +92,7 @@ Coroutines (and tasks) can only run when the event loop is running. used in a callback-style code, wrap its result with :func:`ensure_future`. -.. function:: asyncio.run(coro, \*, debug=False) +.. function:: run(coro, \*, debug=False) This function runs the passed coroutine, taking care of managing the asyncio event loop and finalizing asynchronous diff --git a/Doc/library/ensurepip.rst b/Doc/library/ensurepip.rst index ed22180dc3f8..c797f63326d1 100644 --- a/Doc/library/ensurepip.rst +++ b/Doc/library/ensurepip.rst @@ -78,9 +78,6 @@ options: Providing both of the script selection options will trigger an exception. -.. versionchanged:: 3.7.0 - The exit status is non-zero if the command fails. - Module API ---------- diff --git a/Doc/reference/compound_stmts.rst b/Doc/reference/compound_stmts.rst index 153e85b39491..5076e5df0078 100644 --- a/Doc/reference/compound_stmts.rst +++ b/Doc/reference/compound_stmts.rst @@ -684,6 +684,8 @@ can be used to create instance variables with different implementation details. :pep:`3129` - Class Decorators +.. _async: + Coroutines ========== diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 24a5b3daf92a..09a6eac879c4 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -2,6 +2,8 @@ What's New In Python 3.7 **************************** +:Editor: Elvis Pranskevichus <elvis at magic.io> + .. Rules for maintenance: * Anyone can add text to this document. Do not spend very much time @@ -39,34 +41,141 @@ module. (Contributed by P.Y. Developer in :issue:`12345`.) - This saves the maintainer the effort of going through the Mercurial log + This saves the maintainer the effort of going through the Git log when researching a change. This article explains the new features in Python 3.7, compared to 3.6. For full details, see the :ref:`changelog <changelog>`. -.. note:: - - Prerelease users should be aware that this document is currently in draft - form. It will be updated substantially as Python 3.7 moves towards release, - so it's worth checking back even after reading earlier versions. - -Summary -- Release highlights +Summary -- Release Highlights ============================= .. This section singles out the most important changes in Python 3.7. Brevity is key. +New syntax features: + +* :ref:`PEP 563 <whatsnew37-pep563>`, postponed evaluation of type annotations. + +Backwards incompatible syntax changes: + +* :keyword:`async` and :keyword:`await` are now reserved keywords. + +New library modules: + +* :mod:`contextvars`: :ref:`PEP 567 -- Context Variables <whatsnew37-pep567>` +* :mod:`dataclasses`: :ref:`PEP 557 -- Data Classes <whatsnew37-pep557>` +* :ref:`whatsnew37_importlib_resources` + +New built-in features: + +* :ref:`PEP 553 <whatsnew37-pep553>`, the new :func:`breakpoint` function. + +Python data model improvements: + +* :ref:`PEP 562 <whatsnew37-pep562>`, customization of access to + module attributes. + +* :ref:`PEP 560 <whatsnew37-pep560>`, core support for typing module and + generic types. + +* the insertion-order preservation nature of :ref:`dict <typesmapping>` + objects `has been declared`_ to be an official + part of the Python language spec. + +.. _has been declared: https://mail.python.org/pipermail/python-dev/2017-December/151283.html + +Significant improvements in the standard library: + +* The :mod:`asyncio` module has received new features, significant + :ref:`usability and performance improvements <whatsnew37_asyncio>`. + +* The :mod:`time` module gained support for + :ref:`functions with nanosecond resolution <whatsnew37-pep564>`. + +CPython implementation improvements: + +* :ref:`PEP 552 <whatsnew37-pep552>`, deterministic .pycs +* :ref:`PEP 538 <whatsnew37-pep538>`, legacy C locale coercion +* :ref:`PEP 540 <whatsnew37-pep540>`, forced UTF-8 runtime mode +* :ref:`the new development runtime mode <whatsnew37-devmode>` +* :ref:`PEP 565 <whatsnew37-pep565>`, improved :exc:`DeprecationWarning` + handling -.. PEP-sized items next. +C API improvements: +* :ref:`PEP 539 <whatsnew37-pep539>`, new C API for thread-local storage + +Documentation improvements: + +* :ref:`PEP 545 <whatsnew37-pep545>`, Python documentation translations +* New documentation translations: `Japanese <https://docs.python.org/ja/>`_, + `French <https://docs.python.org/fr/>`_, and + `Korean <https://docs.python.org/ko/>`_. + +This release features notable performance improvements in many areas. +The :ref:`whatsnew37-perf` section lists them in detail. + +For a list of changes that may affect compatibility with previous Python +releases please refer to the :ref:`porting-to-python-37` section. New Features ============ +.. _whatsnew37-pep563: + +PEP 563: Postponed Evaluation of Annotations +-------------------------------------------- + +The advent of type hints in Python uncovered two glaring usability issues +with the functionality of annotations added in :pep:`3107` and refined +further in :pep:`526`: + +* annotations could only use names which were already available in the + current scope, in other words they didn't support forward references + of any kind; and + +* annotating source code had adverse effects on startup time of Python + programs. + +Both of these issues are fixed by postponing the evaluation of +annotations. Instead of compiling code which executes expressions in +annotations at their definition time, the compiler stores the annotation +in a string form equivalent to the AST of the expression in question. +If needed, annotations can be resolved at runtime using +:func:`typing.get_type_hints`. In the common case where this is not +required, the annotations are cheaper to store (since short strings +are interned by the interpreter) and make startup time faster. + +Usability-wise, annotations now support forward references, making the +following syntax valid:: + + class C: + @classmethod + def from_string(cls, source: str) -> C: + ... + + def validate_b(self, obj: B) -> bool: + ... + + class B: + ... + +Since this change breaks compatibility, the new behavior needs to be enabled +on a per-module basis in Python 3.7 using a :mod:`__future__` import:: + + from __future__ import annotations + +It will become the default in Python 4.0. + +.. seealso:: + + :pep:`563` -- Postponed evaluation of annotations + PEP written and implemented by ?ukasz Langa. + .. _whatsnew37-pep538: @@ -106,19 +215,46 @@ legacy C locale remains active when the core interpreter is initialized. PEP written and implemented by Nick Coghlan. +.. _whatsnew37-pep540: + +PEP 540: Forced UTF-8 Runtime Mode +----------------------------------- + +The new :option:`-X` ``utf8`` command line option and :envvar:`PYTHONUTF8` +environment variable can be used to enable the CPython *UTF-8 mode*. + +When in UTF-8 mode, CPython ignores the locale settings, and uses the +UTF-8 encoding by default. The error handlers for :data:`sys.stdin` and +:data:`sys.stdout` streams are set to ``surrogateescape``. + +The forced UTF-8 mode can be used to change the text handling behavior in +an embedded Python interpreter without changing the locale settings of +an embedding application. + +The UTF-8 mode is enabled by default when the locale is "C". See +:ref:`whatsnew37-pep538` for details. + +.. seealso:: + + :pep:`540` -- Add a new UTF-8 mode + PEP written and implemented by Victor Stinner + + .. _whatsnew37-pep553: -PEP 553: Built-in breakpoint() ------------------------------- +PEP 553: Built-in ``breakpoint()`` +---------------------------------- + +Python 3.7 includes the new built-in :func:`breakpoint` function as +an easy and consistent way to enter the Python debugger. -:pep:`553` describes a new built-in called :func:`breakpoint` which makes it -easy and consistent to enter the Python debugger. Built-in ``breakpoint()`` -calls :func:`sys.breakpointhook`. By default, this latter imports :mod:`pdb` and -then calls ``pdb.set_trace()``, but by binding ``sys.breakpointhook()`` to the -function of your choosing, ``breakpoint()`` can enter any debugger. Or, the -environment variable :envvar:`PYTHONBREAKPOINT` can be set to the callable of -your debugger of choice. Set ``PYTHONBREAKPOINT=0`` to completely disable -built-in ``breakpoint()``. +Built-in ``breakpoint()`` calls :func:`sys.breakpointhook`. By default, the +latter imports :mod:`pdb` and then calls ``pdb.set_trace()``, but by binding +``sys.breakpointhook()`` to the function of your choosing, ``breakpoint()`` can +enter any debugger. Additionally, the environment variable +:envvar:`PYTHONBREAKPOINT` can be set to the callable of your debugger of +choice. Set ``PYTHONBREAKPOINT=0`` to completely disable built-in +``breakpoint()``. .. seealso:: @@ -128,8 +264,8 @@ built-in ``breakpoint()``. .. _whatsnew37-pep539: -PEP 539: A New C-API for Thread-Local Storage in CPython --------------------------------------------------------- +PEP 539: New C API for Thread-Local Storage +------------------------------------------- While Python provides a C API for thread-local storage support; the existing :ref:`Thread Local Storage (TLS) API <thread-local-storage-api>` has used @@ -158,17 +294,16 @@ effort will be made to add such support. PEP written by Erik M. Bray; implementation by Masayuki Yamamoto. -PEP 562: Customization of access to module attributes +.. _whatsnew37-pep562: + +PEP 562: Customization of Access to Module Attributes ----------------------------------------------------- -It is sometimes convenient to customize or otherwise have control over access -to module attributes. A typical example is managing deprecation warnings. -Typical workarounds are assigning :attr:`~instance.__class__` of a module -object to a custom subclass of :class:`types.ModuleType` or replacing the -:data:`sys.modules` item with a custom wrapper instance. This procedure is -now simplified by recognizing ``__getattr__`` defined directly in a module -that would act like a normal :meth:`__getattr__` method, except that it will -be defined on module *instances*. +Python 3.7 allows defining :meth:`__getattr__` on modules and will call +it whenever a module attribute is otherwise not found. + +A typical example of where this may be useful is module attribute deprecation +and lazy loading. .. seealso:: @@ -176,62 +311,13 @@ be defined on module *instances*. PEP written and implemented by Ivan Levkivskyi -PEP 563: Postponed evaluation of annotations --------------------------------------------- +.. _whatsnew37-pep564: -The advent of type hints in Python uncovered two glaring usability issues -with the functionality of annotations added in :pep:`3107` and refined -further in :pep:`526`: +PEP 564: New Time Functions With Nanosecond Resolution +------------------------------------------------------ -* annotations could only use names which were already available in the - current scope, in other words they didn't support forward references - of any kind; and - -* annotating source code had adverse effects on startup time of Python - programs. - -Both of these issues are fixed by postponing the evaluation of -annotations. Instead of compiling code which executes expressions in -annotations at their definition time, the compiler stores the annotation -in a string form equivalent to the AST of the expression in question. -If needed, annotations can be resolved at runtime using -``typing.get_type_hints()``. In the common case where this is not -required, the annotations are cheaper to store (since short strings -are interned by the interpreter) and make startup time faster. - -Usability-wise, annotations now support forward references, making the -following syntax valid:: - - class C: - @classmethod - def from_string(cls, source: str) -> C: - ... - - def validate_b(self, obj: B) -> bool: - ... - - class B: - ... - -Since this change breaks compatibility, the new behavior can be enabled -on a per-module basis in Python 3.7 using a :mod:`__future__` import, like -this:: - - from __future__ import annotations - -It will become the default in Python 4.0. - -.. seealso:: - - :pep:`563` -- Postponed evaluation of annotations - PEP written and implemented by ?ukasz Langa. - - -PEP 564: Add new time functions with nanosecond resolution ----------------------------------------------------------- - -Add six new "nanosecond" variants of existing functions to the :mod:`time` -module: +:pep:`564` adds six new "nanosecond" variants of existing functions +to the :mod:`time` module: * :func:`time.clock_gettime_ns` * :func:`time.clock_settime_ns` @@ -240,12 +326,12 @@ module: * :func:`time.process_time_ns` * :func:`time.time_ns` -While similar to the existing functions without the ``_ns`` suffix, they -provide nanosecond resolution: they return a number of nanoseconds as a Python -``int``. +The new functions are similar in function to the existing functions +without the ``_ns`` suffix. They differ by returning nanoseconds as +integers instead of fractional seconds. -The ``time.time_ns()`` resolution is 3 times better than the ``time.time()`` -resolution on Linux and Windows. +On Linux and Windows the resolution of :func:`time.time_ns` is 3 times +better than that of :func:`time.time`. .. seealso:: @@ -291,73 +377,10 @@ by breaking changes in the APIs they used. PEP written and implemented by Nick Coghlan -PEP 540: Add a new UTF-8 mode ------------------------------ - -Add a new UTF-8 mode to ignore the locale, use the UTF-8 encoding, and change -:data:`sys.stdin` and :data:`sys.stdout` error handlers to ``surrogateescape``. -This mode is enabled by default in the POSIX locale, but otherwise disabled by -default. - -The new :option:`-X` ``utf8`` command line option and :envvar:`PYTHONUTF8` -environment variable are added to control the UTF-8 mode. - -.. seealso:: - - :pep:`540` -- Add a new UTF-8 mode - PEP written and implemented by Victor Stinner - - -.. _whatsnew37-pep557: - -PEP 557: Data Classes ---------------------- - -Adds a new module :mod:`dataclasses`. It provides a class decorator -:func:`~dataclasses.dataclass` which inspects the class's variable annotations (see -:pep:`526`) and using them, adds methods such as ``__init__``, -``__repr__``, and ``__eq__`` to the class. It is similar to -:class:`typing.NamedTuple`, but also works on classes with mutable -instances, among other features. - -For example:: - - @dataclass - class Point: - x: float - y: float - z: float = 0.0 - - p = Point(1.5, 2.5) - print(p) # produces "Point(x=1.5, y=2.5, z=0.0)" - -.. seealso:: - - :pep:`557` -- Data Classes - PEP written and implemented by Eric V. Smith - - -PEP 567: Context Variables --------------------------- - -Adds a new module :mod:`contextvars`, that provides APIs to manage, -store, and access non-local state. - -Context variables are natively supported in :mod:`asyncio` and are -ready to be used without any extra configuration. - -The :mod:`decimal` module was updated to use *contextvars* to store -the current decimal context. This allows decimal operations to work -with the correct context in async/await code. - -.. seealso:: - - :pep:`567` -- Context Variables - PEP written and implemented by Yury Selivanov - +.. _whatsnew37-pep560: -PEP 560: Core support for typing module and generic types ---------------------------------------------------------- +PEP 560: Core Support for ``typing`` module and Generic Types +------------------------------------------------------------- Initially :pep:`484` was designed in such way that it would not introduce *any* changes to the core CPython interpreter. Now type hints and the :mod:`typing` @@ -375,17 +398,23 @@ fixed. PEP written and implemented by Ivan Levkivskyi -New Development Mode: -X dev ----------------------------- +.. _whatsnew37-devmode: -Add a new "development mode": :option:`-X` ``dev`` command line option and -:envvar:`PYTHONDEVMODE` environment variable to enable CPython's "development -mode", introducing additional runtime checks which are too expensive to be -enabled by default. See :option:`-X` ``dev`` documentation for the effects of -the development mode. +Development Runtime Mode: -X dev +-------------------------------- -Hash-based pycs ---------------- +The new :option:`-X` ``dev`` command line option or the new +:envvar:`PYTHONDEVMODE` environment variable can be used to enable +CPython's *development mode*. When in development mode, CPython performs +additional runtime checks which are too expensive to be enabled by default. +See :option:`-X` ``dev`` documentation for the full description of the effects +of this mode. + + +.. _whatsnew37-pep552: + +PEP 552: Hash-based .pyc Files +------------------------------ Python has traditionally checked the up-to-dateness of bytecode cache files (i.e., ``.pyc`` files) by comparing the source metadata (last-modified timestamp @@ -412,6 +441,27 @@ keeping ``.pyc`` files up-to-date. See :ref:`pyc-invalidation` for more information. +.. _whatsnew37-pep545: + +PEP 545: Python Documentation Translations +------------------------------------------ + +:pep:`545` describes the process of creating and maintaining Python +documentation translations. + +Three new translations have been added: + +- Japanese: https://docs.python.org/ja/ +- French: https://docs.python.org/fr/ +- Korean: https://docs.python.org/ko/ + +.. seealso:: + + :pep:`545` -- Python Documentation Translations + PEP written and implemented by Julien Palard, Inada Naoki, and + Victor Stinner. + + Other Language Changes ====================== @@ -422,6 +472,11 @@ Other Language Changes * :meth:`bytes.fromhex` and :meth:`bytearray.fromhex` now ignore all ASCII whitespace, not only spaces. (Contributed by Robert Xiao in :issue:`28927`.) +* :class:`str`, :class:`bytes`, and :class:`bytearray` gained support for + the new :meth:`isascii() <str.isascii>` method, which can be used to + test if a string or bytes contain only the ASCII characters. + (Contributed by INADA Naoki in :issue:`32677`.) + * :exc:`ImportError` now displays module name and module ``__file__`` path when ``from ... import ...`` fails. (Contributed by Matthias Bussonnier in :issue:`29546`.) @@ -446,22 +501,83 @@ Other Language Changes time when an import occurs) (Contributed by Nick Coghlan in :issue:`33053`.) +* The new :option:`-X` ``importtime`` option or the + :envvar:`PYTHONPROFILEIMPORTTIME` environment variable can be used to show + the timing of each module import. + (Contributed by Victor Stinner in :issue:`31415`.) + New Modules =========== +.. _whatsnew37-pep567: + +contextvars +----------- + +The new :mod:`contextvars` module and a set of new C APIs introduce +support for *context variables*. Context variables are conceptually +similar to thread-local variables. Unlike TLS, context variables +support asynchronous code correctly. + +The :mod:`asyncio` and :mod:`decimal` modules have been updated to use +and support context variables out of the box. Particularly the active +decimal context is now stored in a context variable, which allows +decimal operations to work with the correct context in asynchronous code. + +.. seealso:: + + :pep:`567` -- Context Variables + PEP written and implemented by Yury Selivanov + + +.. _whatsnew37-pep557: + +dataclasses +----------- + +The new :func:`~dataclasses.dataclass` decorator provides a way to declare +*data classes*. A data class describes its attributes using class variable +annotations. Its constructor and other magic methods, such as +:meth:`~object.__repr__`, :meth:`~object.__eq__`, and +:meth:`~object.__hash__` are generated automatically. + +Example:: + + @dataclass + class Point: + x: float + y: float + z: float = 0.0 + + p = Point(1.5, 2.5) + print(p) # produces "Point(x=1.5, y=2.5, z=0.0)" + +.. seealso:: + + :pep:`557` -- Data Classes + PEP written and implemented by Eric V. Smith + + +.. _whatsnew37_importlib_resources: + importlib.resources ------------------- -This module provides several new APIs and one new ABC for access to, opening, -and reading *resources* inside packages. Resources are roughly akin to files -inside of packages, but they needn't be actual files on the physical file -system. Module loaders can provide a :meth:`get_resource_reader()` function -which returns a :class:`importlib.abc.ResourceReader` instance to support this +The new :mod:`importlib.resources` module provides several new APIs and one +new ABC for access to, opening, and reading *resources* inside packages. +Resources are roughly similar to files inside packages, but they needn't +be actual files on the physical file system. Module loaders can provide a +:meth:`get_resource_reader()` function which returns +a :class:`importlib.abc.ResourceReader` instance to support this new API. Built-in file path loaders and zip file loaders both support this. -(see the PyPI package -`importlib_resources <http://importlib-resources.readthedocs.io/en/latest/>`_ -as a compatible back port for older Python versions). + +Contributed by Barry Warsaw and Brett Cannon in :issue:`32248`. + +.. seealso:: + + `importlib_resources <http://importlib-resources.readthedocs.io/en/latest/>`_ + -- a PyPI backport for earlier Python versions. Improved Modules @@ -471,10 +587,143 @@ Improved Modules argparse -------- -The :meth:`~argparse.ArgumentParser.parse_intermixed_args` supports letting -the user intermix options and positional arguments on the command line, -as is possible in many unix commands. It supports most but not all -argparse features. (Contributed by paul.j3 in :issue:`14191`.) +The new :meth:`ArgumentParser.parse_intermixed_args() +<argparse.ArgumentParser.parse_intermixed_args>` +method allows intermixing options and positional arguments. +(Contributed by paul.j3 in :issue:`14191`.) + + +.. _whatsnew37_asyncio: + +asyncio +------- + +The :mod:`asyncio` module has received many new features, usability and +:ref:`performance improvements <whatsnew37-asyncio-perf>`. Notable changes +include: + +* The new :term:`provisional <provisional api>` :func:`asyncio.run` function can + be used to run a coroutine from synchronous code by automatically creating and + destroying the event loop. + (Contributed by Yury Selivanov in :issue:`32314`.) + +* The new :func:`asyncio.create_task` function has been added as a shortcut + to ``asyncio.get_event_loop().create_task()``. + (Contributed by Andrew Svetlov in :issue:`32311`.) + +* The new :meth:`loop.start_tls() <asyncio.AbstractEventLoop.start_tls>` + method can be used to upgrade an existing connection to TLS. + (Contributed by Yury Selivanov in :issue:`23749`.) + +* The new :meth:`loop.sock_recv_into() <asyncio.AbstractEventLoop.sock_recv_into>` + method allows reading data from a socket directly into a provided buffer making + it possible to reduce data copies. + (Contributed by Antoine Pitrou in :issue:`31819`.) + +* The new :func:`asyncio.current_task` function returns the currently running + :class:`~asyncio.Task` instance, and the new :func:`asyncio.all_tasks` + function returns a set of all existing ``Task`` instances in a given loop. + The :meth:`Task.current_task() <asyncio.Task.current_task>` and + :meth:`Task.all_tasks() <asyncio.Task.all_tasks>` methods have been deprecated. + (Contributed by Andrew Svetlov in :issue:`32250`.) + +* The new *provisional* :class:`~asyncio.BufferedProtocol` class allows + implementing streaming protocols with manual control over the receive buffer. + (Contributed by Yury Selivanov in :issue:`32251`.) + +* The new :func:`asyncio.get_running_loop` function returns the currently + running loop, and raises a :exc:`RuntimeError` if no loop is running. + This is in contrast with :func:`asyncio.get_event_loop`, which will *create* + a new event loop if none is running. + (Contributed by Yury Selivanov in :issue:`32269`.) + +* The new :meth:`StreamWriter.wait_closed() <asyncio.StreamWriter.wait_closed>` + coroutine method allows waiting until the stream writer is closed. The new + :meth:`StreamWriter.is_closing() <asyncio.StreamWriter.is_closing>` method + can be used to determine if the writer is closing. + (Contributed by Andrew Svetlov in :issue:`32391`.) + +* The new :meth:`loop.sock_sendfile() <asyncio.AbstractEventLoop.sock_sendfile>` + coroutine method allows sending files using :mod:`os.sendfile` when possible. + (Contributed by Andrew Svetlov in :issue:`32410`.) + +* The new :meth:`Task.get_loop() <asyncio.Task.get_loop>` and + :meth:`Future.get_loop() <asyncio.Future.get_loop>` methods + return the instance of the loop on which a task or a future were created. + :meth:`Server.get_loop() <asyncio.Server.get_loop>` allows doing the same for + :class:`asyncio.Server` objects. + (Contributed by Yury Selivanov in :issue:`32415` and + Srinivas Reddy Thatiparthy in :issue:`32418`.) + +* It is now possible to control how instances of :class:`asyncio.Server` begin + serving. Previously, the server would start serving immediately when created. + The new *start_serving* keyword argument to + :meth:`loop.create_server() <asyncio.AbstractEventLoop.create_server>` and + :meth:`loop.create_unix_server() <asyncio.AbstractEventLoop.create_unix_server>`, + as well as :meth:`Server.start_serving() <asyncio.Server.start_serving>`, and + :meth:`Server.serve_forever() <asyncio.Server.serve_forever>` + can be used to decouple server instantiation and serving. The new + :meth:`Server.is_serving() <asyncio.Server.is_serving>` method returns ``True`` + if the server is serving. :class:`~asyncio.Server` objects are now + asynchronous context managers:: + + srv = await loop.create_server(...) + + async with srv: + # some code + + # At this point, srv is closed and no longer accepts new connections. + + (Contributed by Yury Selivanov in :issue:`32662`.) + +* Callback objects returned by + :func:`loop.call_later() <asyncio.AbstractEventLoop.call_later>` + gained the new :meth:`when() <asyncio.TimerHandle.when>` method which + returns an absolute scheduled callback timestamp. + (Contributed by Andrew Svetlov in :issue:`32741`.) + +* The :meth:`loop.create_datagram_endpoint() \ + <asyncio.AbstractEventLoop.create_datagram_endpoint>` method + gained support for Unix sockets. + (Contributed by Quentin Dawans in :issue:`31245`.) + +* The :meth:`loop.create_connection() <asyncio.AbstractEventLoop.create_connection>`, + :meth:`loop.create_server() <asyncio.AbstractEventLoop.create_server>`, + :meth:`loop.create_unix_server() <asyncio.AbstractEventLoop.create_unix_server>`, and + :meth:`loop.create_accepted_socket() <asyncio.BaseEventLoop.connect_accepted_socket>` + now accept the *ssl_handshake_timeout* keyword argument. + (Contributed by Neil Aspinall in :issue:`29970`.) + +* The new :meth:`Handle.cancelled() <asyncio.Handle.cancelled>` method returns + ``True`` if the callback was cancelled. + (Contributed by Marat Sharafutdinov in :issue:`31943`.) + +* The asyncio source has been converted to use the + :keyword:`async`/:keyword:`await` syntax. + (Contributed by Andrew Svetlov in :issue:`32193`.) + +* The new :meth:`ReadTransport.is_reading() <asyncio.ReadTransport.is_reading>` + method can be used to determine the reading state of the transport. + Additionally, calls to + :meth:`ReadTransport.resume_reading() <asyncio.ReadTransport.resume_reading>` + and :meth:`ReadTransport.pause_reading() <asyncio.ReadTransport.pause_reading>` + are now idempotent. + (Contributed by Yury Selivanov in :issue:`32356`.) + +* Loop methods which accept socket paths now support passing + :term:`path-like objects <path-like object>`. + (Contributed by Yury Selivanov in :issue:`32066`.) + +* In :mod:`asyncio` TCP sockets on Linux are now created with ``TCP_NODELAY`` + flag set by default. + (Contributed by Yury Selivanov and Victor Stinner in :issue:`27456`.) + +* Exceptions occurring in cancelled tasks are no longer logged. + (Contributed by Yury Selivanov in :issue:`30508`.) + +Several ``asyncio`` APIs have been +:ref:`deprecated <whatsnew37-asyncio-deprecated>`. + binascii -------- @@ -483,54 +732,116 @@ The :func:`~binascii.b2a_uu` function now accepts an optional *backtick* keyword argument. When it's true, zeros are represented by ``'`'`` instead of spaces. (Contributed by Xiang Zhang in :issue:`30103`.) + calendar -------- -The class :class:`~calendar.HTMLCalendar` has new class attributes which ease -the customisation of the CSS classes in the produced HTML calendar. +The :class:`~calendar.HTMLCalendar` class has new class attributes which ease +the customization of CSS classes in the produced HTML calendar. (Contributed by Oz Tiram in :issue:`30095`.) + +collections +----------- + +``collections.namedtuple()`` now supports default values. +(Contributed by Raymond Hettinger in :issue:`32320`.) + + +compileall +---------- + +:func:`compileall.compile_dir` learned the new *invalidation_mode* parameter, +which can be used to enable +:ref:`hash-based .pyc invalidation <whatsnew37-pep552>`. The invalidation +mode can also be specified on the command line using the new +``--invalidation-mode`` argument. +(Contributed by Benjamin Peterson in :issue:`31650`.) + + +concurrent.futures +------------------ + +:class:`ProcessPoolExecutor <concurrent.futures.ProcessPoolExecutor>` and +:class:`ThreadPoolExecutor <concurrent.futures.ThreadPoolExecutor>` now +support the new *initializer* and *initargs* constructor arguments. +(Contributed by Antoine Pitrou in :issue:`21423`.) + +The :class:`ProcessPoolExecutor <concurrent.futures.ProcessPoolExecutor>` +can now take the multiprocessing context via the new *mp_context* argument. +(Contributed by Thomas Moreau in :issue:`31540`.) + + contextlib ---------- -:func:`~contextlib.asynccontextmanager` and -:class:`~contextlib.AbstractAsyncContextManager` have been added. (Contributed -by Jelle Zijlstra in :issue:`29679` and :issue:`30241`.) +The new :func:`~contextlib.nullcontext` is a simpler and faster no-op +context manager than :class:`~contextlib.ExitStack`. +(Contributed by Jesse-Bakker in :issue:`10049`.) + +The new :func:`~contextlib.asynccontextmanager`, +:class:`~contextlib.AbstractAsyncContextManager`, and +:class:`~contextlib.AsyncExitStack` have been added to +complement their synchronous counterparts. (Contributed +by Jelle Zijlstra in :issue:`29679` and :issue:`30241`, +and by Alexander Mohr and Ilya Kulakov in :issue:`29302`.) -:class:`contextlib.AsyncExitStack` has been added. (Contributed by -Alexander Mohr and Ilya Kulakov in :issue:`29302`.) cProfile -------- -:mod:`cProfile` command line now accepts ``-m module_name`` as an alternative -to script path. (Contributed by Sanyam Khurana in :issue:`21862`.) +The :mod:`cProfile` command line now accepts ``-m module_name`` as an +alternative to script path. (Contributed by Sanyam Khurana in :issue:`21862`.) + crypt ----- -Added support for the Blowfish method. +The :mod:`crypt` module now supports the Blowfish hashing method. (Contributed by Serhiy Storchaka in :issue:`31664`.) -The :func:`~crypt.mksalt` function now allows to specify the number of rounds +The :func:`~crypt.mksalt` function now allows specifying the number of rounds for hashing. (Contributed by Serhiy Storchaka in :issue:`31702`.) + datetime -------- -Added the :meth:`datetime.fromisoformat <datetime.datetime.fromisoformat>` -method, which constructs a :class:`~datetime.datetime` object from a string +The new :meth:`datetime.fromisoformat() <datetime.datetime.fromisoformat>` +method constructs a :class:`~datetime.datetime` object from a string in one of the formats output by -:meth:`datetime.isoformat <datetime.datetime.isoformat>`. +:meth:`datetime.isoformat() <datetime.datetime.isoformat>`. (Contributed by Paul Ganssle in :issue:`15873`.) +The :class:`tzinfo <datetime.tzinfo>` class now supports sub-minute offsets. +(Contributed by Alexander Belopolsky in :issue:`5288`.) + + +dbm +--- + +:mod:`dbm.dumb` now supports reading read-only files and no longer writes the +index file when it is not changed. + + +decimal +------- + +The :mod:`decimal` module now uses :ref:`context variables <whatsnew37-pep567>` +to store the decimal context. +(Contributed by Yury Selivanov in :issue:`32630`.) + + dis --- -The :func:`~dis.dis` function now is able to +The :func:`~dis.dis` function is now able to disassemble nested code objects (the code of comprehensions, generator expressions and nested functions, and the code used for building nested -classes). (Contributed by Serhiy Storchaka in :issue:`11822`.) +classes). The maximum depth of disassembly recursion is controlled by +the new *depth* parameter. +(Contributed by Serhiy Storchaka in :issue:`11822`.) + distutils --------- @@ -539,97 +850,244 @@ distutils therefore included in source distributions. (Contributed by Ryan Gonzalez in :issue:`11913`.) -:class:`distutils.core.setup` now warns if the ``classifiers``, ``keywords`` -and ``platforms`` fields are not specified as a list or a string. -(Contributed by Berker Peksag in :issue:`19610`.) -The ``upload`` command no longer tries to change CR end-of-line characters -to CRLF. This fixes a corruption issue with sdists that ended with a byte -equivalent to CR. -(Contributed by Bo Bayles in :issue:`32304`.) +enum +---- + +The :class:`Enum <enum.Enum>` learned the new ``_ignore_`` class property, +which allows listing the names of properties which should not become +enum members. +(Contributed by Ethan Furman in :issue:`31801`.) + +In Python 3.8, attempting to check for non-Enum objects in :class:`Enum` +classes will raise a :exc:`TypeError` (e.g. ``1 in Color``); similarly, +attempting to check for non-Flag objects in a :class:`Flag` member will +raise :exc:`TypeError` (e.g. ``1 in Perm.RW``); currently, both operations +return :const:`False` instead and are deprecated. +(Contributed by Ethan Furman in :issue:`33217`.) + + +functools +--------- + +:func:`functools.singledispatch` now supports registering implementations +using type annotations. +(Contributed by ?ukasz Langa in :issue:`32227`.) + + +gc +-- + +The new :func:`gc.freeze` function allows freezing all objects tracked +by the garbage collector and excluding them from future collections. +This can be used before a POSIX ``fork()`` call to make the GC copy-on-write +friendly or to speed up collection. The new :func:`gc.unfreeze` functions +reverses this operation. Additionally, :func:`gc.get_freeze_count` can +be used to obtain the number of frozen objects. +(Contributed by Li Zekun in :issue:`31558`.) + + +hmac +---- + +The :mod:`hmac` module now has an optimized one-shot :func:`~hmac.digest` +function, which is up to three times faster than :func:`~hmac.HMAC`. +(Contributed by Christian Heimes in :issue:`32433`.) + http.client ----------- -Add configurable *blocksize* to :class:`~http.client.HTTPConnection` and -:class:`~http.client.HTTPSConnection` for improved upload throughput. -(Contributed by Nir Soffer in :issue:`31945`.) +:class:`~http.client.HTTPConnection` and :class:`~http.client.HTTPSConnection` +now support the new *blocksize* argument for improved upload throughput. +(Contributed by Nir Soffer in :issue:`31945`.) + + +http.server +----------- + +:class:`~http.server.SimpleHTTPRequestHandler` now supports the HTTP +``If-Modified-Since`` header. The server returns the 304 response status if +the target file was not modified after the time specified in the header. +(Contributed by Pierre Quentel in :issue:`29654`.) + +:class:`~http.server.SimpleHTTPRequestHandler` accepts the new *directory* +argument, in addition to the new ``--directory`` command line argument. +With this parameter, the server serves the specified directory, by default it +uses the current working directory. +(Contributed by St?phane Wirtel and Julien Palard in :issue:`28707`.) + +The new :class:`ThreadedHTTPServer <http.server.ThreadedHTTPServer>` class +uses threads to handle requests using :class:`~socketserver.ThreadingMixin`. +It is used when ``http.server`` is run with ``-m``. +(Contributed by Julien Palard in :issue:`31639`.) + + +importlib +--------- + +The :class:`importlib.abc.ResourceReader` ABC was introduced to +support the loading of resources from packages. See also +:ref:`whatsnew37_importlib_resources`. +(Contributed by Barry Warsaw, Brett Cannon in :issue:`32248`.) + +:func:`importlib.reload` now raises :exc:`ModuleNotFoundError` if the module +lacks a spec. +(Contributed by Garvit Khatri in :issue:`29851`.) + +:func:`importlib.find_spec` now raises ``ModuleNotFoundError`` instead of +:exc:`AttributeError` if the specified parent module is not a package (i.e. +lacks a ``__path__`` attribute). +(Contributed by Milan Oberkirch in :issue:`30436`.) + +The new :func:`importlib.source_hash` can be used to compute the hash of +the passed source. A :ref:`hash-based .pyc file <whatsnew37-pep552>` +embeds the value returned by this function. + + +io +-- + +The new :meth:`TextIOWrapper.reconfigure() <io.TextIOWrapper.reconfigure>` +method can be used to reconfigure the text stream with the new settings. +(Contributed by Antoine Pitrou in :issue:`30526` and +INADA Naoki in :issue:`15216`.) + + +ipaddress +--------- + +The new ``subnet_of()`` and ``supernet_of()`` methods of +:class:`ipaddress.IPv6Network` and :class:`ipaddress.IPv4Network` can +be used for network containment tests. +(Contributed by Michel Albert and Cheryl Sabella in :issue:`20825`.) + + +itertools +--------- + +:func:`itertools.islice` now accepts +:meth:`integer-like objects <object.__index__>` as start, stop, +and slice arguments. +(Contributed by Will Roberts in :issue:`30537`.) + + +locale +------ + +The new *monetary* argument to :func:`locale.format_string` can be used +to make the conversion use monetary thousands separators and +grouping strings. (Contributed by Garvit in :issue:`10379`.) + +The :func:`locale.getpreferredencoding` function now always returns ``'UTF-8'`` +on Android or when in the :ref:`forced UTF-8 mode <whatsnew37-pep540>`. + + +logging +------- -http.server ------------ +:class:`~logging.Logger` instances can now be pickled. +(Contributed by Vinay Sajip in :issue:`30520`.) -:class:`~http.server.SimpleHTTPRequestHandler` supports the HTTP -``If-Modified-Since`` header. The server returns the 304 response status if the -target file was not modified after the time specified in the header. -(Contributed by Pierre Quentel in :issue:`29654`.) +The new :meth:`StreamHandler.setStream() <logging.StreamHandler.setStream>` +method can be used to replace the logger stream after handler creation. +(Contributed by Vinay Sajip in :issue:`30522`.) -Add the parameter *directory* to the :class:`~http.server.SimpleHTTPRequestHandler` -and the ``--directory`` to the command line of the module :mod:`http.server`. -With this parameter, the server serves the specified directory, by default it -uses the current working directory. -(Contributed by St?phane Wirtel and Julien Palard in :issue:`28707`.) +It is now possible to specify keyword arguments to handler constructors in +configuration passed to :func:`logging.config.fileConfig`. +(Contributed by Preston Landers in :issue:`31080`.) -hmac + +math ---- -The :mod:`hmac` module now has an optimized one-shot :func:`~hmac.digest` -function, which is up to three times faster than :func:`~hmac.HMAC`. -(Contributed by Christian Heimes in :issue:`32433`.) +The new :func:`math.remainder` function implements the IEEE 754-style remainder +operation. (Contributed by Mark Dickinson in :issue:`29962`.) -importlib + +mimetypes --------- -The :class:`importlib.abc.ResourceReader` ABC was introduced to -support the loading of resource from packages. +The MIME type of .bmp has been changed from ``'image/x-ms-bmp'`` to +``'image/bmp'``. +(Contributed by Nitish Chandra in :issue:`22589`.) -locale + +msilib ------ -Added another argument *monetary* in :func:`~locale.format_string` of :mod:`locale`. -If *monetary* is true, the conversion uses monetary thousands separator and -grouping strings. (Contributed by Garvit in :issue:`10379`.) +The new :meth:`Database.Close() <msilib.Database.Close>` method can be used +to close the :abbr:`MSI` database. +(Contributed by Berker Peksag in :issue:`20486`.) -The :func:`~locale.getpreferredencoding` function now always returns ``'UTF-8'`` -on Android or in the UTF-8 mode (:option:`-X` ``utf8`` option), the locale and -the *do_setlocale* argument are ignored. -math ----- +multiprocessing +--------------- + +The new :meth:`Process.close() <multiprocessing.Process.close>` method +explicitly closes the process object and releases all resources associated +with it. :exc:`ValueError` is raised if the underlying process is still +running. +(Contributed by Antoine Pitrou in :issue:`30596`.) + +The new :meth:`Process.kill() <multiprocessing.Process.kill>` method can +be used to terminate the process using the :data:`SIGKILL` signal on Unix. +(Contributed by Vitor Pereira in :issue:`30794`.) + +Non-daemonic threads created by :class:`~multiprocessing.Process` are now +joined on process exit. +(Contributed by Antoine Pitrou in :issue:`18966`.) -New :func:`~math.remainder` function, implementing the IEEE 754-style remainder -operation. (Contributed by Mark Dickinson in :issue:`29962`.) os -- -Added support for :class:`bytes` paths in :func:`~os.fwalk`. (Contributed by -Serhiy Storchaka in :issue:`28682`.) +:func:`os.fwalk` now accepts the *path* argument as :class:`bytes`. +(Contributed by Serhiy Storchaka in :issue:`28682`.) -Added support for :ref:`file descriptors <path_fd>` in :func:`~os.scandir` -on Unix. (Contributed by Serhiy Storchaka in :issue:`25996`.) +:func:`os.scandir` gained support for :ref:`file descriptors <path_fd>`. +(Contributed by Serhiy Storchaka in :issue:`25996`.) -New function :func:`~os.register_at_fork` allows registering Python callbacks -to be executed on a process fork. (Contributed by Antoine Pitrou in -:issue:`16500`.) +The new :func:`~os.register_at_fork` function allows registering Python +callbacks to be executed at process fork. +(Contributed by Antoine Pitrou in :issue:`16500`.) + +Exposed the *preadv*, *preadv2*, *pwritev* and *pwritev2* system calls through +the new :func:`~os.preadv` and :func:`~os.pwritev` functions. +(Contributed by Pablo Galindo in :issue:`31368`.) + +The mode argument of :func:`os.makedirs` no longer affects the file +permission bits of newly-created intermediate-level directories. +(Contributed by Serhiy Storchaka in :issue:`19930`.) + +:func:`os.dup2` now returns the new file descriptor. Previously, ``None`` +was always returned. +(Contributed by Benjamin Peterson in :issue:`32441`.) + +The structure returned by :func:`os.stat` now contains the +:attr:`~os.stat_result.st_fstype` attribute on Solaris and its derivatives. +(Contributed by Jes?s Cea Avi?n in :issue:`32659`.) + + +pathlib +------- -Exposed the system calls *preadv*, *preadv2*, *pwritev* and *pwritev2* through -the new functions :func:`~os.preadv` and :func:`~os.pwritev`. (Contributed by -Pablo Galindo in :issue:`31368`.) +The new :meth:`Path.is_mount() <pathlib.Path.is_mount>` method is now available +on POSIX systems and can be used to determine whether a path is a mount point. +(Contributed by Cooper Ry Lees in :issue:`30897`.) -Exposed the system call *posix_spawn* through the new function -:func:`~os.posix_spawn`. (Contributed by Pablo Galindo, Serhiy Storchaka and -Gregory P. Smith in :issue:`20104`.) pdb --- -:func:`~pdb.set_trace` now takes an optional *header* keyword-only -argument. If given, this is printed to the console just before debugging +:func:`pdb.set_trace` now takes an optional *header* keyword-only +argument. If given, it is printed to the console just before debugging begins. (Contributed by Barry Warsaw in :issue:`31389`.) :mod:`pdb` command line now accepts ``-m module_name`` as an alternative to script file. (Contributed by Mario Corchero in :issue:`32206`.) + py_compile ---------- @@ -641,6 +1099,22 @@ This allows for guaranteeing files when they are created eagerly. (Contributed by Bernhard M. Wiedemann in :issue:`29708`.) + +pydoc +----- + +The pydoc server can now bind to an arbitrary hostname specified by the +new ``-n`` command-line argument. +(Contributed by Feanil Patel in :issue:`31128`.) + + +queue +----- + +The new :class:`~queue.SimpleQueue` class is an unbounded :abbr:`FIFO` queue. +(Contributed by Antoine Pitrou in :issue:`14976`.) + + re -- @@ -652,70 +1126,128 @@ can be set within the scope of a group. ``'^$'`` or ``(?=-)`` that matches an empty string. (Contributed by Serhiy Storchaka in :issue:`25054`.) +Regular expressions compiled with the :const:`re.LOCALE` flag no longer +depend on the locale at compile time. Locale settings are applied only +when the compiled regular expression is used. +(Contributed by Serhiy Storchaka in :issue:`30215`.) + +:exc:`FutureWarning` is now emitted if a regular expression contains +character set constructs that will change semantically in the future, +such as nested sets and set operations. +(Contributed by Serhiy Storchaka in :issue:`30349`.) + +Compiled regular expression and match objects can now be copied +using :func:`copy.copy` and :func:`copy.deepcopy`. +(Contributed by Serhiy Storchaka in :issue:`10076`.) + + +signal +------ + +The new *warn_on_full_buffer* argument to the :func:`signal.set_wakeup_fd` +function makes it possible to specify whether Python prints a warning on +stderr when the wakeup buffer overflows. +(Contributed by Nathaniel J. Smith in :issue:`30050`.) + + +socket +------ + +The new :func:`socket.getblocking() <socket.socket.getblocking>` method +returns ``True`` if the socket is in blocking mode and ``False`` otherwise. +(Contributed by Yury Selivanov in :issue:`32373`.) + +The new :func:`socket.close` function closes the passed socket file descriptor. +This function should be used instead of :func:`os.close` for better +compatibility across platforms. +(Contributed by Christian Heimes in :issue:`32454`.) + +The :mod:`socket` module now exposes the :data:`socket.TCP_CONGESTION` +(Linux 2.6.13), :data:`socket.TCP_USER_TIMEOUT` (Linux 2.6.37), and +:data:`socket.TCP_NOTSENT_LOWAT` (Linux 3.12) constants. +(Contributed by Omar Sandoval in :issue:`26273` and +Nathaniel J. Smith in :issue:`29728`.) + +Support for :data:`socket.AF_VSOCK` sockets has been added to allow +communication between virtual machines and their hosts. +(Contributed by Cathy Avery in :issue:`27584`.) + +Sockets now auto-detect family, type and protocol from file descriptor +by default. +(Contributed by Christian Heimes in :issue:`28134`.) + sqlite3 ------- -:class:`sqlite3.Connection` now exposes a :class:`~sqlite3.Connection.backup` -method, if the underlying SQLite library is at version 3.6.11 or higher. +:class:`sqlite3.Connection` now exposes the :meth:`~sqlite3.Connection.backup` +method when the underlying SQLite library is at version 3.6.11 or higher. (Contributed by Lele Gaifax in :issue:`27645`.) +The *database* argument of :func:`sqlite3.connect` now accepts any +:term:`path-like object`, instead of just a string. +(Contributed by Anders Lorentsen in :issue:`31843`.) + ssl --- The :mod:`ssl` module now uses OpenSSL's builtin API instead of -:func:`~ssl.match_hostname` to check host name or IP address. Values -are validated during TLS handshake. Any cert validation error including -a failing host name match now raises :exc:`~ssl.SSLCertVerificationError` and -aborts the handshake with a proper TLS Alert message. The new exception -contains additional information. Host name validation can be customized -with :attr:`~ssl.SSLContext.host_flags`. +:func:`~ssl.match_hostname` to check a host name or an IP address. Values +are validated during TLS handshake. Any certificate validation error +including failing the host name check now raises +:exc:`~ssl.SSLCertVerificationError` and aborts the handshake with a proper +TLS Alert message. The new exception contains additional information. +Host name validation can be customized with +:attr:`SSLContext.host_flags <ssl.SSLContext.host_flags>`. (Contributed by Christian Heimes in :issue:`31399`.) .. note:: - The improved host name check requires an OpenSSL 1.0.2 or 1.1 compatible - libssl. OpenSSL 0.9.8 and 1.0.1 are no longer supported. LibreSSL is - temporarily not supported until it gains the necessary OpenSSL 1.0.2 APIs. + The improved host name check requires a *libssl* implementation compatible + with OpenSSL 1.0.2 or 1.1. Consequently, OpenSSL 0.9.8 and 1.0.1 are no + longer supported and LibreSSL is temporarily not supported until it gains + the necessary OpenSSL 1.0.2 APIs. -The ssl module no longer sends IP addresses in SNI TLS extension. +The ``ssl`` module no longer sends IP addresses in SNI TLS extension. (Contributed by Christian Heimes in :issue:`32185`.) :func:`~ssl.match_hostname` no longer supports partial wildcards like -``www*.example.org``. :attr:`~ssl.SSLContext.host_flags` has partial -wildcard matching disabled by default. +``www*.example.org``. :attr:`SSLContext.host_flags <ssl.SSLContext.host_flags>` +has partial wildcard matching disabled by default. (Contributed by Mandeep Singh in :issue:`23033` and Christian Heimes in :issue:`31399`.) -The default cipher suite selection of the ssl module now uses a blacklist -approach rather than a hard-coded whitelist. Python no longer re-enables -ciphers that have been blocked by OpenSSL security update. Default cipher -suite selection can be configured on compile time. +The default cipher suite selection of the ``ssl`` module now uses a blacklist +approach rather than a hard-coded whitelist. Python no longer re-enables +ciphers that have been blocked by OpenSSL security updates. Default cipher +suite selection can be configured at compile time. (Contributed by Christian Heimes in :issue:`31429`.) -Added support for validating server certificates containing -internationalized domain names (IDNs). As part of this change, the -:attr:`ssl.SSLSocket.server_hostname` attribute now stores the -expected hostname in A-label form (``"xn--pythn-mua.org"``), rather -than the U-label form (``"pyth?n.org"``). (Contributed by +Validation of server certificates containing internationalized domain names +(IDNs) is now supported. As part of this change, the +:attr:`SSLSocket.server_hostname <ssl.SSLSocket.server_hostname>` attribute +now stores the expected hostname in A-label form (``"xn--pythn-mua.org"``), +rather than the U-label form (``"pyth?n.org"``). (Contributed by Nathaniel J. Smith and Christian Heimes in :issue:`28414`.) -The ssl module has preliminary and experimental support for TLS 1.3 and -OpenSSL 1.1.1. (Contributed by Christian Heimes in :issue:`32947`, +The ``ssl`` module has preliminary and experimental support for TLS 1.3 and +OpenSSL 1.1.1. (Contributed by Christian Heimes in :issue:`32947`, :issue:`20995`, :issue:`29136`, and :issue:`30622`) :class:`~ssl.SSLSocket` and :class:`~ssl.SSLObject` no longer have a public -constructor. Direct instantiation was never a documented and supported -feature. Instances must be created with :class:`~ssl.SSLContext` methods +constructor. Direct instantiation was never a documented and supported +feature. Instances must be created with :class:`~ssl.SSLContext` methods :meth:`~ssl.SSLContext.wrap_socket` and :meth:`~ssl.SSLContext.wrap_bio`. (Contributed by Christian Heimes in :issue:`32951`) OpenSSL 1.1 APIs for setting the minimum and maximum TLS protocol version are -available as :attr:`~ssl.SSLContext.minimum_version` and -:attr:`~ssl.SSLContext.maximum_version`. Supported protocols are indicated -by new flags like :data:`~ssl.HAS_TLSv1_1`. +available as :attr:`SSLContext.minimum_version <ssl.SSLContext.minimum_version>` +and :attr:`SSLContext.maximum_version <ssl.SSLContext.maximum_version>`. +Supported protocols are indicated by serveral new flags, such as +:data:`~ssl.HAS_TLSv1_1`. (Contributed by Christian Heimes in :issue:`32609`.) + string ------ @@ -723,32 +1255,61 @@ string expression pattern for braced placeholders and non-braced placeholders separately. (Contributed by Barry Warsaw in :issue:`1198569`.) + subprocess ---------- +The :func:`subprocess.run` function accepts the new *capture_output* +keyword argument. When true, stdout and stderr will be captured. +This is equivalent to passing :data:`subprocess.PIPE` as *stdout* and +*stderr* arguments. +(Contributed by Bo Bayles in :issue:`32102`.) + +The ``subprocess.run`` function and the :class:`subprocess.Popen` constructor +now accept the *text* keyword argument as an alias +to *universal_newlines*. +(Contributed by Andrew Clegg in :issue:`31756`.) + On Windows the default for *close_fds* was changed from ``False`` to ``True`` when redirecting the standard handles. It's now possible to set -*close_fds* to ``True`` when redirecting the standard handles. See -:class:`subprocess.Popen`. +*close_fds* to true when redirecting the standard handles. See +:class:`subprocess.Popen`. This means that *close_fds* now defaults to +``True`` on all supported platforms. +(Contributed by Segev Finer in :issue:`19764`.) + +The subprocess module is now more graceful when handling +:exc:`KeyboardInterrupt` during :func:`subprocess.call`, +:func:`subprocess.run`, or in a :class:`~subprocess.Popen` +context manager. It now waits a short amount of time for the child +to exit, before continuing the handling of the ``KeyboardInterrupt`` +exception. +(Contributed by Gregory P. Smith in :issue:`25942`.) -This means that *close_fds* now defaults to ``True`` on all supported -platforms. (Contributed by Segev Finer in :issue:`19764`.) sys --- -Added :attr:`sys.flags.dev_mode` flag for the new development mode. +The new :func:`sys.breakpointhook` hook function is called by the +built-in :func:`breakpoint`. +(Contributed by Barry Warsaw in :issue:`31353`.) -tkinter -------- +On Android, the new :func:`sys.getandroidapilevel` returns the build-time +Android API version. +(Contributed by Victor Stinner in :issue:`28740`.) + +The new :func:`sys.get_coroutine_origin_tracking_depth` function returns +the current coroutine origin tracking depth, as set by +the new :func:`sys.set_coroutine_origin_tracking_depth`. :mod:`asyncio` +has been converted to use this new API instead of +the deprecated :func:`sys.set_coroutine_wrapper`. +(Contributed by Nathaniel J. Smith in :issue:`32591`.) -Added :class:`tkinter.ttk.Spinbox`. -(Contributed by Alan Moore in :issue:`32585`.) time ---- -The :pep:`564` added six new functions with nanosecond resolution: +:pep:`564` adds six new functions with nanosecond resolution to the +:mod:`time` module: * :func:`time.clock_gettime_ns` * :func:`time.clock_settime_ns` @@ -757,21 +1318,58 @@ The :pep:`564` added six new functions with nanosecond resolution: * :func:`time.process_time_ns` * :func:`time.time_ns` -Add new clock identifiers: +New clock identifiers have been added: * :data:`time.CLOCK_BOOTTIME` (Linux): Identical to :data:`time.CLOCK_MONOTONIC`, except it also includes any time that the system is suspended. * :data:`time.CLOCK_PROF` (FreeBSD, NetBSD and OpenBSD): High-resolution - per-process timer from the CPU. + per-process CPU timer. * :data:`time.CLOCK_UPTIME` (FreeBSD, OpenBSD): Time whose absolute value is the time the system has been running and not suspended, providing accurate - uptime measurement, both absolute and interval. + uptime measurement. -Added functions :func:`time.thread_time` and :func:`time.thread_time_ns` -to get per-thread CPU time measurements. +The new :func:`time.thread_time` and :func:`time.thread_time_ns` functions +can be used to get per-thread CPU time measurements. (Contributed by Antoine Pitrou in :issue:`32025`.) +The new :func:`time.pthread_getcpuclockid` function returns the clock ID +of the thread-specific CPU-time clock. + + +tkinter +------- + +The new :class:`tkinter.ttk.Spinbox` class is now available. +(Contributed by Alan Moore in :issue:`32585`.) + + +tracemalloc +----------- + +:class:`tracemalloc.Traceback` behaves more like regular tracebacks, +sorting the frames from oldest to most recent. +:meth:`Traceback.format() <tracemalloc.Traceback.format>` +now accepts negative *limit*, truncating the result to the +``abs(limit)`` oldest frames. To get the old behaviour, use +the new *most_recent_first* argument to ``Traceback.format()``. +(Contributed by Jesse Bakker in :issue:`32121`.) + + +types +----- + +The new :class:`~types.WrapperDescriptorType`, +:class:`~types.MethodWrapperType`, :class:`~types.MethodDescriptorType`, +and :class:`~types.ClassMethodDescriptorType` classes are now available. +(Contributed by Manuel Krebber and Guido van Rossum in :issue:`29377`, +and Serhiy Storchaka in :issue:`32265`.) + +The new :func:`types.resolve_bases` function resolves MRO entries +dynamically as specified by :pep:`560`. +(Contributed by Ivan Levkivskyi in :issue:`32717`.) + + unicodedata ----------- @@ -779,15 +1377,18 @@ The internal :mod:`unicodedata` database has been upgraded to use `Unicode 10 <http://www.unicode.org/versions/Unicode10.0.0/>`_. (Contributed by Benjamin Peterson.) + unittest -------- -Added new command-line option ``-k`` to filter tests to run with a substring or -Unix shell-like pattern. For example, ``python -m unittest -k foo`` runs the -tests ``foo_tests.SomeTest.test_something``, ``bar_tests.SomeTest.test_foo``, +The new ``-k`` command-line option allows filtering tests by a name +substring or a Unix shell-like pattern. +For example, ``python -m unittest -k foo`` runs +``foo_tests.SomeTest.test_something``, ``bar_tests.SomeTest.test_foo``, but not ``bar_tests.FooTest.test_something``. (Contributed by Jonas Haag in :issue:`32071`.) + unittest.mock ------------- @@ -795,47 +1396,75 @@ The :const:`~unittest.mock.sentinel` attributes now preserve their identity when they are :mod:`copied <copy>` or :mod:`pickled <pickle>`. (Contributed by Serhiy Storchaka in :issue:`20804`.) -New function :func:`~unittest.mock.seal` will disable the creation of mock -children by preventing to get or set any new attribute on the sealed mock. -The sealing process is performed recursively. (Contributed by Mario Corchero -in :issue:`30541`.) +The new :func:`~unittest.mock.seal` function allows sealing +:class:`~unittest.mock.Mock` instances, which will disallow further creation +of attribute mocks. The seal is applied recursively to all attributes that +are themselves mocks. +(Contributed by Mario Corchero in :issue:`30541`.) + urllib.parse ------------ :func:`urllib.parse.quote` has been updated from :rfc:`2396` to :rfc:`3986`, -adding ``~`` to the set of characters that is never quoted by default. +adding ``~`` to the set of characters that are never quoted by default. (Contributed by Christian Theune and Ratnadeep Debnath in :issue:`16285`.) + uu -- -Function :func:`~uu.encode` now accepts an optional *backtick* +The :func:`uu.encode` function now accepts an optional *backtick* keyword argument. When it's true, zeros are represented by ``'`'`` instead of spaces. (Contributed by Xiang Zhang in :issue:`30103`.) + +uuid +---- + +The new :attr:`UUID.is_safe <uuid.UUID.is_safe>` attribute relays information +from the platform about whether generated UUIDs are generated with a +multiprocessing-safe method. +(Contributed by Barry Warsaw in :issue:`22807`.) + +:func:`uuid.getnode` now prefers universally administered +MAC addresses over locally administered MAC addresses. +This makes a better guarantee for global uniqueness of UUIDs returned +from :func:`uuid.uuid1`. If only locally administered MAC addresses are +available, the first such one found is returned. +(Contributed by Barry Warsaw in :issue:`32107`.) + + warnings -------- The initialization of the default warnings filters has changed as follows: * warnings enabled via command line options (including those for :option:`-b` - and the new CPython-specific ``-X dev`` option) are always passed to the - warnings machinery via the ``sys.warnoptions`` attribute. + and the new CPython-specific :option:`-X` ``dev`` option) are always passed + to the warnings machinery via the :data:`sys.warnoptions` attribute. + * warnings filters enabled via the command line or the environment now have the - following precedence order: + following order of precedence: * the ``BytesWarning`` filter for :option:`-b` (or ``-bb``) - * any filters specified with :option:`-W` - * any filters specified with :envvar:`PYTHONWARNINGS` + * any filters specified with the :option:`-W` option + * any filters specified with the :envvar:`PYTHONWARNINGS` environment + variable * any other CPython specific filters (e.g. the ``default`` filter added for the new ``-X dev`` mode) * any implicit filters defined directly by the warnings machinery + * in CPython debug builds, all warnings are now displayed by default (the implicit filter list is empty) (Contributed by Nick Coghlan and Victor Stinner in :issue:`20361`, -:issue:`32043`, and :issue:`32230`) +:issue:`32043`, and :issue:`32230`.) + +Deprecation warnings are once again shown by default in single-file scripts and +at the interactive prompt. See :ref:`whatsnew37-pep565` for details. +(Contributed by Nick Coghlan in :issue:`31975`.) + xml.etree --------- @@ -845,13 +1474,15 @@ methods can now compare text of the current node with ``[. = "text"]``, not only text in children. Predicates also allow adding spaces for better readability. (Contributed by Stefan Behnel in :issue:`31648`.) + xmlrpc.server ------------- -:meth:`register_function` of :class:`~xmlrpc.server.SimpleXMLRPCDispatcher` and -its subclasses can be used as a decorator. (Contributed by Xiang Zhang in +:meth:`SimpleXMLRPCDispatcher.register_function <xmlrpc.server.SimpleXMLRPCDispatcher>` +can now be used as a decorator. (Contributed by Xiang Zhang in :issue:`7769`.) + zipapp ------ @@ -865,144 +1496,267 @@ argument to generate a compressed archive. A command line option (Contributed by Zhiming Wang in :issue:`31638`.) +zipfile +------- + +:class:`~zipfile.ZipFile` now accepts the new *compresslevel* parameter to +control the compression level. +(Contributed by Bo Bayles in :issue:`21417`.) + +Subdirectories in archives created by ``ZipFile`` are now stored in +alphabetical order. +(Contributed by Bernhard M. Wiedemann in :issue:`30693`.) + + +C API Changes +============= + +A new API for thread-local storage has been implemented. See +:ref:`whatsnew37-pep539` for an overview and +:ref:`thread-specific-storage-api` for a complete reference. +(Contributed by Masayuki Yamamoto in :issue:`25658`.) + +The new :c:func:`PyImport_GetModule` function returns the previously +imported module with the given name. +(Contributed by Eric Snow in :issue:`28411`.) + +The new :c:macro:`Py_RETURN_RICHCOMPARE` macro eases writing rich +comparison functions. +(Contributed by Petr Victorin in :issue:`23699`.) + +The new :c:macro:`Py_UNREACHABLE` macro can be used to mark unreachable +code paths. +(Contributed by Barry Warsaw in :issue:`31338`.) + +The :mod:`tracemalloc` now exposes a C API through the new +:c:func:`PyTraceMalloc_Track` and :c:func:`PyTraceMalloc_Untrack` +functions. +(Contributed by Victor Stinner in :issue:`30054`.) + +The new :c:func:`import__find__load__start` and +:c:func:`import__find__load__done` static markers can be used to trace +module imports. +(Contributed by Christian Heimes in :issue:`31574`.) + +The fields :c:member:`name` and :c:member:`doc` of structures +:c:type:`PyMemberDef`, :c:type:`PyGetSetDef`, +:c:type:`PyStructSequence_Field`, :c:type:`PyStructSequence_Desc`, +and :c:type:`wrapperbase` are now of type ``const char *`` rather of +``char *``. (Contributed by Serhiy Storchaka in :issue:`28761`.) + +The result of :c:func:`PyUnicode_AsUTF8AndSize` and :c:func:`PyUnicode_AsUTF8` +is now of type ``const char *`` rather of ``char *``. (Contributed by Serhiy +Storchaka in :issue:`28769`.) + +The result of :c:func:`PyMapping_Keys`, :c:func:`PyMapping_Values` and +:c:func:`PyMapping_Items` is now always a list, rather than a list or a +tuple. (Contributed by Oren Milman in :issue:`28280`.) + +Added functions :c:func:`PySlice_Unpack` and :c:func:`PySlice_AdjustIndices`. +(Contributed by Serhiy Storchaka in :issue:`27867`.) + +:c:func:`PyOS_AfterFork` is deprecated in favour of the new functions +:c:func:`PyOS_BeforeFork`, :c:func:`PyOS_AfterFork_Parent` and +:c:func:`PyOS_AfterFork_Child`. (Contributed by Antoine Pitrou in +:issue:`16500`.) + +The ``PyExc_RecursionErrorInst`` singleton that was part of the public API +has been removed as its members being never cleared may cause a segfault +during finalization of the interpreter. Contributed by Xavier de Gaye in +:issue:`22898` and :issue:`30697`. + +Added C API support for timezones with timezone constructors +:c:func:`PyTimeZone_FromOffset` and :c:func:`PyTimeZone_FromOffsetAndName`, +and access to the UTC singleton with :c:data:`PyDateTime_TimeZone_UTC`. +Contributed by Paul Ganssle in :issue:`10381`. + +The type of results of :c:func:`PyThread_start_new_thread` and +:c:func:`PyThread_get_thread_ident`, and the *id* parameter of +:c:func:`PyThreadState_SetAsyncExc` changed from :c:type:`long` to +:c:type:`unsigned long`. +(Contributed by Serhiy Storchaka in :issue:`6532`.) + +:c:func:`PyUnicode_AsWideCharString` now raises a :exc:`ValueError` if the +second argument is *NULL* and the :c:type:`wchar_t*` string contains null +characters. (Contributed by Serhiy Storchaka in :issue:`30708`.) + +Changes to the startup sequence and the management of dynamic memory +allocators mean that the long documented requirement to call +:c:func:`Py_Initialize` before calling most C API functions is now +relied on more heavily, and failing to abide by it may lead to segfaults in +embedding applications. See the :ref:`porting-to-python-37` section in this +document and the :ref:`pre-init-safe` section in the C API documentation +for more details. + +The new :c:func:`PyInterpreterState_GetID` returns the unique ID for a +given interpreter. +(Contributed by Eric Snow in :issue:`29102`.) + +:c:func:`Py_DecodeLocale`, :c:func:`Py_EncodeLocale` now use the UTF-8 +encoding when the :ref:`UTF-8 mode <whatsnew37-pep540>` is enabled. +(Contributed by Victor Stinner in :issue:`29240`.) + +:c:func:`PyUnicode_DecodeLocaleAndSize` and :c:func:`PyUnicode_EncodeLocale` +now use the current locale encoding for ``surrogateescape`` error handler. +(Contributed by Victor Stinner in :issue:`29240`.) + +The *start* and *end* parameters of :c:func:`PyUnicode_FindChar` are +now adjusted to behave like string slices. +(Contributed by Xiang Zhang in :issue:`28822`.) + + +Build Changes +============= + +Support for building ``--without-threads`` has been removed. The +:mod:`threading` module is now always available. +(Contributed by Antoine Pitrou in :issue:`31370`.). + +A full copy of libffi is no longer bundled for use when building the +:mod:`_ctypes <ctypes>` module on non-OSX UNIX platforms. An installed copy +of libffi is now required when building ``_ctypes`` on such platforms. +(Contributed by Zachary Ware in :issue:`27979`.) + +The Windows build process no longer depends on Subversion to pull in external +sources, a Python script is used to download zipfiles from GitHub instead. +If Python 3.6 is not found on the system (via ``py -3.6``), NuGet is used to +download a copy of 32-bit Python for this purpose. (Contributed by Zachary +Ware in :issue:`30450`.) + +The :mod:`ssl` module requires OpenSSL 1.0.2 or 1.1 compatible libssl. +OpenSSL 1.0.1 has reached end of lifetime on 2016-12-31 and is no longer +supported. LibreSSL is temporarily not supported as well. LibreSSL releases +up to version 2.6.4 are missing required OpenSSL 1.0.2 APIs. + + +.. _whatsnew37-perf: + Optimizations ============= -* Added two new opcodes: :opcode:`LOAD_METHOD` and :opcode:`CALL_METHOD` to avoid - instantiation of bound method objects for method calls, which results - in method calls being faster up to 20%. (Contributed by Yury Selivanov and - INADA Naoki in :issue:`26110`.) - -* Searching some unlucky Unicode characters (like Ukrainian capital "?") - in a string was up to 25 times slower than searching other characters. - Now it is slower only by 3 times in the worst case. - (Contributed by Serhiy Storchaka in :issue:`24821`.) - -* Fast implementation from standard C library is now used for functions - :func:`~math.erf` and :func:`~math.erfc` in the :mod:`math` module. - (Contributed by Serhiy Storchaka in :issue:`26121`.) - -* The :func:`os.fwalk` function has been sped up by 2 times. This was done - using the :func:`os.scandir` function. - (Contributed by Serhiy Storchaka in :issue:`25996`.) - -* The :func:`shutil.rmtree` function has been sped up to 20--40%. - This was done using the :func:`os.scandir` function. - (Contributed by Serhiy Storchaka in :issue:`28564`.) - -* Optimized case-insensitive matching and searching of :mod:`regular - expressions <re>`. Searching some patterns can now be up to 20 times faster. - (Contributed by Serhiy Storchaka in :issue:`30285`.) - -* :func:`re.compile` now converts ``flags`` parameter to int object if - it is ``RegexFlag``. It is now as fast as Python 3.5, and faster than - Python 3.6 by about 10% depending on the pattern. - (Contributed by INADA Naoki in :issue:`31671`.) - -* :meth:`~selectors.BaseSelector.modify` methods of classes - :class:`selectors.EpollSelector`, :class:`selectors.PollSelector` - and :class:`selectors.DevpollSelector` may be around 10% faster under - heavy loads. (Contributed by Giampaolo Rodola' in :issue:`30014`) - -* Constant folding is moved from peephole optimizer to new AST optimizer. - (Contributed by Eugene Toder and INADA Naoki in :issue:`29469`) - -* Most functions and methods in :mod:`abc` have been rewritten in C. - This makes creation of abstract base classes, and calling :func:`isinstance` - and :func:`issubclass` on them 1.5x faster. This also reduces Python - start-up time by up to 10%. (Contributed by Ivan Levkivskyi and INADA Naoki - in :issue:`31333`) - -* Significant speed improvements to alternate constructors for - :class:`datetime.date` and :class:`datetime.datetime` by using fast-path - constructors when not constructing subclasses. (Contributed by Paul Ganssle - in :issue:`32403`) - - -Build and C API Changes -======================= - -* :mod:`py_compile` and :mod:`compileall` now support the - :envvar:`SOURCE_DATE_EPOCH` environment variable by unconditionally - building ``.pyc`` files for hash verification instead of potentially - timestamp-based ``.pyc`` files. See the notes for the `py_compile`_ - improvement notes for more details. - -* A full copy of libffi is no longer bundled for use when building the - :mod:`_ctypes <ctypes>` module on non-OSX UNIX platforms. An installed copy - of libffi is now required when building ``_ctypes`` on such platforms. - (Contributed by Zachary Ware in :issue:`27979`.) - -* The fields :c:member:`name` and :c:member:`doc` of structures - :c:type:`PyMemberDef`, :c:type:`PyGetSetDef`, - :c:type:`PyStructSequence_Field`, :c:type:`PyStructSequence_Desc`, - and :c:type:`wrapperbase` are now of type ``const char *`` rather of - ``char *``. (Contributed by Serhiy Storchaka in :issue:`28761`.) - -* The result of :c:func:`PyUnicode_AsUTF8AndSize` and :c:func:`PyUnicode_AsUTF8` - is now of type ``const char *`` rather of ``char *``. (Contributed by Serhiy - Storchaka in :issue:`28769`.) - -* The result of :c:func:`PyMapping_Keys`, :c:func:`PyMapping_Values` and - :c:func:`PyMapping_Items` is now always a list, rather than a list or a - tuple. (Contributed by Oren Milman in :issue:`28280`.) - -* Added functions :c:func:`PySlice_Unpack` and :c:func:`PySlice_AdjustIndices`. - (Contributed by Serhiy Storchaka in :issue:`27867`.) - -* :c:func:`PyOS_AfterFork` is deprecated in favour of the new functions - :c:func:`PyOS_BeforeFork`, :c:func:`PyOS_AfterFork_Parent` and - :c:func:`PyOS_AfterFork_Child`. (Contributed by Antoine Pitrou in - :issue:`16500`.) - -* The Windows build process no longer depends on Subversion to pull in external - sources, a Python script is used to download zipfiles from GitHub instead. - If Python 3.6 is not found on the system (via ``py -3.6``), NuGet is used to - download a copy of 32-bit Python for this purpose. (Contributed by Zachary - Ware in :issue:`30450`.) - -* The ``PyExc_RecursionErrorInst`` singleton that was part of the public API - has been removed as its members being never cleared may cause a segfault - during finalization of the interpreter. Contributed by Xavier de Gaye in - :issue:`22898` and :issue:`30697`. - -* Support for building ``--without-threads`` is removed. - (Contributed by Antoine Pitrou in :issue:`31370`.). - -* Added C API support for timezones with timezone constructors - :c:func:`PyTimeZone_FromOffset` and :c:func:`PyTimeZone_FromOffsetAndName`, - and access to the UTC singleton with :c:data:`PyDateTime_TimeZone_UTC`. - Contributed by Paul Ganssle in :issue:`10381`. - -- The type of results of :c:func:`PyThread_start_new_thread` and - :c:func:`PyThread_get_thread_ident`, and the *id* parameter of - :c:func:`PyThreadState_SetAsyncExc` changed from :c:type:`long` to - :c:type:`unsigned long`. - (Contributed by Serhiy Storchaka in :issue:`6532`.) - -- :c:func:`PyUnicode_AsWideCharString` now raises a :exc:`ValueError` if the - second argument is *NULL* and the :c:type:`wchar_t*` string contains null - characters. (Contributed by Serhiy Storchaka in :issue:`30708`.) - -- Changes to the startup sequence and the management of dynamic memory - allocators mean that the long documented requirement to call - :c:func:`Py_Initialize` before calling most C API functions is now - relied on more heavily, and failing to abide by it may lead to segfaults in - embedding applications. See the :ref:`porting-to-python-37` section in this - document and the :ref:`pre-init-safe` section in the C API documentation - for more details. +The overhead of calling many methods of various standard library classes +implemented in C has been significantly reduced by porting more code +to use the ``METH_FASTCALL`` convention. +(Contributed by Victor Stinner in :issue:`29300`, :issue:`29507`, +:issue:`29452`, and :issue:`29286`.) + +Various optimizations have reduced Python startup time by 10% on Linux and +up to 30% on macOS. +(Contributed by Victor Stinner, INADA Naoki in :issue:`29585`, and +Ivan Levkivskyi in :issue:`31333`.) + +Method calls are now up to 20% faster due to the bytecode changes which +avoid creating bound method instances. +(Contributed by Yury Selivanov and INADA Naoki in :issue:`26110`.) + +.. _whatsnew37-asyncio-perf: + +The :mod:`asyncio` module received a number of notable optimizations for +commonly used functions: + +* The :func:`asyncio.get_event_loop` function has been reimplemented in C to + make it up to 15 times faster. + (Contributed by Yury Selivanov in :issue:`32296`.) + +* :class:`asyncio.Future` callback management has been optimized. + (Contributed by Yury Selivanov in :issue:`32348`.) + +* :func:`asyncio.gather` is now up to 15% faster. + (Contributed by Yury Selivanov in :issue:`32355`.) + +* :func:`asyncio.sleep` is now up to 2 times faster when the *delay* + argument is zero or negative. + (Contributed by Andrew Svetlov in :issue:`32351`.) + +* The performance overhead of asyncio debug mode has been reduced. + (Contributed by Antoine Pitrou in :issue:`31970`.) + +As a result of :ref:`PEP 560 work <whatsnew37-pep560>`, the import time +of :mod:`typing` has been reduced by a factor of 7, and many typing operations +are now faster. +(Contributed by Ivan Levkivskyi in :issue:`32226`.) + +:func:`sorted` and :meth:`list.sort` have been optimized for common cases +to be up to 40-75% faster. +(Contributed by Elliot Gorokhovsky in :issue:`28685`.) + +:meth:`dict.copy` is now up to 5.5 times faster. +(Contributed by Yury Selivanov in :issue:`31179`.) + +:func:`hasattr` and :func:`getattr` are now about 4 times faster when +*name* is not found and *obj* does not override :meth:`object.__getattr__` +or :meth:`object.__getattribute__`. +(Contributed by INADA Naoki in :issue:`32544`.) + +Searching for certain Unicode characters (like Ukrainian capital "?") +in a string was up to 25 times slower than searching for other characters. +It is now only 3 times slower in the worst case. +(Contributed by Serhiy Storchaka in :issue:`24821`.) + +The :func:`collections.namedtuple` factory has been reimplemented to +make the creation of named tuples 4 to 6 times faster. +(Contributed by Jelle Zijlstra with further improvements by INADA Naoki, +Serhiy Storchaka, and Raymond Hettinger in :issue:`28638`.) + +:meth:`date.fromordinal` and :meth:`date.fromtimestamp` are now up to +30% faster in the common case. +(Contributed by Paul Ganssle in :issue:`32403`.) + +The :func:`os.fwalk` function is now up to 2 times faster thanks to +the use of :func:`os.scandir`. +(Contributed by Serhiy Storchaka in :issue:`25996`.) + +The speed of the :func:`shutil.rmtree` function has been improved by +20--40% thanks to the use of the :func:`os.scandir` function. +(Contributed by Serhiy Storchaka in :issue:`28564`.) + +Optimized case-insensitive matching and searching of :mod:`regular +expressions <re>`. Searching some patterns can now be up to 20 times faster. +(Contributed by Serhiy Storchaka in :issue:`30285`.) + +:func:`re.compile` now converts ``flags`` parameter to int object if +it is ``RegexFlag``. It is now as fast as Python 3.5, and faster than +Python 3.6 by about 10% depending on the pattern. +(Contributed by INADA Naoki in :issue:`31671`.) + +The :meth:`~selectors.BaseSelector.modify` methods of classes +:class:`selectors.EpollSelector`, :class:`selectors.PollSelector` +and :class:`selectors.DevpollSelector` may be around 10% faster under +heavy loads. (Contributed by Giampaolo Rodola' in :issue:`30014`) + +Constant folding has been moved from the peephole optimizer to the new AST +optimizer, which is able perform optimizations more consistently. +(Contributed by Eugene Toder and INADA Naoki in :issue:`29469` and +:issue:`11549`.) + +Most functions and methods in :mod:`abc` have been rewritten in C. +This makes creation of abstract base classes, and calling :func:`isinstance` +and :func:`issubclass` on them 1.5x faster. This also reduces Python +start-up time by up to 10%. (Contributed by Ivan Levkivskyi and INADA Naoki +in :issue:`31333`) + +Significant speed improvements to alternate constructors for +:class:`datetime.date` and :class:`datetime.datetime` by using fast-path +constructors when not constructing subclasses. (Contributed by Paul Ganssle +in :issue:`32403`) + +The speed of comparison of :class:`array.array` instances has been +improved considerably in certain cases. It is now from 10x to 70x faster +when comparing arrays holding values of the same integer type. +(Contributed by Adrian Wielgosik in :issue:`24700`.) + +The :func:`math.erf` and :func:`math.erfc` functions now use the (faster) +C library implementation on most platforms. +(Contributed by Serhiy Storchaka in :issue:`26121`.) Other CPython Implementation Changes ==================================== -* Trace hooks may now opt out of receiving ``line`` events from the interpreter - by setting the new ``f_trace_lines`` attribute to :const:`False` on the frame - being traced. (Contributed by Nick Coghlan in :issue:`31344`.) - -* Trace hooks may now opt in to receiving ``opcode`` events from the interpreter - by setting the new ``f_trace_opcodes`` attribute to :const:`True` on the frame - being traced. (Contributed by Nick Coghlan in :issue:`31344`.) +* Trace hooks may now opt out of receiving the ``line`` and opt into receiving + the ``opcode`` events from the interpreter by setting the corresponding new + ``f_trace_lines`` and ``f_trace_opcodes`` attributes on the + frame being traced. (Contributed by Nick Coghlan in :issue:`31344`.) * Fixed some consistency problems with namespace package module attributes. Namespace module objects now have an ``__file__`` that is set to ``None`` @@ -1012,90 +1766,213 @@ Other CPython Implementation Changes ``__loader__`` (previously, the former was set to ``None``). See :issue:`32303`. +* The :func:`locals` dictionary now displays in the lexical order that + variables were defined. Previously, the order was undefined. + (Contributed by Raymond Hettinger in :issue:`32690`.) -Deprecated -========== +* The :mod:`distutils` ``upload`` command no longer tries to change CR + end-of-line characters to CRLF. This fixes a corruption issue with sdists + that ended with a byte equivalent to CR. + (Contributed by Bo Bayles in :issue:`32304`.) -* In Python 3.8, the abstract base classes in :mod:`collections.abc` will no - longer be exposed in the regular :mod:`collections` module. This will help - create a clearer distinction between the concrete classes and the abstract - base classes. -* Yield expressions (both ``yield`` and ``yield from`` clauses) are now deprecated - in comprehensions and generator expressions (aside from the iterable expression - in the leftmost :keyword:`for` clause). This ensures that comprehensions - always immediately return a container of the appropriate type (rather than - potentially returning a :term:`generator iterator` object), while generator - expressions won't attempt to interleave their implicit output with the output - from any explicit yield expressions. +Deprecated Python Behavior +========================== - In Python 3.7, such expressions emit :exc:`DeprecationWarning` when compiled, - in Python 3.8+ they will emit :exc:`SyntaxError`. (Contributed by Serhiy - Storchaka in :issue:`10544`.) +Yield expressions (both ``yield`` and ``yield from`` clauses) are now deprecated +in comprehensions and generator expressions (aside from the iterable expression +in the leftmost :keyword:`for` clause). This ensures that comprehensions +always immediately return a container of the appropriate type (rather than +potentially returning a :term:`generator iterator` object), while generator +expressions won't attempt to interleave their implicit output with the output +from any explicit yield expressions. In Python 3.7, such expressions emit +:exc:`DeprecationWarning` when compiled, in Python 3.8 this will be a +:exc:`SyntaxError`. +(Contributed by Serhiy Storchaka in :issue:`10544`.) -- Function :c:func:`PySlice_GetIndicesEx` is deprecated and replaced with - a macro if ``Py_LIMITED_API`` is not set or set to the value between - ``0x03050400`` and ``0x03060000`` (not including) or ``0x03060100`` or - higher. (Contributed by Serhiy Storchaka in :issue:`27867`.) +Returning a subclass of :class:`complex` from :meth:`object.__complex__` is +deprecated and will be an error in future Python versions. This makes +``__complex__()`` consistent with :meth:`object.__int__` and +:meth:`object.__float__`. +(Contributed by Serhiy Storchaka in :issue:`28894`.) -- Deprecated :meth:`format` from :mod:`locale`, use the :meth:`format_string` - instead. (Contributed by Garvit in :issue:`10379`.) -- Methods - :meth:`MetaPathFinder.find_module() <importlib.abc.MetaPathFinder.find_module>` - (replaced by - :meth:`MetaPathFinder.find_spec() <importlib.abc.MetaPathFinder.find_spec>`) - and - :meth:`PathEntryFinder.find_loader() <importlib.abc.PathEntryFinder.find_loader>` - (replaced by - :meth:`PathEntryFinder.find_spec() <importlib.abc.PathEntryFinder.find_spec>`) - both deprecated in Python 3.4 now emit :exc:`DeprecationWarning`. - (Contributed by Matthias Bussonnier in :issue:`29576`) -- Using non-integer value for selecting a plural form in :mod:`gettext` is - now deprecated. It never correctly worked. (Contributed by Serhiy Storchaka - in :issue:`28692`.) +Deprecated Python modules, functions and methods +================================================ -- The :mod:`macpath` is now deprecated and will be removed in Python 3.8. +aifc +---- + +:func:`aifc.openfp` has been deprecated and will be removed in Python 3.9. +Use :func:`aifc.open` instead. +(Contributed by Brian Curtin in :issue:`31985`.) -- The :class:`importlib.abc.ResourceLoader` ABC has been deprecated in - favour of :class:`importlib.abc.ResourceReader`. -- Deprecated :func:`sys.set_coroutine_wrapper` and - :func:`sys.get_coroutine_wrapper`. +.. _whatsnew37-asyncio-deprecated: -- :func:`ssl.wrap_socket` is deprecated. Use - :meth:`ssl.SSLContext.wrap_socket` instead. - (Contributed by Christian Heimes in :issue:`28124`.) +asyncio +------- +Support for directly ``await``-ing instances of :class:`asyncio.Lock` and +other asyncio synchronization primitives has been deprecated. An +asynchronous context manager must be used in order to acquire and release +the synchronization resource. See :ref:`async-with-locks` for more +information. +(Contributed by Andrew Svetlov in :issue:`32253`.) + +The :meth:`asyncio.Task.current_task` and :meth:`asyncio.Task.all_tasks` +methods have been deprecated. +(Contributed by Andrew Svetlov in :issue:`32250`.) + + +collections +----------- + +In Python 3.8, the abstract base classes in :mod:`collections.abc` will no +longer be exposed in the regular :mod:`collections` module. This will help +create a clearer distinction between the concrete classes and the abstract +base classes. +(Contributed by Serhiy Storchaka in :issue:`25988`.) + + +dbm +--- + +:mod:`dbm.dumb` now supports reading read-only files and no longer writes the +index file when it is not changed. A deprecation warning is now emitted +if the index file is missing and recreated in the ``'r'`` and ``'w'`` +modes (this will be an error in future Python releases). +(Contributed by Serhiy Storchaka in :issue:`28847`.) + + +enum +---- + +In Python 3.8, attempting to check for non-Enum objects in :class:`Enum` +classes will raise a :exc:`TypeError` (e.g. ``1 in Color``); similarly, +attempting to check for non-Flag objects in a :class:`Flag` member will +raise :exc:`TypeError` (e.g. ``1 in Perm.RW``); currently, both operations +return :const:`False` instead. +(Contributed by Ethan Furman in :issue:`33217`.) + + +gettext +------- + +Using non-integer value for selecting a plural form in :mod:`gettext` is +now deprecated. It never correctly worked. (Contributed by Serhiy Storchaka +in :issue:`28692`.) + + +importlib +--------- + +Methods +:meth:`MetaPathFinder.find_module() <importlib.abc.MetaPathFinder.find_module>` +(replaced by +:meth:`MetaPathFinder.find_spec() <importlib.abc.MetaPathFinder.find_spec>`) +and +:meth:`PathEntryFinder.find_loader() <importlib.abc.PathEntryFinder.find_loader>` +(replaced by +:meth:`PathEntryFinder.find_spec() <importlib.abc.PathEntryFinder.find_spec>`) +both deprecated in Python 3.4 now emit :exc:`DeprecationWarning`. +(Contributed by Matthias Bussonnier in :issue:`29576`) + +The :class:`importlib.abc.ResourceLoader` ABC has been deprecated in +favour of :class:`importlib.abc.ResourceReader`. + + +locale +------ + +:func:`locale.format` has been deprecated, use :meth:`locale.format_string` +instead. (Contributed by Garvit in :issue:`10379`.) + + +macpath +------- + +The :mod:`macpath` is now deprecated and will be removed in Python 3.8. +(Contributed by Chi Hsuan Yen in :issue:`9850`.) + + +threading +--------- + +:mod:`dummy_threading` and :mod:`_dummy_thread` have been deprecated. It is +no longer possible to build Python with threading disabled. +Use :mod:`threading` instead. +(Contributed by Antoine Pitrou in :issue:`31370`.) -Windows Only ------------- -- The python launcher, (py.exe), can accept 32 & 64 bit specifiers **without** - having to specify a minor version as well. So ``py -3-32`` and ``py -3-64`` - become valid as well as ``py -3.7-32``, also the -*m*-64 and -*m.n*-64 forms - are now accepted to force 64 bit python even if 32 bit would have otherwise - been used. If the specified version is not available py.exe will error exit. - (Contributed by Steve Barnes in :issue:`30291`.) +socket +------ + +The silent argument value trunctation in :func:`socket.htons` and +:func:`socket.ntohs` has been deprecated. In future versions of Python, +if the passed argument is larger than 16 bits, an exception will be raised. +(Contributed by Oren Milman in :issue:`28332`.) + + +ssl +--- + +:func:`ssl.wrap_socket` is deprecated. Use +:meth:`ssl.SSLContext.wrap_socket` instead. +(Contributed by Christian Heimes in :issue:`28124`.) + + +sunau +----- + +:func:`sunau.openfp` has been deprecated and will be removed in Python 3.9. +Use :func:`sunau.open` instead. +(Contributed by Brian Curtin in :issue:`31985`.) + + +sys +--- + +Deprecated :func:`sys.set_coroutine_wrapper` and +:func:`sys.get_coroutine_wrapper`. -- The launcher can be run as ``py -0`` to produce a list of the installed pythons, - *with default marked with an asterisk*. Running ``py -0p`` will include the paths. - If py is run with a version specifier that cannot be matched it will also print - the *short form* list of available specifiers. - (Contributed by Steve Barnes in :issue:`30362`.) +The undocumented ``sys.callstats()`` function has been deprecated and +will be removed in a future Python version. +(Contributed by Victor Stinner in :issue:`28799`.) -Removed -======= +wave +---- + +:func:`wave.openfp` has been deprecated and will be removed in Python 3.9. +Use :func:`wave.open` instead. +(Contributed by Brian Curtin in :issue:`31985`.) + + +Deprecated functions and types of the C API +=========================================== + +Function :c:func:`PySlice_GetIndicesEx` is deprecated and replaced with +a macro if ``Py_LIMITED_API`` is not set or set to a value in the range +between ``0x03050400`` and ``0x03060000`` (not inclusive), or is ``0x03060100`` +or higher. (Contributed by Serhiy Storchaka in :issue:`27867`.) + +:c:func:`PyOS_AfterFork` has been deprecated. Use :c:func:`PyOS_BeforeFork`, +:c:func:`PyOS_AfterFork_Parent` or :c:func:`PyOS_AfterFork_Child()` instead. +(Contributed by Antoine Pitrou in :issue:`16500`.) + Platform Support Removals -------------------------- +========================= + +FreeBSD 9 and older are no longer officially supported. -* FreeBSD 9 and older are no longer supported. API and Feature Removals ------------------------- +======================== + +The following features and APIs have been removed from Python 3.7: * The ``os.stat_float_times()`` function has been removed. It was introduced in Python 2.3 for backward compatibility with Python 2.2, and was deprecated @@ -1129,15 +2006,51 @@ API and Feature Removals can use attribute access to access items of these dictionaries. * The ``asyncio.windows_utils.socketpair()`` function has been - removed: use directly :func:`socket.socketpair` which is available on all - platforms since Python 3.5 (before, it wasn't available on Windows). + removed. Use the :func:`socket.socketpair` function instead, + it is available on all platforms since Python 3.5. ``asyncio.windows_utils.socketpair`` was just an alias to ``socket.socketpair`` on Python 3.5 and newer. -* :mod:`asyncio`: The module doesn't export :mod:`selectors` and +* :mod:`asyncio` no longer exports the :mod:`selectors` and :mod:`_overlapped` modules as ``asyncio.selectors`` and ``asyncio._overlapped``. Replace ``from asyncio import selectors`` with - ``import selectors`` for example. + ``import selectors``. + +* Direct instantiation of :class:`ssl.SSLSocket` and :class:`ssl.SSLObject` + objects is now prohibited. The constructors were never documented, tested, + or designed as public constructors. Users were supposed to use + :func:`ssl.wrap_socket` or :class:`ssl.SSLContext`. + (Contributed by Christian Heimes in :issue:`32951`.) + +* The unused :mod:`distutils` ``install_misc`` command has been removed. + (Contributed by Eric N. Vander Weele in :issue:`29218`.) + + +Module Removals +=============== + +The ``fpectl`` module has been removed. It was never enabled by +default, never worked correctly on x86-64, and it changed the Python +ABI in ways that caused unexpected breakage of C extensions. +(Contributed by Nathaniel J. Smith in :issue:`29137`.) + + +Windows-only Changes +==================== + +The python launcher, (py.exe), can accept 32 & 64 bit specifiers **without** +having to specify a minor version as well. So ``py -3-32`` and ``py -3-64`` +become valid as well as ``py -3.7-32``, also the -*m*-64 and -*m.n*-64 forms +are now accepted to force 64 bit python even if 32 bit would have otherwise +been used. If the specified version is not available py.exe will error exit. +(Contributed by Steve Barnes in :issue:`30291`.) + +The launcher can be run as ``py -0`` to produce a list of the installed pythons, +*with default marked with an asterisk*. Running ``py -0p`` will include the paths. +If py is run with a version specifier that cannot be matched it will also print +the *short form* list of available specifiers. +(Contributed by Steve Barnes in :issue:`30362`.) + .. _porting-to-python-37: @@ -1148,15 +2061,22 @@ This section lists previously described changes and other bugfixes that may require changes to your code. -Changes in Python behavior +Changes in Python Behavior -------------------------- +* :keyword:`async` and :keyword:`await` names are now reserved keywords. + Code using these names as identifiers will now raise a :exc:`SyntaxError`. + (Contributed by Jelle Zijlstra in :issue:`30406`.) + * :pep:`479` is enabled for all code in Python 3.7, meaning that :exc:`StopIteration` exceptions raised directly or indirectly in coroutines and generators are transformed into :exc:`RuntimeError` exceptions. (Contributed by Yury Selivanov in :issue:`32670`.) +* :meth:`object.__aiter__` methods can no longer be declared as + asynchronous. (Contributed by Yury Selivanov in :issue:`31709`.) + * Due to an oversight, earlier Python versions erroneously accepted the following syntax:: @@ -1183,22 +2103,25 @@ Changes in Python behavior Changes in the Python API ------------------------- -* :meth:`socketserver.ThreadingMixIn.server_close` now waits until all - non-daemon threads complete. Use daemonic threads by setting - :data:`socketserver.ThreadingMixIn.daemon_threads` to ``True`` to not - wait until threads complete. - (Contributed by Victor Stinner in :issue:`31233`.) +* ``Module``, ``FunctionDef``, ``AsyncFunctionDef``, and + ``ClassDef`` AST nodes now have the new ``docstring`` attribute. + The first statement in their body is not considered as a docstring + anymore. ``co_firstlineno`` and ``co_lnotab`` of code object for class + and module are affected by this change. (Contributed by INADA Naoki and + Eugene Toder in :issue:`29463`.) -* :meth:`socketserver.ForkingMixIn.server_close` now waits until all - child processes complete. (Contributed by Victor Stinner in :issue:`31151`.) +* :meth:`~socketserver.BaseServer.server_close` in + :class:`socketserver.ThreadingMixIn` and :class:`socketserver.ForkingMixIn` + now waits until all non-daemon threads complete. + (Contributed by Victor Stinner in :issue:`31233` and :issue:`31151`.) -* The :func:`locale.localeconv` function now sets temporarily the ``LC_CTYPE`` - locale to the ``LC_NUMERIC`` locale in some cases. +* The :func:`locale.localeconv` function now temporarily sets the ``LC_CTYPE`` + locale to the value of ``LC_NUMERIC`` in some cases. (Contributed by Victor Stinner in :issue:`31900`.) -* :meth:`pkgutil.walk_packages` now raises :exc:`ValueError` if *path* is a string. - Previously an empty list was returned. (Contributed by Sanyam Khurana in - :issue:`24744`.) +* :meth:`pkgutil.walk_packages` now raises a :exc:`ValueError` if *path* is + a string. Previously an empty list was returned. + (Contributed by Sanyam Khurana in :issue:`24744`.) * A format string argument for :meth:`string.Formatter.format` is now :ref:`positional-only <positional-only_parameter>`. @@ -1213,13 +2136,6 @@ Changes in the Python API Use the :meth:`~http.cookies.Morsel.set` method for setting them. (Contributed by Serhiy Storchaka in :issue:`29192`.) -* ``Module``, ``FunctionDef``, ``AsyncFunctionDef``, and - ``ClassDef`` AST nodes now have a new ``docstring`` field. - The first statement in their body is not considered as a docstring - anymore. ``co_firstlineno`` and ``co_lnotab`` of code object for class - and module are affected by this change. (Contributed by INADA Naoki and - Eugene Toder in :issue:`29463`.) - * The *mode* argument of :func:`os.makedirs` no longer affects the file permission bits of newly-created intermediate-level directories. To set their file permission bits you can set the umask before invoking @@ -1229,34 +2145,35 @@ Changes in the Python API * The :attr:`struct.Struct.format` type is now :class:`str` instead of :class:`bytes`. (Contributed by Victor Stinner in :issue:`21071`.) -* :func:`~cgi.parse_multipart` returns now the same results as +* :func:`~cgi.parse_multipart` now accepts the *encoding* and *errors* + arguments and returns the same results as :class:`~FieldStorage`: for non-file fields, the value associated to a key is a list of strings, not bytes. (Contributed by Pierre Quentel in :issue:`29979`.) -* Due to internal changes in :mod:`socket` you won't be able to - :func:`socket.fromshare` a socket :func:`~socket.socket.share`-ed in older - Python versions. +* Due to internal changes in :mod:`socket`, calling :func:`socket.fromshare` + on a socket created by :func:`socket.share <socket.socket.share>` in older + Python versions is not supported. -* ``repr`` for :exc:`BaseException` has changed not to include trailing comma - in the output. Mind that most exceptions are affected by this change. +* ``repr`` for :exc:`BaseException` has changed to not include the trailing + comma. Most exceptions are affected by this change. (Contributed by Serhiy Storchaka in :issue:`30399`.) -* ``repr`` for :class:`datetime.timedelta` has changed to include keyword arguments - in the output. (Contributed by Utkarsh Upadhyay in :issue:`30302`.) +* ``repr`` for :class:`datetime.timedelta` has changed to include the keyword + arguments in the output. (Contributed by Utkarsh Upadhyay in :issue:`30302`.) * Because :func:`shutil.rmtree` is now implemented using the :func:`os.scandir` function, the user specified handler *onerror* is now called with the first argument ``os.scandir`` instead of ``os.listdir`` when listing the direcory is failed. -* Support of nested sets and set operations in regular expressions as in +* Support for nested sets and set operations in regular expressions as in `Unicode Technical Standard #18`_ might be added in the future. This would - change the syntax, so to facilitate this change a :exc:`FutureWarning` will - be raised in ambiguous cases for the time being. + change the syntax. To facilitate this future change a :exc:`FutureWarning` + will be raised in ambiguous cases for the time being. That include sets starting with a literal ``'['`` or containing literal character sequences ``'--'``, ``'&&'``, ``'~~'``, and ``'||'``. To - avoid a warning escape them with a backslash. + avoid a warning, escape them with a backslash. (Contributed by Serhiy Storchaka in :issue:`30349`.) .. _Unicode Technical Standard #18: https://unicode.org/reports/tr18/ @@ -1308,85 +2225,124 @@ Changes in the Python API previous behaviour, or use :attr:`STARTUPINFO.lpAttributeList <subprocess.STARTUPINFO.lpAttributeList>`. +* :meth:`importlib.machinery.PathFinder.invalidate_caches` -- which implicitly + affects :func:`importlib.invalidate_caches` -- now deletes entries + in :data:`sys.path_importer_cache` which are set to ``None``. + (Contributed by Brett Cannon in :issue:`33169`.) + +* In :mod:`asyncio`, + :meth:`loop.sock_recv() <asyncio.AbstractEventLoop.sock_recv>`, + :meth:`loop.sock_sendall() <asyncio.AbstractEventLoop.sock_sendall>`, + :meth:`loop.sock_accept() <asyncio.AbstractEventLoop.sock_accept>`, + :meth:`loop.getaddrinfo() <asyncio.AbstractEventLoop.getaddrinfo>`, + :meth:`loop.getnameinfo() <asyncio.AbstractEventLoop.getnameinfo>` + have been changed to be proper coroutine methods to match their + documentation. Previously, these methods returned :class:`asyncio.Future` + instances. + (Contributed by Yury Selivanov in :issue:`32327`.) + +* :attr:`asyncio.Server.sockets` now returns a copy of the internal list + of server sockets, instead of returning it directly. + (Contributed by Yury Selivanov in :issue:`32662`.) + +* :attr:`Struct.format <struct.Struct.format>` is now a :class:`str` instance + instead of a :class:`bytes` instance. + (Contributed by Victor Stinner in :issue:`21071`.) + +* :mod:`argparse` subparsers are now required by default. This matches the + behaviour in Python 2. To add an optional subparser, pass + ``required=False`` to + :meth:`ArgumentParser.add_subparsers() <argparse.ArgumentParser.add_subparsers>`. + (Contributed by Anthony Sottile in :issue:`26510`.) + +* :meth:`ast.literal_eval()` is now stricter. Addition and subtraction of + arbitrary numbers are no longer allowed. + (Contributed by Serhiy Storchaka in :issue:`31778`.) + +* :meth:`Calendar.itermonthdates <calendar.Calendar.itermonthdates>` + will now consistently raise an exception when a date falls outside of the + ``0001-01-01`` through ``9999-12-31`` range. To support applications that + cannot tolerate such exceptions, the new + :meth:`Calendar.itermonthdays3 <calendar.Calendar.itermonthdays3>` and + :meth:`Calendar.itermonthdays4 <calendar.Calendar.itermonthdays4>` can be used. + The new methods return tuples and are not restricted by the range supported by + :class:`datetime.date`. + (Contributed by Alexander Belopolsky in :issue:`28292`.) + +* :class:`collections.ChainMap` now preserves the order of the underlying + mappings. (Contributed by Raymond Hettinger in :issue:`32792`.) + +* The ``submit()`` method of :class:`concurrent.futures.ThreadPoolExecutor` + and :class:`concurrent.futures.ProcessPoolExecutor` now raises + a :exc:`RuntimeError` if called during interpreter shutdown. + (Contributed by Mark Nemec in :issue:`33097`.) + +* The :class:`configparser.ConfigParser` constructor now uses ``read_dict()`` + to process the default values, making its behavior consistent with the + rest of the parser. Non-string keys and values in the defaults + dictionary are now being implicitly converted to strings. + (Contributed by James Tocknell in :issue:`23835`.) + Changes in the C API -------------------- -* The function :c:func:`PySlice_GetIndicesEx` is considered not safe for - resizable sequences. If the slice indices are not instances of :class:`int`, - but objects that implement the :meth:`!__index__` method, the sequence can be - resized after passing its length to :c:func:`!PySlice_GetIndicesEx`. This - can lead to returning indices out of the length of the sequence. For - avoiding possible problems use new functions :c:func:`PySlice_Unpack` and - :c:func:`PySlice_AdjustIndices`. - (Contributed by Serhiy Storchaka in :issue:`27867`.) +The function :c:func:`PySlice_GetIndicesEx` is considered unsafe for +resizable sequences. If the slice indices are not instances of :class:`int`, +but objects that implement the :meth:`!__index__` method, the sequence can be +resized after passing its length to :c:func:`!PySlice_GetIndicesEx`. This +can lead to returning indices out of the length of the sequence. For +avoiding possible problems use new functions :c:func:`PySlice_Unpack` and +:c:func:`PySlice_AdjustIndices`. +(Contributed by Serhiy Storchaka in :issue:`27867`.) CPython bytecode changes ------------------------ -* Added two new opcodes: :opcode:`LOAD_METHOD` and :opcode:`CALL_METHOD`. - (Contributed by Yury Selivanov and INADA Naoki in :issue:`26110`.) - -* Removed the :opcode:`STORE_ANNOTATION` opcode. - (Contributed by Mark Shannon in :issue:`32550`.) - - -Other CPython implementation changes ------------------------------------- - -* In preparation for potential future changes to the public CPython runtime - initialization API (see :pep:`432` for an initial, but somewhat outdated, - draft), CPython's internal startup - and configuration management logic has been significantly refactored. While - these updates are intended to be entirely transparent to both embedding - applications and users of the regular CPython CLI, they're being mentioned - here as the refactoring changes the internal order of various operations - during interpreter startup, and hence may uncover previously latent defects, - either in embedding applications, or in CPython itself. - (Initially contributed by Nick Coghlan and Eric Snow as part of - :issue:`22257`, and further updated by Nick, Eric, and Victor Stinner in a - number of other issues). Some known details affected: - - * :c:func:`PySys_AddWarnOptionUnicode` is not currently usable by embedding - applications due to the requirement to create a Unicode object prior to - calling `Py_Initialize`. Use :c:func:`PySys_AddWarnOption` instead. - * warnings filters added by an embedding application with - :c:func:`PySys_AddWarnOption` should now more consistently take precedence - over the default filters set by the interpreter - -* Due to changes in the way the default warnings filters are configured, - setting :c:data:`Py_BytesWarningFlag` to a value greater than one is no longer - sufficient to both emit :exc:`BytesWarning` messages and have them converted - to exceptions. Instead, the flag must be set (to cause the warnings to be - emitted in the first place), and an explicit ``error::BytesWarning`` - warnings filter added to convert them to exceptions. - -* CPython' :mod:`ssl` module requires OpenSSL 1.0.2 or 1.1 compatible libssl. - OpenSSL 1.0.1 has reached end of lifetime on 2016-12-31 and is no longer - supported. LibreSSL is temporarily not supported as well. LibreSSL releases - up to version 2.6.4 are missing required OpenSSL 1.0.2 APIs. - - -Documentation -============= +There are two new opcodes: :opcode:`LOAD_METHOD` and :opcode:`CALL_METHOD`. +(Contributed by Yury Selivanov and INADA Naoki in :issue:`26110`.) -.. _whatsnew37-pep545: +The :opcode:`STORE_ANNOTATION` opcode has been removed. +(Contributed by Mark Shannon in :issue:`32550`.) -PEP 545: Python Documentation Translations ------------------------------------------- -:pep:`545` describes the process to translate Python documentation, -and three translations have been added: +Windows-only Changes +-------------------- -- Japanese: https://docs.python.org/ja/ and associated GitHub - repository: https://github.com/python/python-docs-ja +The file used to override :data:`sys.path` is now called +``<python-executable>._pth`` instead of ``'sys.path'``. +See :ref:`finding_modules` for more information. +(Contributed by Steve Dower in :issue:`28137`.) -- French: https://docs.python.org/fr/ and associated GitHub - repository: https://github.com/python/python-docs-fr -- Korean: https://docs.python.org/ko/ and associated GitHub - repository: https://github.com/python/python-docs-ko +Other CPython implementation changes +------------------------------------ -(Contributed by Julien Palard, Inada Naoki, and Victor Stinner in -:issue:`26546`.) +In preparation for potential future changes to the public CPython runtime +initialization API (see :pep:`432` for an initial, but somewhat outdated, +draft), CPython's internal startup +and configuration management logic has been significantly refactored. While +these updates are intended to be entirely transparent to both embedding +applications and users of the regular CPython CLI, they're being mentioned +here as the refactoring changes the internal order of various operations +during interpreter startup, and hence may uncover previously latent defects, +either in embedding applications, or in CPython itself. +(Initially contributed by Nick Coghlan and Eric Snow as part of +:issue:`22257`, and further updated by Nick, Eric, and Victor Stinner in a +number of other issues). Some known details affected: + +* :c:func:`PySys_AddWarnOptionUnicode` is not currently usable by embedding + applications due to the requirement to create a Unicode object prior to + calling `Py_Initialize`. Use :c:func:`PySys_AddWarnOption` instead. + +* warnings filters added by an embedding application with + :c:func:`PySys_AddWarnOption` should now more consistently take precedence + over the default filters set by the interpreter + +Due to changes in the way the default warnings filters are configured, +setting :c:data:`Py_BytesWarningFlag` to a value greater than one is no longer +sufficient to both emit :exc:`BytesWarning` messages and have them converted +to exceptions. Instead, the flag must be set (to cause the warnings to be +emitted in the first place), and an explicit ``error::BytesWarning`` +warnings filter added to convert them to exceptions. From webhook-mailer at python.org Sat May 19 23:39:48 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Sun, 20 May 2018 03:39:48 -0000 Subject: [Python-checkins] [3.7] bpo-32996: The bulk of What's New in Python 3.7 (GH-6978). (GH-6998) Message-ID: <mailman.161.1526787590.2757.python-checkins@python.org> https://github.com/python/cpython/commit/15f3d0cc7660ee62c7a1c0420afaee18c26a2a1f commit: 15f3d0cc7660ee62c7a1c0420afaee18c26a2a1f branch: 3.7 author: Elvis Pranskevichus <elvis at magic.io> committer: Yury Selivanov <yury at magic.io> date: 2018-05-19T23:39:45-04:00 summary: [3.7] bpo-32996: The bulk of What's New in Python 3.7 (GH-6978). (GH-6998) (cherry picked from commit 63536bd286097e770909052052a21804a5e09b66) Co-authored-by: Elvis Pranskevichus <elvis at magic.io> files: M Doc/library/asyncio-task.rst M Doc/library/ensurepip.rst M Doc/reference/compound_stmts.rst M Doc/whatsnew/3.7.rst diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index db0e04a4a1d1..2488a909ec00 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -92,7 +92,7 @@ Coroutines (and tasks) can only run when the event loop is running. used in a callback-style code, wrap its result with :func:`ensure_future`. -.. function:: asyncio.run(coro, \*, debug=False) +.. function:: run(coro, \*, debug=False) This function runs the passed coroutine, taking care of managing the asyncio event loop and finalizing asynchronous diff --git a/Doc/library/ensurepip.rst b/Doc/library/ensurepip.rst index ed22180dc3f8..c797f63326d1 100644 --- a/Doc/library/ensurepip.rst +++ b/Doc/library/ensurepip.rst @@ -78,9 +78,6 @@ options: Providing both of the script selection options will trigger an exception. -.. versionchanged:: 3.7.0 - The exit status is non-zero if the command fails. - Module API ---------- diff --git a/Doc/reference/compound_stmts.rst b/Doc/reference/compound_stmts.rst index d7792f1eaf82..c695feaa50e5 100644 --- a/Doc/reference/compound_stmts.rst +++ b/Doc/reference/compound_stmts.rst @@ -683,6 +683,8 @@ can be used to create instance variables with different implementation details. :pep:`3129` - Class Decorators +.. _async: + Coroutines ========== diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index dfe6c90d3a38..09a6eac879c4 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -2,6 +2,8 @@ What's New In Python 3.7 **************************** +:Editor: Elvis Pranskevichus <elvis at magic.io> + .. Rules for maintenance: * Anyone can add text to this document. Do not spend very much time @@ -39,34 +41,141 @@ module. (Contributed by P.Y. Developer in :issue:`12345`.) - This saves the maintainer the effort of going through the Mercurial log + This saves the maintainer the effort of going through the Git log when researching a change. This article explains the new features in Python 3.7, compared to 3.6. For full details, see the :ref:`changelog <changelog>`. -.. note:: - - Prerelease users should be aware that this document is currently in draft - form. It will be updated substantially as Python 3.7 moves towards release, - so it's worth checking back even after reading earlier versions. - -Summary -- Release highlights +Summary -- Release Highlights ============================= .. This section singles out the most important changes in Python 3.7. Brevity is key. +New syntax features: + +* :ref:`PEP 563 <whatsnew37-pep563>`, postponed evaluation of type annotations. + +Backwards incompatible syntax changes: + +* :keyword:`async` and :keyword:`await` are now reserved keywords. + +New library modules: + +* :mod:`contextvars`: :ref:`PEP 567 -- Context Variables <whatsnew37-pep567>` +* :mod:`dataclasses`: :ref:`PEP 557 -- Data Classes <whatsnew37-pep557>` +* :ref:`whatsnew37_importlib_resources` + +New built-in features: + +* :ref:`PEP 553 <whatsnew37-pep553>`, the new :func:`breakpoint` function. + +Python data model improvements: + +* :ref:`PEP 562 <whatsnew37-pep562>`, customization of access to + module attributes. + +* :ref:`PEP 560 <whatsnew37-pep560>`, core support for typing module and + generic types. + +* the insertion-order preservation nature of :ref:`dict <typesmapping>` + objects `has been declared`_ to be an official + part of the Python language spec. + +.. _has been declared: https://mail.python.org/pipermail/python-dev/2017-December/151283.html + +Significant improvements in the standard library: + +* The :mod:`asyncio` module has received new features, significant + :ref:`usability and performance improvements <whatsnew37_asyncio>`. + +* The :mod:`time` module gained support for + :ref:`functions with nanosecond resolution <whatsnew37-pep564>`. + +CPython implementation improvements: + +* :ref:`PEP 552 <whatsnew37-pep552>`, deterministic .pycs +* :ref:`PEP 538 <whatsnew37-pep538>`, legacy C locale coercion +* :ref:`PEP 540 <whatsnew37-pep540>`, forced UTF-8 runtime mode +* :ref:`the new development runtime mode <whatsnew37-devmode>` +* :ref:`PEP 565 <whatsnew37-pep565>`, improved :exc:`DeprecationWarning` + handling -.. PEP-sized items next. +C API improvements: +* :ref:`PEP 539 <whatsnew37-pep539>`, new C API for thread-local storage + +Documentation improvements: + +* :ref:`PEP 545 <whatsnew37-pep545>`, Python documentation translations +* New documentation translations: `Japanese <https://docs.python.org/ja/>`_, + `French <https://docs.python.org/fr/>`_, and + `Korean <https://docs.python.org/ko/>`_. + +This release features notable performance improvements in many areas. +The :ref:`whatsnew37-perf` section lists them in detail. + +For a list of changes that may affect compatibility with previous Python +releases please refer to the :ref:`porting-to-python-37` section. New Features ============ +.. _whatsnew37-pep563: + +PEP 563: Postponed Evaluation of Annotations +-------------------------------------------- + +The advent of type hints in Python uncovered two glaring usability issues +with the functionality of annotations added in :pep:`3107` and refined +further in :pep:`526`: + +* annotations could only use names which were already available in the + current scope, in other words they didn't support forward references + of any kind; and + +* annotating source code had adverse effects on startup time of Python + programs. + +Both of these issues are fixed by postponing the evaluation of +annotations. Instead of compiling code which executes expressions in +annotations at their definition time, the compiler stores the annotation +in a string form equivalent to the AST of the expression in question. +If needed, annotations can be resolved at runtime using +:func:`typing.get_type_hints`. In the common case where this is not +required, the annotations are cheaper to store (since short strings +are interned by the interpreter) and make startup time faster. + +Usability-wise, annotations now support forward references, making the +following syntax valid:: + + class C: + @classmethod + def from_string(cls, source: str) -> C: + ... + + def validate_b(self, obj: B) -> bool: + ... + + class B: + ... + +Since this change breaks compatibility, the new behavior needs to be enabled +on a per-module basis in Python 3.7 using a :mod:`__future__` import:: + + from __future__ import annotations + +It will become the default in Python 4.0. + +.. seealso:: + + :pep:`563` -- Postponed evaluation of annotations + PEP written and implemented by ?ukasz Langa. + .. _whatsnew37-pep538: @@ -106,19 +215,46 @@ legacy C locale remains active when the core interpreter is initialized. PEP written and implemented by Nick Coghlan. +.. _whatsnew37-pep540: + +PEP 540: Forced UTF-8 Runtime Mode +----------------------------------- + +The new :option:`-X` ``utf8`` command line option and :envvar:`PYTHONUTF8` +environment variable can be used to enable the CPython *UTF-8 mode*. + +When in UTF-8 mode, CPython ignores the locale settings, and uses the +UTF-8 encoding by default. The error handlers for :data:`sys.stdin` and +:data:`sys.stdout` streams are set to ``surrogateescape``. + +The forced UTF-8 mode can be used to change the text handling behavior in +an embedded Python interpreter without changing the locale settings of +an embedding application. + +The UTF-8 mode is enabled by default when the locale is "C". See +:ref:`whatsnew37-pep538` for details. + +.. seealso:: + + :pep:`540` -- Add a new UTF-8 mode + PEP written and implemented by Victor Stinner + + .. _whatsnew37-pep553: -PEP 553: Built-in breakpoint() ------------------------------- +PEP 553: Built-in ``breakpoint()`` +---------------------------------- -:pep:`553` describes a new built-in called :func:`breakpoint` which makes it -easy and consistent to enter the Python debugger. Built-in ``breakpoint()`` -calls :func:`sys.breakpointhook`. By default, this latter imports :mod:`pdb` and -then calls ``pdb.set_trace()``, but by binding ``sys.breakpointhook()`` to the -function of your choosing, ``breakpoint()`` can enter any debugger. Or, the -environment variable :envvar:`PYTHONBREAKPOINT` can be set to the callable of -your debugger of choice. Set ``PYTHONBREAKPOINT=0`` to completely disable -built-in ``breakpoint()``. +Python 3.7 includes the new built-in :func:`breakpoint` function as +an easy and consistent way to enter the Python debugger. + +Built-in ``breakpoint()`` calls :func:`sys.breakpointhook`. By default, the +latter imports :mod:`pdb` and then calls ``pdb.set_trace()``, but by binding +``sys.breakpointhook()`` to the function of your choosing, ``breakpoint()`` can +enter any debugger. Additionally, the environment variable +:envvar:`PYTHONBREAKPOINT` can be set to the callable of your debugger of +choice. Set ``PYTHONBREAKPOINT=0`` to completely disable built-in +``breakpoint()``. .. seealso:: @@ -128,8 +264,8 @@ built-in ``breakpoint()``. .. _whatsnew37-pep539: -PEP 539: A New C-API for Thread-Local Storage in CPython --------------------------------------------------------- +PEP 539: New C API for Thread-Local Storage +------------------------------------------- While Python provides a C API for thread-local storage support; the existing :ref:`Thread Local Storage (TLS) API <thread-local-storage-api>` has used @@ -158,17 +294,16 @@ effort will be made to add such support. PEP written by Erik M. Bray; implementation by Masayuki Yamamoto. -PEP 562: Customization of access to module attributes +.. _whatsnew37-pep562: + +PEP 562: Customization of Access to Module Attributes ----------------------------------------------------- -It is sometimes convenient to customize or otherwise have control over access -to module attributes. A typical example is managing deprecation warnings. -Typical workarounds are assigning :attr:`~instance.__class__` of a module -object to a custom subclass of :class:`types.ModuleType` or replacing the -:data:`sys.modules` item with a custom wrapper instance. This procedure is -now simplified by recognizing ``__getattr__`` defined directly in a module -that would act like a normal :meth:`__getattr__` method, except that it will -be defined on module *instances*. +Python 3.7 allows defining :meth:`__getattr__` on modules and will call +it whenever a module attribute is otherwise not found. + +A typical example of where this may be useful is module attribute deprecation +and lazy loading. .. seealso:: @@ -176,62 +311,13 @@ be defined on module *instances*. PEP written and implemented by Ivan Levkivskyi -PEP 563: Postponed evaluation of annotations --------------------------------------------- - -The advent of type hints in Python uncovered two glaring usability issues -with the functionality of annotations added in :pep:`3107` and refined -further in :pep:`526`: - -* annotations could only use names which were already available in the - current scope, in other words they didn't support forward references - of any kind; and - -* annotating source code had adverse effects on startup time of Python - programs. - -Both of these issues are fixed by postponing the evaluation of -annotations. Instead of compiling code which executes expressions in -annotations at their definition time, the compiler stores the annotation -in a string form equivalent to the AST of the expression in question. -If needed, annotations can be resolved at runtime using -``typing.get_type_hints()``. In the common case where this is not -required, the annotations are cheaper to store (since short strings -are interned by the interpreter) and make startup time faster. - -Usability-wise, annotations now support forward references, making the -following syntax valid:: - - class C: - @classmethod - def from_string(cls, source: str) -> C: - ... - - def validate_b(self, obj: B) -> bool: - ... - - class B: - ... - -Since this change breaks compatibility, the new behavior can be enabled -on a per-module basis in Python 3.7 using a :mod:`__future__` import, like -this:: - - from __future__ import annotations +.. _whatsnew37-pep564: -It will become the default in Python 4.0. +PEP 564: New Time Functions With Nanosecond Resolution +------------------------------------------------------ -.. seealso:: - - :pep:`563` -- Postponed evaluation of annotations - PEP written and implemented by ?ukasz Langa. - - -PEP 564: Add new time functions with nanosecond resolution ----------------------------------------------------------- - -Add six new "nanosecond" variants of existing functions to the :mod:`time` -module: +:pep:`564` adds six new "nanosecond" variants of existing functions +to the :mod:`time` module: * :func:`time.clock_gettime_ns` * :func:`time.clock_settime_ns` @@ -240,12 +326,12 @@ module: * :func:`time.process_time_ns` * :func:`time.time_ns` -While similar to the existing functions without the ``_ns`` suffix, they -provide nanosecond resolution: they return a number of nanoseconds as a Python -``int``. +The new functions are similar in function to the existing functions +without the ``_ns`` suffix. They differ by returning nanoseconds as +integers instead of fractional seconds. -The ``time.time_ns()`` resolution is 3 times better than the ``time.time()`` -resolution on Linux and Windows. +On Linux and Windows the resolution of :func:`time.time_ns` is 3 times +better than that of :func:`time.time`. .. seealso:: @@ -291,73 +377,10 @@ by breaking changes in the APIs they used. PEP written and implemented by Nick Coghlan -PEP 540: Add a new UTF-8 mode ------------------------------ - -Add a new UTF-8 mode to ignore the locale, use the UTF-8 encoding, and change -:data:`sys.stdin` and :data:`sys.stdout` error handlers to ``surrogateescape``. -This mode is enabled by default in the POSIX locale, but otherwise disabled by -default. - -The new :option:`-X` ``utf8`` command line option and :envvar:`PYTHONUTF8` -environment variable are added to control the UTF-8 mode. - -.. seealso:: - - :pep:`540` -- Add a new UTF-8 mode - PEP written and implemented by Victor Stinner - - -.. _whatsnew37-pep557: - -PEP 557: Data Classes ---------------------- - -Adds a new module :mod:`dataclasses`. It provides a class decorator -:func:`~dataclasses.dataclass` which inspects the class's variable annotations (see -:pep:`526`) and using them, adds methods such as ``__init__``, -``__repr__``, and ``__eq__`` to the class. It is similar to -:class:`typing.NamedTuple`, but also works on classes with mutable -instances, among other features. - -For example:: - - @dataclass - class Point: - x: float - y: float - z: float = 0.0 - - p = Point(1.5, 2.5) - print(p) # produces "Point(x=1.5, y=2.5, z=0.0)" - -.. seealso:: - - :pep:`557` -- Data Classes - PEP written and implemented by Eric V. Smith - - -PEP 567: Context Variables --------------------------- +.. _whatsnew37-pep560: -Adds a new module :mod:`contextvars`, that provides APIs to manage, -store, and access non-local state. - -Context variables are natively supported in :mod:`asyncio` and are -ready to be used without any extra configuration. - -The :mod:`decimal` module was updated to use *contextvars* to store -the current decimal context. This allows decimal operations to work -with the correct context in async/await code. - -.. seealso:: - - :pep:`567` -- Context Variables - PEP written and implemented by Yury Selivanov - - -PEP 560: Core support for typing module and generic types ---------------------------------------------------------- +PEP 560: Core Support for ``typing`` module and Generic Types +------------------------------------------------------------- Initially :pep:`484` was designed in such way that it would not introduce *any* changes to the core CPython interpreter. Now type hints and the :mod:`typing` @@ -375,17 +398,23 @@ fixed. PEP written and implemented by Ivan Levkivskyi -New Development Mode: -X dev ----------------------------- +.. _whatsnew37-devmode: -Add a new "development mode": :option:`-X` ``dev`` command line option and -:envvar:`PYTHONDEVMODE` environment variable to enable CPython's "development -mode", introducing additional runtime checks which are too expensive to be -enabled by default. See :option:`-X` ``dev`` documentation for the effects of -the development mode. +Development Runtime Mode: -X dev +-------------------------------- + +The new :option:`-X` ``dev`` command line option or the new +:envvar:`PYTHONDEVMODE` environment variable can be used to enable +CPython's *development mode*. When in development mode, CPython performs +additional runtime checks which are too expensive to be enabled by default. +See :option:`-X` ``dev`` documentation for the full description of the effects +of this mode. -Hash-based pycs ---------------- + +.. _whatsnew37-pep552: + +PEP 552: Hash-based .pyc Files +------------------------------ Python has traditionally checked the up-to-dateness of bytecode cache files (i.e., ``.pyc`` files) by comparing the source metadata (last-modified timestamp @@ -412,6 +441,27 @@ keeping ``.pyc`` files up-to-date. See :ref:`pyc-invalidation` for more information. +.. _whatsnew37-pep545: + +PEP 545: Python Documentation Translations +------------------------------------------ + +:pep:`545` describes the process of creating and maintaining Python +documentation translations. + +Three new translations have been added: + +- Japanese: https://docs.python.org/ja/ +- French: https://docs.python.org/fr/ +- Korean: https://docs.python.org/ko/ + +.. seealso:: + + :pep:`545` -- Python Documentation Translations + PEP written and implemented by Julien Palard, Inada Naoki, and + Victor Stinner. + + Other Language Changes ====================== @@ -422,6 +472,11 @@ Other Language Changes * :meth:`bytes.fromhex` and :meth:`bytearray.fromhex` now ignore all ASCII whitespace, not only spaces. (Contributed by Robert Xiao in :issue:`28927`.) +* :class:`str`, :class:`bytes`, and :class:`bytearray` gained support for + the new :meth:`isascii() <str.isascii>` method, which can be used to + test if a string or bytes contain only the ASCII characters. + (Contributed by INADA Naoki in :issue:`32677`.) + * :exc:`ImportError` now displays module name and module ``__file__`` path when ``from ... import ...`` fails. (Contributed by Matthias Bussonnier in :issue:`29546`.) @@ -446,22 +501,83 @@ Other Language Changes time when an import occurs) (Contributed by Nick Coghlan in :issue:`33053`.) +* The new :option:`-X` ``importtime`` option or the + :envvar:`PYTHONPROFILEIMPORTTIME` environment variable can be used to show + the timing of each module import. + (Contributed by Victor Stinner in :issue:`31415`.) + New Modules =========== +.. _whatsnew37-pep567: + +contextvars +----------- + +The new :mod:`contextvars` module and a set of new C APIs introduce +support for *context variables*. Context variables are conceptually +similar to thread-local variables. Unlike TLS, context variables +support asynchronous code correctly. + +The :mod:`asyncio` and :mod:`decimal` modules have been updated to use +and support context variables out of the box. Particularly the active +decimal context is now stored in a context variable, which allows +decimal operations to work with the correct context in asynchronous code. + +.. seealso:: + + :pep:`567` -- Context Variables + PEP written and implemented by Yury Selivanov + + +.. _whatsnew37-pep557: + +dataclasses +----------- + +The new :func:`~dataclasses.dataclass` decorator provides a way to declare +*data classes*. A data class describes its attributes using class variable +annotations. Its constructor and other magic methods, such as +:meth:`~object.__repr__`, :meth:`~object.__eq__`, and +:meth:`~object.__hash__` are generated automatically. + +Example:: + + @dataclass + class Point: + x: float + y: float + z: float = 0.0 + + p = Point(1.5, 2.5) + print(p) # produces "Point(x=1.5, y=2.5, z=0.0)" + +.. seealso:: + + :pep:`557` -- Data Classes + PEP written and implemented by Eric V. Smith + + +.. _whatsnew37_importlib_resources: + importlib.resources ------------------- -This module provides several new APIs and one new ABC for access to, opening, -and reading *resources* inside packages. Resources are roughly akin to files -inside of packages, but they needn't be actual files on the physical file -system. Module loaders can provide a :meth:`get_resource_reader()` function -which returns a :class:`importlib.abc.ResourceReader` instance to support this +The new :mod:`importlib.resources` module provides several new APIs and one +new ABC for access to, opening, and reading *resources* inside packages. +Resources are roughly similar to files inside packages, but they needn't +be actual files on the physical file system. Module loaders can provide a +:meth:`get_resource_reader()` function which returns +a :class:`importlib.abc.ResourceReader` instance to support this new API. Built-in file path loaders and zip file loaders both support this. -(see the PyPI package -`importlib_resources <http://importlib-resources.readthedocs.io/en/latest/>`_ -as a compatible back port for older Python versions). + +Contributed by Barry Warsaw and Brett Cannon in :issue:`32248`. + +.. seealso:: + + `importlib_resources <http://importlib-resources.readthedocs.io/en/latest/>`_ + -- a PyPI backport for earlier Python versions. Improved Modules @@ -471,10 +587,143 @@ Improved Modules argparse -------- -The :meth:`~argparse.ArgumentParser.parse_intermixed_args` supports letting -the user intermix options and positional arguments on the command line, -as is possible in many unix commands. It supports most but not all -argparse features. (Contributed by paul.j3 in :issue:`14191`.) +The new :meth:`ArgumentParser.parse_intermixed_args() +<argparse.ArgumentParser.parse_intermixed_args>` +method allows intermixing options and positional arguments. +(Contributed by paul.j3 in :issue:`14191`.) + + +.. _whatsnew37_asyncio: + +asyncio +------- + +The :mod:`asyncio` module has received many new features, usability and +:ref:`performance improvements <whatsnew37-asyncio-perf>`. Notable changes +include: + +* The new :term:`provisional <provisional api>` :func:`asyncio.run` function can + be used to run a coroutine from synchronous code by automatically creating and + destroying the event loop. + (Contributed by Yury Selivanov in :issue:`32314`.) + +* The new :func:`asyncio.create_task` function has been added as a shortcut + to ``asyncio.get_event_loop().create_task()``. + (Contributed by Andrew Svetlov in :issue:`32311`.) + +* The new :meth:`loop.start_tls() <asyncio.AbstractEventLoop.start_tls>` + method can be used to upgrade an existing connection to TLS. + (Contributed by Yury Selivanov in :issue:`23749`.) + +* The new :meth:`loop.sock_recv_into() <asyncio.AbstractEventLoop.sock_recv_into>` + method allows reading data from a socket directly into a provided buffer making + it possible to reduce data copies. + (Contributed by Antoine Pitrou in :issue:`31819`.) + +* The new :func:`asyncio.current_task` function returns the currently running + :class:`~asyncio.Task` instance, and the new :func:`asyncio.all_tasks` + function returns a set of all existing ``Task`` instances in a given loop. + The :meth:`Task.current_task() <asyncio.Task.current_task>` and + :meth:`Task.all_tasks() <asyncio.Task.all_tasks>` methods have been deprecated. + (Contributed by Andrew Svetlov in :issue:`32250`.) + +* The new *provisional* :class:`~asyncio.BufferedProtocol` class allows + implementing streaming protocols with manual control over the receive buffer. + (Contributed by Yury Selivanov in :issue:`32251`.) + +* The new :func:`asyncio.get_running_loop` function returns the currently + running loop, and raises a :exc:`RuntimeError` if no loop is running. + This is in contrast with :func:`asyncio.get_event_loop`, which will *create* + a new event loop if none is running. + (Contributed by Yury Selivanov in :issue:`32269`.) + +* The new :meth:`StreamWriter.wait_closed() <asyncio.StreamWriter.wait_closed>` + coroutine method allows waiting until the stream writer is closed. The new + :meth:`StreamWriter.is_closing() <asyncio.StreamWriter.is_closing>` method + can be used to determine if the writer is closing. + (Contributed by Andrew Svetlov in :issue:`32391`.) + +* The new :meth:`loop.sock_sendfile() <asyncio.AbstractEventLoop.sock_sendfile>` + coroutine method allows sending files using :mod:`os.sendfile` when possible. + (Contributed by Andrew Svetlov in :issue:`32410`.) + +* The new :meth:`Task.get_loop() <asyncio.Task.get_loop>` and + :meth:`Future.get_loop() <asyncio.Future.get_loop>` methods + return the instance of the loop on which a task or a future were created. + :meth:`Server.get_loop() <asyncio.Server.get_loop>` allows doing the same for + :class:`asyncio.Server` objects. + (Contributed by Yury Selivanov in :issue:`32415` and + Srinivas Reddy Thatiparthy in :issue:`32418`.) + +* It is now possible to control how instances of :class:`asyncio.Server` begin + serving. Previously, the server would start serving immediately when created. + The new *start_serving* keyword argument to + :meth:`loop.create_server() <asyncio.AbstractEventLoop.create_server>` and + :meth:`loop.create_unix_server() <asyncio.AbstractEventLoop.create_unix_server>`, + as well as :meth:`Server.start_serving() <asyncio.Server.start_serving>`, and + :meth:`Server.serve_forever() <asyncio.Server.serve_forever>` + can be used to decouple server instantiation and serving. The new + :meth:`Server.is_serving() <asyncio.Server.is_serving>` method returns ``True`` + if the server is serving. :class:`~asyncio.Server` objects are now + asynchronous context managers:: + + srv = await loop.create_server(...) + + async with srv: + # some code + + # At this point, srv is closed and no longer accepts new connections. + + (Contributed by Yury Selivanov in :issue:`32662`.) + +* Callback objects returned by + :func:`loop.call_later() <asyncio.AbstractEventLoop.call_later>` + gained the new :meth:`when() <asyncio.TimerHandle.when>` method which + returns an absolute scheduled callback timestamp. + (Contributed by Andrew Svetlov in :issue:`32741`.) + +* The :meth:`loop.create_datagram_endpoint() \ + <asyncio.AbstractEventLoop.create_datagram_endpoint>` method + gained support for Unix sockets. + (Contributed by Quentin Dawans in :issue:`31245`.) + +* The :meth:`loop.create_connection() <asyncio.AbstractEventLoop.create_connection>`, + :meth:`loop.create_server() <asyncio.AbstractEventLoop.create_server>`, + :meth:`loop.create_unix_server() <asyncio.AbstractEventLoop.create_unix_server>`, and + :meth:`loop.create_accepted_socket() <asyncio.BaseEventLoop.connect_accepted_socket>` + now accept the *ssl_handshake_timeout* keyword argument. + (Contributed by Neil Aspinall in :issue:`29970`.) + +* The new :meth:`Handle.cancelled() <asyncio.Handle.cancelled>` method returns + ``True`` if the callback was cancelled. + (Contributed by Marat Sharafutdinov in :issue:`31943`.) + +* The asyncio source has been converted to use the + :keyword:`async`/:keyword:`await` syntax. + (Contributed by Andrew Svetlov in :issue:`32193`.) + +* The new :meth:`ReadTransport.is_reading() <asyncio.ReadTransport.is_reading>` + method can be used to determine the reading state of the transport. + Additionally, calls to + :meth:`ReadTransport.resume_reading() <asyncio.ReadTransport.resume_reading>` + and :meth:`ReadTransport.pause_reading() <asyncio.ReadTransport.pause_reading>` + are now idempotent. + (Contributed by Yury Selivanov in :issue:`32356`.) + +* Loop methods which accept socket paths now support passing + :term:`path-like objects <path-like object>`. + (Contributed by Yury Selivanov in :issue:`32066`.) + +* In :mod:`asyncio` TCP sockets on Linux are now created with ``TCP_NODELAY`` + flag set by default. + (Contributed by Yury Selivanov and Victor Stinner in :issue:`27456`.) + +* Exceptions occurring in cancelled tasks are no longer logged. + (Contributed by Yury Selivanov in :issue:`30508`.) + +Several ``asyncio`` APIs have been +:ref:`deprecated <whatsnew37-asyncio-deprecated>`. + binascii -------- @@ -483,54 +732,116 @@ The :func:`~binascii.b2a_uu` function now accepts an optional *backtick* keyword argument. When it's true, zeros are represented by ``'`'`` instead of spaces. (Contributed by Xiang Zhang in :issue:`30103`.) + calendar -------- -The class :class:`~calendar.HTMLCalendar` has new class attributes which ease -the customisation of the CSS classes in the produced HTML calendar. +The :class:`~calendar.HTMLCalendar` class has new class attributes which ease +the customization of CSS classes in the produced HTML calendar. (Contributed by Oz Tiram in :issue:`30095`.) + +collections +----------- + +``collections.namedtuple()`` now supports default values. +(Contributed by Raymond Hettinger in :issue:`32320`.) + + +compileall +---------- + +:func:`compileall.compile_dir` learned the new *invalidation_mode* parameter, +which can be used to enable +:ref:`hash-based .pyc invalidation <whatsnew37-pep552>`. The invalidation +mode can also be specified on the command line using the new +``--invalidation-mode`` argument. +(Contributed by Benjamin Peterson in :issue:`31650`.) + + +concurrent.futures +------------------ + +:class:`ProcessPoolExecutor <concurrent.futures.ProcessPoolExecutor>` and +:class:`ThreadPoolExecutor <concurrent.futures.ThreadPoolExecutor>` now +support the new *initializer* and *initargs* constructor arguments. +(Contributed by Antoine Pitrou in :issue:`21423`.) + +The :class:`ProcessPoolExecutor <concurrent.futures.ProcessPoolExecutor>` +can now take the multiprocessing context via the new *mp_context* argument. +(Contributed by Thomas Moreau in :issue:`31540`.) + + contextlib ---------- -:func:`~contextlib.asynccontextmanager` and -:class:`~contextlib.AbstractAsyncContextManager` have been added. (Contributed -by Jelle Zijlstra in :issue:`29679` and :issue:`30241`.) +The new :func:`~contextlib.nullcontext` is a simpler and faster no-op +context manager than :class:`~contextlib.ExitStack`. +(Contributed by Jesse-Bakker in :issue:`10049`.) + +The new :func:`~contextlib.asynccontextmanager`, +:class:`~contextlib.AbstractAsyncContextManager`, and +:class:`~contextlib.AsyncExitStack` have been added to +complement their synchronous counterparts. (Contributed +by Jelle Zijlstra in :issue:`29679` and :issue:`30241`, +and by Alexander Mohr and Ilya Kulakov in :issue:`29302`.) -:class:`contextlib.AsyncExitStack` has been added. (Contributed by -Alexander Mohr and Ilya Kulakov in :issue:`29302`.) cProfile -------- -:mod:`cProfile` command line now accepts ``-m module_name`` as an alternative -to script path. (Contributed by Sanyam Khurana in :issue:`21862`.) +The :mod:`cProfile` command line now accepts ``-m module_name`` as an +alternative to script path. (Contributed by Sanyam Khurana in :issue:`21862`.) + crypt ----- -Added support for the Blowfish method. +The :mod:`crypt` module now supports the Blowfish hashing method. (Contributed by Serhiy Storchaka in :issue:`31664`.) -The :func:`~crypt.mksalt` function now allows to specify the number of rounds +The :func:`~crypt.mksalt` function now allows specifying the number of rounds for hashing. (Contributed by Serhiy Storchaka in :issue:`31702`.) + datetime -------- -Added the :meth:`datetime.fromisoformat <datetime.datetime.fromisoformat>` -method, which constructs a :class:`~datetime.datetime` object from a string +The new :meth:`datetime.fromisoformat() <datetime.datetime.fromisoformat>` +method constructs a :class:`~datetime.datetime` object from a string in one of the formats output by -:meth:`datetime.isoformat <datetime.datetime.isoformat>`. +:meth:`datetime.isoformat() <datetime.datetime.isoformat>`. (Contributed by Paul Ganssle in :issue:`15873`.) +The :class:`tzinfo <datetime.tzinfo>` class now supports sub-minute offsets. +(Contributed by Alexander Belopolsky in :issue:`5288`.) + + +dbm +--- + +:mod:`dbm.dumb` now supports reading read-only files and no longer writes the +index file when it is not changed. + + +decimal +------- + +The :mod:`decimal` module now uses :ref:`context variables <whatsnew37-pep567>` +to store the decimal context. +(Contributed by Yury Selivanov in :issue:`32630`.) + + dis --- -The :func:`~dis.dis` function now is able to +The :func:`~dis.dis` function is now able to disassemble nested code objects (the code of comprehensions, generator expressions and nested functions, and the code used for building nested -classes). (Contributed by Serhiy Storchaka in :issue:`11822`.) +classes). The maximum depth of disassembly recursion is controlled by +the new *depth* parameter. +(Contributed by Serhiy Storchaka in :issue:`11822`.) + distutils --------- @@ -539,93 +850,244 @@ distutils therefore included in source distributions. (Contributed by Ryan Gonzalez in :issue:`11913`.) -:class:`distutils.core.setup` now warns if the ``classifiers``, ``keywords`` -and ``platforms`` fields are not specified as a list or a string. -(Contributed by Berker Peksag in :issue:`19610`.) -The ``upload`` command no longer tries to change CR end-of-line characters -to CRLF. This fixes a corruption issue with sdists that ended with a byte -equivalent to CR. -(Contributed by Bo Bayles in :issue:`32304`.) +enum +---- + +The :class:`Enum <enum.Enum>` learned the new ``_ignore_`` class property, +which allows listing the names of properties which should not become +enum members. +(Contributed by Ethan Furman in :issue:`31801`.) + +In Python 3.8, attempting to check for non-Enum objects in :class:`Enum` +classes will raise a :exc:`TypeError` (e.g. ``1 in Color``); similarly, +attempting to check for non-Flag objects in a :class:`Flag` member will +raise :exc:`TypeError` (e.g. ``1 in Perm.RW``); currently, both operations +return :const:`False` instead and are deprecated. +(Contributed by Ethan Furman in :issue:`33217`.) + + +functools +--------- + +:func:`functools.singledispatch` now supports registering implementations +using type annotations. +(Contributed by ?ukasz Langa in :issue:`32227`.) + + +gc +-- + +The new :func:`gc.freeze` function allows freezing all objects tracked +by the garbage collector and excluding them from future collections. +This can be used before a POSIX ``fork()`` call to make the GC copy-on-write +friendly or to speed up collection. The new :func:`gc.unfreeze` functions +reverses this operation. Additionally, :func:`gc.get_freeze_count` can +be used to obtain the number of frozen objects. +(Contributed by Li Zekun in :issue:`31558`.) + + +hmac +---- + +The :mod:`hmac` module now has an optimized one-shot :func:`~hmac.digest` +function, which is up to three times faster than :func:`~hmac.HMAC`. +(Contributed by Christian Heimes in :issue:`32433`.) + + +http.client +----------- + +:class:`~http.client.HTTPConnection` and :class:`~http.client.HTTPSConnection` +now support the new *blocksize* argument for improved upload throughput. +(Contributed by Nir Soffer in :issue:`31945`.) + + +http.server +----------- + +:class:`~http.server.SimpleHTTPRequestHandler` now supports the HTTP +``If-Modified-Since`` header. The server returns the 304 response status if +the target file was not modified after the time specified in the header. +(Contributed by Pierre Quentel in :issue:`29654`.) + +:class:`~http.server.SimpleHTTPRequestHandler` accepts the new *directory* +argument, in addition to the new ``--directory`` command line argument. +With this parameter, the server serves the specified directory, by default it +uses the current working directory. +(Contributed by St?phane Wirtel and Julien Palard in :issue:`28707`.) + +The new :class:`ThreadedHTTPServer <http.server.ThreadedHTTPServer>` class +uses threads to handle requests using :class:`~socketserver.ThreadingMixin`. +It is used when ``http.server`` is run with ``-m``. +(Contributed by Julien Palard in :issue:`31639`.) + + +importlib +--------- + +The :class:`importlib.abc.ResourceReader` ABC was introduced to +support the loading of resources from packages. See also +:ref:`whatsnew37_importlib_resources`. +(Contributed by Barry Warsaw, Brett Cannon in :issue:`32248`.) + +:func:`importlib.reload` now raises :exc:`ModuleNotFoundError` if the module +lacks a spec. +(Contributed by Garvit Khatri in :issue:`29851`.) + +:func:`importlib.find_spec` now raises ``ModuleNotFoundError`` instead of +:exc:`AttributeError` if the specified parent module is not a package (i.e. +lacks a ``__path__`` attribute). +(Contributed by Milan Oberkirch in :issue:`30436`.) + +The new :func:`importlib.source_hash` can be used to compute the hash of +the passed source. A :ref:`hash-based .pyc file <whatsnew37-pep552>` +embeds the value returned by this function. + + +io +-- + +The new :meth:`TextIOWrapper.reconfigure() <io.TextIOWrapper.reconfigure>` +method can be used to reconfigure the text stream with the new settings. +(Contributed by Antoine Pitrou in :issue:`30526` and +INADA Naoki in :issue:`15216`.) + + +ipaddress +--------- + +The new ``subnet_of()`` and ``supernet_of()`` methods of +:class:`ipaddress.IPv6Network` and :class:`ipaddress.IPv4Network` can +be used for network containment tests. +(Contributed by Michel Albert and Cheryl Sabella in :issue:`20825`.) + + +itertools +--------- + +:func:`itertools.islice` now accepts +:meth:`integer-like objects <object.__index__>` as start, stop, +and slice arguments. +(Contributed by Will Roberts in :issue:`30537`.) + + +locale +------ + +The new *monetary* argument to :func:`locale.format_string` can be used +to make the conversion use monetary thousands separators and +grouping strings. (Contributed by Garvit in :issue:`10379`.) + +The :func:`locale.getpreferredencoding` function now always returns ``'UTF-8'`` +on Android or when in the :ref:`forced UTF-8 mode <whatsnew37-pep540>`. + -http.client ------------ +logging +------- -Add configurable *blocksize* to :class:`~http.client.HTTPConnection` and -:class:`~http.client.HTTPSConnection` for improved upload throughput. -(Contributed by Nir Soffer in :issue:`31945`.) +:class:`~logging.Logger` instances can now be pickled. +(Contributed by Vinay Sajip in :issue:`30520`.) -http.server ------------ +The new :meth:`StreamHandler.setStream() <logging.StreamHandler.setStream>` +method can be used to replace the logger stream after handler creation. +(Contributed by Vinay Sajip in :issue:`30522`.) -:class:`~http.server.SimpleHTTPRequestHandler` supports the HTTP -``If-Modified-Since`` header. The server returns the 304 response status if the -target file was not modified after the time specified in the header. -(Contributed by Pierre Quentel in :issue:`29654`.) +It is now possible to specify keyword arguments to handler constructors in +configuration passed to :func:`logging.config.fileConfig`. +(Contributed by Preston Landers in :issue:`31080`.) -Add the parameter *directory* to the :class:`~http.server.SimpleHTTPRequestHandler` -and the ``--directory`` to the command line of the module :mod:`http.server`. -With this parameter, the server serves the specified directory, by default it -uses the current working directory. -(Contributed by St?phane Wirtel and Julien Palard in :issue:`28707`.) -hmac +math ---- -The :mod:`hmac` module now has an optimized one-shot :func:`~hmac.digest` -function, which is up to three times faster than :func:`~hmac.HMAC`. -(Contributed by Christian Heimes in :issue:`32433`.) +The new :func:`math.remainder` function implements the IEEE 754-style remainder +operation. (Contributed by Mark Dickinson in :issue:`29962`.) -importlib + +mimetypes --------- -The :class:`importlib.abc.ResourceReader` ABC was introduced to -support the loading of resources from packages. +The MIME type of .bmp has been changed from ``'image/x-ms-bmp'`` to +``'image/bmp'``. +(Contributed by Nitish Chandra in :issue:`22589`.) -locale + +msilib ------ -Added another argument *monetary* in :func:`~locale.format_string` of :mod:`locale`. -If *monetary* is true, the conversion uses monetary thousands separator and -grouping strings. (Contributed by Garvit in :issue:`10379`.) +The new :meth:`Database.Close() <msilib.Database.Close>` method can be used +to close the :abbr:`MSI` database. +(Contributed by Berker Peksag in :issue:`20486`.) -The :func:`~locale.getpreferredencoding` function now always returns ``'UTF-8'`` -on Android or in the UTF-8 mode (:option:`-X` ``utf8`` option), the locale and -the *do_setlocale* argument are ignored. -math ----- +multiprocessing +--------------- + +The new :meth:`Process.close() <multiprocessing.Process.close>` method +explicitly closes the process object and releases all resources associated +with it. :exc:`ValueError` is raised if the underlying process is still +running. +(Contributed by Antoine Pitrou in :issue:`30596`.) + +The new :meth:`Process.kill() <multiprocessing.Process.kill>` method can +be used to terminate the process using the :data:`SIGKILL` signal on Unix. +(Contributed by Vitor Pereira in :issue:`30794`.) + +Non-daemonic threads created by :class:`~multiprocessing.Process` are now +joined on process exit. +(Contributed by Antoine Pitrou in :issue:`18966`.) -New :func:`~math.remainder` function, implementing the IEEE 754-style remainder -operation. (Contributed by Mark Dickinson in :issue:`29962`.) os -- -Added support for :class:`bytes` paths in :func:`~os.fwalk`. (Contributed by -Serhiy Storchaka in :issue:`28682`.) +:func:`os.fwalk` now accepts the *path* argument as :class:`bytes`. +(Contributed by Serhiy Storchaka in :issue:`28682`.) -Added support for :ref:`file descriptors <path_fd>` in :func:`~os.scandir` -on Unix. (Contributed by Serhiy Storchaka in :issue:`25996`.) +:func:`os.scandir` gained support for :ref:`file descriptors <path_fd>`. +(Contributed by Serhiy Storchaka in :issue:`25996`.) + +The new :func:`~os.register_at_fork` function allows registering Python +callbacks to be executed at process fork. +(Contributed by Antoine Pitrou in :issue:`16500`.) + +Exposed the *preadv*, *preadv2*, *pwritev* and *pwritev2* system calls through +the new :func:`~os.preadv` and :func:`~os.pwritev` functions. +(Contributed by Pablo Galindo in :issue:`31368`.) + +The mode argument of :func:`os.makedirs` no longer affects the file +permission bits of newly-created intermediate-level directories. +(Contributed by Serhiy Storchaka in :issue:`19930`.) + +:func:`os.dup2` now returns the new file descriptor. Previously, ``None`` +was always returned. +(Contributed by Benjamin Peterson in :issue:`32441`.) + +The structure returned by :func:`os.stat` now contains the +:attr:`~os.stat_result.st_fstype` attribute on Solaris and its derivatives. +(Contributed by Jes?s Cea Avi?n in :issue:`32659`.) -New function :func:`~os.register_at_fork` allows registering Python callbacks -to be executed on a process fork. (Contributed by Antoine Pitrou in -:issue:`16500`.) -Exposed the system calls *preadv*, *preadv2*, *pwritev* and *pwritev2* through -the new functions :func:`~os.preadv` and :func:`~os.pwritev`. (Contributed by -Pablo Galindo in :issue:`31368`.) +pathlib +------- + +The new :meth:`Path.is_mount() <pathlib.Path.is_mount>` method is now available +on POSIX systems and can be used to determine whether a path is a mount point. +(Contributed by Cooper Ry Lees in :issue:`30897`.) + pdb --- -:func:`~pdb.set_trace` now takes an optional *header* keyword-only -argument. If given, this is printed to the console just before debugging +:func:`pdb.set_trace` now takes an optional *header* keyword-only +argument. If given, it is printed to the console just before debugging begins. (Contributed by Barry Warsaw in :issue:`31389`.) :mod:`pdb` command line now accepts ``-m module_name`` as an alternative to script file. (Contributed by Mario Corchero in :issue:`32206`.) + py_compile ---------- @@ -637,6 +1099,22 @@ This allows for guaranteeing files when they are created eagerly. (Contributed by Bernhard M. Wiedemann in :issue:`29708`.) + +pydoc +----- + +The pydoc server can now bind to an arbitrary hostname specified by the +new ``-n`` command-line argument. +(Contributed by Feanil Patel in :issue:`31128`.) + + +queue +----- + +The new :class:`~queue.SimpleQueue` class is an unbounded :abbr:`FIFO` queue. +(Contributed by Antoine Pitrou in :issue:`14976`.) + + re -- @@ -648,70 +1126,128 @@ can be set within the scope of a group. ``'^$'`` or ``(?=-)`` that matches an empty string. (Contributed by Serhiy Storchaka in :issue:`25054`.) +Regular expressions compiled with the :const:`re.LOCALE` flag no longer +depend on the locale at compile time. Locale settings are applied only +when the compiled regular expression is used. +(Contributed by Serhiy Storchaka in :issue:`30215`.) + +:exc:`FutureWarning` is now emitted if a regular expression contains +character set constructs that will change semantically in the future, +such as nested sets and set operations. +(Contributed by Serhiy Storchaka in :issue:`30349`.) + +Compiled regular expression and match objects can now be copied +using :func:`copy.copy` and :func:`copy.deepcopy`. +(Contributed by Serhiy Storchaka in :issue:`10076`.) + + +signal +------ + +The new *warn_on_full_buffer* argument to the :func:`signal.set_wakeup_fd` +function makes it possible to specify whether Python prints a warning on +stderr when the wakeup buffer overflows. +(Contributed by Nathaniel J. Smith in :issue:`30050`.) + + +socket +------ + +The new :func:`socket.getblocking() <socket.socket.getblocking>` method +returns ``True`` if the socket is in blocking mode and ``False`` otherwise. +(Contributed by Yury Selivanov in :issue:`32373`.) + +The new :func:`socket.close` function closes the passed socket file descriptor. +This function should be used instead of :func:`os.close` for better +compatibility across platforms. +(Contributed by Christian Heimes in :issue:`32454`.) + +The :mod:`socket` module now exposes the :data:`socket.TCP_CONGESTION` +(Linux 2.6.13), :data:`socket.TCP_USER_TIMEOUT` (Linux 2.6.37), and +:data:`socket.TCP_NOTSENT_LOWAT` (Linux 3.12) constants. +(Contributed by Omar Sandoval in :issue:`26273` and +Nathaniel J. Smith in :issue:`29728`.) + +Support for :data:`socket.AF_VSOCK` sockets has been added to allow +communication between virtual machines and their hosts. +(Contributed by Cathy Avery in :issue:`27584`.) + +Sockets now auto-detect family, type and protocol from file descriptor +by default. +(Contributed by Christian Heimes in :issue:`28134`.) + sqlite3 ------- -:class:`sqlite3.Connection` now exposes a :class:`~sqlite3.Connection.backup` -method, if the underlying SQLite library is at version 3.6.11 or higher. +:class:`sqlite3.Connection` now exposes the :meth:`~sqlite3.Connection.backup` +method when the underlying SQLite library is at version 3.6.11 or higher. (Contributed by Lele Gaifax in :issue:`27645`.) +The *database* argument of :func:`sqlite3.connect` now accepts any +:term:`path-like object`, instead of just a string. +(Contributed by Anders Lorentsen in :issue:`31843`.) + ssl --- The :mod:`ssl` module now uses OpenSSL's builtin API instead of -:func:`~ssl.match_hostname` to check host name or IP address. Values -are validated during TLS handshake. Any cert validation error including -a failing host name match now raises :exc:`~ssl.SSLCertVerificationError` and -aborts the handshake with a proper TLS Alert message. The new exception -contains additional information. Host name validation can be customized -with :attr:`~ssl.SSLContext.host_flags`. +:func:`~ssl.match_hostname` to check a host name or an IP address. Values +are validated during TLS handshake. Any certificate validation error +including failing the host name check now raises +:exc:`~ssl.SSLCertVerificationError` and aborts the handshake with a proper +TLS Alert message. The new exception contains additional information. +Host name validation can be customized with +:attr:`SSLContext.host_flags <ssl.SSLContext.host_flags>`. (Contributed by Christian Heimes in :issue:`31399`.) .. note:: - The improved host name check requires an OpenSSL 1.0.2 or 1.1 compatible - libssl. OpenSSL 0.9.8 and 1.0.1 are no longer supported. LibreSSL is - temporarily not supported until it gains the necessary OpenSSL 1.0.2 APIs. + The improved host name check requires a *libssl* implementation compatible + with OpenSSL 1.0.2 or 1.1. Consequently, OpenSSL 0.9.8 and 1.0.1 are no + longer supported and LibreSSL is temporarily not supported until it gains + the necessary OpenSSL 1.0.2 APIs. -The ssl module no longer sends IP addresses in SNI TLS extension. +The ``ssl`` module no longer sends IP addresses in SNI TLS extension. (Contributed by Christian Heimes in :issue:`32185`.) :func:`~ssl.match_hostname` no longer supports partial wildcards like -``www*.example.org``. :attr:`~ssl.SSLContext.host_flags` has partial -wildcard matching disabled by default. +``www*.example.org``. :attr:`SSLContext.host_flags <ssl.SSLContext.host_flags>` +has partial wildcard matching disabled by default. (Contributed by Mandeep Singh in :issue:`23033` and Christian Heimes in :issue:`31399`.) -The default cipher suite selection of the ssl module now uses a blacklist -approach rather than a hard-coded whitelist. Python no longer re-enables -ciphers that have been blocked by OpenSSL security update. Default cipher -suite selection can be configured on compile time. +The default cipher suite selection of the ``ssl`` module now uses a blacklist +approach rather than a hard-coded whitelist. Python no longer re-enables +ciphers that have been blocked by OpenSSL security updates. Default cipher +suite selection can be configured at compile time. (Contributed by Christian Heimes in :issue:`31429`.) -Added support for validating server certificates containing -internationalized domain names (IDNs). As part of this change, the -:attr:`ssl.SSLSocket.server_hostname` attribute now stores the -expected hostname in A-label form (``"xn--pythn-mua.org"``), rather -than the U-label form (``"pyth?n.org"``). (Contributed by +Validation of server certificates containing internationalized domain names +(IDNs) is now supported. As part of this change, the +:attr:`SSLSocket.server_hostname <ssl.SSLSocket.server_hostname>` attribute +now stores the expected hostname in A-label form (``"xn--pythn-mua.org"``), +rather than the U-label form (``"pyth?n.org"``). (Contributed by Nathaniel J. Smith and Christian Heimes in :issue:`28414`.) -The ssl module has preliminary and experimental support for TLS 1.3 and -OpenSSL 1.1.1. (Contributed by Christian Heimes in :issue:`32947`, +The ``ssl`` module has preliminary and experimental support for TLS 1.3 and +OpenSSL 1.1.1. (Contributed by Christian Heimes in :issue:`32947`, :issue:`20995`, :issue:`29136`, and :issue:`30622`) :class:`~ssl.SSLSocket` and :class:`~ssl.SSLObject` no longer have a public -constructor. Direct instantiation was never a documented and supported -feature. Instances must be created with :class:`~ssl.SSLContext` methods +constructor. Direct instantiation was never a documented and supported +feature. Instances must be created with :class:`~ssl.SSLContext` methods :meth:`~ssl.SSLContext.wrap_socket` and :meth:`~ssl.SSLContext.wrap_bio`. (Contributed by Christian Heimes in :issue:`32951`) OpenSSL 1.1 APIs for setting the minimum and maximum TLS protocol version are -available as :attr:`~ssl.SSLContext.minimum_version` and -:attr:`~ssl.SSLContext.maximum_version`. Supported protocols are indicated -by new flags like :data:`~ssl.HAS_TLSv1_1`. +available as :attr:`SSLContext.minimum_version <ssl.SSLContext.minimum_version>` +and :attr:`SSLContext.maximum_version <ssl.SSLContext.maximum_version>`. +Supported protocols are indicated by serveral new flags, such as +:data:`~ssl.HAS_TLSv1_1`. (Contributed by Christian Heimes in :issue:`32609`.) + string ------ @@ -719,32 +1255,61 @@ string expression pattern for braced placeholders and non-braced placeholders separately. (Contributed by Barry Warsaw in :issue:`1198569`.) + subprocess ---------- +The :func:`subprocess.run` function accepts the new *capture_output* +keyword argument. When true, stdout and stderr will be captured. +This is equivalent to passing :data:`subprocess.PIPE` as *stdout* and +*stderr* arguments. +(Contributed by Bo Bayles in :issue:`32102`.) + +The ``subprocess.run`` function and the :class:`subprocess.Popen` constructor +now accept the *text* keyword argument as an alias +to *universal_newlines*. +(Contributed by Andrew Clegg in :issue:`31756`.) + On Windows the default for *close_fds* was changed from ``False`` to ``True`` when redirecting the standard handles. It's now possible to set -*close_fds* to ``True`` when redirecting the standard handles. See -:class:`subprocess.Popen`. +*close_fds* to true when redirecting the standard handles. See +:class:`subprocess.Popen`. This means that *close_fds* now defaults to +``True`` on all supported platforms. +(Contributed by Segev Finer in :issue:`19764`.) + +The subprocess module is now more graceful when handling +:exc:`KeyboardInterrupt` during :func:`subprocess.call`, +:func:`subprocess.run`, or in a :class:`~subprocess.Popen` +context manager. It now waits a short amount of time for the child +to exit, before continuing the handling of the ``KeyboardInterrupt`` +exception. +(Contributed by Gregory P. Smith in :issue:`25942`.) -This means that *close_fds* now defaults to ``True`` on all supported -platforms. (Contributed by Segev Finer in :issue:`19764`.) sys --- -Added :attr:`sys.flags.dev_mode` flag for the new development mode. +The new :func:`sys.breakpointhook` hook function is called by the +built-in :func:`breakpoint`. +(Contributed by Barry Warsaw in :issue:`31353`.) -tkinter -------- +On Android, the new :func:`sys.getandroidapilevel` returns the build-time +Android API version. +(Contributed by Victor Stinner in :issue:`28740`.) + +The new :func:`sys.get_coroutine_origin_tracking_depth` function returns +the current coroutine origin tracking depth, as set by +the new :func:`sys.set_coroutine_origin_tracking_depth`. :mod:`asyncio` +has been converted to use this new API instead of +the deprecated :func:`sys.set_coroutine_wrapper`. +(Contributed by Nathaniel J. Smith in :issue:`32591`.) -Added :class:`tkinter.ttk.Spinbox`. -(Contributed by Alan Moore in :issue:`32585`.) time ---- -The :pep:`564` added six new functions with nanosecond resolution: +:pep:`564` adds six new functions with nanosecond resolution to the +:mod:`time` module: * :func:`time.clock_gettime_ns` * :func:`time.clock_settime_ns` @@ -753,21 +1318,58 @@ The :pep:`564` added six new functions with nanosecond resolution: * :func:`time.process_time_ns` * :func:`time.time_ns` -Add new clock identifiers: +New clock identifiers have been added: * :data:`time.CLOCK_BOOTTIME` (Linux): Identical to :data:`time.CLOCK_MONOTONIC`, except it also includes any time that the system is suspended. * :data:`time.CLOCK_PROF` (FreeBSD, NetBSD and OpenBSD): High-resolution - per-process timer from the CPU. + per-process CPU timer. * :data:`time.CLOCK_UPTIME` (FreeBSD, OpenBSD): Time whose absolute value is the time the system has been running and not suspended, providing accurate - uptime measurement, both absolute and interval. + uptime measurement. -Added functions :func:`time.thread_time` and :func:`time.thread_time_ns` -to get per-thread CPU time measurements. +The new :func:`time.thread_time` and :func:`time.thread_time_ns` functions +can be used to get per-thread CPU time measurements. (Contributed by Antoine Pitrou in :issue:`32025`.) +The new :func:`time.pthread_getcpuclockid` function returns the clock ID +of the thread-specific CPU-time clock. + + +tkinter +------- + +The new :class:`tkinter.ttk.Spinbox` class is now available. +(Contributed by Alan Moore in :issue:`32585`.) + + +tracemalloc +----------- + +:class:`tracemalloc.Traceback` behaves more like regular tracebacks, +sorting the frames from oldest to most recent. +:meth:`Traceback.format() <tracemalloc.Traceback.format>` +now accepts negative *limit*, truncating the result to the +``abs(limit)`` oldest frames. To get the old behaviour, use +the new *most_recent_first* argument to ``Traceback.format()``. +(Contributed by Jesse Bakker in :issue:`32121`.) + + +types +----- + +The new :class:`~types.WrapperDescriptorType`, +:class:`~types.MethodWrapperType`, :class:`~types.MethodDescriptorType`, +and :class:`~types.ClassMethodDescriptorType` classes are now available. +(Contributed by Manuel Krebber and Guido van Rossum in :issue:`29377`, +and Serhiy Storchaka in :issue:`32265`.) + +The new :func:`types.resolve_bases` function resolves MRO entries +dynamically as specified by :pep:`560`. +(Contributed by Ivan Levkivskyi in :issue:`32717`.) + + unicodedata ----------- @@ -775,15 +1377,18 @@ The internal :mod:`unicodedata` database has been upgraded to use `Unicode 10 <http://www.unicode.org/versions/Unicode10.0.0/>`_. (Contributed by Benjamin Peterson.) + unittest -------- -Added new command-line option ``-k`` to filter tests to run with a substring or -Unix shell-like pattern. For example, ``python -m unittest -k foo`` runs the -tests ``foo_tests.SomeTest.test_something``, ``bar_tests.SomeTest.test_foo``, +The new ``-k`` command-line option allows filtering tests by a name +substring or a Unix shell-like pattern. +For example, ``python -m unittest -k foo`` runs +``foo_tests.SomeTest.test_something``, ``bar_tests.SomeTest.test_foo``, but not ``bar_tests.FooTest.test_something``. (Contributed by Jonas Haag in :issue:`32071`.) + unittest.mock ------------- @@ -791,47 +1396,75 @@ The :const:`~unittest.mock.sentinel` attributes now preserve their identity when they are :mod:`copied <copy>` or :mod:`pickled <pickle>`. (Contributed by Serhiy Storchaka in :issue:`20804`.) -New function :func:`~unittest.mock.seal` will disable the creation of mock -children by preventing to get or set any new attribute on the sealed mock. -The sealing process is performed recursively. (Contributed by Mario Corchero -in :issue:`30541`.) +The new :func:`~unittest.mock.seal` function allows sealing +:class:`~unittest.mock.Mock` instances, which will disallow further creation +of attribute mocks. The seal is applied recursively to all attributes that +are themselves mocks. +(Contributed by Mario Corchero in :issue:`30541`.) + urllib.parse ------------ :func:`urllib.parse.quote` has been updated from :rfc:`2396` to :rfc:`3986`, -adding ``~`` to the set of characters that is never quoted by default. +adding ``~`` to the set of characters that are never quoted by default. (Contributed by Christian Theune and Ratnadeep Debnath in :issue:`16285`.) + uu -- -Function :func:`~uu.encode` now accepts an optional *backtick* +The :func:`uu.encode` function now accepts an optional *backtick* keyword argument. When it's true, zeros are represented by ``'`'`` instead of spaces. (Contributed by Xiang Zhang in :issue:`30103`.) + +uuid +---- + +The new :attr:`UUID.is_safe <uuid.UUID.is_safe>` attribute relays information +from the platform about whether generated UUIDs are generated with a +multiprocessing-safe method. +(Contributed by Barry Warsaw in :issue:`22807`.) + +:func:`uuid.getnode` now prefers universally administered +MAC addresses over locally administered MAC addresses. +This makes a better guarantee for global uniqueness of UUIDs returned +from :func:`uuid.uuid1`. If only locally administered MAC addresses are +available, the first such one found is returned. +(Contributed by Barry Warsaw in :issue:`32107`.) + + warnings -------- The initialization of the default warnings filters has changed as follows: * warnings enabled via command line options (including those for :option:`-b` - and the new CPython-specific ``-X dev`` option) are always passed to the - warnings machinery via the ``sys.warnoptions`` attribute. + and the new CPython-specific :option:`-X` ``dev`` option) are always passed + to the warnings machinery via the :data:`sys.warnoptions` attribute. + * warnings filters enabled via the command line or the environment now have the - following precedence order: + following order of precedence: * the ``BytesWarning`` filter for :option:`-b` (or ``-bb``) - * any filters specified with :option:`-W` - * any filters specified with :envvar:`PYTHONWARNINGS` + * any filters specified with the :option:`-W` option + * any filters specified with the :envvar:`PYTHONWARNINGS` environment + variable * any other CPython specific filters (e.g. the ``default`` filter added for the new ``-X dev`` mode) * any implicit filters defined directly by the warnings machinery + * in CPython debug builds, all warnings are now displayed by default (the implicit filter list is empty) (Contributed by Nick Coghlan and Victor Stinner in :issue:`20361`, -:issue:`32043`, and :issue:`32230`) +:issue:`32043`, and :issue:`32230`.) + +Deprecation warnings are once again shown by default in single-file scripts and +at the interactive prompt. See :ref:`whatsnew37-pep565` for details. +(Contributed by Nick Coghlan in :issue:`31975`.) + xml.etree --------- @@ -841,13 +1474,15 @@ methods can now compare text of the current node with ``[. = "text"]``, not only text in children. Predicates also allow adding spaces for better readability. (Contributed by Stefan Behnel in :issue:`31648`.) + xmlrpc.server ------------- -:meth:`register_function` of :class:`~xmlrpc.server.SimpleXMLRPCDispatcher` and -its subclasses can be used as a decorator. (Contributed by Xiang Zhang in +:meth:`SimpleXMLRPCDispatcher.register_function <xmlrpc.server.SimpleXMLRPCDispatcher>` +can now be used as a decorator. (Contributed by Xiang Zhang in :issue:`7769`.) + zipapp ------ @@ -861,144 +1496,267 @@ argument to generate a compressed archive. A command line option (Contributed by Zhiming Wang in :issue:`31638`.) +zipfile +------- + +:class:`~zipfile.ZipFile` now accepts the new *compresslevel* parameter to +control the compression level. +(Contributed by Bo Bayles in :issue:`21417`.) + +Subdirectories in archives created by ``ZipFile`` are now stored in +alphabetical order. +(Contributed by Bernhard M. Wiedemann in :issue:`30693`.) + + +C API Changes +============= + +A new API for thread-local storage has been implemented. See +:ref:`whatsnew37-pep539` for an overview and +:ref:`thread-specific-storage-api` for a complete reference. +(Contributed by Masayuki Yamamoto in :issue:`25658`.) + +The new :c:func:`PyImport_GetModule` function returns the previously +imported module with the given name. +(Contributed by Eric Snow in :issue:`28411`.) + +The new :c:macro:`Py_RETURN_RICHCOMPARE` macro eases writing rich +comparison functions. +(Contributed by Petr Victorin in :issue:`23699`.) + +The new :c:macro:`Py_UNREACHABLE` macro can be used to mark unreachable +code paths. +(Contributed by Barry Warsaw in :issue:`31338`.) + +The :mod:`tracemalloc` now exposes a C API through the new +:c:func:`PyTraceMalloc_Track` and :c:func:`PyTraceMalloc_Untrack` +functions. +(Contributed by Victor Stinner in :issue:`30054`.) + +The new :c:func:`import__find__load__start` and +:c:func:`import__find__load__done` static markers can be used to trace +module imports. +(Contributed by Christian Heimes in :issue:`31574`.) + +The fields :c:member:`name` and :c:member:`doc` of structures +:c:type:`PyMemberDef`, :c:type:`PyGetSetDef`, +:c:type:`PyStructSequence_Field`, :c:type:`PyStructSequence_Desc`, +and :c:type:`wrapperbase` are now of type ``const char *`` rather of +``char *``. (Contributed by Serhiy Storchaka in :issue:`28761`.) + +The result of :c:func:`PyUnicode_AsUTF8AndSize` and :c:func:`PyUnicode_AsUTF8` +is now of type ``const char *`` rather of ``char *``. (Contributed by Serhiy +Storchaka in :issue:`28769`.) + +The result of :c:func:`PyMapping_Keys`, :c:func:`PyMapping_Values` and +:c:func:`PyMapping_Items` is now always a list, rather than a list or a +tuple. (Contributed by Oren Milman in :issue:`28280`.) + +Added functions :c:func:`PySlice_Unpack` and :c:func:`PySlice_AdjustIndices`. +(Contributed by Serhiy Storchaka in :issue:`27867`.) + +:c:func:`PyOS_AfterFork` is deprecated in favour of the new functions +:c:func:`PyOS_BeforeFork`, :c:func:`PyOS_AfterFork_Parent` and +:c:func:`PyOS_AfterFork_Child`. (Contributed by Antoine Pitrou in +:issue:`16500`.) + +The ``PyExc_RecursionErrorInst`` singleton that was part of the public API +has been removed as its members being never cleared may cause a segfault +during finalization of the interpreter. Contributed by Xavier de Gaye in +:issue:`22898` and :issue:`30697`. + +Added C API support for timezones with timezone constructors +:c:func:`PyTimeZone_FromOffset` and :c:func:`PyTimeZone_FromOffsetAndName`, +and access to the UTC singleton with :c:data:`PyDateTime_TimeZone_UTC`. +Contributed by Paul Ganssle in :issue:`10381`. + +The type of results of :c:func:`PyThread_start_new_thread` and +:c:func:`PyThread_get_thread_ident`, and the *id* parameter of +:c:func:`PyThreadState_SetAsyncExc` changed from :c:type:`long` to +:c:type:`unsigned long`. +(Contributed by Serhiy Storchaka in :issue:`6532`.) + +:c:func:`PyUnicode_AsWideCharString` now raises a :exc:`ValueError` if the +second argument is *NULL* and the :c:type:`wchar_t*` string contains null +characters. (Contributed by Serhiy Storchaka in :issue:`30708`.) + +Changes to the startup sequence and the management of dynamic memory +allocators mean that the long documented requirement to call +:c:func:`Py_Initialize` before calling most C API functions is now +relied on more heavily, and failing to abide by it may lead to segfaults in +embedding applications. See the :ref:`porting-to-python-37` section in this +document and the :ref:`pre-init-safe` section in the C API documentation +for more details. + +The new :c:func:`PyInterpreterState_GetID` returns the unique ID for a +given interpreter. +(Contributed by Eric Snow in :issue:`29102`.) + +:c:func:`Py_DecodeLocale`, :c:func:`Py_EncodeLocale` now use the UTF-8 +encoding when the :ref:`UTF-8 mode <whatsnew37-pep540>` is enabled. +(Contributed by Victor Stinner in :issue:`29240`.) + +:c:func:`PyUnicode_DecodeLocaleAndSize` and :c:func:`PyUnicode_EncodeLocale` +now use the current locale encoding for ``surrogateescape`` error handler. +(Contributed by Victor Stinner in :issue:`29240`.) + +The *start* and *end* parameters of :c:func:`PyUnicode_FindChar` are +now adjusted to behave like string slices. +(Contributed by Xiang Zhang in :issue:`28822`.) + + +Build Changes +============= + +Support for building ``--without-threads`` has been removed. The +:mod:`threading` module is now always available. +(Contributed by Antoine Pitrou in :issue:`31370`.). + +A full copy of libffi is no longer bundled for use when building the +:mod:`_ctypes <ctypes>` module on non-OSX UNIX platforms. An installed copy +of libffi is now required when building ``_ctypes`` on such platforms. +(Contributed by Zachary Ware in :issue:`27979`.) + +The Windows build process no longer depends on Subversion to pull in external +sources, a Python script is used to download zipfiles from GitHub instead. +If Python 3.6 is not found on the system (via ``py -3.6``), NuGet is used to +download a copy of 32-bit Python for this purpose. (Contributed by Zachary +Ware in :issue:`30450`.) + +The :mod:`ssl` module requires OpenSSL 1.0.2 or 1.1 compatible libssl. +OpenSSL 1.0.1 has reached end of lifetime on 2016-12-31 and is no longer +supported. LibreSSL is temporarily not supported as well. LibreSSL releases +up to version 2.6.4 are missing required OpenSSL 1.0.2 APIs. + + +.. _whatsnew37-perf: + Optimizations ============= -* Added two new opcodes: :opcode:`LOAD_METHOD` and :opcode:`CALL_METHOD` to avoid - instantiation of bound method objects for method calls, which results - in method calls being faster up to 20%. (Contributed by Yury Selivanov and - INADA Naoki in :issue:`26110`.) - -* Searching some unlucky Unicode characters (like Ukrainian capital "?") - in a string was up to 25 times slower than searching other characters. - Now it is slower only by 3 times in the worst case. - (Contributed by Serhiy Storchaka in :issue:`24821`.) - -* Fast implementation from standard C library is now used for functions - :func:`~math.erf` and :func:`~math.erfc` in the :mod:`math` module. - (Contributed by Serhiy Storchaka in :issue:`26121`.) - -* The :func:`os.fwalk` function has been sped up by 2 times. This was done - using the :func:`os.scandir` function. - (Contributed by Serhiy Storchaka in :issue:`25996`.) - -* The :func:`shutil.rmtree` function has been sped up to 20--40%. - This was done using the :func:`os.scandir` function. - (Contributed by Serhiy Storchaka in :issue:`28564`.) - -* Optimized case-insensitive matching and searching of :mod:`regular - expressions <re>`. Searching some patterns can now be up to 20 times faster. - (Contributed by Serhiy Storchaka in :issue:`30285`.) - -* :func:`re.compile` now converts ``flags`` parameter to int object if - it is ``RegexFlag``. It is now as fast as Python 3.5, and faster than - Python 3.6 by about 10% depending on the pattern. - (Contributed by INADA Naoki in :issue:`31671`.) - -* :meth:`~selectors.BaseSelector.modify` methods of classes - :class:`selectors.EpollSelector`, :class:`selectors.PollSelector` - and :class:`selectors.DevpollSelector` may be around 10% faster under - heavy loads. (Contributed by Giampaolo Rodola' in :issue:`30014`) - -* Constant folding is moved from peephole optimizer to new AST optimizer. - (Contributed by Eugene Toder and INADA Naoki in :issue:`29469`) - -* Most functions and methods in :mod:`abc` have been rewritten in C. - This makes creation of abstract base classes, and calling :func:`isinstance` - and :func:`issubclass` on them 1.5x faster. This also reduces Python - start-up time by up to 10%. (Contributed by Ivan Levkivskyi and INADA Naoki - in :issue:`31333`) - -* Significant speed improvements to alternate constructors for - :class:`datetime.date` and :class:`datetime.datetime` by using fast-path - constructors when not constructing subclasses. (Contributed by Paul Ganssle - in :issue:`32403`) - - -Build and C API Changes -======================= - -* :mod:`py_compile` and :mod:`compileall` now support the - :envvar:`SOURCE_DATE_EPOCH` environment variable by unconditionally - building ``.pyc`` files for hash verification instead of potentially - timestamp-based ``.pyc`` files. See the notes for the `py_compile`_ - improvement notes for more details. - -* A full copy of libffi is no longer bundled for use when building the - :mod:`_ctypes <ctypes>` module on non-OSX UNIX platforms. An installed copy - of libffi is now required when building ``_ctypes`` on such platforms. - (Contributed by Zachary Ware in :issue:`27979`.) - -* The fields :c:member:`name` and :c:member:`doc` of structures - :c:type:`PyMemberDef`, :c:type:`PyGetSetDef`, - :c:type:`PyStructSequence_Field`, :c:type:`PyStructSequence_Desc`, - and :c:type:`wrapperbase` are now of type ``const char *`` rather of - ``char *``. (Contributed by Serhiy Storchaka in :issue:`28761`.) - -* The result of :c:func:`PyUnicode_AsUTF8AndSize` and :c:func:`PyUnicode_AsUTF8` - is now of type ``const char *`` rather of ``char *``. (Contributed by Serhiy - Storchaka in :issue:`28769`.) - -* The result of :c:func:`PyMapping_Keys`, :c:func:`PyMapping_Values` and - :c:func:`PyMapping_Items` is now always a list, rather than a list or a - tuple. (Contributed by Oren Milman in :issue:`28280`.) - -* Added functions :c:func:`PySlice_Unpack` and :c:func:`PySlice_AdjustIndices`. - (Contributed by Serhiy Storchaka in :issue:`27867`.) - -* :c:func:`PyOS_AfterFork` is deprecated in favour of the new functions - :c:func:`PyOS_BeforeFork`, :c:func:`PyOS_AfterFork_Parent` and - :c:func:`PyOS_AfterFork_Child`. (Contributed by Antoine Pitrou in - :issue:`16500`.) - -* The Windows build process no longer depends on Subversion to pull in external - sources, a Python script is used to download zipfiles from GitHub instead. - If Python 3.6 is not found on the system (via ``py -3.6``), NuGet is used to - download a copy of 32-bit Python for this purpose. (Contributed by Zachary - Ware in :issue:`30450`.) - -* The ``PyExc_RecursionErrorInst`` singleton that was part of the public API - has been removed as its members being never cleared may cause a segfault - during finalization of the interpreter. Contributed by Xavier de Gaye in - :issue:`22898` and :issue:`30697`. - -* Support for building ``--without-threads`` is removed. - (Contributed by Antoine Pitrou in :issue:`31370`.). - -* Added C API support for timezones with timezone constructors - :c:func:`PyTimeZone_FromOffset` and :c:func:`PyTimeZone_FromOffsetAndName`, - and access to the UTC singleton with :c:data:`PyDateTime_TimeZone_UTC`. - Contributed by Paul Ganssle in :issue:`10381`. - -- The type of results of :c:func:`PyThread_start_new_thread` and - :c:func:`PyThread_get_thread_ident`, and the *id* parameter of - :c:func:`PyThreadState_SetAsyncExc` changed from :c:type:`long` to - :c:type:`unsigned long`. - (Contributed by Serhiy Storchaka in :issue:`6532`.) - -- :c:func:`PyUnicode_AsWideCharString` now raises a :exc:`ValueError` if the - second argument is *NULL* and the :c:type:`wchar_t*` string contains null - characters. (Contributed by Serhiy Storchaka in :issue:`30708`.) - -- Changes to the startup sequence and the management of dynamic memory - allocators mean that the long documented requirement to call - :c:func:`Py_Initialize` before calling most C API functions is now - relied on more heavily, and failing to abide by it may lead to segfaults in - embedding applications. See the :ref:`porting-to-python-37` section in this - document and the :ref:`pre-init-safe` section in the C API documentation - for more details. +The overhead of calling many methods of various standard library classes +implemented in C has been significantly reduced by porting more code +to use the ``METH_FASTCALL`` convention. +(Contributed by Victor Stinner in :issue:`29300`, :issue:`29507`, +:issue:`29452`, and :issue:`29286`.) + +Various optimizations have reduced Python startup time by 10% on Linux and +up to 30% on macOS. +(Contributed by Victor Stinner, INADA Naoki in :issue:`29585`, and +Ivan Levkivskyi in :issue:`31333`.) + +Method calls are now up to 20% faster due to the bytecode changes which +avoid creating bound method instances. +(Contributed by Yury Selivanov and INADA Naoki in :issue:`26110`.) + +.. _whatsnew37-asyncio-perf: + +The :mod:`asyncio` module received a number of notable optimizations for +commonly used functions: + +* The :func:`asyncio.get_event_loop` function has been reimplemented in C to + make it up to 15 times faster. + (Contributed by Yury Selivanov in :issue:`32296`.) + +* :class:`asyncio.Future` callback management has been optimized. + (Contributed by Yury Selivanov in :issue:`32348`.) + +* :func:`asyncio.gather` is now up to 15% faster. + (Contributed by Yury Selivanov in :issue:`32355`.) + +* :func:`asyncio.sleep` is now up to 2 times faster when the *delay* + argument is zero or negative. + (Contributed by Andrew Svetlov in :issue:`32351`.) + +* The performance overhead of asyncio debug mode has been reduced. + (Contributed by Antoine Pitrou in :issue:`31970`.) + +As a result of :ref:`PEP 560 work <whatsnew37-pep560>`, the import time +of :mod:`typing` has been reduced by a factor of 7, and many typing operations +are now faster. +(Contributed by Ivan Levkivskyi in :issue:`32226`.) + +:func:`sorted` and :meth:`list.sort` have been optimized for common cases +to be up to 40-75% faster. +(Contributed by Elliot Gorokhovsky in :issue:`28685`.) + +:meth:`dict.copy` is now up to 5.5 times faster. +(Contributed by Yury Selivanov in :issue:`31179`.) + +:func:`hasattr` and :func:`getattr` are now about 4 times faster when +*name* is not found and *obj* does not override :meth:`object.__getattr__` +or :meth:`object.__getattribute__`. +(Contributed by INADA Naoki in :issue:`32544`.) + +Searching for certain Unicode characters (like Ukrainian capital "?") +in a string was up to 25 times slower than searching for other characters. +It is now only 3 times slower in the worst case. +(Contributed by Serhiy Storchaka in :issue:`24821`.) + +The :func:`collections.namedtuple` factory has been reimplemented to +make the creation of named tuples 4 to 6 times faster. +(Contributed by Jelle Zijlstra with further improvements by INADA Naoki, +Serhiy Storchaka, and Raymond Hettinger in :issue:`28638`.) + +:meth:`date.fromordinal` and :meth:`date.fromtimestamp` are now up to +30% faster in the common case. +(Contributed by Paul Ganssle in :issue:`32403`.) + +The :func:`os.fwalk` function is now up to 2 times faster thanks to +the use of :func:`os.scandir`. +(Contributed by Serhiy Storchaka in :issue:`25996`.) + +The speed of the :func:`shutil.rmtree` function has been improved by +20--40% thanks to the use of the :func:`os.scandir` function. +(Contributed by Serhiy Storchaka in :issue:`28564`.) + +Optimized case-insensitive matching and searching of :mod:`regular +expressions <re>`. Searching some patterns can now be up to 20 times faster. +(Contributed by Serhiy Storchaka in :issue:`30285`.) + +:func:`re.compile` now converts ``flags`` parameter to int object if +it is ``RegexFlag``. It is now as fast as Python 3.5, and faster than +Python 3.6 by about 10% depending on the pattern. +(Contributed by INADA Naoki in :issue:`31671`.) + +The :meth:`~selectors.BaseSelector.modify` methods of classes +:class:`selectors.EpollSelector`, :class:`selectors.PollSelector` +and :class:`selectors.DevpollSelector` may be around 10% faster under +heavy loads. (Contributed by Giampaolo Rodola' in :issue:`30014`) + +Constant folding has been moved from the peephole optimizer to the new AST +optimizer, which is able perform optimizations more consistently. +(Contributed by Eugene Toder and INADA Naoki in :issue:`29469` and +:issue:`11549`.) + +Most functions and methods in :mod:`abc` have been rewritten in C. +This makes creation of abstract base classes, and calling :func:`isinstance` +and :func:`issubclass` on them 1.5x faster. This also reduces Python +start-up time by up to 10%. (Contributed by Ivan Levkivskyi and INADA Naoki +in :issue:`31333`) + +Significant speed improvements to alternate constructors for +:class:`datetime.date` and :class:`datetime.datetime` by using fast-path +constructors when not constructing subclasses. (Contributed by Paul Ganssle +in :issue:`32403`) + +The speed of comparison of :class:`array.array` instances has been +improved considerably in certain cases. It is now from 10x to 70x faster +when comparing arrays holding values of the same integer type. +(Contributed by Adrian Wielgosik in :issue:`24700`.) + +The :func:`math.erf` and :func:`math.erfc` functions now use the (faster) +C library implementation on most platforms. +(Contributed by Serhiy Storchaka in :issue:`26121`.) Other CPython Implementation Changes ==================================== -* Trace hooks may now opt out of receiving ``line`` events from the interpreter - by setting the new ``f_trace_lines`` attribute to :const:`False` on the frame - being traced. (Contributed by Nick Coghlan in :issue:`31344`.) - -* Trace hooks may now opt in to receiving ``opcode`` events from the interpreter - by setting the new ``f_trace_opcodes`` attribute to :const:`True` on the frame - being traced. (Contributed by Nick Coghlan in :issue:`31344`.) +* Trace hooks may now opt out of receiving the ``line`` and opt into receiving + the ``opcode`` events from the interpreter by setting the corresponding new + ``f_trace_lines`` and ``f_trace_opcodes`` attributes on the + frame being traced. (Contributed by Nick Coghlan in :issue:`31344`.) * Fixed some consistency problems with namespace package module attributes. Namespace module objects now have an ``__file__`` that is set to ``None`` @@ -1008,96 +1766,213 @@ Other CPython Implementation Changes ``__loader__`` (previously, the former was set to ``None``). See :issue:`32303`. +* The :func:`locals` dictionary now displays in the lexical order that + variables were defined. Previously, the order was undefined. + (Contributed by Raymond Hettinger in :issue:`32690`.) + +* The :mod:`distutils` ``upload`` command no longer tries to change CR + end-of-line characters to CRLF. This fixes a corruption issue with sdists + that ended with a byte equivalent to CR. + (Contributed by Bo Bayles in :issue:`32304`.) + -Deprecated -========== +Deprecated Python Behavior +========================== -* In Python 3.8, the abstract base classes in :mod:`collections.abc` will no - longer be exposed in the regular :mod:`collections` module. This will help - create a clearer distinction between the concrete classes and the abstract - base classes. +Yield expressions (both ``yield`` and ``yield from`` clauses) are now deprecated +in comprehensions and generator expressions (aside from the iterable expression +in the leftmost :keyword:`for` clause). This ensures that comprehensions +always immediately return a container of the appropriate type (rather than +potentially returning a :term:`generator iterator` object), while generator +expressions won't attempt to interleave their implicit output with the output +from any explicit yield expressions. In Python 3.7, such expressions emit +:exc:`DeprecationWarning` when compiled, in Python 3.8 this will be a +:exc:`SyntaxError`. +(Contributed by Serhiy Storchaka in :issue:`10544`.) -* Yield expressions (both ``yield`` and ``yield from`` clauses) are now deprecated - in comprehensions and generator expressions (aside from the iterable expression - in the leftmost :keyword:`for` clause). This ensures that comprehensions - always immediately return a container of the appropriate type (rather than - potentially returning a :term:`generator iterator` object), while generator - expressions won't attempt to interleave their implicit output with the output - from any explicit yield expressions. +Returning a subclass of :class:`complex` from :meth:`object.__complex__` is +deprecated and will be an error in future Python versions. This makes +``__complex__()`` consistent with :meth:`object.__int__` and +:meth:`object.__float__`. +(Contributed by Serhiy Storchaka in :issue:`28894`.) - In Python 3.7, such expressions emit :exc:`DeprecationWarning` when compiled, - in Python 3.8+ they will emit :exc:`SyntaxError`. (Contributed by Serhiy - Storchaka in :issue:`10544`.) -- Function :c:func:`PySlice_GetIndicesEx` is deprecated and replaced with - a macro if ``Py_LIMITED_API`` is not set or set to the value between - ``0x03050400`` and ``0x03060000`` (not including) or ``0x03060100`` or - higher. (Contributed by Serhiy Storchaka in :issue:`27867`.) -- Deprecated :meth:`format` from :mod:`locale`, use the :meth:`format_string` - instead. (Contributed by Garvit in :issue:`10379`.) +Deprecated Python modules, functions and methods +================================================ -- Methods - :meth:`MetaPathFinder.find_module() <importlib.abc.MetaPathFinder.find_module>` - (replaced by - :meth:`MetaPathFinder.find_spec() <importlib.abc.MetaPathFinder.find_spec>`) - and - :meth:`PathEntryFinder.find_loader() <importlib.abc.PathEntryFinder.find_loader>` - (replaced by - :meth:`PathEntryFinder.find_spec() <importlib.abc.PathEntryFinder.find_spec>`) - both deprecated in Python 3.4 now emit :exc:`DeprecationWarning`. - (Contributed by Matthias Bussonnier in :issue:`29576`) +aifc +---- -- Using non-integer value for selecting a plural form in :mod:`gettext` is - now deprecated. It never correctly worked. (Contributed by Serhiy Storchaka - in :issue:`28692`.) +:func:`aifc.openfp` has been deprecated and will be removed in Python 3.9. +Use :func:`aifc.open` instead. +(Contributed by Brian Curtin in :issue:`31985`.) -- The :mod:`macpath` is now deprecated and will be removed in Python 3.8. -- The :class:`importlib.abc.ResourceLoader` ABC has been deprecated in - favour of :class:`importlib.abc.ResourceReader`. +.. _whatsnew37-asyncio-deprecated: -- Deprecated :func:`sys.set_coroutine_wrapper` and - :func:`sys.get_coroutine_wrapper`. +asyncio +------- -- :func:`ssl.wrap_socket` is deprecated. Use - :meth:`ssl.SSLContext.wrap_socket` instead. - (Contributed by Christian Heimes in :issue:`28124`.) +Support for directly ``await``-ing instances of :class:`asyncio.Lock` and +other asyncio synchronization primitives has been deprecated. An +asynchronous context manager must be used in order to acquire and release +the synchronization resource. See :ref:`async-with-locks` for more +information. +(Contributed by Andrew Svetlov in :issue:`32253`.) -- In Python 3.8, attempting to check for non-Enum objects in :class:`Enum` - classes will raise a :exc:`TypeError` (e.g. ``1 in Color``); similarly, - attempting to check for non-Flag objects in a :class:`Flag` member will - raise :exc:`TypeError` (e.g. ``1 in Perm.RW``); currently, both operations - return :const:`False` instead. +The :meth:`asyncio.Task.current_task` and :meth:`asyncio.Task.all_tasks` +methods have been deprecated. +(Contributed by Andrew Svetlov in :issue:`32250`.) -Windows Only ------------- +collections +----------- + +In Python 3.8, the abstract base classes in :mod:`collections.abc` will no +longer be exposed in the regular :mod:`collections` module. This will help +create a clearer distinction between the concrete classes and the abstract +base classes. +(Contributed by Serhiy Storchaka in :issue:`25988`.) + + +dbm +--- + +:mod:`dbm.dumb` now supports reading read-only files and no longer writes the +index file when it is not changed. A deprecation warning is now emitted +if the index file is missing and recreated in the ``'r'`` and ``'w'`` +modes (this will be an error in future Python releases). +(Contributed by Serhiy Storchaka in :issue:`28847`.) + + +enum +---- + +In Python 3.8, attempting to check for non-Enum objects in :class:`Enum` +classes will raise a :exc:`TypeError` (e.g. ``1 in Color``); similarly, +attempting to check for non-Flag objects in a :class:`Flag` member will +raise :exc:`TypeError` (e.g. ``1 in Perm.RW``); currently, both operations +return :const:`False` instead. +(Contributed by Ethan Furman in :issue:`33217`.) + + +gettext +------- + +Using non-integer value for selecting a plural form in :mod:`gettext` is +now deprecated. It never correctly worked. (Contributed by Serhiy Storchaka +in :issue:`28692`.) + + +importlib +--------- + +Methods +:meth:`MetaPathFinder.find_module() <importlib.abc.MetaPathFinder.find_module>` +(replaced by +:meth:`MetaPathFinder.find_spec() <importlib.abc.MetaPathFinder.find_spec>`) +and +:meth:`PathEntryFinder.find_loader() <importlib.abc.PathEntryFinder.find_loader>` +(replaced by +:meth:`PathEntryFinder.find_spec() <importlib.abc.PathEntryFinder.find_spec>`) +both deprecated in Python 3.4 now emit :exc:`DeprecationWarning`. +(Contributed by Matthias Bussonnier in :issue:`29576`) + +The :class:`importlib.abc.ResourceLoader` ABC has been deprecated in +favour of :class:`importlib.abc.ResourceReader`. + + +locale +------ + +:func:`locale.format` has been deprecated, use :meth:`locale.format_string` +instead. (Contributed by Garvit in :issue:`10379`.) + + +macpath +------- + +The :mod:`macpath` is now deprecated and will be removed in Python 3.8. +(Contributed by Chi Hsuan Yen in :issue:`9850`.) + + +threading +--------- + +:mod:`dummy_threading` and :mod:`_dummy_thread` have been deprecated. It is +no longer possible to build Python with threading disabled. +Use :mod:`threading` instead. +(Contributed by Antoine Pitrou in :issue:`31370`.) -- The python launcher, (py.exe), can accept 32 & 64 bit specifiers **without** - having to specify a minor version as well. So ``py -3-32`` and ``py -3-64`` - become valid as well as ``py -3.7-32``, also the -*m*-64 and -*m.n*-64 forms - are now accepted to force 64 bit python even if 32 bit would have otherwise - been used. If the specified version is not available py.exe will error exit. - (Contributed by Steve Barnes in :issue:`30291`.) -- The launcher can be run as ``py -0`` to produce a list of the installed pythons, - *with default marked with an asterisk*. Running ``py -0p`` will include the paths. - If py is run with a version specifier that cannot be matched it will also print - the *short form* list of available specifiers. - (Contributed by Steve Barnes in :issue:`30362`.) +socket +------ + +The silent argument value trunctation in :func:`socket.htons` and +:func:`socket.ntohs` has been deprecated. In future versions of Python, +if the passed argument is larger than 16 bits, an exception will be raised. +(Contributed by Oren Milman in :issue:`28332`.) + + +ssl +--- + +:func:`ssl.wrap_socket` is deprecated. Use +:meth:`ssl.SSLContext.wrap_socket` instead. +(Contributed by Christian Heimes in :issue:`28124`.) + + +sunau +----- + +:func:`sunau.openfp` has been deprecated and will be removed in Python 3.9. +Use :func:`sunau.open` instead. +(Contributed by Brian Curtin in :issue:`31985`.) + + +sys +--- + +Deprecated :func:`sys.set_coroutine_wrapper` and +:func:`sys.get_coroutine_wrapper`. +The undocumented ``sys.callstats()`` function has been deprecated and +will be removed in a future Python version. +(Contributed by Victor Stinner in :issue:`28799`.) + + +wave +---- + +:func:`wave.openfp` has been deprecated and will be removed in Python 3.9. +Use :func:`wave.open` instead. +(Contributed by Brian Curtin in :issue:`31985`.) + + +Deprecated functions and types of the C API +=========================================== + +Function :c:func:`PySlice_GetIndicesEx` is deprecated and replaced with +a macro if ``Py_LIMITED_API`` is not set or set to a value in the range +between ``0x03050400`` and ``0x03060000`` (not inclusive), or is ``0x03060100`` +or higher. (Contributed by Serhiy Storchaka in :issue:`27867`.) + +:c:func:`PyOS_AfterFork` has been deprecated. Use :c:func:`PyOS_BeforeFork`, +:c:func:`PyOS_AfterFork_Parent` or :c:func:`PyOS_AfterFork_Child()` instead. +(Contributed by Antoine Pitrou in :issue:`16500`.) -Removed -======= Platform Support Removals -------------------------- +========================= + +FreeBSD 9 and older are no longer officially supported. -* FreeBSD 9 and older are no longer supported. API and Feature Removals ------------------------- +======================== + +The following features and APIs have been removed from Python 3.7: * The ``os.stat_float_times()`` function has been removed. It was introduced in Python 2.3 for backward compatibility with Python 2.2, and was deprecated @@ -1131,15 +2006,51 @@ API and Feature Removals can use attribute access to access items of these dictionaries. * The ``asyncio.windows_utils.socketpair()`` function has been - removed: use directly :func:`socket.socketpair` which is available on all - platforms since Python 3.5 (before, it wasn't available on Windows). + removed. Use the :func:`socket.socketpair` function instead, + it is available on all platforms since Python 3.5. ``asyncio.windows_utils.socketpair`` was just an alias to ``socket.socketpair`` on Python 3.5 and newer. -* :mod:`asyncio`: The module doesn't export :mod:`selectors` and +* :mod:`asyncio` no longer exports the :mod:`selectors` and :mod:`_overlapped` modules as ``asyncio.selectors`` and ``asyncio._overlapped``. Replace ``from asyncio import selectors`` with - ``import selectors`` for example. + ``import selectors``. + +* Direct instantiation of :class:`ssl.SSLSocket` and :class:`ssl.SSLObject` + objects is now prohibited. The constructors were never documented, tested, + or designed as public constructors. Users were supposed to use + :func:`ssl.wrap_socket` or :class:`ssl.SSLContext`. + (Contributed by Christian Heimes in :issue:`32951`.) + +* The unused :mod:`distutils` ``install_misc`` command has been removed. + (Contributed by Eric N. Vander Weele in :issue:`29218`.) + + +Module Removals +=============== + +The ``fpectl`` module has been removed. It was never enabled by +default, never worked correctly on x86-64, and it changed the Python +ABI in ways that caused unexpected breakage of C extensions. +(Contributed by Nathaniel J. Smith in :issue:`29137`.) + + +Windows-only Changes +==================== + +The python launcher, (py.exe), can accept 32 & 64 bit specifiers **without** +having to specify a minor version as well. So ``py -3-32`` and ``py -3-64`` +become valid as well as ``py -3.7-32``, also the -*m*-64 and -*m.n*-64 forms +are now accepted to force 64 bit python even if 32 bit would have otherwise +been used. If the specified version is not available py.exe will error exit. +(Contributed by Steve Barnes in :issue:`30291`.) + +The launcher can be run as ``py -0`` to produce a list of the installed pythons, +*with default marked with an asterisk*. Running ``py -0p`` will include the paths. +If py is run with a version specifier that cannot be matched it will also print +the *short form* list of available specifiers. +(Contributed by Steve Barnes in :issue:`30362`.) + .. _porting-to-python-37: @@ -1150,15 +2061,22 @@ This section lists previously described changes and other bugfixes that may require changes to your code. -Changes in Python behavior +Changes in Python Behavior -------------------------- +* :keyword:`async` and :keyword:`await` names are now reserved keywords. + Code using these names as identifiers will now raise a :exc:`SyntaxError`. + (Contributed by Jelle Zijlstra in :issue:`30406`.) + * :pep:`479` is enabled for all code in Python 3.7, meaning that :exc:`StopIteration` exceptions raised directly or indirectly in coroutines and generators are transformed into :exc:`RuntimeError` exceptions. (Contributed by Yury Selivanov in :issue:`32670`.) +* :meth:`object.__aiter__` methods can no longer be declared as + asynchronous. (Contributed by Yury Selivanov in :issue:`31709`.) + * Due to an oversight, earlier Python versions erroneously accepted the following syntax:: @@ -1185,22 +2103,25 @@ Changes in Python behavior Changes in the Python API ------------------------- -* :meth:`socketserver.ThreadingMixIn.server_close` now waits until all - non-daemon threads complete. Use daemonic threads by setting - :data:`socketserver.ThreadingMixIn.daemon_threads` to ``True`` to not - wait until threads complete. - (Contributed by Victor Stinner in :issue:`31233`.) +* ``Module``, ``FunctionDef``, ``AsyncFunctionDef``, and + ``ClassDef`` AST nodes now have the new ``docstring`` attribute. + The first statement in their body is not considered as a docstring + anymore. ``co_firstlineno`` and ``co_lnotab`` of code object for class + and module are affected by this change. (Contributed by INADA Naoki and + Eugene Toder in :issue:`29463`.) -* :meth:`socketserver.ForkingMixIn.server_close` now waits until all - child processes complete. (Contributed by Victor Stinner in :issue:`31151`.) +* :meth:`~socketserver.BaseServer.server_close` in + :class:`socketserver.ThreadingMixIn` and :class:`socketserver.ForkingMixIn` + now waits until all non-daemon threads complete. + (Contributed by Victor Stinner in :issue:`31233` and :issue:`31151`.) -* The :func:`locale.localeconv` function now sets temporarily the ``LC_CTYPE`` - locale to the ``LC_NUMERIC`` locale in some cases. +* The :func:`locale.localeconv` function now temporarily sets the ``LC_CTYPE`` + locale to the value of ``LC_NUMERIC`` in some cases. (Contributed by Victor Stinner in :issue:`31900`.) -* :meth:`pkgutil.walk_packages` now raises :exc:`ValueError` if *path* is a string. - Previously an empty list was returned. (Contributed by Sanyam Khurana in - :issue:`24744`.) +* :meth:`pkgutil.walk_packages` now raises a :exc:`ValueError` if *path* is + a string. Previously an empty list was returned. + (Contributed by Sanyam Khurana in :issue:`24744`.) * A format string argument for :meth:`string.Formatter.format` is now :ref:`positional-only <positional-only_parameter>`. @@ -1215,13 +2136,6 @@ Changes in the Python API Use the :meth:`~http.cookies.Morsel.set` method for setting them. (Contributed by Serhiy Storchaka in :issue:`29192`.) -* ``Module``, ``FunctionDef``, ``AsyncFunctionDef``, and - ``ClassDef`` AST nodes now have a new ``docstring`` field. - The first statement in their body is not considered as a docstring - anymore. ``co_firstlineno`` and ``co_lnotab`` of code object for class - and module are affected by this change. (Contributed by INADA Naoki and - Eugene Toder in :issue:`29463`.) - * The *mode* argument of :func:`os.makedirs` no longer affects the file permission bits of newly-created intermediate-level directories. To set their file permission bits you can set the umask before invoking @@ -1231,34 +2145,35 @@ Changes in the Python API * The :attr:`struct.Struct.format` type is now :class:`str` instead of :class:`bytes`. (Contributed by Victor Stinner in :issue:`21071`.) -* :func:`~cgi.parse_multipart` returns now the same results as +* :func:`~cgi.parse_multipart` now accepts the *encoding* and *errors* + arguments and returns the same results as :class:`~FieldStorage`: for non-file fields, the value associated to a key is a list of strings, not bytes. (Contributed by Pierre Quentel in :issue:`29979`.) -* Due to internal changes in :mod:`socket` you won't be able to - :func:`socket.fromshare` a socket :func:`~socket.socket.share`-ed in older - Python versions. +* Due to internal changes in :mod:`socket`, calling :func:`socket.fromshare` + on a socket created by :func:`socket.share <socket.socket.share>` in older + Python versions is not supported. -* ``repr`` for :exc:`BaseException` has changed not to include trailing comma - in the output. Mind that most exceptions are affected by this change. +* ``repr`` for :exc:`BaseException` has changed to not include the trailing + comma. Most exceptions are affected by this change. (Contributed by Serhiy Storchaka in :issue:`30399`.) -* ``repr`` for :class:`datetime.timedelta` has changed to include keyword arguments - in the output. (Contributed by Utkarsh Upadhyay in :issue:`30302`.) +* ``repr`` for :class:`datetime.timedelta` has changed to include the keyword + arguments in the output. (Contributed by Utkarsh Upadhyay in :issue:`30302`.) * Because :func:`shutil.rmtree` is now implemented using the :func:`os.scandir` function, the user specified handler *onerror* is now called with the first argument ``os.scandir`` instead of ``os.listdir`` when listing the direcory is failed. -* Support of nested sets and set operations in regular expressions as in +* Support for nested sets and set operations in regular expressions as in `Unicode Technical Standard #18`_ might be added in the future. This would - change the syntax, so to facilitate this change a :exc:`FutureWarning` will - be raised in ambiguous cases for the time being. + change the syntax. To facilitate this future change a :exc:`FutureWarning` + will be raised in ambiguous cases for the time being. That include sets starting with a literal ``'['`` or containing literal character sequences ``'--'``, ``'&&'``, ``'~~'``, and ``'||'``. To - avoid a warning escape them with a backslash. + avoid a warning, escape them with a backslash. (Contributed by Serhiy Storchaka in :issue:`30349`.) .. _Unicode Technical Standard #18: https://unicode.org/reports/tr18/ @@ -1315,82 +2230,119 @@ Changes in the Python API in :data:`sys.path_importer_cache` which are set to ``None``. (Contributed by Brett Cannon in :issue:`33169`.) +* In :mod:`asyncio`, + :meth:`loop.sock_recv() <asyncio.AbstractEventLoop.sock_recv>`, + :meth:`loop.sock_sendall() <asyncio.AbstractEventLoop.sock_sendall>`, + :meth:`loop.sock_accept() <asyncio.AbstractEventLoop.sock_accept>`, + :meth:`loop.getaddrinfo() <asyncio.AbstractEventLoop.getaddrinfo>`, + :meth:`loop.getnameinfo() <asyncio.AbstractEventLoop.getnameinfo>` + have been changed to be proper coroutine methods to match their + documentation. Previously, these methods returned :class:`asyncio.Future` + instances. + (Contributed by Yury Selivanov in :issue:`32327`.) + +* :attr:`asyncio.Server.sockets` now returns a copy of the internal list + of server sockets, instead of returning it directly. + (Contributed by Yury Selivanov in :issue:`32662`.) + +* :attr:`Struct.format <struct.Struct.format>` is now a :class:`str` instance + instead of a :class:`bytes` instance. + (Contributed by Victor Stinner in :issue:`21071`.) + +* :mod:`argparse` subparsers are now required by default. This matches the + behaviour in Python 2. To add an optional subparser, pass + ``required=False`` to + :meth:`ArgumentParser.add_subparsers() <argparse.ArgumentParser.add_subparsers>`. + (Contributed by Anthony Sottile in :issue:`26510`.) + +* :meth:`ast.literal_eval()` is now stricter. Addition and subtraction of + arbitrary numbers are no longer allowed. + (Contributed by Serhiy Storchaka in :issue:`31778`.) + +* :meth:`Calendar.itermonthdates <calendar.Calendar.itermonthdates>` + will now consistently raise an exception when a date falls outside of the + ``0001-01-01`` through ``9999-12-31`` range. To support applications that + cannot tolerate such exceptions, the new + :meth:`Calendar.itermonthdays3 <calendar.Calendar.itermonthdays3>` and + :meth:`Calendar.itermonthdays4 <calendar.Calendar.itermonthdays4>` can be used. + The new methods return tuples and are not restricted by the range supported by + :class:`datetime.date`. + (Contributed by Alexander Belopolsky in :issue:`28292`.) + +* :class:`collections.ChainMap` now preserves the order of the underlying + mappings. (Contributed by Raymond Hettinger in :issue:`32792`.) + +* The ``submit()`` method of :class:`concurrent.futures.ThreadPoolExecutor` + and :class:`concurrent.futures.ProcessPoolExecutor` now raises + a :exc:`RuntimeError` if called during interpreter shutdown. + (Contributed by Mark Nemec in :issue:`33097`.) + +* The :class:`configparser.ConfigParser` constructor now uses ``read_dict()`` + to process the default values, making its behavior consistent with the + rest of the parser. Non-string keys and values in the defaults + dictionary are now being implicitly converted to strings. + (Contributed by James Tocknell in :issue:`23835`.) + Changes in the C API -------------------- -* The function :c:func:`PySlice_GetIndicesEx` is considered not safe for - resizable sequences. If the slice indices are not instances of :class:`int`, - but objects that implement the :meth:`!__index__` method, the sequence can be - resized after passing its length to :c:func:`!PySlice_GetIndicesEx`. This - can lead to returning indices out of the length of the sequence. For - avoiding possible problems use new functions :c:func:`PySlice_Unpack` and - :c:func:`PySlice_AdjustIndices`. - (Contributed by Serhiy Storchaka in :issue:`27867`.) +The function :c:func:`PySlice_GetIndicesEx` is considered unsafe for +resizable sequences. If the slice indices are not instances of :class:`int`, +but objects that implement the :meth:`!__index__` method, the sequence can be +resized after passing its length to :c:func:`!PySlice_GetIndicesEx`. This +can lead to returning indices out of the length of the sequence. For +avoiding possible problems use new functions :c:func:`PySlice_Unpack` and +:c:func:`PySlice_AdjustIndices`. +(Contributed by Serhiy Storchaka in :issue:`27867`.) CPython bytecode changes ------------------------ -* Added two new opcodes: :opcode:`LOAD_METHOD` and :opcode:`CALL_METHOD`. - (Contributed by Yury Selivanov and INADA Naoki in :issue:`26110`.) - -* Removed the :opcode:`STORE_ANNOTATION` opcode. - (Contributed by Mark Shannon in :issue:`32550`.) - - -Other CPython implementation changes ------------------------------------- +There are two new opcodes: :opcode:`LOAD_METHOD` and :opcode:`CALL_METHOD`. +(Contributed by Yury Selivanov and INADA Naoki in :issue:`26110`.) -* In preparation for potential future changes to the public CPython runtime - initialization API (see :pep:`432` for an initial, but somewhat outdated, - draft), CPython's internal startup - and configuration management logic has been significantly refactored. While - these updates are intended to be entirely transparent to both embedding - applications and users of the regular CPython CLI, they're being mentioned - here as the refactoring changes the internal order of various operations - during interpreter startup, and hence may uncover previously latent defects, - either in embedding applications, or in CPython itself. - (Initially contributed by Nick Coghlan and Eric Snow as part of - :issue:`22257`, and further updated by Nick, Eric, and Victor Stinner in a - number of other issues). Some known details affected: - - * :c:func:`PySys_AddWarnOptionUnicode` is not currently usable by embedding - applications due to the requirement to create a Unicode object prior to - calling `Py_Initialize`. Use :c:func:`PySys_AddWarnOption` instead. - * warnings filters added by an embedding application with - :c:func:`PySys_AddWarnOption` should now more consistently take precedence - over the default filters set by the interpreter - -* Due to changes in the way the default warnings filters are configured, - setting :c:data:`Py_BytesWarningFlag` to a value greater than one is no longer - sufficient to both emit :exc:`BytesWarning` messages and have them converted - to exceptions. Instead, the flag must be set (to cause the warnings to be - emitted in the first place), and an explicit ``error::BytesWarning`` - warnings filter added to convert them to exceptions. - -* CPython' :mod:`ssl` module requires OpenSSL 1.0.2 or 1.1 compatible libssl. - OpenSSL 1.0.1 has reached end of lifetime on 2016-12-31 and is no longer - supported. LibreSSL is temporarily not supported as well. LibreSSL releases - up to version 2.6.4 are missing required OpenSSL 1.0.2 APIs. - - -Documentation -============= +The :opcode:`STORE_ANNOTATION` opcode has been removed. +(Contributed by Mark Shannon in :issue:`32550`.) -.. _whatsnew37-pep545: -PEP 545: Python Documentation Translations ------------------------------------------- +Windows-only Changes +-------------------- -:pep:`545` describes the process to translate Python documentation, -and two translations have been added: +The file used to override :data:`sys.path` is now called +``<python-executable>._pth`` instead of ``'sys.path'``. +See :ref:`finding_modules` for more information. +(Contributed by Steve Dower in :issue:`28137`.) -- Japanese: https://docs.python.org/ja/ and associated GitHub - repository: https://github.com/python/python-docs-ja -- French: https://docs.python.org/fr/ and associated GitHub - repository: https://github.com/python/python-docs-fr +Other CPython implementation changes +------------------------------------ -(Contributed by Julien Palard, Inada Naoki, and Victor Stinner in -:issue:`26546`.) +In preparation for potential future changes to the public CPython runtime +initialization API (see :pep:`432` for an initial, but somewhat outdated, +draft), CPython's internal startup +and configuration management logic has been significantly refactored. While +these updates are intended to be entirely transparent to both embedding +applications and users of the regular CPython CLI, they're being mentioned +here as the refactoring changes the internal order of various operations +during interpreter startup, and hence may uncover previously latent defects, +either in embedding applications, or in CPython itself. +(Initially contributed by Nick Coghlan and Eric Snow as part of +:issue:`22257`, and further updated by Nick, Eric, and Victor Stinner in a +number of other issues). Some known details affected: + +* :c:func:`PySys_AddWarnOptionUnicode` is not currently usable by embedding + applications due to the requirement to create a Unicode object prior to + calling `Py_Initialize`. Use :c:func:`PySys_AddWarnOption` instead. + +* warnings filters added by an embedding application with + :c:func:`PySys_AddWarnOption` should now more consistently take precedence + over the default filters set by the interpreter + +Due to changes in the way the default warnings filters are configured, +setting :c:data:`Py_BytesWarningFlag` to a value greater than one is no longer +sufficient to both emit :exc:`BytesWarning` messages and have them converted +to exceptions. Instead, the flag must be set (to cause the warnings to be +emitted in the first place), and an explicit ``error::BytesWarning`` +warnings filter added to convert them to exceptions. From webhook-mailer at python.org Sat May 19 23:50:24 2018 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Sun, 20 May 2018 03:50:24 -0000 Subject: [Python-checkins] [3.6] bpo-30928: Update idlelib/NEWS.txt. (GH-6995) (GH-6997) Message-ID: <mailman.162.1526788227.2757.python-checkins@python.org> https://github.com/python/cpython/commit/09a5c077bd8d444e9701b4d1314160b8904434e0 commit: 09a5c077bd8d444e9701b4d1314160b8904434e0 branch: 3.6 author: Terry Jan Reedy <tjreedy at udel.edu> committer: GitHub <noreply at github.com> date: 2018-05-19T23:50:21-04:00 summary: [3.6] bpo-30928: Update idlelib/NEWS.txt. (GH-6995) (GH-6997) (cherry picked from commit 6b0d09b) files: M Lib/idlelib/NEWS.txt diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index 20ee68e0caca..110dbda09a74 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -3,6 +3,11 @@ Released on 2018-06-15? ====================================== +bpo-32831: Add docstrings and tests for codecontext.py. +Coverage is 100%. Patch by Cheryl Sabella. + +bpo-33564: Code context now recognizes async as a block opener. + bpo-29706: IDLE now colors async and await as keywords in 3.6. They become full keywords in 3.7. From webhook-mailer at python.org Sun May 20 01:13:55 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sun, 20 May 2018 05:13:55 -0000 Subject: [Python-checkins] bpo-23722: Fix docs for future __classcell__ changes. (GH-6999) Message-ID: <mailman.163.1526793236.2757.python-checkins@python.org> https://github.com/python/cpython/commit/8ae8e6af37f29163ee263e293570cb892dc5b5d5 commit: 8ae8e6af37f29163ee263e293570cb892dc5b5d5 branch: master author: Serhiy Storchaka <storchaka at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-20T08:13:52+03:00 summary: bpo-23722: Fix docs for future __classcell__ changes. (GH-6999) files: M Doc/reference/datamodel.rst M Doc/whatsnew/3.6.rst diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index b4a0dbf95ec0..cc8dc958a80a 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1968,7 +1968,7 @@ current call is identified based on the first argument passed to the method. be propagated up to the ``type.__new__`` call in order for the class to be initialised correctly. Failing to do so will result in a :exc:`DeprecationWarning` in Python 3.6, - and a :exc:`RuntimeWarning` in the future. + and a :exc:`RuntimeError` in Python 3.8. When using the default metaclass :class:`type`, or any metaclass that ultimately calls ``type.__new__``, the following additional customisation steps are diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst index f7fe70fa9417..c4b639528969 100644 --- a/Doc/whatsnew/3.6.rst +++ b/Doc/whatsnew/3.6.rst @@ -2261,7 +2261,8 @@ Changes in the Python API direct references from methods to the implicit ``__class__`` closure variable, the implicit ``__classcell__`` namespace entry must now be passed up to ``type.__new__`` for initialisation. Failing to do so will result in - a :exc:`DeprecationWarning` in 3.6 and a :exc:`RuntimeWarning` in the future. + a :exc:`DeprecationWarning` in Python 3.6 and a :exc:`RuntimeError` in + Python 3.8. Changes in the C API -------------------- From webhook-mailer at python.org Sun May 20 01:47:08 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sun, 20 May 2018 05:47:08 -0000 Subject: [Python-checkins] bpo-23722: Fix docs for future __classcell__ changes. (GH-6999) Message-ID: <mailman.164.1526795231.2757.python-checkins@python.org> https://github.com/python/cpython/commit/10a122c0d55b01b053126ef3fd4d9e05ab8f2372 commit: 10a122c0d55b01b053126ef3fd4d9e05ab8f2372 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-19T22:47:05-07:00 summary: bpo-23722: Fix docs for future __classcell__ changes. (GH-6999) (cherry picked from commit 8ae8e6af37f29163ee263e293570cb892dc5b5d5) Co-authored-by: Serhiy Storchaka <storchaka at gmail.com> files: M Doc/reference/datamodel.rst M Doc/whatsnew/3.6.rst diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index c08986f6c0a5..11a5c5469643 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1887,7 +1887,7 @@ current call is identified based on the first argument passed to the method. be propagated up to the ``type.__new__`` call in order for the class to be initialised correctly. Failing to do so will result in a :exc:`DeprecationWarning` in Python 3.6, - and a :exc:`RuntimeWarning` in the future. + and a :exc:`RuntimeError` in Python 3.8. When using the default metaclass :class:`type`, or any metaclass that ultimately calls ``type.__new__``, the following additional customisation steps are diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst index 6ebd0706d025..88146dc7bcb8 100644 --- a/Doc/whatsnew/3.6.rst +++ b/Doc/whatsnew/3.6.rst @@ -2270,7 +2270,8 @@ Changes in the Python API direct references from methods to the implicit ``__class__`` closure variable, the implicit ``__classcell__`` namespace entry must now be passed up to ``type.__new__`` for initialisation. Failing to do so will result in - a :exc:`DeprecationWarning` in 3.6 and a :exc:`RuntimeWarning` in the future. + a :exc:`DeprecationWarning` in Python 3.6 and a :exc:`RuntimeError` in + Python 3.8. Changes in the C API -------------------- From webhook-mailer at python.org Sun May 20 01:48:14 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sun, 20 May 2018 05:48:14 -0000 Subject: [Python-checkins] bpo-23722: Raise a RuntimeError for absent __classcell__. (GH-6931) Message-ID: <mailman.165.1526795296.2757.python-checkins@python.org> https://github.com/python/cpython/commit/f5e7b1999f46e592d42dfab51563ea5411946fb7 commit: f5e7b1999f46e592d42dfab51563ea5411946fb7 branch: master author: Serhiy Storchaka <storchaka at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-20T08:48:12+03:00 summary: bpo-23722: Raise a RuntimeError for absent __classcell__. (GH-6931) A DeprecationWarning was emitted in Python 3.6-3.7. files: A Misc/NEWS.d/next/Core and Builtins/2018-05-17-13-06-36.bpo-23722.xisqZk.rst M Doc/reference/datamodel.rst M Doc/whatsnew/3.8.rst M Lib/test/test_super.py M Python/bltinmodule.c diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index cc8dc958a80a..855f2412b139 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1967,8 +1967,7 @@ current call is identified based on the first argument passed to the method. as a ``__classcell__`` entry in the class namespace. If present, this must be propagated up to the ``type.__new__`` call in order for the class to be initialised correctly. - Failing to do so will result in a :exc:`DeprecationWarning` in Python 3.6, - and a :exc:`RuntimeError` in Python 3.8. + Failing to do so will result in a :exc:`RuntimeError` in Python 3.8. When using the default metaclass :class:`type`, or any metaclass that ultimately calls ``type.__new__``, the following additional customisation steps are diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 11538e26691c..9aad908f927f 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -146,6 +146,11 @@ Changes in the Python API a database if it does not exist. (Contributed by Serhiy Storchaka in :issue:`32749`.) +* A :exc:`RuntimeError` is now raised when the custom metaclass doesn't + provide the ``__classcell__`` entry in the namespace passed to + ``type.__new__``. A :exc:`DeprecationWarning` was emitted in Python + 3.6--3.7. (Contributed by Serhiy Storchaka in :issue:`23722`.) + CPython bytecode changes ------------------------ diff --git a/Lib/test/test_super.py b/Lib/test/test_super.py index cb2d7c32236b..5d94372bf6ec 100644 --- a/Lib/test/test_super.py +++ b/Lib/test/test_super.py @@ -1,8 +1,6 @@ """Unit tests for zero-argument super() & related machinery.""" import unittest -import warnings -from test.support import check_warnings class A: @@ -173,14 +171,10 @@ def __new__(cls, name, bases, namespace): test_namespace = namespace return None - # This case shouldn't trigger the __classcell__ deprecation warning - with check_warnings() as w: - warnings.simplefilter("always", DeprecationWarning) - class A(metaclass=Meta): - @staticmethod - def f(): - return __class__ - self.assertEqual(w.warnings, []) + class A(metaclass=Meta): + @staticmethod + def f(): + return __class__ self.assertIs(A, None) @@ -244,37 +238,19 @@ def __new__(cls, name, bases, namespace): namespace.pop('__classcell__', None) return super().__new__(cls, name, bases, namespace) - # The default case should continue to work without any warnings - with check_warnings() as w: - warnings.simplefilter("always", DeprecationWarning) - class WithoutClassRef(metaclass=Meta): - pass - self.assertEqual(w.warnings, []) + # The default case should continue to work without any errors + class WithoutClassRef(metaclass=Meta): + pass # With zero-arg super() or an explicit __class__ reference, we expect - # __build_class__ to emit a DeprecationWarning complaining that + # __build_class__ to raise a RuntimeError complaining that # __class__ was not set, and asking if __classcell__ was propagated # to type.__new__. - # In Python 3.7, that warning will become a RuntimeError. - expected_warning = ( - '__class__ not set.*__classcell__ propagated', - DeprecationWarning - ) - with check_warnings(expected_warning): - warnings.simplefilter("always", DeprecationWarning) + expected_error = '__class__ not set.*__classcell__ propagated' + with self.assertRaisesRegex(RuntimeError, expected_error): class WithClassRef(metaclass=Meta): def f(self): return __class__ - # Check __class__ still gets set despite the warning - self.assertIs(WithClassRef().f(), WithClassRef) - - # Check the warning is turned into an error as expected - with warnings.catch_warnings(): - warnings.simplefilter("error", DeprecationWarning) - with self.assertRaises(DeprecationWarning): - class WithClassRef(metaclass=Meta): - def f(self): - return __class__ def test___classcell___overwrite(self): # See issue #23722 diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-05-17-13-06-36.bpo-23722.xisqZk.rst b/Misc/NEWS.d/next/Core and Builtins/2018-05-17-13-06-36.bpo-23722.xisqZk.rst new file mode 100644 index 000000000000..dfd1e79786ab --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-05-17-13-06-36.bpo-23722.xisqZk.rst @@ -0,0 +1,4 @@ +A :exc:`RuntimeError` is now raised when the custom metaclass doesn't +provide the ``__classcell__`` entry in the namespace passed to +``type.__new__``. A :exc:`DeprecationWarning` was emitted in Python +3.6--3.7. diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 839258b87495..88a4bf991d88 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -254,30 +254,19 @@ builtin___build_class__(PyObject *self, PyObject *const *args, Py_ssize_t nargs, if (cls != NULL && PyType_Check(cls) && PyCell_Check(cell)) { PyObject *cell_cls = PyCell_GET(cell); if (cell_cls != cls) { - /* TODO: In 3.7, DeprecationWarning will become RuntimeError. - * At that point, cell_error won't be needed. - */ - int cell_error; if (cell_cls == NULL) { const char *msg = "__class__ not set defining %.200R as %.200R. " "Was __classcell__ propagated to type.__new__?"; - cell_error = PyErr_WarnFormat( - PyExc_DeprecationWarning, 1, msg, name, cls); + PyErr_Format(PyExc_RuntimeError, msg, name, cls); } else { const char *msg = "__class__ set to %.200R defining %.200R as %.200R"; PyErr_Format(PyExc_TypeError, msg, cell_cls, name, cls); - cell_error = 1; - } - if (cell_error) { - Py_DECREF(cls); - cls = NULL; - goto error; - } else { - /* Fill in the cell, since type.__new__ didn't do it */ - PyCell_Set(cell, cls); } + Py_DECREF(cls); + cls = NULL; + goto error; } } } From webhook-mailer at python.org Sun May 20 01:49:16 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sun, 20 May 2018 05:49:16 -0000 Subject: [Python-checkins] bpo-23722: Fix docs for future __classcell__ changes. (GH-6999) (GH-7000) Message-ID: <mailman.166.1526795358.2757.python-checkins@python.org> https://github.com/python/cpython/commit/f0af69faee902d4b80c07c100dbd528fd8df6832 commit: f0af69faee902d4b80c07c100dbd528fd8df6832 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Serhiy Storchaka <storchaka at gmail.com> date: 2018-05-20T08:49:13+03:00 summary: bpo-23722: Fix docs for future __classcell__ changes. (GH-6999) (GH-7000) (cherry picked from commit 8ae8e6af37f29163ee263e293570cb892dc5b5d5) Co-authored-by: Serhiy Storchaka <storchaka at gmail.com> files: M Doc/reference/datamodel.rst M Doc/whatsnew/3.6.rst diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index b4a0dbf95ec0..cc8dc958a80a 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1968,7 +1968,7 @@ current call is identified based on the first argument passed to the method. be propagated up to the ``type.__new__`` call in order for the class to be initialised correctly. Failing to do so will result in a :exc:`DeprecationWarning` in Python 3.6, - and a :exc:`RuntimeWarning` in the future. + and a :exc:`RuntimeError` in Python 3.8. When using the default metaclass :class:`type`, or any metaclass that ultimately calls ``type.__new__``, the following additional customisation steps are diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst index f7fe70fa9417..c4b639528969 100644 --- a/Doc/whatsnew/3.6.rst +++ b/Doc/whatsnew/3.6.rst @@ -2261,7 +2261,8 @@ Changes in the Python API direct references from methods to the implicit ``__class__`` closure variable, the implicit ``__classcell__`` namespace entry must now be passed up to ``type.__new__`` for initialisation. Failing to do so will result in - a :exc:`DeprecationWarning` in 3.6 and a :exc:`RuntimeWarning` in the future. + a :exc:`DeprecationWarning` in Python 3.6 and a :exc:`RuntimeError` in + Python 3.8. Changes in the C API -------------------- From solipsis at pitrou.net Sun May 20 05:09:28 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 20 May 2018 09:09:28 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=-2 Message-ID: <20180520090928.1.C21F30DBDCE915E9@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_collections leaked [-7, 1, 0] memory blocks, sum=-6 test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_spawn leaked [1, -2, 1] memory blocks, sum=0 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogDGYsr7', '--timeout', '7200'] From webhook-mailer at python.org Sun May 20 06:21:20 2018 From: webhook-mailer at python.org (Andrew Svetlov) Date: Sun, 20 May 2018 10:21:20 -0000 Subject: [Python-checkins] bpo-26819: Prevent proactor double read on resume (#6921) Message-ID: <mailman.167.1526811682.2757.python-checkins@python.org> https://github.com/python/cpython/commit/4151061855b571bf8a7579daa7875b8e243057b9 commit: 4151061855b571bf8a7579daa7875b8e243057b9 branch: master author: CtrlZvi <viz+github at flippedperspective.com> committer: Andrew Svetlov <andrew.svetlov at gmail.com> date: 2018-05-20T13:21:10+03:00 summary: bpo-26819: Prevent proactor double read on resume (#6921) The proactor event loop has a race condition when reading with pausing/resuming. `resume_reading()` unconditionally schedules the read function to read from the current future. If `resume_reading()` was called before the previously scheduled done callback fires, this results in two attempts to get the data from the most recent read and an assertion failure. This commit tracks whether or not `resume_reading` needs to reschedule the callback to restart the loop, preventing a second attempt to read the data. files: A Misc/NEWS.d/next/Library/2018-05-16-05-24-43.bpo-26819.taxbVT.rst M Lib/asyncio/proactor_events.py M Lib/test/test_asyncio/test_proactor_events.py diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py index b675c8200ce3..877dfb074670 100644 --- a/Lib/asyncio/proactor_events.py +++ b/Lib/asyncio/proactor_events.py @@ -161,6 +161,7 @@ def __init__(self, loop, sock, protocol, waiter=None, extra=None, server=None): super().__init__(loop, sock, protocol, waiter, extra, server) self._paused = False + self._reschedule_on_resume = False if protocols._is_buffered_protocol(protocol): self._loop_reading = self._loop_reading__get_buffer @@ -180,6 +181,7 @@ def pause_reading(self): if self._read_fut is not None and not self._read_fut.done(): self._read_fut.cancel() self._read_fut = None + self._reschedule_on_resume = True if self._loop.get_debug(): logger.debug("%r pauses reading", self) @@ -188,7 +190,9 @@ def resume_reading(self): if self._closing or not self._paused: return self._paused = False - self._loop.call_soon(self._loop_reading, self._read_fut) + if self._reschedule_on_resume: + self._loop.call_soon(self._loop_reading, self._read_fut) + self._reschedule_on_resume = False if self._loop.get_debug(): logger.debug("%r resumes reading", self) @@ -208,6 +212,7 @@ def _loop_reading__on_eof(self): def _loop_reading__data_received(self, fut=None): if self._paused: + self._reschedule_on_resume = True return data = None @@ -257,6 +262,7 @@ def _loop_reading__data_received(self, fut=None): def _loop_reading__get_buffer(self, fut=None): if self._paused: + self._reschedule_on_resume = True return nbytes = None diff --git a/Lib/test/test_asyncio/test_proactor_events.py b/Lib/test/test_asyncio/test_proactor_events.py index 98e698983eab..6313d594477a 100644 --- a/Lib/test/test_asyncio/test_proactor_events.py +++ b/Lib/test/test_asyncio/test_proactor_events.py @@ -334,7 +334,7 @@ def test_write_eof_duplex_pipe(self): def test_pause_resume_reading(self): tr = self.socket_transport() futures = [] - for msg in [b'data1', b'data2', b'data3', b'data4', b'']: + for msg in [b'data1', b'data2', b'data3', b'data4', b'data5', b'']: f = asyncio.Future(loop=self.loop) f.set_result(msg) futures.append(f) @@ -364,6 +364,13 @@ def test_pause_resume_reading(self): self.protocol.data_received.assert_called_with(b'data3') self.loop._run_once() self.protocol.data_received.assert_called_with(b'data4') + + tr.pause_reading() + tr.resume_reading() + self.loop.call_exception_handler = mock.Mock() + self.loop._run_once() + self.loop.call_exception_handler.assert_not_called() + self.protocol.data_received.assert_called_with(b'data5') tr.close() self.assertFalse(tr.is_reading()) diff --git a/Misc/NEWS.d/next/Library/2018-05-16-05-24-43.bpo-26819.taxbVT.rst b/Misc/NEWS.d/next/Library/2018-05-16-05-24-43.bpo-26819.taxbVT.rst new file mode 100644 index 000000000000..d407a5800318 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-16-05-24-43.bpo-26819.taxbVT.rst @@ -0,0 +1,2 @@ +Fix race condition with `ReadTransport.resume_reading` in Windows proactor +event loop. From webhook-mailer at python.org Sun May 20 06:57:36 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sun, 20 May 2018 10:57:36 -0000 Subject: [Python-checkins] bpo-26819: Prevent proactor double read on resume (GH-6921) Message-ID: <mailman.168.1526813858.2757.python-checkins@python.org> https://github.com/python/cpython/commit/28ea38b97b2bfbde9f387a8b90b02d05b93c895c commit: 28ea38b97b2bfbde9f387a8b90b02d05b93c895c branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-20T03:57:32-07:00 summary: bpo-26819: Prevent proactor double read on resume (GH-6921) The proactor event loop has a race condition when reading with pausing/resuming. `resume_reading()` unconditionally schedules the read function to read from the current future. If `resume_reading()` was called before the previously scheduled done callback fires, this results in two attempts to get the data from the most recent read and an assertion failure. This commit tracks whether or not `resume_reading` needs to reschedule the callback to restart the loop, preventing a second attempt to read the data. (cherry picked from commit 4151061855b571bf8a7579daa7875b8e243057b9) Co-authored-by: CtrlZvi <viz+github at flippedperspective.com> files: A Misc/NEWS.d/next/Library/2018-05-16-05-24-43.bpo-26819.taxbVT.rst M Lib/asyncio/proactor_events.py M Lib/test/test_asyncio/test_proactor_events.py diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py index b675c8200ce3..877dfb074670 100644 --- a/Lib/asyncio/proactor_events.py +++ b/Lib/asyncio/proactor_events.py @@ -161,6 +161,7 @@ def __init__(self, loop, sock, protocol, waiter=None, extra=None, server=None): super().__init__(loop, sock, protocol, waiter, extra, server) self._paused = False + self._reschedule_on_resume = False if protocols._is_buffered_protocol(protocol): self._loop_reading = self._loop_reading__get_buffer @@ -180,6 +181,7 @@ def pause_reading(self): if self._read_fut is not None and not self._read_fut.done(): self._read_fut.cancel() self._read_fut = None + self._reschedule_on_resume = True if self._loop.get_debug(): logger.debug("%r pauses reading", self) @@ -188,7 +190,9 @@ def resume_reading(self): if self._closing or not self._paused: return self._paused = False - self._loop.call_soon(self._loop_reading, self._read_fut) + if self._reschedule_on_resume: + self._loop.call_soon(self._loop_reading, self._read_fut) + self._reschedule_on_resume = False if self._loop.get_debug(): logger.debug("%r resumes reading", self) @@ -208,6 +212,7 @@ def _loop_reading__on_eof(self): def _loop_reading__data_received(self, fut=None): if self._paused: + self._reschedule_on_resume = True return data = None @@ -257,6 +262,7 @@ def _loop_reading__data_received(self, fut=None): def _loop_reading__get_buffer(self, fut=None): if self._paused: + self._reschedule_on_resume = True return nbytes = None diff --git a/Lib/test/test_asyncio/test_proactor_events.py b/Lib/test/test_asyncio/test_proactor_events.py index 98e698983eab..6313d594477a 100644 --- a/Lib/test/test_asyncio/test_proactor_events.py +++ b/Lib/test/test_asyncio/test_proactor_events.py @@ -334,7 +334,7 @@ def test_write_eof_duplex_pipe(self): def test_pause_resume_reading(self): tr = self.socket_transport() futures = [] - for msg in [b'data1', b'data2', b'data3', b'data4', b'']: + for msg in [b'data1', b'data2', b'data3', b'data4', b'data5', b'']: f = asyncio.Future(loop=self.loop) f.set_result(msg) futures.append(f) @@ -364,6 +364,13 @@ def test_pause_resume_reading(self): self.protocol.data_received.assert_called_with(b'data3') self.loop._run_once() self.protocol.data_received.assert_called_with(b'data4') + + tr.pause_reading() + tr.resume_reading() + self.loop.call_exception_handler = mock.Mock() + self.loop._run_once() + self.loop.call_exception_handler.assert_not_called() + self.protocol.data_received.assert_called_with(b'data5') tr.close() self.assertFalse(tr.is_reading()) diff --git a/Misc/NEWS.d/next/Library/2018-05-16-05-24-43.bpo-26819.taxbVT.rst b/Misc/NEWS.d/next/Library/2018-05-16-05-24-43.bpo-26819.taxbVT.rst new file mode 100644 index 000000000000..d407a5800318 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-16-05-24-43.bpo-26819.taxbVT.rst @@ -0,0 +1,2 @@ +Fix race condition with `ReadTransport.resume_reading` in Windows proactor +event loop. From webhook-mailer at python.org Sun May 20 09:30:34 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sun, 20 May 2018 13:30:34 -0000 Subject: [Python-checkins] bpo-33584: Fix several minor bugs in asyncio. (GH-7003) Message-ID: <mailman.169.1526823035.2757.python-checkins@python.org> https://github.com/python/cpython/commit/6655354afcd116c27486bb5ba1dfa50b369d8d85 commit: 6655354afcd116c27486bb5ba1dfa50b369d8d85 branch: master author: Serhiy Storchaka <storchaka at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-20T16:30:31+03:00 summary: bpo-33584: Fix several minor bugs in asyncio. (GH-7003) Fix the following bugs in the C implementation: * get_future_loop() silenced all exceptions raised when look up the get_loop attribute, not just an AttributeError. * enter_task() silenced all exceptions raised when look up the current task, not just a KeyError. * repr() was called for a borrowed link in enter_task() and task_step_impl(). * str() was used instead of repr() in formatting one error message (in Python implementation too). * There where few reference leaks in error cases. files: M Lib/asyncio/tasks.py M Modules/_asynciomodule.c diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index 3590748c477a..5df1af6642e4 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -261,7 +261,7 @@ def __step(self, exc=None): # Yielding a generator is just wrong. new_exc = RuntimeError( f'yield was used instead of yield from for ' - f'generator in task {self!r} with {result}') + f'generator in task {self!r} with {result!r}') self._loop.call_soon( self.__step, new_exc, context=self._context) else: diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index d66cc4cf0a5f..6d7249a58009 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -201,6 +201,7 @@ get_future_loop(PyObject *fut) _Py_IDENTIFIER(get_loop); _Py_IDENTIFIER(_loop); + PyObject *getloop; if (Future_CheckExact(fut) || Task_CheckExact(fut)) { PyObject *loop = ((FutureObj *)fut)->fut_loop; @@ -208,14 +209,15 @@ get_future_loop(PyObject *fut) return loop; } - PyObject *getloop = _PyObject_GetAttrId(fut, &PyId_get_loop); + if (_PyObject_LookupAttrId(fut, &PyId_get_loop, &getloop) < 0) { + return NULL; + } if (getloop != NULL) { PyObject *res = _PyObject_CallNoArg(getloop); Py_DECREF(getloop); return res; } - PyErr_Clear(); return _PyObject_GetAttrId(fut, &PyId__loop); } @@ -1877,17 +1879,19 @@ enter_task(PyObject *loop, PyObject *task) } item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash); if (item != NULL) { + Py_INCREF(item); PyErr_Format( PyExc_RuntimeError, "Cannot enter into task %R while another " \ "task %R is being executed.", task, item, NULL); + Py_DECREF(item); return -1; } - if (_PyDict_SetItem_KnownHash(current_tasks, loop, task, hash) < 0) { + if (PyErr_Occurred()) { return -1; } - return 0; + return _PyDict_SetItem_KnownHash(current_tasks, loop, task, hash); } @@ -2075,6 +2079,7 @@ _asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop) if (loop == Py_None) { loop = get_event_loop(); if (loop == NULL) { + Py_DECREF(current_task_func); return NULL; } ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL); @@ -2107,11 +2112,6 @@ _asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop) PyObject *res; PyObject *all_tasks_func; - all_tasks_func = _PyObject_GetAttrId(asyncio_mod, &PyId_all_tasks); - if (all_tasks_func == NULL) { - return NULL; - } - if (PyErr_WarnEx(PyExc_PendingDeprecationWarning, "Task.all_tasks() is deprecated, " \ "use asyncio.all_tasks() instead", @@ -2119,6 +2119,11 @@ _asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop) return NULL; } + all_tasks_func = _PyObject_GetAttrId(asyncio_mod, &PyId_all_tasks); + if (all_tasks_func == NULL) { + return NULL; + } + res = PyObject_CallFunctionObjArgs(all_tasks_func, loop, NULL); Py_DECREF(all_tasks_func); return res; @@ -2723,6 +2728,7 @@ task_step_impl(TaskObj *task, PyObject *exc) PyObject *add_cb = _PyObject_GetAttrId( result, &PyId_add_done_callback); if (add_cb == NULL) { + Py_DECREF(wrapper); goto fail; } PyObject *stack[2]; @@ -2788,19 +2794,19 @@ task_step_impl(TaskObj *task, PyObject *exc) } if (res == 1) { /* `result` is a generator */ - PyObject *ret; - ret = task_set_error_soon( + o = task_set_error_soon( task, PyExc_RuntimeError, "yield was used instead of yield from for " - "generator in task %R with %S", task, result); + "generator in task %R with %R", task, result); Py_DECREF(result); - return ret; + return o; } /* The `result` is none of the above */ - Py_DECREF(result); - return task_set_error_soon( + o = task_set_error_soon( task, PyExc_RuntimeError, "Task got bad yield: %R", result); + Py_DECREF(result); + return o; self_await: o = task_set_error_soon( From webhook-mailer at python.org Sun May 20 10:33:58 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sun, 20 May 2018 14:33:58 -0000 Subject: [Python-checkins] [3.6] bpo-33584: Fix several minor bugs in asyncio. (GH-7003) (#7006) Message-ID: <mailman.170.1526826839.2757.python-checkins@python.org> https://github.com/python/cpython/commit/49418f6df7a234243a470260e1b59e9e4c0e4768 commit: 49418f6df7a234243a470260e1b59e9e4c0e4768 branch: 3.6 author: Serhiy Storchaka <storchaka at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-20T17:33:55+03:00 summary: [3.6] bpo-33584: Fix several minor bugs in asyncio. (GH-7003) (#7006) * repr() was called for a borrowed link. * str() was used instead of repr() in formatting one error message. (cherry picked from commit 6655354afcd116c27486bb5ba1dfa50b369d8d85) files: M Lib/asyncio/tasks.py M Modules/_asynciomodule.c diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index 9fe2a2fabf07..a294dfbf5e57 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -233,7 +233,7 @@ def _step(self, exc=None): self._step, RuntimeError( 'yield was used instead of yield from for ' - 'generator in task {!r} with {}'.format( + 'generator in task {!r} with {!r}'.format( self, result))) else: # Yielding something else is an error. diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index f53387115e73..1430097f82da 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -2248,19 +2248,19 @@ task_step_impl(TaskObj *task, PyObject *exc) } if (res == 1) { /* `result` is a generator */ - PyObject *ret; - ret = task_set_error_soon( + o = task_set_error_soon( task, PyExc_RuntimeError, "yield was used instead of yield from for " - "generator in task %R with %S", task, result); + "generator in task %R with %R", task, result); Py_DECREF(result); - return ret; + return o; } /* The `result` is none of the above */ - Py_DECREF(result); - return task_set_error_soon( + o = task_set_error_soon( task, PyExc_RuntimeError, "Task got bad yield: %R", result); + Py_DECREF(result); + return o; self_await: o = task_set_error_soon( From webhook-mailer at python.org Sun May 20 10:34:31 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sun, 20 May 2018 14:34:31 -0000 Subject: [Python-checkins] bpo-33584: Fix several minor bugs in asyncio. (GH-7003) (GH-7005) Message-ID: <mailman.171.1526826873.2757.python-checkins@python.org> https://github.com/python/cpython/commit/52d1741c954448cd9ce3f705402e88211b8d4136 commit: 52d1741c954448cd9ce3f705402e88211b8d4136 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Serhiy Storchaka <storchaka at gmail.com> date: 2018-05-20T17:34:28+03:00 summary: bpo-33584: Fix several minor bugs in asyncio. (GH-7003) (GH-7005) Fix the following bugs in the C implementation: * get_future_loop() silenced all exceptions raised when look up the get_loop attribute, not just an AttributeError. * enter_task() silenced all exceptions raised when look up the current task, not just a KeyError. * repr() was called for a borrowed link in enter_task() and task_step_impl(). * str() was used instead of repr() in formatting one error message (in Python implementation too). * There where few reference leaks in error cases. (cherry picked from commit 6655354afcd116c27486bb5ba1dfa50b369d8d85) Co-authored-by: Serhiy Storchaka <storchaka at gmail.com> files: M Lib/asyncio/tasks.py M Modules/_asynciomodule.c diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index 3590748c477a..5df1af6642e4 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -261,7 +261,7 @@ def __step(self, exc=None): # Yielding a generator is just wrong. new_exc = RuntimeError( f'yield was used instead of yield from for ' - f'generator in task {self!r} with {result}') + f'generator in task {self!r} with {result!r}') self._loop.call_soon( self.__step, new_exc, context=self._context) else: diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index d66cc4cf0a5f..6d7249a58009 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -201,6 +201,7 @@ get_future_loop(PyObject *fut) _Py_IDENTIFIER(get_loop); _Py_IDENTIFIER(_loop); + PyObject *getloop; if (Future_CheckExact(fut) || Task_CheckExact(fut)) { PyObject *loop = ((FutureObj *)fut)->fut_loop; @@ -208,14 +209,15 @@ get_future_loop(PyObject *fut) return loop; } - PyObject *getloop = _PyObject_GetAttrId(fut, &PyId_get_loop); + if (_PyObject_LookupAttrId(fut, &PyId_get_loop, &getloop) < 0) { + return NULL; + } if (getloop != NULL) { PyObject *res = _PyObject_CallNoArg(getloop); Py_DECREF(getloop); return res; } - PyErr_Clear(); return _PyObject_GetAttrId(fut, &PyId__loop); } @@ -1877,17 +1879,19 @@ enter_task(PyObject *loop, PyObject *task) } item = _PyDict_GetItem_KnownHash(current_tasks, loop, hash); if (item != NULL) { + Py_INCREF(item); PyErr_Format( PyExc_RuntimeError, "Cannot enter into task %R while another " \ "task %R is being executed.", task, item, NULL); + Py_DECREF(item); return -1; } - if (_PyDict_SetItem_KnownHash(current_tasks, loop, task, hash) < 0) { + if (PyErr_Occurred()) { return -1; } - return 0; + return _PyDict_SetItem_KnownHash(current_tasks, loop, task, hash); } @@ -2075,6 +2079,7 @@ _asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop) if (loop == Py_None) { loop = get_event_loop(); if (loop == NULL) { + Py_DECREF(current_task_func); return NULL; } ret = PyObject_CallFunctionObjArgs(current_task_func, loop, NULL); @@ -2107,11 +2112,6 @@ _asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop) PyObject *res; PyObject *all_tasks_func; - all_tasks_func = _PyObject_GetAttrId(asyncio_mod, &PyId_all_tasks); - if (all_tasks_func == NULL) { - return NULL; - } - if (PyErr_WarnEx(PyExc_PendingDeprecationWarning, "Task.all_tasks() is deprecated, " \ "use asyncio.all_tasks() instead", @@ -2119,6 +2119,11 @@ _asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop) return NULL; } + all_tasks_func = _PyObject_GetAttrId(asyncio_mod, &PyId_all_tasks); + if (all_tasks_func == NULL) { + return NULL; + } + res = PyObject_CallFunctionObjArgs(all_tasks_func, loop, NULL); Py_DECREF(all_tasks_func); return res; @@ -2723,6 +2728,7 @@ task_step_impl(TaskObj *task, PyObject *exc) PyObject *add_cb = _PyObject_GetAttrId( result, &PyId_add_done_callback); if (add_cb == NULL) { + Py_DECREF(wrapper); goto fail; } PyObject *stack[2]; @@ -2788,19 +2794,19 @@ task_step_impl(TaskObj *task, PyObject *exc) } if (res == 1) { /* `result` is a generator */ - PyObject *ret; - ret = task_set_error_soon( + o = task_set_error_soon( task, PyExc_RuntimeError, "yield was used instead of yield from for " - "generator in task %R with %S", task, result); + "generator in task %R with %R", task, result); Py_DECREF(result); - return ret; + return o; } /* The `result` is none of the above */ - Py_DECREF(result); - return task_set_error_soon( + o = task_set_error_soon( task, PyExc_RuntimeError, "Task got bad yield: %R", result); + Py_DECREF(result); + return o; self_await: o = task_set_error_soon( From webhook-mailer at python.org Sun May 20 10:38:04 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sun, 20 May 2018 14:38:04 -0000 Subject: [Python-checkins] Docs: be less specific about python versions (GH-6985) Message-ID: <mailman.172.1526827085.2757.python-checkins@python.org> https://github.com/python/cpython/commit/9572132ab3c2edddb8087a0112116da866373f79 commit: 9572132ab3c2edddb8087a0112116da866373f79 branch: master author: Eitan Adler <grimreaper at users.noreply.github.com> committer: Serhiy Storchaka <storchaka at gmail.com> date: 2018-05-20T17:38:01+03:00 summary: Docs: be less specific about python versions (GH-6985) CPython 3.5 is old now, and we don't bump this version often, so lets avoid using specific versions. files: M Doc/howto/clinic.rst diff --git a/Doc/howto/clinic.rst b/Doc/howto/clinic.rst index 788a0eee2ba1..695fbb1be192 100644 --- a/Doc/howto/clinic.rst +++ b/Doc/howto/clinic.rst @@ -22,8 +22,8 @@ Argument Clinic How-To compatibility for future versions. In other words: if you maintain an external C extension for CPython, you're welcome to experiment with Argument Clinic in your own code. But the - version of Argument Clinic that ships with CPython 3.5 *could* - be totally incompatible and break all your code. + version of Argument Clinic that ships with the next version + of CPython *could* be totally incompatible and break all your code. The Goals Of Argument Clinic ============================ From webhook-mailer at python.org Sun May 20 11:00:24 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sun, 20 May 2018 15:00:24 -0000 Subject: [Python-checkins] bpo-30940: Updating round() docs. (GH-6342) Message-ID: <mailman.173.1526828425.2757.python-checkins@python.org> https://github.com/python/cpython/commit/900c48dba3f3eb8fb03ea766a5646f81c3bf3e9c commit: 900c48dba3f3eb8fb03ea766a5646f81c3bf3e9c branch: master author: Lisa Roach <lisaroach14 at gmail.com> committer: Serhiy Storchaka <storchaka at gmail.com> date: 2018-05-20T18:00:18+03:00 summary: bpo-30940: Updating round() docs. (GH-6342) files: M Doc/library/functions.rst diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index 3b05a3a4ed32..457e1c34ec9a 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -1329,11 +1329,12 @@ are always available. They are listed here in alphabetical order. equally close, rounding is done toward the even choice (so, for example, both ``round(0.5)`` and ``round(-0.5)`` are ``0``, and ``round(1.5)`` is ``2``). Any integer value is valid for *ndigits* (positive, zero, or - negative). The return value is an integer if called with one argument, - otherwise of the same type as *number*. + negative). The return value is an integer if *ndigits* is omitted or + ``None``. + Otherwise the return value has the same type as *number*. - For a general Python object ``number``, ``round(number, ndigits)`` delegates to - ``number.__round__(ndigits)``. + For a general Python object ``number``, ``round`` delegates to + ``number.__round__``. .. note:: From webhook-mailer at python.org Sun May 20 11:03:27 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sun, 20 May 2018 15:03:27 -0000 Subject: [Python-checkins] bpo-33542: Ignore DUID in uuid.get_node on Windows. (GH-6922) Message-ID: <mailman.174.1526828610.2757.python-checkins@python.org> https://github.com/python/cpython/commit/c66c342cb42ab8a88884527ddfe3a5086bc06316 commit: c66c342cb42ab8a88884527ddfe3a5086bc06316 branch: master author: CtrlZvi <viz+github at flippedperspective.com> committer: Serhiy Storchaka <storchaka at gmail.com> date: 2018-05-20T18:03:25+03:00 summary: bpo-33542: Ignore DUID in uuid.get_node on Windows. (GH-6922) uuid._ipconfig_getnode did not validate the maximum length of the value, so long as the value had the same type of formatting as a MAC address. This let it select DUIDs as MAC addresses. It now requires an exact length match. files: A Misc/NEWS.d/next/Library/2018-05-16-09-30-27.bpo-33542.idNAcs.rst M Lib/uuid.py M Misc/ACKS diff --git a/Lib/uuid.py b/Lib/uuid.py index 9cb73e877181..66383218e70c 100644 --- a/Lib/uuid.py +++ b/Lib/uuid.py @@ -488,7 +488,7 @@ def _ipconfig_getnode(): with proc: for line in proc.stdout: value = line.split(':')[-1].strip().lower() - if re.match('([0-9a-f][0-9a-f]-){5}[0-9a-f][0-9a-f]', value): + if re.fullmatch('(?:[0-9a-f][0-9a-f]-){5}[0-9a-f][0-9a-f]', value): mac = int(value.replace('-', ''), 16) if _is_universal(mac): return mac diff --git a/Misc/ACKS b/Misc/ACKS index b1f1e8a4b8de..cb7f4cd0275b 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -428,6 +428,7 @@ Ulrich Eckhardt David Edelsohn John Edmonds Grant Edwards +Zvi Effron John Ehresman Tal Einat Eric Eisner diff --git a/Misc/NEWS.d/next/Library/2018-05-16-09-30-27.bpo-33542.idNAcs.rst b/Misc/NEWS.d/next/Library/2018-05-16-09-30-27.bpo-33542.idNAcs.rst new file mode 100644 index 000000000000..16ba799131f4 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-16-09-30-27.bpo-33542.idNAcs.rst @@ -0,0 +1,2 @@ +Prevent ``uuid.get_node`` from using a DUID instead of a MAC on Windows. +Patch by Zvi Effron From webhook-mailer at python.org Sun May 20 11:06:11 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sun, 20 May 2018 15:06:11 -0000 Subject: [Python-checkins] [3.7] bpo-33475: Fix and improve converting annotations to strings. (GH-6774). (GH-6927) Message-ID: <mailman.175.1526828774.2757.python-checkins@python.org> https://github.com/python/cpython/commit/b32f8897eafcf335f9e9899c5e622a0b27679437 commit: b32f8897eafcf335f9e9899c5e622a0b27679437 branch: 3.7 author: Serhiy Storchaka <storchaka at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-20T18:06:08+03:00 summary: [3.7] bpo-33475: Fix and improve converting annotations to strings. (GH-6774). (GH-6927) (cherry picked from commit 64fddc423fcbe90b8088446c63385ec0aaf3077c) Co-authored-by: Serhiy Storchaka <storchaka at gmail.com> files: A Misc/NEWS.d/next/Core and Builtins/2018-05-13-01-26-18.bpo-33475.rI0y1U.rst M Include/ast.h M Lib/test/test_future.py M Python/ast_unparse.c M Python/compile.c diff --git a/Include/ast.h b/Include/ast.h index 639c4f82325a..5bc2b05b3e94 100644 --- a/Include/ast.h +++ b/Include/ast.h @@ -19,9 +19,7 @@ PyAPI_FUNC(mod_ty) PyAST_FromNodeObject( #ifndef Py_LIMITED_API /* _PyAST_ExprAsUnicode is defined in ast_unparse.c */ -PyAPI_FUNC(PyObject *) _PyAST_ExprAsUnicode( - expr_ty e, - int omit_parens); +PyAPI_FUNC(PyObject *) _PyAST_ExprAsUnicode(expr_ty); #endif /* !Py_LIMITED_API */ diff --git a/Lib/test/test_future.py b/Lib/test/test_future.py index 29c4632e7e50..61cd63479d85 100644 --- a/Lib/test/test_future.py +++ b/Lib/test/test_future.py @@ -157,55 +157,76 @@ def test_annotations(self): eq('True or False or None') eq('True and False') eq('True and False and None') - eq('(Name1 and Name2) or Name3') - eq('Name1 or (Name2 and Name3)') - eq('(Name1 and Name2) or (Name3 and Name4)') - eq('Name1 or (Name2 and Name3) or Name4') + eq('Name1 and Name2 or Name3') + eq('Name1 and (Name2 or Name3)') + eq('Name1 or Name2 and Name3') + eq('(Name1 or Name2) and Name3') + eq('Name1 and Name2 or Name3 and Name4') + eq('Name1 or Name2 and Name3 or Name4') + eq('a + b + (c + d)') + eq('a * b * (c * d)') + eq('(a ** b) ** c ** d') eq('v1 << 2') eq('1 >> v2') - eq(r'1 % finished') - eq('((1 + v2) - (v3 * 4)) ^ (((5 ** v6) / 7) // 8)') + eq('1 % finished') + eq('1 + v2 - v3 * 4 ^ 5 ** v6 / 7 // 8') eq('not great') + eq('not not great') eq('~great') eq('+value') + eq('++value') eq('-1') - eq('(~int) and (not ((v1 ^ (123 + v2)) | True))') + eq('~int and not v1 ^ 123 + v2 | True') + eq('a + (not b)') eq('lambda arg: None') eq('lambda a=True: a') eq('lambda a, b, c=True: a') - eq("lambda a, b, c=True, *, d=(1 << v2), e='str': a") - eq("lambda a, b, c=True, *vararg, d=(v1 << 2), e='str', **kwargs: a + b") + eq("lambda a, b, c=True, *, d=1 << v2, e='str': a") + eq("lambda a, b, c=True, *vararg, d=v1 << 2, e='str', **kwargs: a + b") + eq('lambda x: lambda y: x + y') eq('1 if True else 2') - eq('(str or None) if True else (str or bytes or None)') - eq('(str or None) if (1 if True else 2) else (str or bytes or None)') - eq("{'2.7': dead, '3.7': (long_live or die_hard)}") - eq("{'2.7': dead, '3.7': (long_live or die_hard), **{'3.6': verygood}}") + eq('str or None if int or True else str or bytes or None') + eq('str or None if (1 if True else 2) else str or bytes or None') + eq("0 if not x else 1 if x > 0 else -1") + eq("(1 if x > 0 else -1) if x else 0") + eq("{'2.7': dead, '3.7': long_live or die_hard}") + eq("{'2.7': dead, '3.7': long_live or die_hard, **{'3.6': verygood}}") eq("{**a, **b, **c}") - eq("{'2.7', '3.6', '3.7', '3.8', '3.9', ('4.0' if gilectomy else '3.10')}") - eq("({'a': 'b'}, (True or False), (+value), 'string', b'bytes') or None") + eq("{'2.7', '3.6', '3.7', '3.8', '3.9', '4.0' if gilectomy else '3.10'}") + eq("{*a, *b, *c}") + eq("({'a': 'b'}, True or False, +value, 'string', b'bytes') or None") eq("()") - eq("(1,)") - eq("(1, 2)") - eq("(1, 2, 3)") + eq("(a,)") + eq("(a, b)") + eq("(a, b, c)") + eq("(*a, *b, *c)") eq("[]") - eq("[1, 2, 3, 4, 5, 6, 7, 8, 9, (10 or A), (11 or B), (12 or C)]") + eq("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10 or A, 11 or B, 12 or C]") + eq("[*a, *b, *c]") eq("{i for i in (1, 2, 3)}") - eq("{(i ** 2) for i in (1, 2, 3)}") - eq("{(i ** 2) for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))}") - eq("{((i ** 2) + j) for i in (1, 2, 3) for j in (1, 2, 3)}") + eq("{i ** 2 for i in (1, 2, 3)}") + eq("{i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))}") + eq("{i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3)}") eq("[i for i in (1, 2, 3)]") - eq("[(i ** 2) for i in (1, 2, 3)]") - eq("[(i ** 2) for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))]") - eq("[((i ** 2) + j) for i in (1, 2, 3) for j in (1, 2, 3)]") - eq(r"{i: 0 for i in (1, 2, 3)}") + eq("[i ** 2 for i in (1, 2, 3)]") + eq("[i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c'))]") + eq("[i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3)]") + eq("(i for i in (1, 2, 3))") + eq("(i ** 2 for i in (1, 2, 3))") + eq("(i ** 2 for i, _ in ((1, 'a'), (2, 'b'), (3, 'c')))") + eq("(i ** 2 + j for i in (1, 2, 3) for j in (1, 2, 3))") + eq("{i: 0 for i in (1, 2, 3)}") eq("{i: j for i, j in ((1, 'a'), (2, 'b'), (3, 'c'))}") + eq("[(x, y) for x, y in (a, b)]") + eq("[(x,) for x, in (a,)]") eq("Python3 > Python2 > COBOL") eq("Life is Life") eq("call()") eq("call(arg)") eq("call(kwarg='hey')") eq("call(arg, kwarg='hey')") - eq("call(arg, another, kwarg='hey', **kwargs)") + eq("call(arg, *args, another, kwarg='hey')") + eq("call(arg, another, kwarg='hey', **kwargs, kwarg2='ho')") eq("lukasz.langa.pl") eq("call.me(maybe)") eq("1 .real") @@ -213,6 +234,7 @@ def test_annotations(self): eq("....__class__") eq("list[str]") eq("dict[str, int]") + eq("set[str,]") eq("tuple[str, ...]") eq("tuple[str, int, float, dict[str, int]]") eq("slice[0]") @@ -222,49 +244,28 @@ def test_annotations(self): eq("slice[:-1]") eq("slice[1:]") eq("slice[::-1]") - eq('(str or None) if (sys.version_info[0] > (3,)) else (str or bytes or None)') + eq("slice[()]") + eq("slice[a, b:c, d:e:f]") + eq("slice[(x for x in a)]") + eq('str or None if sys.version_info[0] > (3,) else str or bytes or None') eq("f'f-string without formatted values is just a string'") eq("f'{{NOT a formatted value}}'") eq("f'some f-string with {a} {few():.2f} {formatted.values!r}'") eq('''f"{f'{nested} inner'} outer"''') eq("f'space between opening braces: { {a for a in (1, 2, 3)}}'") - - def test_annotations_inexact(self): - """Source formatting is not always preserved - - This is due to reconstruction from AST. We *need to* put the parens - in nested expressions because we don't know if the source code - had them in the first place or not. - """ - eq = partial(self.assertAnnotationEqual, drop_parens=True) - eq('Name1 and Name2 or Name3') - eq('Name1 or Name2 and Name3') - eq('Name1 and Name2 or Name3 and Name4') - eq('Name1 or Name2 and Name3 or Name4') - eq('1 + v2 - v3 * 4 ^ v5 ** 6 / 7 // 8') - eq('~int and not v1 ^ 123 + v2 | True') - eq('str or None if True else str or bytes or None') - eq("{'2.7': dead, '3.7': long_live or die_hard}") - eq("{'2.7', '3.6', '3.7', '3.8', '3.9', '4.0' if gilectomy else '3.10'}") - eq("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10 or A, 11 or B, 12 or C]") - # Consequently, we always drop unnecessary parens if they were given in - # the outer scope: - some_name = self.getActual("(SomeName)") - self.assertEqual(some_name, 'SomeName') - # Interestingly, in the case of tuples (and generator expressions) the - # parens are *required* by the Python syntax in the annotation context. - # But there's no point storing that detail in __annotations__ so we're - # fine with the parens-less form. - eq = partial(self.assertAnnotationEqual, is_tuple=True) - eq("(Good, Bad, Ugly)") - eq("(i for i in (1, 2, 3))") - eq("((i ** 2) for i in (1, 2, 3))") - eq("((i ** 2) for i, _ in ((1, 'a'), (2, 'b'), (3, 'c')))") - eq("(((i ** 2) + j) for i in (1, 2, 3) for j in (1, 2, 3))") - eq("(*starred)") + eq("f'{(lambda x: x)}'") + eq("f'{(None if a else lambda x: x)}'") eq('(yield from outside_of_generator)') eq('(yield)') - eq('(await some.complicated[0].call(with_args=(True or (1 is not 1))))') + eq('(yield a + b)') + eq('await some.complicated[0].call(with_args=True or 1 is not 1)') + eq('[x for x in (a if b else c)]') + eq('[x for x in a if (b if c else d)]') + eq('f(x for x in a)') + eq('f(1, (x for x in a))') + eq('f((x for x in a), 2)') + eq('(((a)))', 'a') + eq('(((a, b)))', '(a, b)') if __name__ == "__main__": diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-05-13-01-26-18.bpo-33475.rI0y1U.rst b/Misc/NEWS.d/next/Core and Builtins/2018-05-13-01-26-18.bpo-33475.rI0y1U.rst new file mode 100644 index 000000000000..cd714b9d1e89 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-05-13-01-26-18.bpo-33475.rI0y1U.rst @@ -0,0 +1,2 @@ +Fixed miscellaneous bugs in converting annotations to strings and optimized +parentheses in the string representation. diff --git a/Python/ast_unparse.c b/Python/ast_unparse.c index 1345271e599b..725ce31fe3c0 100644 --- a/Python/ast_unparse.c +++ b/Python/ast_unparse.c @@ -9,13 +9,15 @@ static PyObject *_str_dbl_close_br; /* Forward declarations for recursion via helper functions. */ static PyObject * -expr_as_unicode(expr_ty e, bool omit_parens); +expr_as_unicode(expr_ty e, int level); static int -append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens); +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); +static int +append_ast_slice(_PyUnicodeWriter *writer, slice_ty slice); static int append_charp(_PyUnicodeWriter *writer, const char *charp) @@ -23,6 +25,39 @@ append_charp(_PyUnicodeWriter *writer, const char *charp) return _PyUnicodeWriter_WriteASCIIString(writer, charp, -1); } +#define APPEND_STR_FINISH(str) do { \ + return append_charp(writer, (str)); \ + } while (0) + +#define APPEND_STR(str) do { \ + if (-1 == append_charp(writer, (str))) { \ + return -1; \ + } \ + } while (0) + +#define APPEND_STR_IF(cond, str) do { \ + if ((cond) && -1 == append_charp(writer, (str))) { \ + return -1; \ + } \ + } while (0) + +#define APPEND_STR_IF_NOT_FIRST(str) do { \ + APPEND_STR_IF(!first, (str)); \ + first = false; \ + } while (0) + +#define APPEND_EXPR(expr, pr) do { \ + if (-1 == append_ast_expr(writer, (expr), (pr))) { \ + return -1; \ + } \ + } while (0) + +#define APPEND(type, value) do { \ + if (-1 == append_ast_ ## type(writer, (value))) { \ + return -1; \ + } \ + } while (0) + static int append_repr(_PyUnicodeWriter *writer, PyObject *obj) { @@ -37,111 +72,108 @@ append_repr(_PyUnicodeWriter *writer, PyObject *obj) return ret; } -static int -append_ast_boolop(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) +/* Priority levels */ + +enum { + PR_TUPLE, + PR_TEST, /* 'if'-'else', 'lambda' */ + PR_OR, /* 'or' */ + PR_AND, /* 'and' */ + PR_NOT, /* 'not' */ + PR_CMP, /* '<', '>', '==', '>=', '<=', '!=', + 'in', 'not in', 'is', 'is not' */ + PR_EXPR, + PR_BOR = PR_EXPR, /* '|' */ + PR_BXOR, /* '^' */ + PR_BAND, /* '&' */ + PR_SHIFT, /* '<<', '>>' */ + PR_ARITH, /* '+', '-' */ + PR_TERM, /* '*', '@', '/', '%', '//' */ + PR_FACTOR, /* unary '+', '-', '~' */ + PR_POWER, /* '**' */ + PR_AWAIT, /* 'await' */ + PR_ATOM, +}; + +static int +append_ast_boolop(_PyUnicodeWriter *writer, expr_ty e, int level) { Py_ssize_t i, value_count; asdl_seq *values; + const char *op = (e->v.BoolOp.op == And) ? " and " : " or "; + int pr = (e->v.BoolOp.op == And) ? PR_AND : PR_OR; - if (!omit_parens && -1 == append_charp(writer, "(")) { - return -1; - } + APPEND_STR_IF(level > pr, "("); values = e->v.BoolOp.values; - value_count = asdl_seq_LEN(values) - 1; - assert(value_count >= 0); + value_count = asdl_seq_LEN(values); - if (-1 == append_ast_expr(writer, - (expr_ty)asdl_seq_GET(values, 0), - false)) { - return -1; - } - - const char *op = (e->v.BoolOp.op == And) ? " and " : " or "; - for (i = 1; i <= value_count; ++i) { - if (-1 == append_charp(writer, op)) { - return -1; - } - - if (-1 == append_ast_expr(writer, - (expr_ty)asdl_seq_GET(values, i), - false)) { - return -1; - } + for (i = 0; i < value_count; ++i) { + APPEND_STR_IF(i > 0, op); + APPEND_EXPR((expr_ty)asdl_seq_GET(values, i), pr + 1); } - return omit_parens ? 0 : append_charp(writer, ")"); + APPEND_STR_IF(level > pr, ")"); + return 0; } static int -append_ast_binop(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) +append_ast_binop(_PyUnicodeWriter *writer, expr_ty e, int level) { const char *op; - - if (!omit_parens && -1 == append_charp(writer, "(")) { - return -1; - } - - if (-1 == append_ast_expr(writer, e->v.BinOp.left, false)) { - return -1; - } - - switch(e->v.BinOp.op) { - case Add: op = " + "; break; - case Sub: op = " - "; break; - case Mult: op = " * "; break; - case MatMult: op = " @ "; break; - case Div: op = " / "; break; - case Mod: op = " % "; break; - case LShift: op = " << "; break; - case RShift: op = " >> "; break; - case BitOr: op = " | "; break; - case BitXor: op = " ^ "; break; - case BitAnd: op = " & "; break; - case FloorDiv: op = " // "; break; - case Pow: op = " ** "; break; + int pr; + bool rassoc = false; /* is right-associative? */ + + switch (e->v.BinOp.op) { + case Add: op = " + "; pr = PR_ARITH; break; + case Sub: op = " - "; pr = PR_ARITH; break; + case Mult: op = " * "; pr = PR_TERM; break; + case MatMult: op = " @ "; pr = PR_TERM; break; + case Div: op = " / "; pr = PR_TERM; break; + case Mod: op = " % "; pr = PR_TERM; break; + case LShift: op = " << "; pr = PR_SHIFT; break; + case RShift: op = " >> "; pr = PR_SHIFT; break; + case BitOr: op = " | "; pr = PR_BOR; break; + case BitXor: op = " ^ "; pr = PR_BXOR; break; + case BitAnd: op = " & "; pr = PR_BAND; break; + case FloorDiv: op = " // "; pr = PR_TERM; break; + case Pow: op = " ** "; pr = PR_POWER; rassoc = true; break; default: - Py_UNREACHABLE(); - } - - if (-1 == append_charp(writer, op)) { - return -1; - } - - if (-1 == append_ast_expr(writer, e->v.BinOp.right, false)) { + PyErr_SetString(PyExc_SystemError, + "unknown binary operator"); return -1; } - return omit_parens ? 0 : append_charp(writer, ")"); + APPEND_STR_IF(level > pr, "("); + APPEND_EXPR(e->v.BinOp.left, pr + rassoc); + APPEND_STR(op); + APPEND_EXPR(e->v.BinOp.right, pr + !rassoc); + APPEND_STR_IF(level > pr, ")"); + return 0; } static int -append_ast_unaryop(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) +append_ast_unaryop(_PyUnicodeWriter *writer, expr_ty e, int level) { const char *op; + int pr; - if (!omit_parens && -1 == append_charp(writer, "(")) { - return -1; - } - - switch(e->v.UnaryOp.op) { - case Invert: op = "~"; break; - case Not: op = "not "; break; - case UAdd: op = "+"; break; - case USub: op = "-"; break; + switch (e->v.UnaryOp.op) { + case Invert: op = "~"; pr = PR_FACTOR; break; + case Not: op = "not "; pr = PR_NOT; break; + case UAdd: op = "+"; pr = PR_FACTOR; break; + case USub: op = "-"; pr = PR_FACTOR; break; default: - Py_UNREACHABLE(); - } - - if (-1 == append_charp(writer, op)) { - return -1; - } - - if (-1 == append_ast_expr(writer, e->v.UnaryOp.operand, false)) { + PyErr_SetString(PyExc_SystemError, + "unknown unary operator"); return -1; } - return omit_parens ? 0 : append_charp(writer, ")"); + APPEND_STR_IF(level > pr, "("); + APPEND_STR(op); + APPEND_EXPR(e->v.UnaryOp.operand, pr); + APPEND_STR_IF(level > pr, ")"); + return 0; } static int @@ -151,12 +183,8 @@ append_ast_arg(_PyUnicodeWriter *writer, arg_ty arg) return -1; } if (arg->annotation) { - if (-1 == append_charp(writer, ": ")) { - return -1; - } - if (-1 == append_ast_expr(writer, arg->annotation, true)) { - return -1; - } + APPEND_STR(": "); + APPEND_EXPR(arg->annotation, PR_TEST); } return 0; } @@ -166,8 +194,6 @@ append_ast_args(_PyUnicodeWriter *writer, arguments_ty args) { bool first; Py_ssize_t i, di, arg_count, default_count; - arg_ty arg; - expr_ty default_; first = true; @@ -175,47 +201,22 @@ append_ast_args(_PyUnicodeWriter *writer, arguments_ty args) arg_count = asdl_seq_LEN(args->args); default_count = asdl_seq_LEN(args->defaults); for (i = 0; i < arg_count; i++) { - if (first) { - first = false; - } - else if (-1 == append_charp(writer, ", ")) { - return -1; - } - - arg = (arg_ty)asdl_seq_GET(args->args, i); - if (-1 == append_ast_arg(writer, arg)) { - return -1; - } + APPEND_STR_IF_NOT_FIRST(", "); + APPEND(arg, (arg_ty)asdl_seq_GET(args->args, i)); di = i - arg_count + default_count; if (di >= 0) { - if (-1 == append_charp(writer, "=")) { - return -1; - } - default_ = (expr_ty)asdl_seq_GET(args->defaults, di); - if (-1 == append_ast_expr(writer, default_, false)) { - return -1; - } + APPEND_STR("="); + APPEND_EXPR((expr_ty)asdl_seq_GET(args->defaults, di), PR_TEST); } } /* vararg, or bare '*' if no varargs but keyword-only arguments present */ if (args->vararg || args->kwonlyargs) { - if (first) { - first = false; - } - else if (-1 == append_charp(writer, ", ")) { - return -1; - } - - if (-1 == append_charp(writer, "*")) { - return -1; - } - + APPEND_STR_IF_NOT_FIRST(", "); + APPEND_STR("*"); if (args->vararg) { - if (-1 == append_ast_arg(writer, args->vararg)) { - return -1; - } + APPEND(arg, args->vararg); } } @@ -223,223 +224,127 @@ append_ast_args(_PyUnicodeWriter *writer, arguments_ty args) arg_count = asdl_seq_LEN(args->kwonlyargs); default_count = asdl_seq_LEN(args->kw_defaults); for (i = 0; i < arg_count; i++) { - if (first) { - first = false; - } - else if (-1 == append_charp(writer, ", ")) { - return -1; - } - - arg = (arg_ty)asdl_seq_GET(args->kwonlyargs, i); - if (-1 == append_ast_arg(writer, arg)) { - return -1; - } + APPEND_STR_IF_NOT_FIRST(", "); + APPEND(arg, (arg_ty)asdl_seq_GET(args->kwonlyargs, i)); di = i - arg_count + default_count; if (di >= 0) { - if (-1 == append_charp(writer, "=")) { - return -1; - } - default_ = (expr_ty)asdl_seq_GET(args->kw_defaults, di); - if (-1 == append_ast_expr(writer, default_, false)) { - return -1; - } + APPEND_STR("="); + APPEND_EXPR((expr_ty)asdl_seq_GET(args->kw_defaults, di), PR_TEST); } } /* **kwargs */ if (args->kwarg) { - if (first) { - first = false; - } - else if (-1 == append_charp(writer, ", ")) { - return -1; - } - - if (-1 == append_charp(writer, "**")) { - return -1; - } - - if (-1 == append_ast_arg(writer, args->kwarg)) { - return -1; - } + APPEND_STR_IF_NOT_FIRST(", "); + APPEND_STR("**"); + APPEND(arg, args->kwarg); } return 0; } static int -append_ast_lambda(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) +append_ast_lambda(_PyUnicodeWriter *writer, expr_ty e, int level) { - if (!omit_parens && -1 == append_charp(writer, "(")) { - return -1; - } - - if (-1 == append_charp(writer, "lambda ")) { - return -1; - } - - if (-1 == append_ast_args(writer, e->v.Lambda.args)) { - return -1; - } - - if (-1 == append_charp(writer, ": ")) { - return -1; - } - - if (-1 == append_ast_expr(writer, e->v.Lambda.body, true)) { - return -1; - } - - return omit_parens ? 0 : append_charp(writer, ")"); + APPEND_STR_IF(level > PR_TEST, "("); + APPEND_STR("lambda "); + APPEND(args, e->v.Lambda.args); + APPEND_STR(": "); + APPEND_EXPR(e->v.Lambda.body, PR_TEST); + APPEND_STR_IF(level > PR_TEST, ")"); + return 0; } static int -append_ast_ifexp(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) +append_ast_ifexp(_PyUnicodeWriter *writer, expr_ty e, int level) { - if (!omit_parens && -1 == append_charp(writer, "(")) { - return -1; - } - - if (-1 == append_ast_expr(writer, e->v.IfExp.body, false)) { - return -1; - } - - if (-1 == append_charp(writer, " if ")) { - return -1; - } - - if (-1 == append_ast_expr(writer, e->v.IfExp.test, false)) { - return -1; - } - - if (-1 == append_charp(writer, " else ")) { - return -1; - } - - if (-1 == append_ast_expr(writer, e->v.IfExp.orelse, false)) { - return -1; - } - - return omit_parens ? 0 : append_charp(writer, ")"); + APPEND_STR_IF(level > PR_TEST, "("); + APPEND_EXPR(e->v.IfExp.body, PR_TEST + 1); + APPEND_STR(" if "); + APPEND_EXPR(e->v.IfExp.test, PR_TEST + 1); + APPEND_STR(" else "); + APPEND_EXPR(e->v.IfExp.orelse, PR_TEST); + APPEND_STR_IF(level > PR_TEST, ")"); + return 0; } static int append_ast_dict(_PyUnicodeWriter *writer, expr_ty e) { Py_ssize_t i, value_count; - expr_ty key_node, value_node; - - if (-1 == append_charp(writer, "{")) { - return -1; - } + expr_ty key_node; + APPEND_STR("{"); value_count = asdl_seq_LEN(e->v.Dict.values); for (i = 0; i < value_count; i++) { - if (i > 0 && -1 == append_charp(writer, ", ")) { - return -1; - } + APPEND_STR_IF(i > 0, ", "); key_node = (expr_ty)asdl_seq_GET(e->v.Dict.keys, i); if (key_node != NULL) { - if (-1 == append_ast_expr(writer, key_node, false)) { - return -1; - } - - if (-1 == append_charp(writer, ": ")) { - return -1; - } - } - else if (-1 == append_charp(writer, "**")) { - return -1; + APPEND_EXPR(key_node, PR_TEST); + APPEND_STR(": "); + APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Dict.values, i), PR_TEST); } - - value_node = (expr_ty)asdl_seq_GET(e->v.Dict.values, i); - if (-1 == append_ast_expr(writer, value_node, false)) { - return -1; + else { + APPEND_STR("**"); + APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Dict.values, i), PR_EXPR); } } - return append_charp(writer, "}"); + APPEND_STR_FINISH("}"); } static int append_ast_set(_PyUnicodeWriter *writer, expr_ty e) { Py_ssize_t i, elem_count; - expr_ty elem_node; - - if (-1 == append_charp(writer, "{")) { - return -1; - } + APPEND_STR("{"); elem_count = asdl_seq_LEN(e->v.Set.elts); for (i = 0; i < elem_count; i++) { - if (i > 0 && -1 == append_charp(writer, ", ")) { - return -1; - } - - elem_node = (expr_ty)asdl_seq_GET(e->v.Set.elts, i); - if (-1 == append_ast_expr(writer, elem_node, false)) { - return -1; - } + APPEND_STR_IF(i > 0, ", "); + APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Set.elts, i), PR_TEST); } - return append_charp(writer, "}"); + APPEND_STR_FINISH("}"); } static int append_ast_list(_PyUnicodeWriter *writer, expr_ty e) { Py_ssize_t i, elem_count; - expr_ty elem_node; - - if (-1 == append_charp(writer, "[")) { - return -1; - } + APPEND_STR("["); elem_count = asdl_seq_LEN(e->v.List.elts); for (i = 0; i < elem_count; i++) { - if (i > 0 && -1 == append_charp(writer, ", ")) { - return -1; - } - elem_node = (expr_ty)asdl_seq_GET(e->v.List.elts, i); - if (-1 == append_ast_expr(writer, elem_node, false)) { - return -1; - } + APPEND_STR_IF(i > 0, ", "); + APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.List.elts, i), PR_TEST); } - return append_charp(writer, "]"); + APPEND_STR_FINISH("]"); } static int -append_ast_tuple(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) +append_ast_tuple(_PyUnicodeWriter *writer, expr_ty e, int level) { Py_ssize_t i, elem_count; - expr_ty elem_node; elem_count = asdl_seq_LEN(e->v.Tuple.elts); - if (!omit_parens || elem_count < 2) { - if (-1 == append_charp(writer, "(")) { - return -1; - } + if (elem_count == 0) { + APPEND_STR_FINISH("()"); } - for (i = 0; i < elem_count; i++) { - if ((i > 0 || elem_count == 1) && -1 == append_charp(writer, ", ")) { - return -1; - } - elem_node = (expr_ty)asdl_seq_GET(e->v.Tuple.elts, i); - if (-1 == append_ast_expr(writer, elem_node, false)) { - return -1; - } - } + APPEND_STR_IF(level > PR_TUPLE, "("); - if (!omit_parens || elem_count < 2) { - return append_charp(writer, ")"); + for (i = 0; i < elem_count; i++) { + APPEND_STR_IF(i > 0, ", "); + APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Tuple.elts, i), PR_TEST); } + APPEND_STR_IF(elem_count == 1, ","); + APPEND_STR_IF(level > PR_TUPLE, ")"); return 0; } @@ -448,33 +353,15 @@ append_ast_comprehension(_PyUnicodeWriter *writer, comprehension_ty gen) { Py_ssize_t i, if_count; - if (-1 == append_charp(writer, gen->is_async ? " async for " : " for ")) { - return -1; - } - - if (-1 == append_ast_expr(writer, gen->target, true)) { - return -1; - } - - if (-1 == append_charp(writer, " in ")) { - return -1; - } - - if (-1 == append_ast_expr(writer, gen->iter, false)) { - return -1; - } + APPEND_STR(gen->is_async ? " async for " : " for "); + APPEND_EXPR(gen->target, PR_TUPLE); + APPEND_STR(" in "); + APPEND_EXPR(gen->iter, PR_TEST + 1); if_count = asdl_seq_LEN(gen->ifs); for (i = 0; i < if_count; i++) { - if (-1 == append_charp(writer, " if ")) { - return -1; - } - - if (-1 == append_ast_expr(writer, - (expr_ty)asdl_seq_GET(gen->ifs, i), - false)) { - return -1; - } + APPEND_STR(" if "); + APPEND_EXPR((expr_ty)asdl_seq_GET(gen->ifs, i), PR_TEST + 1); } return 0; } @@ -483,110 +370,62 @@ static int append_ast_comprehensions(_PyUnicodeWriter *writer, asdl_seq *comprehensions) { Py_ssize_t i, gen_count; - comprehension_ty comp_node; gen_count = asdl_seq_LEN(comprehensions); for (i = 0; i < gen_count; i++) { - comp_node = (comprehension_ty)asdl_seq_GET(comprehensions, i); - if (-1 == append_ast_comprehension(writer, comp_node)) { - return -1; - } + APPEND(comprehension, (comprehension_ty)asdl_seq_GET(comprehensions, i)); } return 0; } static int -append_ast_genexp(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) +append_ast_genexp(_PyUnicodeWriter *writer, expr_ty e) { - if (!omit_parens && -1 == append_charp(writer, "(")) { - return -1; - } - - if (-1 == append_ast_expr(writer, e->v.GeneratorExp.elt, false)) { - return -1; - } - - if (-1 == append_ast_comprehensions(writer, e->v.GeneratorExp.generators)) { - return -1; - } - - return omit_parens ? 0 : append_charp(writer, ")"); + APPEND_STR("("); + APPEND_EXPR(e->v.GeneratorExp.elt, PR_TEST); + APPEND(comprehensions, e->v.GeneratorExp.generators); + APPEND_STR_FINISH(")"); } static int append_ast_listcomp(_PyUnicodeWriter *writer, expr_ty e) { - if (-1 == append_charp(writer, "[")) { - return -1; - } - - if (-1 == append_ast_expr(writer, e->v.ListComp.elt, false)) { - return -1; - } - - if (-1 == append_ast_comprehensions(writer, e->v.ListComp.generators)) { - return -1; - } - - return append_charp(writer, "]"); + APPEND_STR("["); + APPEND_EXPR(e->v.ListComp.elt, PR_TEST); + APPEND(comprehensions, e->v.ListComp.generators); + APPEND_STR_FINISH("]"); } static int append_ast_setcomp(_PyUnicodeWriter *writer, expr_ty e) { - if (-1 == append_charp(writer, "{")) { - return -1; - } - - if (-1 == append_ast_expr(writer, e->v.SetComp.elt, false)) { - return -1; - } - - if (-1 == append_ast_comprehensions(writer, e->v.SetComp.generators)) { - return -1; - } - - return append_charp(writer, "}"); + APPEND_STR("{"); + APPEND_EXPR(e->v.SetComp.elt, PR_TEST); + APPEND(comprehensions, e->v.SetComp.generators); + APPEND_STR_FINISH("}"); } static int append_ast_dictcomp(_PyUnicodeWriter *writer, expr_ty e) { - if (-1 == append_charp(writer, "{")) { - return -1; - } - - if (-1 == append_ast_expr(writer, e->v.DictComp.key, false)) { - return -1; - } - - if (-1 == append_charp(writer, ": ")) { - return -1; - } - - if (-1 == append_ast_expr(writer, e->v.DictComp.value, false)) { - return -1; - } - - if (-1 == append_ast_comprehensions(writer, e->v.DictComp.generators)) { - return -1; - } - - return append_charp(writer, "}"); + APPEND_STR("{"); + APPEND_EXPR(e->v.DictComp.key, PR_TEST); + APPEND_STR(": "); + APPEND_EXPR(e->v.DictComp.value, PR_TEST); + APPEND(comprehensions, e->v.DictComp.generators); + APPEND_STR_FINISH("}"); } static int -append_ast_compare(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) +append_ast_compare(_PyUnicodeWriter *writer, expr_ty e, int level) { const char *op; Py_ssize_t i, comparator_count; asdl_seq *comparators; asdl_int_seq *ops; - if (!omit_parens && -1 == append_charp(writer, "(")) { - return -1; - } + APPEND_STR_IF(level > PR_CMP, "("); comparators = e->v.Compare.comparators; ops = e->v.Compare.ops; @@ -594,9 +433,7 @@ append_ast_compare(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) assert(comparator_count > 0); assert(comparator_count == asdl_seq_LEN(ops)); - if (-1 == append_ast_expr(writer, e->v.Compare.left, false)) { - return -1; - } + APPEND_EXPR(e->v.Compare.left, PR_CMP + 1); for (i = 0; i < comparator_count; i++) { switch ((cmpop_ty)asdl_seq_GET(ops, i)) { @@ -636,39 +473,30 @@ append_ast_compare(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) return -1; } - if (-1 == append_charp(writer, op)) { - return -1; - } - - if (-1 == append_ast_expr(writer, - (expr_ty)asdl_seq_GET(comparators, i), - false)) { - return -1; - } + APPEND_STR(op); + APPEND_EXPR((expr_ty)asdl_seq_GET(comparators, i), PR_CMP + 1); } - return omit_parens ? 0 : append_charp(writer, ")"); + APPEND_STR_IF(level > PR_CMP, ")"); + return 0; } static int append_ast_keyword(_PyUnicodeWriter *writer, keyword_ty kw) { if (kw->arg == NULL) { - if (-1 == append_charp(writer, "**")) { - return -1; - } + APPEND_STR("**"); } else { if (-1 == _PyUnicodeWriter_WriteStr(writer, kw->arg)) { return -1; } - if (-1 == append_charp(writer, "=")) { - return -1; - } + APPEND_STR("="); } - return append_ast_expr(writer, kw->value, false); + APPEND_EXPR(kw->value, PR_TEST); + return 0; } static int @@ -677,48 +505,33 @@ append_ast_call(_PyUnicodeWriter *writer, expr_ty e) bool first; Py_ssize_t i, arg_count, kw_count; expr_ty expr; - keyword_ty kw; - if (-1 == append_ast_expr(writer, e->v.Call.func, false)) { - return -1; - } + APPEND_EXPR(e->v.Call.func, PR_ATOM); - if (-1 == append_charp(writer, "(")) { - return -1; + arg_count = asdl_seq_LEN(e->v.Call.args); + kw_count = asdl_seq_LEN(e->v.Call.keywords); + if (arg_count == 1 && kw_count == 0) { + expr = (expr_ty)asdl_seq_GET(e->v.Call.args, 0); + if (expr->kind == GeneratorExp_kind) { + /* Special case: a single generator expression. */ + return append_ast_genexp(writer, expr); + } } + APPEND_STR("("); + first = true; - arg_count = asdl_seq_LEN(e->v.Call.args); for (i = 0; i < arg_count; i++) { - if (first) { - first = false; - } - else if (-1 == append_charp(writer, ", ")) { - return -1; - } - - expr = (expr_ty)asdl_seq_GET(e->v.Call.args, i); - if (-1 == append_ast_expr(writer, expr, false)) { - return -1; - } + APPEND_STR_IF_NOT_FIRST(", "); + APPEND_EXPR((expr_ty)asdl_seq_GET(e->v.Call.args, i), PR_TEST); } - kw_count = asdl_seq_LEN(e->v.Call.keywords); for (i = 0; i < kw_count; i++) { - if (first) { - first = false; - } - else if (-1 == append_charp(writer, ", ")) { - return -1; - } - - kw = (keyword_ty)asdl_seq_GET(e->v.Call.keywords, i); - if (-1 == append_ast_keyword(writer, kw)) { - return -1; - } + APPEND_STR_IF_NOT_FIRST(", "); + APPEND(keyword, (keyword_ty)asdl_seq_GET(e->v.Call.keywords, i)); } - return append_charp(writer, ")"); + APPEND_STR_FINISH(")"); } static PyObject * @@ -778,9 +591,8 @@ build_fstring_body(asdl_seq *values, bool is_format_spec) body_writer.min_length = 256; body_writer.overallocate = 1; - value_count = asdl_seq_LEN(values) - 1; - assert(value_count >= 0); - for (i = 0; i <= value_count; ++i) { + value_count = asdl_seq_LEN(values); + for (i = 0; i < value_count; ++i) { if (-1 == append_fstring_element(&body_writer, (expr_ty)asdl_seq_GET(values, i), is_format_spec @@ -819,9 +631,11 @@ append_joinedstr(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec) static int append_formattedvalue(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec) { - char *conversion; - char *outer_brace = "{"; - PyObject *temp_fv_str = expr_as_unicode(e->v.FormattedValue.value, true); + const char *conversion; + const char *outer_brace = "{"; + /* Grammar allows PR_TUPLE, but use >PR_TEST for adding parenthesis + around a lambda with ':' */ + PyObject *temp_fv_str = expr_as_unicode(e->v.FormattedValue.value, PR_TEST + 1); if (!temp_fv_str) { return -1; } @@ -842,13 +656,13 @@ append_formattedvalue(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec) if (e->v.FormattedValue.conversion > 0) { switch (e->v.FormattedValue.conversion) { - case 97: + case 'a': conversion = "!a"; break; - case 114: + case 'r': conversion = "!r"; break; - case 115: + case 's': conversion = "!s"; break; default: @@ -856,9 +670,7 @@ append_formattedvalue(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec) "unknown f-value conversion kind"); return -1; } - if (-1 == append_charp(writer, conversion)) { - return -1; - } + APPEND_STR(conversion); } if (e->v.FormattedValue.format_spec) { if (-1 == _PyUnicodeWriter_WriteASCIIString(writer, ":", 1) || @@ -870,16 +682,15 @@ append_formattedvalue(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec) return -1; } } - return append_charp(writer, "}"); + + APPEND_STR_FINISH("}"); } static int append_ast_attribute(_PyUnicodeWriter *writer, expr_ty e) { const char *period; - if (-1 == append_ast_expr(writer, e->v.Attribute.value, false)) { - return -1; - } + APPEND_EXPR(e->v.Attribute.value, PR_ATOM); /* Special case: integers require a space for attribute access to be unambiguous. Floats and complex numbers don't but work with it, too. */ @@ -891,9 +702,7 @@ append_ast_attribute(_PyUnicodeWriter *writer, expr_ty e) else { period = "."; } - if (-1 == append_charp(writer, period)) { - return -1; - } + APPEND_STR(period); return _PyUnicodeWriter_WriteStr(writer, e->v.Attribute.attr); } @@ -902,28 +711,18 @@ static int append_ast_simple_slice(_PyUnicodeWriter *writer, slice_ty slice) { if (slice->v.Slice.lower) { - if (-1 == append_ast_expr(writer, slice->v.Slice.lower, false)) { - return -1; - } + APPEND_EXPR(slice->v.Slice.lower, PR_TEST); } - if (-1 == append_charp(writer, ":")) { - return -1; - } + APPEND_STR(":"); if (slice->v.Slice.upper) { - if (-1 == append_ast_expr(writer, slice->v.Slice.upper, false)) { - return -1; - } + APPEND_EXPR(slice->v.Slice.upper, PR_TEST); } if (slice->v.Slice.step) { - if (-1 == append_charp(writer, ":")) { - return -1; - } - if (-1 == append_ast_expr(writer, slice->v.Slice.step, false)) { - return -1; - } + APPEND_STR(":"); + APPEND_EXPR(slice->v.Slice.step, PR_TEST); } return 0; } @@ -934,28 +733,23 @@ append_ast_ext_slice(_PyUnicodeWriter *writer, slice_ty slice) Py_ssize_t i, dims_count; dims_count = asdl_seq_LEN(slice->v.ExtSlice.dims); for (i = 0; i < dims_count; i++) { - if (i > 0 && -1 == append_charp(writer, ", ")) { - return -1; - } - if (-1 == append_ast_expr(writer, - (expr_ty)asdl_seq_GET(slice->v.ExtSlice.dims, i), - false)) { - return -1; - } + APPEND_STR_IF(i > 0, ", "); + APPEND(slice, (slice_ty)asdl_seq_GET(slice->v.ExtSlice.dims, i)); } return 0; } static int -append_ast_slice(_PyUnicodeWriter *writer, slice_ty slice, bool omit_parens) +append_ast_slice(_PyUnicodeWriter *writer, slice_ty slice) { - switch(slice->kind) { + switch (slice->kind) { case Slice_kind: return append_ast_simple_slice(writer, slice); case ExtSlice_kind: return append_ast_ext_slice(writer, slice); case Index_kind: - return append_ast_expr(writer, slice->v.Index.value, omit_parens); + APPEND_EXPR(slice->v.Index.value, PR_TUPLE); + return 0; default: PyErr_SetString(PyExc_SystemError, "unexpected slice kind"); @@ -966,109 +760,70 @@ append_ast_slice(_PyUnicodeWriter *writer, slice_ty slice, bool omit_parens) static int append_ast_subscript(_PyUnicodeWriter *writer, expr_ty e) { - if (-1 == append_ast_expr(writer, e->v.Subscript.value, false)) { - return -1; - } - - if (-1 == append_charp(writer, "[")) { - return -1; - } - - if (-1 == append_ast_slice(writer, e->v.Subscript.slice, true)) { - return -1; - } - - return append_charp(writer, "]"); + APPEND_EXPR(e->v.Subscript.value, PR_ATOM); + APPEND_STR("["); + APPEND(slice, e->v.Subscript.slice); + APPEND_STR_FINISH("]"); } static int append_ast_starred(_PyUnicodeWriter *writer, expr_ty e) { - if (-1 == append_charp(writer, "*")) { - return -1; - } - - return append_ast_expr(writer, e->v.Starred.value, false); + APPEND_STR("*"); + APPEND_EXPR(e->v.Starred.value, PR_EXPR); + return 0; } static int -append_ast_yield(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) +append_ast_yield(_PyUnicodeWriter *writer, expr_ty e) { - if (!omit_parens && -1 == append_charp(writer, "(")) { - return -1; - } - - if (-1 == append_charp(writer, e->v.Yield.value ? "yield " : "yield")) { - return -1; + if (!e->v.Yield.value) { + APPEND_STR_FINISH("(yield)"); } - if (e->v.Yield.value) { - if (-1 == append_ast_expr(writer, e->v.Yield.value, false)) { - return -1; - } - } - return omit_parens ? 0 : append_charp(writer, ")"); + APPEND_STR("(yield "); + APPEND_EXPR(e->v.Yield.value, PR_TEST); + APPEND_STR_FINISH(")"); } static int -append_ast_yield_from(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) +append_ast_yield_from(_PyUnicodeWriter *writer, expr_ty e) { - if (!omit_parens && -1 == append_charp(writer, "(")) { - return -1; - } - - if (-1 == append_charp(writer, - e->v.YieldFrom.value ? "yield from " : "yield from")) { - return -1; - } - - if (e->v.YieldFrom.value) { - if (-1 == append_ast_expr(writer, e->v.YieldFrom.value, false)) { - return -1; - } - } - return omit_parens ? 0 : append_charp(writer, ")"); + APPEND_STR("(yield from "); + APPEND_EXPR(e->v.YieldFrom.value, PR_TEST); + APPEND_STR_FINISH(")"); } static int -append_ast_await(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) +append_ast_await(_PyUnicodeWriter *writer, expr_ty e, int level) { - if (!omit_parens && -1 == append_charp(writer, "(")) { - return -1; - } - - if (-1 == append_charp(writer, e->v.Await.value ? "await " : "await")) { - return -1; - } - - if (e->v.Await.value) { - if (-1 == append_ast_expr(writer, e->v.Await.value, false)) { - return -1; - } - } - return omit_parens ? 0 : append_charp(writer, ")"); + APPEND_STR_IF(level > PR_AWAIT, "("); + APPEND_STR("await "); + APPEND_EXPR(e->v.Await.value, PR_ATOM); + APPEND_STR_IF(level > PR_AWAIT, ")"); + return 0; } static int -append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) +append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, int level) { switch (e->kind) { case BoolOp_kind: - return append_ast_boolop(writer, e, omit_parens); + return append_ast_boolop(writer, e, level); case BinOp_kind: - return append_ast_binop(writer, e, omit_parens); + return append_ast_binop(writer, e, level); case UnaryOp_kind: - return append_ast_unaryop(writer, e, omit_parens); + return append_ast_unaryop(writer, e, level); case Lambda_kind: - return append_ast_lambda(writer, e, omit_parens); + return append_ast_lambda(writer, e, level); case IfExp_kind: - return append_ast_ifexp(writer, e, omit_parens); + return append_ast_ifexp(writer, e, level); case Dict_kind: return append_ast_dict(writer, e); case Set_kind: return append_ast_set(writer, e); case GeneratorExp_kind: - return append_ast_genexp(writer, e, omit_parens); + return append_ast_genexp(writer, e); case ListComp_kind: return append_ast_listcomp(writer, e); case SetComp_kind: @@ -1076,13 +831,13 @@ append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) case DictComp_kind: return append_ast_dictcomp(writer, e); case Yield_kind: - return append_ast_yield(writer, e, omit_parens); + return append_ast_yield(writer, e); case YieldFrom_kind: - return append_ast_yield_from(writer, e, omit_parens); + return append_ast_yield_from(writer, e); case Await_kind: - return append_ast_await(writer, e, omit_parens); + return append_ast_await(writer, e, level); case Compare_kind: - return append_ast_compare(writer, e, omit_parens); + return append_ast_compare(writer, e, level); case Call_kind: return append_ast_call(writer, e); case Constant_kind: @@ -1098,7 +853,7 @@ append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) case Bytes_kind: return append_repr(writer, e->v.Bytes.s); case Ellipsis_kind: - return append_charp(writer, "..."); + APPEND_STR_FINISH("..."); case NameConstant_kind: return append_repr(writer, e->v.NameConstant.value); /* The following exprs can be assignment targets. */ @@ -1110,11 +865,10 @@ append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) return append_ast_starred(writer, e); case Name_kind: return _PyUnicodeWriter_WriteStr(writer, e->v.Name.id); - /* child nodes of List and Tuple will have expr_context set */ case List_kind: return append_ast_list(writer, e); case Tuple_kind: - return append_ast_tuple(writer, e, omit_parens); + return append_ast_tuple(writer, e, level); default: PyErr_SetString(PyExc_SystemError, "unknown expression kind"); @@ -1145,14 +899,14 @@ maybe_init_static_strings(void) } static PyObject * -expr_as_unicode(expr_ty e, bool omit_parens) +expr_as_unicode(expr_ty e, int level) { _PyUnicodeWriter writer; _PyUnicodeWriter_Init(&writer); writer.min_length = 256; writer.overallocate = 1; if (-1 == maybe_init_static_strings() || - -1 == append_ast_expr(&writer, e, omit_parens)) + -1 == append_ast_expr(&writer, e, level)) { _PyUnicodeWriter_Dealloc(&writer); return NULL; @@ -1161,7 +915,7 @@ expr_as_unicode(expr_ty e, bool omit_parens) } PyObject * -_PyAST_ExprAsUnicode(expr_ty e, bool omit_parens) +_PyAST_ExprAsUnicode(expr_ty e) { - return expr_as_unicode(e, omit_parens); + return expr_as_unicode(e, PR_TEST); } diff --git a/Python/compile.c b/Python/compile.c index 62d78867e077..c38a0d1b1a31 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1705,7 +1705,7 @@ static int compiler_visit_annexpr(struct compiler *c, expr_ty annotation) { PyObject *ann_as_str; - ann_as_str = _PyAST_ExprAsUnicode(annotation, 1); + ann_as_str = _PyAST_ExprAsUnicode(annotation); if (!ann_as_str) { return 0; } From webhook-mailer at python.org Sun May 20 11:10:01 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sun, 20 May 2018 15:10:01 -0000 Subject: [Python-checkins] Docs: be less specific about python versions (GH-6985) Message-ID: <mailman.176.1526829002.2757.python-checkins@python.org> https://github.com/python/cpython/commit/cef1f870be1148f56e63c6222af8dc065f1c75e6 commit: cef1f870be1148f56e63c6222af8dc065f1c75e6 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-20T08:09:58-07:00 summary: Docs: be less specific about python versions (GH-6985) CPython 3.5 is old now, and we don't bump this version often, so lets avoid using specific versions. (cherry picked from commit 9572132ab3c2edddb8087a0112116da866373f79) Co-authored-by: Eitan Adler <grimreaper at users.noreply.github.com> files: M Doc/howto/clinic.rst diff --git a/Doc/howto/clinic.rst b/Doc/howto/clinic.rst index 214b2bdef827..77b2aae088c3 100644 --- a/Doc/howto/clinic.rst +++ b/Doc/howto/clinic.rst @@ -22,8 +22,8 @@ Argument Clinic How-To compatibility for future versions. In other words: if you maintain an external C extension for CPython, you're welcome to experiment with Argument Clinic in your own code. But the - version of Argument Clinic that ships with CPython 3.5 *could* - be totally incompatible and break all your code. + version of Argument Clinic that ships with the next version + of CPython *could* be totally incompatible and break all your code. The Goals Of Argument Clinic ============================ From webhook-mailer at python.org Sun May 20 11:12:53 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sun, 20 May 2018 15:12:53 -0000 Subject: [Python-checkins] bpo-33580: Make binary/text file glossary entries follow most common "see also" style. (GH-6991) Message-ID: <mailman.177.1526829175.2757.python-checkins@python.org> https://github.com/python/cpython/commit/0c4be82890858f874ff2158b0fcfdb8f261569c0 commit: 0c4be82890858f874ff2158b0fcfdb8f261569c0 branch: master author: Andr?s Delfino <adelfino at gmail.com> committer: Serhiy Storchaka <storchaka at gmail.com> date: 2018-05-20T18:12:50+03:00 summary: bpo-33580: Make binary/text file glossary entries follow most common "see also" style. (GH-6991) files: M Doc/glossary.rst diff --git a/Doc/glossary.rst b/Doc/glossary.rst index 13d0b9e90b39..0ee056ee28dd 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -148,8 +148,8 @@ Glossary :data:`sys.stdout.buffer`, and instances of :class:`io.BytesIO` and :class:`gzip.GzipFile`. - .. seealso:: - A :term:`text file` reads and writes :class:`str` objects. + See also :term:`text file` for a file object able to read and write + :class:`str` objects. bytes-like object An object that supports the :ref:`bufferobjects` and can @@ -1030,8 +1030,8 @@ Glossary :data:`sys.stdin`, :data:`sys.stdout`, and instances of :class:`io.StringIO`. - .. seealso:: - A :term:`binary file` reads and write :class:`bytes` objects. + See also :term:`binary file` for a file object able to read and write + :term:`bytes-like objects <bytes-like object>`. triple-quoted string A string which is bound by three instances of either a quotation mark From webhook-mailer at python.org Sun May 20 11:14:42 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sun, 20 May 2018 15:14:42 -0000 Subject: [Python-checkins] Docs: be less specific about python versions (GH-6985) (GH-7008) Message-ID: <mailman.178.1526829283.2757.python-checkins@python.org> https://github.com/python/cpython/commit/296b60acd0f1fdc05310d5a2bbc83be47f73618d commit: 296b60acd0f1fdc05310d5a2bbc83be47f73618d branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Serhiy Storchaka <storchaka at gmail.com> date: 2018-05-20T18:14:39+03:00 summary: Docs: be less specific about python versions (GH-6985) (GH-7008) CPython 3.5 is old now, and we don't bump this version often, so lets avoid using specific versions. (cherry picked from commit 9572132ab3c2edddb8087a0112116da866373f79) Co-authored-by: Eitan Adler <grimreaper at users.noreply.github.com> files: M Doc/howto/clinic.rst diff --git a/Doc/howto/clinic.rst b/Doc/howto/clinic.rst index 788a0eee2ba1..695fbb1be192 100644 --- a/Doc/howto/clinic.rst +++ b/Doc/howto/clinic.rst @@ -22,8 +22,8 @@ Argument Clinic How-To compatibility for future versions. In other words: if you maintain an external C extension for CPython, you're welcome to experiment with Argument Clinic in your own code. But the - version of Argument Clinic that ships with CPython 3.5 *could* - be totally incompatible and break all your code. + version of Argument Clinic that ships with the next version + of CPython *could* be totally incompatible and break all your code. The Goals Of Argument Clinic ============================ From webhook-mailer at python.org Sun May 20 11:28:18 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sun, 20 May 2018 15:28:18 -0000 Subject: [Python-checkins] bpo-30940: Updating round() docs. (GH-6342) (GH-7009) Message-ID: <mailman.179.1526830100.2757.python-checkins@python.org> https://github.com/python/cpython/commit/736e3b32194b52b1779ce88a2c13862f0f913a7a commit: 736e3b32194b52b1779ce88a2c13862f0f913a7a branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Serhiy Storchaka <storchaka at gmail.com> date: 2018-05-20T18:28:15+03:00 summary: bpo-30940: Updating round() docs. (GH-6342) (GH-7009) (cherry picked from commit 900c48dba3f3eb8fb03ea766a5646f81c3bf3e9c) Co-authored-by: Lisa Roach <lisaroach14 at gmail.com> files: M Doc/library/functions.rst diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index 3b05a3a4ed32..457e1c34ec9a 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -1329,11 +1329,12 @@ are always available. They are listed here in alphabetical order. equally close, rounding is done toward the even choice (so, for example, both ``round(0.5)`` and ``round(-0.5)`` are ``0``, and ``round(1.5)`` is ``2``). Any integer value is valid for *ndigits* (positive, zero, or - negative). The return value is an integer if called with one argument, - otherwise of the same type as *number*. + negative). The return value is an integer if *ndigits* is omitted or + ``None``. + Otherwise the return value has the same type as *number*. - For a general Python object ``number``, ``round(number, ndigits)`` delegates to - ``number.__round__(ndigits)``. + For a general Python object ``number``, ``round`` delegates to + ``number.__round__``. .. note:: From webhook-mailer at python.org Sun May 20 11:29:48 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sun, 20 May 2018 15:29:48 -0000 Subject: [Python-checkins] bpo-30940: Updating round() docs. (GH-6342) Message-ID: <mailman.180.1526830189.2757.python-checkins@python.org> https://github.com/python/cpython/commit/82c9adb3f94e5d889f03205d03a76a5ff0928531 commit: 82c9adb3f94e5d889f03205d03a76a5ff0928531 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-20T08:29:45-07:00 summary: bpo-30940: Updating round() docs. (GH-6342) (cherry picked from commit 900c48dba3f3eb8fb03ea766a5646f81c3bf3e9c) Co-authored-by: Lisa Roach <lisaroach14 at gmail.com> files: M Doc/library/functions.rst diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst index 94675c1aa83b..501a3c99d41a 100644 --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -1315,11 +1315,12 @@ are always available. They are listed here in alphabetical order. equally close, rounding is done toward the even choice (so, for example, both ``round(0.5)`` and ``round(-0.5)`` are ``0``, and ``round(1.5)`` is ``2``). Any integer value is valid for *ndigits* (positive, zero, or - negative). The return value is an integer if called with one argument, - otherwise of the same type as *number*. + negative). The return value is an integer if *ndigits* is omitted or + ``None``. + Otherwise the return value has the same type as *number*. - For a general Python object ``number``, ``round(number, ndigits)`` delegates to - ``number.__round__(ndigits)``. + For a general Python object ``number``, ``round`` delegates to + ``number.__round__``. .. note:: From webhook-mailer at python.org Sun May 20 11:40:13 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sun, 20 May 2018 15:40:13 -0000 Subject: [Python-checkins] bpo-33542: Ignore DUID in uuid.get_node on Windows. (GH-6922) Message-ID: <mailman.181.1526830816.2757.python-checkins@python.org> https://github.com/python/cpython/commit/073eca39a55b86ec7dd7a437ac0c910751a60ace commit: 073eca39a55b86ec7dd7a437ac0c910751a60ace branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-20T08:40:10-07:00 summary: bpo-33542: Ignore DUID in uuid.get_node on Windows. (GH-6922) uuid._ipconfig_getnode did not validate the maximum length of the value, so long as the value had the same type of formatting as a MAC address. This let it select DUIDs as MAC addresses. It now requires an exact length match. (cherry picked from commit c66c342cb42ab8a88884527ddfe3a5086bc06316) Co-authored-by: CtrlZvi <viz+github at flippedperspective.com> files: A Misc/NEWS.d/next/Library/2018-05-16-09-30-27.bpo-33542.idNAcs.rst M Lib/uuid.py M Misc/ACKS diff --git a/Lib/uuid.py b/Lib/uuid.py index 9cb73e877181..66383218e70c 100644 --- a/Lib/uuid.py +++ b/Lib/uuid.py @@ -488,7 +488,7 @@ def _ipconfig_getnode(): with proc: for line in proc.stdout: value = line.split(':')[-1].strip().lower() - if re.match('([0-9a-f][0-9a-f]-){5}[0-9a-f][0-9a-f]', value): + if re.fullmatch('(?:[0-9a-f][0-9a-f]-){5}[0-9a-f][0-9a-f]', value): mac = int(value.replace('-', ''), 16) if _is_universal(mac): return mac diff --git a/Misc/ACKS b/Misc/ACKS index ffc932b08607..31ad80f8bc9c 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -426,6 +426,7 @@ Ulrich Eckhardt David Edelsohn John Edmonds Grant Edwards +Zvi Effron John Ehresman Tal Einat Eric Eisner diff --git a/Misc/NEWS.d/next/Library/2018-05-16-09-30-27.bpo-33542.idNAcs.rst b/Misc/NEWS.d/next/Library/2018-05-16-09-30-27.bpo-33542.idNAcs.rst new file mode 100644 index 000000000000..16ba799131f4 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-16-09-30-27.bpo-33542.idNAcs.rst @@ -0,0 +1,2 @@ +Prevent ``uuid.get_node`` from using a DUID instead of a MAC on Windows. +Patch by Zvi Effron From webhook-mailer at python.org Sun May 20 11:57:45 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sun, 20 May 2018 15:57:45 -0000 Subject: [Python-checkins] bpo-33580: Make binary/text file glossary entries follow most common "see also" style. (GH-6991) Message-ID: <mailman.182.1526831868.2757.python-checkins@python.org> https://github.com/python/cpython/commit/983e9653e0584b65a6ec66543ce1631f888aa285 commit: 983e9653e0584b65a6ec66543ce1631f888aa285 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-20T08:57:42-07:00 summary: bpo-33580: Make binary/text file glossary entries follow most common "see also" style. (GH-6991) (cherry picked from commit 0c4be82890858f874ff2158b0fcfdb8f261569c0) Co-authored-by: Andr?s Delfino <adelfino at gmail.com> files: M Doc/glossary.rst diff --git a/Doc/glossary.rst b/Doc/glossary.rst index 425ab81a9090..279233906091 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -136,8 +136,8 @@ Glossary :data:`sys.stdout.buffer`, and instances of :class:`io.BytesIO` and :class:`gzip.GzipFile`. - .. seealso:: - A :term:`text file` reads and writes :class:`str` objects. + See also :term:`text file` for a file object able to read and write + :class:`str` objects. bytes-like object An object that supports the :ref:`bufferobjects` and can @@ -998,8 +998,8 @@ Glossary :data:`sys.stdin`, :data:`sys.stdout`, and instances of :class:`io.StringIO`. - .. seealso:: - A :term:`binary file` reads and write :class:`bytes` objects. + See also :term:`binary file` for a file object able to read and write + :term:`bytes-like objects <bytes-like object>`. triple-quoted string A string which is bound by three instances of either a quotation mark From webhook-mailer at python.org Sun May 20 13:42:34 2018 From: webhook-mailer at python.org (Alexander Belopolsky) Date: Sun, 20 May 2018 17:42:34 -0000 Subject: [Python-checkins] bpo-33541: Remove unused __pad function (GH-4377) Message-ID: <mailman.183.1526838155.2757.python-checkins@python.org> https://github.com/python/cpython/commit/89a25ce4fdb9c2a1a59d8cbfc498a2614b98e9ae commit: 89a25ce4fdb9c2a1a59d8cbfc498a2614b98e9ae branch: master author: Mario Corchero <mariocj89 at gmail.com> committer: Alexander Belopolsky <abalkin at users.noreply.github.com> date: 2018-05-20T13:42:30-04:00 summary: bpo-33541: Remove unused __pad function (GH-4377) Function was added with the initial implementation 00efe7e798. files: A Misc/NEWS.d/next/Library/2018-05-16-12-32-48.bpo-33541.kQORPE.rst M Lib/_strptime.py diff --git a/Lib/_strptime.py b/Lib/_strptime.py index c8f2f94e5500..f4f3c0b80c1d 100644 --- a/Lib/_strptime.py +++ b/Lib/_strptime.py @@ -77,15 +77,6 @@ def __init__(self): if time.tzname != self.tzname or time.daylight != self.daylight: raise ValueError("timezone changed during initialization") - def __pad(self, seq, front): - # Add '' to seq to either the front (is True), else the back. - seq = list(seq) - if front: - seq.insert(0, '') - else: - seq.append('') - return seq - def __calc_weekday(self): # Set self.a_weekday and self.f_weekday using the calendar # module. diff --git a/Misc/NEWS.d/next/Library/2018-05-16-12-32-48.bpo-33541.kQORPE.rst b/Misc/NEWS.d/next/Library/2018-05-16-12-32-48.bpo-33541.kQORPE.rst new file mode 100644 index 000000000000..137189849ea7 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-16-12-32-48.bpo-33541.kQORPE.rst @@ -0,0 +1,2 @@ +Remove unused private method ``_strptime.LocaleTime.__pad`` (a.k.a. +``_LocaleTime__pad``). From webhook-mailer at python.org Sun May 20 13:57:16 2018 From: webhook-mailer at python.org (Christian Heimes) Date: Sun, 20 May 2018 17:57:16 -0000 Subject: [Python-checkins] bpo-32262: Fix typo in f-string (GH-7016) Message-ID: <mailman.184.1526839038.2757.python-checkins@python.org> https://github.com/python/cpython/commit/d361e99868a9eaa7ffce9341e1207705dbb66b50 commit: d361e99868a9eaa7ffce9341e1207705dbb66b50 branch: master author: Christian Heimes <christian at python.org> committer: GitHub <noreply at github.com> date: 2018-05-20T19:57:13+02:00 summary: bpo-32262: Fix typo in f-string (GH-7016) Fix typo from commit 6370f345e1d5829e1fba59cd695c8b82c5a8c620 Signed-off-by: Christian Heimes <christian at python.org> <!-- Thanks for your contribution! Please read this comment in its entirety. It's quite important. # Pull Request title It should be in the following format: ``` bpo-NNNN: Summary of the changes made ``` Where: bpo-NNNN refers to the issue number in the https://bugs.python.org. Most PRs will require an issue number. Trivial changes, like fixing a typo, do not need an issue. # Backport Pull Request title If this is a backport PR (PR made against branches other than `master`), please ensure that the PR title is in the following format: ``` [X.Y] <title from the original PR> (GH-NNNN) ``` Where: [X.Y] is the branch name, e.g. [3.6]. GH-NNNN refers to the PR number from `master`. --> <!-- issue-number: bpo-32262 --> https://bugs.python.org/issue32262 <!-- /issue-number --> files: M Lib/asyncio/base_subprocess.py M Lib/test/test_asyncio/test_subprocess.py diff --git a/Lib/asyncio/base_subprocess.py b/Lib/asyncio/base_subprocess.py index 7c17066f8bb2..b547c444ad5d 100644 --- a/Lib/asyncio/base_subprocess.py +++ b/Lib/asyncio/base_subprocess.py @@ -57,7 +57,7 @@ def __repr__(self): if self._closed: info.append('closed') if self._pid is not None: - info.append(f'pid={self.pid}') + info.append(f'pid={self._pid}') if self._returncode is not None: info.append(f'returncode={self._returncode}') elif self._pid is not None: diff --git a/Lib/test/test_asyncio/test_subprocess.py b/Lib/test/test_asyncio/test_subprocess.py index 81b08d6c292a..428510f77161 100644 --- a/Lib/test/test_asyncio/test_subprocess.py +++ b/Lib/test/test_asyncio/test_subprocess.py @@ -29,6 +29,7 @@ def _start(self, *args, **kwargs): self._proc.stdin = None self._proc.stdout = None self._proc.stderr = None + self._proc.pid = -1 class SubprocessTransportTests(test_utils.TestCase): @@ -73,6 +74,29 @@ def test_proc_exited(self): transport.close() + def test_subprocess_repr(self): + waiter = asyncio.Future(loop=self.loop) + transport, protocol = self.create_transport(waiter) + transport._process_exited(6) + self.loop.run_until_complete(waiter) + + self.assertEqual( + repr(transport), + "<TestSubprocessTransport pid=-1 returncode=6>" + ) + transport._returncode = None + self.assertEqual( + repr(transport), + "<TestSubprocessTransport pid=-1 running>" + ) + transport._pid = None + transport._returncode = None + self.assertEqual( + repr(transport), + "<TestSubprocessTransport not started>" + ) + transport.close() + class SubprocessMixin: From webhook-mailer at python.org Sun May 20 14:22:59 2018 From: webhook-mailer at python.org (Christian Heimes) Date: Sun, 20 May 2018 18:22:59 -0000 Subject: [Python-checkins] [3.7] bpo-32262: Fix typo in f-string (GH-7016) Message-ID: <mailman.185.1526840580.2757.python-checkins@python.org> https://github.com/python/cpython/commit/b85115ed4c5d4e80ab818b44401e71299de9e9a5 commit: b85115ed4c5d4e80ab818b44401e71299de9e9a5 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Christian Heimes <christian at python.org> date: 2018-05-20T20:22:50+02:00 summary: [3.7] bpo-32262: Fix typo in f-string (GH-7016) Fix typo from commit 6370f345e1d5829e1fba59cd695c8b82c5a8c620 (cherry picked from commit d361e99868a9eaa7ffce9341e1207705dbb66b50) Co-authored-by: Christian Heimes <christian at python.org> files: M Lib/asyncio/base_subprocess.py M Lib/test/test_asyncio/test_subprocess.py diff --git a/Lib/asyncio/base_subprocess.py b/Lib/asyncio/base_subprocess.py index 7c17066f8bb2..b547c444ad5d 100644 --- a/Lib/asyncio/base_subprocess.py +++ b/Lib/asyncio/base_subprocess.py @@ -57,7 +57,7 @@ def __repr__(self): if self._closed: info.append('closed') if self._pid is not None: - info.append(f'pid={self.pid}') + info.append(f'pid={self._pid}') if self._returncode is not None: info.append(f'returncode={self._returncode}') elif self._pid is not None: diff --git a/Lib/test/test_asyncio/test_subprocess.py b/Lib/test/test_asyncio/test_subprocess.py index 81b08d6c292a..428510f77161 100644 --- a/Lib/test/test_asyncio/test_subprocess.py +++ b/Lib/test/test_asyncio/test_subprocess.py @@ -29,6 +29,7 @@ def _start(self, *args, **kwargs): self._proc.stdin = None self._proc.stdout = None self._proc.stderr = None + self._proc.pid = -1 class SubprocessTransportTests(test_utils.TestCase): @@ -73,6 +74,29 @@ def test_proc_exited(self): transport.close() + def test_subprocess_repr(self): + waiter = asyncio.Future(loop=self.loop) + transport, protocol = self.create_transport(waiter) + transport._process_exited(6) + self.loop.run_until_complete(waiter) + + self.assertEqual( + repr(transport), + "<TestSubprocessTransport pid=-1 returncode=6>" + ) + transport._returncode = None + self.assertEqual( + repr(transport), + "<TestSubprocessTransport pid=-1 running>" + ) + transport._pid = None + transport._returncode = None + self.assertEqual( + repr(transport), + "<TestSubprocessTransport not started>" + ) + transport.close() + class SubprocessMixin: From webhook-mailer at python.org Sun May 20 17:00:16 2018 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Sun, 20 May 2018 21:00:16 -0000 Subject: [Python-checkins] Add idlelib and IDLE section to What's New in 3.7. (#7019) Message-ID: <mailman.186.1526850017.2757.python-checkins@python.org> https://github.com/python/cpython/commit/dd281873baeaade38ceee70b10e649cfaadcf15a commit: dd281873baeaade38ceee70b10e649cfaadcf15a branch: master author: Terry Jan Reedy <tjreedy at udel.edu> committer: GitHub <noreply at github.com> date: 2018-05-20T17:00:13-04:00 summary: Add idlelib and IDLE section to What's New in 3.7. (#7019) files: M Doc/whatsnew/3.7.rst diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 09a6eac879c4..8324be801491 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -923,6 +923,33 @@ It is used when ``http.server`` is run with ``-m``. (Contributed by Julien Palard in :issue:`31639`.) +idlelib and IDLE +---------------- + +Module Browser (on the File menu, formerly called Class Browser), +now displays nested functions and classed in addition to top-level +functions and classes. +(Contributed by Guilherme Polo, Cheryl Sabella, and Terry Jan Reedy +in :issue:`1612262`.) + +The Settings dialog (Options, Configure IDLE) has been partly rewritten +to improve both appearance and function. +(Contributed by Cheryl Sabella and Terry Jan Reedy in multiple issues.) + +The font sample now includes a selection of non-Latin characters so that +users can better see the effect of selecting a particular font. +(Contributed by Terry Jan Reedy in :issue:`13802`.) +The sample can be edited to test other characters. +(Contributed by Serhiy Storchaka in :issue:`31860`.) + +The IDLE features formerly implemented as extensions have been reimplemented +as normal features. Their settings have been moved from the Extensions tab +to other dialog tabs. +(Contributed by Charles Wohlganger and Terry Jan Reedy in :issue:`27099`.) + +The changes above have been backported to 3.6 maintenance releases. + + importlib --------- From webhook-mailer at python.org Sun May 20 17:44:20 2018 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Sun, 20 May 2018 21:44:20 -0000 Subject: [Python-checkins] Add idlelib and IDLE section to What's New in 3.7. (GH-7019) (GH-7020) Message-ID: <mailman.187.1526852661.2757.python-checkins@python.org> https://github.com/python/cpython/commit/98a18def99c140afdedf0da86d72333e8a466188 commit: 98a18def99c140afdedf0da86d72333e8a466188 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Terry Jan Reedy <tjreedy at udel.edu> date: 2018-05-20T17:44:12-04:00 summary: Add idlelib and IDLE section to What's New in 3.7. (GH-7019) (GH-7020) (cherry picked from commit dd281873baeaade38ceee70b10e649cfaadcf15a) Co-authored-by: Terry Jan Reedy <tjreedy at udel.edu> files: M Doc/whatsnew/3.7.rst diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 09a6eac879c4..8324be801491 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -923,6 +923,33 @@ It is used when ``http.server`` is run with ``-m``. (Contributed by Julien Palard in :issue:`31639`.) +idlelib and IDLE +---------------- + +Module Browser (on the File menu, formerly called Class Browser), +now displays nested functions and classed in addition to top-level +functions and classes. +(Contributed by Guilherme Polo, Cheryl Sabella, and Terry Jan Reedy +in :issue:`1612262`.) + +The Settings dialog (Options, Configure IDLE) has been partly rewritten +to improve both appearance and function. +(Contributed by Cheryl Sabella and Terry Jan Reedy in multiple issues.) + +The font sample now includes a selection of non-Latin characters so that +users can better see the effect of selecting a particular font. +(Contributed by Terry Jan Reedy in :issue:`13802`.) +The sample can be edited to test other characters. +(Contributed by Serhiy Storchaka in :issue:`31860`.) + +The IDLE features formerly implemented as extensions have been reimplemented +as normal features. Their settings have been moved from the Extensions tab +to other dialog tabs. +(Contributed by Charles Wohlganger and Terry Jan Reedy in :issue:`27099`.) + +The changes above have been backported to 3.6 maintenance releases. + + importlib --------- From webhook-mailer at python.org Sun May 20 18:50:36 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sun, 20 May 2018 22:50:36 -0000 Subject: [Python-checkins] [2.7] bpo-33542: Ignore DUID in uuid.get_node on Windows. (GH-6922) (GH-7015) Message-ID: <mailman.188.1526856637.2757.python-checkins@python.org> https://github.com/python/cpython/commit/ea9a0994cd0f4bd37799b045c34097eb21662b3d commit: ea9a0994cd0f4bd37799b045c34097eb21662b3d branch: 2.7 author: Serhiy Storchaka <storchaka at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-21T01:50:33+03:00 summary: [2.7] bpo-33542: Ignore DUID in uuid.get_node on Windows. (GH-6922) (GH-7015) uuid._ipconfig_getnode did not validate the maximum length of the value, so long as the value had the same type of formatting as a MAC address. This let it select DUIDs as MAC addresses. It now requires an exact length match.. (cherry picked from commit c66c342cb42ab8a88884527ddfe3a5086bc06316) Co-authored-by: CtrlZvi <viz+github at flippedperspective.com> files: A Misc/NEWS.d/next/Library/2018-05-16-09-30-27.bpo-33542.idNAcs.rst M Lib/uuid.py M Misc/ACKS diff --git a/Lib/uuid.py b/Lib/uuid.py index 618bc6385cfc..973013c00636 100644 --- a/Lib/uuid.py +++ b/Lib/uuid.py @@ -419,7 +419,7 @@ def _ipconfig_getnode(): with pipe: for line in pipe: value = line.split(':')[-1].strip().lower() - if re.match('([0-9a-f][0-9a-f]-){5}[0-9a-f][0-9a-f]', value): + if re.match('(?:[0-9a-f][0-9a-f]-){5}[0-9a-f][0-9a-f]$', value): return int(value.replace('-', ''), 16) def _netbios_getnode(): diff --git a/Misc/ACKS b/Misc/ACKS index 394fbb93f2f1..295b933f4b95 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -381,6 +381,7 @@ Ulrich Eckhardt David Edelsohn John Edmonds Grant Edwards +Zvi Effron John Ehresman Tal Einat Eric Eisner diff --git a/Misc/NEWS.d/next/Library/2018-05-16-09-30-27.bpo-33542.idNAcs.rst b/Misc/NEWS.d/next/Library/2018-05-16-09-30-27.bpo-33542.idNAcs.rst new file mode 100644 index 000000000000..16ba799131f4 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-16-09-30-27.bpo-33542.idNAcs.rst @@ -0,0 +1,2 @@ +Prevent ``uuid.get_node`` from using a DUID instead of a MAC on Windows. +Patch by Zvi Effron From webhook-mailer at python.org Sun May 20 18:51:39 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sun, 20 May 2018 22:51:39 -0000 Subject: [Python-checkins] bpo-33580: Make binary/text file glossary entries follow most common "see also" style. (GH-6991) (GH-7012) Message-ID: <mailman.189.1526856701.2757.python-checkins@python.org> https://github.com/python/cpython/commit/4ecdc1110df211686a4406ba666a7f8106e0f618 commit: 4ecdc1110df211686a4406ba666a7f8106e0f618 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Serhiy Storchaka <storchaka at gmail.com> date: 2018-05-21T01:51:37+03:00 summary: bpo-33580: Make binary/text file glossary entries follow most common "see also" style. (GH-6991) (GH-7012) (cherry picked from commit 0c4be82890858f874ff2158b0fcfdb8f261569c0) Co-authored-by: Andr?s Delfino <adelfino at gmail.com> files: M Doc/glossary.rst diff --git a/Doc/glossary.rst b/Doc/glossary.rst index a90f176db7ba..4b1722f5c036 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -136,8 +136,8 @@ Glossary :data:`sys.stdout.buffer`, and instances of :class:`io.BytesIO` and :class:`gzip.GzipFile`. - .. seealso:: - A :term:`text file` reads and writes :class:`str` objects. + See also :term:`text file` for a file object able to read and write + :class:`str` objects. bytes-like object An object that supports the :ref:`bufferobjects` and can @@ -1006,8 +1006,8 @@ Glossary :data:`sys.stdin`, :data:`sys.stdout`, and instances of :class:`io.StringIO`. - .. seealso:: - A :term:`binary file` reads and write :class:`bytes` objects. + See also :term:`binary file` for a file object able to read and write + :term:`bytes-like objects <bytes-like object>`. triple-quoted string A string which is bound by three instances of either a quotation mark From webhook-mailer at python.org Sun May 20 19:36:10 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sun, 20 May 2018 23:36:10 -0000 Subject: [Python-checkins] Fix line breaks added after hyphens by blurb. (GH-7002) Message-ID: <mailman.190.1526859370.2757.python-checkins@python.org> https://github.com/python/cpython/commit/aef639f62677f8a342af24e9c19f0503b0d1e36e commit: aef639f62677f8a342af24e9c19f0503b0d1e36e branch: master author: Serhiy Storchaka <storchaka at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-21T02:36:05+03:00 summary: Fix line breaks added after hyphens by blurb. (GH-7002) Also remove bullet asterisks from IDLE entries. files: M Misc/NEWS.d/3.5.0a1.rst M Misc/NEWS.d/3.5.0a3.rst M Misc/NEWS.d/3.5.0b3.rst M Misc/NEWS.d/3.5.0b4.rst M Misc/NEWS.d/3.5.1rc1.rst M Misc/NEWS.d/3.5.2rc1.rst M Misc/NEWS.d/3.5.3rc1.rst M Misc/NEWS.d/3.6.0a1.rst M Misc/NEWS.d/3.6.0b1.rst M Misc/NEWS.d/3.6.0b4.rst M Misc/NEWS.d/3.7.0a1.rst M Misc/NEWS.d/3.7.0a3.rst M Misc/NEWS.d/3.7.0b1.rst M Misc/NEWS.d/next/macOS/2018-03-29-06-56-12.bpo-32726.urS9uX.rst diff --git a/Misc/NEWS.d/3.5.0a1.rst b/Misc/NEWS.d/3.5.0a1.rst index e83a8080cf8d..0104a31629eb 100644 --- a/Misc/NEWS.d/3.5.0a1.rst +++ b/Misc/NEWS.d/3.5.0a1.rst @@ -2706,8 +2706,8 @@ Added support for the "xztar" format in the shutil module. .. nonce: ZLsRil .. section: Library -Don't force 3rd party C extensions to be built with -Werror=declaration- -after-statement. +Don't force 3rd party C extensions to be built with +``-Werror=declaration-after-statement``. .. @@ -4464,8 +4464,8 @@ Improve repr of inspect.Signature and inspect.Parameter. .. nonce: DFMEgN .. section: Library -Fix inspect.getcallargs() to raise correct TypeError for missing keyword- -only arguments. Patch by Jeremiah Lowin. +Fix inspect.getcallargs() to raise correct TypeError for missing +keyword-only arguments. Patch by Jeremiah Lowin. .. @@ -5059,8 +5059,8 @@ Anticipated fixes to support OS X versions > 10.9. .. nonce: KAl7aO .. section: Build -Prevent possible segfaults and other random failures of python --generate- -posix-vars in pybuilddir.txt build target. +Prevent possible segfaults and other random failures of python +``--generate-posix-vars`` in pybuilddir.txt build target. .. diff --git a/Misc/NEWS.d/3.5.0a3.rst b/Misc/NEWS.d/3.5.0a3.rst index a096809951da..c71afe63ab6d 100644 --- a/Misc/NEWS.d/3.5.0a3.rst +++ b/Misc/NEWS.d/3.5.0a3.rst @@ -62,8 +62,8 @@ Fix the default __sizeof__ implementation for variable-sized objects. .. nonce: b5M04V .. section: Library -The groupindex attribute of regular expression pattern object now is non- -modifiable mapping. +The groupindex attribute of regular expression pattern object now is +non-modifiable mapping. .. diff --git a/Misc/NEWS.d/3.5.0b3.rst b/Misc/NEWS.d/3.5.0b3.rst index 4081dd54876f..00f2de3863f5 100644 --- a/Misc/NEWS.d/3.5.0b3.rst +++ b/Misc/NEWS.d/3.5.0b3.rst @@ -110,8 +110,8 @@ by Martin Panter. .. nonce: aAbWbQ .. section: Library -Restore semantic round-trip correctness in tokenize/untokenize for tab- -indented blocks. +Restore semantic round-trip correctness in tokenize/untokenize for +tab-indented blocks. .. diff --git a/Misc/NEWS.d/3.5.0b4.rst b/Misc/NEWS.d/3.5.0b4.rst index 436981c6fe92..8ab257ae1c5a 100644 --- a/Misc/NEWS.d/3.5.0b4.rst +++ b/Misc/NEWS.d/3.5.0b4.rst @@ -224,8 +224,8 @@ segment. .. nonce: hwXwCH .. section: Library -SMTP.auth() and SMTP.login() now support RFC 4954's optional initial- -response argument to the SMTP AUTH command. +SMTP.auth() and SMTP.login() now support RFC 4954's optional +initial-response argument to the SMTP AUTH command. .. diff --git a/Misc/NEWS.d/3.5.1rc1.rst b/Misc/NEWS.d/3.5.1rc1.rst index 87672566ccae..1f8850fc678a 100644 --- a/Misc/NEWS.d/3.5.1rc1.rst +++ b/Misc/NEWS.d/3.5.1rc1.rst @@ -159,8 +159,8 @@ twice. On Solaris 11.3 or newer, os.urandom() now uses the getrandom() function instead of the getentropy() function. The getentropy() function is blocking -to generate very good quality entropy, os.urandom() doesn't need such high- -quality entropy. +to generate very good quality entropy, os.urandom() doesn't need such +high-quality entropy. .. @@ -1083,10 +1083,10 @@ them a 'sheet'. Patch by Mark Roseman. .. nonce: -j_BV7 .. section: IDLE -Enhance the initial html viewer now used for Idle Help. * Properly indent -fixed-pitch text (patch by Mark Roseman). * Give code snippet a very Sphinx- -like light blueish-gray background. * Re-use initial width and height set by -users for shell and editor. * When the Table of Contents (TOC) menu is used, +Enhance the initial html viewer now used for Idle Help. Properly indent +fixed-pitch text (patch by Mark Roseman). Give code snippet a very +Sphinx-like light blueish-gray background. Re-use initial width and height set by +users for shell and editor. When the Table of Contents (TOC) menu is used, put the section header at the top of the screen. .. diff --git a/Misc/NEWS.d/3.5.2rc1.rst b/Misc/NEWS.d/3.5.2rc1.rst index caed84a06f78..920c95169e28 100644 --- a/Misc/NEWS.d/3.5.2rc1.rst +++ b/Misc/NEWS.d/3.5.2rc1.rst @@ -568,9 +568,9 @@ string. Original fix by J?n Janech. .. section: Library The "urllib.request" module now percent-encodes non-ASCII bytes found in -redirect target URLs. Some servers send Location header fields with non- -ASCII bytes, but "http.client" requires the request target to be ASCII- -encodable, otherwise a UnicodeEncodeError is raised. Based on patch by +redirect target URLs. Some servers send Location header fields with +non-ASCII bytes, but "http.client" requires the request target to be +ASCII-encodable, otherwise a UnicodeEncodeError is raised. Based on patch by Christian Heimes. .. @@ -1952,8 +1952,8 @@ Fix linking extension modules for cross builds. Patch by Xavier de Gaye. .. nonce: HDjM4s .. section: Build -Disable the rules for running _freeze_importlib and pgen when cross- -compiling. The output of these programs is normally saved with the source +Disable the rules for running _freeze_importlib and pgen when +cross-compiling. The output of these programs is normally saved with the source code anyway, and is still regenerated when doing a native build. Patch by Xavier de Gaye. diff --git a/Misc/NEWS.d/3.5.3rc1.rst b/Misc/NEWS.d/3.5.3rc1.rst index 5c6859c8c1ab..09ebc541a396 100644 --- a/Misc/NEWS.d/3.5.3rc1.rst +++ b/Misc/NEWS.d/3.5.3rc1.rst @@ -81,8 +81,8 @@ astral characters. Patch by Xiang Zhang. .. nonce: RYbEGH .. section: Core and Builtins -Extra slash no longer added to sys.path components in case of empty compile- -time PYTHONPATH components. +Extra slash no longer added to sys.path components in case of empty +compile-time PYTHONPATH components. .. @@ -349,8 +349,8 @@ Patch written by Xiang Zhang. .. section: Core and Builtins Standard __import__() no longer look up "__import__" in globals or builtins -for importing submodules or "from import". Fixed handling an error of non- -string package name. +for importing submodules or "from import". Fixed handling an error of +non-string package name. .. @@ -2070,9 +2070,9 @@ Update message in validate_ucrtbase.py .. section: Build Cause lack of llvm-profdata tool when using clang as required for PGO -linking to be a configure time error rather than make time when --with- -optimizations is enabled. Also improve our ability to find the llvm- -profdata tool on MacOS and some Linuxes. +linking to be a configure time error rather than make time when +``--with-optimizations`` is enabled. Also improve our ability to find the +llvm-profdata tool on MacOS and some Linuxes. .. diff --git a/Misc/NEWS.d/3.6.0a1.rst b/Misc/NEWS.d/3.6.0a1.rst index 02c92a96882a..b1081a9e4e3b 100644 --- a/Misc/NEWS.d/3.6.0a1.rst +++ b/Misc/NEWS.d/3.6.0a1.rst @@ -728,8 +728,8 @@ Fixed a number of bugs in UTF-7 decoding of misformed data. .. section: Core and Builtins The UTF-8 encoder is now up to 75 times as fast for error handlers: -``ignore``, ``replace``, ``surrogateescape``, ``surrogatepass``. Patch co- -written with Serhiy Storchaka. +``ignore``, ``replace``, ``surrogateescape``, ``surrogatepass``. Patch +co-written with Serhiy Storchaka. .. @@ -761,8 +761,8 @@ by Serhiy Storchaka. On Solaris 11.3 or newer, os.urandom() now uses the getrandom() function instead of the getentropy() function. The getentropy() function is blocking -to generate very good quality entropy, os.urandom() doesn't need such high- -quality entropy. +to generate very good quality entropy, os.urandom() doesn't need such +high-quality entropy. .. @@ -891,9 +891,9 @@ string. Original fix by J?n Janech. .. section: Library The "urllib.request" module now percent-encodes non-ASCII bytes found in -redirect target URLs. Some servers send Location header fields with non- -ASCII bytes, but "http.client" requires the request target to be ASCII- -encodable, otherwise a UnicodeEncodeError is raised. Based on patch by +redirect target URLs. Some servers send Location header fields with +non-ASCII bytes, but "http.client" requires the request target to be +ASCII-encodable, otherwise a UnicodeEncodeError is raised. Based on patch by Christian Heimes. .. @@ -3328,10 +3328,10 @@ them a 'sheet'. Patch by Mark Roseman. .. nonce: -j_BV7 .. section: IDLE -Enhance the initial html viewer now used for Idle Help. * Properly indent -fixed-pitch text (patch by Mark Roseman). * Give code snippet a very Sphinx- -like light blueish-gray background. * Re-use initial width and height set by -users for shell and editor. * When the Table of Contents (TOC) menu is used, +Enhance the initial html viewer now used for Idle Help. Properly indent +fixed-pitch text (patch by Mark Roseman). Give code snippet a very +Sphinx-like light blueish-gray background. Re-use initial width and height set by +users for shell and editor. When the Table of Contents (TOC) menu is used, put the section header at the top of the screen. .. @@ -3651,8 +3651,8 @@ particular on Android). Patch by Chi Hsuan Yen. .. nonce: HDjM4s .. section: Build -Disable the rules for running _freeze_importlib and pgen when cross- -compiling. The output of these programs is normally saved with the source +Disable the rules for running _freeze_importlib and pgen when +cross-compiling. The output of these programs is normally saved with the source code anyway, and is still regenerated when doing a native build. Patch by Xavier de Gaye. diff --git a/Misc/NEWS.d/3.6.0b1.rst b/Misc/NEWS.d/3.6.0b1.rst index 8e0197fcbcae..6ff8bbb99d2c 100644 --- a/Misc/NEWS.d/3.6.0b1.rst +++ b/Misc/NEWS.d/3.6.0b1.rst @@ -507,8 +507,8 @@ expression. .. nonce: TJ779X .. section: Library -xmlrpc now supports unmarshalling additional data types used by Apache XML- -RPC implementation for numerics and None. +xmlrpc now supports unmarshalling additional data types used by Apache +XML-RPC implementation for numerics and None. .. @@ -1416,9 +1416,9 @@ platforms. .. section: Build Cause lack of llvm-profdata tool when using clang as required for PGO -linking to be a configure time error rather than make time when --with- -optimizations is enabled. Also improve our ability to find the llvm- -profdata tool on MacOS and some Linuxes. +linking to be a configure time error rather than make time when +``--with-optimizations`` is enabled. Also improve our ability to find the +llvm-profdata tool on MacOS and some Linuxes. .. diff --git a/Misc/NEWS.d/3.6.0b4.rst b/Misc/NEWS.d/3.6.0b4.rst index 326da19dd26e..ab11cfd89bb4 100644 --- a/Misc/NEWS.d/3.6.0b4.rst +++ b/Misc/NEWS.d/3.6.0b4.rst @@ -54,8 +54,8 @@ astral characters. Patch by Xiang Zhang. .. nonce: RYbEGH .. section: Core and Builtins -Extra slash no longer added to sys.path components in case of empty compile- -time PYTHONPATH components. +Extra slash no longer added to sys.path components in case of empty +compile-time PYTHONPATH components. .. diff --git a/Misc/NEWS.d/3.7.0a1.rst b/Misc/NEWS.d/3.7.0a1.rst index 262bfabb3ec1..3962923a2d24 100644 --- a/Misc/NEWS.d/3.7.0a1.rst +++ b/Misc/NEWS.d/3.7.0a1.rst @@ -49,8 +49,8 @@ Upgrade expat copy from 2.2.0 to 2.2.1 to get fixes of multiple security vulnerabilities including: CVE-2017-9233 (External entity infinite loop DoS), CVE-2016-9063 (Integer overflow, re-fix), CVE-2016-0718 (Fix regression bugs from 2.2.0's fix to CVE-2016-0718) and CVE-2012-0876 -(Counter hash flooding with SipHash). Note: the CVE-2016-5300 (Use os- -specific entropy sources like getrandom) doesn't impact Python, since Python +(Counter hash flooding with SipHash). Note: the CVE-2016-5300 (Use +os-specific entropy sources like getrandom) doesn't impact Python, since Python already gets entropy from the OS to set the expat secret using ``XML_SetHashSalt()``. @@ -336,8 +336,8 @@ ImportError rather than SystemError. Improve signal delivery. -Avoid using Py_AddPendingCall from signal handler, to avoid calling signal- -unsafe functions. The tests I'm adding here fail without the rest of the +Avoid using Py_AddPendingCall from signal handler, to avoid calling +signal-unsafe functions. The tests I'm adding here fail without the rest of the patch, on Linux and OS X. This means our signal delivery logic had defects (some signals could be lost). @@ -1153,8 +1153,8 @@ Improve speed of the STORE_DEREF opcode by 40%. .. nonce: RYbEGH .. section: Core and Builtins -Extra slash no longer added to sys.path components in case of empty compile- -time PYTHONPATH components. +Extra slash no longer added to sys.path components in case of empty +compile-time PYTHONPATH components. .. @@ -2274,8 +2274,8 @@ LF. Patch by Dong-hee Na. .. nonce: N3KI-o .. section: Library -os.listdir() and os.scandir() now emit bytes names when called with bytes- -like argument. +os.listdir() and os.scandir() now emit bytes names when called with +bytes-like argument. .. @@ -2440,8 +2440,8 @@ leaving a fd in a bad state in case of error. Patch by Giampaolo Rodola'. .. nonce: d0nRRA .. section: Library -multiprocessing.Queue.get() with a timeout now polls its reader in non- -blocking mode if it succeeded to acquire the lock but the acquire took +multiprocessing.Queue.get() with a timeout now polls its reader in +non-blocking mode if it succeeded to acquire the lock but the acquire took longer than the timeout. .. @@ -2815,8 +2815,8 @@ of space. .. section: Library Various updates to typing module: add typing.NoReturn type, use -WrapperDescriptorType, minor bug-fixes. Original PRs by Jim Fasarakis- -Hilliard and Ivan Levkivskyi. +WrapperDescriptorType, minor bug-fixes. Original PRs by Jim +Fasarakis-Hilliard and Ivan Levkivskyi. .. @@ -3634,8 +3634,8 @@ Removed deprecated features in the http.cookies module. .. nonce: CgcjEx .. section: Library -A format string argument for string.Formatter.format() is now positional- -only. +A format string argument for string.Formatter.format() is now +positional-only. .. @@ -5164,8 +5164,8 @@ Fix out-of-tree builds of Python when configured with ``--with--dtrace``. .. section: Build Prevent unnecessary rebuilding of Python during ``make test``, ``make -install`` and some other make targets when configured with ``--enable- -optimizations``. +install`` and some other make targets when configured with +``--enable-optimizations``. .. @@ -5213,9 +5213,9 @@ Update Windows build and OS X installers to use OpenSSL 1.0.2k. .. nonce: i8UzRC .. section: Build -Prohibit implicit C function declarations: use -Werror=implicit-function- -declaration when possible (GCC and Clang, but it depends on the compiler -version). Patch written by Chi Hsuan Yen. +Prohibit implicit C function declarations: use +``-Werror=implicit-function-declaration`` when possible (GCC and Clang, +but it depends on the compiler version). Patch written by Chi Hsuan Yen. .. @@ -5774,8 +5774,8 @@ All custom keysets are saved as a whole in config- extension.cfg. All take effect as soon as one clicks Apply or Ok. The affected events are '<<force-open-completions>>', '<<expand-word>>', -'<<force-open-calltip>>', '<<flash-paren>>', '<<format-paragraph>>', '<<run- -module>>', '<<check-module>>', and '<<zoom-height>>'. Any (global) +'<<force-open-calltip>>', '<<flash-paren>>', '<<format-paragraph>>', +'<<run-module>>', '<<check-module>>', and '<<zoom-height>>'. Any (global) customizations made before 3.6.3 will not affect their keyset- specific customization after 3.6.3. and vice versa. diff --git a/Misc/NEWS.d/3.7.0a3.rst b/Misc/NEWS.d/3.7.0a3.rst index 516e41e48eca..7de841526cdc 100644 --- a/Misc/NEWS.d/3.7.0a3.rst +++ b/Misc/NEWS.d/3.7.0a3.rst @@ -1544,8 +1544,8 @@ Multilingual Plane, tcl/tk will use other fonts that define a character. The expanded example give users of non-Latin characters a better idea of what they might see in IDLE's shell and editors. -To make room for the expanded sample, frames on the Font tab are re- -arranged. The Font/Tabs help explains a bit about the additions. +To make room for the expanded sample, frames on the Font tab are +re-arranged. The Font/Tabs help explains a bit about the additions. .. diff --git a/Misc/NEWS.d/3.7.0b1.rst b/Misc/NEWS.d/3.7.0b1.rst index ec7b3c8ecf78..aad642e41b16 100644 --- a/Misc/NEWS.d/3.7.0b1.rst +++ b/Misc/NEWS.d/3.7.0b1.rst @@ -180,8 +180,8 @@ longer raises ``RecursionError``; OrderedDict similarly. Instead, use .. section: Core and Builtins Py_Initialize() now creates the GIL. The GIL is no longer created "on -demand" to fix a race condition when PyGILState_Ensure() is called in a non- -Python thread. +demand" to fix a race condition when PyGILState_Ensure() is called in a +non-Python thread. .. diff --git a/Misc/NEWS.d/next/macOS/2018-03-29-06-56-12.bpo-32726.urS9uX.rst b/Misc/NEWS.d/next/macOS/2018-03-29-06-56-12.bpo-32726.urS9uX.rst index 470dc7f3eb12..9b769a831e58 100644 --- a/Misc/NEWS.d/next/macOS/2018-03-29-06-56-12.bpo-32726.urS9uX.rst +++ b/Misc/NEWS.d/next/macOS/2018-03-29-06-56-12.bpo-32726.urS9uX.rst @@ -1,5 +1,5 @@ Build and link with private copy of Tcl/Tk 8.6 for the macOS 10.6+ installer. The 10.9+ installer variant already does this. This means that the Python 3.7 provided by the python.org macOS installers no longer need or -use any external versions of Tcl/Tk, either system-provided or user- -installed, such as ActiveTcl. +use any external versions of Tcl/Tk, either system-provided or +user-installed, such as ActiveTcl. From webhook-mailer at python.org Sun May 20 19:46:45 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sun, 20 May 2018 23:46:45 -0000 Subject: [Python-checkins] bpo-26103: Fix inspect.isdatadescriptor() and a data descriptor definition. (GH-1959) Message-ID: <mailman.191.1526860009.2757.python-checkins@python.org> https://github.com/python/cpython/commit/4054b172ab59054715a2aaf4979bd84ac23e3ada commit: 4054b172ab59054715a2aaf4979bd84ac23e3ada branch: master author: Aaron Hall, MBA <aaronchall at yahoo.com> committer: Serhiy Storchaka <storchaka at gmail.com> date: 2018-05-21T02:46:42+03:00 summary: bpo-26103: Fix inspect.isdatadescriptor() and a data descriptor definition. (GH-1959) Look for '__set__' or '__delete__'. files: A Misc/NEWS.d/next/Library/2018-05-14-09-07-14.bpo-26103._zU8E2.rst M Doc/howto/descriptor.rst M Lib/inspect.py M Lib/test/test_inspect.py M Misc/ACKS diff --git a/Doc/howto/descriptor.rst b/Doc/howto/descriptor.rst index 5e85a9aa6594..6e4aa3e975f6 100644 --- a/Doc/howto/descriptor.rst +++ b/Doc/howto/descriptor.rst @@ -58,7 +58,7 @@ That is all there is to it. Define any of these methods and an object is considered a descriptor and can override default behavior upon being looked up as an attribute. -If an object defines both :meth:`__get__` and :meth:`__set__`, it is considered +If an object defines :meth:`__set__` or :meth:`__delete__`, it is considered a data descriptor. Descriptors that only define :meth:`__get__` are called non-data descriptors (they are typically used for methods but other uses are possible). diff --git a/Lib/inspect.py b/Lib/inspect.py index 512785f9237e..e5d312eb3021 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -110,7 +110,7 @@ def ismethoddescriptor(object): def isdatadescriptor(object): """Return true if the object is a data descriptor. - Data descriptors have both a __get__ and a __set__ attribute. Examples are + Data descriptors have a __set__ or a __delete__ attribute. Examples are properties (defined in Python) and getsets and members (defined in C). Typically, data descriptors will also have __name__ and __doc__ attributes (properties, getsets, and members have both of these attributes), but this @@ -119,7 +119,7 @@ def isdatadescriptor(object): # mutual exclusion return False tp = type(object) - return hasattr(tp, "__set__") and hasattr(tp, "__get__") + return hasattr(tp, "__set__") or hasattr(tp, "__delete__") if hasattr(types, 'MemberDescriptorType'): # CPython and equivalent diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index 3481a57ec833..ee227a66b17c 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -1134,6 +1134,61 @@ class C(metaclass=M): attrs = [a[0] for a in inspect.getmembers(C)] self.assertNotIn('missing', attrs) +class TestIsDataDescriptor(unittest.TestCase): + + def test_custom_descriptors(self): + class NonDataDescriptor: + def __get__(self, value, type=None): pass + class DataDescriptor0: + def __set__(self, name, value): pass + class DataDescriptor1: + def __delete__(self, name): pass + class DataDescriptor2: + __set__ = None + self.assertFalse(inspect.isdatadescriptor(NonDataDescriptor()), + 'class with only __get__ not a data descriptor') + self.assertTrue(inspect.isdatadescriptor(DataDescriptor0()), + 'class with __set__ is a data descriptor') + self.assertTrue(inspect.isdatadescriptor(DataDescriptor1()), + 'class with __delete__ is a data descriptor') + self.assertTrue(inspect.isdatadescriptor(DataDescriptor2()), + 'class with __set__ = None is a data descriptor') + + def test_slot(self): + class Slotted: + __slots__ = 'foo', + self.assertTrue(inspect.isdatadescriptor(Slotted.foo), + 'a slot is a data descriptor') + + def test_property(self): + class Propertied: + @property + def a_property(self): + pass + self.assertTrue(inspect.isdatadescriptor(Propertied.a_property), + 'a property is a data descriptor') + + def test_functions(self): + class Test(object): + def instance_method(self): pass + @classmethod + def class_method(cls): pass + @staticmethod + def static_method(): pass + def function(): + pass + a_lambda = lambda: None + self.assertFalse(inspect.isdatadescriptor(Test().instance_method), + 'a instance method is not a data descriptor') + self.assertFalse(inspect.isdatadescriptor(Test().class_method), + 'a class method is not a data descriptor') + self.assertFalse(inspect.isdatadescriptor(Test().static_method), + 'a static method is not a data descriptor') + self.assertFalse(inspect.isdatadescriptor(function), + 'a function is not a data descriptor') + self.assertFalse(inspect.isdatadescriptor(a_lambda), + 'a lambda is not a data descriptor') + _global_ref = object() class TestGetClosureVars(unittest.TestCase): @@ -3792,7 +3847,7 @@ def test_main(): TestGetcallargsUnboundMethods, TestGetattrStatic, TestGetGeneratorState, TestNoEOL, TestSignatureObject, TestSignatureBind, TestParameterObject, TestBoundArguments, TestSignaturePrivateHelpers, - TestSignatureDefinitions, + TestSignatureDefinitions, TestIsDataDescriptor, TestGetClosureVars, TestUnwrap, TestMain, TestReload, TestGetCoroutineState ) diff --git a/Misc/ACKS b/Misc/ACKS index cb7f4cd0275b..4d295b60a065 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -603,6 +603,7 @@ Peter Haight V?clav Haisman Zbigniew Halas Walker Hale IV +Aaron Christopher Hall Bob Halley Jesse Hallio Jun Hamano diff --git a/Misc/NEWS.d/next/Library/2018-05-14-09-07-14.bpo-26103._zU8E2.rst b/Misc/NEWS.d/next/Library/2018-05-14-09-07-14.bpo-26103._zU8E2.rst new file mode 100644 index 000000000000..cb4c41ba5db9 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-14-09-07-14.bpo-26103._zU8E2.rst @@ -0,0 +1,2 @@ +Correct ``inspect.isdatadescriptor`` to look for ``__set__`` or +``__delete__``. Patch by Aaron Hall. From webhook-mailer at python.org Mon May 21 04:13:58 2018 From: webhook-mailer at python.org (Andrew Svetlov) Date: Mon, 21 May 2018 08:13:58 -0000 Subject: [Python-checkins] bpo-33263: Fix FD leak in _SelectorSocketTransport (GH-6450) Message-ID: <mailman.192.1526890440.2757.python-checkins@python.org> https://github.com/python/cpython/commit/a84d0b361a26c05c6fadc6640591ec3feee5bfb5 commit: a84d0b361a26c05c6fadc6640591ec3feee5bfb5 branch: master author: Vlad Starostin <drtyrsa at yandex.ru> committer: Andrew Svetlov <andrew.svetlov at gmail.com> date: 2018-05-21T11:13:45+03:00 summary: bpo-33263: Fix FD leak in _SelectorSocketTransport (GH-6450) * bpo-33263 Fix FD leak in _SelectorSocketTransport. (GH-6450) Under particular circumstances _SelectorSocketTransport can try to add a reader even the transport is already being closed. This can lead to FD leak and invalid stated of the following connections. Fixed the SelectorSocketTransport to add the reader only if the trasport is still active. files: A Misc/NEWS.d/next/Library/2018-04-11-20-29-19.bpo-33263.B56Hc1.rst M Lib/asyncio/selector_events.py M Lib/test/test_asyncio/test_selector_events.py diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py index 354bf9d1c2de..f9533a1d77be 100644 --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -706,6 +706,12 @@ def _call_connection_lost(self, exc): def get_write_buffer_size(self): return len(self._buffer) + def _add_reader(self, fd, callback, *args): + if self._closing: + return + + self._loop._add_reader(fd, callback, *args) + class _SelectorSocketTransport(_SelectorTransport): @@ -732,7 +738,7 @@ def __init__(self, loop, sock, protocol, waiter=None, self._loop.call_soon(self._protocol.connection_made, self) # only start reading when connection_made() has been called - self._loop.call_soon(self._loop._add_reader, + self._loop.call_soon(self._add_reader, self._sock_fd, self._read_ready) if waiter is not None: # only wake up the waiter when connection_made() has been called @@ -754,7 +760,7 @@ def resume_reading(self): if self._closing or not self._paused: return self._paused = False - self._loop._add_reader(self._sock_fd, self._read_ready) + self._add_reader(self._sock_fd, self._read_ready) if self._loop.get_debug(): logger.debug("%r resumes reading", self) @@ -930,7 +936,7 @@ def __init__(self, loop, sock, protocol, address=None, self._address = address self._loop.call_soon(self._protocol.connection_made, self) # only start reading when connection_made() has been called - self._loop.call_soon(self._loop._add_reader, + self._loop.call_soon(self._add_reader, self._sock_fd, self._read_ready) if waiter is not None: # only wake up the waiter when connection_made() has been called diff --git a/Lib/test/test_asyncio/test_selector_events.py b/Lib/test/test_asyncio/test_selector_events.py index 219ab0eb5b8b..684c29dec3e2 100644 --- a/Lib/test/test_asyncio/test_selector_events.py +++ b/Lib/test/test_asyncio/test_selector_events.py @@ -871,6 +871,21 @@ def test_connection_lost(self): self.assertIsNone(tr._protocol) self.assertIsNone(tr._loop) + def test__add_reader(self): + tr = self.create_transport() + tr._buffer.extend(b'1') + tr._add_reader(7, mock.sentinel) + self.assertTrue(self.loop.readers) + + tr._force_close(None) + + self.assertTrue(tr.is_closing()) + self.assertFalse(self.loop.readers) + + # can not add readers after closing + tr._add_reader(7, mock.sentinel) + self.assertFalse(self.loop.readers) + class SelectorSocketTransportTests(test_utils.TestCase): diff --git a/Misc/NEWS.d/next/Library/2018-04-11-20-29-19.bpo-33263.B56Hc1.rst b/Misc/NEWS.d/next/Library/2018-04-11-20-29-19.bpo-33263.B56Hc1.rst new file mode 100644 index 000000000000..77994f6a5986 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-04-11-20-29-19.bpo-33263.B56Hc1.rst @@ -0,0 +1 @@ +Fix FD leak in `_SelectorSocketTransport` Patch by Vlad Starostin. From webhook-mailer at python.org Mon May 21 04:35:28 2018 From: webhook-mailer at python.org (Andrew Svetlov) Date: Mon, 21 May 2018 08:35:28 -0000 Subject: [Python-checkins] bpo-33263: Fix FD leak in _SelectorSocketTransport (GH-6450) (#7022) Message-ID: <mailman.193.1526891731.2757.python-checkins@python.org> https://github.com/python/cpython/commit/b8b800090ff0954117a26ffcb501307823f3d33a commit: b8b800090ff0954117a26ffcb501307823f3d33a branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Andrew Svetlov <andrew.svetlov at gmail.com> date: 2018-05-21T11:35:25+03:00 summary: bpo-33263: Fix FD leak in _SelectorSocketTransport (GH-6450) (#7022) * bpo-33263 Fix FD leak in _SelectorSocketTransport. (GH-6450) Under particular circumstances _SelectorSocketTransport can try to add a reader even the transport is already being closed. This can lead to FD leak and invalid stated of the following connections. Fixed the SelectorSocketTransport to add the reader only if the trasport is still active. (cherry picked from commit a84d0b361a26c05c6fadc6640591ec3feee5bfb5) Co-authored-by: Vlad Starostin <drtyrsa at yandex.ru> files: A Misc/NEWS.d/next/Library/2018-04-11-20-29-19.bpo-33263.B56Hc1.rst M Lib/asyncio/selector_events.py M Lib/test/test_asyncio/test_selector_events.py diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py index 354bf9d1c2de..f9533a1d77be 100644 --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -706,6 +706,12 @@ def _call_connection_lost(self, exc): def get_write_buffer_size(self): return len(self._buffer) + def _add_reader(self, fd, callback, *args): + if self._closing: + return + + self._loop._add_reader(fd, callback, *args) + class _SelectorSocketTransport(_SelectorTransport): @@ -732,7 +738,7 @@ def __init__(self, loop, sock, protocol, waiter=None, self._loop.call_soon(self._protocol.connection_made, self) # only start reading when connection_made() has been called - self._loop.call_soon(self._loop._add_reader, + self._loop.call_soon(self._add_reader, self._sock_fd, self._read_ready) if waiter is not None: # only wake up the waiter when connection_made() has been called @@ -754,7 +760,7 @@ def resume_reading(self): if self._closing or not self._paused: return self._paused = False - self._loop._add_reader(self._sock_fd, self._read_ready) + self._add_reader(self._sock_fd, self._read_ready) if self._loop.get_debug(): logger.debug("%r resumes reading", self) @@ -930,7 +936,7 @@ def __init__(self, loop, sock, protocol, address=None, self._address = address self._loop.call_soon(self._protocol.connection_made, self) # only start reading when connection_made() has been called - self._loop.call_soon(self._loop._add_reader, + self._loop.call_soon(self._add_reader, self._sock_fd, self._read_ready) if waiter is not None: # only wake up the waiter when connection_made() has been called diff --git a/Lib/test/test_asyncio/test_selector_events.py b/Lib/test/test_asyncio/test_selector_events.py index 219ab0eb5b8b..684c29dec3e2 100644 --- a/Lib/test/test_asyncio/test_selector_events.py +++ b/Lib/test/test_asyncio/test_selector_events.py @@ -871,6 +871,21 @@ def test_connection_lost(self): self.assertIsNone(tr._protocol) self.assertIsNone(tr._loop) + def test__add_reader(self): + tr = self.create_transport() + tr._buffer.extend(b'1') + tr._add_reader(7, mock.sentinel) + self.assertTrue(self.loop.readers) + + tr._force_close(None) + + self.assertTrue(tr.is_closing()) + self.assertFalse(self.loop.readers) + + # can not add readers after closing + tr._add_reader(7, mock.sentinel) + self.assertFalse(self.loop.readers) + class SelectorSocketTransportTests(test_utils.TestCase): diff --git a/Misc/NEWS.d/next/Library/2018-04-11-20-29-19.bpo-33263.B56Hc1.rst b/Misc/NEWS.d/next/Library/2018-04-11-20-29-19.bpo-33263.B56Hc1.rst new file mode 100644 index 000000000000..77994f6a5986 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-04-11-20-29-19.bpo-33263.B56Hc1.rst @@ -0,0 +1 @@ +Fix FD leak in `_SelectorSocketTransport` Patch by Vlad Starostin. From webhook-mailer at python.org Mon May 21 05:03:55 2018 From: webhook-mailer at python.org (Andrew Svetlov) Date: Mon, 21 May 2018 09:03:55 -0000 Subject: [Python-checkins] Fix asyncio flaky tests (#7023) Message-ID: <mailman.194.1526893435.2757.python-checkins@python.org> https://github.com/python/cpython/commit/e2537521916c5bf88fcf54d4654ff1bcd332be4a commit: e2537521916c5bf88fcf54d4654ff1bcd332be4a branch: master author: Andrew Svetlov <andrew.svetlov at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-21T12:03:45+03:00 summary: Fix asyncio flaky tests (#7023) files: M Lib/test/test_asyncio/test_base_events.py diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index 72c63df91070..a14c55693539 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -1855,9 +1855,10 @@ def prepare(self): for _ in range(10): try: - self.run_loop(self.loop.sock_connect(sock, (support.HOST, port))) + self.run_loop(self.loop.sock_connect(sock, + (support.HOST, port))) except OSError: - time.sleep(0.5) + self.run_loop(asyncio.sleep(0.5)) continue else: break From solipsis at pitrou.net Mon May 21 05:12:44 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Mon, 21 May 2018 09:12:44 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=5 Message-ID: <20180521091244.1.026580E8E9A3EFC8@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_collections leaked [7, -7, 1] memory blocks, sum=1 test_functools leaked [0, 3, 1] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflog0QcNE_', '--timeout', '7200'] From webhook-mailer at python.org Mon May 21 05:35:51 2018 From: webhook-mailer at python.org (INADA Naoki) Date: Mon, 21 May 2018 09:35:51 -0000 Subject: [Python-checkins] bpo-33583: Add note in PyObject_GC_Resize() doc (GH-7021) Message-ID: <mailman.195.1526895353.2757.python-checkins@python.org> https://github.com/python/cpython/commit/1179f4b40f375af5c59cd4b6be9cc313fa0e1a37 commit: 1179f4b40f375af5c59cd4b6be9cc313fa0e1a37 branch: master author: INADA Naoki <methane at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-21T18:35:41+09:00 summary: bpo-33583: Add note in PyObject_GC_Resize() doc (GH-7021) files: M Doc/c-api/gcsupport.rst M Modules/gcmodule.c diff --git a/Doc/c-api/gcsupport.rst b/Doc/c-api/gcsupport.rst index f5e0d7ec9c79..7f54b6a9cff8 100644 --- a/Doc/c-api/gcsupport.rst +++ b/Doc/c-api/gcsupport.rst @@ -49,7 +49,7 @@ Constructors for container types must conform to two rules: .. c:function:: TYPE* PyObject_GC_Resize(TYPE, PyVarObject *op, Py_ssize_t newsize) Resize an object allocated by :c:func:`PyObject_NewVar`. Returns the - resized object or *NULL* on failure. + resized object or *NULL* on failure. *op* must not be tracked by the collector yet. .. c:function:: void PyObject_GC_Track(PyObject *op) diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index 8ba1093c029d..09c73569360e 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -1752,6 +1752,7 @@ _PyObject_GC_Resize(PyVarObject *op, Py_ssize_t nitems) { const size_t basicsize = _PyObject_VAR_SIZE(Py_TYPE(op), nitems); PyGC_Head *g = AS_GC(op); + assert(!IS_TRACKED(op)); if (basicsize > PY_SSIZE_T_MAX - sizeof(PyGC_Head)) return (PyVarObject *)PyErr_NoMemory(); g = (PyGC_Head *)PyObject_REALLOC(g, sizeof(PyGC_Head) + basicsize); From webhook-mailer at python.org Mon May 21 06:09:55 2018 From: webhook-mailer at python.org (Andrew Svetlov) Date: Mon, 21 May 2018 10:09:55 -0000 Subject: [Python-checkins] [3.6] bpo-33263: Fix FD leak in _SelectorSocketTransport (GH-6450) (#7025) Message-ID: <mailman.196.1526897397.2757.python-checkins@python.org> https://github.com/python/cpython/commit/7208bfb64b74f31f9704be3f01f26861c9cf092b commit: 7208bfb64b74f31f9704be3f01f26861c9cf092b branch: 3.6 author: Andrew Svetlov <andrew.svetlov at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-21T13:09:49+03:00 summary: [3.6] bpo-33263: Fix FD leak in _SelectorSocketTransport (GH-6450) (#7025) * bpo-33263 Fix FD leak in _SelectorSocketTransport. (GH-6450) Under particular circumstances _SelectorSocketTransport can try to add a reader even the transport is already being closed. This can lead to FD leak and invalid stated of the following connections. Fixed the SelectorSocketTransport to add the reader only if the trasport is still active.. (cherry picked from commit a84d0b361a26c05c6fadc6640591ec3feee5bfb5) files: A Misc/NEWS.d/next/Library/2018-04-11-20-29-19.bpo-33263.B56Hc1.rst M Lib/asyncio/selector_events.py M Lib/test/test_asyncio/test_selector_events.py diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py index aa65702f2dbc..c7e7909449eb 100644 --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -673,6 +673,12 @@ def _call_connection_lost(self, exc): def get_write_buffer_size(self): return len(self._buffer) + def _add_reader(self, fd, callback, *args): + if self._closing: + return + + self._loop._add_reader(fd, callback, *args) + class _SelectorSocketTransport(_SelectorTransport): @@ -689,7 +695,7 @@ def __init__(self, loop, sock, protocol, waiter=None, self._loop.call_soon(self._protocol.connection_made, self) # only start reading when connection_made() has been called - self._loop.call_soon(self._loop._add_reader, + self._loop.call_soon(self._add_reader, self._sock_fd, self._read_ready) if waiter is not None: # only wake up the waiter when connection_made() has been called @@ -710,9 +716,7 @@ def resume_reading(self): if not self._paused: raise RuntimeError('Not paused') self._paused = False - if self._closing: - return - self._loop._add_reader(self._sock_fd, self._read_ready) + self._add_reader(self._sock_fd, self._read_ready) if self._loop.get_debug(): logger.debug("%r resumes reading", self) @@ -1052,7 +1056,7 @@ def __init__(self, loop, sock, protocol, address=None, self._address = address self._loop.call_soon(self._protocol.connection_made, self) # only start reading when connection_made() has been called - self._loop.call_soon(self._loop._add_reader, + self._loop.call_soon(self._add_reader, self._sock_fd, self._read_ready) if waiter is not None: # only wake up the waiter when connection_made() has been called diff --git a/Lib/test/test_asyncio/test_selector_events.py b/Lib/test/test_asyncio/test_selector_events.py index 830b15c0893e..0794e994c9d4 100644 --- a/Lib/test/test_asyncio/test_selector_events.py +++ b/Lib/test/test_asyncio/test_selector_events.py @@ -832,6 +832,21 @@ def test_connection_lost(self): self.assertIsNone(tr._protocol) self.assertIsNone(tr._loop) + def test__add_reader(self): + tr = self.create_transport() + tr._buffer.extend(b'1') + tr._add_reader(7, mock.sentinel) + self.assertTrue(self.loop.readers) + + tr._force_close(None) + + self.assertTrue(tr.is_closing()) + self.assertFalse(self.loop.readers) + + # can not add readers after closing + tr._add_reader(7, mock.sentinel) + self.assertFalse(self.loop.readers) + class SelectorSocketTransportTests(test_utils.TestCase): diff --git a/Misc/NEWS.d/next/Library/2018-04-11-20-29-19.bpo-33263.B56Hc1.rst b/Misc/NEWS.d/next/Library/2018-04-11-20-29-19.bpo-33263.B56Hc1.rst new file mode 100644 index 000000000000..77994f6a5986 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-04-11-20-29-19.bpo-33263.B56Hc1.rst @@ -0,0 +1 @@ +Fix FD leak in `_SelectorSocketTransport` Patch by Vlad Starostin. From webhook-mailer at python.org Mon May 21 07:47:34 2018 From: webhook-mailer at python.org (Andrew Svetlov) Date: Mon, 21 May 2018 11:47:34 -0000 Subject: [Python-checkins] Fix asyncio flaky tests (GH-7023) (#7024) Message-ID: <mailman.197.1526903255.2757.python-checkins@python.org> https://github.com/python/cpython/commit/4d39ade62ac370cf59661a2fa7cd151c76cff087 commit: 4d39ade62ac370cf59661a2fa7cd151c76cff087 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Andrew Svetlov <andrew.svetlov at gmail.com> date: 2018-05-21T14:47:29+03:00 summary: Fix asyncio flaky tests (GH-7023) (#7024) (cherry picked from commit e2537521916c5bf88fcf54d4654ff1bcd332be4a) Co-authored-by: Andrew Svetlov <andrew.svetlov at gmail.com> files: M Lib/test/test_asyncio/test_base_events.py diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index 72c63df91070..a14c55693539 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -1855,9 +1855,10 @@ def prepare(self): for _ in range(10): try: - self.run_loop(self.loop.sock_connect(sock, (support.HOST, port))) + self.run_loop(self.loop.sock_connect(sock, + (support.HOST, port))) except OSError: - time.sleep(0.5) + self.run_loop(asyncio.sleep(0.5)) continue else: break From webhook-mailer at python.org Mon May 21 08:06:28 2018 From: webhook-mailer at python.org (Andrew Svetlov) Date: Mon, 21 May 2018 12:06:28 -0000 Subject: [Python-checkins] Use IPv4 only to avoid IP address collision (#7030) Message-ID: <mailman.198.1526904390.2757.python-checkins@python.org> https://github.com/python/cpython/commit/b7555babe95ee0db2f1224ec53cfe68a005448a1 commit: b7555babe95ee0db2f1224ec53cfe68a005448a1 branch: master author: Andrew Svetlov <andrew.svetlov at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-21T15:06:26+03:00 summary: Use IPv4 only to avoid IP address collision (#7030) files: M Lib/test/test_asyncio/test_base_events.py diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index a14c55693539..8566a9d5504f 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -1848,15 +1848,13 @@ def run_loop(self, coro): def prepare(self): sock = self.make_socket() proto = self.MyProto(self.loop) - af = socket.AF_UNSPEC if support.IPV6_ENABLED else socket.AF_INET server = self.run_loop(self.loop.create_server( - lambda: proto, support.HOST, 0, family=af)) - port = server.sockets[0].getsockname()[1] + lambda: proto, support.HOST, 0, family=socket.AF_INET)) + addr = server.sockets[0].getsockname() for _ in range(10): try: - self.run_loop(self.loop.sock_connect(sock, - (support.HOST, port))) + self.run_loop(self.loop.sock_connect(sock, addr)) except OSError: self.run_loop(asyncio.sleep(0.5)) continue @@ -1864,7 +1862,7 @@ def prepare(self): break else: # One last try, so we get the exception - self.run_loop(self.loop.sock_connect(sock, (support.HOST, port))) + self.run_loop(self.loop.sock_connect(sock, addr)) def cleanup(): server.close() From webhook-mailer at python.org Mon May 21 08:20:58 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Mon, 21 May 2018 12:20:58 -0000 Subject: [Python-checkins] [3.6] bpo-33542: Ignore DUID in uuid.get_node on Windows. (GH-6922) (GH-7014) Message-ID: <mailman.199.1526905261.2757.python-checkins@python.org> https://github.com/python/cpython/commit/e9e2fd75ccbc6e9a5221cf3525e39e9d042d843f commit: e9e2fd75ccbc6e9a5221cf3525e39e9d042d843f branch: 3.6 author: Serhiy Storchaka <storchaka at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-21T15:20:55+03:00 summary: [3.6] bpo-33542: Ignore DUID in uuid.get_node on Windows. (GH-6922) (GH-7014) uuid._ipconfig_getnode did not validate the maximum length of the value, so long as the value had the same type of formatting as a MAC address. This let it select DUIDs as MAC addresses. It now requires an exact length match. (cherry picked from commit c66c342cb42ab8a88884527ddfe3a5086bc06316) Co-authored-by: CtrlZvi <viz+github at flippedperspective.com> files: A Misc/NEWS.d/next/Library/2018-05-16-09-30-27.bpo-33542.idNAcs.rst M Lib/uuid.py M Misc/ACKS diff --git a/Lib/uuid.py b/Lib/uuid.py index 32a48eaeacff..db8b2ef94ed4 100644 --- a/Lib/uuid.py +++ b/Lib/uuid.py @@ -438,7 +438,7 @@ def _ipconfig_getnode(): with proc: for line in proc.stdout: value = line.split(':')[-1].strip().lower() - if re.match('([0-9a-f][0-9a-f]-){5}[0-9a-f][0-9a-f]', value): + if re.fullmatch('(?:[0-9a-f][0-9a-f]-){5}[0-9a-f][0-9a-f]', value): return int(value.replace('-', ''), 16) def _netbios_getnode(): diff --git a/Misc/ACKS b/Misc/ACKS index cda62f579095..8414b9140f51 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -415,6 +415,7 @@ Ulrich Eckhardt David Edelsohn John Edmonds Grant Edwards +Zvi Effron John Ehresman Tal Einat Eric Eisner diff --git a/Misc/NEWS.d/next/Library/2018-05-16-09-30-27.bpo-33542.idNAcs.rst b/Misc/NEWS.d/next/Library/2018-05-16-09-30-27.bpo-33542.idNAcs.rst new file mode 100644 index 000000000000..16ba799131f4 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-16-09-30-27.bpo-33542.idNAcs.rst @@ -0,0 +1,2 @@ +Prevent ``uuid.get_node`` from using a DUID instead of a MAC on Windows. +Patch by Zvi Effron From webhook-mailer at python.org Mon May 21 08:30:09 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 21 May 2018 12:30:09 -0000 Subject: [Python-checkins] Use IPv4 only to avoid IP address collision (GH-7030) Message-ID: <mailman.200.1526905809.2757.python-checkins@python.org> https://github.com/python/cpython/commit/316f86911a369a1c8f6f3a94620f1bdecefe59b2 commit: 316f86911a369a1c8f6f3a94620f1bdecefe59b2 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-21T05:30:06-07:00 summary: Use IPv4 only to avoid IP address collision (GH-7030) (cherry picked from commit b7555babe95ee0db2f1224ec53cfe68a005448a1) Co-authored-by: Andrew Svetlov <andrew.svetlov at gmail.com> files: M Lib/test/test_asyncio/test_base_events.py diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index a14c55693539..8566a9d5504f 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -1848,15 +1848,13 @@ def run_loop(self, coro): def prepare(self): sock = self.make_socket() proto = self.MyProto(self.loop) - af = socket.AF_UNSPEC if support.IPV6_ENABLED else socket.AF_INET server = self.run_loop(self.loop.create_server( - lambda: proto, support.HOST, 0, family=af)) - port = server.sockets[0].getsockname()[1] + lambda: proto, support.HOST, 0, family=socket.AF_INET)) + addr = server.sockets[0].getsockname() for _ in range(10): try: - self.run_loop(self.loop.sock_connect(sock, - (support.HOST, port))) + self.run_loop(self.loop.sock_connect(sock, addr)) except OSError: self.run_loop(asyncio.sleep(0.5)) continue @@ -1864,7 +1862,7 @@ def prepare(self): break else: # One last try, so we get the exception - self.run_loop(self.loop.sock_connect(sock, (support.HOST, port))) + self.run_loop(self.loop.sock_connect(sock, addr)) def cleanup(): server.close() From webhook-mailer at python.org Mon May 21 10:10:31 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 21 May 2018 14:10:31 -0000 Subject: [Python-checkins] bpo-33583: Add note in PyObject_GC_Resize() doc (GH-7021) Message-ID: <mailman.201.1526911832.2757.python-checkins@python.org> https://github.com/python/cpython/commit/3ccc31386da5f35f83756a265429831d650db731 commit: 3ccc31386da5f35f83756a265429831d650db731 branch: 2.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-21T07:10:27-07:00 summary: bpo-33583: Add note in PyObject_GC_Resize() doc (GH-7021) (cherry picked from commit 1179f4b40f375af5c59cd4b6be9cc313fa0e1a37) Co-authored-by: INADA Naoki <methane at users.noreply.github.com> files: M Doc/c-api/gcsupport.rst M Modules/gcmodule.c diff --git a/Doc/c-api/gcsupport.rst b/Doc/c-api/gcsupport.rst index 9438feaeb18a..18ecd071d7a3 100644 --- a/Doc/c-api/gcsupport.rst +++ b/Doc/c-api/gcsupport.rst @@ -56,7 +56,7 @@ Constructors for container types must conform to two rules: .. c:function:: TYPE* PyObject_GC_Resize(TYPE, PyVarObject *op, Py_ssize_t newsize) Resize an object allocated by :c:func:`PyObject_NewVar`. Returns the - resized object or *NULL* on failure. + resized object or *NULL* on failure. *op* must not be tracked by the collector yet. .. versionchanged:: 2.5 This function used an :c:type:`int` type for *newsize*. This might diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index 916e4817d93e..19011c47b5c4 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -1539,6 +1539,7 @@ _PyObject_GC_Resize(PyVarObject *op, Py_ssize_t nitems) { const size_t basicsize = _PyObject_VAR_SIZE(Py_TYPE(op), nitems); PyGC_Head *g = AS_GC(op); + assert(!IS_TRACKED(op)); if (basicsize > PY_SSIZE_T_MAX - sizeof(PyGC_Head)) return (PyVarObject *)PyErr_NoMemory(); g = (PyGC_Head *)PyObject_REALLOC(g, sizeof(PyGC_Head) + basicsize); From webhook-mailer at python.org Mon May 21 10:51:03 2018 From: webhook-mailer at python.org (INADA Naoki) Date: Mon, 21 May 2018 14:51:03 -0000 Subject: [Python-checkins] bpo-33583: Add note in PyObject_GC_Resize() doc (GH-7021) Message-ID: <mailman.202.1526914266.2757.python-checkins@python.org> https://github.com/python/cpython/commit/2b4ed5da1d599190c3be0084ee235b0a8f0a75ea commit: 2b4ed5da1d599190c3be0084ee235b0a8f0a75ea branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: INADA Naoki <methane at users.noreply.github.com> date: 2018-05-21T23:51:00+09:00 summary: bpo-33583: Add note in PyObject_GC_Resize() doc (GH-7021) (cherry picked from commit 1179f4b40f375af5c59cd4b6be9cc313fa0e1a37) Co-authored-by: INADA Naoki <methane at users.noreply.github.com> files: M Doc/c-api/gcsupport.rst M Modules/gcmodule.c diff --git a/Doc/c-api/gcsupport.rst b/Doc/c-api/gcsupport.rst index f5e0d7ec9c79..7f54b6a9cff8 100644 --- a/Doc/c-api/gcsupport.rst +++ b/Doc/c-api/gcsupport.rst @@ -49,7 +49,7 @@ Constructors for container types must conform to two rules: .. c:function:: TYPE* PyObject_GC_Resize(TYPE, PyVarObject *op, Py_ssize_t newsize) Resize an object allocated by :c:func:`PyObject_NewVar`. Returns the - resized object or *NULL* on failure. + resized object or *NULL* on failure. *op* must not be tracked by the collector yet. .. c:function:: void PyObject_GC_Track(PyObject *op) diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index 8ba1093c029d..09c73569360e 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -1752,6 +1752,7 @@ _PyObject_GC_Resize(PyVarObject *op, Py_ssize_t nitems) { const size_t basicsize = _PyObject_VAR_SIZE(Py_TYPE(op), nitems); PyGC_Head *g = AS_GC(op); + assert(!IS_TRACKED(op)); if (basicsize > PY_SSIZE_T_MAX - sizeof(PyGC_Head)) return (PyVarObject *)PyErr_NoMemory(); g = (PyGC_Head *)PyObject_REALLOC(g, sizeof(PyGC_Head) + basicsize); From lp_benchmark_robot at intel.com Mon May 21 21:17:34 2018 From: lp_benchmark_robot at intel.com (lp_benchmark_robot at intel.com) Date: Mon, 21 May 2018 18:17:34 -0700 Subject: [Python-checkins] [65 flat] Results for Python (master branch) 2018-05-21 Message-ID: <ec325f4b-5f8a-41bd-a3e4-aab4c56fa879@orsmsx151.amr.corp.intel.com> Results for project python/master, build date: 2018-05-21 03:03:27-07:00. - commit: 1179f4b - previous commit: d89ca94 - revision date: 2018-05-21 18:35:41+09:00 - environment: Broadwell-EP - cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores, stepping 1, LLC 55 MB - mem: 128 GB - os: Ubuntu 16.04.2 LTS - kernel: 4.4.0-62-generic x86_64 GNU/Linux Baseline results were generated using release v3.6.0, with hash 5c4568a from 2016-12-22 23:38:47+00:00. +-----+------------------------+--------+------------+------------+------------+ | | |relative|change since|change since|current rev | | | benchmark|std_dev*| last run | baseline |run with PGO| +-----+------------------------+--------+------------+------------+------------+ | :-| | 2to3| 0.748% | +0.599% | +9.462% | +6.587% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method| 1.066% | +0.094% | +23.866% | +12.655% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_slots| 2.274% | -0.283% | +25.045% | +11.934% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_unknown| 1.334% | -0.355% | +22.208% | +13.825% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_simple| 2.425% | -1.035% | +10.866% | +12.184% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chameleon| 1.734% | +1.317% | +12.580% | +10.095% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chaos| 0.739% | -0.290% | +8.516% | +11.126% | +-----+------------------------+--------+------------+------------+------------+ | :-| | crypto_pyaes| 0.744% | -0.001% | +0.030% | +8.257% | +-----+------------------------+--------+------------+------------+------------+ | :-| | deltablue| 3.277% | +0.062% | +11.989% | +17.239% | +-----+------------------------+--------+------------+------------+------------+ | :-| | django_template| 3.463% | -0.779% | +20.683% | +13.061% | +-----+------------------------+--------+------------+------------+------------+ | :-| | dulwich_log| 1.122% | +0.862% | +5.496% | +6.169% | +-----+------------------------+--------+------------+------------+------------+ | :-| | fannkuch| 0.905% | -0.420% | +7.164% | +4.914% | +-----+------------------------+--------+------------+------------+------------+ | :-| | float| 1.042% | +0.124% | +2.746% | +7.119% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_text| 1.182% | +0.033% | +14.667% | +9.103% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_xml| 1.625% | -1.458% | +10.967% | +9.655% | +-----+------------------------+--------+------------+------------+------------+ | :-| | go| 5.847% | -0.020% | +5.346% | +11.012% | +-----+------------------------+--------+------------+------------+------------+ | :-| | hexiom| 0.566% | -0.357% | +11.959% | +10.862% | +-----+------------------------+--------+------------+------------+------------+ | :-| | html5lib| 2.936% | +0.883% | +11.544% | +11.383% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_dumps| 0.934% | +0.806% | +4.122% | +8.735% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_loads| 3.544% | +2.665% | -3.354% | +14.962% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_format| 1.646% | +0.080% | +17.837% | +12.972% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_silent| 2.646% | -0.061% | +47.777% | +12.441% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_simple| 1.730% | +0.742% | +13.139% | +12.847% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mako| 0.542% | -0.073% | +16.816% | +15.268% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mdp| 6.860% | -0.136% | +1.637% | +15.365% | +-----+------------------------+--------+------------+------------+------------+ | :-| | meteor_contest| 0.699% | +0.291% | +4.825% | +6.408% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nbody| 0.902% | +1.740% | +0.832% | -1.700% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nqueens| 0.608% | -0.755% | +5.783% | +6.206% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pathlib| 1.414% | +1.212% | +2.191% | +9.103% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle| 1.195% | +0.158% | -0.088% | +21.976% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_dict| 0.267% | +0.063% | +7.624% | +11.109% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_list| 0.793% | -0.256% | +6.908% | +15.137% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_pure_python| 5.475% | +0.006% | +11.746% | +10.322% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pidigits| 0.036% | -0.025% | +0.272% | +10.389% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup| 0.120% | +0.235% | +19.063% | +4.825% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup_no_site| 0.081% | +0.195% | +6.118% | +5.008% | +-----+------------------------+--------+------------+------------+------------+ | :-| | raytrace| 1.095% | -1.251% | +9.691% | +14.997% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_compile| 5.667% | +0.899% | +4.595% | +11.301% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_dna| 0.472% | +0.044% | -2.050% | +14.038% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_effbot| 2.530% | +5.288% | -2.521% | +4.786% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_v8| 1.855% | -0.648% | +3.961% | +7.995% | +-----+------------------------+--------+------------+------------+------------+ | :-| | richards| 1.518% | -0.994% | +9.203% | +15.203% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_fft| 0.978% | -1.096% | -1.539% | +2.886% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_lu| 3.055% | -0.249% | +21.952% | +10.962% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_monte_carlo| 2.403% | -0.002% | +4.759% | +5.904% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sor| 1.317% | +0.427% | +15.281% | +7.458% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sparse_mat_mult| 0.969% | -0.093% | -3.008% | -0.708% | +-----+------------------------+--------+------------+------------+------------+ | :-| | spectral_norm| 1.001% | -1.299% | +4.177% | +5.939% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_declarative| 1.935% | +0.651% | +7.545% | +5.851% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_imperative| 3.825% | -1.123% | +7.408% | +5.936% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlite_synth| 3.598% | -0.694% | -0.976% | +9.875% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_expand| 2.410% | +0.792% | +18.374% | +6.510% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_integrate| 1.594% | +0.145% | +18.660% | +5.895% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_str| 3.451% | +0.605% | +19.783% | +7.855% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_sum| 6.903% | +0.475% | +16.514% | +10.468% | +-----+------------------------+--------+------------+------------+------------+ | :-| | telco| 4.658% | -1.230% | +19.618% | +9.546% | +-----+------------------------+--------+------------+------------+------------+ | :-| | tornado_http| 0.975% | +0.288% | +7.592% | +6.630% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpack_sequence| 1.006% | -0.226% | +2.572% | +2.295% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle| 7.980% | +0.422% | +6.890% | +21.984% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_list| 7.001% | -1.233% | -4.929% | +17.404% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_pure_python| 1.063% | -0.285% | +7.561% | +7.626% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_generate| 1.078% | +0.131% | +2.730% | +12.922% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_iterparse| 2.184% | +0.649% | +4.921% | +7.090% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_parse| 3.135% | -0.557% | -6.238% | +12.712% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_process| 1.040% | +0.103% | +5.025% | +10.897% | +-----+------------------------+--------+------------+------------+------------+ * Relative Standard Deviation (Standard Deviation/Average) If this is not displayed properly please visit our results page here: http://languagesperformance.intel.com/65-flat-results-for-python-master-branch-2018-05-21 Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. From webhook-mailer at python.org Mon May 21 22:18:48 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 22 May 2018 02:18:48 -0000 Subject: [Python-checkins] bpo-33583: Add note in PyObject_GC_Resize() doc (GH-7021) Message-ID: <mailman.0.1526955529.18020.python-checkins@python.org> https://github.com/python/cpython/commit/0c1e7d8122808d42f9fdb7019061dc2e78a78efa commit: 0c1e7d8122808d42f9fdb7019061dc2e78a78efa branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-21T19:18:41-07:00 summary: bpo-33583: Add note in PyObject_GC_Resize() doc (GH-7021) (cherry picked from commit 1179f4b40f375af5c59cd4b6be9cc313fa0e1a37) Co-authored-by: INADA Naoki <methane at users.noreply.github.com> files: M Doc/c-api/gcsupport.rst M Modules/gcmodule.c diff --git a/Doc/c-api/gcsupport.rst b/Doc/c-api/gcsupport.rst index f5e0d7ec9c79..7f54b6a9cff8 100644 --- a/Doc/c-api/gcsupport.rst +++ b/Doc/c-api/gcsupport.rst @@ -49,7 +49,7 @@ Constructors for container types must conform to two rules: .. c:function:: TYPE* PyObject_GC_Resize(TYPE, PyVarObject *op, Py_ssize_t newsize) Resize an object allocated by :c:func:`PyObject_NewVar`. Returns the - resized object or *NULL* on failure. + resized object or *NULL* on failure. *op* must not be tracked by the collector yet. .. c:function:: void PyObject_GC_Track(PyObject *op) diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index 754348e20a92..0b057ddbf5e4 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -1773,6 +1773,7 @@ _PyObject_GC_Resize(PyVarObject *op, Py_ssize_t nitems) { const size_t basicsize = _PyObject_VAR_SIZE(Py_TYPE(op), nitems); PyGC_Head *g = AS_GC(op); + assert(!IS_TRACKED(op)); if (basicsize > PY_SSIZE_T_MAX - sizeof(PyGC_Head)) return (PyVarObject *)PyErr_NoMemory(); g = (PyGC_Head *)PyObject_REALLOC(g, sizeof(PyGC_Head) + basicsize); From webhook-mailer at python.org Tue May 22 01:57:49 2018 From: webhook-mailer at python.org (Julien Palard) Date: Tue, 22 May 2018 05:57:49 -0000 Subject: [Python-checkins] Fix lambda parameters being refered as arguments (GH-7037) Message-ID: <mailman.1.1526968670.18020.python-checkins@python.org> https://github.com/python/cpython/commit/268cc7c3f8f58075b42ff0cd6b6c6c5d76044895 commit: 268cc7c3f8f58075b42ff0cd6b6c6c5d76044895 branch: master author: Andr?s Delfino <adelfino at gmail.com> committer: Julien Palard <julien at palard.fr> date: 2018-05-22T07:57:45+02:00 summary: Fix lambda parameters being refered as arguments (GH-7037) files: M Doc/glossary.rst M Doc/reference/expressions.rst diff --git a/Doc/glossary.rst b/Doc/glossary.rst index 0ee056ee28dd..194788824792 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -627,7 +627,7 @@ Glossary lambda An anonymous inline function consisting of a single :term:`expression` which is evaluated when the function is called. The syntax to create - a lambda function is ``lambda [arguments]: expression`` + a lambda function is ``lambda [parameters]: expression`` LBYL Look before you leap. This coding style explicitly tests for diff --git a/Doc/reference/expressions.rst b/Doc/reference/expressions.rst index e5af927da1ea..222b8978e370 100644 --- a/Doc/reference/expressions.rst +++ b/Doc/reference/expressions.rst @@ -1608,12 +1608,12 @@ Lambdas lambda_expr_nocond: "lambda" [`parameter_list`]: `expression_nocond` Lambda expressions (sometimes called lambda forms) are used to create anonymous -functions. The expression ``lambda arguments: expression`` yields a function +functions. The expression ``lambda parameters: expression`` yields a function object. The unnamed object behaves like a function object defined with: .. code-block:: none - def <lambda>(arguments): + def <lambda>(parameters): return expression See section :ref:`function` for the syntax of parameter lists. Note that From webhook-mailer at python.org Tue May 22 04:02:54 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Tue, 22 May 2018 08:02:54 -0000 Subject: [Python-checkins] bpo-5945: Improve mappings and sequences C API docs. (GH-7029) Message-ID: <mailman.2.1526976174.18020.python-checkins@python.org> https://github.com/python/cpython/commit/f5b1183610d5888db3bbd639b1a0c945dbd8f8dd commit: f5b1183610d5888db3bbd639b1a0c945dbd8f8dd branch: master author: Serhiy Storchaka <storchaka at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-22T11:02:44+03:00 summary: bpo-5945: Improve mappings and sequences C API docs. (GH-7029) files: M Doc/c-api/mapping.rst M Doc/c-api/object.rst M Doc/c-api/sequence.rst M Doc/c-api/typeobj.rst M Include/abstract.h diff --git a/Doc/c-api/mapping.rst b/Doc/c-api/mapping.rst index 308a9761f87e..b8eaadbd702c 100644 --- a/Doc/c-api/mapping.rst +++ b/Doc/c-api/mapping.rst @@ -5,11 +5,17 @@ Mapping Protocol ================ +See also :c:func:`PyObject_GetItem`, :c:func:`PyObject_SetItem` and +:c:func:`PyObject_DelItem`. + .. c:function:: int PyMapping_Check(PyObject *o) - Return ``1`` if the object provides mapping protocol, and ``0`` otherwise. This - function always succeeds. + Return ``1`` if the object provides mapping protocol or supports slicing, + and ``0`` otherwise. Note that it returns ``1`` for Python classes with + a :meth:`__getitem__` method since in general case it is impossible to + determine what the type of keys it supports. This function always + succeeds. .. c:function:: Py_ssize_t PyMapping_Size(PyObject *o) @@ -17,35 +23,49 @@ Mapping Protocol .. index:: builtin: len - Returns the number of keys in object *o* on success, and ``-1`` on failure. For - objects that do not provide mapping protocol, this is equivalent to the Python - expression ``len(o)``. + Returns the number of keys in object *o* on success, and ``-1`` on failure. + This is equivalent to the Python expression ``len(o)``. -.. c:function:: int PyMapping_DelItemString(PyObject *o, const char *key) +.. c:function:: PyObject* PyMapping_GetItemString(PyObject *o, const char *key) + + Return element of *o* corresponding to the string *key* or *NULL* on failure. + This is the equivalent of the Python expression ``o[key]``. + See also :c:func:`PyObject_GetItem`. + - Remove the mapping for object *key* from the object *o*. Return ``-1`` on - failure. This is equivalent to the Python statement ``del o[key]``. +.. c:function:: int PyMapping_SetItemString(PyObject *o, const char *key, PyObject *v) + + Map the string *key* to the value *v* in object *o*. Returns ``-1`` on + failure. This is the equivalent of the Python statement ``o[key] = v``. + See also :c:func:`PyObject_SetItem`. .. c:function:: int PyMapping_DelItem(PyObject *o, PyObject *key) - Remove the mapping for object *key* from the object *o*. Return ``-1`` on - failure. This is equivalent to the Python statement ``del o[key]``. + Remove the mapping for the object *key* from the object *o*. Return ``-1`` + on failure. This is equivalent to the Python statement ``del o[key]``. + This is an alias of :c:func:`PyObject_DelItem`. -.. c:function:: int PyMapping_HasKeyString(PyObject *o, const char *key) +.. c:function:: int PyMapping_DelItemString(PyObject *o, const char *key) - On success, return ``1`` if the mapping object has the key *key* and ``0`` - otherwise. This is equivalent to the Python expression ``key in o``. - This function always succeeds. + Remove the mapping for the string *key* from the object *o*. Return ``-1`` + on failure. This is equivalent to the Python statement ``del o[key]``. .. c:function:: int PyMapping_HasKey(PyObject *o, PyObject *key) - Return ``1`` if the mapping object has the key *key* and ``0`` otherwise. This - is equivalent to the Python expression ``key in o``. This function always - succeeds. + Return ``1`` if the mapping object has the key *key* and ``0`` otherwise. + This is equivalent to the Python expression ``key in o``. + This function always succeeds. + + +.. c:function:: int PyMapping_HasKeyString(PyObject *o, const char *key) + + Return ``1`` if the mapping object has the key *key* and ``0`` otherwise. + This is equivalent to the Python expression ``key in o``. + This function always succeeds. .. c:function:: PyObject* PyMapping_Keys(PyObject *o) @@ -73,15 +93,3 @@ Mapping Protocol .. versionchanged:: 3.7 Previously, the function returned a list or a tuple. - - -.. c:function:: PyObject* PyMapping_GetItemString(PyObject *o, const char *key) - - Return element of *o* corresponding to the object *key* or *NULL* on failure. - This is the equivalent of the Python expression ``o[key]``. - - -.. c:function:: int PyMapping_SetItemString(PyObject *o, const char *key, PyObject *v) - - Map the object *key* to the value *v* in object *o*. Returns ``-1`` on failure. - This is the equivalent of the Python statement ``o[key] = v``. diff --git a/Doc/c-api/object.rst b/Doc/c-api/object.rst index 754dedc1c603..f0b2005f2d12 100644 --- a/Doc/c-api/object.rst +++ b/Doc/c-api/object.rst @@ -379,8 +379,8 @@ Object Protocol parameters must be non-*NULL*. -.. c:function:: Py_ssize_t PyObject_Length(PyObject *o) - Py_ssize_t PyObject_Size(PyObject *o) +.. c:function:: Py_ssize_t PyObject_Size(PyObject *o) + Py_ssize_t PyObject_Length(PyObject *o) .. index:: builtin: len @@ -414,8 +414,8 @@ Object Protocol .. c:function:: int PyObject_DelItem(PyObject *o, PyObject *key) - Delete the mapping for *key* from *o*. Returns ``-1`` on failure. This is the - equivalent of the Python statement ``del o[key]``. + Remove the mapping for the object *key* from the object *o*. Return ``-1`` + on failure. This is equivalent to the Python statement ``del o[key]``. .. c:function:: PyObject* PyObject_Dir(PyObject *o) diff --git a/Doc/c-api/sequence.rst b/Doc/c-api/sequence.rst index 81f8557ea6e6..6d22f35e22b1 100644 --- a/Doc/c-api/sequence.rst +++ b/Doc/c-api/sequence.rst @@ -9,7 +9,10 @@ Sequence Protocol .. c:function:: int PySequence_Check(PyObject *o) Return ``1`` if the object provides sequence protocol, and ``0`` otherwise. - This function always succeeds. + Note that it returns ``1`` for Python classes with a :meth:`__getitem__` + method unless they are :class:`dict` subclasses since in general case it + is impossible to determine what the type of keys it supports. This + function always succeeds. .. c:function:: Py_ssize_t PySequence_Size(PyObject *o) @@ -119,18 +122,27 @@ Sequence Protocol .. index:: builtin: tuple - Return a tuple object with the same contents as the arbitrary sequence *o* or - *NULL* on failure. If *o* is a tuple, a new reference will be returned, + Return a tuple object with the same contents as the sequence or iterable *o*, + or *NULL* on failure. If *o* is a tuple, a new reference will be returned, otherwise a tuple will be constructed with the appropriate contents. This is equivalent to the Python expression ``tuple(o)``. .. c:function:: PyObject* PySequence_Fast(PyObject *o, const char *m) - Return the sequence *o* as a list, unless it is already a tuple or list, in + Return the sequence or iterable *o* as a list, unless it is already a tuple or list, in which case *o* is returned. Use :c:func:`PySequence_Fast_GET_ITEM` to access the members of the result. Returns *NULL* on failure. If the object is not - a sequence, raises :exc:`TypeError` with *m* as the message text. + a sequence or iterable, raises :exc:`TypeError` with *m* as the message text. + + +.. c:function:: Py_ssize_t PySequence_Fast_GET_SIZE(PyObject *o) + + Returns the length of *o*, assuming that *o* was returned by + :c:func:`PySequence_Fast` and that *o* is not *NULL*. The size can also be + gotten by calling :c:func:`PySequence_Size` on *o*, but + :c:func:`PySequence_Fast_GET_SIZE` is faster because it can assume *o* is a list + or tuple. .. c:function:: PyObject* PySequence_Fast_GET_ITEM(PyObject *o, Py_ssize_t i) @@ -155,12 +167,3 @@ Sequence Protocol :c:func:`PySequence_GetItem` but without checking that :c:func:`PySequence_Check` on *o* is true and without adjustment for negative indices. - - -.. c:function:: Py_ssize_t PySequence_Fast_GET_SIZE(PyObject *o) - - Returns the length of *o*, assuming that *o* was returned by - :c:func:`PySequence_Fast` and that *o* is not *NULL*. The size can also be - gotten by calling :c:func:`PySequence_Size` on *o*, but - :c:func:`PySequence_Fast_GET_SIZE` is faster because it can assume *o* is a list - or tuple. diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst index 3bdf45ad9b61..6cbcc273c1f1 100644 --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -1167,21 +1167,24 @@ Mapping Object Structures .. c:member:: lenfunc PyMappingMethods.mp_length - This function is used by :c:func:`PyMapping_Length` and + This function is used by :c:func:`PyMapping_Size` and :c:func:`PyObject_Size`, and has the same signature. This slot may be set to *NULL* if the object has no defined length. .. c:member:: binaryfunc PyMappingMethods.mp_subscript - This function is used by :c:func:`PyObject_GetItem` and has the same - signature. This slot must be filled for the :c:func:`PyMapping_Check` - function to return ``1``, it can be *NULL* otherwise. + This function is used by :c:func:`PyObject_GetItem` and + :c:func:`PySequence_GetSlice`, and has the same signature as + :c:func:`!PyObject_GetItem`. This slot must be filled for the + :c:func:`PyMapping_Check` function to return ``1``, it can be *NULL* + otherwise. .. c:member:: objobjargproc PyMappingMethods.mp_ass_subscript - This function is used by :c:func:`PyObject_SetItem` and - :c:func:`PyObject_DelItem`. It has the same signature as - :c:func:`PyObject_SetItem`, but *v* can also be set to *NULL* to delete + This function is used by :c:func:`PyObject_SetItem`, + :c:func:`PyObject_DelItem`, :c:func:`PyObject_SetSlice` and + :c:func:`PyObject_DelSlice`. It has the same signature as + :c:func:`!PyObject_SetItem`, but *v* can also be set to *NULL* to delete an item. If this slot is *NULL*, the object does not support item assignment and deletion. @@ -1201,26 +1204,29 @@ Sequence Object Structures .. c:member:: lenfunc PySequenceMethods.sq_length - This function is used by :c:func:`PySequence_Size` and :c:func:`PyObject_Size`, - and has the same signature. + This function is used by :c:func:`PySequence_Size` and + :c:func:`PyObject_Size`, and has the same signature. It is also used for + handling negative indices via the :c:member:`~PySequenceMethods.sq_item` + and the :c:member:`~PySequenceMethods.sq_ass_item` slots. .. c:member:: binaryfunc PySequenceMethods.sq_concat This function is used by :c:func:`PySequence_Concat` and has the same signature. It is also used by the ``+`` operator, after trying the numeric - addition via the :c:member:`~PyTypeObject.tp_as_number.nb_add` slot. + addition via the :c:member:`~PyNumberMethods.nb_add` slot. .. c:member:: ssizeargfunc PySequenceMethods.sq_repeat This function is used by :c:func:`PySequence_Repeat` and has the same signature. It is also used by the ``*`` operator, after trying numeric - multiplication via the :c:member:`~PyTypeObject.tp_as_number.nb_multiply` - slot. + multiplication via the :c:member:`~PyNumberMethods.nb_multiply` slot. .. c:member:: ssizeargfunc PySequenceMethods.sq_item This function is used by :c:func:`PySequence_GetItem` and has the same - signature. This slot must be filled for the :c:func:`PySequence_Check` + signature. It is also used by :c:func:`PyObject_GetItem`, after trying + the subscription via the :c:member:`~PyMappingMethods.mp_subscript` slot. + This slot must be filled for the :c:func:`PySequence_Check` function to return ``1``, it can be *NULL* otherwise. Negative indexes are handled as follows: if the :attr:`sq_length` slot is @@ -1231,28 +1237,36 @@ Sequence Object Structures .. c:member:: ssizeobjargproc PySequenceMethods.sq_ass_item This function is used by :c:func:`PySequence_SetItem` and has the same - signature. This slot may be left to *NULL* if the object does not support + signature. It is also used by :c:func:`PyObject_SetItem` and + :c:func:`PyObject_DelItem`, after trying the item assignment and deletion + via the :c:member:`~PyMappingMethods.mp_ass_subscript` slot. + This slot may be left to *NULL* if the object does not support item assignment and deletion. .. c:member:: objobjproc PySequenceMethods.sq_contains This function may be used by :c:func:`PySequence_Contains` and has the same signature. This slot may be left to *NULL*, in this case - :c:func:`PySequence_Contains` simply traverses the sequence until it finds a - match. + :c:func:`!PySequence_Contains` simply traverses the sequence until it + finds a match. .. c:member:: binaryfunc PySequenceMethods.sq_inplace_concat This function is used by :c:func:`PySequence_InPlaceConcat` and has the same - signature. It should modify its first operand, and return it. + signature. It should modify its first operand, and return it. This slot + may be left to *NULL*, in this case :c:func:`!PySequence_InPlaceConcat` + will fall back to :c:func:`PySequence_Concat`. It is also used by the + augmented assignment ``+=``, after trying numeric inplace addition + via the :c:member:`~PyNumberMethods.nb_inplace_add` slot. .. c:member:: ssizeargfunc PySequenceMethods.sq_inplace_repeat This function is used by :c:func:`PySequence_InPlaceRepeat` and has the same - signature. It should modify its first operand, and return it. - -.. XXX need to explain precedence between mapping and sequence -.. XXX explains when to implement the sq_inplace_* slots + signature. It should modify its first operand, and return it. This slot + may be left to *NULL*, in this case :c:func:`!PySequence_InPlaceRepeat` + will fall back to :c:func:`PySequence_Repeat`. It is also used by the + augmented assignment ``*=``, after trying numeric inplace multiplication + via the :c:member:`~PyNumberMethods.nb_inplace_multiply` slot. .. _buffer-structs: diff --git a/Include/abstract.h b/Include/abstract.h index 3133cd105353..4088f75ff3c7 100644 --- a/Include/abstract.h +++ b/Include/abstract.h @@ -442,13 +442,14 @@ PyAPI_FUNC(PyObject *) PyObject_GetItem(PyObject *o, PyObject *key); This is the equivalent of the Python statement: o[key]=v. */ PyAPI_FUNC(int) PyObject_SetItem(PyObject *o, PyObject *key, PyObject *v); -/* Remove the mapping for object, key, from the object 'o'. +/* Remove the mapping for the string 'key' from the object 'o'. Returns -1 on failure. This is equivalent to the Python statement: del o[key]. */ PyAPI_FUNC(int) PyObject_DelItemString(PyObject *o, const char *key); -/* Delete the mapping for key from object 'o'. Returns -1 on failure. +/* Delete the mapping for the object 'key' from the object 'o'. + Returns -1 on failure. This is the equivalent of the Python statement: del o[key]. */ PyAPI_FUNC(int) PyObject_DelItem(PyObject *o, PyObject *key); @@ -1005,8 +1006,7 @@ PyAPI_FUNC(PyObject *) PySequence_InPlaceRepeat(PyObject *o, Py_ssize_t count); PyAPI_FUNC(int) PyMapping_Check(PyObject *o); /* Returns the number of keys in mapping object 'o' on success, and -1 on - failure. For objects that do not provide sequence protocol, this is - equivalent to the Python expression: len(o). */ + failure. This is equivalent to the Python expression: len(o). */ PyAPI_FUNC(Py_ssize_t) PyMapping_Size(PyObject *o); /* For DLL compatibility */ @@ -1019,7 +1019,7 @@ PyAPI_FUNC(Py_ssize_t) PyMapping_Length(PyObject *o); int PyMapping_DelItemString(PyObject *o, const char *key); - Remove the mapping for object 'key' from the mapping 'o'. Returns -1 on + Remove the mapping for the string 'key' from the mapping 'o'. Returns -1 on failure. This is equivalent to the Python statement: del o[key]. */ @@ -1029,7 +1029,7 @@ PyAPI_FUNC(Py_ssize_t) PyMapping_Length(PyObject *o); int PyMapping_DelItem(PyObject *o, PyObject *key); - Remove the mapping for object 'key' from the mapping object 'o'. + Remove the mapping for the object 'key' from the mapping object 'o'. Returns -1 on failure. This is equivalent to the Python statement: del o[key]. */ @@ -1063,13 +1063,13 @@ PyAPI_FUNC(PyObject *) PyMapping_Values(PyObject *o); NULL. */ PyAPI_FUNC(PyObject *) PyMapping_Items(PyObject *o); -/* Return element of o corresponding to the object, key, or NULL on failure. +/* Return element of 'o' corresponding to the string 'key' or NULL on failure. This is the equivalent of the Python expression: o[key]. */ PyAPI_FUNC(PyObject *) PyMapping_GetItemString(PyObject *o, const char *key); -/* Map the object 'key' to the value 'v' in the mapping 'o'. +/* Map the string 'key' to the value 'v' in the mapping 'o'. Returns -1 on failure. This is the equivalent of the Python statement: o[key]=v. */ From webhook-mailer at python.org Tue May 22 04:07:31 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 22 May 2018 08:07:31 -0000 Subject: [Python-checkins] Fix lambda parameters being refered as arguments (GH-7037) Message-ID: <mailman.3.1526976452.18020.python-checkins@python.org> https://github.com/python/cpython/commit/d9055f8176deeba43506f080e31e9503f35fc3d2 commit: d9055f8176deeba43506f080e31e9503f35fc3d2 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-22T01:07:28-07:00 summary: Fix lambda parameters being refered as arguments (GH-7037) (cherry picked from commit 268cc7c3f8f58075b42ff0cd6b6c6c5d76044895) Co-authored-by: Andr?s Delfino <adelfino at gmail.com> files: M Doc/glossary.rst M Doc/reference/expressions.rst diff --git a/Doc/glossary.rst b/Doc/glossary.rst index 4b1722f5c036..66964692ccba 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -603,7 +603,7 @@ Glossary lambda An anonymous inline function consisting of a single :term:`expression` which is evaluated when the function is called. The syntax to create - a lambda function is ``lambda [arguments]: expression`` + a lambda function is ``lambda [parameters]: expression`` LBYL Look before you leap. This coding style explicitly tests for diff --git a/Doc/reference/expressions.rst b/Doc/reference/expressions.rst index 7fe989b90524..6b2d6a9e0a85 100644 --- a/Doc/reference/expressions.rst +++ b/Doc/reference/expressions.rst @@ -1613,12 +1613,12 @@ Lambdas lambda_expr_nocond: "lambda" [`parameter_list`]: `expression_nocond` Lambda expressions (sometimes called lambda forms) are used to create anonymous -functions. The expression ``lambda arguments: expression`` yields a function +functions. The expression ``lambda parameters: expression`` yields a function object. The unnamed object behaves like a function object defined with: .. code-block:: none - def <lambda>(arguments): + def <lambda>(parameters): return expression See section :ref:`function` for the syntax of parameter lists. Note that From webhook-mailer at python.org Tue May 22 04:07:39 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 22 May 2018 08:07:39 -0000 Subject: [Python-checkins] Fix lambda parameters being refered as arguments (GH-7037) Message-ID: <mailman.4.1526976459.18020.python-checkins@python.org> https://github.com/python/cpython/commit/ab90ea2a9c818e7016359cb368f025dd274b27b9 commit: ab90ea2a9c818e7016359cb368f025dd274b27b9 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-22T01:07:35-07:00 summary: Fix lambda parameters being refered as arguments (GH-7037) (cherry picked from commit 268cc7c3f8f58075b42ff0cd6b6c6c5d76044895) Co-authored-by: Andr?s Delfino <adelfino at gmail.com> files: M Doc/glossary.rst M Doc/reference/expressions.rst diff --git a/Doc/glossary.rst b/Doc/glossary.rst index 279233906091..5e25dbbdc06a 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -595,7 +595,7 @@ Glossary lambda An anonymous inline function consisting of a single :term:`expression` which is evaluated when the function is called. The syntax to create - a lambda function is ``lambda [arguments]: expression`` + a lambda function is ``lambda [parameters]: expression`` LBYL Look before you leap. This coding style explicitly tests for diff --git a/Doc/reference/expressions.rst b/Doc/reference/expressions.rst index ff890a815b5b..57ae639ab6e0 100644 --- a/Doc/reference/expressions.rst +++ b/Doc/reference/expressions.rst @@ -1571,12 +1571,12 @@ Lambdas lambda_expr_nocond: "lambda" [`parameter_list`]: `expression_nocond` Lambda expressions (sometimes called lambda forms) are used to create anonymous -functions. The expression ``lambda arguments: expression`` yields a function +functions. The expression ``lambda parameters: expression`` yields a function object. The unnamed object behaves like a function object defined with: .. code-block:: none - def <lambda>(arguments): + def <lambda>(parameters): return expression See section :ref:`function` for the syntax of parameter lists. Note that From webhook-mailer at python.org Tue May 22 04:21:35 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Tue, 22 May 2018 08:21:35 -0000 Subject: [Python-checkins] Add PyThread_tss_* to Doc/data/refcounts.dat. (GH-7038) Message-ID: <mailman.5.1526977296.18020.python-checkins@python.org> https://github.com/python/cpython/commit/55bfe690d570958a66ee6c7b15fc8daca0f9c2d3 commit: 55bfe690d570958a66ee6c7b15fc8daca0f9c2d3 branch: master author: Masayuki Yamamoto <ma3yuki.8mamo10 at gmail.com> committer: Serhiy Storchaka <storchaka at gmail.com> date: 2018-05-22T11:21:25+03:00 summary: Add PyThread_tss_* to Doc/data/refcounts.dat. (GH-7038) Thread Specific Storage (TSS) API is a public C API (new in 3.7). files: M Doc/data/refcounts.dat diff --git a/Doc/data/refcounts.dat b/Doc/data/refcounts.dat index 6dc86fc5e54c..f403c16547c4 100644 --- a/Doc/data/refcounts.dat +++ b/Doc/data/refcounts.dat @@ -1383,6 +1383,27 @@ PyThreadState_New:PyInterpreterState*:interp:: PyThreadState_Swap:PyThreadState*::: PyThreadState_Swap:PyThreadState*:tstate:: +PyThread_tss_alloc:Py_tss_t*::: + +PyThread_tss_create:int::: +PyThread_tss_create:Py_tss_t*:key:: + +PyThread_tss_delete:void::: +PyThread_tss_delete:Py_tss_t*:key:: + +PyThread_tss_free:void::: +PyThread_tss_free:Py_tss_t*:key:: + +PyThread_tss_get:void*::: +PyThread_tss_get:Py_tss_t*:key:: + +PyThread_tss_is_created:int::: +PyThread_tss_is_created:Py_tss_t*:key:: + +PyThread_tss_set:int::: +PyThread_tss_set:Py_tss_t*:key:: +PyThread_tss_set:void*:value:: + PyTime_FromTime:PyObject*::+1: PyTime_FromTime:int:hour:: PyTime_FromTime:int:minute:: From webhook-mailer at python.org Tue May 22 04:23:23 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 22 May 2018 08:23:23 -0000 Subject: [Python-checkins] bpo-5945: Improve mappings and sequences C API docs. (GH-7029) Message-ID: <mailman.6.1526977405.18020.python-checkins@python.org> https://github.com/python/cpython/commit/e1a78cacf65f007b1000966ce3aac6ac2eaa5cfc commit: e1a78cacf65f007b1000966ce3aac6ac2eaa5cfc branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-22T01:23:20-07:00 summary: bpo-5945: Improve mappings and sequences C API docs. (GH-7029) (cherry picked from commit f5b1183610d5888db3bbd639b1a0c945dbd8f8dd) Co-authored-by: Serhiy Storchaka <storchaka at gmail.com> files: M Doc/c-api/mapping.rst M Doc/c-api/object.rst M Doc/c-api/sequence.rst M Doc/c-api/typeobj.rst M Include/abstract.h diff --git a/Doc/c-api/mapping.rst b/Doc/c-api/mapping.rst index 308a9761f87e..b8eaadbd702c 100644 --- a/Doc/c-api/mapping.rst +++ b/Doc/c-api/mapping.rst @@ -5,11 +5,17 @@ Mapping Protocol ================ +See also :c:func:`PyObject_GetItem`, :c:func:`PyObject_SetItem` and +:c:func:`PyObject_DelItem`. + .. c:function:: int PyMapping_Check(PyObject *o) - Return ``1`` if the object provides mapping protocol, and ``0`` otherwise. This - function always succeeds. + Return ``1`` if the object provides mapping protocol or supports slicing, + and ``0`` otherwise. Note that it returns ``1`` for Python classes with + a :meth:`__getitem__` method since in general case it is impossible to + determine what the type of keys it supports. This function always + succeeds. .. c:function:: Py_ssize_t PyMapping_Size(PyObject *o) @@ -17,35 +23,49 @@ Mapping Protocol .. index:: builtin: len - Returns the number of keys in object *o* on success, and ``-1`` on failure. For - objects that do not provide mapping protocol, this is equivalent to the Python - expression ``len(o)``. + Returns the number of keys in object *o* on success, and ``-1`` on failure. + This is equivalent to the Python expression ``len(o)``. -.. c:function:: int PyMapping_DelItemString(PyObject *o, const char *key) +.. c:function:: PyObject* PyMapping_GetItemString(PyObject *o, const char *key) + + Return element of *o* corresponding to the string *key* or *NULL* on failure. + This is the equivalent of the Python expression ``o[key]``. + See also :c:func:`PyObject_GetItem`. + - Remove the mapping for object *key* from the object *o*. Return ``-1`` on - failure. This is equivalent to the Python statement ``del o[key]``. +.. c:function:: int PyMapping_SetItemString(PyObject *o, const char *key, PyObject *v) + + Map the string *key* to the value *v* in object *o*. Returns ``-1`` on + failure. This is the equivalent of the Python statement ``o[key] = v``. + See also :c:func:`PyObject_SetItem`. .. c:function:: int PyMapping_DelItem(PyObject *o, PyObject *key) - Remove the mapping for object *key* from the object *o*. Return ``-1`` on - failure. This is equivalent to the Python statement ``del o[key]``. + Remove the mapping for the object *key* from the object *o*. Return ``-1`` + on failure. This is equivalent to the Python statement ``del o[key]``. + This is an alias of :c:func:`PyObject_DelItem`. -.. c:function:: int PyMapping_HasKeyString(PyObject *o, const char *key) +.. c:function:: int PyMapping_DelItemString(PyObject *o, const char *key) - On success, return ``1`` if the mapping object has the key *key* and ``0`` - otherwise. This is equivalent to the Python expression ``key in o``. - This function always succeeds. + Remove the mapping for the string *key* from the object *o*. Return ``-1`` + on failure. This is equivalent to the Python statement ``del o[key]``. .. c:function:: int PyMapping_HasKey(PyObject *o, PyObject *key) - Return ``1`` if the mapping object has the key *key* and ``0`` otherwise. This - is equivalent to the Python expression ``key in o``. This function always - succeeds. + Return ``1`` if the mapping object has the key *key* and ``0`` otherwise. + This is equivalent to the Python expression ``key in o``. + This function always succeeds. + + +.. c:function:: int PyMapping_HasKeyString(PyObject *o, const char *key) + + Return ``1`` if the mapping object has the key *key* and ``0`` otherwise. + This is equivalent to the Python expression ``key in o``. + This function always succeeds. .. c:function:: PyObject* PyMapping_Keys(PyObject *o) @@ -73,15 +93,3 @@ Mapping Protocol .. versionchanged:: 3.7 Previously, the function returned a list or a tuple. - - -.. c:function:: PyObject* PyMapping_GetItemString(PyObject *o, const char *key) - - Return element of *o* corresponding to the object *key* or *NULL* on failure. - This is the equivalent of the Python expression ``o[key]``. - - -.. c:function:: int PyMapping_SetItemString(PyObject *o, const char *key, PyObject *v) - - Map the object *key* to the value *v* in object *o*. Returns ``-1`` on failure. - This is the equivalent of the Python statement ``o[key] = v``. diff --git a/Doc/c-api/object.rst b/Doc/c-api/object.rst index 754dedc1c603..f0b2005f2d12 100644 --- a/Doc/c-api/object.rst +++ b/Doc/c-api/object.rst @@ -379,8 +379,8 @@ Object Protocol parameters must be non-*NULL*. -.. c:function:: Py_ssize_t PyObject_Length(PyObject *o) - Py_ssize_t PyObject_Size(PyObject *o) +.. c:function:: Py_ssize_t PyObject_Size(PyObject *o) + Py_ssize_t PyObject_Length(PyObject *o) .. index:: builtin: len @@ -414,8 +414,8 @@ Object Protocol .. c:function:: int PyObject_DelItem(PyObject *o, PyObject *key) - Delete the mapping for *key* from *o*. Returns ``-1`` on failure. This is the - equivalent of the Python statement ``del o[key]``. + Remove the mapping for the object *key* from the object *o*. Return ``-1`` + on failure. This is equivalent to the Python statement ``del o[key]``. .. c:function:: PyObject* PyObject_Dir(PyObject *o) diff --git a/Doc/c-api/sequence.rst b/Doc/c-api/sequence.rst index 81f8557ea6e6..6d22f35e22b1 100644 --- a/Doc/c-api/sequence.rst +++ b/Doc/c-api/sequence.rst @@ -9,7 +9,10 @@ Sequence Protocol .. c:function:: int PySequence_Check(PyObject *o) Return ``1`` if the object provides sequence protocol, and ``0`` otherwise. - This function always succeeds. + Note that it returns ``1`` for Python classes with a :meth:`__getitem__` + method unless they are :class:`dict` subclasses since in general case it + is impossible to determine what the type of keys it supports. This + function always succeeds. .. c:function:: Py_ssize_t PySequence_Size(PyObject *o) @@ -119,18 +122,27 @@ Sequence Protocol .. index:: builtin: tuple - Return a tuple object with the same contents as the arbitrary sequence *o* or - *NULL* on failure. If *o* is a tuple, a new reference will be returned, + Return a tuple object with the same contents as the sequence or iterable *o*, + or *NULL* on failure. If *o* is a tuple, a new reference will be returned, otherwise a tuple will be constructed with the appropriate contents. This is equivalent to the Python expression ``tuple(o)``. .. c:function:: PyObject* PySequence_Fast(PyObject *o, const char *m) - Return the sequence *o* as a list, unless it is already a tuple or list, in + Return the sequence or iterable *o* as a list, unless it is already a tuple or list, in which case *o* is returned. Use :c:func:`PySequence_Fast_GET_ITEM` to access the members of the result. Returns *NULL* on failure. If the object is not - a sequence, raises :exc:`TypeError` with *m* as the message text. + a sequence or iterable, raises :exc:`TypeError` with *m* as the message text. + + +.. c:function:: Py_ssize_t PySequence_Fast_GET_SIZE(PyObject *o) + + Returns the length of *o*, assuming that *o* was returned by + :c:func:`PySequence_Fast` and that *o* is not *NULL*. The size can also be + gotten by calling :c:func:`PySequence_Size` on *o*, but + :c:func:`PySequence_Fast_GET_SIZE` is faster because it can assume *o* is a list + or tuple. .. c:function:: PyObject* PySequence_Fast_GET_ITEM(PyObject *o, Py_ssize_t i) @@ -155,12 +167,3 @@ Sequence Protocol :c:func:`PySequence_GetItem` but without checking that :c:func:`PySequence_Check` on *o* is true and without adjustment for negative indices. - - -.. c:function:: Py_ssize_t PySequence_Fast_GET_SIZE(PyObject *o) - - Returns the length of *o*, assuming that *o* was returned by - :c:func:`PySequence_Fast` and that *o* is not *NULL*. The size can also be - gotten by calling :c:func:`PySequence_Size` on *o*, but - :c:func:`PySequence_Fast_GET_SIZE` is faster because it can assume *o* is a list - or tuple. diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst index 3bdf45ad9b61..6cbcc273c1f1 100644 --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -1167,21 +1167,24 @@ Mapping Object Structures .. c:member:: lenfunc PyMappingMethods.mp_length - This function is used by :c:func:`PyMapping_Length` and + This function is used by :c:func:`PyMapping_Size` and :c:func:`PyObject_Size`, and has the same signature. This slot may be set to *NULL* if the object has no defined length. .. c:member:: binaryfunc PyMappingMethods.mp_subscript - This function is used by :c:func:`PyObject_GetItem` and has the same - signature. This slot must be filled for the :c:func:`PyMapping_Check` - function to return ``1``, it can be *NULL* otherwise. + This function is used by :c:func:`PyObject_GetItem` and + :c:func:`PySequence_GetSlice`, and has the same signature as + :c:func:`!PyObject_GetItem`. This slot must be filled for the + :c:func:`PyMapping_Check` function to return ``1``, it can be *NULL* + otherwise. .. c:member:: objobjargproc PyMappingMethods.mp_ass_subscript - This function is used by :c:func:`PyObject_SetItem` and - :c:func:`PyObject_DelItem`. It has the same signature as - :c:func:`PyObject_SetItem`, but *v* can also be set to *NULL* to delete + This function is used by :c:func:`PyObject_SetItem`, + :c:func:`PyObject_DelItem`, :c:func:`PyObject_SetSlice` and + :c:func:`PyObject_DelSlice`. It has the same signature as + :c:func:`!PyObject_SetItem`, but *v* can also be set to *NULL* to delete an item. If this slot is *NULL*, the object does not support item assignment and deletion. @@ -1201,26 +1204,29 @@ Sequence Object Structures .. c:member:: lenfunc PySequenceMethods.sq_length - This function is used by :c:func:`PySequence_Size` and :c:func:`PyObject_Size`, - and has the same signature. + This function is used by :c:func:`PySequence_Size` and + :c:func:`PyObject_Size`, and has the same signature. It is also used for + handling negative indices via the :c:member:`~PySequenceMethods.sq_item` + and the :c:member:`~PySequenceMethods.sq_ass_item` slots. .. c:member:: binaryfunc PySequenceMethods.sq_concat This function is used by :c:func:`PySequence_Concat` and has the same signature. It is also used by the ``+`` operator, after trying the numeric - addition via the :c:member:`~PyTypeObject.tp_as_number.nb_add` slot. + addition via the :c:member:`~PyNumberMethods.nb_add` slot. .. c:member:: ssizeargfunc PySequenceMethods.sq_repeat This function is used by :c:func:`PySequence_Repeat` and has the same signature. It is also used by the ``*`` operator, after trying numeric - multiplication via the :c:member:`~PyTypeObject.tp_as_number.nb_multiply` - slot. + multiplication via the :c:member:`~PyNumberMethods.nb_multiply` slot. .. c:member:: ssizeargfunc PySequenceMethods.sq_item This function is used by :c:func:`PySequence_GetItem` and has the same - signature. This slot must be filled for the :c:func:`PySequence_Check` + signature. It is also used by :c:func:`PyObject_GetItem`, after trying + the subscription via the :c:member:`~PyMappingMethods.mp_subscript` slot. + This slot must be filled for the :c:func:`PySequence_Check` function to return ``1``, it can be *NULL* otherwise. Negative indexes are handled as follows: if the :attr:`sq_length` slot is @@ -1231,28 +1237,36 @@ Sequence Object Structures .. c:member:: ssizeobjargproc PySequenceMethods.sq_ass_item This function is used by :c:func:`PySequence_SetItem` and has the same - signature. This slot may be left to *NULL* if the object does not support + signature. It is also used by :c:func:`PyObject_SetItem` and + :c:func:`PyObject_DelItem`, after trying the item assignment and deletion + via the :c:member:`~PyMappingMethods.mp_ass_subscript` slot. + This slot may be left to *NULL* if the object does not support item assignment and deletion. .. c:member:: objobjproc PySequenceMethods.sq_contains This function may be used by :c:func:`PySequence_Contains` and has the same signature. This slot may be left to *NULL*, in this case - :c:func:`PySequence_Contains` simply traverses the sequence until it finds a - match. + :c:func:`!PySequence_Contains` simply traverses the sequence until it + finds a match. .. c:member:: binaryfunc PySequenceMethods.sq_inplace_concat This function is used by :c:func:`PySequence_InPlaceConcat` and has the same - signature. It should modify its first operand, and return it. + signature. It should modify its first operand, and return it. This slot + may be left to *NULL*, in this case :c:func:`!PySequence_InPlaceConcat` + will fall back to :c:func:`PySequence_Concat`. It is also used by the + augmented assignment ``+=``, after trying numeric inplace addition + via the :c:member:`~PyNumberMethods.nb_inplace_add` slot. .. c:member:: ssizeargfunc PySequenceMethods.sq_inplace_repeat This function is used by :c:func:`PySequence_InPlaceRepeat` and has the same - signature. It should modify its first operand, and return it. - -.. XXX need to explain precedence between mapping and sequence -.. XXX explains when to implement the sq_inplace_* slots + signature. It should modify its first operand, and return it. This slot + may be left to *NULL*, in this case :c:func:`!PySequence_InPlaceRepeat` + will fall back to :c:func:`PySequence_Repeat`. It is also used by the + augmented assignment ``*=``, after trying numeric inplace multiplication + via the :c:member:`~PyNumberMethods.nb_inplace_multiply` slot. .. _buffer-structs: diff --git a/Include/abstract.h b/Include/abstract.h index 3133cd105353..4088f75ff3c7 100644 --- a/Include/abstract.h +++ b/Include/abstract.h @@ -442,13 +442,14 @@ PyAPI_FUNC(PyObject *) PyObject_GetItem(PyObject *o, PyObject *key); This is the equivalent of the Python statement: o[key]=v. */ PyAPI_FUNC(int) PyObject_SetItem(PyObject *o, PyObject *key, PyObject *v); -/* Remove the mapping for object, key, from the object 'o'. +/* Remove the mapping for the string 'key' from the object 'o'. Returns -1 on failure. This is equivalent to the Python statement: del o[key]. */ PyAPI_FUNC(int) PyObject_DelItemString(PyObject *o, const char *key); -/* Delete the mapping for key from object 'o'. Returns -1 on failure. +/* Delete the mapping for the object 'key' from the object 'o'. + Returns -1 on failure. This is the equivalent of the Python statement: del o[key]. */ PyAPI_FUNC(int) PyObject_DelItem(PyObject *o, PyObject *key); @@ -1005,8 +1006,7 @@ PyAPI_FUNC(PyObject *) PySequence_InPlaceRepeat(PyObject *o, Py_ssize_t count); PyAPI_FUNC(int) PyMapping_Check(PyObject *o); /* Returns the number of keys in mapping object 'o' on success, and -1 on - failure. For objects that do not provide sequence protocol, this is - equivalent to the Python expression: len(o). */ + failure. This is equivalent to the Python expression: len(o). */ PyAPI_FUNC(Py_ssize_t) PyMapping_Size(PyObject *o); /* For DLL compatibility */ @@ -1019,7 +1019,7 @@ PyAPI_FUNC(Py_ssize_t) PyMapping_Length(PyObject *o); int PyMapping_DelItemString(PyObject *o, const char *key); - Remove the mapping for object 'key' from the mapping 'o'. Returns -1 on + Remove the mapping for the string 'key' from the mapping 'o'. Returns -1 on failure. This is equivalent to the Python statement: del o[key]. */ @@ -1029,7 +1029,7 @@ PyAPI_FUNC(Py_ssize_t) PyMapping_Length(PyObject *o); int PyMapping_DelItem(PyObject *o, PyObject *key); - Remove the mapping for object 'key' from the mapping object 'o'. + Remove the mapping for the object 'key' from the mapping object 'o'. Returns -1 on failure. This is equivalent to the Python statement: del o[key]. */ @@ -1063,13 +1063,13 @@ PyAPI_FUNC(PyObject *) PyMapping_Values(PyObject *o); NULL. */ PyAPI_FUNC(PyObject *) PyMapping_Items(PyObject *o); -/* Return element of o corresponding to the object, key, or NULL on failure. +/* Return element of 'o' corresponding to the string 'key' or NULL on failure. This is the equivalent of the Python expression: o[key]. */ PyAPI_FUNC(PyObject *) PyMapping_GetItemString(PyObject *o, const char *key); -/* Map the object 'key' to the value 'v' in the mapping 'o'. +/* Map the string 'key' to the value 'v' in the mapping 'o'. Returns -1 on failure. This is the equivalent of the Python statement: o[key]=v. */ From webhook-mailer at python.org Tue May 22 04:59:43 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 22 May 2018 08:59:43 -0000 Subject: [Python-checkins] Add PyThread_tss_* to Doc/data/refcounts.dat. (GH-7038) Message-ID: <mailman.7.1526979585.18020.python-checkins@python.org> https://github.com/python/cpython/commit/3718f92e1652ba4494b4fa8c8a8c4a5bdc1a8e90 commit: 3718f92e1652ba4494b4fa8c8a8c4a5bdc1a8e90 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-22T01:59:33-07:00 summary: Add PyThread_tss_* to Doc/data/refcounts.dat. (GH-7038) Thread Specific Storage (TSS) API is a public C API (new in 3.7). (cherry picked from commit 55bfe690d570958a66ee6c7b15fc8daca0f9c2d3) Co-authored-by: Masayuki Yamamoto <ma3yuki.8mamo10 at gmail.com> files: M Doc/data/refcounts.dat diff --git a/Doc/data/refcounts.dat b/Doc/data/refcounts.dat index 6dc86fc5e54c..f403c16547c4 100644 --- a/Doc/data/refcounts.dat +++ b/Doc/data/refcounts.dat @@ -1383,6 +1383,27 @@ PyThreadState_New:PyInterpreterState*:interp:: PyThreadState_Swap:PyThreadState*::: PyThreadState_Swap:PyThreadState*:tstate:: +PyThread_tss_alloc:Py_tss_t*::: + +PyThread_tss_create:int::: +PyThread_tss_create:Py_tss_t*:key:: + +PyThread_tss_delete:void::: +PyThread_tss_delete:Py_tss_t*:key:: + +PyThread_tss_free:void::: +PyThread_tss_free:Py_tss_t*:key:: + +PyThread_tss_get:void*::: +PyThread_tss_get:Py_tss_t*:key:: + +PyThread_tss_is_created:int::: +PyThread_tss_is_created:Py_tss_t*:key:: + +PyThread_tss_set:int::: +PyThread_tss_set:Py_tss_t*:key:: +PyThread_tss_set:void*:value:: + PyTime_FromTime:PyObject*::+1: PyTime_FromTime:int:hour:: PyTime_FromTime:int:minute:: From solipsis at pitrou.net Tue May 22 05:16:28 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Tue, 22 May 2018 09:16:28 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=5 Message-ID: <20180522091628.1.4120E5C8098F0A89@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_collections leaked [7, -7, 1] memory blocks, sum=1 test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_fork leaked [-2, 2, 0] memory blocks, sum=0 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogynEqQX', '--timeout', '7200'] From webhook-mailer at python.org Tue May 22 07:53:11 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Tue, 22 May 2018 11:53:11 -0000 Subject: [Python-checkins] [3.7] Fix line breaks added after hyphens by blurb. (GH-7002) (GH-7050) Message-ID: <mailman.8.1526989992.18020.python-checkins@python.org> https://github.com/python/cpython/commit/fecad4abe257651003ad89a59012032382ecd223 commit: fecad4abe257651003ad89a59012032382ecd223 branch: 3.7 author: Serhiy Storchaka <storchaka at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-22T14:53:08+03:00 summary: [3.7] Fix line breaks added after hyphens by blurb. (GH-7002) (GH-7050) Also remove bullet asterisks from IDLE entries. (cherry picked from commit aef639f62677f8a342af24e9c19f0503b0d1e36e) files: M Misc/NEWS.d/3.5.0a1.rst M Misc/NEWS.d/3.5.0a3.rst M Misc/NEWS.d/3.5.0b3.rst M Misc/NEWS.d/3.5.0b4.rst M Misc/NEWS.d/3.5.1rc1.rst M Misc/NEWS.d/3.5.2rc1.rst M Misc/NEWS.d/3.5.3rc1.rst M Misc/NEWS.d/3.6.0a1.rst M Misc/NEWS.d/3.6.0b1.rst M Misc/NEWS.d/3.6.0b4.rst M Misc/NEWS.d/3.7.0a1.rst M Misc/NEWS.d/3.7.0a3.rst M Misc/NEWS.d/3.7.0b1.rst M Misc/NEWS.d/3.7.0b2.rst M Misc/NEWS.d/3.7.0b3.rst diff --git a/Misc/NEWS.d/3.5.0a1.rst b/Misc/NEWS.d/3.5.0a1.rst index e83a8080cf8d..0104a31629eb 100644 --- a/Misc/NEWS.d/3.5.0a1.rst +++ b/Misc/NEWS.d/3.5.0a1.rst @@ -2706,8 +2706,8 @@ Added support for the "xztar" format in the shutil module. .. nonce: ZLsRil .. section: Library -Don't force 3rd party C extensions to be built with -Werror=declaration- -after-statement. +Don't force 3rd party C extensions to be built with +``-Werror=declaration-after-statement``. .. @@ -4464,8 +4464,8 @@ Improve repr of inspect.Signature and inspect.Parameter. .. nonce: DFMEgN .. section: Library -Fix inspect.getcallargs() to raise correct TypeError for missing keyword- -only arguments. Patch by Jeremiah Lowin. +Fix inspect.getcallargs() to raise correct TypeError for missing +keyword-only arguments. Patch by Jeremiah Lowin. .. @@ -5059,8 +5059,8 @@ Anticipated fixes to support OS X versions > 10.9. .. nonce: KAl7aO .. section: Build -Prevent possible segfaults and other random failures of python --generate- -posix-vars in pybuilddir.txt build target. +Prevent possible segfaults and other random failures of python +``--generate-posix-vars`` in pybuilddir.txt build target. .. diff --git a/Misc/NEWS.d/3.5.0a3.rst b/Misc/NEWS.d/3.5.0a3.rst index a096809951da..c71afe63ab6d 100644 --- a/Misc/NEWS.d/3.5.0a3.rst +++ b/Misc/NEWS.d/3.5.0a3.rst @@ -62,8 +62,8 @@ Fix the default __sizeof__ implementation for variable-sized objects. .. nonce: b5M04V .. section: Library -The groupindex attribute of regular expression pattern object now is non- -modifiable mapping. +The groupindex attribute of regular expression pattern object now is +non-modifiable mapping. .. diff --git a/Misc/NEWS.d/3.5.0b3.rst b/Misc/NEWS.d/3.5.0b3.rst index 4081dd54876f..00f2de3863f5 100644 --- a/Misc/NEWS.d/3.5.0b3.rst +++ b/Misc/NEWS.d/3.5.0b3.rst @@ -110,8 +110,8 @@ by Martin Panter. .. nonce: aAbWbQ .. section: Library -Restore semantic round-trip correctness in tokenize/untokenize for tab- -indented blocks. +Restore semantic round-trip correctness in tokenize/untokenize for +tab-indented blocks. .. diff --git a/Misc/NEWS.d/3.5.0b4.rst b/Misc/NEWS.d/3.5.0b4.rst index 436981c6fe92..8ab257ae1c5a 100644 --- a/Misc/NEWS.d/3.5.0b4.rst +++ b/Misc/NEWS.d/3.5.0b4.rst @@ -224,8 +224,8 @@ segment. .. nonce: hwXwCH .. section: Library -SMTP.auth() and SMTP.login() now support RFC 4954's optional initial- -response argument to the SMTP AUTH command. +SMTP.auth() and SMTP.login() now support RFC 4954's optional +initial-response argument to the SMTP AUTH command. .. diff --git a/Misc/NEWS.d/3.5.1rc1.rst b/Misc/NEWS.d/3.5.1rc1.rst index 87672566ccae..1f8850fc678a 100644 --- a/Misc/NEWS.d/3.5.1rc1.rst +++ b/Misc/NEWS.d/3.5.1rc1.rst @@ -159,8 +159,8 @@ twice. On Solaris 11.3 or newer, os.urandom() now uses the getrandom() function instead of the getentropy() function. The getentropy() function is blocking -to generate very good quality entropy, os.urandom() doesn't need such high- -quality entropy. +to generate very good quality entropy, os.urandom() doesn't need such +high-quality entropy. .. @@ -1083,10 +1083,10 @@ them a 'sheet'. Patch by Mark Roseman. .. nonce: -j_BV7 .. section: IDLE -Enhance the initial html viewer now used for Idle Help. * Properly indent -fixed-pitch text (patch by Mark Roseman). * Give code snippet a very Sphinx- -like light blueish-gray background. * Re-use initial width and height set by -users for shell and editor. * When the Table of Contents (TOC) menu is used, +Enhance the initial html viewer now used for Idle Help. Properly indent +fixed-pitch text (patch by Mark Roseman). Give code snippet a very +Sphinx-like light blueish-gray background. Re-use initial width and height set by +users for shell and editor. When the Table of Contents (TOC) menu is used, put the section header at the top of the screen. .. diff --git a/Misc/NEWS.d/3.5.2rc1.rst b/Misc/NEWS.d/3.5.2rc1.rst index caed84a06f78..920c95169e28 100644 --- a/Misc/NEWS.d/3.5.2rc1.rst +++ b/Misc/NEWS.d/3.5.2rc1.rst @@ -568,9 +568,9 @@ string. Original fix by J?n Janech. .. section: Library The "urllib.request" module now percent-encodes non-ASCII bytes found in -redirect target URLs. Some servers send Location header fields with non- -ASCII bytes, but "http.client" requires the request target to be ASCII- -encodable, otherwise a UnicodeEncodeError is raised. Based on patch by +redirect target URLs. Some servers send Location header fields with +non-ASCII bytes, but "http.client" requires the request target to be +ASCII-encodable, otherwise a UnicodeEncodeError is raised. Based on patch by Christian Heimes. .. @@ -1952,8 +1952,8 @@ Fix linking extension modules for cross builds. Patch by Xavier de Gaye. .. nonce: HDjM4s .. section: Build -Disable the rules for running _freeze_importlib and pgen when cross- -compiling. The output of these programs is normally saved with the source +Disable the rules for running _freeze_importlib and pgen when +cross-compiling. The output of these programs is normally saved with the source code anyway, and is still regenerated when doing a native build. Patch by Xavier de Gaye. diff --git a/Misc/NEWS.d/3.5.3rc1.rst b/Misc/NEWS.d/3.5.3rc1.rst index 5c6859c8c1ab..09ebc541a396 100644 --- a/Misc/NEWS.d/3.5.3rc1.rst +++ b/Misc/NEWS.d/3.5.3rc1.rst @@ -81,8 +81,8 @@ astral characters. Patch by Xiang Zhang. .. nonce: RYbEGH .. section: Core and Builtins -Extra slash no longer added to sys.path components in case of empty compile- -time PYTHONPATH components. +Extra slash no longer added to sys.path components in case of empty +compile-time PYTHONPATH components. .. @@ -349,8 +349,8 @@ Patch written by Xiang Zhang. .. section: Core and Builtins Standard __import__() no longer look up "__import__" in globals or builtins -for importing submodules or "from import". Fixed handling an error of non- -string package name. +for importing submodules or "from import". Fixed handling an error of +non-string package name. .. @@ -2070,9 +2070,9 @@ Update message in validate_ucrtbase.py .. section: Build Cause lack of llvm-profdata tool when using clang as required for PGO -linking to be a configure time error rather than make time when --with- -optimizations is enabled. Also improve our ability to find the llvm- -profdata tool on MacOS and some Linuxes. +linking to be a configure time error rather than make time when +``--with-optimizations`` is enabled. Also improve our ability to find the +llvm-profdata tool on MacOS and some Linuxes. .. diff --git a/Misc/NEWS.d/3.6.0a1.rst b/Misc/NEWS.d/3.6.0a1.rst index 02c92a96882a..b1081a9e4e3b 100644 --- a/Misc/NEWS.d/3.6.0a1.rst +++ b/Misc/NEWS.d/3.6.0a1.rst @@ -728,8 +728,8 @@ Fixed a number of bugs in UTF-7 decoding of misformed data. .. section: Core and Builtins The UTF-8 encoder is now up to 75 times as fast for error handlers: -``ignore``, ``replace``, ``surrogateescape``, ``surrogatepass``. Patch co- -written with Serhiy Storchaka. +``ignore``, ``replace``, ``surrogateescape``, ``surrogatepass``. Patch +co-written with Serhiy Storchaka. .. @@ -761,8 +761,8 @@ by Serhiy Storchaka. On Solaris 11.3 or newer, os.urandom() now uses the getrandom() function instead of the getentropy() function. The getentropy() function is blocking -to generate very good quality entropy, os.urandom() doesn't need such high- -quality entropy. +to generate very good quality entropy, os.urandom() doesn't need such +high-quality entropy. .. @@ -891,9 +891,9 @@ string. Original fix by J?n Janech. .. section: Library The "urllib.request" module now percent-encodes non-ASCII bytes found in -redirect target URLs. Some servers send Location header fields with non- -ASCII bytes, but "http.client" requires the request target to be ASCII- -encodable, otherwise a UnicodeEncodeError is raised. Based on patch by +redirect target URLs. Some servers send Location header fields with +non-ASCII bytes, but "http.client" requires the request target to be +ASCII-encodable, otherwise a UnicodeEncodeError is raised. Based on patch by Christian Heimes. .. @@ -3328,10 +3328,10 @@ them a 'sheet'. Patch by Mark Roseman. .. nonce: -j_BV7 .. section: IDLE -Enhance the initial html viewer now used for Idle Help. * Properly indent -fixed-pitch text (patch by Mark Roseman). * Give code snippet a very Sphinx- -like light blueish-gray background. * Re-use initial width and height set by -users for shell and editor. * When the Table of Contents (TOC) menu is used, +Enhance the initial html viewer now used for Idle Help. Properly indent +fixed-pitch text (patch by Mark Roseman). Give code snippet a very +Sphinx-like light blueish-gray background. Re-use initial width and height set by +users for shell and editor. When the Table of Contents (TOC) menu is used, put the section header at the top of the screen. .. @@ -3651,8 +3651,8 @@ particular on Android). Patch by Chi Hsuan Yen. .. nonce: HDjM4s .. section: Build -Disable the rules for running _freeze_importlib and pgen when cross- -compiling. The output of these programs is normally saved with the source +Disable the rules for running _freeze_importlib and pgen when +cross-compiling. The output of these programs is normally saved with the source code anyway, and is still regenerated when doing a native build. Patch by Xavier de Gaye. diff --git a/Misc/NEWS.d/3.6.0b1.rst b/Misc/NEWS.d/3.6.0b1.rst index 8e0197fcbcae..6ff8bbb99d2c 100644 --- a/Misc/NEWS.d/3.6.0b1.rst +++ b/Misc/NEWS.d/3.6.0b1.rst @@ -507,8 +507,8 @@ expression. .. nonce: TJ779X .. section: Library -xmlrpc now supports unmarshalling additional data types used by Apache XML- -RPC implementation for numerics and None. +xmlrpc now supports unmarshalling additional data types used by Apache +XML-RPC implementation for numerics and None. .. @@ -1416,9 +1416,9 @@ platforms. .. section: Build Cause lack of llvm-profdata tool when using clang as required for PGO -linking to be a configure time error rather than make time when --with- -optimizations is enabled. Also improve our ability to find the llvm- -profdata tool on MacOS and some Linuxes. +linking to be a configure time error rather than make time when +``--with-optimizations`` is enabled. Also improve our ability to find the +llvm-profdata tool on MacOS and some Linuxes. .. diff --git a/Misc/NEWS.d/3.6.0b4.rst b/Misc/NEWS.d/3.6.0b4.rst index 326da19dd26e..ab11cfd89bb4 100644 --- a/Misc/NEWS.d/3.6.0b4.rst +++ b/Misc/NEWS.d/3.6.0b4.rst @@ -54,8 +54,8 @@ astral characters. Patch by Xiang Zhang. .. nonce: RYbEGH .. section: Core and Builtins -Extra slash no longer added to sys.path components in case of empty compile- -time PYTHONPATH components. +Extra slash no longer added to sys.path components in case of empty +compile-time PYTHONPATH components. .. diff --git a/Misc/NEWS.d/3.7.0a1.rst b/Misc/NEWS.d/3.7.0a1.rst index 262bfabb3ec1..3962923a2d24 100644 --- a/Misc/NEWS.d/3.7.0a1.rst +++ b/Misc/NEWS.d/3.7.0a1.rst @@ -49,8 +49,8 @@ Upgrade expat copy from 2.2.0 to 2.2.1 to get fixes of multiple security vulnerabilities including: CVE-2017-9233 (External entity infinite loop DoS), CVE-2016-9063 (Integer overflow, re-fix), CVE-2016-0718 (Fix regression bugs from 2.2.0's fix to CVE-2016-0718) and CVE-2012-0876 -(Counter hash flooding with SipHash). Note: the CVE-2016-5300 (Use os- -specific entropy sources like getrandom) doesn't impact Python, since Python +(Counter hash flooding with SipHash). Note: the CVE-2016-5300 (Use +os-specific entropy sources like getrandom) doesn't impact Python, since Python already gets entropy from the OS to set the expat secret using ``XML_SetHashSalt()``. @@ -336,8 +336,8 @@ ImportError rather than SystemError. Improve signal delivery. -Avoid using Py_AddPendingCall from signal handler, to avoid calling signal- -unsafe functions. The tests I'm adding here fail without the rest of the +Avoid using Py_AddPendingCall from signal handler, to avoid calling +signal-unsafe functions. The tests I'm adding here fail without the rest of the patch, on Linux and OS X. This means our signal delivery logic had defects (some signals could be lost). @@ -1153,8 +1153,8 @@ Improve speed of the STORE_DEREF opcode by 40%. .. nonce: RYbEGH .. section: Core and Builtins -Extra slash no longer added to sys.path components in case of empty compile- -time PYTHONPATH components. +Extra slash no longer added to sys.path components in case of empty +compile-time PYTHONPATH components. .. @@ -2274,8 +2274,8 @@ LF. Patch by Dong-hee Na. .. nonce: N3KI-o .. section: Library -os.listdir() and os.scandir() now emit bytes names when called with bytes- -like argument. +os.listdir() and os.scandir() now emit bytes names when called with +bytes-like argument. .. @@ -2440,8 +2440,8 @@ leaving a fd in a bad state in case of error. Patch by Giampaolo Rodola'. .. nonce: d0nRRA .. section: Library -multiprocessing.Queue.get() with a timeout now polls its reader in non- -blocking mode if it succeeded to acquire the lock but the acquire took +multiprocessing.Queue.get() with a timeout now polls its reader in +non-blocking mode if it succeeded to acquire the lock but the acquire took longer than the timeout. .. @@ -2815,8 +2815,8 @@ of space. .. section: Library Various updates to typing module: add typing.NoReturn type, use -WrapperDescriptorType, minor bug-fixes. Original PRs by Jim Fasarakis- -Hilliard and Ivan Levkivskyi. +WrapperDescriptorType, minor bug-fixes. Original PRs by Jim +Fasarakis-Hilliard and Ivan Levkivskyi. .. @@ -3634,8 +3634,8 @@ Removed deprecated features in the http.cookies module. .. nonce: CgcjEx .. section: Library -A format string argument for string.Formatter.format() is now positional- -only. +A format string argument for string.Formatter.format() is now +positional-only. .. @@ -5164,8 +5164,8 @@ Fix out-of-tree builds of Python when configured with ``--with--dtrace``. .. section: Build Prevent unnecessary rebuilding of Python during ``make test``, ``make -install`` and some other make targets when configured with ``--enable- -optimizations``. +install`` and some other make targets when configured with +``--enable-optimizations``. .. @@ -5213,9 +5213,9 @@ Update Windows build and OS X installers to use OpenSSL 1.0.2k. .. nonce: i8UzRC .. section: Build -Prohibit implicit C function declarations: use -Werror=implicit-function- -declaration when possible (GCC and Clang, but it depends on the compiler -version). Patch written by Chi Hsuan Yen. +Prohibit implicit C function declarations: use +``-Werror=implicit-function-declaration`` when possible (GCC and Clang, +but it depends on the compiler version). Patch written by Chi Hsuan Yen. .. @@ -5774,8 +5774,8 @@ All custom keysets are saved as a whole in config- extension.cfg. All take effect as soon as one clicks Apply or Ok. The affected events are '<<force-open-completions>>', '<<expand-word>>', -'<<force-open-calltip>>', '<<flash-paren>>', '<<format-paragraph>>', '<<run- -module>>', '<<check-module>>', and '<<zoom-height>>'. Any (global) +'<<force-open-calltip>>', '<<flash-paren>>', '<<format-paragraph>>', +'<<run-module>>', '<<check-module>>', and '<<zoom-height>>'. Any (global) customizations made before 3.6.3 will not affect their keyset- specific customization after 3.6.3. and vice versa. diff --git a/Misc/NEWS.d/3.7.0a3.rst b/Misc/NEWS.d/3.7.0a3.rst index 516e41e48eca..7de841526cdc 100644 --- a/Misc/NEWS.d/3.7.0a3.rst +++ b/Misc/NEWS.d/3.7.0a3.rst @@ -1544,8 +1544,8 @@ Multilingual Plane, tcl/tk will use other fonts that define a character. The expanded example give users of non-Latin characters a better idea of what they might see in IDLE's shell and editors. -To make room for the expanded sample, frames on the Font tab are re- -arranged. The Font/Tabs help explains a bit about the additions. +To make room for the expanded sample, frames on the Font tab are +re-arranged. The Font/Tabs help explains a bit about the additions. .. diff --git a/Misc/NEWS.d/3.7.0b1.rst b/Misc/NEWS.d/3.7.0b1.rst index 3f850904d4be..db4adfb78879 100644 --- a/Misc/NEWS.d/3.7.0b1.rst +++ b/Misc/NEWS.d/3.7.0b1.rst @@ -181,8 +181,8 @@ longer raises ``RecursionError``; OrderedDict similarly. Instead, use .. section: Core and Builtins Py_Initialize() now creates the GIL. The GIL is no longer created "on -demand" to fix a race condition when PyGILState_Ensure() is called in a non- -Python thread. +demand" to fix a race condition when PyGILState_Ensure() is called in a +non-Python thread. .. diff --git a/Misc/NEWS.d/3.7.0b2.rst b/Misc/NEWS.d/3.7.0b2.rst index d597cee12309..7d137128b5b3 100644 --- a/Misc/NEWS.d/3.7.0b2.rst +++ b/Misc/NEWS.d/3.7.0b2.rst @@ -62,8 +62,8 @@ Fix the warning messages for Python/ast_unparse.c. Patch by St?phane Wirtel .. nonce: Fh3fau .. section: Core and Builtins -Fix possible crashing in builtin Unicode decoders caused by write out-of- -bound errors when using customized decode error handlers. +Fix possible crashing in builtin Unicode decoders caused by write +out-of-bound errors when using customized decode error handlers. .. diff --git a/Misc/NEWS.d/3.7.0b3.rst b/Misc/NEWS.d/3.7.0b3.rst index 876463d10ec8..fc5492c36c48 100644 --- a/Misc/NEWS.d/3.7.0b3.rst +++ b/Misc/NEWS.d/3.7.0b3.rst @@ -483,8 +483,8 @@ to a UNC path. Build and link with private copy of Tcl/Tk 8.6 for the macOS 10.6+ installer. The 10.9+ installer variant already does this. This means that the Python 3.7 provided by the python.org macOS installers no longer need or -use any external versions of Tcl/Tk, either system-provided or user- -installed, such as ActiveTcl. +use any external versions of Tcl/Tk, either system-provided or +user-installed, such as ActiveTcl. .. From webhook-mailer at python.org Tue May 22 07:53:40 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Tue, 22 May 2018 11:53:40 -0000 Subject: [Python-checkins] [3.6] Fix line breaks added after hyphens by blurb. (GH-7002) (GH-7051) Message-ID: <mailman.9.1526990020.18020.python-checkins@python.org> https://github.com/python/cpython/commit/1b48b9cfacaa915606e15cc32eb208643f1a2e34 commit: 1b48b9cfacaa915606e15cc32eb208643f1a2e34 branch: 3.6 author: Serhiy Storchaka <storchaka at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-22T14:53:37+03:00 summary: [3.6] Fix line breaks added after hyphens by blurb. (GH-7002) (GH-7051) Also remove bullet asterisks from IDLE entries. (cherry picked from commit aef639f62677f8a342af24e9c19f0503b0d1e36e) files: M Misc/NEWS.d/3.5.0a1.rst M Misc/NEWS.d/3.5.0a3.rst M Misc/NEWS.d/3.5.0b3.rst M Misc/NEWS.d/3.5.0b4.rst M Misc/NEWS.d/3.5.1rc1.rst M Misc/NEWS.d/3.5.2rc1.rst M Misc/NEWS.d/3.5.3rc1.rst M Misc/NEWS.d/3.6.0a1.rst M Misc/NEWS.d/3.6.0b1.rst M Misc/NEWS.d/3.6.0b4.rst M Misc/NEWS.d/3.6.2rc1.rst M Misc/NEWS.d/3.6.2rc2.rst M Misc/NEWS.d/3.6.3rc1.rst M Misc/NEWS.d/3.6.5rc1.rst diff --git a/Misc/NEWS.d/3.5.0a1.rst b/Misc/NEWS.d/3.5.0a1.rst index 97fe42d18fba..92ca7cab2270 100644 --- a/Misc/NEWS.d/3.5.0a1.rst +++ b/Misc/NEWS.d/3.5.0a1.rst @@ -2706,8 +2706,8 @@ Added support for the "xztar" format in the shutil module. .. nonce: ZLsRil .. section: Library -Don't force 3rd party C extensions to be built with -Werror=declaration- -after-statement. +Don't force 3rd party C extensions to be built with +``-Werror=declaration-after-statement``. .. @@ -4464,8 +4464,8 @@ Improve repr of inspect.Signature and inspect.Parameter. .. nonce: DFMEgN .. section: Library -Fix inspect.getcallargs() to raise correct TypeError for missing keyword- -only arguments. Patch by Jeremiah Lowin. +Fix inspect.getcallargs() to raise correct TypeError for missing +keyword-only arguments. Patch by Jeremiah Lowin. .. @@ -5059,8 +5059,8 @@ Anticipated fixes to support OS X versions > 10.9. .. nonce: KAl7aO .. section: Build -Prevent possible segfaults and other random failures of python --generate- -posix-vars in pybuilddir.txt build target. +Prevent possible segfaults and other random failures of python +``--generate-posix-vars`` in pybuilddir.txt build target. .. diff --git a/Misc/NEWS.d/3.5.0a3.rst b/Misc/NEWS.d/3.5.0a3.rst index b69c4c39ca00..9e2d3e85b1c9 100644 --- a/Misc/NEWS.d/3.5.0a3.rst +++ b/Misc/NEWS.d/3.5.0a3.rst @@ -62,8 +62,8 @@ Fix the default __sizeof__ implementation for variable-sized objects. .. nonce: b5M04V .. section: Library -The groupindex attribute of regular expression pattern object now is non- -modifiable mapping. +The groupindex attribute of regular expression pattern object now is +non-modifiable mapping. .. diff --git a/Misc/NEWS.d/3.5.0b3.rst b/Misc/NEWS.d/3.5.0b3.rst index 6b72d4b177e7..7f898316632b 100644 --- a/Misc/NEWS.d/3.5.0b3.rst +++ b/Misc/NEWS.d/3.5.0b3.rst @@ -110,8 +110,8 @@ by Martin Panter. .. nonce: aAbWbQ .. section: Library -Restore semantic round-trip correctness in tokenize/untokenize for tab- -indented blocks. +Restore semantic round-trip correctness in tokenize/untokenize for +tab-indented blocks. .. diff --git a/Misc/NEWS.d/3.5.0b4.rst b/Misc/NEWS.d/3.5.0b4.rst index 6f115483567e..5497df8011a0 100644 --- a/Misc/NEWS.d/3.5.0b4.rst +++ b/Misc/NEWS.d/3.5.0b4.rst @@ -224,8 +224,8 @@ segment. .. nonce: hwXwCH .. section: Library -SMTP.auth() and SMTP.login() now support RFC 4954's optional initial- -response argument to the SMTP AUTH command. +SMTP.auth() and SMTP.login() now support RFC 4954's optional +initial-response argument to the SMTP AUTH command. .. diff --git a/Misc/NEWS.d/3.5.1rc1.rst b/Misc/NEWS.d/3.5.1rc1.rst index 45cf6d93c226..93d0dbc1e7bb 100644 --- a/Misc/NEWS.d/3.5.1rc1.rst +++ b/Misc/NEWS.d/3.5.1rc1.rst @@ -159,8 +159,8 @@ twice. On Solaris 11.3 or newer, os.urandom() now uses the getrandom() function instead of the getentropy() function. The getentropy() function is blocking -to generate very good quality entropy, os.urandom() doesn't need such high- -quality entropy. +to generate very good quality entropy, os.urandom() doesn't need such +high-quality entropy. .. @@ -1083,10 +1083,10 @@ them a 'sheet'. Patch by Mark Roseman. .. nonce: -j_BV7 .. section: IDLE -Enhance the initial html viewer now used for Idle Help. * Properly indent -fixed-pitch text (patch by Mark Roseman). * Give code snippet a very Sphinx- -like light blueish-gray background. * Re-use initial width and height set by -users for shell and editor. * When the Table of Contents (TOC) menu is used, +Enhance the initial html viewer now used for Idle Help. Properly indent +fixed-pitch text (patch by Mark Roseman). Give code snippet a very +Sphinx-like light blueish-gray background. Re-use initial width and height set by +users for shell and editor. When the Table of Contents (TOC) menu is used, put the section header at the top of the screen. .. diff --git a/Misc/NEWS.d/3.5.2rc1.rst b/Misc/NEWS.d/3.5.2rc1.rst index b9c4e0d651e4..97385b57aac7 100644 --- a/Misc/NEWS.d/3.5.2rc1.rst +++ b/Misc/NEWS.d/3.5.2rc1.rst @@ -568,9 +568,9 @@ string. Original fix by J?n Janech. .. section: Library The "urllib.request" module now percent-encodes non-ASCII bytes found in -redirect target URLs. Some servers send Location header fields with non- -ASCII bytes, but "http.client" requires the request target to be ASCII- -encodable, otherwise a UnicodeEncodeError is raised. Based on patch by +redirect target URLs. Some servers send Location header fields with +non-ASCII bytes, but "http.client" requires the request target to be +ASCII-encodable, otherwise a UnicodeEncodeError is raised. Based on patch by Christian Heimes. .. @@ -1952,8 +1952,8 @@ Fix linking extension modules for cross builds. Patch by Xavier de Gaye. .. nonce: HDjM4s .. section: Build -Disable the rules for running _freeze_importlib and pgen when cross- -compiling. The output of these programs is normally saved with the source +Disable the rules for running _freeze_importlib and pgen when +cross-compiling. The output of these programs is normally saved with the source code anyway, and is still regenerated when doing a native build. Patch by Xavier de Gaye. diff --git a/Misc/NEWS.d/3.5.3rc1.rst b/Misc/NEWS.d/3.5.3rc1.rst index caba4d403be5..7ac5e19c24c2 100644 --- a/Misc/NEWS.d/3.5.3rc1.rst +++ b/Misc/NEWS.d/3.5.3rc1.rst @@ -81,8 +81,8 @@ astral characters. Patch by Xiang Zhang. .. nonce: RYbEGH .. section: Core and Builtins -Extra slash no longer added to sys.path components in case of empty compile- -time PYTHONPATH components. +Extra slash no longer added to sys.path components in case of empty +compile-time PYTHONPATH components. .. @@ -349,8 +349,8 @@ Patch written by Xiang Zhang. .. section: Core and Builtins Standard __import__() no longer look up "__import__" in globals or builtins -for importing submodules or "from import". Fixed handling an error of non- -string package name. +for importing submodules or "from import". Fixed handling an error of +non-string package name. .. @@ -2070,9 +2070,9 @@ Update message in validate_ucrtbase.py .. section: Build Cause lack of llvm-profdata tool when using clang as required for PGO -linking to be a configure time error rather than make time when --with- -optimizations is enabled. Also improve our ability to find the llvm- -profdata tool on MacOS and some Linuxes. +linking to be a configure time error rather than make time when +``--with-optimizations`` is enabled. Also improve our ability to find the +llvm-profdata tool on MacOS and some Linuxes. .. diff --git a/Misc/NEWS.d/3.6.0a1.rst b/Misc/NEWS.d/3.6.0a1.rst index e9745fb30330..62bfd4e2ef55 100644 --- a/Misc/NEWS.d/3.6.0a1.rst +++ b/Misc/NEWS.d/3.6.0a1.rst @@ -728,8 +728,8 @@ Fixed a number of bugs in UTF-7 decoding of misformed data. .. section: Core and Builtins The UTF-8 encoder is now up to 75 times as fast for error handlers: -``ignore``, ``replace``, ``surrogateescape``, ``surrogatepass``. Patch co- -written with Serhiy Storchaka. +``ignore``, ``replace``, ``surrogateescape``, ``surrogatepass``. Patch +co-written with Serhiy Storchaka. .. @@ -761,8 +761,8 @@ by Serhiy Storchaka. On Solaris 11.3 or newer, os.urandom() now uses the getrandom() function instead of the getentropy() function. The getentropy() function is blocking -to generate very good quality entropy, os.urandom() doesn't need such high- -quality entropy. +to generate very good quality entropy, os.urandom() doesn't need such +high-quality entropy. .. @@ -891,9 +891,9 @@ string. Original fix by J?n Janech. .. section: Library The "urllib.request" module now percent-encodes non-ASCII bytes found in -redirect target URLs. Some servers send Location header fields with non- -ASCII bytes, but "http.client" requires the request target to be ASCII- -encodable, otherwise a UnicodeEncodeError is raised. Based on patch by +redirect target URLs. Some servers send Location header fields with +non-ASCII bytes, but "http.client" requires the request target to be +ASCII-encodable, otherwise a UnicodeEncodeError is raised. Based on patch by Christian Heimes. .. @@ -3328,10 +3328,10 @@ them a 'sheet'. Patch by Mark Roseman. .. nonce: -j_BV7 .. section: IDLE -Enhance the initial html viewer now used for Idle Help. * Properly indent -fixed-pitch text (patch by Mark Roseman). * Give code snippet a very Sphinx- -like light blueish-gray background. * Re-use initial width and height set by -users for shell and editor. * When the Table of Contents (TOC) menu is used, +Enhance the initial html viewer now used for Idle Help. Properly indent +fixed-pitch text (patch by Mark Roseman). Give code snippet a very +Sphinx-like light blueish-gray background. Re-use initial width and height set by +users for shell and editor. When the Table of Contents (TOC) menu is used, put the section header at the top of the screen. .. @@ -3651,8 +3651,8 @@ particular on Android). Patch by Chi Hsuan Yen. .. nonce: HDjM4s .. section: Build -Disable the rules for running _freeze_importlib and pgen when cross- -compiling. The output of these programs is normally saved with the source +Disable the rules for running _freeze_importlib and pgen when +cross-compiling. The output of these programs is normally saved with the source code anyway, and is still regenerated when doing a native build. Patch by Xavier de Gaye. diff --git a/Misc/NEWS.d/3.6.0b1.rst b/Misc/NEWS.d/3.6.0b1.rst index 655f6f749e46..560d49cd87e7 100644 --- a/Misc/NEWS.d/3.6.0b1.rst +++ b/Misc/NEWS.d/3.6.0b1.rst @@ -507,8 +507,8 @@ expression. .. nonce: TJ779X .. section: Library -xmlrpc now supports unmarshalling additional data types used by Apache XML- -RPC implementation for numerics and None. +xmlrpc now supports unmarshalling additional data types used by Apache +XML-RPC implementation for numerics and None. .. @@ -1416,9 +1416,9 @@ platforms. .. section: Build Cause lack of llvm-profdata tool when using clang as required for PGO -linking to be a configure time error rather than make time when --with- -optimizations is enabled. Also improve our ability to find the llvm- -profdata tool on MacOS and some Linuxes. +linking to be a configure time error rather than make time when +``--with-optimizations`` is enabled. Also improve our ability to find the +llvm-profdata tool on MacOS and some Linuxes. .. diff --git a/Misc/NEWS.d/3.6.0b4.rst b/Misc/NEWS.d/3.6.0b4.rst index c725ffd44b25..a8e408619af0 100644 --- a/Misc/NEWS.d/3.6.0b4.rst +++ b/Misc/NEWS.d/3.6.0b4.rst @@ -54,8 +54,8 @@ astral characters. Patch by Xiang Zhang. .. nonce: RYbEGH .. section: Core and Builtins -Extra slash no longer added to sys.path components in case of empty compile- -time PYTHONPATH components. +Extra slash no longer added to sys.path components in case of empty +compile-time PYTHONPATH components. .. diff --git a/Misc/NEWS.d/3.6.2rc1.rst b/Misc/NEWS.d/3.6.2rc1.rst index 4ec0f9789fea..0a21ae7622e0 100644 --- a/Misc/NEWS.d/3.6.2rc1.rst +++ b/Misc/NEWS.d/3.6.2rc1.rst @@ -492,8 +492,8 @@ is received. .. section: Library Various updates to typing module: add typing.NoReturn type, use -WrapperDescriptorType, minor bug-fixes. Original PRs by Jim Fasarakis- -Hilliard and Ivan Levkivskyi. +WrapperDescriptorType, minor bug-fixes. Original PRs by Jim +Fasarakis-Hilliard and Ivan Levkivskyi. .. @@ -830,8 +830,8 @@ Fix out-of-tree builds of Python when configured with ``--with--dtrace``. .. section: Build Prevent unnecessary rebuilding of Python during ``make test``, ``make -install`` and some other make targets when configured with ``--enable- -optimizations``. +install`` and some other make targets when configured with +``--enable-optimizations``. .. diff --git a/Misc/NEWS.d/3.6.2rc2.rst b/Misc/NEWS.d/3.6.2rc2.rst index 4fdfabd0e311..45be03eb5fa4 100644 --- a/Misc/NEWS.d/3.6.2rc2.rst +++ b/Misc/NEWS.d/3.6.2rc2.rst @@ -20,9 +20,9 @@ Upgrade expat copy from 2.2.0 to 2.2.1 to get fixes of multiple security vulnerabilities including: CVE-2017-9233 (External entity infinite loop DoS), CVE-2016-9063 (Integer overflow, re-fix), CVE-2016-0718 (Fix regression bugs from 2.2.0's fix to CVE-2016-0718) and CVE-2012-0876 -(Counter hash flooding with SipHash). Note: the CVE-2016-5300 (Use os- -specific entropy sources like getrandom) doesn't impact Python, since Python -already gets entropy from the OS to set the expat secret using +(Counter hash flooding with SipHash). Note: the CVE-2016-5300 (Use +os-specific entropy sources like getrandom) doesn't impact Python, since +Python already gets entropy from the OS to set the expat secret using ``XML_SetHashSalt()``. .. diff --git a/Misc/NEWS.d/3.6.3rc1.rst b/Misc/NEWS.d/3.6.3rc1.rst index b16592bf1a5d..8e1ffb97d344 100644 --- a/Misc/NEWS.d/3.6.3rc1.rst +++ b/Misc/NEWS.d/3.6.3rc1.rst @@ -197,10 +197,10 @@ ImportError rather than SystemError. Improve signal delivery. -Avoid using Py_AddPendingCall from signal handler, to avoid calling signal- -unsafe functions. The tests I'm adding here fail without the rest of the -patch, on Linux and OS X. This means our signal delivery logic had defects -(some signals could be lost). +Avoid using Py_AddPendingCall from signal handler, to avoid calling +signal-unsafe functions. The tests I'm adding here fail without the rest of +the patch, on Linux and OS X. This means our signal delivery logic had +defects (some signals could be lost). .. @@ -516,9 +516,9 @@ LF. Patch by Dong-hee Na. .. nonce: -zJ7d8 .. section: Library -multiprocessing.Queue.get() with a timeout now polls its reader in non- -blocking mode if it succeeded to aquire the lock but the acquire took longer -than the timeout. +multiprocessing.Queue.get() with a timeout now polls its reader in +non-blocking mode if it succeeded to aquire the lock but the acquire took +longer than the timeout. .. @@ -627,8 +627,8 @@ Fix email header value parser dropping folding white space in certain cases. .. nonce: N3KI-o .. section: Library -os.listdir() and os.scandir() now emit bytes names when called with bytes- -like argument. +os.listdir() and os.scandir() now emit bytes names when called with +bytes-like argument. .. @@ -881,8 +881,8 @@ All custom keysets are saved as a whole in config- extension.cfg. All take effect as soon as one clicks Apply or Ok. The affected events are '<<force-open-completions>>', '<<expand-word>>', -'<<force-open-calltip>>', '<<flash-paren>>', '<<format-paragraph>>', '<<run- -module>>', '<<check-module>>', and '<<zoom-height>>'. Any (global) +'<<force-open-calltip>>', '<<flash-paren>>', '<<format-paragraph>>', +'<<run-module>>', '<<check-module>>', and '<<zoom-height>>'. Any (global) customizations made before 3.6.3 will not affect their keyset- specific customization after 3.6.3. and vice versa. diff --git a/Misc/NEWS.d/3.6.5rc1.rst b/Misc/NEWS.d/3.6.5rc1.rst index 5231de1c6f78..7790a9e3d104 100644 --- a/Misc/NEWS.d/3.6.5rc1.rst +++ b/Misc/NEWS.d/3.6.5rc1.rst @@ -74,8 +74,8 @@ terminated by a semi-colon instead of a newline. Patch by Nitish Chandra. .. nonce: Fh3fau .. section: Core and Builtins -Fix possible crashing in builtin Unicode decoders caused by write out-of- -bound errors when using customized decode error handlers. +Fix possible crashing in builtin Unicode decoders caused by write +out-of-bound errors when using customized decode error handlers. .. From webhook-mailer at python.org Tue May 22 07:54:17 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Tue, 22 May 2018 11:54:17 -0000 Subject: [Python-checkins] [3.6] bpo-5945: Improve mappings and sequences C API docs. (GH-7029). (GH-7049) Message-ID: <mailman.10.1526990058.18020.python-checkins@python.org> https://github.com/python/cpython/commit/93e9fb5664e56c02c9aa89098b556929735b35db commit: 93e9fb5664e56c02c9aa89098b556929735b35db branch: 3.6 author: Serhiy Storchaka <storchaka at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-22T14:54:14+03:00 summary: [3.6] bpo-5945: Improve mappings and sequences C API docs. (GH-7029). (GH-7049) (cherry picked from commit f5b1183610d5888db3bbd639b1a0c945dbd8f8dd) files: M Doc/c-api/mapping.rst M Doc/c-api/object.rst M Doc/c-api/sequence.rst M Doc/c-api/typeobj.rst diff --git a/Doc/c-api/mapping.rst b/Doc/c-api/mapping.rst index a71e94283776..c16fcf4439d4 100644 --- a/Doc/c-api/mapping.rst +++ b/Doc/c-api/mapping.rst @@ -5,11 +5,17 @@ Mapping Protocol ================ +See also :c:func:`PyObject_GetItem`, :c:func:`PyObject_SetItem` and +:c:func:`PyObject_DelItem`. + .. c:function:: int PyMapping_Check(PyObject *o) - Return ``1`` if the object provides mapping protocol, and ``0`` otherwise. This - function always succeeds. + Return ``1`` if the object provides mapping protocol or supports slicing, + and ``0`` otherwise. Note that it returns ``1`` for Python classes with + a :meth:`__getitem__` method since in general case it is impossible to + determine what the type of keys it supports. This function always + succeeds. .. c:function:: Py_ssize_t PyMapping_Size(PyObject *o) @@ -17,35 +23,49 @@ Mapping Protocol .. index:: builtin: len - Returns the number of keys in object *o* on success, and ``-1`` on failure. For - objects that do not provide mapping protocol, this is equivalent to the Python - expression ``len(o)``. + Returns the number of keys in object *o* on success, and ``-1`` on failure. + This is equivalent to the Python expression ``len(o)``. -.. c:function:: int PyMapping_DelItemString(PyObject *o, const char *key) +.. c:function:: PyObject* PyMapping_GetItemString(PyObject *o, const char *key) + + Return element of *o* corresponding to the string *key* or *NULL* on failure. + This is the equivalent of the Python expression ``o[key]``. + See also :c:func:`PyObject_GetItem`. + - Remove the mapping for object *key* from the object *o*. Return ``-1`` on - failure. This is equivalent to the Python statement ``del o[key]``. +.. c:function:: int PyMapping_SetItemString(PyObject *o, const char *key, PyObject *v) + + Map the string *key* to the value *v* in object *o*. Returns ``-1`` on + failure. This is the equivalent of the Python statement ``o[key] = v``. + See also :c:func:`PyObject_SetItem`. .. c:function:: int PyMapping_DelItem(PyObject *o, PyObject *key) - Remove the mapping for object *key* from the object *o*. Return ``-1`` on - failure. This is equivalent to the Python statement ``del o[key]``. + Remove the mapping for the object *key* from the object *o*. Return ``-1`` + on failure. This is equivalent to the Python statement ``del o[key]``. + This is an alias of :c:func:`PyObject_DelItem`. -.. c:function:: int PyMapping_HasKeyString(PyObject *o, const char *key) +.. c:function:: int PyMapping_DelItemString(PyObject *o, const char *key) - On success, return ``1`` if the mapping object has the key *key* and ``0`` - otherwise. This is equivalent to the Python expression ``key in o``. - This function always succeeds. + Remove the mapping for the string *key* from the object *o*. Return ``-1`` + on failure. This is equivalent to the Python statement ``del o[key]``. .. c:function:: int PyMapping_HasKey(PyObject *o, PyObject *key) - Return ``1`` if the mapping object has the key *key* and ``0`` otherwise. This - is equivalent to the Python expression ``key in o``. This function always - succeeds. + Return ``1`` if the mapping object has the key *key* and ``0`` otherwise. + This is equivalent to the Python expression ``key in o``. + This function always succeeds. + + +.. c:function:: int PyMapping_HasKeyString(PyObject *o, const char *key) + + Return ``1`` if the mapping object has the key *key* and ``0`` otherwise. + This is equivalent to the Python expression ``key in o``. + This function always succeeds. .. c:function:: PyObject* PyMapping_Keys(PyObject *o) @@ -64,15 +84,3 @@ Mapping Protocol On success, return a list or tuple of the items in object *o*, where each item is a tuple containing a key-value pair. On failure, return *NULL*. - - -.. c:function:: PyObject* PyMapping_GetItemString(PyObject *o, const char *key) - - Return element of *o* corresponding to the object *key* or *NULL* on failure. - This is the equivalent of the Python expression ``o[key]``. - - -.. c:function:: int PyMapping_SetItemString(PyObject *o, const char *key, PyObject *v) - - Map the object *key* to the value *v* in object *o*. Returns ``-1`` on failure. - This is the equivalent of the Python statement ``o[key] = v``. diff --git a/Doc/c-api/object.rst b/Doc/c-api/object.rst index b761c808fcb7..8692a2c14ca2 100644 --- a/Doc/c-api/object.rst +++ b/Doc/c-api/object.rst @@ -360,8 +360,8 @@ Object Protocol parameters must be non-*NULL*. -.. c:function:: Py_ssize_t PyObject_Length(PyObject *o) - Py_ssize_t PyObject_Size(PyObject *o) +.. c:function:: Py_ssize_t PyObject_Size(PyObject *o) + Py_ssize_t PyObject_Length(PyObject *o) .. index:: builtin: len @@ -395,8 +395,8 @@ Object Protocol .. c:function:: int PyObject_DelItem(PyObject *o, PyObject *key) - Delete the mapping for *key* from *o*. Returns ``-1`` on failure. This is the - equivalent of the Python statement ``del o[key]``. + Remove the mapping for the object *key* from the object *o*. Return ``-1`` + on failure. This is equivalent to the Python statement ``del o[key]``. .. c:function:: PyObject* PyObject_Dir(PyObject *o) diff --git a/Doc/c-api/sequence.rst b/Doc/c-api/sequence.rst index 81f8557ea6e6..6d22f35e22b1 100644 --- a/Doc/c-api/sequence.rst +++ b/Doc/c-api/sequence.rst @@ -9,7 +9,10 @@ Sequence Protocol .. c:function:: int PySequence_Check(PyObject *o) Return ``1`` if the object provides sequence protocol, and ``0`` otherwise. - This function always succeeds. + Note that it returns ``1`` for Python classes with a :meth:`__getitem__` + method unless they are :class:`dict` subclasses since in general case it + is impossible to determine what the type of keys it supports. This + function always succeeds. .. c:function:: Py_ssize_t PySequence_Size(PyObject *o) @@ -119,18 +122,27 @@ Sequence Protocol .. index:: builtin: tuple - Return a tuple object with the same contents as the arbitrary sequence *o* or - *NULL* on failure. If *o* is a tuple, a new reference will be returned, + Return a tuple object with the same contents as the sequence or iterable *o*, + or *NULL* on failure. If *o* is a tuple, a new reference will be returned, otherwise a tuple will be constructed with the appropriate contents. This is equivalent to the Python expression ``tuple(o)``. .. c:function:: PyObject* PySequence_Fast(PyObject *o, const char *m) - Return the sequence *o* as a list, unless it is already a tuple or list, in + Return the sequence or iterable *o* as a list, unless it is already a tuple or list, in which case *o* is returned. Use :c:func:`PySequence_Fast_GET_ITEM` to access the members of the result. Returns *NULL* on failure. If the object is not - a sequence, raises :exc:`TypeError` with *m* as the message text. + a sequence or iterable, raises :exc:`TypeError` with *m* as the message text. + + +.. c:function:: Py_ssize_t PySequence_Fast_GET_SIZE(PyObject *o) + + Returns the length of *o*, assuming that *o* was returned by + :c:func:`PySequence_Fast` and that *o* is not *NULL*. The size can also be + gotten by calling :c:func:`PySequence_Size` on *o*, but + :c:func:`PySequence_Fast_GET_SIZE` is faster because it can assume *o* is a list + or tuple. .. c:function:: PyObject* PySequence_Fast_GET_ITEM(PyObject *o, Py_ssize_t i) @@ -155,12 +167,3 @@ Sequence Protocol :c:func:`PySequence_GetItem` but without checking that :c:func:`PySequence_Check` on *o* is true and without adjustment for negative indices. - - -.. c:function:: Py_ssize_t PySequence_Fast_GET_SIZE(PyObject *o) - - Returns the length of *o*, assuming that *o* was returned by - :c:func:`PySequence_Fast` and that *o* is not *NULL*. The size can also be - gotten by calling :c:func:`PySequence_Size` on *o*, but - :c:func:`PySequence_Fast_GET_SIZE` is faster because it can assume *o* is a list - or tuple. diff --git a/Doc/c-api/typeobj.rst b/Doc/c-api/typeobj.rst index 0b4577f5b950..76515fd2c430 100644 --- a/Doc/c-api/typeobj.rst +++ b/Doc/c-api/typeobj.rst @@ -1151,21 +1151,24 @@ Mapping Object Structures .. c:member:: lenfunc PyMappingMethods.mp_length - This function is used by :c:func:`PyMapping_Length` and + This function is used by :c:func:`PyMapping_Size` and :c:func:`PyObject_Size`, and has the same signature. This slot may be set to *NULL* if the object has no defined length. .. c:member:: binaryfunc PyMappingMethods.mp_subscript - This function is used by :c:func:`PyObject_GetItem` and has the same - signature. This slot must be filled for the :c:func:`PyMapping_Check` - function to return ``1``, it can be *NULL* otherwise. + This function is used by :c:func:`PyObject_GetItem` and + :c:func:`PySequence_GetSlice`, and has the same signature as + :c:func:`!PyObject_GetItem`. This slot must be filled for the + :c:func:`PyMapping_Check` function to return ``1``, it can be *NULL* + otherwise. .. c:member:: objobjargproc PyMappingMethods.mp_ass_subscript - This function is used by :c:func:`PyObject_SetItem` and - :c:func:`PyObject_DelItem`. It has the same signature as - :c:func:`PyObject_SetItem`, but *v* can also be set to *NULL* to delete + This function is used by :c:func:`PyObject_SetItem`, + :c:func:`PyObject_DelItem`, :c:func:`PyObject_SetSlice` and + :c:func:`PyObject_DelSlice`. It has the same signature as + :c:func:`!PyObject_SetItem`, but *v* can also be set to *NULL* to delete an item. If this slot is *NULL*, the object does not support item assignment and deletion. @@ -1185,26 +1188,29 @@ Sequence Object Structures .. c:member:: lenfunc PySequenceMethods.sq_length - This function is used by :c:func:`PySequence_Size` and :c:func:`PyObject_Size`, - and has the same signature. + This function is used by :c:func:`PySequence_Size` and + :c:func:`PyObject_Size`, and has the same signature. It is also used for + handling negative indices via the :c:member:`~PySequenceMethods.sq_item` + and the :c:member:`~PySequenceMethods.sq_ass_item` slots. .. c:member:: binaryfunc PySequenceMethods.sq_concat This function is used by :c:func:`PySequence_Concat` and has the same signature. It is also used by the ``+`` operator, after trying the numeric - addition via the :c:member:`~PyTypeObject.tp_as_number.nb_add` slot. + addition via the :c:member:`~PyNumberMethods.nb_add` slot. .. c:member:: ssizeargfunc PySequenceMethods.sq_repeat This function is used by :c:func:`PySequence_Repeat` and has the same signature. It is also used by the ``*`` operator, after trying numeric - multiplication via the :c:member:`~PyTypeObject.tp_as_number.nb_multiply` - slot. + multiplication via the :c:member:`~PyNumberMethods.nb_multiply` slot. .. c:member:: ssizeargfunc PySequenceMethods.sq_item This function is used by :c:func:`PySequence_GetItem` and has the same - signature. This slot must be filled for the :c:func:`PySequence_Check` + signature. It is also used by :c:func:`PyObject_GetItem`, after trying + the subscription via the :c:member:`~PyMappingMethods.mp_subscript` slot. + This slot must be filled for the :c:func:`PySequence_Check` function to return ``1``, it can be *NULL* otherwise. Negative indexes are handled as follows: if the :attr:`sq_length` slot is @@ -1215,28 +1221,36 @@ Sequence Object Structures .. c:member:: ssizeobjargproc PySequenceMethods.sq_ass_item This function is used by :c:func:`PySequence_SetItem` and has the same - signature. This slot may be left to *NULL* if the object does not support + signature. It is also used by :c:func:`PyObject_SetItem` and + :c:func:`PyObject_DelItem`, after trying the item assignment and deletion + via the :c:member:`~PyMappingMethods.mp_ass_subscript` slot. + This slot may be left to *NULL* if the object does not support item assignment and deletion. .. c:member:: objobjproc PySequenceMethods.sq_contains This function may be used by :c:func:`PySequence_Contains` and has the same signature. This slot may be left to *NULL*, in this case - :c:func:`PySequence_Contains` simply traverses the sequence until it finds a - match. + :c:func:`!PySequence_Contains` simply traverses the sequence until it + finds a match. .. c:member:: binaryfunc PySequenceMethods.sq_inplace_concat This function is used by :c:func:`PySequence_InPlaceConcat` and has the same - signature. It should modify its first operand, and return it. + signature. It should modify its first operand, and return it. This slot + may be left to *NULL*, in this case :c:func:`!PySequence_InPlaceConcat` + will fall back to :c:func:`PySequence_Concat`. It is also used by the + augmented assignment ``+=``, after trying numeric inplace addition + via the :c:member:`~PyNumberMethods.nb_inplace_add` slot. .. c:member:: ssizeargfunc PySequenceMethods.sq_inplace_repeat This function is used by :c:func:`PySequence_InPlaceRepeat` and has the same - signature. It should modify its first operand, and return it. - -.. XXX need to explain precedence between mapping and sequence -.. XXX explains when to implement the sq_inplace_* slots + signature. It should modify its first operand, and return it. This slot + may be left to *NULL*, in this case :c:func:`!PySequence_InPlaceRepeat` + will fall back to :c:func:`PySequence_Repeat`. It is also used by the + augmented assignment ``*=``, after trying numeric inplace multiplication + via the :c:member:`~PyNumberMethods.nb_inplace_multiply` slot. .. _buffer-structs: From webhook-mailer at python.org Tue May 22 07:55:10 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Tue, 22 May 2018 11:55:10 -0000 Subject: [Python-checkins] bpo-30877: Fix clearing a cache in the the JSON decoder. (GH-7048) Message-ID: <mailman.11.1526990110.18020.python-checkins@python.org> https://github.com/python/cpython/commit/ae00fb1d4f38ea1803b10d798564740adcdad63e commit: ae00fb1d4f38ea1803b10d798564740adcdad63e branch: master author: Serhiy Storchaka <storchaka at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-22T14:55:07+03:00 summary: bpo-30877: Fix clearing a cache in the the JSON decoder. (GH-7048) files: A Misc/NEWS.d/next/Library/2018-05-22-13-05-12.bpo-30877.JZEGjI.rst M Lib/json/scanner.py M Lib/test/test_json/test_decode.py diff --git a/Lib/json/scanner.py b/Lib/json/scanner.py index c451ebab5842..7a61cfc2d24d 100644 --- a/Lib/json/scanner.py +++ b/Lib/json/scanner.py @@ -68,6 +68,6 @@ def scan_once(string, idx): finally: memo.clear() - return _scan_once + return scan_once make_scanner = c_make_scanner or py_make_scanner diff --git a/Lib/test/test_json/test_decode.py b/Lib/test/test_json/test_decode.py index d84ef7da2446..fdb9e62124ec 100644 --- a/Lib/test/test_json/test_decode.py +++ b/Lib/test/test_json/test_decode.py @@ -58,7 +58,9 @@ def check_keys_reuse(self, source, loads): def test_keys_reuse(self): s = '[{"a_key": 1, "b_\xe9": 2}, {"a_key": 3, "b_\xe9": 4}]' self.check_keys_reuse(s, self.loads) - self.check_keys_reuse(s, self.json.decoder.JSONDecoder().decode) + decoder = self.json.decoder.JSONDecoder() + self.check_keys_reuse(s, decoder.decode) + self.assertFalse(decoder.memo) def test_extra_data(self): s = '[1, 2, 3]5' diff --git a/Misc/NEWS.d/next/Library/2018-05-22-13-05-12.bpo-30877.JZEGjI.rst b/Misc/NEWS.d/next/Library/2018-05-22-13-05-12.bpo-30877.JZEGjI.rst new file mode 100644 index 000000000000..4be0fae4ecb6 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-22-13-05-12.bpo-30877.JZEGjI.rst @@ -0,0 +1,3 @@ +Fixed a bug in the Python implementation of the JSON decoder that prevented +the cache of parsed strings from clearing after finishing the decoding. +Based on patch by c-fos. From webhook-mailer at python.org Tue May 22 07:55:55 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Tue, 22 May 2018 11:55:55 -0000 Subject: [Python-checkins] [2.7] Fix line breaks added after hyphens by blurb. (GH-7052) Message-ID: <mailman.12.1526990156.18020.python-checkins@python.org> https://github.com/python/cpython/commit/6c58f7f4b1b9783d4f3b1c4f31fd4fe8a845ee1f commit: 6c58f7f4b1b9783d4f3b1c4f31fd4fe8a845ee1f branch: 2.7 author: Serhiy Storchaka <storchaka at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-22T14:55:52+03:00 summary: [2.7] Fix line breaks added after hyphens by blurb. (GH-7052) files: M Misc/NEWS.d/2.6a1.rst M Misc/NEWS.d/2.6a2.rst M Misc/NEWS.d/2.7.11rc1.rst M Misc/NEWS.d/2.7.13rc1.rst M Misc/NEWS.d/2.7.14rc1.rst M Misc/NEWS.d/2.7.15rc1.rst M Misc/NEWS.d/2.7.2rc1.rst M Misc/NEWS.d/2.7.4rc1.rst M Misc/NEWS.d/2.7.5.rst M Misc/NEWS.d/2.7.9rc1.rst M Misc/NEWS.d/2.7a1.rst M Misc/NEWS.d/2.7a2.rst M Misc/NEWS.d/2.7b1.rst M Misc/NEWS.d/2.7b2.rst M Misc/NEWS.d/2.7rc1.rst diff --git a/Misc/NEWS.d/2.6a1.rst b/Misc/NEWS.d/2.6a1.rst index 8edf052299fc..058d8c4d6a1e 100644 --- a/Misc/NEWS.d/2.6a1.rst +++ b/Misc/NEWS.d/2.6a1.rst @@ -562,8 +562,8 @@ shifts from ints to longs. .. nonce: mFw2O5 .. section: Core and Builtins -Tuple's tp_repr did not take into account the possibility of having a self- -referential tuple, which is possible from C code. Nor did object's tp_str +Tuple's tp_repr did not take into account the possibility of having a +self-referential tuple, which is possible from C code. Nor did object's tp_str consider that a type's tp_str could do something that could lead to an inifinite recursion. Py_ReprEnter() and Py_EnterRecursiveCall(), respectively, fixed the issues. @@ -1592,8 +1592,8 @@ fix a bug to avoid FileHandler throwing an exception in flush(). .. section: Library distutils' build command now uses different build directory when building -extension modules against versions of Python compiled with ``--with- -pydebug``. +extension modules against versions of Python compiled with +``--with-pydebug``. .. @@ -2070,8 +2070,8 @@ with --with-system-ffi. .. nonce: MPohFL .. section: Library -ctypes now does work on OS X when Python is built with --disable-toolbox- -glue. +ctypes now does work on OS X when Python is built with +``--disable-toolbox-glue``. .. @@ -5142,8 +5142,8 @@ platform. .. nonce: bwAdWN .. section: Build -don't add -L/usr/lib/pythonX.Y/config to the LDFLAGS returned by python- -config if Python was built with --enable-shared because that prevented the +don't add -L/usr/lib/pythonX.Y/config to the LDFLAGS returned by +python-config if Python was built with --enable-shared because that prevented the shared library from being used. .. diff --git a/Misc/NEWS.d/2.6a2.rst b/Misc/NEWS.d/2.6a2.rst index fe6cd26fdb1d..f7c6641f4e15 100644 --- a/Misc/NEWS.d/2.6a2.rst +++ b/Misc/NEWS.d/2.6a2.rst @@ -83,8 +83,8 @@ add Py3k warning for buffer(). With narrow Unicode builds, the unicode escape sequence \Uxxxxxxxx did not accept values outside the Basic Multilingual Plane. This affected raw unicode literals and the 'raw-unicode-escape' codec. Now UTF-16 surrogates -are generated in this case, like normal unicode literals and the 'unicode- -escape' codec. +are generated in this case, like normal unicode literals and the +'unicode-escape' codec. .. @@ -370,8 +370,8 @@ Add triangular distribution to the random module .. nonce: pMUClw .. section: Library -urllib2's auth handler now allows single-quoted realms in the WWW- -Authenticate header. +urllib2's auth handler now allows single-quoted realms in the +WWW-Authenticate header. .. diff --git a/Misc/NEWS.d/2.7.11rc1.rst b/Misc/NEWS.d/2.7.11rc1.rst index f995ed0aff1e..bba31329dedd 100644 --- a/Misc/NEWS.d/2.7.11rc1.rst +++ b/Misc/NEWS.d/2.7.11rc1.rst @@ -522,8 +522,8 @@ tarfile now tolerates number fields consisting of only whitespace. .. nonce: aAbWbQ .. section: Library -Restore semantic round-trip correctness in tokenize/untokenize for tab- -indented blocks. +Restore semantic round-trip correctness in tokenize/untokenize for +tab-indented blocks. .. @@ -866,8 +866,8 @@ them a 'sheet'. Patch by Mark Roseman. .. section: IDLE Enhance the initial html viewer now used for Idle Help. * Properly indent -fixed-pitch text (patch by Mark Roseman). * Give code snippet a very Sphinx- -like light blueish-gray background. * Re-use initial width and height set by +fixed-pitch text (patch by Mark Roseman). * Give code snippet a very +Sphinx-like light blueish-gray background. * Re-use initial width and height set by users for shell and editor. * When the Table of Contents (TOC) menu is used, put the section header at the top of the screen. diff --git a/Misc/NEWS.d/2.7.13rc1.rst b/Misc/NEWS.d/2.7.13rc1.rst index 26ffeea2b378..6bef454bcbe1 100644 --- a/Misc/NEWS.d/2.7.13rc1.rst +++ b/Misc/NEWS.d/2.7.13rc1.rst @@ -44,8 +44,8 @@ C-inherited Cython classes). .. nonce: RYbEGH .. section: Core and Builtins -Extra slash no longer added to sys.path components in case of empty compile- -time PYTHONPATH components. +Extra slash no longer added to sys.path components in case of empty +compile-time PYTHONPATH components. .. @@ -373,8 +373,8 @@ Fixed support of default root window in the Tix module. When parsing HTTP header fields, if an invalid line is encountered, skip it and continue parsing. Previously, no more header fields were parsed, which -could lead to fields for HTTP framing like Content-Length and Transfer- -Encoding being overlooked. +could lead to fields for HTTP framing like Content-Length and +Transfer-Encoding being overlooked. .. @@ -935,9 +935,9 @@ Fix clean target in freeze makefile (patch by Lisa Roach) .. section: Build Cause lack of llvm-profdata tool when using clang as required for PGO -linking to be a configure time error rather than make time when --with- -optimizations is enabled. Also improve our ability to find the llvm- -profdata tool on MacOS and some Linuxes. +linking to be a configure time error rather than make time when +``--with-optimizations`` is enabled. Also improve our ability to find the +llvm-profdata tool on MacOS and some Linuxes. .. diff --git a/Misc/NEWS.d/2.7.14rc1.rst b/Misc/NEWS.d/2.7.14rc1.rst index 462c03a9fc3f..cc74f22cef5f 100644 --- a/Misc/NEWS.d/2.7.14rc1.rst +++ b/Misc/NEWS.d/2.7.14rc1.rst @@ -66,8 +66,8 @@ LF. Patch by Dong-hee Na. .. nonce: -zJ7d8 .. section: Library -multiprocessing.Queue.get() with a timeout now polls its reader in non- -blocking mode if it succeeded to aquire the lock but the acquire took longer +multiprocessing.Queue.get() with a timeout now polls its reader in +non-blocking mode if it succeeded to aquire the lock but the acquire took longer than the timeout. .. diff --git a/Misc/NEWS.d/2.7.15rc1.rst b/Misc/NEWS.d/2.7.15rc1.rst index 1835bd1dfad6..a01bfd6b8f53 100644 --- a/Misc/NEWS.d/2.7.15rc1.rst +++ b/Misc/NEWS.d/2.7.15rc1.rst @@ -56,8 +56,8 @@ Upgrade expat copy from 2.2.0 to 2.2.1 to get fixes of multiple security vulnerabilities including: CVE-2017-9233 (External entity infinite loop DoS), CVE-2016-9063 (Integer overflow, re-fix), CVE-2016-0718 (Fix regression bugs from 2.2.0's fix to CVE-2016-0718) and CVE-2012-0876 -(Counter hash flooding with SipHash). Note: the CVE-2016-5300 (Use os- -specific entropy sources like getrandom) doesn't impact Python, since Python +(Counter hash flooding with SipHash). Note: the CVE-2016-5300 (Use +os-specific entropy sources like getrandom) doesn't impact Python, since Python already gets entropy from the OS to set the expat secret using ``XML_SetHashSalt()``. @@ -1329,8 +1329,8 @@ documentation. Patch by Matthias Bussonnier. Rewrite Comparisons section in the Expressions chapter of the language reference. Some of the details of comparing mixed types were incorrect or -ambiguous. Added default behaviour and consistency suggestions for user- -defined classes. Based on patch from Andy Maier. +ambiguous. Added default behaviour and consistency suggestions for +user-defined classes. Based on patch from Andy Maier. .. @@ -1493,8 +1493,8 @@ Fix -Wint-in-bool-context warnings in PyMem_MALLOC and PyMem_REALLOC macros .. section: Build Prevent unnecessary rebuilding of Python during ``make test``, ``make -install`` and some other make targets when configured with ``--enable- -optimizations``. +install`` and some other make targets when configured with +``--enable-optimizations``. .. diff --git a/Misc/NEWS.d/2.7.2rc1.rst b/Misc/NEWS.d/2.7.2rc1.rst index 0b6f7c02d216..8d55be5702a9 100644 --- a/Misc/NEWS.d/2.7.2rc1.rst +++ b/Misc/NEWS.d/2.7.2rc1.rst @@ -26,8 +26,8 @@ propagated. .. nonce: rUvlec .. section: Core and Builtins -Fix input() if it is interrupted by CTRL+d and then CTRL+c, clear the end- -of-file indicator after CTRL+d. +Fix input() if it is interrupted by CTRL+d and then CTRL+c, clear the +end-of-file indicator after CTRL+d. .. @@ -799,8 +799,8 @@ Allow mmap() to work on file sizes and offsets larger than 4GB, even on .. nonce: JAYw4l .. section: Library -In WeakSet, do not raise TypeErrors when testing for membership of non- -weakrefable objects. +In WeakSet, do not raise TypeErrors when testing for membership of +non-weakrefable objects. .. @@ -886,8 +886,8 @@ FSTAT. .. nonce: xpdEg8 .. section: Library -mmap should not segfault when a file is mapped using 0 as length and a non- -zero offset, and an attempt to read past the end of file is made (IndexError +mmap should not segfault when a file is mapped using 0 as length and a +non-zero offset, and an attempt to read past the end of file is made (IndexError is raised instead). Patch by Ross Lagerwall. .. @@ -1480,8 +1480,8 @@ includes a link to the installed documentation. .. nonce: BN3sYU .. section: Build -Allow Mac OS X installer builds to again work on 10.5 with the system- -provided Python. +Allow Mac OS X installer builds to again work on 10.5 with the +system-provided Python. .. diff --git a/Misc/NEWS.d/2.7.4rc1.rst b/Misc/NEWS.d/2.7.4rc1.rst index bb0bd5f94813..d0c615ba362b 100644 --- a/Misc/NEWS.d/2.7.4rc1.rst +++ b/Misc/NEWS.d/2.7.4rc1.rst @@ -1396,8 +1396,8 @@ subprocess.Popen.wait(). .. nonce: 9Mn07O .. section: Library -Fix a bug where zlib.decompressobj().flush() might try to access previously- -freed memory. Patch by Serhiy Storchaka. +Fix a bug where zlib.decompressobj().flush() might try to access +previously-freed memory. Patch by Serhiy Storchaka. .. @@ -1678,8 +1678,8 @@ Bohuslav Kabrda. .. nonce: 9gGqPw .. section: Library -In cmath and math modules, add workaround for platforms whose system- -supplied log1p function doesn't respect signs of zeros. +In cmath and math modules, add workaround for platforms whose +system-supplied log1p function doesn't respect signs of zeros. .. @@ -2441,8 +2441,8 @@ require an argument again. .. section: Library OS X Xcode 4 - improve support for universal extension modules In -particular, fix extension module build failures when trying to use 32-bit- -only installer Pythons on systems with Xcode 4 (currently OS X 10.8, 10.7, +particular, fix extension module build failures when trying to use +32-bit-only installer Pythons on systems with Xcode 4 (currently OS X 10.8, 10.7, and optionally 10.6). * Backport 3.3.0 fixes to 2.7 branch (for release in 2.7.4) * Since Xcode 4 removes ppc support, extension module builds now check for ppc compiler support and by default remove ppc and ppc64 archs diff --git a/Misc/NEWS.d/2.7.5.rst b/Misc/NEWS.d/2.7.5.rst index f2093128ba93..9cd483e8a3bb 100644 --- a/Misc/NEWS.d/2.7.5.rst +++ b/Misc/NEWS.d/2.7.5.rst @@ -246,8 +246,8 @@ module. Patch by Nickolai Zeldovich. .. nonce: E6rcrn .. section: Library -Add to webbrowser's browser list: xdg-open, gvfs-open, www-browser, x-www- -browser, chromium browsers, iceweasel, iceape. +Add to webbrowser's browser list: xdg-open, gvfs-open, www-browser, +x-www-browser, chromium browsers, iceweasel, iceape. .. diff --git a/Misc/NEWS.d/2.7.9rc1.rst b/Misc/NEWS.d/2.7.9rc1.rst index 45782bd9e576..fb58165221f0 100644 --- a/Misc/NEWS.d/2.7.9rc1.rst +++ b/Misc/NEWS.d/2.7.9rc1.rst @@ -1050,8 +1050,8 @@ special message when and only when there are failures. .. nonce: KAl7aO .. section: Build -Prevent possible segfaults and other random failures of python --generate- -posix-vars in pybuilddir.txt build target. +Prevent possible segfaults and other random failures of python +``--generate-posix-vars`` in pybuilddir.txt build target. .. diff --git a/Misc/NEWS.d/2.7a1.rst b/Misc/NEWS.d/2.7a1.rst index 5d0f99c623af..e2a28e0543e7 100644 --- a/Misc/NEWS.d/2.7a1.rst +++ b/Misc/NEWS.d/2.7a1.rst @@ -92,8 +92,8 @@ within Python are now correctly rounded. Places these conversions occur include: str for floats and complex numbers; the float and complex constructors; old-style and new-style numeric formatting; serialization and deserialization of floats and complex numbers using marshal, pickle and -json; parsing of float and imaginary literals in Python code; Decimal-to- -float conversion. +json; parsing of float and imaginary literals in Python code; +Decimal-to-float conversion. The conversions use a Python-adapted version of David Gay's well-known dtoa.c, providing correctly-rounded strtod and dtoa C functions. This code @@ -5647,8 +5647,8 @@ trailing 0 in the version number. .. nonce: c2vdqn .. section: Tests -Moved tests involving loading tk from Lib/test/test_tcl to Lib/lib- -tk/test/test_tkinter/test_loadtk. With this, these tests demonstrate the +Moved tests involving loading tk from Lib/test/test_tcl to +Lib/lib-tk/test/test_tkinter/test_loadtk. With this, these tests demonstrate the same behaviour as test_ttkguionly (and now also test_tk) which is to skip the tests if DISPLAY is defined but can't be used. diff --git a/Misc/NEWS.d/2.7a2.rst b/Misc/NEWS.d/2.7a2.rst index fa1308116864..d453e96f8e8a 100644 --- a/Misc/NEWS.d/2.7a2.rst +++ b/Misc/NEWS.d/2.7a2.rst @@ -314,8 +314,8 @@ logging: Fix bug in Unicode encoding fallback. .. nonce: oAWtv2 .. section: Library -Fixed IMAP4_SSL hang when the IMAP server response is missing proper end-of- -line termination. +Fixed IMAP4_SSL hang when the IMAP server response is missing proper +end-of-line termination. .. diff --git a/Misc/NEWS.d/2.7b1.rst b/Misc/NEWS.d/2.7b1.rst index cfa710ed8c55..9e096ecaa581 100644 --- a/Misc/NEWS.d/2.7b1.rst +++ b/Misc/NEWS.d/2.7b1.rst @@ -60,8 +60,8 @@ Raise a TypeError when trying to delete a T_STRING_INPLACE struct member. .. nonce: ZEBSAJ .. section: Core and Builtins -Issue a PendingDeprecationWarning if object.__format__ is called with a non- -empty format string. This is an effort to future-proof user code. If a +Issue a PendingDeprecationWarning if object.__format__ is called with a +non-empty format string. This is an effort to future-proof user code. If a derived class does not currently implement __format__ but later adds its own __format__, it would most likely break user code that had supplied a format string. This will be changed to a DeprecationWarning in Python 3.3 and it @@ -201,8 +201,8 @@ the specification of rich comparisons. .. nonce: nshtA2 .. section: Library -The functools module also adds cmp_to_key() as a tool to transition old- -style comparison functions to new-style key-functions. +The functools module also adds cmp_to_key() as a tool to transition +old-style comparison functions to new-style key-functions. .. diff --git a/Misc/NEWS.d/2.7b2.rst b/Misc/NEWS.d/2.7b2.rst index caa336b7427e..acc395bd1384 100644 --- a/Misc/NEWS.d/2.7b2.rst +++ b/Misc/NEWS.d/2.7b2.rst @@ -13,8 +13,8 @@ Run Clang 2.7's static analyzer for ``Objects/`` and ``Python/``. .. nonce: 6FLjC9 .. section: Core and Builtins -Fix inconsistency in range function argument processing: any non-float non- -integer argument is now converted to an integer (if possible) using its +Fix inconsistency in range function argument processing: any non-float +non-integer argument is now converted to an integer (if possible) using its __int__ method. Previously, only small arguments were treated this way; larger arguments (those whose __int__ was outside the range of a C long) would produce a TypeError. diff --git a/Misc/NEWS.d/2.7rc1.rst b/Misc/NEWS.d/2.7rc1.rst index 1984c09a6e85..18578b5037ed 100644 --- a/Misc/NEWS.d/2.7rc1.rst +++ b/Misc/NEWS.d/2.7rc1.rst @@ -98,8 +98,8 @@ in a framework build on MacOSX 10.5 or earlier. A new C API function, :cfunc:`PySys_SetArgvEx`, allows embedders of the interpreter to set sys.argv without also modifying sys.path. This helps fix -`CVE-2008-5983 <http://cve.mitre.org/cgi- -bin/cvename.cgi?name=CVE-2008-5983>`_. +`CVE-2008-5983 +<http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2008-5983>`_. .. From webhook-mailer at python.org Tue May 22 09:03:21 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 22 May 2018 13:03:21 -0000 Subject: [Python-checkins] bpo-30877: Fix clearing a cache in the the JSON decoder. (GH-7048) Message-ID: <mailman.13.1526994203.18020.python-checkins@python.org> https://github.com/python/cpython/commit/25fd6cc5b0ad311bb771ae47ae8173417730bb6a commit: 25fd6cc5b0ad311bb771ae47ae8173417730bb6a branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-22T06:03:10-07:00 summary: bpo-30877: Fix clearing a cache in the the JSON decoder. (GH-7048) (cherry picked from commit ae00fb1d4f38ea1803b10d798564740adcdad63e) Co-authored-by: Serhiy Storchaka <storchaka at gmail.com> files: A Misc/NEWS.d/next/Library/2018-05-22-13-05-12.bpo-30877.JZEGjI.rst M Lib/json/scanner.py M Lib/test/test_json/test_decode.py diff --git a/Lib/json/scanner.py b/Lib/json/scanner.py index c451ebab5842..7a61cfc2d24d 100644 --- a/Lib/json/scanner.py +++ b/Lib/json/scanner.py @@ -68,6 +68,6 @@ def scan_once(string, idx): finally: memo.clear() - return _scan_once + return scan_once make_scanner = c_make_scanner or py_make_scanner diff --git a/Lib/test/test_json/test_decode.py b/Lib/test/test_json/test_decode.py index d84ef7da2446..fdb9e62124ec 100644 --- a/Lib/test/test_json/test_decode.py +++ b/Lib/test/test_json/test_decode.py @@ -58,7 +58,9 @@ def check_keys_reuse(self, source, loads): def test_keys_reuse(self): s = '[{"a_key": 1, "b_\xe9": 2}, {"a_key": 3, "b_\xe9": 4}]' self.check_keys_reuse(s, self.loads) - self.check_keys_reuse(s, self.json.decoder.JSONDecoder().decode) + decoder = self.json.decoder.JSONDecoder() + self.check_keys_reuse(s, decoder.decode) + self.assertFalse(decoder.memo) def test_extra_data(self): s = '[1, 2, 3]5' diff --git a/Misc/NEWS.d/next/Library/2018-05-22-13-05-12.bpo-30877.JZEGjI.rst b/Misc/NEWS.d/next/Library/2018-05-22-13-05-12.bpo-30877.JZEGjI.rst new file mode 100644 index 000000000000..4be0fae4ecb6 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-22-13-05-12.bpo-30877.JZEGjI.rst @@ -0,0 +1,3 @@ +Fixed a bug in the Python implementation of the JSON decoder that prevented +the cache of parsed strings from clearing after finishing the decoding. +Based on patch by c-fos. From webhook-mailer at python.org Tue May 22 09:26:53 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 22 May 2018 13:26:53 -0000 Subject: [Python-checkins] bpo-30877: Fix clearing a cache in the the JSON decoder. (GH-7048) Message-ID: <mailman.14.1526995615.18020.python-checkins@python.org> https://github.com/python/cpython/commit/2baee0aa77055755ac50e92e64bbccfea4108621 commit: 2baee0aa77055755ac50e92e64bbccfea4108621 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-22T06:26:43-07:00 summary: bpo-30877: Fix clearing a cache in the the JSON decoder. (GH-7048) (cherry picked from commit ae00fb1d4f38ea1803b10d798564740adcdad63e) Co-authored-by: Serhiy Storchaka <storchaka at gmail.com> files: A Misc/NEWS.d/next/Library/2018-05-22-13-05-12.bpo-30877.JZEGjI.rst M Lib/json/scanner.py M Lib/test/test_json/test_decode.py diff --git a/Lib/json/scanner.py b/Lib/json/scanner.py index 86426cde1a72..6e19ca633168 100644 --- a/Lib/json/scanner.py +++ b/Lib/json/scanner.py @@ -68,6 +68,6 @@ def scan_once(string, idx): finally: memo.clear() - return _scan_once + return scan_once make_scanner = c_make_scanner or py_make_scanner diff --git a/Lib/test/test_json/test_decode.py b/Lib/test/test_json/test_decode.py index 7e568be40974..738f109fe68d 100644 --- a/Lib/test/test_json/test_decode.py +++ b/Lib/test/test_json/test_decode.py @@ -58,7 +58,9 @@ def check_keys_reuse(self, source, loads): def test_keys_reuse(self): s = '[{"a_key": 1, "b_\xe9": 2}, {"a_key": 3, "b_\xe9": 4}]' self.check_keys_reuse(s, self.loads) - self.check_keys_reuse(s, self.json.decoder.JSONDecoder().decode) + decoder = self.json.decoder.JSONDecoder() + self.check_keys_reuse(s, decoder.decode) + self.assertFalse(decoder.memo) def test_extra_data(self): s = '[1, 2, 3]5' diff --git a/Misc/NEWS.d/next/Library/2018-05-22-13-05-12.bpo-30877.JZEGjI.rst b/Misc/NEWS.d/next/Library/2018-05-22-13-05-12.bpo-30877.JZEGjI.rst new file mode 100644 index 000000000000..4be0fae4ecb6 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-22-13-05-12.bpo-30877.JZEGjI.rst @@ -0,0 +1,3 @@ +Fixed a bug in the Python implementation of the JSON decoder that prevented +the cache of parsed strings from clearing after finishing the decoding. +Based on patch by c-fos. From webhook-mailer at python.org Tue May 22 09:37:28 2018 From: webhook-mailer at python.org (Victor Stinner) Date: Tue, 22 May 2018 13:37:28 -0000 Subject: [Python-checkins] [2.7] bpo-33518: Add PEP entry to documentation glossary (GH-6860). (#6936) Message-ID: <mailman.15.1526996251.18020.python-checkins@python.org> https://github.com/python/cpython/commit/8cbde8a43769641373a681af4b0d72944af43f95 commit: 8cbde8a43769641373a681af4b0d72944af43f95 branch: 2.7 author: Andr?s Delfino <adelfino at gmail.com> committer: Victor Stinner <vstinner at redhat.com> date: 2018-05-22T15:37:24+02:00 summary: [2.7] bpo-33518: Add PEP entry to documentation glossary (GH-6860). (#6936) (cherry picked from commit d5f144260886959c1fe06bc4506a23fd10f92348) Co-authored-by: Andr?s Delfino <adelfino at gmail.com> files: M Doc/glossary.rst diff --git a/Doc/glossary.rst b/Doc/glossary.rst index cbd1237f8e5f..feb40a88bbed 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -625,6 +625,21 @@ Glossary :ref:`the difference between arguments and parameters <faq-argument-vs-parameter>`, and the :ref:`function` section. + PEP + Python Enhancement Proposal. A PEP is a design document + providing information to the Python community, or describing a new + feature for Python or its processes or environment. PEPs should + provide a concise technical specification and a rationale for proposed + features. + + PEPs are intended to be the primary mechanisms for proposing major new + features, for collecting community input on an issue, and for documenting + the design decisions that have gone into Python. The PEP author is + responsible for building consensus within the community and documenting + dissenting opinions. + + See :pep:`1`. + positional argument See :term:`argument`. From webhook-mailer at python.org Tue May 22 13:24:08 2018 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Tue, 22 May 2018 17:24:08 -0000 Subject: [Python-checkins] Improve comments in test_idle.py. (GH-7057) Message-ID: <mailman.16.1527009849.18020.python-checkins@python.org> https://github.com/python/cpython/commit/2a6d5da1d35b4a5342f6347d75298e2bec8194ed commit: 2a6d5da1d35b4a5342f6347d75298e2bec8194ed branch: master author: Terry Jan Reedy <tjreedy at udel.edu> committer: GitHub <noreply at github.com> date: 2018-05-22T13:24:04-04:00 summary: Improve comments in test_idle.py. (GH-7057) files: M Lib/test/test_idle.py diff --git a/Lib/test/test_idle.py b/Lib/test/test_idle.py index 31fffd94a08f..8bc01deaa338 100644 --- a/Lib/test/test_idle.py +++ b/Lib/test/test_idle.py @@ -1,18 +1,20 @@ import unittest from test.support import import_module -# Skip test if _tkinter wasn't built, if idlelib is missing, -# or if tcl/tk is not the 8.5+ needed for ttk widgets. -tk = import_module('tkinter') # imports _tkinter +# Skip test_idle if _tkinter wasn't built, if tkinter is missing, +# if tcl/tk is not the 8.5+ needed for ttk widgets, +# or if idlelib is missing (not installed). +tk = import_module('tkinter') # Also imports _tkinter. if tk.TkVersion < 8.5: raise unittest.SkipTest("IDLE requires tk 8.5 or later.") idlelib = import_module('idlelib') -# Before test imports, tell IDLE to avoid changing the environment. +# Before importing and executing more of idlelib, +# tell IDLE to avoid changing the environment. idlelib.testing = True -# unittest.main and test.libregrtest.runtest.runtest_inner -# call load_tests, when present, to discover tests to run. +# Unittest.main and test.libregrtest.runtest.runtest_inner +# call load_tests, when present here, to discover tests to run. from idlelib.idle_test import load_tests if __name__ == '__main__': From webhook-mailer at python.org Tue May 22 13:32:03 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Tue, 22 May 2018 17:32:03 -0000 Subject: [Python-checkins] bpo-33592: Document the C API in PEP 567 (contextvars) (GH-7033) Message-ID: <mailman.17.1527010326.18020.python-checkins@python.org> https://github.com/python/cpython/commit/b2f5f59ae15564b991f3ca4850e6ad28d9faacbc commit: b2f5f59ae15564b991f3ca4850e6ad28d9faacbc branch: master author: Elvis Pranskevichus <elvis at magic.io> committer: Yury Selivanov <yury at magic.io> date: 2018-05-22T13:31:56-04:00 summary: bpo-33592: Document the C API in PEP 567 (contextvars) (GH-7033) files: A Doc/c-api/contextvars.rst M Doc/c-api/concrete.rst M Doc/whatsnew/3.7.rst diff --git a/Doc/c-api/concrete.rst b/Doc/c-api/concrete.rst index 47dab81891d3..9558a4a583cb 100644 --- a/Doc/c-api/concrete.rst +++ b/Doc/c-api/concrete.rst @@ -113,5 +113,5 @@ Other Objects capsule.rst gen.rst coro.rst + contextvars.rst datetime.rst - diff --git a/Doc/c-api/contextvars.rst b/Doc/c-api/contextvars.rst new file mode 100644 index 000000000000..4c33ba4f9944 --- /dev/null +++ b/Doc/c-api/contextvars.rst @@ -0,0 +1,125 @@ +.. highlightlang:: c + +.. _contextvarsobjects: + +Context Variables Objects +------------------------- + +.. versionadded:: 3.7 + +This section details the public C API for the :mod:`contextvars` module. + +.. c:type:: PyContext + + The C structure used to represent a :class:`contextvars.Context` + object. + +.. c:type:: PyContextVar + + The C structure used to represent a :class:`contextvars.ContextVar` + object. + +.. c:type:: PyContextToken + + The C structure used to represent a :class:`contextvars.Token` object. + +.. c:var:: PyTypeObject PyContext_Type + + The type object representing the *context* type. + +.. c:var:: PyTypeObject PyContextVar_Type + + The type object representing the *context variable* type. + +.. c:var:: PyTypeObject PyContextToken_Type + + The type object representing the *context variable token* type. + + +Type-check macros: + +.. c:function:: int PyContext_CheckExact(PyObject *o) + + Return true if *o* is of type :c:data:`PyContext_Type`. *o* must not be + *NULL*. This function always succeeds. + +.. c:function:: int PyContextVar_CheckExact(PyObject *o) + + Return true if *o* is of type :c:data:`PyContextVar_Type`. *o* must not be + *NULL*. This function always succeeds. + +.. c:function:: int PyContextToken_CheckExact(PyObject *o) + + Return true if *o* is of type :c:data:`PyContextToken_Type`. + *o* must not be *NULL*. This function always succeeds. + + +Context object management functions: + +.. c:function:: PyContext *PyContext_New(void) + + Create a new empty context object. Returns ``NULL`` if an error + has occurred. + +.. c:function:: PyContext *PyContext_Copy(PyContext *ctx) + + Create a shallow copy of the passed *ctx* context object. + Returns ``NULL`` if an error has occurred. + +.. c:function:: PyContext *PyContext_CopyCurrent(void) + + Create a shallow copy of the current thread context. + Returns ``NULL`` if an error has occurred. + +.. c:function:: int PyContext_Enter(PyContext *ctx) + + Set *ctx* as the current context for the current thread. + Returns ``0`` on success, and ``-1`` on error. + +.. c:function:: int PyContext_Exit(PyContext *ctx) + + Deactivate the *ctx* context and restore the previous context as the + current context for the current thread. Returns ``0`` on success, + and ``-1`` on error. + +.. c:function:: int PyContext_ClearFreeList() + + Clear the context variable free list. Return the total number of + freed items. This function always succeeds. + + +Context variable functions: + +.. c:function:: PyContextVar *PyContextVar_New(const char *name, PyObject *def) + + Create a new ``ContextVar`` object. The *name* parameter is used + for introspection and debug purposes. The *def* parameter may optionally + specify the default value for the context variable. If an error has + occurred, this function returns ``NULL``. + +.. c:function:: int PyContextVar_Get(PyContextVar *var, PyObject *default_value, PyObject **value) + + Get the value of a context variable. Returns ``-1`` if an error has + occurred during lookup, and ``0`` if no error occurred, whether or not + a value was found. + + If the context variable was found, *value* will be a pointer to it. + If the context variable was *not* found, *value* will point to: + + - *default_value*, if not ``NULL``; + - the default value of *var*, if not ``NULL``; + - ``NULL`` + + If the value was found, the function will create a new reference to it. + +.. c:function:: PyContextToken *PyContextVar_Set(PyContextVar *var, PyObject *value) + + Set the value of *var* to *value* in the current context. Returns a + pointer to a :c:type:`PyContextToken` object, or ``NULL`` if an error + has occurred. + +.. c:function:: int PyContextVar_Reset(PyContextVar *var, PyContextToken *token) + + Reset the state of the *var* context variable to that it was in before + :c:func:`PyContextVar_Set` that returned the *token* was called. + This function returns ``0`` on success and ``-1`` on error. diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 8324be801491..ac697191b50d 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -515,7 +515,8 @@ New Modules contextvars ----------- -The new :mod:`contextvars` module and a set of new C APIs introduce +The new :mod:`contextvars` module and a set of +:ref:`new C APIs <contextvarsobjects>` introduce support for *context variables*. Context variables are conceptually similar to thread-local variables. Unlike TLS, context variables support asynchronous code correctly. @@ -1543,6 +1544,9 @@ A new API for thread-local storage has been implemented. See :ref:`thread-specific-storage-api` for a complete reference. (Contributed by Masayuki Yamamoto in :issue:`25658`.) +The new :ref:`context variables <whatsnew37-pep567>` functionality +exposes a number of :ref:`new C APIs <contextvarsobjects>`. + The new :c:func:`PyImport_GetModule` function returns the previously imported module with the given name. (Contributed by Eric Snow in :issue:`28411`.) From webhook-mailer at python.org Tue May 22 13:43:58 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 22 May 2018 17:43:58 -0000 Subject: [Python-checkins] Improve comments in test_idle.py. (GH-7057) Message-ID: <mailman.18.1527011039.18020.python-checkins@python.org> https://github.com/python/cpython/commit/ca6d7aee91930363e7a1fcc1535d1be1b8debdea commit: ca6d7aee91930363e7a1fcc1535d1be1b8debdea branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-22T10:43:55-07:00 summary: Improve comments in test_idle.py. (GH-7057) (cherry picked from commit 2a6d5da1d35b4a5342f6347d75298e2bec8194ed) Co-authored-by: Terry Jan Reedy <tjreedy at udel.edu> files: M Lib/test/test_idle.py diff --git a/Lib/test/test_idle.py b/Lib/test/test_idle.py index 31fffd94a08f..8bc01deaa338 100644 --- a/Lib/test/test_idle.py +++ b/Lib/test/test_idle.py @@ -1,18 +1,20 @@ import unittest from test.support import import_module -# Skip test if _tkinter wasn't built, if idlelib is missing, -# or if tcl/tk is not the 8.5+ needed for ttk widgets. -tk = import_module('tkinter') # imports _tkinter +# Skip test_idle if _tkinter wasn't built, if tkinter is missing, +# if tcl/tk is not the 8.5+ needed for ttk widgets, +# or if idlelib is missing (not installed). +tk = import_module('tkinter') # Also imports _tkinter. if tk.TkVersion < 8.5: raise unittest.SkipTest("IDLE requires tk 8.5 or later.") idlelib = import_module('idlelib') -# Before test imports, tell IDLE to avoid changing the environment. +# Before importing and executing more of idlelib, +# tell IDLE to avoid changing the environment. idlelib.testing = True -# unittest.main and test.libregrtest.runtest.runtest_inner -# call load_tests, when present, to discover tests to run. +# Unittest.main and test.libregrtest.runtest.runtest_inner +# call load_tests, when present here, to discover tests to run. from idlelib.idle_test import load_tests if __name__ == '__main__': From webhook-mailer at python.org Tue May 22 13:58:05 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 22 May 2018 17:58:05 -0000 Subject: [Python-checkins] bpo-33592: Document the C API in PEP 567 (contextvars) (GH-7033) Message-ID: <mailman.19.1527011887.18020.python-checkins@python.org> https://github.com/python/cpython/commit/afec2d583a06849c5080c6cd40266743c8e04b3e commit: afec2d583a06849c5080c6cd40266743c8e04b3e branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-22T10:58:01-07:00 summary: bpo-33592: Document the C API in PEP 567 (contextvars) (GH-7033) (cherry picked from commit b2f5f59ae15564b991f3ca4850e6ad28d9faacbc) Co-authored-by: Elvis Pranskevichus <elvis at magic.io> files: A Doc/c-api/contextvars.rst M Doc/c-api/concrete.rst M Doc/whatsnew/3.7.rst diff --git a/Doc/c-api/concrete.rst b/Doc/c-api/concrete.rst index 47dab81891d3..9558a4a583cb 100644 --- a/Doc/c-api/concrete.rst +++ b/Doc/c-api/concrete.rst @@ -113,5 +113,5 @@ Other Objects capsule.rst gen.rst coro.rst + contextvars.rst datetime.rst - diff --git a/Doc/c-api/contextvars.rst b/Doc/c-api/contextvars.rst new file mode 100644 index 000000000000..4c33ba4f9944 --- /dev/null +++ b/Doc/c-api/contextvars.rst @@ -0,0 +1,125 @@ +.. highlightlang:: c + +.. _contextvarsobjects: + +Context Variables Objects +------------------------- + +.. versionadded:: 3.7 + +This section details the public C API for the :mod:`contextvars` module. + +.. c:type:: PyContext + + The C structure used to represent a :class:`contextvars.Context` + object. + +.. c:type:: PyContextVar + + The C structure used to represent a :class:`contextvars.ContextVar` + object. + +.. c:type:: PyContextToken + + The C structure used to represent a :class:`contextvars.Token` object. + +.. c:var:: PyTypeObject PyContext_Type + + The type object representing the *context* type. + +.. c:var:: PyTypeObject PyContextVar_Type + + The type object representing the *context variable* type. + +.. c:var:: PyTypeObject PyContextToken_Type + + The type object representing the *context variable token* type. + + +Type-check macros: + +.. c:function:: int PyContext_CheckExact(PyObject *o) + + Return true if *o* is of type :c:data:`PyContext_Type`. *o* must not be + *NULL*. This function always succeeds. + +.. c:function:: int PyContextVar_CheckExact(PyObject *o) + + Return true if *o* is of type :c:data:`PyContextVar_Type`. *o* must not be + *NULL*. This function always succeeds. + +.. c:function:: int PyContextToken_CheckExact(PyObject *o) + + Return true if *o* is of type :c:data:`PyContextToken_Type`. + *o* must not be *NULL*. This function always succeeds. + + +Context object management functions: + +.. c:function:: PyContext *PyContext_New(void) + + Create a new empty context object. Returns ``NULL`` if an error + has occurred. + +.. c:function:: PyContext *PyContext_Copy(PyContext *ctx) + + Create a shallow copy of the passed *ctx* context object. + Returns ``NULL`` if an error has occurred. + +.. c:function:: PyContext *PyContext_CopyCurrent(void) + + Create a shallow copy of the current thread context. + Returns ``NULL`` if an error has occurred. + +.. c:function:: int PyContext_Enter(PyContext *ctx) + + Set *ctx* as the current context for the current thread. + Returns ``0`` on success, and ``-1`` on error. + +.. c:function:: int PyContext_Exit(PyContext *ctx) + + Deactivate the *ctx* context and restore the previous context as the + current context for the current thread. Returns ``0`` on success, + and ``-1`` on error. + +.. c:function:: int PyContext_ClearFreeList() + + Clear the context variable free list. Return the total number of + freed items. This function always succeeds. + + +Context variable functions: + +.. c:function:: PyContextVar *PyContextVar_New(const char *name, PyObject *def) + + Create a new ``ContextVar`` object. The *name* parameter is used + for introspection and debug purposes. The *def* parameter may optionally + specify the default value for the context variable. If an error has + occurred, this function returns ``NULL``. + +.. c:function:: int PyContextVar_Get(PyContextVar *var, PyObject *default_value, PyObject **value) + + Get the value of a context variable. Returns ``-1`` if an error has + occurred during lookup, and ``0`` if no error occurred, whether or not + a value was found. + + If the context variable was found, *value* will be a pointer to it. + If the context variable was *not* found, *value* will point to: + + - *default_value*, if not ``NULL``; + - the default value of *var*, if not ``NULL``; + - ``NULL`` + + If the value was found, the function will create a new reference to it. + +.. c:function:: PyContextToken *PyContextVar_Set(PyContextVar *var, PyObject *value) + + Set the value of *var* to *value* in the current context. Returns a + pointer to a :c:type:`PyContextToken` object, or ``NULL`` if an error + has occurred. + +.. c:function:: int PyContextVar_Reset(PyContextVar *var, PyContextToken *token) + + Reset the state of the *var* context variable to that it was in before + :c:func:`PyContextVar_Set` that returned the *token* was called. + This function returns ``0`` on success and ``-1`` on error. diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 8324be801491..ac697191b50d 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -515,7 +515,8 @@ New Modules contextvars ----------- -The new :mod:`contextvars` module and a set of new C APIs introduce +The new :mod:`contextvars` module and a set of +:ref:`new C APIs <contextvarsobjects>` introduce support for *context variables*. Context variables are conceptually similar to thread-local variables. Unlike TLS, context variables support asynchronous code correctly. @@ -1543,6 +1544,9 @@ A new API for thread-local storage has been implemented. See :ref:`thread-specific-storage-api` for a complete reference. (Contributed by Masayuki Yamamoto in :issue:`25658`.) +The new :ref:`context variables <whatsnew37-pep567>` functionality +exposes a number of :ref:`new C APIs <contextvarsobjects>`. + The new :c:func:`PyImport_GetModule` function returns the previously imported module with the given name. (Contributed by Eric Snow in :issue:`28411`.) From webhook-mailer at python.org Tue May 22 13:59:45 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Tue, 22 May 2018 17:59:45 -0000 Subject: [Python-checkins] Add missed details of the C API introduced in 3.7. (GH-7047) Message-ID: <mailman.20.1527011986.18020.python-checkins@python.org> https://github.com/python/cpython/commit/4e29f566e8821c09d8274eadcdd355e8b1284b8b commit: 4e29f566e8821c09d8274eadcdd355e8b1284b8b branch: master author: Serhiy Storchaka <storchaka at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-22T20:59:42+03:00 summary: Add missed details of the C API introduced in 3.7. (GH-7047) * Set the limited API version for PyImport_GetModule and PyOS_*Fork functions. * Add PyImport_GetModule and Py_UTF8Mode in PC/python3.def. * Add several functions in Doc/data/refcounts.dat. files: M Doc/data/refcounts.dat M Include/import.h M Include/intrcheck.h M PC/python3.def diff --git a/Doc/data/refcounts.dat b/Doc/data/refcounts.dat index f403c16547c4..62cc93832783 100644 --- a/Doc/data/refcounts.dat +++ b/Doc/data/refcounts.dat @@ -152,6 +152,47 @@ PyComplex_ImagAsDouble:PyObject*:op:0: PyComplex_RealAsDouble:double::: PyComplex_RealAsDouble:PyObject*:op:0: +PyContext_CheckExact:int::: +PyContext_CheckExact:PyObject*:o:0: + +PyContext_ClearFreeList:int::: + +PyContext_Copy:PyObject*::+1: +PyContext_Copy:PyObject*:ctx:0: + +PyContext_CopyCurrent:PyObject*::+1: + +PyContext_Enter:int::: +PyContext_Enter:PyObject*:ctx:+1: + +PyContext_Exit:int::: +PyContext_Exit:PyObject*:ctx:-1: + +PyContext_New:PyObject*::+1: + +PyContextToken_CheckExact:int::: +PyContextToken_CheckExact:PyObject*:o:0: + +PyContextVar_CheckExact:int::: +PyContextVar_CheckExact:PyObject*:o:0: + +PyContextVar_Get:int::: +PyContextVar_Get:PyObject*:var:0: +PyContextVar_Get:PyObject*:default_value:0: +PyContextVar_Get:PyObject**:value:+1:??? + +PyContextVar_New:PyObject*::+1: +PyContextVar_New:const char*:name:: +PyContextVar_New:PyObject*:def:+1: + +PyContextVar_Set:PyObject*::+1: +PyContextVar_Set:PyObject*:var:0: +PyContextVar_Set:PyObject*:value:+1: + +PyContextVar_Reset:int::: +PyContextVar_Reset:PyObject*:var:0: +PyContextVar_Reset:PyObject*:token:-1: + PyDate_FromDate:PyObject*::+1: PyDate_FromDate:int:year:: PyDate_FromDate:int:month:: @@ -541,6 +582,9 @@ PyImport_ExecCodeModuleEx:const char*:pathname:: PyImport_GetMagicNumber:long::: +PyImport_GetModule:PyObject*::+1: +PyImport_GetModule:PyObject*:name:0: + PyImport_GetModuleDict:PyObject*::0: PyImport_Import:PyObject*::+1: @@ -605,6 +649,9 @@ PyInterpreterState_Clear:PyInterpreterState*:interp:: PyInterpreterState_Delete:void::: PyInterpreterState_Delete:PyInterpreterState*:interp:: +PyInterpreterState_GetID:int64_t::: +PyInterpreterState_GetID:PyInterpreterState*:interp:: + PyInterpreterState_New:PyInterpreterState*::: PyIter_Check:int:o:0: @@ -933,6 +980,14 @@ PyNumber_Xor:PyObject*:o2:0: PyObject_AsFileDescriptor:int::: PyObject_AsFileDescriptor:PyObject*:o:0: +PyOS_AfterFork:void::: + +PyOS_AfterFork_Child:void::: + +PyOS_AfterFork_Parent:void::: + +PyOS_BeforeFork:void::: + PyOS_FSPath:PyObject*::+1: PyOS_FSPath:PyObject*:path:0: @@ -1252,6 +1307,12 @@ PySet_Pop:PyObject*:set:0: PySet_Size:int::: PySet_Size:PyObject*:anyset:0: +PySlice_AdjustIndices:Py_ssize_t::: +PySlice_AdjustIndices:Py_ssize_t:length:: +PySlice_AdjustIndices:Py_ssize_t*:start:: +PySlice_AdjustIndices:Py_ssize_t*:stop:: +PySlice_AdjustIndices:Py_ssize_t*:step:: + PySlice_Check:int::: PySlice_Check:PyObject*:ob:0: @@ -1260,6 +1321,12 @@ PySlice_New:PyObject*:start:0: PySlice_New:PyObject*:stop:0: PySlice_New:PyObject*:step:0: +PySlice_Unpack:int::: +PySlice_Unpack:PyObject*:slice:0: +PySlice_Unpack:Py_ssize_t*:start:: +PySlice_Unpack:Py_ssize_t*:stop:: +PySlice_Unpack:Py_ssize_t*:step:: + PyString_AS_STRING:const char*::: PyString_AS_STRING:PyObject*:string:0: @@ -1410,6 +1477,15 @@ PyTime_FromTime:int:minute:: PyTime_FromTime:int:second:: PyTime_FromTime:int:usecond:: +PyTraceMalloc_Track:int::: +PyTraceMalloc_Track:unsigned int:domain:: +PyTraceMalloc_Track:uintptr_t:ptr:: +PyTraceMalloc_Track:size_t:size:: + +PyTraceMalloc_Untrack:int::: +PyTraceMalloc_Untrack:unsigned int:domain:: +PyTraceMalloc_Untrack:uintptr_t:ptr:: + PyTuple_Check:int::: PyTuple_Check:PyObject*:p:0: diff --git a/Include/import.h b/Include/import.h index ac3fc3bd28c0..13f32a1004cf 100644 --- a/Include/import.h +++ b/Include/import.h @@ -38,7 +38,9 @@ PyAPI_FUNC(PyObject *) PyImport_ExecCodeModuleObject( ); #endif PyAPI_FUNC(PyObject *) PyImport_GetModuleDict(void); +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03070000 PyAPI_FUNC(PyObject *) PyImport_GetModule(PyObject *name); +#endif #ifndef Py_LIMITED_API PyAPI_FUNC(int) _PyImport_IsInitialized(PyInterpreterState *); PyAPI_FUNC(PyObject *) _PyImport_GetModuleId(struct _Py_Identifier *name); diff --git a/Include/intrcheck.h b/Include/intrcheck.h index 944968bd1171..2e17336ca659 100644 --- a/Include/intrcheck.h +++ b/Include/intrcheck.h @@ -8,10 +8,12 @@ extern "C" { PyAPI_FUNC(int) PyOS_InterruptOccurred(void); PyAPI_FUNC(void) PyOS_InitInterrupts(void); #ifdef HAVE_FORK +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03070000 PyAPI_FUNC(void) PyOS_BeforeFork(void); PyAPI_FUNC(void) PyOS_AfterFork_Parent(void); PyAPI_FUNC(void) PyOS_AfterFork_Child(void); #endif +#endif /* Deprecated, please use PyOS_AfterFork_Child() instead */ PyAPI_FUNC(void) PyOS_AfterFork(void) Py_DEPRECATED(3.7); diff --git a/PC/python3.def b/PC/python3.def index fb36f300ae65..48a2d07aab13 100644 --- a/PC/python3.def +++ b/PC/python3.def @@ -284,6 +284,7 @@ EXPORTS PyImport_GetImporter=python38.PyImport_GetImporter PyImport_GetMagicNumber=python38.PyImport_GetMagicNumber PyImport_GetMagicTag=python38.PyImport_GetMagicTag + PyImport_GetModule=python38.PyImport_GetModule PyImport_GetModuleDict=python38.PyImport_GetModuleDict PyImport_Import=python38.PyImport_Import PyImport_ImportFrozenModule=python38.PyImport_ImportFrozenModule @@ -757,6 +758,7 @@ EXPORTS Py_SetPythonHome=python38.Py_SetPythonHome Py_SetRecursionLimit=python38.Py_SetRecursionLimit Py_SymtableString=python38.Py_SymtableString + Py_UTF8Mode=python38.Py_UTF8Mode DATA Py_VaBuildValue=python38.Py_VaBuildValue _PyArg_ParseTupleAndKeywords_SizeT=python38._PyArg_ParseTupleAndKeywords_SizeT _PyArg_ParseTuple_SizeT=python38._PyArg_ParseTuple_SizeT From webhook-mailer at python.org Tue May 22 14:34:21 2018 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Tue, 22 May 2018 18:34:21 -0000 Subject: [Python-checkins] [3.6] Improve comments in test_idle.py. (GH-7057) (GH-7060) Message-ID: <mailman.21.1527014062.18020.python-checkins@python.org> https://github.com/python/cpython/commit/32adddb65e6c7ba482812bddf8e87fe58ee4bcc4 commit: 32adddb65e6c7ba482812bddf8e87fe58ee4bcc4 branch: 3.6 author: Terry Jan Reedy <tjreedy at udel.edu> committer: GitHub <noreply at github.com> date: 2018-05-22T14:34:18-04:00 summary: [3.6] Improve comments in test_idle.py. (GH-7057) (GH-7060) (cherry picked from commit 2a6d5da) files: M Lib/test/test_idle.py diff --git a/Lib/test/test_idle.py b/Lib/test/test_idle.py index da05da50f336..6db1f11f2b77 100644 --- a/Lib/test/test_idle.py +++ b/Lib/test/test_idle.py @@ -1,19 +1,23 @@ import unittest from test.support import import_module -# Skip test if _thread or _tkinter wasn't built, if idlelib is missing, -# or if tcl/tk is not the 8.5+ needed for ttk widgets. -import_module('threading') # imported by PyShell, imports _thread +# For 3.6, skip test_idle if threads are not supported. +import_module('threading') # Imported by PyShell, imports _thread. + +# Skip test_idle if _tkinter wasn't built, if tkinter is missing, +# if tcl/tk is not the 8.5+ needed for ttk widgets, +# or if idlelib is missing (not installed). tk = import_module('tkinter') # imports _tkinter if tk.TkVersion < 8.5: raise unittest.SkipTest("IDLE requires tk 8.5 or later.") idlelib = import_module('idlelib') -# Before test imports, tell IDLE to avoid changing the environment. +# Before importing and executing more of idlelib, +# tell IDLE to avoid changing the environment. idlelib.testing = True -# unittest.main and test.libregrtest.runtest.runtest_inner -# call load_tests, when present, to discover tests to run. +# Unittest.main and test.libregrtest.runtest.runtest_inner +# call load_tests, when present here, to discover tests to run. from idlelib.idle_test import load_tests if __name__ == '__main__': From webhook-mailer at python.org Tue May 22 15:26:47 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Tue, 22 May 2018 19:26:47 -0000 Subject: [Python-checkins] [3.7] Add missed details of the C API introduced in 3.7. (GH-7047) (GH-7061) Message-ID: <mailman.22.1527017208.18020.python-checkins@python.org> https://github.com/python/cpython/commit/1f22a3003e0d5f125cfbcd6872ccdb92e7f2d798 commit: 1f22a3003e0d5f125cfbcd6872ccdb92e7f2d798 branch: 3.7 author: Serhiy Storchaka <storchaka at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-22T22:26:42+03:00 summary: [3.7] Add missed details of the C API introduced in 3.7. (GH-7047) (GH-7061) * Set the limited API version for PyImport_GetModule and PyOS_*Fork functions. * Add PyImport_GetModule and Py_UTF8Mode in PC/python3.def. * Add several functions in Doc/data/refcounts.dat. (cherry picked from commit 4e29f566e8821c09d8274eadcdd355e8b1284b8b) files: M Doc/data/refcounts.dat M Include/import.h M Include/intrcheck.h M PC/python3.def diff --git a/Doc/data/refcounts.dat b/Doc/data/refcounts.dat index f403c16547c4..62cc93832783 100644 --- a/Doc/data/refcounts.dat +++ b/Doc/data/refcounts.dat @@ -152,6 +152,47 @@ PyComplex_ImagAsDouble:PyObject*:op:0: PyComplex_RealAsDouble:double::: PyComplex_RealAsDouble:PyObject*:op:0: +PyContext_CheckExact:int::: +PyContext_CheckExact:PyObject*:o:0: + +PyContext_ClearFreeList:int::: + +PyContext_Copy:PyObject*::+1: +PyContext_Copy:PyObject*:ctx:0: + +PyContext_CopyCurrent:PyObject*::+1: + +PyContext_Enter:int::: +PyContext_Enter:PyObject*:ctx:+1: + +PyContext_Exit:int::: +PyContext_Exit:PyObject*:ctx:-1: + +PyContext_New:PyObject*::+1: + +PyContextToken_CheckExact:int::: +PyContextToken_CheckExact:PyObject*:o:0: + +PyContextVar_CheckExact:int::: +PyContextVar_CheckExact:PyObject*:o:0: + +PyContextVar_Get:int::: +PyContextVar_Get:PyObject*:var:0: +PyContextVar_Get:PyObject*:default_value:0: +PyContextVar_Get:PyObject**:value:+1:??? + +PyContextVar_New:PyObject*::+1: +PyContextVar_New:const char*:name:: +PyContextVar_New:PyObject*:def:+1: + +PyContextVar_Set:PyObject*::+1: +PyContextVar_Set:PyObject*:var:0: +PyContextVar_Set:PyObject*:value:+1: + +PyContextVar_Reset:int::: +PyContextVar_Reset:PyObject*:var:0: +PyContextVar_Reset:PyObject*:token:-1: + PyDate_FromDate:PyObject*::+1: PyDate_FromDate:int:year:: PyDate_FromDate:int:month:: @@ -541,6 +582,9 @@ PyImport_ExecCodeModuleEx:const char*:pathname:: PyImport_GetMagicNumber:long::: +PyImport_GetModule:PyObject*::+1: +PyImport_GetModule:PyObject*:name:0: + PyImport_GetModuleDict:PyObject*::0: PyImport_Import:PyObject*::+1: @@ -605,6 +649,9 @@ PyInterpreterState_Clear:PyInterpreterState*:interp:: PyInterpreterState_Delete:void::: PyInterpreterState_Delete:PyInterpreterState*:interp:: +PyInterpreterState_GetID:int64_t::: +PyInterpreterState_GetID:PyInterpreterState*:interp:: + PyInterpreterState_New:PyInterpreterState*::: PyIter_Check:int:o:0: @@ -933,6 +980,14 @@ PyNumber_Xor:PyObject*:o2:0: PyObject_AsFileDescriptor:int::: PyObject_AsFileDescriptor:PyObject*:o:0: +PyOS_AfterFork:void::: + +PyOS_AfterFork_Child:void::: + +PyOS_AfterFork_Parent:void::: + +PyOS_BeforeFork:void::: + PyOS_FSPath:PyObject*::+1: PyOS_FSPath:PyObject*:path:0: @@ -1252,6 +1307,12 @@ PySet_Pop:PyObject*:set:0: PySet_Size:int::: PySet_Size:PyObject*:anyset:0: +PySlice_AdjustIndices:Py_ssize_t::: +PySlice_AdjustIndices:Py_ssize_t:length:: +PySlice_AdjustIndices:Py_ssize_t*:start:: +PySlice_AdjustIndices:Py_ssize_t*:stop:: +PySlice_AdjustIndices:Py_ssize_t*:step:: + PySlice_Check:int::: PySlice_Check:PyObject*:ob:0: @@ -1260,6 +1321,12 @@ PySlice_New:PyObject*:start:0: PySlice_New:PyObject*:stop:0: PySlice_New:PyObject*:step:0: +PySlice_Unpack:int::: +PySlice_Unpack:PyObject*:slice:0: +PySlice_Unpack:Py_ssize_t*:start:: +PySlice_Unpack:Py_ssize_t*:stop:: +PySlice_Unpack:Py_ssize_t*:step:: + PyString_AS_STRING:const char*::: PyString_AS_STRING:PyObject*:string:0: @@ -1410,6 +1477,15 @@ PyTime_FromTime:int:minute:: PyTime_FromTime:int:second:: PyTime_FromTime:int:usecond:: +PyTraceMalloc_Track:int::: +PyTraceMalloc_Track:unsigned int:domain:: +PyTraceMalloc_Track:uintptr_t:ptr:: +PyTraceMalloc_Track:size_t:size:: + +PyTraceMalloc_Untrack:int::: +PyTraceMalloc_Untrack:unsigned int:domain:: +PyTraceMalloc_Untrack:uintptr_t:ptr:: + PyTuple_Check:int::: PyTuple_Check:PyObject*:p:0: diff --git a/Include/import.h b/Include/import.h index ac3fc3bd28c0..13f32a1004cf 100644 --- a/Include/import.h +++ b/Include/import.h @@ -38,7 +38,9 @@ PyAPI_FUNC(PyObject *) PyImport_ExecCodeModuleObject( ); #endif PyAPI_FUNC(PyObject *) PyImport_GetModuleDict(void); +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03070000 PyAPI_FUNC(PyObject *) PyImport_GetModule(PyObject *name); +#endif #ifndef Py_LIMITED_API PyAPI_FUNC(int) _PyImport_IsInitialized(PyInterpreterState *); PyAPI_FUNC(PyObject *) _PyImport_GetModuleId(struct _Py_Identifier *name); diff --git a/Include/intrcheck.h b/Include/intrcheck.h index 944968bd1171..2e17336ca659 100644 --- a/Include/intrcheck.h +++ b/Include/intrcheck.h @@ -8,10 +8,12 @@ extern "C" { PyAPI_FUNC(int) PyOS_InterruptOccurred(void); PyAPI_FUNC(void) PyOS_InitInterrupts(void); #ifdef HAVE_FORK +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03070000 PyAPI_FUNC(void) PyOS_BeforeFork(void); PyAPI_FUNC(void) PyOS_AfterFork_Parent(void); PyAPI_FUNC(void) PyOS_AfterFork_Child(void); #endif +#endif /* Deprecated, please use PyOS_AfterFork_Child() instead */ PyAPI_FUNC(void) PyOS_AfterFork(void) Py_DEPRECATED(3.7); diff --git a/PC/python3.def b/PC/python3.def index a4c0415242b1..9e0348b62544 100644 --- a/PC/python3.def +++ b/PC/python3.def @@ -284,6 +284,7 @@ EXPORTS PyImport_GetImporter=python37.PyImport_GetImporter PyImport_GetMagicNumber=python37.PyImport_GetMagicNumber PyImport_GetMagicTag=python37.PyImport_GetMagicTag + PyImport_GetModule=python37.PyImport_GetModule PyImport_GetModuleDict=python37.PyImport_GetModuleDict PyImport_Import=python37.PyImport_Import PyImport_ImportFrozenModule=python37.PyImport_ImportFrozenModule @@ -757,6 +758,7 @@ EXPORTS Py_SetPythonHome=python37.Py_SetPythonHome Py_SetRecursionLimit=python37.Py_SetRecursionLimit Py_SymtableString=python37.Py_SymtableString + Py_UTF8Mode=python37.Py_UTF8Mode DATA Py_VaBuildValue=python37.Py_VaBuildValue _PyArg_ParseTupleAndKeywords_SizeT=python37._PyArg_ParseTupleAndKeywords_SizeT _PyArg_ParseTuple_SizeT=python37._PyArg_ParseTuple_SizeT From webhook-mailer at python.org Tue May 22 16:01:16 2018 From: webhook-mailer at python.org (Victor Stinner) Date: Tue, 22 May 2018 20:01:16 -0000 Subject: [Python-checkins] bpo-33516: Add support for __round__ in MagicMock (GH-6880) Message-ID: <mailman.23.1527019279.18020.python-checkins@python.org> https://github.com/python/cpython/commit/6c4fab0f4b95410a1a964a75dcdd953697eff089 commit: 6c4fab0f4b95410a1a964a75dcdd953697eff089 branch: master author: John Reese <john at noswap.com> committer: Victor Stinner <vstinner at redhat.com> date: 2018-05-22T22:01:10+02:00 summary: bpo-33516: Add support for __round__ in MagicMock (GH-6880) unittest.mock.MagicMock now supports the __round__() magic method. files: A Misc/NEWS.d/next/Library/2018-05-15-17-06-42.bpo-33516.ZzARe4.rst M Doc/library/unittest.mock.rst M Lib/unittest/mock.py M Lib/unittest/test/testmock/testmagicmethods.py diff --git a/Doc/library/unittest.mock.rst b/Doc/library/unittest.mock.rst index bb647bb6a811..7dad3340ad61 100644 --- a/Doc/library/unittest.mock.rst +++ b/Doc/library/unittest.mock.rst @@ -1660,7 +1660,7 @@ The full list of supported magic methods is: * ``__hash__``, ``__sizeof__``, ``__repr__`` and ``__str__`` * ``__dir__``, ``__format__`` and ``__subclasses__`` -* ``__floor__``, ``__trunc__`` and ``__ceil__`` +* ``__round__``, ``__floor__``, ``__trunc__`` and ``__ceil__`` * Comparisons: ``__lt__``, ``__gt__``, ``__le__``, ``__ge__``, ``__eq__`` and ``__ne__`` * Container methods: ``__getitem__``, ``__setitem__``, ``__delitem__``, diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py index 9302dedae7fd..e9bb46359060 100644 --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -1709,7 +1709,7 @@ def _patch_stopall(): # because there is no idivmod "divmod rdivmod neg pos abs invert " "complex int float index " - "trunc floor ceil " + "round trunc floor ceil " "bool next " ) diff --git a/Lib/unittest/test/testmock/testmagicmethods.py b/Lib/unittest/test/testmock/testmagicmethods.py index 37623dcebc6c..5ab95978f60d 100644 --- a/Lib/unittest/test/testmock/testmagicmethods.py +++ b/Lib/unittest/test/testmock/testmagicmethods.py @@ -1,3 +1,4 @@ +import math import unittest import sys from unittest.mock import Mock, MagicMock, _magics @@ -280,6 +281,10 @@ def test_magicmock_defaults(self): self.assertEqual(hash(mock), object.__hash__(mock)) self.assertEqual(str(mock), object.__str__(mock)) self.assertTrue(bool(mock)) + self.assertEqual(round(mock), mock.__round__()) + self.assertEqual(math.trunc(mock), mock.__trunc__()) + self.assertEqual(math.floor(mock), mock.__floor__()) + self.assertEqual(math.ceil(mock), mock.__ceil__()) # in Python 3 oct and hex use __index__ # so these tests are for __index__ in py3k diff --git a/Misc/NEWS.d/next/Library/2018-05-15-17-06-42.bpo-33516.ZzARe4.rst b/Misc/NEWS.d/next/Library/2018-05-15-17-06-42.bpo-33516.ZzARe4.rst new file mode 100644 index 000000000000..77b1428f3c87 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-15-17-06-42.bpo-33516.ZzARe4.rst @@ -0,0 +1 @@ +:class:`unittest.mock.MagicMock` now supports the ``__round__`` magic method. From webhook-mailer at python.org Tue May 22 16:50:23 2018 From: webhook-mailer at python.org (Christian Heimes) Date: Tue, 22 May 2018 20:50:23 -0000 Subject: [Python-checkins] bpo-33570: TLS 1.3 ciphers for OpenSSL 1.1.1 (GH-6976) Message-ID: <mailman.24.1527022226.18020.python-checkins@python.org> https://github.com/python/cpython/commit/e8eb6cb7920ded66abc5d284319a8539bdc2bae3 commit: e8eb6cb7920ded66abc5d284319a8539bdc2bae3 branch: master author: Christian Heimes <christian at python.org> committer: GitHub <noreply at github.com> date: 2018-05-22T22:50:12+02:00 summary: bpo-33570: TLS 1.3 ciphers for OpenSSL 1.1.1 (GH-6976) Change TLS 1.3 cipher suite settings for compatibility with OpenSSL 1.1.1-pre6 and newer. OpenSSL 1.1.1 will have TLS 1.3 cipers enabled by default. Also update multissltests and Travis config to test with latest OpenSSL. Signed-off-by: Christian Heimes <christian at python.org> files: A Misc/NEWS.d/next/Library/2018-05-18-21-50-47.bpo-33570.7CZy4t.rst M .travis.yml M Doc/library/ssl.rst M Lib/test/test_ssl.py M Tools/ssl/multissltests.py diff --git a/.travis.yml b/.travis.yml index fecad290d8bb..204c63fb567d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,7 +12,7 @@ cache: env: global: - - OPENSSL=1.1.0g + - OPENSSL=1.1.0h - OPENSSL_DIR="$HOME/multissl/openssl/${OPENSSL}" - PATH="${OPENSSL_DIR}/bin:$PATH" # Use -O3 because we don't use debugger on Travis-CI diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index dcb26664feae..2ccea13b6142 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -169,11 +169,6 @@ purposes. 3DES was dropped from the default cipher string. - .. versionchanged:: 3.7 - - TLS 1.3 cipher suites TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, - and TLS_CHACHA20_POLY1305_SHA256 were added to the default cipher string. - Exceptions ^^^^^^^^^^ @@ -1601,6 +1596,9 @@ to speed up repeated connections from the same clients. when connected, the :meth:`SSLSocket.cipher` method of SSL sockets will give the currently selected cipher. + OpenSSL 1.1.1 has TLS 1.3 cipher suites enabled by default. The suites + cannot be disabled with :meth:`~SSLContext.set_ciphers`. + .. method:: SSLContext.set_alpn_protocols(protocols) Specify which protocols the socket should advertise during the SSL/TLS diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 71380797748e..03952b10a8e7 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -2695,10 +2695,7 @@ def test_check_hostname(self): def test_ecc_cert(self): client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) client_context.load_verify_locations(SIGNING_CA) - client_context.set_ciphers( - 'TLS13-AES-128-GCM-SHA256:TLS13-CHACHA20-POLY1305-SHA256:' - 'ECDHE:ECDSA:!NULL:!aRSA' - ) + client_context.set_ciphers('ECDHE:ECDSA:!NULL:!aRSA') hostname = SIGNED_CERTFILE_ECC_HOSTNAME server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) @@ -3439,17 +3436,16 @@ def test_do_handshake_enotconn(self): sock.do_handshake() self.assertEqual(cm.exception.errno, errno.ENOTCONN) - def test_default_ciphers(self): - context = ssl.SSLContext(ssl.PROTOCOL_TLS) - try: - # Force a set of weak ciphers on our client context - context.set_ciphers("DES") - except ssl.SSLError: - self.skipTest("no DES cipher available") - with ThreadedEchoServer(CERTFILE, - ssl_version=ssl.PROTOCOL_TLS, - chatty=False) as server: - with context.wrap_socket(socket.socket()) as s: + def test_no_shared_ciphers(self): + client_context, server_context, hostname = testing_context() + # OpenSSL enables all TLS 1.3 ciphers, enforce TLS 1.2 for test + client_context.options |= ssl.OP_NO_TLSv1_3 + # Force different suites on client and master + client_context.set_ciphers("AES128") + server_context.set_ciphers("AES256") + with ThreadedEchoServer(context=server_context) as server: + with client_context.wrap_socket(socket.socket(), + server_hostname=hostname) as s: with self.assertRaises(OSError): s.connect((HOST, server.port)) self.assertIn("no shared cipher", server.conn_errors[0]) @@ -3490,9 +3486,9 @@ def test_tls1_3(self): with context.wrap_socket(socket.socket()) as s: s.connect((HOST, server.port)) self.assertIn(s.cipher()[0], { - 'TLS13-AES-256-GCM-SHA384', - 'TLS13-CHACHA20-POLY1305-SHA256', - 'TLS13-AES-128-GCM-SHA256', + 'TLS_AES_256_GCM_SHA384', + 'TLS_CHACHA20_POLY1305_SHA256', + 'TLS_AES_128_GCM_SHA256', }) self.assertEqual(s.version(), 'TLSv1.3') @@ -3898,23 +3894,20 @@ def cb_wrong_return_type(ssl_sock, server_name, initial_context): def test_shared_ciphers(self): client_context, server_context, hostname = testing_context() - if ssl.OPENSSL_VERSION_INFO >= (1, 0, 2): - client_context.set_ciphers("AES128:AES256") - server_context.set_ciphers("AES256") - alg1 = "AES256" - alg2 = "AES-256" - else: - client_context.set_ciphers("AES:3DES") - server_context.set_ciphers("3DES") - alg1 = "3DES" - alg2 = "DES-CBC3" + client_context.set_ciphers("AES128:AES256") + server_context.set_ciphers("AES256") + expected_algs = [ + "AES256", "AES-256", + # TLS 1.3 ciphers are always enabled + "TLS_CHACHA20", "TLS_AES", + ] stats = server_params_test(client_context, server_context, sni_name=hostname) ciphers = stats['server_shared_ciphers'][0] self.assertGreater(len(ciphers), 0) for name, tls_version, bits in ciphers: - if not alg1 in name.split("-") and alg2 not in name: + if not any(alg in name for alg in expected_algs): self.fail(name) def test_read_write_after_close_raises_valuerror(self): diff --git a/Misc/NEWS.d/next/Library/2018-05-18-21-50-47.bpo-33570.7CZy4t.rst b/Misc/NEWS.d/next/Library/2018-05-18-21-50-47.bpo-33570.7CZy4t.rst new file mode 100644 index 000000000000..bd719a47e8f8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-18-21-50-47.bpo-33570.7CZy4t.rst @@ -0,0 +1,3 @@ +Change TLS 1.3 cipher suite settings for compatibility with OpenSSL +1.1.1-pre6 and newer. OpenSSL 1.1.1 will have TLS 1.3 cipers enabled by +default. diff --git a/Tools/ssl/multissltests.py b/Tools/ssl/multissltests.py index 2efc4258de91..bbc5c6652098 100755 --- a/Tools/ssl/multissltests.py +++ b/Tools/ssl/multissltests.py @@ -45,16 +45,16 @@ ] OPENSSL_RECENT_VERSIONS = [ - "1.0.2n", - "1.1.0g", - "1.1.1-pre1", + "1.0.2o", + "1.1.0h", + "1.1.1-pre6", ] LIBRESSL_OLD_VERSIONS = [ ] LIBRESSL_RECENT_VERSIONS = [ - "2.7.1", + "2.7.3", ] # store files in ../multissl From webhook-mailer at python.org Tue May 22 17:40:49 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 22 May 2018 21:40:49 -0000 Subject: [Python-checkins] bpo-33570: TLS 1.3 ciphers for OpenSSL 1.1.1 (GH-6976) Message-ID: <mailman.25.1527025252.18020.python-checkins@python.org> https://github.com/python/cpython/commit/cd57b48ef9a70b7ef693ba52aaf38d7c945ab5d3 commit: cd57b48ef9a70b7ef693ba52aaf38d7c945ab5d3 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-22T14:40:46-07:00 summary: bpo-33570: TLS 1.3 ciphers for OpenSSL 1.1.1 (GH-6976) Change TLS 1.3 cipher suite settings for compatibility with OpenSSL 1.1.1-pre6 and newer. OpenSSL 1.1.1 will have TLS 1.3 cipers enabled by default. Also update multissltests and Travis config to test with latest OpenSSL. Signed-off-by: Christian Heimes <christian at python.org> (cherry picked from commit e8eb6cb7920ded66abc5d284319a8539bdc2bae3) Co-authored-by: Christian Heimes <christian at python.org> files: A Misc/NEWS.d/next/Library/2018-05-18-21-50-47.bpo-33570.7CZy4t.rst M .travis.yml M Doc/library/ssl.rst M Lib/test/test_ssl.py M Tools/ssl/multissltests.py diff --git a/.travis.yml b/.travis.yml index ab43318975fb..3a5d203f8cb8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,7 +12,7 @@ cache: env: global: - - OPENSSL=1.1.0g + - OPENSSL=1.1.0h - OPENSSL_DIR="$HOME/multissl/openssl/${OPENSSL}" - PATH="${OPENSSL_DIR}/bin:$PATH" # Use -O3 because we don't use debugger on Travis-CI diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index dcb26664feae..2ccea13b6142 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -169,11 +169,6 @@ purposes. 3DES was dropped from the default cipher string. - .. versionchanged:: 3.7 - - TLS 1.3 cipher suites TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, - and TLS_CHACHA20_POLY1305_SHA256 were added to the default cipher string. - Exceptions ^^^^^^^^^^ @@ -1601,6 +1596,9 @@ to speed up repeated connections from the same clients. when connected, the :meth:`SSLSocket.cipher` method of SSL sockets will give the currently selected cipher. + OpenSSL 1.1.1 has TLS 1.3 cipher suites enabled by default. The suites + cannot be disabled with :meth:`~SSLContext.set_ciphers`. + .. method:: SSLContext.set_alpn_protocols(protocols) Specify which protocols the socket should advertise during the SSL/TLS diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 36580d55b9e2..9017ad571156 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -2716,10 +2716,7 @@ def test_check_hostname(self): def test_ecc_cert(self): client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) client_context.load_verify_locations(SIGNING_CA) - client_context.set_ciphers( - 'TLS13-AES-128-GCM-SHA256:TLS13-CHACHA20-POLY1305-SHA256:' - 'ECDHE:ECDSA:!NULL:!aRSA' - ) + client_context.set_ciphers('ECDHE:ECDSA:!NULL:!aRSA') hostname = SIGNED_CERTFILE_ECC_HOSTNAME server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) @@ -3466,17 +3463,16 @@ def test_do_handshake_enotconn(self): sock.do_handshake() self.assertEqual(cm.exception.errno, errno.ENOTCONN) - def test_default_ciphers(self): - context = ssl.SSLContext(ssl.PROTOCOL_TLS) - try: - # Force a set of weak ciphers on our client context - context.set_ciphers("DES") - except ssl.SSLError: - self.skipTest("no DES cipher available") - with ThreadedEchoServer(CERTFILE, - ssl_version=ssl.PROTOCOL_TLS, - chatty=False) as server: - with context.wrap_socket(socket.socket()) as s: + def test_no_shared_ciphers(self): + client_context, server_context, hostname = testing_context() + # OpenSSL enables all TLS 1.3 ciphers, enforce TLS 1.2 for test + client_context.options |= ssl.OP_NO_TLSv1_3 + # Force different suites on client and master + client_context.set_ciphers("AES128") + server_context.set_ciphers("AES256") + with ThreadedEchoServer(context=server_context) as server: + with client_context.wrap_socket(socket.socket(), + server_hostname=hostname) as s: with self.assertRaises(OSError): s.connect((HOST, server.port)) self.assertIn("no shared cipher", server.conn_errors[0]) @@ -3517,9 +3513,9 @@ def test_tls1_3(self): with context.wrap_socket(socket.socket()) as s: s.connect((HOST, server.port)) self.assertIn(s.cipher()[0], { - 'TLS13-AES-256-GCM-SHA384', - 'TLS13-CHACHA20-POLY1305-SHA256', - 'TLS13-AES-128-GCM-SHA256', + 'TLS_AES_256_GCM_SHA384', + 'TLS_CHACHA20_POLY1305_SHA256', + 'TLS_AES_128_GCM_SHA256', }) self.assertEqual(s.version(), 'TLSv1.3') @@ -3925,23 +3921,20 @@ def cb_wrong_return_type(ssl_sock, server_name, initial_context): def test_shared_ciphers(self): client_context, server_context, hostname = testing_context() - if ssl.OPENSSL_VERSION_INFO >= (1, 0, 2): - client_context.set_ciphers("AES128:AES256") - server_context.set_ciphers("AES256") - alg1 = "AES256" - alg2 = "AES-256" - else: - client_context.set_ciphers("AES:3DES") - server_context.set_ciphers("3DES") - alg1 = "3DES" - alg2 = "DES-CBC3" + client_context.set_ciphers("AES128:AES256") + server_context.set_ciphers("AES256") + expected_algs = [ + "AES256", "AES-256", + # TLS 1.3 ciphers are always enabled + "TLS_CHACHA20", "TLS_AES", + ] stats = server_params_test(client_context, server_context, sni_name=hostname) ciphers = stats['server_shared_ciphers'][0] self.assertGreater(len(ciphers), 0) for name, tls_version, bits in ciphers: - if not alg1 in name.split("-") and alg2 not in name: + if not any(alg in name for alg in expected_algs): self.fail(name) def test_read_write_after_close_raises_valuerror(self): diff --git a/Misc/NEWS.d/next/Library/2018-05-18-21-50-47.bpo-33570.7CZy4t.rst b/Misc/NEWS.d/next/Library/2018-05-18-21-50-47.bpo-33570.7CZy4t.rst new file mode 100644 index 000000000000..bd719a47e8f8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-18-21-50-47.bpo-33570.7CZy4t.rst @@ -0,0 +1,3 @@ +Change TLS 1.3 cipher suite settings for compatibility with OpenSSL +1.1.1-pre6 and newer. OpenSSL 1.1.1 will have TLS 1.3 cipers enabled by +default. diff --git a/Tools/ssl/multissltests.py b/Tools/ssl/multissltests.py index 2efc4258de91..bbc5c6652098 100755 --- a/Tools/ssl/multissltests.py +++ b/Tools/ssl/multissltests.py @@ -45,16 +45,16 @@ ] OPENSSL_RECENT_VERSIONS = [ - "1.0.2n", - "1.1.0g", - "1.1.1-pre1", + "1.0.2o", + "1.1.0h", + "1.1.1-pre6", ] LIBRESSL_OLD_VERSIONS = [ ] LIBRESSL_RECENT_VERSIONS = [ - "2.7.1", + "2.7.3", ] # store files in ../multissl From webhook-mailer at python.org Tue May 22 18:55:41 2018 From: webhook-mailer at python.org (Gregory P. Smith) Date: Tue, 22 May 2018 22:55:41 -0000 Subject: [Python-checkins] bpo-33604: Remove Pending from hmac Deprecation warning. (GH-7062) Message-ID: <mailman.26.1527029743.18020.python-checkins@python.org> https://github.com/python/cpython/commit/8bb0b5b03cffa2a2e74f248ef479a9e7fbe95cf4 commit: 8bb0b5b03cffa2a2e74f248ef479a9e7fbe95cf4 branch: master author: Matthias Bussonnier <bussonniermatthias at gmail.com> committer: Gregory P. Smith <greg at krypto.org> date: 2018-05-22T15:55:31-07:00 summary: bpo-33604: Remove Pending from hmac Deprecation warning. (GH-7062) bpo-33604: Bump removal notice from 3.6 to 3.8 and change PendingDeprecationWarning to DeprecationWarning as we had intended to do earlier... files: A Misc/NEWS.d/next/Documentation/2018-05-22-11-47-14.bpo-33604.5YHTpz.rst M Doc/library/hmac.rst M Lib/hmac.py M Lib/test/test_hmac.py diff --git a/Doc/library/hmac.rst b/Doc/library/hmac.rst index fcda86cf7978..731624ba94e3 100644 --- a/Doc/library/hmac.rst +++ b/Doc/library/hmac.rst @@ -27,7 +27,7 @@ This module implements the HMAC algorithm as described by :rfc:`2104`. Parameter *msg* can be of any type supported by :mod:`hashlib`. Parameter *digestmod* can be the name of a hash algorithm. - .. deprecated:: 3.4 + .. deprecated-removed:: 3.4 3.8 MD5 as implicit default digest for *digestmod* is deprecated. diff --git a/Lib/hmac.py b/Lib/hmac.py index 93c084e4ae80..43b721297637 100644 --- a/Lib/hmac.py +++ b/Lib/hmac.py @@ -39,8 +39,8 @@ def __init__(self, key, msg = None, digestmod = None): A hashlib constructor returning a new hash object. *OR* A hash name suitable for hashlib.new(). Defaults to hashlib.md5. - Implicit default to hashlib.md5 is deprecated and will be - removed in Python 3.6. + Implicit default to hashlib.md5 is deprecated since Python + 3.4 and will be removed in Python 3.8. Note: key and msg must be a bytes or bytearray objects. """ @@ -50,7 +50,9 @@ def __init__(self, key, msg = None, digestmod = None): if digestmod is None: _warnings.warn("HMAC() without an explicit digestmod argument " - "is deprecated.", PendingDeprecationWarning, 2) + "is deprecated since Python 3.4, and will be removed " + "in 3.8", + DeprecationWarning, 2) digestmod = _hashlib.md5 if callable(digestmod): diff --git a/Lib/test/test_hmac.py b/Lib/test/test_hmac.py index 4e4ef0ec0e86..7f4901307630 100644 --- a/Lib/test/test_hmac.py +++ b/Lib/test/test_hmac.py @@ -12,7 +12,7 @@ def ignore_warning(func): def wrapper(*args, **kwargs): with warnings.catch_warnings(): warnings.filterwarnings("ignore", - category=PendingDeprecationWarning) + category=DeprecationWarning) return func(*args, **kwargs) return wrapper @@ -303,7 +303,7 @@ def digest(self): self.fail('Expected warning about small block_size') def test_with_digestmod_warning(self): - with self.assertWarns(PendingDeprecationWarning): + with self.assertWarns(DeprecationWarning): key = b"\x0b" * 16 data = b"Hi There" digest = "9294727A3638BB1C13F48EF8158BFC9D" diff --git a/Misc/NEWS.d/next/Documentation/2018-05-22-11-47-14.bpo-33604.5YHTpz.rst b/Misc/NEWS.d/next/Documentation/2018-05-22-11-47-14.bpo-33604.5YHTpz.rst new file mode 100644 index 000000000000..3c2f2d0b8230 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2018-05-22-11-47-14.bpo-33604.5YHTpz.rst @@ -0,0 +1 @@ +Update HMAC md5 default to a DeprecationWarning, bump removal to 3.8. From webhook-mailer at python.org Tue May 22 19:40:55 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 22 May 2018 23:40:55 -0000 Subject: [Python-checkins] bpo-33604: Remove Pending from hmac Deprecation warning. (GH-7062) Message-ID: <mailman.27.1527032457.18020.python-checkins@python.org> https://github.com/python/cpython/commit/2751dccca4098b799ea575bb35cec9959c74684a commit: 2751dccca4098b799ea575bb35cec9959c74684a branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-22T16:40:44-07:00 summary: bpo-33604: Remove Pending from hmac Deprecation warning. (GH-7062) bpo-33604: Bump removal notice from 3.6 to 3.8 and change PendingDeprecationWarning to DeprecationWarning as we had intended to do earlier... (cherry picked from commit 8bb0b5b03cffa2a2e74f248ef479a9e7fbe95cf4) Co-authored-by: Matthias Bussonnier <bussonniermatthias at gmail.com> files: A Misc/NEWS.d/next/Documentation/2018-05-22-11-47-14.bpo-33604.5YHTpz.rst M Doc/library/hmac.rst M Lib/hmac.py M Lib/test/test_hmac.py diff --git a/Doc/library/hmac.rst b/Doc/library/hmac.rst index fcda86cf7978..731624ba94e3 100644 --- a/Doc/library/hmac.rst +++ b/Doc/library/hmac.rst @@ -27,7 +27,7 @@ This module implements the HMAC algorithm as described by :rfc:`2104`. Parameter *msg* can be of any type supported by :mod:`hashlib`. Parameter *digestmod* can be the name of a hash algorithm. - .. deprecated:: 3.4 + .. deprecated-removed:: 3.4 3.8 MD5 as implicit default digest for *digestmod* is deprecated. diff --git a/Lib/hmac.py b/Lib/hmac.py index 93c084e4ae80..43b721297637 100644 --- a/Lib/hmac.py +++ b/Lib/hmac.py @@ -39,8 +39,8 @@ def __init__(self, key, msg = None, digestmod = None): A hashlib constructor returning a new hash object. *OR* A hash name suitable for hashlib.new(). Defaults to hashlib.md5. - Implicit default to hashlib.md5 is deprecated and will be - removed in Python 3.6. + Implicit default to hashlib.md5 is deprecated since Python + 3.4 and will be removed in Python 3.8. Note: key and msg must be a bytes or bytearray objects. """ @@ -50,7 +50,9 @@ def __init__(self, key, msg = None, digestmod = None): if digestmod is None: _warnings.warn("HMAC() without an explicit digestmod argument " - "is deprecated.", PendingDeprecationWarning, 2) + "is deprecated since Python 3.4, and will be removed " + "in 3.8", + DeprecationWarning, 2) digestmod = _hashlib.md5 if callable(digestmod): diff --git a/Lib/test/test_hmac.py b/Lib/test/test_hmac.py index 4e4ef0ec0e86..7f4901307630 100644 --- a/Lib/test/test_hmac.py +++ b/Lib/test/test_hmac.py @@ -12,7 +12,7 @@ def ignore_warning(func): def wrapper(*args, **kwargs): with warnings.catch_warnings(): warnings.filterwarnings("ignore", - category=PendingDeprecationWarning) + category=DeprecationWarning) return func(*args, **kwargs) return wrapper @@ -303,7 +303,7 @@ def digest(self): self.fail('Expected warning about small block_size') def test_with_digestmod_warning(self): - with self.assertWarns(PendingDeprecationWarning): + with self.assertWarns(DeprecationWarning): key = b"\x0b" * 16 data = b"Hi There" digest = "9294727A3638BB1C13F48EF8158BFC9D" diff --git a/Misc/NEWS.d/next/Documentation/2018-05-22-11-47-14.bpo-33604.5YHTpz.rst b/Misc/NEWS.d/next/Documentation/2018-05-22-11-47-14.bpo-33604.5YHTpz.rst new file mode 100644 index 000000000000..3c2f2d0b8230 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2018-05-22-11-47-14.bpo-33604.5YHTpz.rst @@ -0,0 +1 @@ +Update HMAC md5 default to a DeprecationWarning, bump removal to 3.8. From webhook-mailer at python.org Tue May 22 23:32:15 2018 From: webhook-mailer at python.org (Ivan Levkivskyi) Date: Wed, 23 May 2018 03:32:15 -0000 Subject: [Python-checkins] Reverse the meaning of is_argument when used for type check (GH-7039) Message-ID: <mailman.28.1527046336.18020.python-checkins@python.org> https://github.com/python/cpython/commit/0e61dffdbaf39ac5916ce431ff3b37db8faa1d2d commit: 0e61dffdbaf39ac5916ce431ff3b37db8faa1d2d branch: master author: Nina Zakharenko <nzakharenko at gmail.com> committer: Ivan Levkivskyi <levkivskyi at gmail.com> date: 2018-05-22T20:32:10-07:00 summary: Reverse the meaning of is_argument when used for type check (GH-7039) files: M Lib/typing.py diff --git a/Lib/typing.py b/Lib/typing.py index 3e82c6b1bb21..18b04cf4dbe2 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -106,7 +106,7 @@ # legitimate imports of those modules. -def _type_check(arg, msg, is_argument=False): +def _type_check(arg, msg, is_argument=True): """Check that the argument is a type, and return it (internal helper). As a special case, accept None and return type(None) instead. Also wrap strings @@ -119,7 +119,7 @@ def _type_check(arg, msg, is_argument=False): We append the repr() of the actual value (truncated to 100 chars). """ invalid_generic_forms = (Generic, _Protocol) - if not is_argument: + if is_argument: invalid_generic_forms = invalid_generic_forms + (ClassVar, ) if arg is None: @@ -445,7 +445,7 @@ class ForwardRef(_Final, _root=True): '__forward_evaluated__', '__forward_value__', '__forward_is_argument__') - def __init__(self, arg, is_argument=False): + def __init__(self, arg, is_argument=True): if not isinstance(arg, str): raise TypeError(f"Forward reference must be a string -- got {arg!r}") try: @@ -979,7 +979,7 @@ def get_type_hints(obj, globalns=None, localns=None): if value is None: value = type(None) if isinstance(value, str): - value = ForwardRef(value, is_argument=True) + value = ForwardRef(value, is_argument=False) value = _eval_type(value, base_globals, localns) hints[name] = value return hints From lp_benchmark_robot at intel.com Tue May 22 23:47:20 2018 From: lp_benchmark_robot at intel.com (lp_benchmark_robot at intel.com) Date: Tue, 22 May 2018 20:47:20 -0700 Subject: [Python-checkins] [65 flat] Results for Python (master branch) 2018-05-22 Message-ID: <cfc43b7c-09f9-4168-9485-9d4cfc1b7114@orsmsx152.amr.corp.intel.com> Results for project python/master, build date: 2018-05-22 03:03:31-07:00. - commit: 55bfe69 - previous commit: 1179f4b - revision date: 2018-05-22 11:21:25+03:00 - environment: Broadwell-EP - cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores, stepping 1, LLC 55 MB - mem: 128 GB - os: Ubuntu 16.04.2 LTS - kernel: 4.4.0-62-generic x86_64 GNU/Linux Baseline results were generated using release v3.6.0, with hash 5c4568a from 2016-12-22 23:38:47+00:00. +-----+------------------------+--------+------------+------------+------------+ | | |relative|change since|change since|current rev | | | benchmark|std_dev*| last run | baseline |run with PGO| +-----+------------------------+--------+------------+------------+------------+ | :-| | 2to3| 0.634% | +0.144% | +9.592% | +5.975% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method| 1.462% | -0.034% | +23.840% | +13.027% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_slots| 1.650% | +0.549% | +25.457% | +11.480% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_unknown| 0.922% | +0.187% | +22.354% | +12.677% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_simple| 3.369% | -0.323% | +10.578% | +14.494% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chameleon| 2.265% | -0.785% | +11.894% | +10.613% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chaos| 0.680% | -0.060% | +8.461% | +10.035% | +-----+------------------------+--------+------------+------------+------------+ | :-| | crypto_pyaes| 0.539% | -0.101% | -0.072% | +9.070% | +-----+------------------------+--------+------------+------------+------------+ | :-| | deltablue| 3.222% | -0.332% | +11.697% | +17.509% | +-----+------------------------+--------+------------+------------+------------+ | :-| | django_template| 3.029% | +1.333% | +21.740% | +11.796% | +-----+------------------------+--------+------------+------------+------------+ | :-| | dulwich_log| 1.073% | +0.150% | +5.637% | +6.536% | +-----+------------------------+--------+------------+------------+------------+ | :-| | fannkuch| 0.355% | +0.130% | +7.284% | +4.870% | +-----+------------------------+--------+------------+------------+------------+ | :-| | float| 1.033% | -0.089% | +2.660% | +7.412% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_text| 1.302% | +0.123% | +14.772% | +9.392% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_xml| 1.942% | +0.155% | +11.105% | +8.886% | +-----+------------------------+--------+------------+------------+------------+ | :-| | go| 6.306% | -0.452% | +4.919% | +13.088% | +-----+------------------------+--------+------------+------------+------------+ | :-| | hexiom| 0.981% | -0.120% | +11.854% | +11.236% | +-----+------------------------+--------+------------+------------+------------+ | :-| | html5lib| 2.741% | +0.444% | +11.937% | +9.648% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_dumps| 1.223% | -0.504% | +3.638% | +9.136% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_loads| 4.557% | -0.833% | -4.216% | +16.039% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_format| 1.618% | +0.079% | +17.902% | +12.612% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_silent| 2.268% | +0.552% | +48.065% | +11.732% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_simple| 1.538% | -0.195% | +12.969% | +13.368% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mako| 0.466% | +0.026% | +16.838% | +12.819% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mdp| 6.242% | -0.022% | +1.616% | +14.847% | +-----+------------------------+--------+------------+------------+------------+ | :-| | meteor_contest| 0.784% | -0.312% | +4.528% | +5.659% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nbody| 1.111% | -0.156% | +0.678% | +0.389% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nqueens| 0.877% | -0.072% | +5.715% | +7.229% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pathlib| 1.020% | +0.488% | +2.668% | +7.565% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle| 0.964% | -0.444% | -0.532% | +22.669% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_dict| 0.179% | +0.013% | +7.636% | +16.102% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_list| 0.510% | +0.123% | +7.023% | +17.182% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_pure_python| 4.789% | +0.262% | +11.977% | +9.471% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pidigits| 0.156% | -0.021% | +0.252% | +10.571% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup| 0.111% | +0.026% | +19.085% | +5.026% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup_no_site| 0.088% | +0.028% | +6.144% | +5.268% | +-----+------------------------+--------+------------+------------+------------+ | :-| | raytrace| 1.052% | +0.046% | +9.732% | +14.241% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_compile| 5.480% | -0.811% | +3.821% | +9.576% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_dna| 0.476% | -0.041% | -2.092% | +13.483% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_effbot| 1.531% | +0.112% | -2.406% | +5.732% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_v8| 1.770% | +0.081% | +4.039% | +10.118% | +-----+------------------------+--------+------------+------------+------------+ | :-| | richards| 1.508% | +0.232% | +9.414% | +15.218% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_fft| 0.443% | +0.204% | -1.332% | +4.019% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_lu| 3.372% | -0.495% | +21.565% | +12.889% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_monte_carlo| 2.178% | -0.272% | +4.501% | +5.084% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sor| 2.468% | +0.422% | +15.638% | +7.628% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sparse_mat_mult| 3.972% | -0.848% | -3.882% | +3.293% | +-----+------------------------+--------+------------+------------+------------+ | :-| | spectral_norm| 0.553% | +0.309% | +4.473% | +4.337% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_declarative| 1.979% | +0.144% | +7.678% | +5.111% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_imperative| 3.564% | +0.875% | +8.218% | +5.345% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlite_synth| 2.719% | +1.332% | +0.369% | +8.373% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_expand| 2.692% | -0.412% | +18.038% | +6.502% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_integrate| 1.520% | +0.260% | +18.872% | +5.485% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_str| 3.728% | -0.260% | +19.574% | +6.838% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_sum| 6.160% | +0.922% | +17.284% | +7.966% | +-----+------------------------+--------+------------+------------+------------+ | :-| | telco| 4.018% | +0.528% | +20.043% | +9.344% | +-----+------------------------+--------+------------+------------+------------+ | :-| | tornado_http| 1.130% | +0.037% | +7.626% | +4.978% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpack_sequence| 2.253% | -0.345% | +2.236% | +2.861% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle| 9.262% | -1.856% | +5.162% | +22.656% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_list| 0.787% | +1.188% | -3.682% | +18.974% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_pure_python| 2.049% | -0.046% | +7.519% | +7.070% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_generate| 0.828% | +0.072% | +2.800% | +11.634% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_iterparse| 1.998% | +0.075% | +4.992% | +9.205% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_parse| 2.555% | +0.429% | -5.782% | +12.347% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_process| 1.182% | -0.174% | +4.860% | +10.279% | +-----+------------------------+--------+------------+------------+------------+ * Relative Standard Deviation (Standard Deviation/Average) If this is not displayed properly please visit our results page here: http://languagesperformance.intel.com/65-flat-results-for-python-master-branch-2018-05-22 Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. From webhook-mailer at python.org Tue May 22 23:51:18 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 23 May 2018 03:51:18 -0000 Subject: [Python-checkins] Reverse the meaning of is_argument when used for type check (GH-7039) Message-ID: <mailman.29.1527047478.18020.python-checkins@python.org> https://github.com/python/cpython/commit/0f9b68a728f69a64dc224ec7b27e92013f0ed9cc commit: 0f9b68a728f69a64dc224ec7b27e92013f0ed9cc branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-22T20:51:15-07:00 summary: Reverse the meaning of is_argument when used for type check (GH-7039) (cherry picked from commit 0e61dffdbaf39ac5916ce431ff3b37db8faa1d2d) Co-authored-by: Nina Zakharenko <nzakharenko at gmail.com> files: M Lib/typing.py diff --git a/Lib/typing.py b/Lib/typing.py index 3e82c6b1bb21..18b04cf4dbe2 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -106,7 +106,7 @@ # legitimate imports of those modules. -def _type_check(arg, msg, is_argument=False): +def _type_check(arg, msg, is_argument=True): """Check that the argument is a type, and return it (internal helper). As a special case, accept None and return type(None) instead. Also wrap strings @@ -119,7 +119,7 @@ def _type_check(arg, msg, is_argument=False): We append the repr() of the actual value (truncated to 100 chars). """ invalid_generic_forms = (Generic, _Protocol) - if not is_argument: + if is_argument: invalid_generic_forms = invalid_generic_forms + (ClassVar, ) if arg is None: @@ -445,7 +445,7 @@ class ForwardRef(_Final, _root=True): '__forward_evaluated__', '__forward_value__', '__forward_is_argument__') - def __init__(self, arg, is_argument=False): + def __init__(self, arg, is_argument=True): if not isinstance(arg, str): raise TypeError(f"Forward reference must be a string -- got {arg!r}") try: @@ -979,7 +979,7 @@ def get_type_hints(obj, globalns=None, localns=None): if value is None: value = type(None) if isinstance(value, str): - value = ForwardRef(value, is_argument=True) + value = ForwardRef(value, is_argument=False) value = _eval_type(value, base_globals, localns) hints[name] = value return hints From webhook-mailer at python.org Wed May 23 01:07:11 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Wed, 23 May 2018 05:07:11 -0000 Subject: [Python-checkins] bpo-27300: Add the errors parameter to tempfile classes. (GH-6696) Message-ID: <mailman.30.1527052032.18020.python-checkins@python.org> https://github.com/python/cpython/commit/825aab95fde959541859383f8ea7e7854ebfd49f commit: 825aab95fde959541859383f8ea7e7854ebfd49f branch: master author: sth <sth.dev at tejp.de> committer: Serhiy Storchaka <storchaka at gmail.com> date: 2018-05-23T08:07:01+03:00 summary: bpo-27300: Add the errors parameter to tempfile classes. (GH-6696) files: A Misc/NEWS.d/next/Library/2018-05-01-02-24-44.bpo-27300.LdIXvK.rst M Doc/library/tempfile.rst M Lib/tempfile.py M Lib/test/test_tempfile.py diff --git a/Doc/library/tempfile.rst b/Doc/library/tempfile.rst index c59aca1e1890..79914e15f444 100644 --- a/Doc/library/tempfile.rst +++ b/Doc/library/tempfile.rst @@ -31,7 +31,7 @@ is recommended to use keyword arguments for clarity. The module defines the following user-callable items: -.. function:: TemporaryFile(mode='w+b', buffering=None, encoding=None, newline=None, suffix=None, prefix=None, dir=None) +.. function:: TemporaryFile(mode='w+b', buffering=None, encoding=None, newline=None, suffix=None, prefix=None, dir=None, *, errors=None) Return a :term:`file-like object` that can be used as a temporary storage area. The file is created securely, using the same rules as :func:`mkstemp`. It will be destroyed as soon @@ -49,7 +49,7 @@ The module defines the following user-callable items: The *mode* parameter defaults to ``'w+b'`` so that the file created can be read and written without being closed. Binary mode is used so that it behaves consistently on all platforms without regard for the data that is - stored. *buffering*, *encoding* and *newline* are interpreted as for + stored. *buffering*, *encoding*, *errors* and *newline* are interpreted as for :func:`open`. The *dir*, *prefix* and *suffix* parameters have the same meaning and @@ -66,8 +66,11 @@ The module defines the following user-callable items: The :py:data:`os.O_TMPFILE` flag is now used if available. + .. versionchanged:: 3.8 + Added *errors* parameter. -.. function:: NamedTemporaryFile(mode='w+b', buffering=None, encoding=None, newline=None, suffix=None, prefix=None, dir=None, delete=True) + +.. function:: NamedTemporaryFile(mode='w+b', buffering=None, encoding=None, newline=None, suffix=None, prefix=None, dir=None, delete=True, *, errors=None) This function operates exactly as :func:`TemporaryFile` does, except that the file is guaranteed to have a visible name in the file system (on @@ -82,8 +85,11 @@ The module defines the following user-callable items: attribute is the underlying true file object. This file-like object can be used in a :keyword:`with` statement, just like a normal file. + .. versionchanged:: 3.8 + Added *errors* parameter. + -.. function:: SpooledTemporaryFile(max_size=0, mode='w+b', buffering=None, encoding=None, newline=None, suffix=None, prefix=None, dir=None) +.. function:: SpooledTemporaryFile(max_size=0, mode='w+b', buffering=None, encoding=None, newline=None, suffix=None, prefix=None, dir=None, *, errors=None) This function operates exactly as :func:`TemporaryFile` does, except that data is spooled in memory until the file size exceeds *max_size*, or @@ -104,6 +110,9 @@ The module defines the following user-callable items: .. versionchanged:: 3.3 the truncate method now accepts a ``size`` argument. + .. versionchanged:: 3.8 + Added *errors* parameter. + .. function:: TemporaryDirectory(suffix=None, prefix=None, dir=None) diff --git a/Lib/tempfile.py b/Lib/tempfile.py index 214322416963..e6fb3c8e9ad8 100644 --- a/Lib/tempfile.py +++ b/Lib/tempfile.py @@ -519,7 +519,7 @@ def __iter__(self): def NamedTemporaryFile(mode='w+b', buffering=-1, encoding=None, newline=None, suffix=None, prefix=None, - dir=None, delete=True): + dir=None, delete=True, *, errors=None): """Create and return a temporary file. Arguments: 'prefix', 'suffix', 'dir' -- as for mkstemp. @@ -528,6 +528,7 @@ def NamedTemporaryFile(mode='w+b', buffering=-1, encoding=None, 'encoding' -- the encoding argument to io.open (default None) 'newline' -- the newline argument to io.open (default None) 'delete' -- whether the file is deleted on close (default True). + 'errors' -- the errors argument to io.open (default None) The file is created as mkstemp() would do it. Returns an object with a file-like interface; the name of the file @@ -547,7 +548,7 @@ def NamedTemporaryFile(mode='w+b', buffering=-1, encoding=None, (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags, output_type) try: file = _io.open(fd, mode, buffering=buffering, - newline=newline, encoding=encoding) + newline=newline, encoding=encoding, errors=errors) return _TemporaryFileWrapper(file, name, delete) except BaseException: @@ -568,7 +569,7 @@ def NamedTemporaryFile(mode='w+b', buffering=-1, encoding=None, def TemporaryFile(mode='w+b', buffering=-1, encoding=None, newline=None, suffix=None, prefix=None, - dir=None): + dir=None, *, errors=None): """Create and return a temporary file. Arguments: 'prefix', 'suffix', 'dir' -- as for mkstemp. @@ -576,6 +577,7 @@ def TemporaryFile(mode='w+b', buffering=-1, encoding=None, 'buffering' -- the buffer size argument to io.open (default -1). 'encoding' -- the encoding argument to io.open (default None) 'newline' -- the newline argument to io.open (default None) + 'errors' -- the errors argument to io.open (default None) The file is created as mkstemp() would do it. Returns an object with a file-like interface. The file has no @@ -609,7 +611,8 @@ def TemporaryFile(mode='w+b', buffering=-1, encoding=None, else: try: return _io.open(fd, mode, buffering=buffering, - newline=newline, encoding=encoding) + newline=newline, encoding=encoding, + errors=errors) except: _os.close(fd) raise @@ -619,7 +622,7 @@ def TemporaryFile(mode='w+b', buffering=-1, encoding=None, try: _os.unlink(name) return _io.open(fd, mode, buffering=buffering, - newline=newline, encoding=encoding) + newline=newline, encoding=encoding, errors=errors) except: _os.close(fd) raise @@ -633,7 +636,7 @@ class SpooledTemporaryFile: def __init__(self, max_size=0, mode='w+b', buffering=-1, encoding=None, newline=None, - suffix=None, prefix=None, dir=None): + suffix=None, prefix=None, dir=None, *, errors=None): if 'b' in mode: self._file = _io.BytesIO() else: @@ -646,7 +649,7 @@ def __init__(self, max_size=0, mode='w+b', buffering=-1, self._TemporaryFileArgs = {'mode': mode, 'buffering': buffering, 'suffix': suffix, 'prefix': prefix, 'encoding': encoding, 'newline': newline, - 'dir': dir} + 'dir': dir, 'errors': errors} def _check(self, file): if self._rolled: return @@ -692,12 +695,11 @@ def closed(self): @property def encoding(self): - try: - return self._file.encoding - except AttributeError: - if 'b' in self._TemporaryFileArgs['mode']: - raise - return self._TemporaryFileArgs['encoding'] + return self._file.encoding + + @property + def errors(self): + return self._file.errors def fileno(self): self.rollover() @@ -725,12 +727,7 @@ def name(self): @property def newlines(self): - try: - return self._file.newlines - except AttributeError: - if 'b' in self._TemporaryFileArgs['mode']: - raise - return self._TemporaryFileArgs['newline'] + return self._file.newlines def read(self, *args): return self._file.read(*args) diff --git a/Lib/test/test_tempfile.py b/Lib/test/test_tempfile.py index 710756bde64c..e5098d2eea6b 100644 --- a/Lib/test/test_tempfile.py +++ b/Lib/test/test_tempfile.py @@ -1094,6 +1094,8 @@ def test_properties(self): f.newlines with self.assertRaises(AttributeError): f.encoding + with self.assertRaises(AttributeError): + f.errors f.write(b'x') self.assertTrue(f._rolled) @@ -1103,6 +1105,8 @@ def test_properties(self): f.newlines with self.assertRaises(AttributeError): f.encoding + with self.assertRaises(AttributeError): + f.errors def test_text_mode(self): # Creating a SpooledTemporaryFile with a text mode should produce @@ -1119,6 +1123,7 @@ def test_text_mode(self): self.assertIsNone(f.name) self.assertIsNone(f.newlines) self.assertIsNone(f.encoding) + self.assertIsNone(f.errors) f.write("xyzzy\n") f.seek(0) @@ -1132,10 +1137,12 @@ def test_text_mode(self): self.assertIsNotNone(f.name) self.assertEqual(f.newlines, os.linesep) self.assertIsNotNone(f.encoding) + self.assertIsNotNone(f.errors) def test_text_newline_and_encoding(self): f = tempfile.SpooledTemporaryFile(mode='w+', max_size=10, - newline='', encoding='utf-8') + newline='', encoding='utf-8', + errors='ignore') f.write("\u039B\r\n") f.seek(0) self.assertEqual(f.read(), "\u039B\r\n") @@ -1144,6 +1151,7 @@ def test_text_newline_and_encoding(self): self.assertIsNone(f.name) self.assertIsNone(f.newlines) self.assertIsNone(f.encoding) + self.assertIsNone(f.errors) f.write("\u039B" * 20 + "\r\n") f.seek(0) @@ -1153,6 +1161,7 @@ def test_text_newline_and_encoding(self): self.assertIsNotNone(f.name) self.assertIsNotNone(f.newlines) self.assertEqual(f.encoding, 'utf-8') + self.assertEqual(f.errors, 'ignore') def test_context_manager_before_rollover(self): # A SpooledTemporaryFile can be used as a context manager diff --git a/Misc/NEWS.d/next/Library/2018-05-01-02-24-44.bpo-27300.LdIXvK.rst b/Misc/NEWS.d/next/Library/2018-05-01-02-24-44.bpo-27300.LdIXvK.rst new file mode 100644 index 000000000000..5edbc86b9c9c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-01-02-24-44.bpo-27300.LdIXvK.rst @@ -0,0 +1,2 @@ +The file classes in *tempfile* now accept an *errors* parameter that +complements the already existing *encoding*. Patch by Stephan Hohe. From solipsis at pitrou.net Wed May 23 05:17:36 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 23 May 2018 09:17:36 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=4 Message-ID: <20180523091736.1.CE15CB3B38286D5A@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_functools leaked [0, 3, 1] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogMz2zW6', '--timeout', '7200'] From webhook-mailer at python.org Wed May 23 12:00:59 2018 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 23 May 2018 16:00:59 -0000 Subject: [Python-checkins] bpo-33612: Remove PyThreadState_Clear() assertion (#7069) Message-ID: <mailman.31.1527091263.18020.python-checkins@python.org> https://github.com/python/cpython/commit/b6dccf54fd3bac9c87348d96f9d6b571608c15bc commit: b6dccf54fd3bac9c87348d96f9d6b571608c15bc branch: master author: Victor Stinner <vstinner at redhat.com> committer: GitHub <noreply at github.com> date: 2018-05-23T18:00:55+02:00 summary: bpo-33612: Remove PyThreadState_Clear() assertion (#7069) bpo-25612, bpo-33612: Remove an assertion from PyThreadState_Clear() which failed at Python shutdown or on fork if a thread was running a generator. files: M Python/pystate.c diff --git a/Python/pystate.c b/Python/pystate.c index d276bfc7e8af..4534c4770f24 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -586,7 +586,6 @@ PyThreadState_Clear(PyThreadState *tstate) Py_CLEAR(tstate->exc_state.exc_traceback); /* The stack of exception states should contain just this thread. */ - assert(tstate->exc_info->previous_item == NULL); if (Py_VerboseFlag && tstate->exc_info != &tstate->exc_state) { fprintf(stderr, "PyThreadState_Clear: warning: thread still has a generator\n"); From webhook-mailer at python.org Wed May 23 13:35:07 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Wed, 23 May 2018 17:35:07 -0000 Subject: [Python-checkins] bpo-32436: Document PEP 567 changes to asyncio. (GH-7073) Message-ID: <mailman.32.1527096910.18020.python-checkins@python.org> https://github.com/python/cpython/commit/28b9178023a445b1da2694774c265cd4b7a244ec commit: 28b9178023a445b1da2694774c265cd4b7a244ec branch: master author: Yury Selivanov <yury at magic.io> committer: GitHub <noreply at github.com> date: 2018-05-23T13:35:04-04:00 summary: bpo-32436: Document PEP 567 changes to asyncio. (GH-7073) files: A Misc/NEWS.d/next/Documentation/2018-05-23-11-59-51.bpo-32436.S1LGPa.rst M Doc/library/asyncio-eventloop.rst M Doc/library/asyncio-task.rst M Doc/whatsnew/3.7.rst diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index 2770fa6f8acd..9d7f2362b3d1 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -124,7 +124,7 @@ keywords to your callback, use :func:`functools.partial`. For example, parameters in debug mode, whereas ``lambda`` functions have a poor representation. -.. method:: AbstractEventLoop.call_soon(callback, \*args) +.. method:: AbstractEventLoop.call_soon(callback, *args, context=None) Arrange for a callback to be called as soon as possible. The callback is called after :meth:`call_soon` returns, when control returns to the event @@ -137,19 +137,31 @@ keywords to your callback, use :func:`functools.partial`. For example, Any positional arguments after the callback will be passed to the callback when it is called. + An optional keyword-only *context* argument allows specifying a custom + :class:`contextvars.Context` for the *callback* to run in. The current + context is used when no *context* is provided. + An instance of :class:`asyncio.Handle` is returned, which can be used to cancel the callback. :ref:`Use functools.partial to pass keywords to the callback <asyncio-pass-keywords>`. -.. method:: AbstractEventLoop.call_soon_threadsafe(callback, \*args) + .. versionchanged:: 3.7 + The *context* keyword-only parameter was added. See :pep:`567` + for more details. + +.. method:: AbstractEventLoop.call_soon_threadsafe(callback, *args, context=None) Like :meth:`call_soon`, but thread safe. See the :ref:`concurrency and multithreading <asyncio-multithreading>` section of the documentation. + .. versionchanged:: 3.7 + The *context* keyword-only parameter was added. See :pep:`567` + for more details. + .. _asyncio-delayed-calls: @@ -166,7 +178,7 @@ a different clock than :func:`time.time`. Timeouts (relative *delay* or absolute *when*) should not exceed one day. -.. method:: AbstractEventLoop.call_later(delay, callback, *args) +.. method:: AbstractEventLoop.call_later(delay, callback, *args, context=None) Arrange for the *callback* to be called after the given *delay* seconds (either an int or float). @@ -182,10 +194,18 @@ a different clock than :func:`time.time`. is called. If you want the callback to be called with some named arguments, use a closure or :func:`functools.partial`. + An optional keyword-only *context* argument allows specifying a custom + :class:`contextvars.Context` for the *callback* to run in. The current + context is used when no *context* is provided. + :ref:`Use functools.partial to pass keywords to the callback <asyncio-pass-keywords>`. -.. method:: AbstractEventLoop.call_at(when, callback, *args) + .. versionchanged:: 3.7 + The *context* keyword-only parameter was added. See :pep:`567` + for more details. + +.. method:: AbstractEventLoop.call_at(when, callback, *args, context=None) Arrange for the *callback* to be called at the given absolute timestamp *when* (an int or float), using the same time reference as @@ -199,6 +219,10 @@ a different clock than :func:`time.time`. :ref:`Use functools.partial to pass keywords to the callback <asyncio-pass-keywords>`. + .. versionchanged:: 3.7 + The *context* keyword-only parameter was added. See :pep:`567` + for more details. + .. method:: AbstractEventLoop.time() Return the current time, as a :class:`float` value, according to the diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index 2488a909ec00..4892333d8cee 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -275,19 +275,27 @@ Future :exc:`CancelledError`. If the future isn't done yet, raises :exc:`InvalidStateError`. - .. method:: add_done_callback(fn) + .. method:: add_done_callback(callback, *, context=None) Add a callback to be run when the future becomes done. - The callback is called with a single argument - the future object. If the + The *callback* is called with a single argument - the future object. If the future is already done when this is called, the callback is scheduled with :meth:`~AbstractEventLoop.call_soon`. + An optional keyword-only *context* argument allows specifying a custom + :class:`contextvars.Context` for the *callback* to run in. The current + context is used when no *context* is provided. + :ref:`Use functools.partial to pass parameters to the callback <asyncio-pass-keywords>`. For example, ``fut.add_done_callback(functools.partial(print, "Future:", flush=True))`` will call ``print("Future:", fut, flush=True)``. + .. versionchanged:: 3.7 + The *context* keyword-only parameter was added. See :pep:`567` + for more details. + .. method:: remove_done_callback(fn) Remove all instances of a callback from the "call when done" list. @@ -421,8 +429,15 @@ Task Don't directly create :class:`Task` instances: use the :func:`create_task` function or the :meth:`AbstractEventLoop.create_task` method. + Tasks support the :mod:`contextvars` module. When a Task + is created it copies the current context and later runs its coroutine + in the copied context. See :pep:`567` for more details. + This class is :ref:`not thread safe <asyncio-multithreading>`. + .. versionchanged:: 3.7 + Added support for the :mod:`contextvars` module. + .. classmethod:: all_tasks(loop=None) Return a set of all tasks for an event loop. diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index ac697191b50d..af2aad9e81e7 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -608,6 +608,17 @@ include: destroying the event loop. (Contributed by Yury Selivanov in :issue:`32314`.) +* asyncio gained support for :mod:`contextvars`. + :meth:`loop.call_soon() <asyncio.AbstractEventLoop.call_soon>`, + :meth:`loop.call_soon_threadsafe() <asyncio.AbstractEventLoop.call_soon_threadsafe>`, + :meth:`loop.call_later() <asyncio.AbstractEventLoop.call_later>`, + :meth:`loop.call_at() <asyncio.AbstractEventLoop.call_at>`, and + :meth:`Future.add_done_callback() <asyncio.Future.add_done_callback>` + have a new optional keyword-only *context* parameter. + :class:`Tasks <asyncio.Task>` now track their context automatically. + See :pep:`567` for more details. + (Contributed by Yury Selivanov in :issue:`32436`.) + * The new :func:`asyncio.create_task` function has been added as a shortcut to ``asyncio.get_event_loop().create_task()``. (Contributed by Andrew Svetlov in :issue:`32311`.) diff --git a/Misc/NEWS.d/next/Documentation/2018-05-23-11-59-51.bpo-32436.S1LGPa.rst b/Misc/NEWS.d/next/Documentation/2018-05-23-11-59-51.bpo-32436.S1LGPa.rst new file mode 100644 index 000000000000..8eeb561921a8 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2018-05-23-11-59-51.bpo-32436.S1LGPa.rst @@ -0,0 +1 @@ +Document PEP 567 changes to asyncio. From webhook-mailer at python.org Wed May 23 13:59:21 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 23 May 2018 17:59:21 -0000 Subject: [Python-checkins] bpo-32436: Document PEP 567 changes to asyncio. (GH-7073) Message-ID: <mailman.33.1527098364.18020.python-checkins@python.org> https://github.com/python/cpython/commit/2fc443c469fb15033b6b96acd727e2e7cc147adc commit: 2fc443c469fb15033b6b96acd727e2e7cc147adc branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-23T10:59:17-07:00 summary: bpo-32436: Document PEP 567 changes to asyncio. (GH-7073) (cherry picked from commit 28b9178023a445b1da2694774c265cd4b7a244ec) Co-authored-by: Yury Selivanov <yury at magic.io> files: A Misc/NEWS.d/next/Documentation/2018-05-23-11-59-51.bpo-32436.S1LGPa.rst M Doc/library/asyncio-eventloop.rst M Doc/library/asyncio-task.rst M Doc/whatsnew/3.7.rst diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index 2770fa6f8acd..9d7f2362b3d1 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -124,7 +124,7 @@ keywords to your callback, use :func:`functools.partial`. For example, parameters in debug mode, whereas ``lambda`` functions have a poor representation. -.. method:: AbstractEventLoop.call_soon(callback, \*args) +.. method:: AbstractEventLoop.call_soon(callback, *args, context=None) Arrange for a callback to be called as soon as possible. The callback is called after :meth:`call_soon` returns, when control returns to the event @@ -137,19 +137,31 @@ keywords to your callback, use :func:`functools.partial`. For example, Any positional arguments after the callback will be passed to the callback when it is called. + An optional keyword-only *context* argument allows specifying a custom + :class:`contextvars.Context` for the *callback* to run in. The current + context is used when no *context* is provided. + An instance of :class:`asyncio.Handle` is returned, which can be used to cancel the callback. :ref:`Use functools.partial to pass keywords to the callback <asyncio-pass-keywords>`. -.. method:: AbstractEventLoop.call_soon_threadsafe(callback, \*args) + .. versionchanged:: 3.7 + The *context* keyword-only parameter was added. See :pep:`567` + for more details. + +.. method:: AbstractEventLoop.call_soon_threadsafe(callback, *args, context=None) Like :meth:`call_soon`, but thread safe. See the :ref:`concurrency and multithreading <asyncio-multithreading>` section of the documentation. + .. versionchanged:: 3.7 + The *context* keyword-only parameter was added. See :pep:`567` + for more details. + .. _asyncio-delayed-calls: @@ -166,7 +178,7 @@ a different clock than :func:`time.time`. Timeouts (relative *delay* or absolute *when*) should not exceed one day. -.. method:: AbstractEventLoop.call_later(delay, callback, *args) +.. method:: AbstractEventLoop.call_later(delay, callback, *args, context=None) Arrange for the *callback* to be called after the given *delay* seconds (either an int or float). @@ -182,10 +194,18 @@ a different clock than :func:`time.time`. is called. If you want the callback to be called with some named arguments, use a closure or :func:`functools.partial`. + An optional keyword-only *context* argument allows specifying a custom + :class:`contextvars.Context` for the *callback* to run in. The current + context is used when no *context* is provided. + :ref:`Use functools.partial to pass keywords to the callback <asyncio-pass-keywords>`. -.. method:: AbstractEventLoop.call_at(when, callback, *args) + .. versionchanged:: 3.7 + The *context* keyword-only parameter was added. See :pep:`567` + for more details. + +.. method:: AbstractEventLoop.call_at(when, callback, *args, context=None) Arrange for the *callback* to be called at the given absolute timestamp *when* (an int or float), using the same time reference as @@ -199,6 +219,10 @@ a different clock than :func:`time.time`. :ref:`Use functools.partial to pass keywords to the callback <asyncio-pass-keywords>`. + .. versionchanged:: 3.7 + The *context* keyword-only parameter was added. See :pep:`567` + for more details. + .. method:: AbstractEventLoop.time() Return the current time, as a :class:`float` value, according to the diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index 2488a909ec00..4892333d8cee 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -275,19 +275,27 @@ Future :exc:`CancelledError`. If the future isn't done yet, raises :exc:`InvalidStateError`. - .. method:: add_done_callback(fn) + .. method:: add_done_callback(callback, *, context=None) Add a callback to be run when the future becomes done. - The callback is called with a single argument - the future object. If the + The *callback* is called with a single argument - the future object. If the future is already done when this is called, the callback is scheduled with :meth:`~AbstractEventLoop.call_soon`. + An optional keyword-only *context* argument allows specifying a custom + :class:`contextvars.Context` for the *callback* to run in. The current + context is used when no *context* is provided. + :ref:`Use functools.partial to pass parameters to the callback <asyncio-pass-keywords>`. For example, ``fut.add_done_callback(functools.partial(print, "Future:", flush=True))`` will call ``print("Future:", fut, flush=True)``. + .. versionchanged:: 3.7 + The *context* keyword-only parameter was added. See :pep:`567` + for more details. + .. method:: remove_done_callback(fn) Remove all instances of a callback from the "call when done" list. @@ -421,8 +429,15 @@ Task Don't directly create :class:`Task` instances: use the :func:`create_task` function or the :meth:`AbstractEventLoop.create_task` method. + Tasks support the :mod:`contextvars` module. When a Task + is created it copies the current context and later runs its coroutine + in the copied context. See :pep:`567` for more details. + This class is :ref:`not thread safe <asyncio-multithreading>`. + .. versionchanged:: 3.7 + Added support for the :mod:`contextvars` module. + .. classmethod:: all_tasks(loop=None) Return a set of all tasks for an event loop. diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index ac697191b50d..af2aad9e81e7 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -608,6 +608,17 @@ include: destroying the event loop. (Contributed by Yury Selivanov in :issue:`32314`.) +* asyncio gained support for :mod:`contextvars`. + :meth:`loop.call_soon() <asyncio.AbstractEventLoop.call_soon>`, + :meth:`loop.call_soon_threadsafe() <asyncio.AbstractEventLoop.call_soon_threadsafe>`, + :meth:`loop.call_later() <asyncio.AbstractEventLoop.call_later>`, + :meth:`loop.call_at() <asyncio.AbstractEventLoop.call_at>`, and + :meth:`Future.add_done_callback() <asyncio.Future.add_done_callback>` + have a new optional keyword-only *context* parameter. + :class:`Tasks <asyncio.Task>` now track their context automatically. + See :pep:`567` for more details. + (Contributed by Yury Selivanov in :issue:`32436`.) + * The new :func:`asyncio.create_task` function has been added as a shortcut to ``asyncio.get_event_loop().create_task()``. (Contributed by Andrew Svetlov in :issue:`32311`.) diff --git a/Misc/NEWS.d/next/Documentation/2018-05-23-11-59-51.bpo-32436.S1LGPa.rst b/Misc/NEWS.d/next/Documentation/2018-05-23-11-59-51.bpo-32436.S1LGPa.rst new file mode 100644 index 000000000000..8eeb561921a8 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2018-05-23-11-59-51.bpo-32436.S1LGPa.rst @@ -0,0 +1 @@ +Document PEP 567 changes to asyncio. From webhook-mailer at python.org Wed May 23 15:58:26 2018 From: webhook-mailer at python.org (Ned Deily) Date: Wed, 23 May 2018 19:58:26 -0000 Subject: [Python-checkins] bpo-33612: Remove PyThreadState_Clear() assertion (GH-7069) (GH-7074) Message-ID: <mailman.34.1527105509.18020.python-checkins@python.org> https://github.com/python/cpython/commit/508d7693bc09affd99fdaa4a321cc3da0638c8a0 commit: 508d7693bc09affd99fdaa4a321cc3da0638c8a0 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Ned Deily <nad at python.org> date: 2018-05-23T15:58:21-04:00 summary: bpo-33612: Remove PyThreadState_Clear() assertion (GH-7069) (GH-7074) bpo-25612, bpo-33612: Remove an assertion from PyThreadState_Clear() which failed at Python shutdown or on fork if a thread was running a generator. (cherry picked from commit b6dccf54fd3bac9c87348d96f9d6b571608c15bc) Co-authored-by: Victor Stinner <vstinner at redhat.com> files: M Python/pystate.c diff --git a/Python/pystate.c b/Python/pystate.c index 7750f4ca8a55..15761e7da90f 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -581,7 +581,6 @@ PyThreadState_Clear(PyThreadState *tstate) Py_CLEAR(tstate->exc_state.exc_traceback); /* The stack of exception states should contain just this thread. */ - assert(tstate->exc_info->previous_item == NULL); if (Py_VerboseFlag && tstate->exc_info != &tstate->exc_state) { fprintf(stderr, "PyThreadState_Clear: warning: thread still has a generator\n"); From webhook-mailer at python.org Wed May 23 16:24:54 2018 From: webhook-mailer at python.org (Christian Heimes) Date: Wed, 23 May 2018 20:24:54 -0000 Subject: [Python-checkins] bpo-33618: Enable TLS 1.3 in tests (GH-7079) Message-ID: <mailman.35.1527107096.18020.python-checkins@python.org> https://github.com/python/cpython/commit/529525fb5a8fd9b96ab4021311a598c77588b918 commit: 529525fb5a8fd9b96ab4021311a598c77588b918 branch: master author: Christian Heimes <christian at python.org> committer: GitHub <noreply at github.com> date: 2018-05-23T22:24:45+02:00 summary: bpo-33618: Enable TLS 1.3 in tests (GH-7079) TLS 1.3 behaves slightly different than TLS 1.2. Session tickets and TLS client cert auth are now handled after the initialy handshake. Tests now either send/recv data to trigger session and client certs. Or tests ignore ConnectionResetError / BrokenPipeError on the server side to handle clients that force-close the socket fd. To test TLS 1.3, OpenSSL 1.1.1-pre7-dev (git master + OpenSSL PR https://github.com/openssl/openssl/pull/6340) is required. Signed-off-by: Christian Heimes <christian at python.org> files: A Misc/NEWS.d/next/Library/2018-05-23-20-14-34.bpo-33618.xU39lr.rst M Doc/library/ssl.rst M Doc/whatsnew/3.7.rst M Lib/test/test_asyncio/test_sslproto.py M Lib/test/test_asyncio/utils.py M Lib/test/test_ftplib.py M Lib/test/test_poplib.py M Lib/test/test_ssl.py M Tools/ssl/multissltests.py diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 2ccea13b6142..14eac2c58947 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -2587,7 +2587,33 @@ successful call of :func:`~ssl.RAND_add`, :func:`~ssl.RAND_bytes` or :func:`~ssl.RAND_pseudo_bytes` is sufficient. -.. ssl-libressl: +.. _ssl-tlsv1_3: + +TLS 1.3 +------- + +.. versionadded:: 3.7 + +Python has provisional and experimental support for TLS 1.3 with OpenSSL +1.1.1. The new protocol behaves slightly differently than previous version +of TLS/SSL. Some new TLS 1.3 features are not yet available. + +- TLS 1.3 uses a disjunct set of cipher suites. All AES-GCM and + ChaCha20 cipher suites are enabled by default. The method + :meth:`SSLContext.set_ciphers` cannot enable or disable any TLS 1.3 + ciphers yet, but :meth:`SSLContext.get_cipers` returns them. +- Session tickets are no longer sent as part of the initial handshake and + are handled differently. :attr:`SSLSocket.session` and :class:`SSLSession` + are not compatible with TLS 1.3. +- Client-side certificates are also no longer verified during the initial + handshake. A server can request a certificate at any time. Clients + process certificate requests while they send or receive application data + from the server. +- TLS 1.3 features like early data, deferred TLS client cert request, + signature algorithm configuration, and rekeying are not supported yet. + + +.. _ssl-libressl: LibreSSL support ---------------- diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index af2aad9e81e7..46015af3e739 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -1244,8 +1244,8 @@ Host name validation can be customized with .. note:: The improved host name check requires a *libssl* implementation compatible with OpenSSL 1.0.2 or 1.1. Consequently, OpenSSL 0.9.8 and 1.0.1 are no - longer supported and LibreSSL is temporarily not supported until it gains - the necessary OpenSSL 1.0.2 APIs. + longer supported. The ssl module is mostly compatible with LibreSSL 2.7.2 + and newer. The ``ssl`` module no longer sends IP addresses in SNI TLS extension. (Contributed by Christian Heimes in :issue:`32185`.) @@ -1270,8 +1270,12 @@ rather than the U-label form (``"pyth?n.org"``). (Contributed by Nathaniel J. Smith and Christian Heimes in :issue:`28414`.) The ``ssl`` module has preliminary and experimental support for TLS 1.3 and -OpenSSL 1.1.1. (Contributed by Christian Heimes in :issue:`32947`, -:issue:`20995`, :issue:`29136`, and :issue:`30622`) +OpenSSL 1.1.1. At the time of Python 3.7.0 release, OpenSSL 1.1.1 is still +under development and TLS 1.3 hasn't been finalized yet. The TLS 1.3 +handshake and protocol behaves slightly differently than TLS 1.2 and earlier, +see :ref:`ssl-tlsv1_3`. +(Contributed by Christian Heimes in :issue:`32947`, :issue:`20995`, +:issue:`29136`, :issue:`30622` and :issue:`33618`) :class:`~ssl.SSLSocket` and :class:`~ssl.SSLObject` no longer have a public constructor. Direct instantiation was never a documented and supported diff --git a/Lib/test/test_asyncio/test_sslproto.py b/Lib/test/test_asyncio/test_sslproto.py index 7b27f4cfa322..c534a341352b 100644 --- a/Lib/test/test_asyncio/test_sslproto.py +++ b/Lib/test/test_asyncio/test_sslproto.py @@ -251,6 +251,8 @@ def test_start_tls_server_1(self): server_context = test_utils.simple_server_sslcontext() client_context = test_utils.simple_client_sslcontext() + # TODO: fix TLSv1.3 support + client_context.options |= ssl.OP_NO_TLSv1_3 def client(sock, addr): time.sleep(0.5) diff --git a/Lib/test/test_asyncio/utils.py b/Lib/test/test_asyncio/utils.py index 711085fde5c5..96dfe2f85b4d 100644 --- a/Lib/test/test_asyncio/utils.py +++ b/Lib/test/test_asyncio/utils.py @@ -74,8 +74,6 @@ def simple_server_sslcontext(): server_context.load_cert_chain(ONLYCERT, ONLYKEY) server_context.check_hostname = False server_context.verify_mode = ssl.CERT_NONE - # TODO: fix TLSv1.3 support - server_context.options |= ssl.OP_NO_TLSv1_3 return server_context diff --git a/Lib/test/test_ftplib.py b/Lib/test/test_ftplib.py index 1a8e2f91d386..f9488a96cfca 100644 --- a/Lib/test/test_ftplib.py +++ b/Lib/test/test_ftplib.py @@ -257,6 +257,7 @@ class DummyFTPServer(asyncore.dispatcher, threading.Thread): def __init__(self, address, af=socket.AF_INET): threading.Thread.__init__(self) asyncore.dispatcher.__init__(self) + self.daemon = True self.create_socket(af, socket.SOCK_STREAM) self.bind(address) self.listen(5) @@ -312,8 +313,6 @@ class SSLConnection(asyncore.dispatcher): def secure_connection(self): context = ssl.SSLContext() - # TODO: fix TLSv1.3 support - context.options |= ssl.OP_NO_TLSv1_3 context.load_cert_chain(CERTFILE) socket = context.wrap_socket(self.socket, suppress_ragged_eofs=False, @@ -405,7 +404,7 @@ def handle_error(self): def close(self): if (isinstance(self.socket, ssl.SSLSocket) and - self.socket._sslobj is not None): + self.socket._sslobj is not None): self._do_ssl_shutdown() else: super(SSLConnection, self).close() @@ -910,8 +909,6 @@ def test_auth_issued_twice(self): def test_context(self): self.client.quit() ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) - # TODO: fix TLSv1.3 support - ctx.options |= ssl.OP_NO_TLSv1_3 ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE self.assertRaises(ValueError, ftplib.FTP_TLS, keyfile=CERTFILE, @@ -944,8 +941,6 @@ def test_ccc(self): def test_check_hostname(self): self.client.quit() ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) - # TODO: fix TLSv1.3 support - ctx.options |= ssl.OP_NO_TLSv1_3 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED) self.assertEqual(ctx.check_hostname, True) ctx.load_verify_locations(CAFILE) @@ -982,6 +977,7 @@ def setUp(self): self.sock.settimeout(20) self.port = support.bind_port(self.sock) self.server_thread = threading.Thread(target=self.server) + self.server_thread.daemon = True self.server_thread.start() # Wait for the server to be ready. self.evt.wait() diff --git a/Lib/test/test_poplib.py b/Lib/test/test_poplib.py index bbedbbdb10a1..20d4eeac12d4 100644 --- a/Lib/test/test_poplib.py +++ b/Lib/test/test_poplib.py @@ -153,8 +153,6 @@ def cmd_stls(self, arg): if self.tls_active is False: self.push('+OK Begin TLS negotiation') context = ssl.SSLContext() - # TODO: fix TLSv1.3 support - context.options |= ssl.OP_NO_TLSv1_3 context.load_cert_chain(CERTFILE) tls_sock = context.wrap_socket(self.socket, server_side=True, @@ -206,6 +204,7 @@ class DummyPOP3Server(asyncore.dispatcher, threading.Thread): def __init__(self, address, af=socket.AF_INET): threading.Thread.__init__(self) asyncore.dispatcher.__init__(self) + self.daemon = True self.create_socket(af, socket.SOCK_STREAM) self.bind(address) self.listen(5) @@ -370,8 +369,6 @@ def test_stls(self): def test_stls_context(self): expected = b'+OK Begin TLS negotiation' ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) - # TODO: fix TLSv1.3 support - ctx.options |= ssl.OP_NO_TLSv1_3 ctx.load_verify_locations(CAFILE) self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED) self.assertEqual(ctx.check_hostname, True) @@ -412,8 +409,6 @@ def test__all__(self): def test_context(self): ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) - # TODO: fix TLSv1.3 support - ctx.options |= ssl.OP_NO_TLSv1_3 ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE self.assertRaises(ValueError, poplib.POP3_SSL, self.server.host, @@ -482,7 +477,7 @@ def setUp(self): self.sock.settimeout(60) # Safety net. Look issue 11812 self.port = test_support.bind_port(self.sock) self.thread = threading.Thread(target=self.server, args=(self.evt,self.sock)) - self.thread.setDaemon(True) + self.thread.daemon = True self.thread.start() self.evt.wait() diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 03952b10a8e7..73d3e3bbcdae 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -1826,6 +1826,7 @@ def test_connect_capath(self): s.connect(self.server_addr) cert = s.getpeercert() self.assertTrue(cert) + # Same with a bytes `capath` argument ctx = ssl.SSLContext(ssl.PROTOCOL_TLS) ctx.verify_mode = ssl.CERT_REQUIRED @@ -1841,8 +1842,6 @@ def test_connect_cadata(self): der = ssl.PEM_cert_to_DER_cert(pem) ctx = ssl.SSLContext(ssl.PROTOCOL_TLS) ctx.verify_mode = ssl.CERT_REQUIRED - # TODO: fix TLSv1.3 support - ctx.options |= ssl.OP_NO_TLSv1_3 ctx.load_verify_locations(cadata=pem) with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s: s.connect(self.server_addr) @@ -1852,8 +1851,6 @@ def test_connect_cadata(self): # same with DER ctx = ssl.SSLContext(ssl.PROTOCOL_TLS) ctx.verify_mode = ssl.CERT_REQUIRED - # TODO: fix TLSv1.3 support - ctx.options |= ssl.OP_NO_TLSv1_3 ctx.load_verify_locations(cadata=der) with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s: s.connect(self.server_addr) @@ -2109,11 +2106,21 @@ def wrap_conn(self): self.sock, server_side=True) self.server.selected_npn_protocols.append(self.sslconn.selected_npn_protocol()) self.server.selected_alpn_protocols.append(self.sslconn.selected_alpn_protocol()) - except (ssl.SSLError, ConnectionResetError, OSError) as e: + except (ConnectionResetError, BrokenPipeError) as e: # We treat ConnectionResetError as though it were an # SSLError - OpenSSL on Ubuntu abruptly closes the # connection when asked to use an unsupported protocol. # + # BrokenPipeError is raised in TLS 1.3 mode, when OpenSSL + # tries to send session tickets after handshake. + # https://github.com/openssl/openssl/issues/6342 + self.server.conn_errors.append(str(e)) + if self.server.chatty: + handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n") + self.running = False + self.close() + return False + except (ssl.SSLError, OSError) as e: # OSError may occur with wrong protocols, e.g. both # sides use PROTOCOL_TLS_SERVER. # @@ -2220,11 +2227,22 @@ def run(self): sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n" % (msg, ctype, msg.lower(), ctype)) self.write(msg.lower()) + except ConnectionResetError: + # XXX: OpenSSL 1.1.1 sometimes raises ConnectionResetError + # when connection is not shut down gracefully. + if self.server.chatty and support.verbose: + sys.stdout.write( + " Connection reset by peer: {}\n".format( + self.addr) + ) + self.close() + self.running = False except OSError: if self.server.chatty: handle_error("Test server failure:\n") self.close() self.running = False + # normally, we'd just stop here, but for the test # harness, we want to stop the server self.server.stop() @@ -2299,6 +2317,11 @@ def run(self): pass except KeyboardInterrupt: self.stop() + except BaseException as e: + if support.verbose and self.chatty: + sys.stdout.write( + ' connection handling failed: ' + repr(e) + '\n') + self.sock.close() def stop(self): @@ -2745,8 +2768,6 @@ def test_check_hostname_idn(self): server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) server_context.load_cert_chain(IDNSANSFILE) - # TODO: fix TLSv1.3 support - server_context.options |= ssl.OP_NO_TLSv1_3 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) context.verify_mode = ssl.CERT_REQUIRED @@ -2797,7 +2818,7 @@ def test_check_hostname_idn(self): with self.assertRaises(ssl.CertificateError): s.connect((HOST, server.port)) - def test_wrong_cert(self): + def test_wrong_cert_tls12(self): """Connecting when the server rejects the client's certificate Launch a server with CERT_REQUIRED, and check that trying to @@ -2808,9 +2829,8 @@ def test_wrong_cert(self): client_context.load_cert_chain(WRONG_CERT) # require TLS client authentication server_context.verify_mode = ssl.CERT_REQUIRED - # TODO: fix TLSv1.3 support - # With TLS 1.3, test fails with exception in server thread - server_context.options |= ssl.OP_NO_TLSv1_3 + # TLS 1.3 has different handshake + client_context.maximum_version = ssl.TLSVersion.TLSv1_2 server = ThreadedEchoServer( context=server_context, chatty=True, connectionchatty=True, @@ -2835,6 +2855,36 @@ def test_wrong_cert(self): else: self.fail("Use of invalid cert should have failed!") + @unittest.skipUnless(ssl.HAS_TLSv1_3, "Test needs TLS 1.3") + def test_wrong_cert_tls13(self): + client_context, server_context, hostname = testing_context() + client_context.load_cert_chain(WRONG_CERT) + server_context.verify_mode = ssl.CERT_REQUIRED + server_context.minimum_version = ssl.TLSVersion.TLSv1_3 + client_context.minimum_version = ssl.TLSVersion.TLSv1_3 + + server = ThreadedEchoServer( + context=server_context, chatty=True, connectionchatty=True, + ) + with server, \ + client_context.wrap_socket(socket.socket(), + server_hostname=hostname) as s: + # TLS 1.3 perform client cert exchange after handshake + s.connect((HOST, server.port)) + try: + s.write(b'data') + s.read(4) + except ssl.SSLError as e: + if support.verbose: + sys.stdout.write("\nSSLError is %r\n" % e) + except OSError as e: + if e.errno != errno.ECONNRESET: + raise + if support.verbose: + sys.stdout.write("\nsocket.error is %r\n" % e) + else: + self.fail("Use of invalid cert should have failed!") + def test_rude_shutdown(self): """A brutal shutdown of an SSL server should raise an OSError in the client when attempting handshake. @@ -3405,7 +3455,7 @@ def serve(): # Block on the accept and wait on the connection to close. evt.set() remote, peer = server.accept() - remote.recv(1) + remote.send(remote.recv(4)) t = threading.Thread(target=serve) t.start() @@ -3413,6 +3463,8 @@ def serve(): evt.wait() client = context.wrap_socket(socket.socket()) client.connect((host, port)) + client.send(b'data') + client.recv() client_addr = client.getsockname() client.close() t.join() @@ -3465,7 +3517,7 @@ def test_version_basic(self): self.assertIs(s.version(), None) self.assertIs(s._sslobj, None) s.connect((HOST, server.port)) - if ssl.OPENSSL_VERSION_INFO >= (1, 1, 1): + if IS_OPENSSL_1_1_1 and ssl.HAS_TLSv1_3: self.assertEqual(s.version(), 'TLSv1.3') elif ssl.OPENSSL_VERSION_INFO >= (1, 0, 2): self.assertEqual(s.version(), 'TLSv1.2') @@ -3574,8 +3626,6 @@ def test_tls_unique_channel_binding(self): sys.stdout.write("\n") client_context, server_context, hostname = testing_context() - # TODO: fix TLSv1.3 support - client_context.options |= ssl.OP_NO_TLSv1_3 server = ThreadedEchoServer(context=server_context, chatty=True, @@ -3594,7 +3644,10 @@ def test_tls_unique_channel_binding(self): # check if it is sane self.assertIsNotNone(cb_data) - self.assertEqual(len(cb_data), 12) # True for TLSv1 + if s.version() == 'TLSv1.3': + self.assertEqual(len(cb_data), 48) + else: + self.assertEqual(len(cb_data), 12) # True for TLSv1 # and compare with the peers version s.write(b"CB tls-unique\n") @@ -3616,7 +3669,10 @@ def test_tls_unique_channel_binding(self): # is it really unique self.assertNotEqual(cb_data, new_cb_data) self.assertIsNotNone(cb_data) - self.assertEqual(len(cb_data), 12) # True for TLSv1 + if s.version() == 'TLSv1.3': + self.assertEqual(len(cb_data), 48) + else: + self.assertEqual(len(cb_data), 12) # True for TLSv1 s.write(b"CB tls-unique\n") peer_data_repr = s.read().strip() self.assertEqual(peer_data_repr, diff --git a/Misc/NEWS.d/next/Library/2018-05-23-20-14-34.bpo-33618.xU39lr.rst b/Misc/NEWS.d/next/Library/2018-05-23-20-14-34.bpo-33618.xU39lr.rst new file mode 100644 index 000000000000..6cc2452b145c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-23-20-14-34.bpo-33618.xU39lr.rst @@ -0,0 +1,2 @@ +Finalize and document preliminary and experimental TLS 1.3 support with +OpenSSL 1.1.1 diff --git a/Tools/ssl/multissltests.py b/Tools/ssl/multissltests.py index bbc5c6652098..c4ebe317797d 100755 --- a/Tools/ssl/multissltests.py +++ b/Tools/ssl/multissltests.py @@ -47,7 +47,7 @@ OPENSSL_RECENT_VERSIONS = [ "1.0.2o", "1.1.0h", - "1.1.1-pre6", + # "1.1.1-pre7", ] LIBRESSL_OLD_VERSIONS = [ @@ -73,7 +73,7 @@ parser.add_argument( '--debug', action='store_true', - help="Enable debug mode", + help="Enable debug logging", ) parser.add_argument( '--disable-ancient', @@ -130,6 +130,18 @@ default='', help="Override the automatic system type detection." ) +parser.add_argument( + '--force', + action='store_true', + dest='force', + help="Force build and installation." +) +parser.add_argument( + '--keep-sources', + action='store_true', + dest='keep_sources', + help="Keep original sources for debugging." +) class AbstractBuilder(object): @@ -260,26 +272,31 @@ def _build_src(self): """Now build openssl""" log.info("Running build in {}".format(self.build_dir)) cwd = self.build_dir - cmd = ["./config", "shared", "--prefix={}".format(self.install_dir)] - env = None + cmd = [ + "./config", + "shared", "--debug", + "--prefix={}".format(self.install_dir) + ] + env = os.environ.copy() + # set rpath + env["LD_RUN_PATH"] = self.lib_dir if self.system: - env = os.environ.copy() env['SYSTEM'] = self.system self._subprocess_call(cmd, cwd=cwd, env=env) # Old OpenSSL versions do not support parallel builds. self._subprocess_call(["make", "-j1"], cwd=cwd, env=env) - def _make_install(self, remove=True): + def _make_install(self): self._subprocess_call( ["make", "-j1", self.install_target], cwd=self.build_dir ) - if remove: + if not self.args.keep_sources: shutil.rmtree(self.build_dir) def install(self): log.info(self.openssl_cli) - if not self.has_openssl: + if not self.has_openssl or self.args.force: if not self.has_src: self._download_src() else: From webhook-mailer at python.org Wed May 23 16:49:15 2018 From: webhook-mailer at python.org (Christian Heimes) Date: Wed, 23 May 2018 20:49:15 -0000 Subject: [Python-checkins] [3.7] bpo-33618: Enable TLS 1.3 in tests (GH-7079) (GH-7082) Message-ID: <mailman.36.1527108557.18020.python-checkins@python.org> https://github.com/python/cpython/commit/72ef4fc32b354f8e56eec64f4c15ac2e07d118be commit: 72ef4fc32b354f8e56eec64f4c15ac2e07d118be branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Christian Heimes <christian at python.org> date: 2018-05-23T22:49:04+02:00 summary: [3.7] bpo-33618: Enable TLS 1.3 in tests (GH-7079) (GH-7082) TLS 1.3 behaves slightly different than TLS 1.2. Session tickets and TLS client cert auth are now handled after the initialy handshake. Tests now either send/recv data to trigger session and client certs. Or tests ignore ConnectionResetError / BrokenPipeError on the server side to handle clients that force-close the socket fd. To test TLS 1.3, OpenSSL 1.1.1-pre7-dev (git master + OpenSSL PR https://github.com/openssl/openssl/pull/6340) is required. Signed-off-by: Christian Heimes <christian at python.org> (cherry picked from commit 529525fb5a8fd9b96ab4021311a598c77588b918) files: A Misc/NEWS.d/next/Library/2018-05-23-20-14-34.bpo-33618.xU39lr.rst M Doc/library/ssl.rst M Doc/whatsnew/3.7.rst M Lib/test/test_asyncio/test_sslproto.py M Lib/test/test_asyncio/utils.py M Lib/test/test_ftplib.py M Lib/test/test_poplib.py M Lib/test/test_ssl.py M Tools/ssl/multissltests.py diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 2ccea13b6142..14eac2c58947 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -2587,7 +2587,33 @@ successful call of :func:`~ssl.RAND_add`, :func:`~ssl.RAND_bytes` or :func:`~ssl.RAND_pseudo_bytes` is sufficient. -.. ssl-libressl: +.. _ssl-tlsv1_3: + +TLS 1.3 +------- + +.. versionadded:: 3.7 + +Python has provisional and experimental support for TLS 1.3 with OpenSSL +1.1.1. The new protocol behaves slightly differently than previous version +of TLS/SSL. Some new TLS 1.3 features are not yet available. + +- TLS 1.3 uses a disjunct set of cipher suites. All AES-GCM and + ChaCha20 cipher suites are enabled by default. The method + :meth:`SSLContext.set_ciphers` cannot enable or disable any TLS 1.3 + ciphers yet, but :meth:`SSLContext.get_cipers` returns them. +- Session tickets are no longer sent as part of the initial handshake and + are handled differently. :attr:`SSLSocket.session` and :class:`SSLSession` + are not compatible with TLS 1.3. +- Client-side certificates are also no longer verified during the initial + handshake. A server can request a certificate at any time. Clients + process certificate requests while they send or receive application data + from the server. +- TLS 1.3 features like early data, deferred TLS client cert request, + signature algorithm configuration, and rekeying are not supported yet. + + +.. _ssl-libressl: LibreSSL support ---------------- diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index af2aad9e81e7..46015af3e739 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -1244,8 +1244,8 @@ Host name validation can be customized with .. note:: The improved host name check requires a *libssl* implementation compatible with OpenSSL 1.0.2 or 1.1. Consequently, OpenSSL 0.9.8 and 1.0.1 are no - longer supported and LibreSSL is temporarily not supported until it gains - the necessary OpenSSL 1.0.2 APIs. + longer supported. The ssl module is mostly compatible with LibreSSL 2.7.2 + and newer. The ``ssl`` module no longer sends IP addresses in SNI TLS extension. (Contributed by Christian Heimes in :issue:`32185`.) @@ -1270,8 +1270,12 @@ rather than the U-label form (``"pyth?n.org"``). (Contributed by Nathaniel J. Smith and Christian Heimes in :issue:`28414`.) The ``ssl`` module has preliminary and experimental support for TLS 1.3 and -OpenSSL 1.1.1. (Contributed by Christian Heimes in :issue:`32947`, -:issue:`20995`, :issue:`29136`, and :issue:`30622`) +OpenSSL 1.1.1. At the time of Python 3.7.0 release, OpenSSL 1.1.1 is still +under development and TLS 1.3 hasn't been finalized yet. The TLS 1.3 +handshake and protocol behaves slightly differently than TLS 1.2 and earlier, +see :ref:`ssl-tlsv1_3`. +(Contributed by Christian Heimes in :issue:`32947`, :issue:`20995`, +:issue:`29136`, :issue:`30622` and :issue:`33618`) :class:`~ssl.SSLSocket` and :class:`~ssl.SSLObject` no longer have a public constructor. Direct instantiation was never a documented and supported diff --git a/Lib/test/test_asyncio/test_sslproto.py b/Lib/test/test_asyncio/test_sslproto.py index 7b27f4cfa322..c534a341352b 100644 --- a/Lib/test/test_asyncio/test_sslproto.py +++ b/Lib/test/test_asyncio/test_sslproto.py @@ -251,6 +251,8 @@ def test_start_tls_server_1(self): server_context = test_utils.simple_server_sslcontext() client_context = test_utils.simple_client_sslcontext() + # TODO: fix TLSv1.3 support + client_context.options |= ssl.OP_NO_TLSv1_3 def client(sock, addr): time.sleep(0.5) diff --git a/Lib/test/test_asyncio/utils.py b/Lib/test/test_asyncio/utils.py index 711085fde5c5..96dfe2f85b4d 100644 --- a/Lib/test/test_asyncio/utils.py +++ b/Lib/test/test_asyncio/utils.py @@ -74,8 +74,6 @@ def simple_server_sslcontext(): server_context.load_cert_chain(ONLYCERT, ONLYKEY) server_context.check_hostname = False server_context.verify_mode = ssl.CERT_NONE - # TODO: fix TLSv1.3 support - server_context.options |= ssl.OP_NO_TLSv1_3 return server_context diff --git a/Lib/test/test_ftplib.py b/Lib/test/test_ftplib.py index 1a8e2f91d386..f9488a96cfca 100644 --- a/Lib/test/test_ftplib.py +++ b/Lib/test/test_ftplib.py @@ -257,6 +257,7 @@ class DummyFTPServer(asyncore.dispatcher, threading.Thread): def __init__(self, address, af=socket.AF_INET): threading.Thread.__init__(self) asyncore.dispatcher.__init__(self) + self.daemon = True self.create_socket(af, socket.SOCK_STREAM) self.bind(address) self.listen(5) @@ -312,8 +313,6 @@ class SSLConnection(asyncore.dispatcher): def secure_connection(self): context = ssl.SSLContext() - # TODO: fix TLSv1.3 support - context.options |= ssl.OP_NO_TLSv1_3 context.load_cert_chain(CERTFILE) socket = context.wrap_socket(self.socket, suppress_ragged_eofs=False, @@ -405,7 +404,7 @@ def handle_error(self): def close(self): if (isinstance(self.socket, ssl.SSLSocket) and - self.socket._sslobj is not None): + self.socket._sslobj is not None): self._do_ssl_shutdown() else: super(SSLConnection, self).close() @@ -910,8 +909,6 @@ def test_auth_issued_twice(self): def test_context(self): self.client.quit() ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) - # TODO: fix TLSv1.3 support - ctx.options |= ssl.OP_NO_TLSv1_3 ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE self.assertRaises(ValueError, ftplib.FTP_TLS, keyfile=CERTFILE, @@ -944,8 +941,6 @@ def test_ccc(self): def test_check_hostname(self): self.client.quit() ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) - # TODO: fix TLSv1.3 support - ctx.options |= ssl.OP_NO_TLSv1_3 self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED) self.assertEqual(ctx.check_hostname, True) ctx.load_verify_locations(CAFILE) @@ -982,6 +977,7 @@ def setUp(self): self.sock.settimeout(20) self.port = support.bind_port(self.sock) self.server_thread = threading.Thread(target=self.server) + self.server_thread.daemon = True self.server_thread.start() # Wait for the server to be ready. self.evt.wait() diff --git a/Lib/test/test_poplib.py b/Lib/test/test_poplib.py index bbedbbdb10a1..20d4eeac12d4 100644 --- a/Lib/test/test_poplib.py +++ b/Lib/test/test_poplib.py @@ -153,8 +153,6 @@ def cmd_stls(self, arg): if self.tls_active is False: self.push('+OK Begin TLS negotiation') context = ssl.SSLContext() - # TODO: fix TLSv1.3 support - context.options |= ssl.OP_NO_TLSv1_3 context.load_cert_chain(CERTFILE) tls_sock = context.wrap_socket(self.socket, server_side=True, @@ -206,6 +204,7 @@ class DummyPOP3Server(asyncore.dispatcher, threading.Thread): def __init__(self, address, af=socket.AF_INET): threading.Thread.__init__(self) asyncore.dispatcher.__init__(self) + self.daemon = True self.create_socket(af, socket.SOCK_STREAM) self.bind(address) self.listen(5) @@ -370,8 +369,6 @@ def test_stls(self): def test_stls_context(self): expected = b'+OK Begin TLS negotiation' ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) - # TODO: fix TLSv1.3 support - ctx.options |= ssl.OP_NO_TLSv1_3 ctx.load_verify_locations(CAFILE) self.assertEqual(ctx.verify_mode, ssl.CERT_REQUIRED) self.assertEqual(ctx.check_hostname, True) @@ -412,8 +409,6 @@ def test__all__(self): def test_context(self): ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) - # TODO: fix TLSv1.3 support - ctx.options |= ssl.OP_NO_TLSv1_3 ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE self.assertRaises(ValueError, poplib.POP3_SSL, self.server.host, @@ -482,7 +477,7 @@ def setUp(self): self.sock.settimeout(60) # Safety net. Look issue 11812 self.port = test_support.bind_port(self.sock) self.thread = threading.Thread(target=self.server, args=(self.evt,self.sock)) - self.thread.setDaemon(True) + self.thread.daemon = True self.thread.start() self.evt.wait() diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 9017ad571156..7bbaa9f1e8eb 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -1846,6 +1846,7 @@ def test_connect_capath(self): s.connect(self.server_addr) cert = s.getpeercert() self.assertTrue(cert) + # Same with a bytes `capath` argument ctx = ssl.SSLContext(ssl.PROTOCOL_TLS) ctx.verify_mode = ssl.CERT_REQUIRED @@ -1861,8 +1862,6 @@ def test_connect_cadata(self): der = ssl.PEM_cert_to_DER_cert(pem) ctx = ssl.SSLContext(ssl.PROTOCOL_TLS) ctx.verify_mode = ssl.CERT_REQUIRED - # TODO: fix TLSv1.3 support - ctx.options |= ssl.OP_NO_TLSv1_3 ctx.load_verify_locations(cadata=pem) with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s: s.connect(self.server_addr) @@ -1872,8 +1871,6 @@ def test_connect_cadata(self): # same with DER ctx = ssl.SSLContext(ssl.PROTOCOL_TLS) ctx.verify_mode = ssl.CERT_REQUIRED - # TODO: fix TLSv1.3 support - ctx.options |= ssl.OP_NO_TLSv1_3 ctx.load_verify_locations(cadata=der) with ctx.wrap_socket(socket.socket(socket.AF_INET)) as s: s.connect(self.server_addr) @@ -2129,11 +2126,21 @@ def wrap_conn(self): self.sock, server_side=True) self.server.selected_npn_protocols.append(self.sslconn.selected_npn_protocol()) self.server.selected_alpn_protocols.append(self.sslconn.selected_alpn_protocol()) - except (ssl.SSLError, ConnectionResetError, OSError) as e: + except (ConnectionResetError, BrokenPipeError) as e: # We treat ConnectionResetError as though it were an # SSLError - OpenSSL on Ubuntu abruptly closes the # connection when asked to use an unsupported protocol. # + # BrokenPipeError is raised in TLS 1.3 mode, when OpenSSL + # tries to send session tickets after handshake. + # https://github.com/openssl/openssl/issues/6342 + self.server.conn_errors.append(str(e)) + if self.server.chatty: + handle_error("\n server: bad connection attempt from " + repr(self.addr) + ":\n") + self.running = False + self.close() + return False + except (ssl.SSLError, OSError) as e: # OSError may occur with wrong protocols, e.g. both # sides use PROTOCOL_TLS_SERVER. # @@ -2240,11 +2247,22 @@ def run(self): sys.stdout.write(" server: read %r (%s), sending back %r (%s)...\n" % (msg, ctype, msg.lower(), ctype)) self.write(msg.lower()) + except ConnectionResetError: + # XXX: OpenSSL 1.1.1 sometimes raises ConnectionResetError + # when connection is not shut down gracefully. + if self.server.chatty and support.verbose: + sys.stdout.write( + " Connection reset by peer: {}\n".format( + self.addr) + ) + self.close() + self.running = False except OSError: if self.server.chatty: handle_error("Test server failure:\n") self.close() self.running = False + # normally, we'd just stop here, but for the test # harness, we want to stop the server self.server.stop() @@ -2319,6 +2337,11 @@ def run(self): pass except KeyboardInterrupt: self.stop() + except BaseException as e: + if support.verbose and self.chatty: + sys.stdout.write( + ' connection handling failed: ' + repr(e) + '\n') + self.sock.close() def stop(self): @@ -2766,8 +2789,6 @@ def test_check_hostname_idn(self): server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) server_context.load_cert_chain(IDNSANSFILE) - # TODO: fix TLSv1.3 support - server_context.options |= ssl.OP_NO_TLSv1_3 context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) context.verify_mode = ssl.CERT_REQUIRED @@ -2818,7 +2839,7 @@ def test_check_hostname_idn(self): with self.assertRaises(ssl.CertificateError): s.connect((HOST, server.port)) - def test_wrong_cert(self): + def test_wrong_cert_tls12(self): """Connecting when the server rejects the client's certificate Launch a server with CERT_REQUIRED, and check that trying to @@ -2829,9 +2850,8 @@ def test_wrong_cert(self): client_context.load_cert_chain(WRONG_CERT) # require TLS client authentication server_context.verify_mode = ssl.CERT_REQUIRED - # TODO: fix TLSv1.3 support - # With TLS 1.3, test fails with exception in server thread - server_context.options |= ssl.OP_NO_TLSv1_3 + # TLS 1.3 has different handshake + client_context.maximum_version = ssl.TLSVersion.TLSv1_2 server = ThreadedEchoServer( context=server_context, chatty=True, connectionchatty=True, @@ -2856,6 +2876,36 @@ def test_wrong_cert(self): else: self.fail("Use of invalid cert should have failed!") + @unittest.skipUnless(ssl.HAS_TLSv1_3, "Test needs TLS 1.3") + def test_wrong_cert_tls13(self): + client_context, server_context, hostname = testing_context() + client_context.load_cert_chain(WRONG_CERT) + server_context.verify_mode = ssl.CERT_REQUIRED + server_context.minimum_version = ssl.TLSVersion.TLSv1_3 + client_context.minimum_version = ssl.TLSVersion.TLSv1_3 + + server = ThreadedEchoServer( + context=server_context, chatty=True, connectionchatty=True, + ) + with server, \ + client_context.wrap_socket(socket.socket(), + server_hostname=hostname) as s: + # TLS 1.3 perform client cert exchange after handshake + s.connect((HOST, server.port)) + try: + s.write(b'data') + s.read(4) + except ssl.SSLError as e: + if support.verbose: + sys.stdout.write("\nSSLError is %r\n" % e) + except OSError as e: + if e.errno != errno.ECONNRESET: + raise + if support.verbose: + sys.stdout.write("\nsocket.error is %r\n" % e) + else: + self.fail("Use of invalid cert should have failed!") + def test_rude_shutdown(self): """A brutal shutdown of an SSL server should raise an OSError in the client when attempting handshake. @@ -3432,7 +3482,7 @@ def serve(): # Block on the accept and wait on the connection to close. evt.set() remote, peer = server.accept() - remote.recv(1) + remote.send(remote.recv(4)) t = threading.Thread(target=serve) t.start() @@ -3440,6 +3490,8 @@ def serve(): evt.wait() client = context.wrap_socket(socket.socket()) client.connect((host, port)) + client.send(b'data') + client.recv() client_addr = client.getsockname() client.close() t.join() @@ -3492,7 +3544,7 @@ def test_version_basic(self): self.assertIs(s.version(), None) self.assertIs(s._sslobj, None) s.connect((HOST, server.port)) - if ssl.OPENSSL_VERSION_INFO >= (1, 1, 1): + if IS_OPENSSL_1_1_1 and ssl.HAS_TLSv1_3: self.assertEqual(s.version(), 'TLSv1.3') elif ssl.OPENSSL_VERSION_INFO >= (1, 0, 2): self.assertEqual(s.version(), 'TLSv1.2') @@ -3601,8 +3653,6 @@ def test_tls_unique_channel_binding(self): sys.stdout.write("\n") client_context, server_context, hostname = testing_context() - # TODO: fix TLSv1.3 support - client_context.options |= ssl.OP_NO_TLSv1_3 server = ThreadedEchoServer(context=server_context, chatty=True, @@ -3621,7 +3671,10 @@ def test_tls_unique_channel_binding(self): # check if it is sane self.assertIsNotNone(cb_data) - self.assertEqual(len(cb_data), 12) # True for TLSv1 + if s.version() == 'TLSv1.3': + self.assertEqual(len(cb_data), 48) + else: + self.assertEqual(len(cb_data), 12) # True for TLSv1 # and compare with the peers version s.write(b"CB tls-unique\n") @@ -3643,7 +3696,10 @@ def test_tls_unique_channel_binding(self): # is it really unique self.assertNotEqual(cb_data, new_cb_data) self.assertIsNotNone(cb_data) - self.assertEqual(len(cb_data), 12) # True for TLSv1 + if s.version() == 'TLSv1.3': + self.assertEqual(len(cb_data), 48) + else: + self.assertEqual(len(cb_data), 12) # True for TLSv1 s.write(b"CB tls-unique\n") peer_data_repr = s.read().strip() self.assertEqual(peer_data_repr, diff --git a/Misc/NEWS.d/next/Library/2018-05-23-20-14-34.bpo-33618.xU39lr.rst b/Misc/NEWS.d/next/Library/2018-05-23-20-14-34.bpo-33618.xU39lr.rst new file mode 100644 index 000000000000..6cc2452b145c --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-23-20-14-34.bpo-33618.xU39lr.rst @@ -0,0 +1,2 @@ +Finalize and document preliminary and experimental TLS 1.3 support with +OpenSSL 1.1.1 diff --git a/Tools/ssl/multissltests.py b/Tools/ssl/multissltests.py index bbc5c6652098..c4ebe317797d 100755 --- a/Tools/ssl/multissltests.py +++ b/Tools/ssl/multissltests.py @@ -47,7 +47,7 @@ OPENSSL_RECENT_VERSIONS = [ "1.0.2o", "1.1.0h", - "1.1.1-pre6", + # "1.1.1-pre7", ] LIBRESSL_OLD_VERSIONS = [ @@ -73,7 +73,7 @@ parser.add_argument( '--debug', action='store_true', - help="Enable debug mode", + help="Enable debug logging", ) parser.add_argument( '--disable-ancient', @@ -130,6 +130,18 @@ default='', help="Override the automatic system type detection." ) +parser.add_argument( + '--force', + action='store_true', + dest='force', + help="Force build and installation." +) +parser.add_argument( + '--keep-sources', + action='store_true', + dest='keep_sources', + help="Keep original sources for debugging." +) class AbstractBuilder(object): @@ -260,26 +272,31 @@ def _build_src(self): """Now build openssl""" log.info("Running build in {}".format(self.build_dir)) cwd = self.build_dir - cmd = ["./config", "shared", "--prefix={}".format(self.install_dir)] - env = None + cmd = [ + "./config", + "shared", "--debug", + "--prefix={}".format(self.install_dir) + ] + env = os.environ.copy() + # set rpath + env["LD_RUN_PATH"] = self.lib_dir if self.system: - env = os.environ.copy() env['SYSTEM'] = self.system self._subprocess_call(cmd, cwd=cwd, env=env) # Old OpenSSL versions do not support parallel builds. self._subprocess_call(["make", "-j1"], cwd=cwd, env=env) - def _make_install(self, remove=True): + def _make_install(self): self._subprocess_call( ["make", "-j1", self.install_target], cwd=self.build_dir ) - if remove: + if not self.args.keep_sources: shutil.rmtree(self.build_dir) def install(self): log.info(self.openssl_cli) - if not self.has_openssl: + if not self.has_openssl or self.args.force: if not self.has_src: self._download_src() else: From webhook-mailer at python.org Wed May 23 18:56:12 2018 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 23 May 2018 22:56:12 -0000 Subject: [Python-checkins] bpo-33353: test_asyncio uses smaller sendfile data (#7083) Message-ID: <mailman.37.1527116174.18020.python-checkins@python.org> https://github.com/python/cpython/commit/2932755cc11fd82b4908d60b24b837aa4f3028e6 commit: 2932755cc11fd82b4908d60b24b837aa4f3028e6 branch: master author: Victor Stinner <vstinner at redhat.com> committer: GitHub <noreply at github.com> date: 2018-05-24T00:56:00+02:00 summary: bpo-33353: test_asyncio uses smaller sendfile data (#7083) bpo-32622, bpo-33353: sendfile() tests of test_asyncio use socket buffers of 1 kB "to test on relative small data sets". Send only 160 KiB rather 10 MB to make the test much faster. Shrink also SendfileBase.DATA from 1600 KiB to 160 KiB. On Linux, 3 test_sock_sendfile_mix_with_regular_send() runs now take less than 1 second, instead of 18 seconds. On FreeBSD, the 3 tests didn't hang, but took 3 minutes. Now the 3 tests pass in less than 1 seconds. files: M Lib/test/test_asyncio/test_events.py diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index 66c77b976dce..c9e39b2b0321 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -2095,7 +2095,7 @@ def test_subprocess_shell_invalid_args(self): class SendfileBase: - DATA = b"12345abcde" * 160 * 1024 # 160 KiB + DATA = b"12345abcde" * 16 * 1024 # 160 KiB @classmethod def setUpClass(cls): @@ -2208,7 +2208,7 @@ def test_sock_sendfile_zero_size(self): self.assertEqual(self.file.tell(), 0) def test_sock_sendfile_mix_with_regular_send(self): - buf = b'1234567890' * 1024 * 1024 # 10 MB + buf = b"X" * 160 * 1024 # 160 KiB sock, proto = self.prepare_socksendfile() self.run_loop(self.loop.sock_sendall(sock, buf)) ret = self.run_loop(self.loop.sock_sendfile(sock, self.file)) From lp_benchmark_robot at intel.com Wed May 23 20:39:01 2018 From: lp_benchmark_robot at intel.com (lp_benchmark_robot at intel.com) Date: Wed, 23 May 2018 17:39:01 -0700 Subject: [Python-checkins] [65 flat] Results for Python (master branch) 2018-05-23 Message-ID: <9801cb1e-22ea-435f-a47c-1be5b16c8856@orsmsx155.amr.corp.intel.com> Results for project python/master, build date: 2018-05-23 03:03:33-07:00. - commit: 825aab9 - previous commit: 55bfe69 - revision date: 2018-05-23 08:07:01+03:00 - environment: Broadwell-EP - cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores, stepping 1, LLC 55 MB - mem: 128 GB - os: Ubuntu 16.04.2 LTS - kernel: 4.4.0-62-generic x86_64 GNU/Linux Baseline results were generated using release v3.6.0, with hash 5c4568a from 2016-12-22 23:38:47+00:00. +-----+------------------------+--------+------------+------------+------------+ | | |relative|change since|change since|current rev | | | benchmark|std_dev*| last run | baseline |run with PGO| +-----+------------------------+--------+------------+------------+------------+ | :-| | 2to3| 0.776% | -0.075% | +9.524% | +6.209% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method| 1.835% | -0.293% | +23.617% | +12.138% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_slots| 1.336% | +0.005% | +25.461% | +11.017% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_unknown| 1.181% | -0.125% | +22.257% | +12.867% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_simple| 2.536% | -0.181% | +10.417% | +12.206% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chameleon| 1.419% | +0.963% | +12.743% | +10.194% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chaos| 0.713% | +0.304% | +8.739% | +10.417% | +-----+------------------------+--------+------------+------------+------------+ | :-| | crypto_pyaes| 0.560% | +0.167% | +0.096% | +7.142% | +-----+------------------------+--------+------------+------------+------------+ | :-| | deltablue| 3.817% | +0.206% | +11.878% | +17.139% | +-----+------------------------+--------+------------+------------+------------+ | :-| | django_template| 1.331% | +0.768% | +22.341% | +13.108% | +-----+------------------------+--------+------------+------------+------------+ | :-| | dulwich_log| 1.093% | +0.103% | +5.734% | +7.392% | +-----+------------------------+--------+------------+------------+------------+ | :-| | fannkuch| 0.353% | -0.036% | +7.251% | +4.720% | +-----+------------------------+--------+------------+------------+------------+ | :-| | float| 1.043% | -0.270% | +2.397% | +7.962% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_text| 1.328% | -0.169% | +14.628% | +9.610% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_xml| 1.288% | +0.553% | +11.596% | +9.840% | +-----+------------------------+--------+------------+------------+------------+ | :-| | go| 6.293% | +0.193% | +5.102% | +10.776% | +-----+------------------------+--------+------------+------------+------------+ | :-| | hexiom| 0.516% | +0.239% | +12.064% | +11.061% | +-----+------------------------+--------+------------+------------+------------+ | :-| | html5lib| 2.678% | +0.181% | +12.096% | +10.665% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_dumps| 1.792% | -0.013% | +3.626% | +7.118% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_loads| 5.100% | +0.084% | -4.129% | +14.663% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_format| 1.667% | +0.180% | +18.050% | +11.749% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_silent| 2.593% | -0.620% | +47.743% | +13.887% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_simple| 1.381% | +0.557% | +13.454% | +11.676% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mako| 1.017% | -0.159% | +16.706% | +14.535% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mdp| 7.588% | -1.445% | +0.195% | +18.422% | +-----+------------------------+--------+------------+------------+------------+ | :-| | meteor_contest| 1.155% | +0.224% | +4.742% | +6.341% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nbody| 2.014% | -0.892% | -0.209% | +2.313% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nqueens| 0.974% | -0.178% | +5.547% | +9.145% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pathlib| 1.283% | -0.408% | +2.271% | +10.115% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle| 1.511% | -0.317% | -0.851% | +21.802% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_dict| 0.348% | -0.110% | +7.534% | +11.148% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_list| 0.807% | -0.084% | +6.945% | +15.267% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_pure_python| 6.702% | -1.344% | +10.794% | +10.551% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pidigits| 0.045% | +0.011% | +0.263% | +9.597% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup| 0.121% | +0.065% | +19.137% | +4.963% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup_no_site| 0.086% | +0.011% | +6.154% | +5.294% | +-----+------------------------+--------+------------+------------+------------+ | :-| | raytrace| 1.534% | +0.287% | +9.991% | +12.511% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_compile| 5.469% | +0.726% | +4.520% | +12.709% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_dna| 0.409% | +0.063% | -2.028% | +13.880% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_effbot| 1.213% | +0.111% | -2.293% | +5.117% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_v8| 1.511% | +0.051% | +4.088% | +10.184% | +-----+------------------------+--------+------------+------------+------------+ | :-| | richards| 1.708% | -0.085% | +9.337% | +14.735% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_fft| 0.581% | +0.009% | -1.323% | +6.134% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_lu| 3.883% | +0.510% | +21.966% | +13.606% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_monte_carlo| 1.868% | +0.554% | +5.029% | +5.676% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sor| 1.469% | -0.079% | +15.572% | +9.252% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sparse_mat_mult| 0.884% | +0.907% | -2.939% | +0.973% | +-----+------------------------+--------+------------+------------+------------+ | :-| | spectral_norm| 0.664% | -0.198% | +4.284% | +7.357% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_declarative| 1.657% | -0.216% | +7.479% | +6.425% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_imperative| 4.079% | +0.048% | +8.263% | +4.253% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlite_synth| 4.084% | -0.620% | -0.249% | +11.671% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_expand| 3.311% | -0.028% | +18.015% | +6.921% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_integrate| 1.617% | +0.104% | +18.957% | +6.465% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_str| 4.384% | -0.240% | +19.381% | +8.229% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_sum| 7.044% | -1.657% | +15.913% | +11.411% | +-----+------------------------+--------+------------+------------+------------+ | :-| | telco| 3.522% | +0.013% | +20.053% | +11.124% | +-----+------------------------+--------+------------+------------+------------+ | :-| | tornado_http| 1.143% | +0.109% | +7.726% | +6.418% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpack_sequence| 1.183% | +0.447% | +2.673% | -0.796% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle| 6.427% | +2.759% | +7.778% | +21.532% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_list| 0.551% | +0.406% | -3.261% | +15.630% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_pure_python| 1.804% | -0.224% | +7.312% | +8.223% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_generate| 1.335% | +0.104% | +2.901% | +11.916% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_iterparse| 2.072% | -0.161% | +4.839% | +8.070% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_parse| 1.706% | +0.106% | -5.670% | +12.274% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_process| 1.408% | -0.191% | +4.678% | +11.305% | +-----+------------------------+--------+------------+------------+------------+ * Relative Standard Deviation (Standard Deviation/Average) If this is not displayed properly please visit our results page here: http://languagesperformance.intel.com/65-flat-results-for-python-master-branch-2018-05-23 Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. From webhook-mailer at python.org Wed May 23 20:43:49 2018 From: webhook-mailer at python.org (Victor Stinner) Date: Thu, 24 May 2018 00:43:49 -0000 Subject: [Python-checkins] bpo-33353: test_asyncio set SO_SNDBUF after connect (GH-7086) Message-ID: <mailman.38.1527122629.18020.python-checkins@python.org> https://github.com/python/cpython/commit/b97de3dd86046ac46567146d86a69d4f78ea09db commit: b97de3dd86046ac46567146d86a69d4f78ea09db branch: master author: Victor Stinner <vstinner at redhat.com> committer: GitHub <noreply at github.com> date: 2018-05-24T02:43:45+02:00 summary: bpo-33353: test_asyncio set SO_SNDBUF after connect (GH-7086) bpo-32622, bpo-33353: On macOS, sock.connect() changes the SO_SNDBUF value. Only set SO_SNDBUF and SO_RCVBUF buffer sizes once a socket is connected or binded, not before. files: M Lib/test/test_asyncio/test_events.py diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index c9e39b2b0321..64d726d16d1c 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -2142,11 +2142,15 @@ def connection_lost(self, exc): async def wait_closed(self): await self.fut + def set_socket_opts(self, sock): + # On macOS, SO_SNDBUF is reset by connect(). So this method + # should be called after the socket is connected. + sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 1024) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 1024) + def make_socket(self, cleanup=True): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setblocking(False) - sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 1024) - sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 1024) if cleanup: self.addCleanup(sock.close) return sock @@ -2159,7 +2163,9 @@ def prepare_socksendfile(self): srv_sock.bind((support.HOST, port)) server = self.run_loop(self.loop.create_server( lambda: proto, sock=srv_sock)) + self.set_socket_opts(srv_sock) self.run_loop(self.loop.sock_connect(sock, ('127.0.0.1', port))) + self.set_socket_opts(sock) def cleanup(): if proto.transport is not None: @@ -2264,9 +2270,9 @@ def prepare_sendfile(self, *, is_ssl=False, close_after=0): else: server_hostname = None cli_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + cli_sock.connect((support.HOST, port)) # reduce send socket buffer size to test on relative small data sets cli_sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 1024) - cli_sock.connect((support.HOST, port)) cli_proto = self.MySendfileProto(loop=self.loop) tr, pr = self.run_loop(self.loop.create_connection( lambda: cli_proto, sock=cli_sock, From webhook-mailer at python.org Wed May 23 21:14:48 2018 From: webhook-mailer at python.org (Victor Stinner) Date: Thu, 24 May 2018 01:14:48 -0000 Subject: [Python-checkins] bpo-33540: Add block_on_close attr to socketserver (GH-6911) Message-ID: <mailman.39.1527124492.18020.python-checkins@python.org> https://github.com/python/cpython/commit/453bd0bc65b7ea6a18c43da69143ab10d54c0a35 commit: 453bd0bc65b7ea6a18c43da69143ab10d54c0a35 branch: master author: Victor Stinner <vstinner at redhat.com> committer: GitHub <noreply at github.com> date: 2018-05-24T03:14:44+02:00 summary: bpo-33540: Add block_on_close attr to socketserver (GH-6911) Add a new block_on_close class attribute to ForkingMixIn and ThreadingMixIn classes of socketserver to opt-in for pre-3.7 behaviour. files: A Misc/NEWS.d/next/Library/2018-05-16-18-10-38.bpo-33540.wy9LRV.rst M Doc/library/socketserver.rst M Doc/whatsnew/3.7.rst M Lib/socketserver.py diff --git a/Doc/library/socketserver.rst b/Doc/library/socketserver.rst index 560002738375..1b3062da6df9 100644 --- a/Doc/library/socketserver.rst +++ b/Doc/library/socketserver.rst @@ -116,10 +116,13 @@ server classes. only available on POSIX platforms that support :func:`~os.fork`. :meth:`socketserver.ForkingMixIn.server_close` waits until all child - processes complete. + processes complete, except if + :attr:`socketserver.ForkingMixIn.block_on_close` attribute is false. :meth:`socketserver.ThreadingMixIn.server_close` waits until all non-daemon - threads complete. Use daemonic threads by setting + threads complete, except if + :attr:`socketserver.ThreadingMixIn.block_on_close` attribute is false. Use + daemonic threads by setting :data:`ThreadingMixIn.daemon_threads` to ``True`` to not wait until threads complete. @@ -128,6 +131,8 @@ server classes. :meth:`socketserver.ForkingMixIn.server_close` and :meth:`socketserver.ThreadingMixIn.server_close` now waits until all child processes and non-daemonic threads complete. + Add a new :attr:`socketserver.ForkingMixIn.block_on_close` class + attribute to opt-in for the pre-3.7 behaviour. .. class:: ForkingTCPServer diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 46015af3e739..b466e74cffb4 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -1216,6 +1216,18 @@ by default. (Contributed by Christian Heimes in :issue:`28134`.) +socketserver +------------ + +:meth:`socketserver.ThreadingMixIn.server_close` now waits until all non-daemon +threads complete. :meth:`socketserver.ForkingMixIn.server_close` now waits +until all child processes complete. + +Add a new :attr:`socketserver.ForkingMixIn.block_on_close` class attribute to +:class:`socketserver.ForkingMixIn` and :class:`socketserver.ThreadingMixIn` +classes. Set the class attribute to ``False`` to get the pre-3.7 behaviour. + + sqlite3 ------- @@ -2156,10 +2168,17 @@ Changes in the Python API and module are affected by this change. (Contributed by INADA Naoki and Eugene Toder in :issue:`29463`.) -* :meth:`~socketserver.BaseServer.server_close` in - :class:`socketserver.ThreadingMixIn` and :class:`socketserver.ForkingMixIn` - now waits until all non-daemon threads complete. - (Contributed by Victor Stinner in :issue:`31233` and :issue:`31151`.) +* :meth:`socketserver.ThreadingMixIn.server_close` now waits until all + non-daemon threads complete. Set the new + :attr:`socketserver.ThreadingMixIn.block_on_close` class attribute to + ``False`` to get the pre-3.7 behaviour. + (Contributed by Victor Stinner in :issue:`31233` and :issue:`33540`.) + +* :meth:`socketserver.ForkingMixIn.server_close` now waits until all + child processes complete. Set the new + :attr:`socketserver.ForkingMixIn.block_on_close` class attribute to ``False`` + to get the pre-3.7 behaviour. + (Contributed by Victor Stinner in :issue:`31151` and :issue:`33540`.) * The :func:`locale.localeconv` function now temporarily sets the ``LC_CTYPE`` locale to the value of ``LC_NUMERIC`` in some cases. diff --git a/Lib/socketserver.py b/Lib/socketserver.py index 1ae7bef90407..71bb9a48fa91 100644 --- a/Lib/socketserver.py +++ b/Lib/socketserver.py @@ -543,6 +543,8 @@ class ForkingMixIn: timeout = 300 active_children = None max_children = 40 + # If true, server_close() waits until all child processes complete. + block_on_close = True def collect_children(self, *, blocking=False): """Internal routine to wait for children that have exited.""" @@ -620,7 +622,7 @@ def process_request(self, request, client_address): def server_close(self): super().server_close() - self.collect_children(blocking=True) + self.collect_children(blocking=self.block_on_close) class ThreadingMixIn: @@ -629,6 +631,8 @@ class ThreadingMixIn: # Decides how threads will act upon termination of the # main process daemon_threads = False + # If true, server_close() waits until all non-daemonic threads terminate. + block_on_close = True # For non-daemonic threads, list of threading.Threading objects # used by server_close() to wait for all threads completion. _threads = None @@ -659,11 +663,12 @@ def process_request(self, request, client_address): def server_close(self): super().server_close() - threads = self._threads - self._threads = None - if threads: - for thread in threads: - thread.join() + if self.block_on_close: + threads = self._threads + self._threads = None + if threads: + for thread in threads: + thread.join() if hasattr(os, "fork"): diff --git a/Misc/NEWS.d/next/Library/2018-05-16-18-10-38.bpo-33540.wy9LRV.rst b/Misc/NEWS.d/next/Library/2018-05-16-18-10-38.bpo-33540.wy9LRV.rst new file mode 100644 index 000000000000..9019cc14f515 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-16-18-10-38.bpo-33540.wy9LRV.rst @@ -0,0 +1,2 @@ +Add a new ``block_on_close`` class attribute to ``ForkingMixIn`` and +``ThreadingMixIn`` classes of :mod:`socketserver`. From webhook-mailer at python.org Wed May 23 21:21:17 2018 From: webhook-mailer at python.org (Victor Stinner) Date: Thu, 24 May 2018 01:21:17 -0000 Subject: [Python-checkins] [3.7] bpo-33353: Fix test_asyncio on FreeBSD (GH-7087) Message-ID: <mailman.40.1527124880.18020.python-checkins@python.org> https://github.com/python/cpython/commit/fa24c1c5afa9ba2453d88db5ed6b9d2cc3b58384 commit: fa24c1c5afa9ba2453d88db5ed6b9d2cc3b58384 branch: 3.7 author: Victor Stinner <vstinner at redhat.com> committer: GitHub <noreply at github.com> date: 2018-05-24T03:21:14+02:00 summary: [3.7] bpo-33353: Fix test_asyncio on FreeBSD (GH-7087) * bpo-33353: test_asyncio uses smaller sendfile data (#7083) bpo-32622, bpo-33353: sendfile() tests of test_asyncio use socket buffers of 1 kB "to test on relative small data sets". Send only 160 KiB rather 10 MB to make the test much faster. Shrink also SendfileBase.DATA from 1600 KiB to 160 KiB. On Linux, 3 test_sock_sendfile_mix_with_regular_send() runs now take less than 1 second, instead of 18 seconds. On FreeBSD, the 3 tests didn't hang, but took 3 minutes. Now the 3 tests pass in less than 1 seconds. (cherry picked from commit 2932755cc11fd82b4908d60b24b837aa4f3028e6) * bpo-33353: test_asyncio set SO_SNDBUF after connect (GH-7086) bpo-32622, bpo-33353: On macOS, sock.connect() changes the SO_SNDBUF value. Only set SO_SNDBUF and SO_RCVBUF buffer sizes once a socket is connected or binded, not before. (cherry picked from commit b97de3dd86046ac46567146d86a69d4f78ea09db) files: M Lib/test/test_asyncio/test_events.py diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index 66c77b976dce..64d726d16d1c 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -2095,7 +2095,7 @@ def test_subprocess_shell_invalid_args(self): class SendfileBase: - DATA = b"12345abcde" * 160 * 1024 # 160 KiB + DATA = b"12345abcde" * 16 * 1024 # 160 KiB @classmethod def setUpClass(cls): @@ -2142,11 +2142,15 @@ def connection_lost(self, exc): async def wait_closed(self): await self.fut + def set_socket_opts(self, sock): + # On macOS, SO_SNDBUF is reset by connect(). So this method + # should be called after the socket is connected. + sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 1024) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 1024) + def make_socket(self, cleanup=True): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setblocking(False) - sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 1024) - sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 1024) if cleanup: self.addCleanup(sock.close) return sock @@ -2159,7 +2163,9 @@ def prepare_socksendfile(self): srv_sock.bind((support.HOST, port)) server = self.run_loop(self.loop.create_server( lambda: proto, sock=srv_sock)) + self.set_socket_opts(srv_sock) self.run_loop(self.loop.sock_connect(sock, ('127.0.0.1', port))) + self.set_socket_opts(sock) def cleanup(): if proto.transport is not None: @@ -2208,7 +2214,7 @@ def test_sock_sendfile_zero_size(self): self.assertEqual(self.file.tell(), 0) def test_sock_sendfile_mix_with_regular_send(self): - buf = b'1234567890' * 1024 * 1024 # 10 MB + buf = b"X" * 160 * 1024 # 160 KiB sock, proto = self.prepare_socksendfile() self.run_loop(self.loop.sock_sendall(sock, buf)) ret = self.run_loop(self.loop.sock_sendfile(sock, self.file)) @@ -2264,9 +2270,9 @@ def prepare_sendfile(self, *, is_ssl=False, close_after=0): else: server_hostname = None cli_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + cli_sock.connect((support.HOST, port)) # reduce send socket buffer size to test on relative small data sets cli_sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 1024) - cli_sock.connect((support.HOST, port)) cli_proto = self.MySendfileProto(loop=self.loop) tr, pr = self.run_loop(self.loop.create_connection( lambda: cli_proto, sock=cli_sock, From webhook-mailer at python.org Wed May 23 21:34:46 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 24 May 2018 01:34:46 -0000 Subject: [Python-checkins] bpo-33540: Add block_on_close attr to socketserver (GH-6911) Message-ID: <mailman.41.1527125689.18020.python-checkins@python.org> https://github.com/python/cpython/commit/fa286edbde9ed660d99628aea14ee3b824c2afe6 commit: fa286edbde9ed660d99628aea14ee3b824c2afe6 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-23T18:34:43-07:00 summary: bpo-33540: Add block_on_close attr to socketserver (GH-6911) Add a new block_on_close class attribute to ForkingMixIn and ThreadingMixIn classes of socketserver to opt-in for pre-3.7 behaviour. (cherry picked from commit 453bd0bc65b7ea6a18c43da69143ab10d54c0a35) Co-authored-by: Victor Stinner <vstinner at redhat.com> files: A Misc/NEWS.d/next/Library/2018-05-16-18-10-38.bpo-33540.wy9LRV.rst M Doc/library/socketserver.rst M Doc/whatsnew/3.7.rst M Lib/socketserver.py diff --git a/Doc/library/socketserver.rst b/Doc/library/socketserver.rst index 560002738375..1b3062da6df9 100644 --- a/Doc/library/socketserver.rst +++ b/Doc/library/socketserver.rst @@ -116,10 +116,13 @@ server classes. only available on POSIX platforms that support :func:`~os.fork`. :meth:`socketserver.ForkingMixIn.server_close` waits until all child - processes complete. + processes complete, except if + :attr:`socketserver.ForkingMixIn.block_on_close` attribute is false. :meth:`socketserver.ThreadingMixIn.server_close` waits until all non-daemon - threads complete. Use daemonic threads by setting + threads complete, except if + :attr:`socketserver.ThreadingMixIn.block_on_close` attribute is false. Use + daemonic threads by setting :data:`ThreadingMixIn.daemon_threads` to ``True`` to not wait until threads complete. @@ -128,6 +131,8 @@ server classes. :meth:`socketserver.ForkingMixIn.server_close` and :meth:`socketserver.ThreadingMixIn.server_close` now waits until all child processes and non-daemonic threads complete. + Add a new :attr:`socketserver.ForkingMixIn.block_on_close` class + attribute to opt-in for the pre-3.7 behaviour. .. class:: ForkingTCPServer diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 46015af3e739..b466e74cffb4 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -1216,6 +1216,18 @@ by default. (Contributed by Christian Heimes in :issue:`28134`.) +socketserver +------------ + +:meth:`socketserver.ThreadingMixIn.server_close` now waits until all non-daemon +threads complete. :meth:`socketserver.ForkingMixIn.server_close` now waits +until all child processes complete. + +Add a new :attr:`socketserver.ForkingMixIn.block_on_close` class attribute to +:class:`socketserver.ForkingMixIn` and :class:`socketserver.ThreadingMixIn` +classes. Set the class attribute to ``False`` to get the pre-3.7 behaviour. + + sqlite3 ------- @@ -2156,10 +2168,17 @@ Changes in the Python API and module are affected by this change. (Contributed by INADA Naoki and Eugene Toder in :issue:`29463`.) -* :meth:`~socketserver.BaseServer.server_close` in - :class:`socketserver.ThreadingMixIn` and :class:`socketserver.ForkingMixIn` - now waits until all non-daemon threads complete. - (Contributed by Victor Stinner in :issue:`31233` and :issue:`31151`.) +* :meth:`socketserver.ThreadingMixIn.server_close` now waits until all + non-daemon threads complete. Set the new + :attr:`socketserver.ThreadingMixIn.block_on_close` class attribute to + ``False`` to get the pre-3.7 behaviour. + (Contributed by Victor Stinner in :issue:`31233` and :issue:`33540`.) + +* :meth:`socketserver.ForkingMixIn.server_close` now waits until all + child processes complete. Set the new + :attr:`socketserver.ForkingMixIn.block_on_close` class attribute to ``False`` + to get the pre-3.7 behaviour. + (Contributed by Victor Stinner in :issue:`31151` and :issue:`33540`.) * The :func:`locale.localeconv` function now temporarily sets the ``LC_CTYPE`` locale to the value of ``LC_NUMERIC`` in some cases. diff --git a/Lib/socketserver.py b/Lib/socketserver.py index 1ae7bef90407..71bb9a48fa91 100644 --- a/Lib/socketserver.py +++ b/Lib/socketserver.py @@ -543,6 +543,8 @@ class ForkingMixIn: timeout = 300 active_children = None max_children = 40 + # If true, server_close() waits until all child processes complete. + block_on_close = True def collect_children(self, *, blocking=False): """Internal routine to wait for children that have exited.""" @@ -620,7 +622,7 @@ def process_request(self, request, client_address): def server_close(self): super().server_close() - self.collect_children(blocking=True) + self.collect_children(blocking=self.block_on_close) class ThreadingMixIn: @@ -629,6 +631,8 @@ class ThreadingMixIn: # Decides how threads will act upon termination of the # main process daemon_threads = False + # If true, server_close() waits until all non-daemonic threads terminate. + block_on_close = True # For non-daemonic threads, list of threading.Threading objects # used by server_close() to wait for all threads completion. _threads = None @@ -659,11 +663,12 @@ def process_request(self, request, client_address): def server_close(self): super().server_close() - threads = self._threads - self._threads = None - if threads: - for thread in threads: - thread.join() + if self.block_on_close: + threads = self._threads + self._threads = None + if threads: + for thread in threads: + thread.join() if hasattr(os, "fork"): diff --git a/Misc/NEWS.d/next/Library/2018-05-16-18-10-38.bpo-33540.wy9LRV.rst b/Misc/NEWS.d/next/Library/2018-05-16-18-10-38.bpo-33540.wy9LRV.rst new file mode 100644 index 000000000000..9019cc14f515 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-16-18-10-38.bpo-33540.wy9LRV.rst @@ -0,0 +1,2 @@ +Add a new ``block_on_close`` class attribute to ``ForkingMixIn`` and +``ThreadingMixIn`` classes of :mod:`socketserver`. From webhook-mailer at python.org Wed May 23 21:55:18 2018 From: webhook-mailer at python.org (Ned Deily) Date: Thu, 24 May 2018 01:55:18 -0000 Subject: [Python-checkins] bpo-33109: argparse subparsers are once again not required by default (GH-6919) Message-ID: <mailman.42.1527126923.18020.python-checkins@python.org> https://github.com/python/cpython/commit/8ebf5ceb0f5408d1ebc26c19702ac0762ef5ea04 commit: 8ebf5ceb0f5408d1ebc26c19702ac0762ef5ea04 branch: master author: Ned Deily <nad at python.org> committer: GitHub <noreply at github.com> date: 2018-05-23T21:55:15-04:00 summary: bpo-33109: argparse subparsers are once again not required by default (GH-6919) bpo-26510 in 3.7.0a2 changed the behavior of argparse to make subparsers required by default, returning to the behavior of 2.7 and 3.2. The behavior was changed in 3.3 to be no longer required. While it might make more sense to have the default to required, compatibility with 3.3 through 3.6 is probably less disruptive than trying to reintroduce compatibility with 2.7 at this point. This change restores the 3.6 behavior. files: A Misc/NEWS.d/next/Library/2018-05-16-14-57-58.bpo-33109.nPLL_S.rst M Doc/library/argparse.rst M Lib/argparse.py M Lib/test/test_argparse.py M Misc/NEWS.d/3.7.0a2.rst diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst index 3f327c0cfa77..260e5cbf7000 100644 --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -1577,7 +1577,7 @@ Sub-commands stored; by default ``None`` and no value is stored * required_ - Whether or not a subcommand must be provided, by default - ``True``. + ``False``. * help_ - help for sub-parser group in help output, by default ``None`` diff --git a/Lib/argparse.py b/Lib/argparse.py index e3da7f0443cf..e0e367bf20ca 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -1077,7 +1077,7 @@ def __init__(self, prog, parser_class, dest=SUPPRESS, - required=True, + required=False, help=None, metavar=None): diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index c4440e4df7c1..bcf15ce123e4 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -1932,7 +1932,9 @@ def test_required_subparsers_default(self): parser = ErrorRaisingArgumentParser() subparsers = parser.add_subparsers(dest='command') subparsers.add_parser('run') - self._test_required_subparsers(parser) + # No error here + ret = parser.parse_args(()) + self.assertIsNone(ret.command) def test_optional_subparsers(self): parser = ErrorRaisingArgumentParser() diff --git a/Misc/NEWS.d/3.7.0a2.rst b/Misc/NEWS.d/3.7.0a2.rst index 190038d5dd12..621de6d78a76 100644 --- a/Misc/NEWS.d/3.7.0a2.rst +++ b/Misc/NEWS.d/3.7.0a2.rst @@ -477,6 +477,8 @@ module now requires sqlite version at least 3.3.9. argparse subparsers are now required by default. This matches behaviour in Python 2. For optional subparsers, use the new parameter ``add_subparsers(required=False)``. Patch by Anthony Sottile. +(As of 3.7.0rc1, the default was changed to not required as had been the case +since Python 3.3.) .. diff --git a/Misc/NEWS.d/next/Library/2018-05-16-14-57-58.bpo-33109.nPLL_S.rst b/Misc/NEWS.d/next/Library/2018-05-16-14-57-58.bpo-33109.nPLL_S.rst new file mode 100644 index 000000000000..be731f99f7f0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-16-14-57-58.bpo-33109.nPLL_S.rst @@ -0,0 +1,2 @@ +argparse subparsers are once again not required by default, reverting the +change in behavior introduced by bpo-26510 in 3.7.0a2. From webhook-mailer at python.org Wed May 23 22:18:18 2018 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Thu, 24 May 2018 02:18:18 -0000 Subject: [Python-checkins] bpo-33628: IDLE: Minor code cleanup of codecontext.py and its tests (GH-7085) Message-ID: <mailman.43.1527128300.18020.python-checkins@python.org> https://github.com/python/cpython/commit/8506016f904ba6bc27bf5261f27a0bdd5945cd26 commit: 8506016f904ba6bc27bf5261f27a0bdd5945cd26 branch: master author: Cheryl Sabella <cheryl.sabella at gmail.com> committer: Terry Jan Reedy <tjreedy at udel.edu> date: 2018-05-23T22:18:15-04:00 summary: bpo-33628: IDLE: Minor code cleanup of codecontext.py and its tests (GH-7085) files: A Misc/NEWS.d/next/IDLE/2018-05-23-19-51-07.bpo-33628.sLlFLO.rst M Lib/idlelib/NEWS.txt M Lib/idlelib/codecontext.py M Lib/idlelib/idle_test/test_codecontext.py diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index 786378e2a632..2f8237d2395d 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -3,6 +3,8 @@ Released on 2018-06-18? ====================================== +bpo-33628: Cleanup codecontext.py and its test. + bpo-32831: Add docstrings and tests for codecontext.py. Coverage is 100%. Patch by Cheryl Sabella. diff --git a/Lib/idlelib/codecontext.py b/Lib/idlelib/codecontext.py index efd163ed265e..635f68c86e1f 100644 --- a/Lib/idlelib/codecontext.py +++ b/Lib/idlelib/codecontext.py @@ -23,9 +23,23 @@ FONTUPDATEINTERVAL = 1000 # millisec -def getspacesfirstword(s, c=re.compile(r"^(\s*)(\w*)")): - "Extract the beginning whitespace and first word from s." - return c.match(s).groups() +def get_spaces_firstword(codeline, c=re.compile(r"^(\s*)(\w*)")): + "Extract the beginning whitespace and first word from codeline." + return c.match(codeline).groups() + + +def get_line_info(codeline): + """Return tuple of (line indent value, codeline, block start keyword). + + The indentation of empty lines (or comment lines) is INFINITY. + If the line does not start a block, the keyword value is False. + """ + spaces, firstword = get_spaces_firstword(codeline) + indent = len(spaces) + if len(codeline) == indent or codeline[indent] == '#': + indent = INFINITY + opener = firstword in BLOCKOPENERS and firstword + return indent, codeline, opener class CodeContext: @@ -42,15 +56,15 @@ def __init__(self, editwin): self.textfont is the editor window font. self.label displays the code context text above the editor text. - Initially None it is toggled via <<toggle-code-context>>. + Initially None, it is toggled via <<toggle-code-context>>. self.topvisible is the number of the top text line displayed. self.info is a list of (line number, indent level, line text, block keyword) tuples for the block structure above topvisible. - s self.info[0] is initialized a 'dummy' line which - # starts the toplevel 'block' of the module. + self.info[0] is initialized with a 'dummy' line which + starts the toplevel 'block' of the module. self.t1 and self.t2 are two timer events on the editor text widget to - monitor for changes to the context text or editor font. + monitor for changes to the context text or editor font. """ self.editwin = editwin self.text = editwin.text @@ -94,23 +108,21 @@ def toggle_code_context_event(self, event=None): # All values are passed through getint(), since some # values may be pixel objects, which can't simply be added to ints. widgets = self.editwin.text, self.editwin.text_frame - # Calculate the required vertical padding + # Calculate the required horizontal padding and border width. padx = 0 + border = 0 for widget in widgets: padx += widget.tk.getint(widget.pack_info()['padx']) padx += widget.tk.getint(widget.cget('padx')) - # Calculate the required border width - border = 0 - for widget in widgets: border += widget.tk.getint(widget.cget('border')) self.label = tkinter.Label( self.editwin.top, text="\n" * (self.context_depth - 1), anchor=W, justify=LEFT, font=self.textfont, bg=self.bgcolor, fg=self.fgcolor, - width=1, #don't request more than we get + width=1, # Don't request more than we get. padx=padx, border=border, relief=SUNKEN) # Pack the label widget before and above the text_frame widget, - # thus ensuring that it will appear directly above text_frame + # thus ensuring that it will appear directly above text_frame. self.label.pack(side=TOP, fill=X, expand=False, before=self.editwin.text_frame) else: @@ -118,21 +130,6 @@ def toggle_code_context_event(self, event=None): self.label = None return "break" - def get_line_info(self, linenum): - """Return tuple of (line indent value, text, and block start keyword). - - If the line does not start a block, the keyword value is False. - The indentation of empty lines (or comment lines) is INFINITY. - """ - text = self.text.get("%d.0" % linenum, "%d.end" % linenum) - spaces, firstword = getspacesfirstword(text) - opener = firstword in BLOCKOPENERS and firstword - if len(text) == len(spaces) or text[len(spaces)] == '#': - indent = INFINITY - else: - indent = len(spaces) - return indent, text, opener - def get_context(self, new_topvisible, stopline=1, stopindent=0): """Return a list of block line tuples and the 'last' indent. @@ -144,16 +141,17 @@ def get_context(self, new_topvisible, stopline=1, stopindent=0): """ assert stopline > 0 lines = [] - # The indentation level we are currently in: + # The indentation level we are currently in. lastindent = INFINITY # For a line to be interesting, it must begin with a block opening # keyword, and have less indentation than lastindent. for linenum in range(new_topvisible, stopline-1, -1): - indent, text, opener = self.get_line_info(linenum) + codeline = self.text.get(f'{linenum}.0', f'{linenum}.end') + indent, text, opener = get_line_info(codeline) if indent < lastindent: lastindent = indent if opener in ("else", "elif"): - # We also show the if statement + # Also show the if statement. lastindent += 1 if opener and linenum < new_topvisible and indent >= stopindent: lines.append((linenum, indent, text, opener)) @@ -172,19 +170,19 @@ def update_code_context(self): the context label. """ new_topvisible = int(self.text.index("@0,0").split('.')[0]) - if self.topvisible == new_topvisible: # haven't scrolled + if self.topvisible == new_topvisible: # Haven't scrolled. return - if self.topvisible < new_topvisible: # scroll down + if self.topvisible < new_topvisible: # Scroll down. lines, lastindent = self.get_context(new_topvisible, self.topvisible) - # retain only context info applicable to the region - # between topvisible and new_topvisible: + # Retain only context info applicable to the region + # between topvisible and new_topvisible. while self.info[-1][1] >= lastindent: del self.info[-1] - else: # self.topvisible > new_topvisible: # scroll up + else: # self.topvisible > new_topvisible: # Scroll up. stopindent = self.info[-1][1] + 1 - # retain only context info associated - # with lines above new_topvisible: + # Retain only context info associated + # with lines above new_topvisible. while self.info[-1][0] >= new_topvisible: stopindent = self.info[-1][1] del self.info[-1] @@ -193,9 +191,9 @@ def update_code_context(self): stopindent) self.info.extend(lines) self.topvisible = new_topvisible - # empty lines in context pane: + # Empty lines in context pane. context_strings = [""] * max(0, self.context_depth - len(self.info)) - # followed by the context hint lines: + # Followed by the context hint lines. context_strings += [x[2] for x in self.info[-self.context_depth:]] self.label["text"] = '\n'.join(context_strings) diff --git a/Lib/idlelib/idle_test/test_codecontext.py b/Lib/idlelib/idle_test/test_codecontext.py index 448094eda7ef..ed45828641b4 100644 --- a/Lib/idlelib/idle_test/test_codecontext.py +++ b/Lib/idlelib/idle_test/test_codecontext.py @@ -96,8 +96,6 @@ def test_init(self): eq(self.root.tk.call('after', 'info', self.cc.t2)[1], 'timer') def test_del(self): - self.root.tk.call('after', 'info', self.cc.t1) - self.root.tk.call('after', 'info', self.cc.t2) self.cc.__del__() with self.assertRaises(TclError) as msg: self.root.tk.call('after', 'info', self.cc.t1) @@ -135,21 +133,6 @@ def test_toggle_code_context_event(self): eq(toggle(), 'break') self.assertIsNone(cc.label) - def test_get_line_info(self): - eq = self.assertEqual - gli = self.cc.get_line_info - - # Line 1 is not a BLOCKOPENER. - eq(gli(1), (codecontext.INFINITY, '', False)) - # Line 2 is a BLOCKOPENER without an indent. - eq(gli(2), (0, 'class C1():', 'class')) - # Line 3 is not a BLOCKOPENER and does not return the indent level. - eq(gli(3), (codecontext.INFINITY, ' # Class comment.', False)) - # Line 4 is a BLOCKOPENER and is indented. - eq(gli(4), (4, ' def __init__(self, a, b):', 'def')) - # Line 8 is a different BLOCKOPENER and is indented. - eq(gli(8), (8, ' if a > b:', 'if')) - def test_get_context(self): eq = self.assertEqual gc = self.cc.get_context @@ -323,8 +306,8 @@ def test_font_timer_event(self): class HelperFunctionText(unittest.TestCase): - def test_getspacesfirstword(self): - get = codecontext.getspacesfirstword + def test_get_spaces_firstword(self): + get = codecontext.get_spaces_firstword test_lines = ( (' first word', (' ', 'first')), ('\tfirst word', ('\t', 'first')), @@ -342,6 +325,24 @@ def test_getspacesfirstword(self): c=re.compile(r'^(\s*)([^\s]*)')), (' ', '(continuation)')) + def test_get_line_info(self): + eq = self.assertEqual + gli = codecontext.get_line_info + lines = code_sample.splitlines() + + # Line 1 is not a BLOCKOPENER. + eq(gli(lines[0]), (codecontext.INFINITY, '', False)) + # Line 2 is a BLOCKOPENER without an indent. + eq(gli(lines[1]), (0, 'class C1():', 'class')) + # Line 3 is not a BLOCKOPENER and does not return the indent level. + eq(gli(lines[2]), (codecontext.INFINITY, ' # Class comment.', False)) + # Line 4 is a BLOCKOPENER and is indented. + eq(gli(lines[3]), (4, ' def __init__(self, a, b):', 'def')) + # Line 8 is a different BLOCKOPENER and is indented. + eq(gli(lines[7]), (8, ' if a > b:', 'if')) + # Test tab. + eq(gli('\tif a == b:'), (1, '\tif a == b:', 'if')) + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/Misc/NEWS.d/next/IDLE/2018-05-23-19-51-07.bpo-33628.sLlFLO.rst b/Misc/NEWS.d/next/IDLE/2018-05-23-19-51-07.bpo-33628.sLlFLO.rst new file mode 100644 index 000000000000..f0b13a21c346 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2018-05-23-19-51-07.bpo-33628.sLlFLO.rst @@ -0,0 +1,2 @@ +IDLE: Cleanup codecontext.py and its test. + From webhook-mailer at python.org Wed May 23 22:22:49 2018 From: webhook-mailer at python.org (Ned Deily) Date: Thu, 24 May 2018 02:22:49 -0000 Subject: [Python-checkins] bpo-33109: argparse subparsers are once again not required by default (GH-6919) (GH-7089) Message-ID: <mailman.44.1527128575.18020.python-checkins@python.org> https://github.com/python/cpython/commit/dd7a255911f364cf521676082a89d4cac307737e commit: dd7a255911f364cf521676082a89d4cac307737e branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Ned Deily <nad at python.org> date: 2018-05-23T22:22:46-04:00 summary: bpo-33109: argparse subparsers are once again not required by default (GH-6919) (GH-7089) bpo-26510 in 3.7.0a2 changed the behavior of argparse to make subparsers required by default, returning to the behavior of 2.7 and 3.2. The behavior was changed in 3.3 to be no longer required. While it might make more sense to have the default to required, compatibility with 3.3 through 3.6 is probably less disruptive than trying to reintroduce compatibility with 2.7 at this point. This change restores the 3.6 behavior. (cherry picked from commit 8ebf5ceb0f5408d1ebc26c19702ac0762ef5ea04) Co-authored-by: Ned Deily <nad at python.org> files: A Misc/NEWS.d/next/Library/2018-05-16-14-57-58.bpo-33109.nPLL_S.rst M Doc/library/argparse.rst M Lib/argparse.py M Lib/test/test_argparse.py M Misc/NEWS.d/3.7.0a2.rst diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst index 3f327c0cfa77..260e5cbf7000 100644 --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -1577,7 +1577,7 @@ Sub-commands stored; by default ``None`` and no value is stored * required_ - Whether or not a subcommand must be provided, by default - ``True``. + ``False``. * help_ - help for sub-parser group in help output, by default ``None`` diff --git a/Lib/argparse.py b/Lib/argparse.py index e3da7f0443cf..e0e367bf20ca 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -1077,7 +1077,7 @@ def __init__(self, prog, parser_class, dest=SUPPRESS, - required=True, + required=False, help=None, metavar=None): diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index c4440e4df7c1..bcf15ce123e4 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -1932,7 +1932,9 @@ def test_required_subparsers_default(self): parser = ErrorRaisingArgumentParser() subparsers = parser.add_subparsers(dest='command') subparsers.add_parser('run') - self._test_required_subparsers(parser) + # No error here + ret = parser.parse_args(()) + self.assertIsNone(ret.command) def test_optional_subparsers(self): parser = ErrorRaisingArgumentParser() diff --git a/Misc/NEWS.d/3.7.0a2.rst b/Misc/NEWS.d/3.7.0a2.rst index 190038d5dd12..621de6d78a76 100644 --- a/Misc/NEWS.d/3.7.0a2.rst +++ b/Misc/NEWS.d/3.7.0a2.rst @@ -477,6 +477,8 @@ module now requires sqlite version at least 3.3.9. argparse subparsers are now required by default. This matches behaviour in Python 2. For optional subparsers, use the new parameter ``add_subparsers(required=False)``. Patch by Anthony Sottile. +(As of 3.7.0rc1, the default was changed to not required as had been the case +since Python 3.3.) .. diff --git a/Misc/NEWS.d/next/Library/2018-05-16-14-57-58.bpo-33109.nPLL_S.rst b/Misc/NEWS.d/next/Library/2018-05-16-14-57-58.bpo-33109.nPLL_S.rst new file mode 100644 index 000000000000..be731f99f7f0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-16-14-57-58.bpo-33109.nPLL_S.rst @@ -0,0 +1,2 @@ +argparse subparsers are once again not required by default, reverting the +change in behavior introduced by bpo-26510 in 3.7.0a2. From webhook-mailer at python.org Wed May 23 23:16:44 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 24 May 2018 03:16:44 -0000 Subject: [Python-checkins] bpo-33628: IDLE: Minor code cleanup of codecontext.py and its tests (GH-7085) Message-ID: <mailman.45.1527131806.18020.python-checkins@python.org> https://github.com/python/cpython/commit/935c81bbbca28ca23862d7ee1f79cd502e447edd commit: 935c81bbbca28ca23862d7ee1f79cd502e447edd branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-23T20:16:33-07:00 summary: bpo-33628: IDLE: Minor code cleanup of codecontext.py and its tests (GH-7085) (cherry picked from commit 8506016f904ba6bc27bf5261f27a0bdd5945cd26) Co-authored-by: Cheryl Sabella <cheryl.sabella at gmail.com> files: A Misc/NEWS.d/next/IDLE/2018-05-23-19-51-07.bpo-33628.sLlFLO.rst M Lib/idlelib/NEWS.txt M Lib/idlelib/codecontext.py M Lib/idlelib/idle_test/test_codecontext.py diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index 110dbda09a74..9971bf455430 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -3,6 +3,8 @@ Released on 2018-06-15? ====================================== +bpo-33628: Cleanup codecontext.py and its test. + bpo-32831: Add docstrings and tests for codecontext.py. Coverage is 100%. Patch by Cheryl Sabella. diff --git a/Lib/idlelib/codecontext.py b/Lib/idlelib/codecontext.py index efd163ed265e..635f68c86e1f 100644 --- a/Lib/idlelib/codecontext.py +++ b/Lib/idlelib/codecontext.py @@ -23,9 +23,23 @@ FONTUPDATEINTERVAL = 1000 # millisec -def getspacesfirstword(s, c=re.compile(r"^(\s*)(\w*)")): - "Extract the beginning whitespace and first word from s." - return c.match(s).groups() +def get_spaces_firstword(codeline, c=re.compile(r"^(\s*)(\w*)")): + "Extract the beginning whitespace and first word from codeline." + return c.match(codeline).groups() + + +def get_line_info(codeline): + """Return tuple of (line indent value, codeline, block start keyword). + + The indentation of empty lines (or comment lines) is INFINITY. + If the line does not start a block, the keyword value is False. + """ + spaces, firstword = get_spaces_firstword(codeline) + indent = len(spaces) + if len(codeline) == indent or codeline[indent] == '#': + indent = INFINITY + opener = firstword in BLOCKOPENERS and firstword + return indent, codeline, opener class CodeContext: @@ -42,15 +56,15 @@ def __init__(self, editwin): self.textfont is the editor window font. self.label displays the code context text above the editor text. - Initially None it is toggled via <<toggle-code-context>>. + Initially None, it is toggled via <<toggle-code-context>>. self.topvisible is the number of the top text line displayed. self.info is a list of (line number, indent level, line text, block keyword) tuples for the block structure above topvisible. - s self.info[0] is initialized a 'dummy' line which - # starts the toplevel 'block' of the module. + self.info[0] is initialized with a 'dummy' line which + starts the toplevel 'block' of the module. self.t1 and self.t2 are two timer events on the editor text widget to - monitor for changes to the context text or editor font. + monitor for changes to the context text or editor font. """ self.editwin = editwin self.text = editwin.text @@ -94,23 +108,21 @@ def toggle_code_context_event(self, event=None): # All values are passed through getint(), since some # values may be pixel objects, which can't simply be added to ints. widgets = self.editwin.text, self.editwin.text_frame - # Calculate the required vertical padding + # Calculate the required horizontal padding and border width. padx = 0 + border = 0 for widget in widgets: padx += widget.tk.getint(widget.pack_info()['padx']) padx += widget.tk.getint(widget.cget('padx')) - # Calculate the required border width - border = 0 - for widget in widgets: border += widget.tk.getint(widget.cget('border')) self.label = tkinter.Label( self.editwin.top, text="\n" * (self.context_depth - 1), anchor=W, justify=LEFT, font=self.textfont, bg=self.bgcolor, fg=self.fgcolor, - width=1, #don't request more than we get + width=1, # Don't request more than we get. padx=padx, border=border, relief=SUNKEN) # Pack the label widget before and above the text_frame widget, - # thus ensuring that it will appear directly above text_frame + # thus ensuring that it will appear directly above text_frame. self.label.pack(side=TOP, fill=X, expand=False, before=self.editwin.text_frame) else: @@ -118,21 +130,6 @@ def toggle_code_context_event(self, event=None): self.label = None return "break" - def get_line_info(self, linenum): - """Return tuple of (line indent value, text, and block start keyword). - - If the line does not start a block, the keyword value is False. - The indentation of empty lines (or comment lines) is INFINITY. - """ - text = self.text.get("%d.0" % linenum, "%d.end" % linenum) - spaces, firstword = getspacesfirstword(text) - opener = firstword in BLOCKOPENERS and firstword - if len(text) == len(spaces) or text[len(spaces)] == '#': - indent = INFINITY - else: - indent = len(spaces) - return indent, text, opener - def get_context(self, new_topvisible, stopline=1, stopindent=0): """Return a list of block line tuples and the 'last' indent. @@ -144,16 +141,17 @@ def get_context(self, new_topvisible, stopline=1, stopindent=0): """ assert stopline > 0 lines = [] - # The indentation level we are currently in: + # The indentation level we are currently in. lastindent = INFINITY # For a line to be interesting, it must begin with a block opening # keyword, and have less indentation than lastindent. for linenum in range(new_topvisible, stopline-1, -1): - indent, text, opener = self.get_line_info(linenum) + codeline = self.text.get(f'{linenum}.0', f'{linenum}.end') + indent, text, opener = get_line_info(codeline) if indent < lastindent: lastindent = indent if opener in ("else", "elif"): - # We also show the if statement + # Also show the if statement. lastindent += 1 if opener and linenum < new_topvisible and indent >= stopindent: lines.append((linenum, indent, text, opener)) @@ -172,19 +170,19 @@ def update_code_context(self): the context label. """ new_topvisible = int(self.text.index("@0,0").split('.')[0]) - if self.topvisible == new_topvisible: # haven't scrolled + if self.topvisible == new_topvisible: # Haven't scrolled. return - if self.topvisible < new_topvisible: # scroll down + if self.topvisible < new_topvisible: # Scroll down. lines, lastindent = self.get_context(new_topvisible, self.topvisible) - # retain only context info applicable to the region - # between topvisible and new_topvisible: + # Retain only context info applicable to the region + # between topvisible and new_topvisible. while self.info[-1][1] >= lastindent: del self.info[-1] - else: # self.topvisible > new_topvisible: # scroll up + else: # self.topvisible > new_topvisible: # Scroll up. stopindent = self.info[-1][1] + 1 - # retain only context info associated - # with lines above new_topvisible: + # Retain only context info associated + # with lines above new_topvisible. while self.info[-1][0] >= new_topvisible: stopindent = self.info[-1][1] del self.info[-1] @@ -193,9 +191,9 @@ def update_code_context(self): stopindent) self.info.extend(lines) self.topvisible = new_topvisible - # empty lines in context pane: + # Empty lines in context pane. context_strings = [""] * max(0, self.context_depth - len(self.info)) - # followed by the context hint lines: + # Followed by the context hint lines. context_strings += [x[2] for x in self.info[-self.context_depth:]] self.label["text"] = '\n'.join(context_strings) diff --git a/Lib/idlelib/idle_test/test_codecontext.py b/Lib/idlelib/idle_test/test_codecontext.py index 448094eda7ef..ed45828641b4 100644 --- a/Lib/idlelib/idle_test/test_codecontext.py +++ b/Lib/idlelib/idle_test/test_codecontext.py @@ -96,8 +96,6 @@ def test_init(self): eq(self.root.tk.call('after', 'info', self.cc.t2)[1], 'timer') def test_del(self): - self.root.tk.call('after', 'info', self.cc.t1) - self.root.tk.call('after', 'info', self.cc.t2) self.cc.__del__() with self.assertRaises(TclError) as msg: self.root.tk.call('after', 'info', self.cc.t1) @@ -135,21 +133,6 @@ def test_toggle_code_context_event(self): eq(toggle(), 'break') self.assertIsNone(cc.label) - def test_get_line_info(self): - eq = self.assertEqual - gli = self.cc.get_line_info - - # Line 1 is not a BLOCKOPENER. - eq(gli(1), (codecontext.INFINITY, '', False)) - # Line 2 is a BLOCKOPENER without an indent. - eq(gli(2), (0, 'class C1():', 'class')) - # Line 3 is not a BLOCKOPENER and does not return the indent level. - eq(gli(3), (codecontext.INFINITY, ' # Class comment.', False)) - # Line 4 is a BLOCKOPENER and is indented. - eq(gli(4), (4, ' def __init__(self, a, b):', 'def')) - # Line 8 is a different BLOCKOPENER and is indented. - eq(gli(8), (8, ' if a > b:', 'if')) - def test_get_context(self): eq = self.assertEqual gc = self.cc.get_context @@ -323,8 +306,8 @@ def test_font_timer_event(self): class HelperFunctionText(unittest.TestCase): - def test_getspacesfirstword(self): - get = codecontext.getspacesfirstword + def test_get_spaces_firstword(self): + get = codecontext.get_spaces_firstword test_lines = ( (' first word', (' ', 'first')), ('\tfirst word', ('\t', 'first')), @@ -342,6 +325,24 @@ def test_getspacesfirstword(self): c=re.compile(r'^(\s*)([^\s]*)')), (' ', '(continuation)')) + def test_get_line_info(self): + eq = self.assertEqual + gli = codecontext.get_line_info + lines = code_sample.splitlines() + + # Line 1 is not a BLOCKOPENER. + eq(gli(lines[0]), (codecontext.INFINITY, '', False)) + # Line 2 is a BLOCKOPENER without an indent. + eq(gli(lines[1]), (0, 'class C1():', 'class')) + # Line 3 is not a BLOCKOPENER and does not return the indent level. + eq(gli(lines[2]), (codecontext.INFINITY, ' # Class comment.', False)) + # Line 4 is a BLOCKOPENER and is indented. + eq(gli(lines[3]), (4, ' def __init__(self, a, b):', 'def')) + # Line 8 is a different BLOCKOPENER and is indented. + eq(gli(lines[7]), (8, ' if a > b:', 'if')) + # Test tab. + eq(gli('\tif a == b:'), (1, '\tif a == b:', 'if')) + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/Misc/NEWS.d/next/IDLE/2018-05-23-19-51-07.bpo-33628.sLlFLO.rst b/Misc/NEWS.d/next/IDLE/2018-05-23-19-51-07.bpo-33628.sLlFLO.rst new file mode 100644 index 000000000000..f0b13a21c346 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2018-05-23-19-51-07.bpo-33628.sLlFLO.rst @@ -0,0 +1,2 @@ +IDLE: Cleanup codecontext.py and its test. + From webhook-mailer at python.org Wed May 23 23:26:57 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 24 May 2018 03:26:57 -0000 Subject: [Python-checkins] bpo-33628: IDLE: Minor code cleanup of codecontext.py and its tests (GH-7085) Message-ID: <mailman.46.1527132419.18020.python-checkins@python.org> https://github.com/python/cpython/commit/b2ab5dc72b36d074a86f2b1d91ae804e5a7210f8 commit: b2ab5dc72b36d074a86f2b1d91ae804e5a7210f8 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-23T20:26:54-07:00 summary: bpo-33628: IDLE: Minor code cleanup of codecontext.py and its tests (GH-7085) (cherry picked from commit 8506016f904ba6bc27bf5261f27a0bdd5945cd26) Co-authored-by: Cheryl Sabella <cheryl.sabella at gmail.com> files: A Misc/NEWS.d/next/IDLE/2018-05-23-19-51-07.bpo-33628.sLlFLO.rst M Lib/idlelib/NEWS.txt M Lib/idlelib/codecontext.py M Lib/idlelib/idle_test/test_codecontext.py diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index 786378e2a632..2f8237d2395d 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -3,6 +3,8 @@ Released on 2018-06-18? ====================================== +bpo-33628: Cleanup codecontext.py and its test. + bpo-32831: Add docstrings and tests for codecontext.py. Coverage is 100%. Patch by Cheryl Sabella. diff --git a/Lib/idlelib/codecontext.py b/Lib/idlelib/codecontext.py index efd163ed265e..635f68c86e1f 100644 --- a/Lib/idlelib/codecontext.py +++ b/Lib/idlelib/codecontext.py @@ -23,9 +23,23 @@ FONTUPDATEINTERVAL = 1000 # millisec -def getspacesfirstword(s, c=re.compile(r"^(\s*)(\w*)")): - "Extract the beginning whitespace and first word from s." - return c.match(s).groups() +def get_spaces_firstword(codeline, c=re.compile(r"^(\s*)(\w*)")): + "Extract the beginning whitespace and first word from codeline." + return c.match(codeline).groups() + + +def get_line_info(codeline): + """Return tuple of (line indent value, codeline, block start keyword). + + The indentation of empty lines (or comment lines) is INFINITY. + If the line does not start a block, the keyword value is False. + """ + spaces, firstword = get_spaces_firstword(codeline) + indent = len(spaces) + if len(codeline) == indent or codeline[indent] == '#': + indent = INFINITY + opener = firstword in BLOCKOPENERS and firstword + return indent, codeline, opener class CodeContext: @@ -42,15 +56,15 @@ def __init__(self, editwin): self.textfont is the editor window font. self.label displays the code context text above the editor text. - Initially None it is toggled via <<toggle-code-context>>. + Initially None, it is toggled via <<toggle-code-context>>. self.topvisible is the number of the top text line displayed. self.info is a list of (line number, indent level, line text, block keyword) tuples for the block structure above topvisible. - s self.info[0] is initialized a 'dummy' line which - # starts the toplevel 'block' of the module. + self.info[0] is initialized with a 'dummy' line which + starts the toplevel 'block' of the module. self.t1 and self.t2 are two timer events on the editor text widget to - monitor for changes to the context text or editor font. + monitor for changes to the context text or editor font. """ self.editwin = editwin self.text = editwin.text @@ -94,23 +108,21 @@ def toggle_code_context_event(self, event=None): # All values are passed through getint(), since some # values may be pixel objects, which can't simply be added to ints. widgets = self.editwin.text, self.editwin.text_frame - # Calculate the required vertical padding + # Calculate the required horizontal padding and border width. padx = 0 + border = 0 for widget in widgets: padx += widget.tk.getint(widget.pack_info()['padx']) padx += widget.tk.getint(widget.cget('padx')) - # Calculate the required border width - border = 0 - for widget in widgets: border += widget.tk.getint(widget.cget('border')) self.label = tkinter.Label( self.editwin.top, text="\n" * (self.context_depth - 1), anchor=W, justify=LEFT, font=self.textfont, bg=self.bgcolor, fg=self.fgcolor, - width=1, #don't request more than we get + width=1, # Don't request more than we get. padx=padx, border=border, relief=SUNKEN) # Pack the label widget before and above the text_frame widget, - # thus ensuring that it will appear directly above text_frame + # thus ensuring that it will appear directly above text_frame. self.label.pack(side=TOP, fill=X, expand=False, before=self.editwin.text_frame) else: @@ -118,21 +130,6 @@ def toggle_code_context_event(self, event=None): self.label = None return "break" - def get_line_info(self, linenum): - """Return tuple of (line indent value, text, and block start keyword). - - If the line does not start a block, the keyword value is False. - The indentation of empty lines (or comment lines) is INFINITY. - """ - text = self.text.get("%d.0" % linenum, "%d.end" % linenum) - spaces, firstword = getspacesfirstword(text) - opener = firstword in BLOCKOPENERS and firstword - if len(text) == len(spaces) or text[len(spaces)] == '#': - indent = INFINITY - else: - indent = len(spaces) - return indent, text, opener - def get_context(self, new_topvisible, stopline=1, stopindent=0): """Return a list of block line tuples and the 'last' indent. @@ -144,16 +141,17 @@ def get_context(self, new_topvisible, stopline=1, stopindent=0): """ assert stopline > 0 lines = [] - # The indentation level we are currently in: + # The indentation level we are currently in. lastindent = INFINITY # For a line to be interesting, it must begin with a block opening # keyword, and have less indentation than lastindent. for linenum in range(new_topvisible, stopline-1, -1): - indent, text, opener = self.get_line_info(linenum) + codeline = self.text.get(f'{linenum}.0', f'{linenum}.end') + indent, text, opener = get_line_info(codeline) if indent < lastindent: lastindent = indent if opener in ("else", "elif"): - # We also show the if statement + # Also show the if statement. lastindent += 1 if opener and linenum < new_topvisible and indent >= stopindent: lines.append((linenum, indent, text, opener)) @@ -172,19 +170,19 @@ def update_code_context(self): the context label. """ new_topvisible = int(self.text.index("@0,0").split('.')[0]) - if self.topvisible == new_topvisible: # haven't scrolled + if self.topvisible == new_topvisible: # Haven't scrolled. return - if self.topvisible < new_topvisible: # scroll down + if self.topvisible < new_topvisible: # Scroll down. lines, lastindent = self.get_context(new_topvisible, self.topvisible) - # retain only context info applicable to the region - # between topvisible and new_topvisible: + # Retain only context info applicable to the region + # between topvisible and new_topvisible. while self.info[-1][1] >= lastindent: del self.info[-1] - else: # self.topvisible > new_topvisible: # scroll up + else: # self.topvisible > new_topvisible: # Scroll up. stopindent = self.info[-1][1] + 1 - # retain only context info associated - # with lines above new_topvisible: + # Retain only context info associated + # with lines above new_topvisible. while self.info[-1][0] >= new_topvisible: stopindent = self.info[-1][1] del self.info[-1] @@ -193,9 +191,9 @@ def update_code_context(self): stopindent) self.info.extend(lines) self.topvisible = new_topvisible - # empty lines in context pane: + # Empty lines in context pane. context_strings = [""] * max(0, self.context_depth - len(self.info)) - # followed by the context hint lines: + # Followed by the context hint lines. context_strings += [x[2] for x in self.info[-self.context_depth:]] self.label["text"] = '\n'.join(context_strings) diff --git a/Lib/idlelib/idle_test/test_codecontext.py b/Lib/idlelib/idle_test/test_codecontext.py index 448094eda7ef..ed45828641b4 100644 --- a/Lib/idlelib/idle_test/test_codecontext.py +++ b/Lib/idlelib/idle_test/test_codecontext.py @@ -96,8 +96,6 @@ def test_init(self): eq(self.root.tk.call('after', 'info', self.cc.t2)[1], 'timer') def test_del(self): - self.root.tk.call('after', 'info', self.cc.t1) - self.root.tk.call('after', 'info', self.cc.t2) self.cc.__del__() with self.assertRaises(TclError) as msg: self.root.tk.call('after', 'info', self.cc.t1) @@ -135,21 +133,6 @@ def test_toggle_code_context_event(self): eq(toggle(), 'break') self.assertIsNone(cc.label) - def test_get_line_info(self): - eq = self.assertEqual - gli = self.cc.get_line_info - - # Line 1 is not a BLOCKOPENER. - eq(gli(1), (codecontext.INFINITY, '', False)) - # Line 2 is a BLOCKOPENER without an indent. - eq(gli(2), (0, 'class C1():', 'class')) - # Line 3 is not a BLOCKOPENER and does not return the indent level. - eq(gli(3), (codecontext.INFINITY, ' # Class comment.', False)) - # Line 4 is a BLOCKOPENER and is indented. - eq(gli(4), (4, ' def __init__(self, a, b):', 'def')) - # Line 8 is a different BLOCKOPENER and is indented. - eq(gli(8), (8, ' if a > b:', 'if')) - def test_get_context(self): eq = self.assertEqual gc = self.cc.get_context @@ -323,8 +306,8 @@ def test_font_timer_event(self): class HelperFunctionText(unittest.TestCase): - def test_getspacesfirstword(self): - get = codecontext.getspacesfirstword + def test_get_spaces_firstword(self): + get = codecontext.get_spaces_firstword test_lines = ( (' first word', (' ', 'first')), ('\tfirst word', ('\t', 'first')), @@ -342,6 +325,24 @@ def test_getspacesfirstword(self): c=re.compile(r'^(\s*)([^\s]*)')), (' ', '(continuation)')) + def test_get_line_info(self): + eq = self.assertEqual + gli = codecontext.get_line_info + lines = code_sample.splitlines() + + # Line 1 is not a BLOCKOPENER. + eq(gli(lines[0]), (codecontext.INFINITY, '', False)) + # Line 2 is a BLOCKOPENER without an indent. + eq(gli(lines[1]), (0, 'class C1():', 'class')) + # Line 3 is not a BLOCKOPENER and does not return the indent level. + eq(gli(lines[2]), (codecontext.INFINITY, ' # Class comment.', False)) + # Line 4 is a BLOCKOPENER and is indented. + eq(gli(lines[3]), (4, ' def __init__(self, a, b):', 'def')) + # Line 8 is a different BLOCKOPENER and is indented. + eq(gli(lines[7]), (8, ' if a > b:', 'if')) + # Test tab. + eq(gli('\tif a == b:'), (1, '\tif a == b:', 'if')) + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/Misc/NEWS.d/next/IDLE/2018-05-23-19-51-07.bpo-33628.sLlFLO.rst b/Misc/NEWS.d/next/IDLE/2018-05-23-19-51-07.bpo-33628.sLlFLO.rst new file mode 100644 index 000000000000..f0b13a21c346 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2018-05-23-19-51-07.bpo-33628.sLlFLO.rst @@ -0,0 +1,2 @@ +IDLE: Cleanup codecontext.py and its test. + From webhook-mailer at python.org Thu May 24 02:37:19 2018 From: webhook-mailer at python.org (Benjamin Peterson) Date: Thu, 24 May 2018 06:37:19 -0000 Subject: [Python-checkins] closes bpo-33619: Fix libffi detection by regenerating ./configure (GH-7075) Message-ID: <mailman.47.1527143840.18020.python-checkins@python.org> https://github.com/python/cpython/commit/03c0d2e1f272c7c6df5f6066a6abc222ff61073a commit: 03c0d2e1f272c7c6df5f6066a6abc222ff61073a branch: master author: Chih-Hsuan Yen <yan12125 at gmail.com> committer: Benjamin Peterson <benjamin at python.org> date: 2018-05-23T23:37:08-07:00 summary: closes bpo-33619: Fix libffi detection by regenerating ./configure (GH-7075) files: M aclocal.m4 M configure diff --git a/aclocal.m4 b/aclocal.m4 index 6aa28ee7a5c4..8ed232fb515f 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -12,4 +12,280 @@ # PARTICULAR PURPOSE. m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) +# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +# serial 12 (pkg-config-0.29.2) + +dnl Copyright ? 2004 Scott James Remnant <scott at netsplit.com>. +dnl Copyright ? 2012-2015 Dan Nicholson <dbn.lists at gmail.com> +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but +dnl WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +dnl 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a +dnl configuration script generated by Autoconf, you may include it under +dnl the same distribution terms that you use for the rest of that +dnl program. + +dnl PKG_PREREQ(MIN-VERSION) +dnl ----------------------- +dnl Since: 0.29 +dnl +dnl Verify that the version of the pkg-config macros are at least +dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's +dnl installed version of pkg-config, this checks the developer's version +dnl of pkg.m4 when generating configure. +dnl +dnl To ensure that this macro is defined, also add: +dnl m4_ifndef([PKG_PREREQ], +dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) +dnl +dnl See the "Since" comment for each macro you use to see what version +dnl of the macros you require. +m4_defun([PKG_PREREQ], +[m4_define([PKG_MACROS_VERSION], [0.29.2]) +m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, + [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) +])dnl PKG_PREREQ + +dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) +dnl ---------------------------------- +dnl Since: 0.16 +dnl +dnl Search for the pkg-config tool and set the PKG_CONFIG variable to +dnl first found in the path. Checks that the version of pkg-config found +dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is +dnl used since that's the first version where most current features of +dnl pkg-config existed. +AC_DEFUN([PKG_PROG_PKG_CONFIG], +[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) +m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) +AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) +AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.9.0]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi +fi[]dnl +])dnl PKG_PROG_PKG_CONFIG + +dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------------------------------- +dnl Since: 0.18 +dnl +dnl Check to see whether a particular set of modules exists. Similar to +dnl PKG_CHECK_MODULES(), but does not set variables or print errors. +dnl +dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +dnl only at the first occurence in configure.ac, so if the first place +dnl it's called might be skipped (such as if it is within an "if", you +dnl have to call PKG_CHECK_EXISTS manually +AC_DEFUN([PKG_CHECK_EXISTS], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +if test -n "$PKG_CONFIG" && \ + AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then + m4_default([$2], [:]) +m4_ifvaln([$3], [else + $3])dnl +fi]) + +dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +dnl --------------------------------------------- +dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting +dnl pkg_failed based on the result. +m4_define([_PKG_CONFIG], +[if test -n "$$1"; then + pkg_cv_[]$1="$$1" + elif test -n "$PKG_CONFIG"; then + PKG_CHECK_EXISTS([$3], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes ], + [pkg_failed=yes]) + else + pkg_failed=untried +fi[]dnl +])dnl _PKG_CONFIG + +dnl _PKG_SHORT_ERRORS_SUPPORTED +dnl --------------------------- +dnl Internal check to see if pkg-config supports short errors. +AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi[]dnl +])dnl _PKG_SHORT_ERRORS_SUPPORTED + + +dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl -------------------------------------------------------------- +dnl Since: 0.4.0 +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES might not happen, you should be sure to include an +dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac +AC_DEFUN([PKG_CHECK_MODULES], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl +AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl + +pkg_failed=no +AC_MSG_CHECKING([for $2]) + +_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) +_PKG_CONFIG([$1][_LIBS], [libs], [$2]) + +m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS +and $1[]_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details.]) + +if test $pkg_failed = yes; then + AC_MSG_RESULT([no]) + _PKG_SHORT_ERRORS_SUPPORTED + if test $_pkg_short_errors_supported = yes; then + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + + m4_default([$4], [AC_MSG_ERROR( +[Package requirements ($2) were not met: + +$$1_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +_PKG_TEXT])[]dnl + ]) +elif test $pkg_failed = untried; then + AC_MSG_RESULT([no]) + m4_default([$4], [AC_MSG_FAILURE( +[The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +_PKG_TEXT + +To get pkg-config, see <http://pkg-config.freedesktop.org/>.])[]dnl + ]) +else + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + AC_MSG_RESULT([yes]) + $3 +fi[]dnl +])dnl PKG_CHECK_MODULES + + +dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl --------------------------------------------------------------------- +dnl Since: 0.29 +dnl +dnl Checks for existence of MODULES and gathers its build flags with +dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags +dnl and VARIABLE-PREFIX_LIBS from --libs. +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to +dnl include an explicit call to PKG_PROG_PKG_CONFIG in your +dnl configure.ac. +AC_DEFUN([PKG_CHECK_MODULES_STATIC], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +_save_PKG_CONFIG=$PKG_CONFIG +PKG_CONFIG="$PKG_CONFIG --static" +PKG_CHECK_MODULES($@) +PKG_CONFIG=$_save_PKG_CONFIG[]dnl +])dnl PKG_CHECK_MODULES_STATIC + + +dnl PKG_INSTALLDIR([DIRECTORY]) +dnl ------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable pkgconfigdir as the location where a module +dnl should install pkg-config .pc files. By default the directory is +dnl $libdir/pkgconfig, but the default can be changed by passing +dnl DIRECTORY. The user can override through the --with-pkgconfigdir +dnl parameter. +AC_DEFUN([PKG_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([pkgconfigdir], + [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, + [with_pkgconfigdir=]pkg_default) +AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_INSTALLDIR + + +dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) +dnl -------------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable noarch_pkgconfigdir as the location where a +dnl module should install arch-independent pkg-config .pc files. By +dnl default the directory is $datadir/pkgconfig, but the default can be +dnl changed by passing DIRECTORY. The user can override through the +dnl --with-noarch-pkgconfigdir parameter. +AC_DEFUN([PKG_NOARCH_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([noarch-pkgconfigdir], + [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, + [with_noarch_pkgconfigdir=]pkg_default) +AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_NOARCH_INSTALLDIR + + +dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, +dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------- +dnl Since: 0.28 +dnl +dnl Retrieves the value of the pkg-config variable for the given module. +AC_DEFUN([PKG_CHECK_VAR], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl + +_PKG_CONFIG([$1], [variable="][$3]["], [$2]) +AS_VAR_COPY([$1], [pkg_cv_][$1]) + +AS_VAR_IF([$1], [""], [$5], [$4])dnl +])dnl PKG_CHECK_VAR + m4_include([m4/ax_check_openssl.m4]) diff --git a/configure b/configure index 669060bea128..6a4650243ddd 100755 --- a/configure +++ b/configure @@ -626,7 +626,6 @@ ac_subst_vars='LTLIBOBJS OPENSSL_LDFLAGS OPENSSL_LIBS OPENSSL_INCLUDES -PKG_CONFIG ENSUREPIP SRCDIRS THREADHEADERS @@ -654,6 +653,9 @@ LDLAST TCLTK_LIBS TCLTK_INCLUDES LIBFFI_INCLUDEDIR +PKG_CONFIG_LIBDIR +PKG_CONFIG_PATH +PKG_CONFIG SHLIBS CFLAGSFORSHARED LINKFORSHARED @@ -847,7 +849,10 @@ CFLAGS LDFLAGS LIBS CPPFLAGS -CPP' +CPP +PKG_CONFIG +PKG_CONFIG_PATH +PKG_CONFIG_LIBDIR' # Initialize some variables set by options. @@ -1547,6 +1552,11 @@ Some influential environment variables: CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if you have headers in a nonstandard directory <include dir> CPP C preprocessor + PKG_CONFIG path to pkg-config utility + PKG_CONFIG_PATH + directories to add to pkg-config's search path + PKG_CONFIG_LIBDIR + path overriding pkg-config's built-in search path Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. @@ -9906,7 +9916,126 @@ $as_echo "no" >&6; } fi -PKG_PROG_PKG_CONFIG + + + + + + + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG +if test -n "$PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +$as_echo "$PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_PKG_CONFIG"; then + ac_pt_PKG_CONFIG=$PKG_CONFIG + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG +if test -n "$ac_pt_PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 +$as_echo "$ac_pt_PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_pt_PKG_CONFIG" = x; then + PKG_CONFIG="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + PKG_CONFIG=$ac_pt_PKG_CONFIG + fi +else + PKG_CONFIG="$ac_cv_path_PKG_CONFIG" +fi + +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=0.9.0 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 +$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + PKG_CONFIG="" + fi +fi # Check for use of the system expat library { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-system-expat" >&5 From solipsis at pitrou.net Thu May 24 05:10:31 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 24 May 2018 09:10:31 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=6 Message-ID: <20180524091031.1.F2E3738922F59E57@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_collections leaked [7, -7, 1] memory blocks, sum=1 test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_forkserver leaked [0, -1, 2] memory blocks, sum=1 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflog4CmXew', '--timeout', '7200'] From webhook-mailer at python.org Thu May 24 08:19:37 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Thu, 24 May 2018 12:19:37 -0000 Subject: [Python-checkins] bpo-33622: Fix issues with handling errors in the GC. (GH-7078) Message-ID: <mailman.48.1527164380.18020.python-checkins@python.org> https://github.com/python/cpython/commit/301e3cc8a5bc68c5347ab6ac6f83428000d31ab2 commit: 301e3cc8a5bc68c5347ab6ac6f83428000d31ab2 branch: master author: Serhiy Storchaka <storchaka at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-24T15:19:29+03:00 summary: bpo-33622: Fix issues with handling errors in the GC. (GH-7078) * Fixed a leak when the GC fails to add an object with __del__ into the gc.garbage list. * PyGC_Collect() can now be called when an exception is set and preserves it. * Fixed an undefined behavior with comparing a dead pointer with NULL. files: A Misc/NEWS.d/next/Core and Builtins/2018-05-23-20-46-14.bpo-33622.xPucO9.rst M Modules/gcmodule.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-05-23-20-46-14.bpo-33622.xPucO9.rst b/Misc/NEWS.d/next/Core and Builtins/2018-05-23-20-46-14.bpo-33622.xPucO9.rst new file mode 100644 index 000000000000..e589b4503229 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-05-23-20-46-14.bpo-33622.xPucO9.rst @@ -0,0 +1,4 @@ +Fixed a leak when the garbage collector fails to add an object with the +``__del__`` method or referenced by it into the :data:`gc.garbage` list. +:c:func:`PyGC_Collect` can now be called when an exception is set and +preserves it. diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index 09c73569360e..4d701cb72e8c 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -648,10 +648,8 @@ debug_cycle(const char *msg, PyObject *op) * garbage list (a Python list), else only the objects in finalizers with * __del__ methods are appended to garbage. All objects in finalizers are * merged into the old list regardless. - * Returns 0 if all OK, <0 on error (out of memory to grow the garbage list). - * The finalizers list is made empty on a successful return. */ -static int +static void handle_legacy_finalizers(PyGC_Head *finalizers, PyGC_Head *old) { PyGC_Head *gc = finalizers->gc.gc_next; @@ -666,12 +664,11 @@ handle_legacy_finalizers(PyGC_Head *finalizers, PyGC_Head *old) if ((_PyRuntime.gc.debug & DEBUG_SAVEALL) || has_legacy_finalizer(op)) { if (PyList_Append(_PyRuntime.gc.garbage, op) < 0) - return -1; + break; } } gc_list_merge(finalizers, old); - return 0; } /* Run first-time finalizers (if any) on all the objects in collectable. @@ -945,7 +942,7 @@ collect(int generation, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable, * reachable list of garbage. The programmer has to deal with * this if they insist on creating this type of structure. */ - (void)handle_legacy_finalizers(&finalizers, old); + handle_legacy_finalizers(&finalizers, old); /* Clear free list only during the collection of the highest * generation */ @@ -1009,9 +1006,12 @@ invoke_gc_callback(const char *phase, int generation, PyObject *r, *cb = PyList_GET_ITEM(_PyRuntime.gc.callbacks, i); Py_INCREF(cb); /* make sure cb doesn't go away */ r = PyObject_CallFunction(cb, "sO", phase, info); - Py_XDECREF(r); - if (r == NULL) + if (r == NULL) { PyErr_WriteUnraisable(cb); + } + else { + Py_DECREF(r); + } Py_DECREF(cb); } Py_XDECREF(info); @@ -1567,8 +1567,11 @@ PyGC_Collect(void) if (_PyRuntime.gc.collecting) n = 0; /* already collecting, don't do anything */ else { + PyObject *exc, *value, *tb; _PyRuntime.gc.collecting = 1; + PyErr_Fetch(&exc, &value, &tb); n = collect_with_callback(NUM_GENERATIONS - 1); + PyErr_Restore(exc, value, tb); _PyRuntime.gc.collecting = 0; } From webhook-mailer at python.org Thu May 24 08:39:12 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 24 May 2018 12:39:12 -0000 Subject: [Python-checkins] bpo-33622: Fix issues with handling errors in the GC. (GH-7078) Message-ID: <mailman.49.1527165554.18020.python-checkins@python.org> https://github.com/python/cpython/commit/2fe940c727802ad54cff9486c658bc38743f7bfc commit: 2fe940c727802ad54cff9486c658bc38743f7bfc branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-24T05:39:08-07:00 summary: bpo-33622: Fix issues with handling errors in the GC. (GH-7078) * Fixed a leak when the GC fails to add an object with __del__ into the gc.garbage list. * PyGC_Collect() can now be called when an exception is set and preserves it. * Fixed an undefined behavior with comparing a dead pointer with NULL. (cherry picked from commit 301e3cc8a5bc68c5347ab6ac6f83428000d31ab2) Co-authored-by: Serhiy Storchaka <storchaka at gmail.com> files: A Misc/NEWS.d/next/Core and Builtins/2018-05-23-20-46-14.bpo-33622.xPucO9.rst M Modules/gcmodule.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-05-23-20-46-14.bpo-33622.xPucO9.rst b/Misc/NEWS.d/next/Core and Builtins/2018-05-23-20-46-14.bpo-33622.xPucO9.rst new file mode 100644 index 000000000000..e589b4503229 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-05-23-20-46-14.bpo-33622.xPucO9.rst @@ -0,0 +1,4 @@ +Fixed a leak when the garbage collector fails to add an object with the +``__del__`` method or referenced by it into the :data:`gc.garbage` list. +:c:func:`PyGC_Collect` can now be called when an exception is set and +preserves it. diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index 09c73569360e..4d701cb72e8c 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -648,10 +648,8 @@ debug_cycle(const char *msg, PyObject *op) * garbage list (a Python list), else only the objects in finalizers with * __del__ methods are appended to garbage. All objects in finalizers are * merged into the old list regardless. - * Returns 0 if all OK, <0 on error (out of memory to grow the garbage list). - * The finalizers list is made empty on a successful return. */ -static int +static void handle_legacy_finalizers(PyGC_Head *finalizers, PyGC_Head *old) { PyGC_Head *gc = finalizers->gc.gc_next; @@ -666,12 +664,11 @@ handle_legacy_finalizers(PyGC_Head *finalizers, PyGC_Head *old) if ((_PyRuntime.gc.debug & DEBUG_SAVEALL) || has_legacy_finalizer(op)) { if (PyList_Append(_PyRuntime.gc.garbage, op) < 0) - return -1; + break; } } gc_list_merge(finalizers, old); - return 0; } /* Run first-time finalizers (if any) on all the objects in collectable. @@ -945,7 +942,7 @@ collect(int generation, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable, * reachable list of garbage. The programmer has to deal with * this if they insist on creating this type of structure. */ - (void)handle_legacy_finalizers(&finalizers, old); + handle_legacy_finalizers(&finalizers, old); /* Clear free list only during the collection of the highest * generation */ @@ -1009,9 +1006,12 @@ invoke_gc_callback(const char *phase, int generation, PyObject *r, *cb = PyList_GET_ITEM(_PyRuntime.gc.callbacks, i); Py_INCREF(cb); /* make sure cb doesn't go away */ r = PyObject_CallFunction(cb, "sO", phase, info); - Py_XDECREF(r); - if (r == NULL) + if (r == NULL) { PyErr_WriteUnraisable(cb); + } + else { + Py_DECREF(r); + } Py_DECREF(cb); } Py_XDECREF(info); @@ -1567,8 +1567,11 @@ PyGC_Collect(void) if (_PyRuntime.gc.collecting) n = 0; /* already collecting, don't do anything */ else { + PyObject *exc, *value, *tb; _PyRuntime.gc.collecting = 1; + PyErr_Fetch(&exc, &value, &tb); n = collect_with_callback(NUM_GENERATIONS - 1); + PyErr_Restore(exc, value, tb); _PyRuntime.gc.collecting = 0; } From webhook-mailer at python.org Thu May 24 09:05:41 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Thu, 24 May 2018 13:05:41 -0000 Subject: [Python-checkins] [3.6] bpo-33622: Fix issues with handling errors in the GC. (GH-7078) (GH-7095) Message-ID: <mailman.50.1527167143.18020.python-checkins@python.org> https://github.com/python/cpython/commit/f0e04b2ae27a4da940a76ae522f0438f80ce5d5a commit: f0e04b2ae27a4da940a76ae522f0438f80ce5d5a branch: 3.6 author: Serhiy Storchaka <storchaka at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-24T16:05:38+03:00 summary: [3.6] bpo-33622: Fix issues with handling errors in the GC. (GH-7078) (GH-7095) * Fixed a leak when the GC fails to add an object with __del__ into the gc.garbage list. * PyGC_Collect() can now be called when an exception is set and preserves it. * Fixed an undefined behavior with comparing a dead pointer with NULL. (cherry picked from commit 301e3cc8a5bc68c5347ab6ac6f83428000d31ab2) files: A Misc/NEWS.d/next/Core and Builtins/2018-05-23-20-46-14.bpo-33622.xPucO9.rst M Modules/gcmodule.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-05-23-20-46-14.bpo-33622.xPucO9.rst b/Misc/NEWS.d/next/Core and Builtins/2018-05-23-20-46-14.bpo-33622.xPucO9.rst new file mode 100644 index 000000000000..e589b4503229 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-05-23-20-46-14.bpo-33622.xPucO9.rst @@ -0,0 +1,4 @@ +Fixed a leak when the garbage collector fails to add an object with the +``__del__`` method or referenced by it into the :data:`gc.garbage` list. +:c:func:`PyGC_Collect` can now be called when an exception is set and +preserves it. diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index 0b057ddbf5e4..3bddc403da9c 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -751,10 +751,8 @@ debug_cycle(const char *msg, PyObject *op) * garbage list (a Python list), else only the objects in finalizers with * __del__ methods are appended to garbage. All objects in finalizers are * merged into the old list regardless. - * Returns 0 if all OK, <0 on error (out of memory to grow the garbage list). - * The finalizers list is made empty on a successful return. */ -static int +static void handle_legacy_finalizers(PyGC_Head *finalizers, PyGC_Head *old) { PyGC_Head *gc = finalizers->gc.gc_next; @@ -769,12 +767,11 @@ handle_legacy_finalizers(PyGC_Head *finalizers, PyGC_Head *old) if ((debug & DEBUG_SAVEALL) || has_legacy_finalizer(op)) { if (PyList_Append(garbage, op) < 0) - return -1; + break; } } gc_list_merge(finalizers, old); - return 0; } /* Run first-time finalizers (if any) on all the objects in collectable. @@ -1045,7 +1042,7 @@ collect(int generation, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable, * reachable list of garbage. The programmer has to deal with * this if they insist on creating this type of structure. */ - (void)handle_legacy_finalizers(&finalizers, old); + handle_legacy_finalizers(&finalizers, old); /* Clear free list only during the collection of the highest * generation */ @@ -1109,9 +1106,12 @@ invoke_gc_callback(const char *phase, int generation, PyObject *r, *cb = PyList_GET_ITEM(callbacks, i); Py_INCREF(cb); /* make sure cb doesn't go away */ r = PyObject_CallFunction(cb, "sO", phase, info); - Py_XDECREF(r); - if (r == NULL) + if (r == NULL) { PyErr_WriteUnraisable(cb); + } + else { + Py_DECREF(r); + } Py_DECREF(cb); } Py_XDECREF(info); @@ -1588,8 +1588,11 @@ PyGC_Collect(void) if (collecting) n = 0; /* already collecting, don't do anything */ else { + PyObject *exc, *value, *tb; collecting = 1; + PyErr_Fetch(&exc, &value, &tb); n = collect_with_callback(NUM_GENERATIONS - 1); + PyErr_Restore(exc, value, tb); collecting = 0; } From webhook-mailer at python.org Thu May 24 16:19:37 2018 From: webhook-mailer at python.org (Victor Stinner) Date: Thu, 24 May 2018 20:19:37 -0000 Subject: [Python-checkins] bpo-33629: Prevent coredump in test_importlib (GH-7090) Message-ID: <mailman.51.1527193183.18020.python-checkins@python.org> https://github.com/python/cpython/commit/483000e164ec68717d335767b223ae31b4b720cf commit: 483000e164ec68717d335767b223ae31b4b720cf branch: master author: Victor Stinner <vstinner at redhat.com> committer: GitHub <noreply at github.com> date: 2018-05-24T22:19:33+02:00 summary: bpo-33629: Prevent coredump in test_importlib (GH-7090) bpo-32374, bpo-33629: Use support.SuppressCrashReport() in test_bad_traverse() of MultiPhaseExtensionModuleTests to prevent leaking a core dump file. files: M Lib/test/test_importlib/extension/test_loader.py diff --git a/Lib/test/test_importlib/extension/test_loader.py b/Lib/test/test_importlib/extension/test_loader.py index 53ac3c71d4b5..57ba7083d37d 100644 --- a/Lib/test/test_importlib/extension/test_loader.py +++ b/Lib/test/test_importlib/extension/test_loader.py @@ -275,10 +275,13 @@ def test_bad_traverse(self): (Multiphase initialization modules only) ''' script = """if True: + from test import support import importlib.util as util spec = util.find_spec('_testmultiphase') spec.name = '_testmultiphase_with_bad_traverse' - m = spec.loader.create_module(spec)""" + + with support.SuppressCrashReport(): + m = spec.loader.create_module(spec)""" assert_python_failure("-c", script) From webhook-mailer at python.org Thu May 24 16:27:12 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Thu, 24 May 2018 20:27:12 -0000 Subject: [Python-checkins] [2.7] bpo-33622: Fix issues with handling errors in the GC. (GH-7078) (#7096) Message-ID: <mailman.52.1527193634.18020.python-checkins@python.org> https://github.com/python/cpython/commit/9044cd675902b438bc500908e410382ff48299d8 commit: 9044cd675902b438bc500908e410382ff48299d8 branch: 2.7 author: Serhiy Storchaka <storchaka at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-24T23:27:08+03:00 summary: [2.7] bpo-33622: Fix issues with handling errors in the GC. (GH-7078) (#7096) * Fixed a leak when the GC fails to add an object with __del__ into the gc.garbage list. * PyGC_Collect() can now be called when an exception is set and preserves it. (cherry picked from commit 301e3cc8a5bc68c5347ab6ac6f83428000d31ab2) files: A Misc/NEWS.d/next/Core and Builtins/2018-05-23-20-46-14.bpo-33622.xPucO9.rst M Modules/gcmodule.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-05-23-20-46-14.bpo-33622.xPucO9.rst b/Misc/NEWS.d/next/Core and Builtins/2018-05-23-20-46-14.bpo-33622.xPucO9.rst new file mode 100644 index 000000000000..e589b4503229 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-05-23-20-46-14.bpo-33622.xPucO9.rst @@ -0,0 +1,4 @@ +Fixed a leak when the garbage collector fails to add an object with the +``__del__`` method or referenced by it into the :data:`gc.garbage` list. +:c:func:`PyGC_Collect` can now be called when an exception is set and +preserves it. diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index 19011c47b5c4..700c1a32b079 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -771,10 +771,8 @@ debug_cycle(char *msg, PyObject *op) * garbage list (a Python list), else only the objects in finalizers with * __del__ methods are appended to garbage. All objects in finalizers are * merged into the old list regardless. - * Returns 0 if all OK, <0 on error (out of memory to grow the garbage list). - * The finalizers list is made empty on a successful return. */ -static int +static void handle_finalizers(PyGC_Head *finalizers, PyGC_Head *old) { PyGC_Head *gc = finalizers->gc.gc_next; @@ -789,12 +787,11 @@ handle_finalizers(PyGC_Head *finalizers, PyGC_Head *old) if ((debug & DEBUG_SAVEALL) || has_finalizer(op)) { if (PyList_Append(garbage, op) < 0) - return -1; + break; } } gc_list_merge(finalizers, old); - return 0; } /* Break reference cycles by clearing the containers involved. This is @@ -1012,7 +1009,7 @@ collect(int generation) * reachable list of garbage. The programmer has to deal with * this if they insist on creating this type of structure. */ - (void)handle_finalizers(&finalizers, old); + handle_finalizers(&finalizers, old); /* Clear free list only during the collection of the highest * generation */ @@ -1436,8 +1433,11 @@ PyGC_Collect(void) if (collecting) n = 0; /* already collecting, don't do anything */ else { + PyObject *exc, *value, *tb; collecting = 1; + PyErr_Fetch(&exc, &value, &tb); n = collect(NUM_GENERATIONS - 1); + PyErr_Restore(exc, value, tb); collecting = 0; } From webhook-mailer at python.org Thu May 24 16:45:00 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 24 May 2018 20:45:00 -0000 Subject: [Python-checkins] bpo-33629: Prevent coredump in test_importlib (GH-7090) Message-ID: <mailman.53.1527194701.18020.python-checkins@python.org> https://github.com/python/cpython/commit/d9eb22c67c38b45764dd924801c72092770d200f commit: d9eb22c67c38b45764dd924801c72092770d200f branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-24T13:44:56-07:00 summary: bpo-33629: Prevent coredump in test_importlib (GH-7090) bpo-32374, bpo-33629: Use support.SuppressCrashReport() in test_bad_traverse() of MultiPhaseExtensionModuleTests to prevent leaking a core dump file. (cherry picked from commit 483000e164ec68717d335767b223ae31b4b720cf) Co-authored-by: Victor Stinner <vstinner at redhat.com> files: M Lib/test/test_importlib/extension/test_loader.py diff --git a/Lib/test/test_importlib/extension/test_loader.py b/Lib/test/test_importlib/extension/test_loader.py index 53ac3c71d4b5..57ba7083d37d 100644 --- a/Lib/test/test_importlib/extension/test_loader.py +++ b/Lib/test/test_importlib/extension/test_loader.py @@ -275,10 +275,13 @@ def test_bad_traverse(self): (Multiphase initialization modules only) ''' script = """if True: + from test import support import importlib.util as util spec = util.find_spec('_testmultiphase') spec.name = '_testmultiphase_with_bad_traverse' - m = spec.loader.create_module(spec)""" + + with support.SuppressCrashReport(): + m = spec.loader.create_module(spec)""" assert_python_failure("-c", script) From webhook-mailer at python.org Thu May 24 17:07:47 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 24 May 2018 21:07:47 -0000 Subject: [Python-checkins] bpo-33629: Prevent coredump in test_importlib (GH-7090) Message-ID: <mailman.54.1527196072.18020.python-checkins@python.org> https://github.com/python/cpython/commit/fc0356d2a34719df517a5056bf1a3709850776cf commit: fc0356d2a34719df517a5056bf1a3709850776cf branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-24T14:07:44-07:00 summary: bpo-33629: Prevent coredump in test_importlib (GH-7090) bpo-32374, bpo-33629: Use support.SuppressCrashReport() in test_bad_traverse() of MultiPhaseExtensionModuleTests to prevent leaking a core dump file. (cherry picked from commit 483000e164ec68717d335767b223ae31b4b720cf) Co-authored-by: Victor Stinner <vstinner at redhat.com> files: M Lib/test/test_importlib/extension/test_loader.py diff --git a/Lib/test/test_importlib/extension/test_loader.py b/Lib/test/test_importlib/extension/test_loader.py index 53ac3c71d4b5..57ba7083d37d 100644 --- a/Lib/test/test_importlib/extension/test_loader.py +++ b/Lib/test/test_importlib/extension/test_loader.py @@ -275,10 +275,13 @@ def test_bad_traverse(self): (Multiphase initialization modules only) ''' script = """if True: + from test import support import importlib.util as util spec = util.find_spec('_testmultiphase') spec.name = '_testmultiphase_with_bad_traverse' - m = spec.loader.create_module(spec)""" + + with support.SuppressCrashReport(): + m = spec.loader.create_module(spec)""" assert_python_failure("-c", script) From webhook-mailer at python.org Thu May 24 18:20:47 2018 From: webhook-mailer at python.org (Victor Stinner) Date: Thu, 24 May 2018 22:20:47 -0000 Subject: [Python-checkins] bpo-33354: Fix test_ssl when a filename cannot be encoded (GH-6613) Message-ID: <mailman.55.1527200450.18020.python-checkins@python.org> https://github.com/python/cpython/commit/19f6bd06af3c7fc0db5f96878aaa68f5589ff13e commit: 19f6bd06af3c7fc0db5f96878aaa68f5589ff13e branch: 2.7 author: Pablo Galindo <Pablogsal at gmail.com> committer: Victor Stinner <vstinner at redhat.com> date: 2018-05-25T00:20:44+02:00 summary: bpo-33354: Fix test_ssl when a filename cannot be encoded (GH-6613) Skip test_load_dh_params() of test_ssl when Python filesystem encoding cannot encode the provided path. files: A Misc/NEWS.d/next/Tests/2018-04-26-22-39-17.bpo-33354.g35-44.rst M Lib/test/test_ssl.py diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index b59fe73f04c7..7ced90fdf678 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -989,6 +989,13 @@ def test_load_verify_cadata(self): def test_load_dh_params(self): + filename = u'dhp?r?m.pem' + fs_encoding = sys.getfilesystemencoding() + try: + filename.encode(fs_encoding) + except UnicodeEncodeError: + self.skipTest("filename %r cannot be encoded to the filesystem encoding %r" % (filename, fs_encoding)) + ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) ctx.load_dh_params(DHFILE) if os.name != 'nt': @@ -1001,7 +1008,7 @@ def test_load_dh_params(self): with self.assertRaises(ssl.SSLError) as cm: ctx.load_dh_params(CERTFILE) with support.temp_dir() as d: - fname = os.path.join(d, u'dhp?r?m.pem') + fname = os.path.join(d, filename) shutil.copy(DHFILE, fname) ctx.load_dh_params(fname) diff --git a/Misc/NEWS.d/next/Tests/2018-04-26-22-39-17.bpo-33354.g35-44.rst b/Misc/NEWS.d/next/Tests/2018-04-26-22-39-17.bpo-33354.g35-44.rst new file mode 100644 index 000000000000..c66cecac32e7 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2018-04-26-22-39-17.bpo-33354.g35-44.rst @@ -0,0 +1,2 @@ +Skip ``test_ssl.test_load_dh_params`` when Python filesystem encoding cannot encode the +provided path. From webhook-mailer at python.org Thu May 24 18:45:18 2018 From: webhook-mailer at python.org (Victor Stinner) Date: Thu, 24 May 2018 22:45:18 -0000 Subject: [Python-checkins] bpo-32493: Fix uuid.uuid1() on FreeBSD. (GH-7099) Message-ID: <mailman.56.1527201919.18020.python-checkins@python.org> https://github.com/python/cpython/commit/17d8830312d82e7de42ab89739b0771f712645ff commit: 17d8830312d82e7de42ab89739b0771f712645ff branch: master author: Serhiy Storchaka <storchaka at gmail.com> committer: Victor Stinner <vstinner at redhat.com> date: 2018-05-25T00:45:09+02:00 summary: bpo-32493: Fix uuid.uuid1() on FreeBSD. (GH-7099) Use uuid_enc_be() if available to encode UUID to bytes as big endian. files: A Misc/NEWS.d/next/Library/2018-05-24-17-41-36.bpo-32493.5tAoAu.rst M Modules/_uuidmodule.c M configure M configure.ac M pyconfig.h.in diff --git a/Misc/NEWS.d/next/Library/2018-05-24-17-41-36.bpo-32493.5tAoAu.rst b/Misc/NEWS.d/next/Library/2018-05-24-17-41-36.bpo-32493.5tAoAu.rst new file mode 100644 index 000000000000..32f88dd0388d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-24-17-41-36.bpo-32493.5tAoAu.rst @@ -0,0 +1 @@ +Fixed :func:`uuid.uuid1` on FreeBSD. diff --git a/Modules/_uuidmodule.c b/Modules/_uuidmodule.c index 3a0c05738266..0b7f2a2545d4 100644 --- a/Modules/_uuidmodule.c +++ b/Modules/_uuidmodule.c @@ -19,10 +19,16 @@ py_uuid_generate_time_safe(PyObject *Py_UNUSED(context), res = uuid_generate_time_safe(uuid); return Py_BuildValue("y#i", (const char *) uuid, sizeof(uuid), res); -#elif HAVE_UUID_CREATE +#elif defined(HAVE_UUID_CREATE) uint32_t status; uuid_create(&uuid, &status); +# if defined(HAVE_UUID_ENC_BE) + unsigned char buf[sizeof(uuid)]; + uuid_enc_be(buf, &uuid); + return Py_BuildValue("y#i", buf, sizeof(uuid), (int) status); +# else return Py_BuildValue("y#i", (const char *) &uuid, sizeof(uuid), (int) status); +# endif #else uuid_generate_time(uuid); return Py_BuildValue("y#O", (const char *) uuid, sizeof(uuid), Py_None); @@ -58,6 +64,7 @@ PyInit__uuid(void) } if (PyModule_AddIntConstant(mod, "has_uuid_generate_time_safe", has_uuid_generate_time_safe) < 0) { + Py_DECREF(mod); return NULL; } diff --git a/configure b/configure index 6a4650243ddd..ea482602c615 100755 --- a/configure +++ b/configure @@ -9584,6 +9584,40 @@ $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +# Little-endian FreeBSD, OpenBSD and NetBSD needs encoding into an octet +# stream in big-endian byte-order +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_enc_be" >&5 +$as_echo_n "checking for uuid_enc_be... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <uuid.h> +int +main () +{ + +#ifndef uuid_enc_be +uuid_t uuid; +unsigned char buf[sizeof(uuid)]; +uuid_enc_be(buf, &uuid); +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +$as_echo "#define HAVE_UUID_ENC_BE 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + # 'Real Time' functions on Solaris # posix4 on Solaris 2.6 # pthread (first!) on Linux diff --git a/configure.ac b/configure.ac index 679fac318e17..872a829f7327 100644 --- a/configure.ac +++ b/configure.ac @@ -2696,6 +2696,21 @@ void *x = uuid_create [AC_MSG_RESULT(no)] ) +# Little-endian FreeBSD, OpenBSD and NetBSD needs encoding into an octet +# stream in big-endian byte-order +AC_MSG_CHECKING(for uuid_enc_be) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <uuid.h>]], [[ +#ifndef uuid_enc_be +uuid_t uuid; +unsigned char buf[sizeof(uuid)]; +uuid_enc_be(buf, &uuid); +#endif +]])], + [AC_DEFINE(HAVE_UUID_ENC_BE, 1, Define if uuid_enc_be() exists.) + AC_MSG_RESULT(yes)], + [AC_MSG_RESULT(no)] +) + # 'Real Time' functions on Solaris # posix4 on Solaris 2.6 # pthread (first!) on Linux diff --git a/pyconfig.h.in b/pyconfig.h.in index 2af411705a67..914831903623 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -1215,6 +1215,9 @@ /* Define if uuid_create() exists. */ #undef HAVE_UUID_CREATE +/* Define if uuid_enc_be() exists. */ +#undef HAVE_UUID_ENC_BE + /* Define if uuid_generate_time_safe() exists. */ #undef HAVE_UUID_GENERATE_TIME_SAFE From webhook-mailer at python.org Thu May 24 19:23:02 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 24 May 2018 23:23:02 -0000 Subject: [Python-checkins] bpo-32493: Fix uuid.uuid1() on FreeBSD. (GH-7099) Message-ID: <mailman.57.1527204184.18020.python-checkins@python.org> https://github.com/python/cpython/commit/5734f41a9b46b4fd65b6ba90240b108f8a0b7c57 commit: 5734f41a9b46b4fd65b6ba90240b108f8a0b7c57 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-24T16:22:59-07:00 summary: bpo-32493: Fix uuid.uuid1() on FreeBSD. (GH-7099) Use uuid_enc_be() if available to encode UUID to bytes as big endian. (cherry picked from commit 17d8830312d82e7de42ab89739b0771f712645ff) Co-authored-by: Serhiy Storchaka <storchaka at gmail.com> files: A Misc/NEWS.d/next/Library/2018-05-24-17-41-36.bpo-32493.5tAoAu.rst M Modules/_uuidmodule.c M configure M configure.ac M pyconfig.h.in diff --git a/Misc/NEWS.d/next/Library/2018-05-24-17-41-36.bpo-32493.5tAoAu.rst b/Misc/NEWS.d/next/Library/2018-05-24-17-41-36.bpo-32493.5tAoAu.rst new file mode 100644 index 000000000000..32f88dd0388d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-24-17-41-36.bpo-32493.5tAoAu.rst @@ -0,0 +1 @@ +Fixed :func:`uuid.uuid1` on FreeBSD. diff --git a/Modules/_uuidmodule.c b/Modules/_uuidmodule.c index 16aa09b04ff2..89499143a61b 100644 --- a/Modules/_uuidmodule.c +++ b/Modules/_uuidmodule.c @@ -18,10 +18,16 @@ py_uuid_generate_time_safe(void) res = uuid_generate_time_safe(uuid); return Py_BuildValue("y#i", (const char *) uuid, sizeof(uuid), res); -#elif HAVE_UUID_CREATE +#elif defined(HAVE_UUID_CREATE) uint32_t status; uuid_create(&uuid, &status); +# if defined(HAVE_UUID_ENC_BE) + unsigned char buf[sizeof(uuid)]; + uuid_enc_be(buf, &uuid); + return Py_BuildValue("y#i", buf, sizeof(uuid), (int) status); +# else return Py_BuildValue("y#i", (const char *) &uuid, sizeof(uuid), (int) status); +# endif #else uuid_generate_time(uuid); return Py_BuildValue("y#O", (const char *) uuid, sizeof(uuid), Py_None); @@ -57,6 +63,7 @@ PyInit__uuid(void) } if (PyModule_AddIntConstant(mod, "has_uuid_generate_time_safe", has_uuid_generate_time_safe) < 0) { + Py_DECREF(mod); return NULL; } diff --git a/configure b/configure index f1f01df4a80e..b1cd944ac562 100755 --- a/configure +++ b/configure @@ -9625,6 +9625,40 @@ $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +# Little-endian FreeBSD, OpenBSD and NetBSD needs encoding into an octet +# stream in big-endian byte-order +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_enc_be" >&5 +$as_echo_n "checking for uuid_enc_be... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <uuid.h> +int +main () +{ + +#ifndef uuid_enc_be +uuid_t uuid; +unsigned char buf[sizeof(uuid)]; +uuid_enc_be(buf, &uuid); +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +$as_echo "#define HAVE_UUID_ENC_BE 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + # 'Real Time' functions on Solaris # posix4 on Solaris 2.6 # pthread (first!) on Linux diff --git a/configure.ac b/configure.ac index 253596964204..59489047fc24 100644 --- a/configure.ac +++ b/configure.ac @@ -2742,6 +2742,21 @@ void *x = uuid_create [AC_MSG_RESULT(no)] ) +# Little-endian FreeBSD, OpenBSD and NetBSD needs encoding into an octet +# stream in big-endian byte-order +AC_MSG_CHECKING(for uuid_enc_be) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <uuid.h>]], [[ +#ifndef uuid_enc_be +uuid_t uuid; +unsigned char buf[sizeof(uuid)]; +uuid_enc_be(buf, &uuid); +#endif +]])], + [AC_DEFINE(HAVE_UUID_ENC_BE, 1, Define if uuid_enc_be() exists.) + AC_MSG_RESULT(yes)], + [AC_MSG_RESULT(no)] +) + # 'Real Time' functions on Solaris # posix4 on Solaris 2.6 # pthread (first!) on Linux diff --git a/pyconfig.h.in b/pyconfig.h.in index a0efff9777d2..e561a7c07cca 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -1212,6 +1212,9 @@ /* Define if uuid_create() exists. */ #undef HAVE_UUID_CREATE +/* Define if uuid_enc_be() exists. */ +#undef HAVE_UUID_ENC_BE + /* Define if uuid_generate_time_safe() exists. */ #undef HAVE_UUID_GENERATE_TIME_SAFE From lp_benchmark_robot at intel.com Thu May 24 21:00:13 2018 From: lp_benchmark_robot at intel.com (lp_benchmark_robot at intel.com) Date: Thu, 24 May 2018 18:00:13 -0700 Subject: [Python-checkins] [65 flat] Results for Python (master branch) 2018-05-24 Message-ID: <ff003e82-9ee0-45ed-bded-b889f267bc28@orsmsx106.amr.corp.intel.com> Results for project python/master, build date: 2018-05-24 03:03:36-07:00. - commit: 03c0d2e - previous commit: 825aab9 - revision date: 2018-05-23 23:37:08-07:00 - environment: Broadwell-EP - cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores, stepping 1, LLC 55 MB - mem: 128 GB - os: Ubuntu 16.04.2 LTS - kernel: 4.4.0-62-generic x86_64 GNU/Linux Baseline results were generated using release v3.6.0, with hash 5c4568a from 2016-12-22 23:38:47+00:00. +-----+------------------------+--------+------------+------------+------------+ | | |relative|change since|change since|current rev | | | benchmark|std_dev*| last run | baseline |run with PGO| +-----+------------------------+--------+------------+------------+------------+ | :-| | 2to3| 0.660% | -0.224% | +9.322% | +6.730% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method| 1.118% | +0.284% | +23.834% | +14.230% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_slots| 1.356% | +0.307% | +25.690% | +11.789% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_unknown| 1.220% | +0.068% | +22.310% | +13.362% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_simple| 3.188% | +0.125% | +10.529% | +11.788% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chameleon| 1.643% | -0.021% | +12.725% | +10.664% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chaos| 0.775% | -0.405% | +8.369% | +10.779% | +-----+------------------------+--------+------------+------------+------------+ | :-| | crypto_pyaes| 0.594% | -0.006% | +0.090% | +8.776% | +-----+------------------------+--------+------------+------------+------------+ | :-| | deltablue| 3.917% | +0.109% | +11.975% | +17.203% | +-----+------------------------+--------+------------+------------+------------+ | :-| | django_template| 1.907% | -1.101% | +21.485% | +12.378% | +-----+------------------------+--------+------------+------------+------------+ | :-| | dulwich_log| 1.281% | -0.509% | +5.255% | +7.583% | +-----+------------------------+--------+------------+------------+------------+ | :-| | fannkuch| 0.441% | -0.067% | +7.189% | +5.562% | +-----+------------------------+--------+------------+------------+------------+ | :-| | float| 1.483% | -0.037% | +2.362% | +7.880% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_text| 1.058% | -0.105% | +14.539% | +9.960% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_xml| 1.215% | -0.531% | +11.126% | +9.795% | +-----+------------------------+--------+------------+------------+------------+ | :-| | go| 6.016% | -0.153% | +4.957% | +10.528% | +-----+------------------------+--------+------------+------------+------------+ | :-| | hexiom| 0.560% | -0.137% | +11.943% | +11.396% | +-----+------------------------+--------+------------+------------+------------+ | :-| | html5lib| 2.580% | -0.066% | +12.038% | +9.071% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_dumps| 1.405% | +0.425% | +4.036% | +8.627% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_loads| 0.616% | +1.114% | -2.968% | +15.815% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_format| 1.331% | -0.568% | +17.584% | +14.054% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_silent| 2.297% | +0.817% | +48.170% | +13.210% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_simple| 1.298% | -0.564% | +12.966% | +14.462% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mako| 0.931% | +0.067% | +16.761% | +15.026% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mdp| 6.178% | +1.727% | +1.919% | +16.508% | +-----+------------------------+--------+------------+------------+------------+ | :-| | meteor_contest| 0.646% | +0.020% | +4.761% | +6.200% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nbody| 1.531% | +0.577% | +0.369% | +1.981% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nqueens| 0.492% | +0.230% | +5.764% | +8.338% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pathlib| 1.152% | -0.416% | +1.864% | +8.854% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle| 1.334% | +0.633% | -0.213% | +20.287% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_dict| 0.478% | -0.058% | +7.480% | +15.241% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_list| 0.590% | -0.228% | +6.733% | +17.710% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_pure_python| 4.496% | +1.199% | +11.864% | +11.729% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pidigits| 0.178% | -0.018% | +0.245% | +10.413% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup| 0.120% | -0.104% | +19.053% | +4.994% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup_no_site| 0.085% | -0.051% | +6.106% | +5.000% | +-----+------------------------+--------+------------+------------+------------+ | :-| | raytrace| 1.233% | -0.029% | +9.965% | +13.345% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_compile| 5.253% | -0.732% | +3.821% | +11.018% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_dna| 0.229% | +0.018% | -2.009% | +12.322% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_effbot| 1.853% | -0.174% | -2.471% | +3.692% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_v8| 1.637% | +0.237% | +4.316% | +8.895% | +-----+------------------------+--------+------------+------------+------------+ | :-| | richards| 2.194% | +0.088% | +9.417% | +15.903% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_fft| 0.566% | +0.080% | -1.242% | +3.586% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_lu| 4.134% | +0.087% | +22.033% | +14.273% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_monte_carlo| 1.656% | -0.722% | +4.344% | +5.995% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sor| 1.235% | -0.548% | +15.109% | +9.290% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sparse_mat_mult| 1.255% | -0.281% | -3.229% | +2.318% | +-----+------------------------+--------+------------+------------+------------+ | :-| | spectral_norm| 0.748% | +0.212% | +4.487% | +5.740% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_declarative| 1.649% | +0.055% | +7.529% | +5.153% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_imperative| 4.508% | -0.914% | +7.424% | +4.378% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlite_synth| 3.196% | +0.177% | -0.071% | +9.757% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_expand| 2.987% | -0.039% | +17.983% | +5.679% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_integrate| 1.704% | -0.561% | +18.502% | +6.180% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_str| 4.405% | -0.405% | +19.054% | +6.887% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_sum| 6.011% | +0.538% | +16.365% | +9.626% | +-----+------------------------+--------+------------+------------+------------+ | :-| | telco| 3.666% | +0.354% | +20.336% | +8.561% | +-----+------------------------+--------+------------+------------+------------+ | :-| | tornado_http| 1.067% | -0.260% | +7.487% | +6.681% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpack_sequence| 0.969% | +0.155% | +2.824% | +0.103% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle| 8.641% | -1.592% | +6.310% | +23.564% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_list| 2.829% | -1.119% | -4.417% | +19.356% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_pure_python| 1.654% | +0.157% | +7.458% | +8.730% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_generate| 0.906% | -0.167% | +2.739% | +12.869% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_iterparse| 2.216% | -0.165% | +4.681% | +6.679% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_parse| 1.873% | +0.298% | -5.355% | +11.607% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_process| 1.106% | +0.459% | +5.115% | +11.533% | +-----+------------------------+--------+------------+------------+------------+ * Relative Standard Deviation (Standard Deviation/Average) If this is not displayed properly please visit our results page here: http://languagesperformance.intel.com/65-flat-results-for-python-master-branch-2018-05-24 Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. From webhook-mailer at python.org Fri May 25 00:34:04 2018 From: webhook-mailer at python.org (Ivan Levkivskyi) Date: Fri, 25 May 2018 04:34:04 -0000 Subject: [Python-checkins] Document typing.NoReturn (GH-7107) Message-ID: <mailman.58.1527222845.18020.python-checkins@python.org> https://github.com/python/cpython/commit/6e413f4327a68c4c7d62e0b6d0f9144be11dd6cd commit: 6e413f4327a68c4c7d62e0b6d0f9144be11dd6cd branch: master author: Ivan Levkivskyi <levkivskyi at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-24T21:33:55-07:00 summary: Document typing.NoReturn (GH-7107) files: M Doc/library/typing.rst diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index be6636eea08f..91d10e324cae 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -937,6 +937,18 @@ The module defines the following classes, functions and decorators: * Every type is compatible with :data:`Any`. * :data:`Any` is compatible with every type. +.. data:: NoReturn + + Special type indicating that a function never returns. + For example:: + + from typing import NoReturn + + def stop() -> NoReturn: + raise RuntimeError('no way') + + .. versionadded:: 3.6.5 + .. data:: Union Union type; ``Union[X, Y]`` means either X or Y. From webhook-mailer at python.org Fri May 25 00:51:18 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 25 May 2018 04:51:18 -0000 Subject: [Python-checkins] Document typing.NoReturn (GH-7107) Message-ID: <mailman.59.1527223879.18020.python-checkins@python.org> https://github.com/python/cpython/commit/82d727fce68577d9f44f9ecfaf20bd4581a66404 commit: 82d727fce68577d9f44f9ecfaf20bd4581a66404 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-24T21:51:14-07:00 summary: Document typing.NoReturn (GH-7107) (cherry picked from commit 6e413f4327a68c4c7d62e0b6d0f9144be11dd6cd) Co-authored-by: Ivan Levkivskyi <levkivskyi at gmail.com> files: M Doc/library/typing.rst diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index be6636eea08f..91d10e324cae 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -937,6 +937,18 @@ The module defines the following classes, functions and decorators: * Every type is compatible with :data:`Any`. * :data:`Any` is compatible with every type. +.. data:: NoReturn + + Special type indicating that a function never returns. + For example:: + + from typing import NoReturn + + def stop() -> NoReturn: + raise RuntimeError('no way') + + .. versionadded:: 3.6.5 + .. data:: Union Union type; ``Union[X, Y]`` means either X or Y. From webhook-mailer at python.org Fri May 25 00:56:27 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 25 May 2018 04:56:27 -0000 Subject: [Python-checkins] Document typing.NoReturn (GH-7107) Message-ID: <mailman.60.1527224188.18020.python-checkins@python.org> https://github.com/python/cpython/commit/36f066a9747afdbc2e9376db90ae8d66399521ff commit: 36f066a9747afdbc2e9376db90ae8d66399521ff branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-24T21:56:24-07:00 summary: Document typing.NoReturn (GH-7107) (cherry picked from commit 6e413f4327a68c4c7d62e0b6d0f9144be11dd6cd) Co-authored-by: Ivan Levkivskyi <levkivskyi at gmail.com> files: M Doc/library/typing.rst diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index 4a8f2f8e12e6..bd6f3a95fe62 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -938,6 +938,18 @@ The module defines the following classes, functions and decorators: * Every type is compatible with :data:`Any`. * :data:`Any` is compatible with every type. +.. data:: NoReturn + + Special type indicating that a function never returns. + For example:: + + from typing import NoReturn + + def stop() -> NoReturn: + raise RuntimeError('no way') + + .. versionadded:: 3.6.5 + .. data:: Union Union type; ``Union[X, Y]`` means either X or Y. From webhook-mailer at python.org Fri May 25 04:03:37 2018 From: webhook-mailer at python.org (Andrew Svetlov) Date: Fri, 25 May 2018 08:03:37 -0000 Subject: [Python-checkins] [3.6] bpo-26819: Prevent proactor double read on resume (GH-6921) (#7110) Message-ID: <mailman.61.1527235421.18020.python-checkins@python.org> https://github.com/python/cpython/commit/749afe81ec0a4b92ad6b89a67c82f2c04f79c5ac commit: 749afe81ec0a4b92ad6b89a67c82f2c04f79c5ac branch: 3.6 author: CtrlZvi <viz+github at flippedperspective.com> committer: Andrew Svetlov <andrew.svetlov at gmail.com> date: 2018-05-25T11:03:25+03:00 summary: [3.6] bpo-26819: Prevent proactor double read on resume (GH-6921) (#7110) The proactor event loop has a race condition when reading with pausing/resuming. `resume_reading()` unconditionally schedules the read function to read from the current future. If `resume_reading()` was called before the previously scheduled done callback fires, this results in two attempts to get the data from the most recent read and an assertion failure. This commit tracks whether or not `resume_reading` needs to reschedule the callback to restart the loop, preventing a second attempt to read the data.. (cherry picked from commit 4151061855b571bf8a7579daa7875b8e243057b9) Co-authored-by: CtrlZvi <viz+github at flippedperspective.com> files: A Misc/NEWS.d/next/Library/2018-05-16-05-24-43.bpo-26819.taxbVT.rst M Lib/asyncio/proactor_events.py M Lib/test/test_asyncio/test_proactor_events.py diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py index a81645d9c5d8..967a696961a6 100644 --- a/Lib/asyncio/proactor_events.py +++ b/Lib/asyncio/proactor_events.py @@ -156,6 +156,7 @@ def __init__(self, loop, sock, protocol, waiter=None, extra=None, server=None): super().__init__(loop, sock, protocol, waiter, extra, server) self._paused = False + self._reschedule_on_resume = False self._loop.call_soon(self._loop_reading) def pause_reading(self): @@ -173,12 +174,15 @@ def resume_reading(self): self._paused = False if self._closing: return - self._loop.call_soon(self._loop_reading, self._read_fut) + if self._reschedule_on_resume: + self._loop.call_soon(self._loop_reading, self._read_fut) + self._reschedule_on_resume = False if self._loop.get_debug(): logger.debug("%r resumes reading", self) def _loop_reading(self, fut=None): if self._paused: + self._reschedule_on_resume = True return data = None diff --git a/Lib/test/test_asyncio/test_proactor_events.py b/Lib/test/test_asyncio/test_proactor_events.py index d76da661ab92..edf0461957f8 100644 --- a/Lib/test/test_asyncio/test_proactor_events.py +++ b/Lib/test/test_asyncio/test_proactor_events.py @@ -330,7 +330,7 @@ def test_write_eof_duplex_pipe(self): def test_pause_resume_reading(self): tr = self.socket_transport() futures = [] - for msg in [b'data1', b'data2', b'data3', b'data4', b'']: + for msg in [b'data1', b'data2', b'data3', b'data4', b'data5', b'']: f = asyncio.Future(loop=self.loop) f.set_result(msg) futures.append(f) @@ -352,6 +352,13 @@ def test_pause_resume_reading(self): self.protocol.data_received.assert_called_with(b'data3') self.loop._run_once() self.protocol.data_received.assert_called_with(b'data4') + + tr.pause_reading() + tr.resume_reading() + self.loop.call_exception_handler = mock.Mock() + self.loop._run_once() + self.loop.call_exception_handler.assert_not_called() + self.protocol.data_received.assert_called_with(b'data5') tr.close() diff --git a/Misc/NEWS.d/next/Library/2018-05-16-05-24-43.bpo-26819.taxbVT.rst b/Misc/NEWS.d/next/Library/2018-05-16-05-24-43.bpo-26819.taxbVT.rst new file mode 100644 index 000000000000..d407a5800318 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-16-05-24-43.bpo-26819.taxbVT.rst @@ -0,0 +1,2 @@ +Fix race condition with `ReadTransport.resume_reading` in Windows proactor +event loop. From solipsis at pitrou.net Fri May 25 05:12:06 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 25 May 2018 09:12:06 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=5 Message-ID: <20180525091206.1.86F0B7F5218CD938@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_collections leaked [0, -7, 8] memory blocks, sum=1 test_functools leaked [0, 3, 1] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflog6YpLV8', '--timeout', '7200'] From webhook-mailer at python.org Fri May 25 06:16:54 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Fri, 25 May 2018 10:16:54 -0000 Subject: [Python-checkins] bpo-33012: Add -Wno-cast-function-type for gcc 8. (GH-6757) Message-ID: <mailman.62.1527243418.18020.python-checkins@python.org> https://github.com/python/cpython/commit/ef91ddeae79497fac25545dd68ee55a5a3c60e8d commit: ef91ddeae79497fac25545dd68ee55a5a3c60e8d branch: 3.7 author: Serhiy Storchaka <storchaka at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-25T13:16:51+03:00 summary: bpo-33012: Add -Wno-cast-function-type for gcc 8. (GH-6757) files: A Misc/NEWS.d/next/Build/2018-05-10-21-10-01.bpo-33012.5Zfjac.rst M configure M configure.ac diff --git a/Misc/NEWS.d/next/Build/2018-05-10-21-10-01.bpo-33012.5Zfjac.rst b/Misc/NEWS.d/next/Build/2018-05-10-21-10-01.bpo-33012.5Zfjac.rst new file mode 100644 index 000000000000..ecaa5c6117a0 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2018-05-10-21-10-01.bpo-33012.5Zfjac.rst @@ -0,0 +1,2 @@ +Add ``-Wno-cast-function-type`` for gcc 8 for silencing warnings about +function casts like casting to PyCFunction in method definition lists. diff --git a/configure b/configure index b1cd944ac562..b398ef8b0d57 100755 --- a/configure +++ b/configure @@ -7052,6 +7052,47 @@ $as_echo "$ac_cv_disable_missing_field_initializers" >&6; } CFLAGS_NODIST="$CFLAGS_NODIST -Wno-missing-field-initializers" fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can turn off $CC invalid function cast warning" >&5 +$as_echo_n "checking if we can turn off $CC invalid function cast warning... " >&6; } + ac_save_cc="$CC" + CC="$CC -Wcast-function-type -Werror" + if ${ac_cv_disable_cast_function_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ + + ; + return 0; +} + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + ac_cv_disable_cast_function_type=yes + +else + + ac_cv_disable_cast_function_type=no + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + + CC="$ac_save_cc" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_disable_cast_function_type" >&5 +$as_echo "$ac_cv_disable_cast_function_type" >&6; } + + if test $ac_cv_disable_cast_function_type = yes + then + CFLAGS_NODIST="$CFLAGS_NODIST -Wno-cast-function-type" + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can turn on $CC mixed sign comparison warning" >&5 $as_echo_n "checking if we can turn on $CC mixed sign comparison warning... " >&6; } ac_save_cc="$CC" diff --git a/configure.ac b/configure.ac index 59489047fc24..11fc7e545dec 100644 --- a/configure.ac +++ b/configure.ac @@ -1660,6 +1660,26 @@ yes) CFLAGS_NODIST="$CFLAGS_NODIST -Wno-missing-field-initializers" fi + AC_MSG_CHECKING(if we can turn off $CC invalid function cast warning) + ac_save_cc="$CC" + CC="$CC -Wcast-function-type -Werror" + AC_CACHE_VAL(ac_cv_disable_cast_function_type, + AC_COMPILE_IFELSE( + [ + AC_LANG_PROGRAM([[]], [[]]) + ],[ + ac_cv_disable_cast_function_type=yes + ],[ + ac_cv_disable_cast_function_type=no + ])) + CC="$ac_save_cc" + AC_MSG_RESULT($ac_cv_disable_cast_function_type) + + if test $ac_cv_disable_cast_function_type = yes + then + CFLAGS_NODIST="$CFLAGS_NODIST -Wno-cast-function-type" + fi + AC_MSG_CHECKING(if we can turn on $CC mixed sign comparison warning) ac_save_cc="$CC" CC="$CC -Wsign-compare" From webhook-mailer at python.org Fri May 25 07:03:05 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 25 May 2018 11:03:05 -0000 Subject: [Python-checkins] bpo-33012: Add -Wno-cast-function-type for gcc 8. (GH-6757) Message-ID: <mailman.63.1527246189.18020.python-checkins@python.org> https://github.com/python/cpython/commit/20b797dafa149afcdd7b64e489eb8ea1386d8eb4 commit: 20b797dafa149afcdd7b64e489eb8ea1386d8eb4 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-25T04:02:54-07:00 summary: bpo-33012: Add -Wno-cast-function-type for gcc 8. (GH-6757) (cherry picked from commit ef91ddeae79497fac25545dd68ee55a5a3c60e8d) Co-authored-by: Serhiy Storchaka <storchaka at gmail.com> files: A Misc/NEWS.d/next/Build/2018-05-10-21-10-01.bpo-33012.5Zfjac.rst M configure M configure.ac diff --git a/Misc/NEWS.d/next/Build/2018-05-10-21-10-01.bpo-33012.5Zfjac.rst b/Misc/NEWS.d/next/Build/2018-05-10-21-10-01.bpo-33012.5Zfjac.rst new file mode 100644 index 000000000000..ecaa5c6117a0 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2018-05-10-21-10-01.bpo-33012.5Zfjac.rst @@ -0,0 +1,2 @@ +Add ``-Wno-cast-function-type`` for gcc 8 for silencing warnings about +function casts like casting to PyCFunction in method definition lists. diff --git a/configure b/configure index a707743b4966..f1f2daa3be99 100755 --- a/configure +++ b/configure @@ -7186,6 +7186,47 @@ $as_echo "$ac_cv_disable_missing_field_initializers" >&6; } CFLAGS_NODIST="$CFLAGS_NODIST -Wno-missing-field-initializers" fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can turn off $CC invalid function cast warning" >&5 +$as_echo_n "checking if we can turn off $CC invalid function cast warning... " >&6; } + ac_save_cc="$CC" + CC="$CC -Wcast-function-type -Werror" + if ${ac_cv_disable_cast_function_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ + + ; + return 0; +} + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + ac_cv_disable_cast_function_type=yes + +else + + ac_cv_disable_cast_function_type=no + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + + CC="$ac_save_cc" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_disable_cast_function_type" >&5 +$as_echo "$ac_cv_disable_cast_function_type" >&6; } + + if test $ac_cv_disable_cast_function_type = yes + then + CFLAGS_NODIST="$CFLAGS_NODIST -Wno-cast-function-type" + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can turn on $CC mixed sign comparison warning" >&5 $as_echo_n "checking if we can turn on $CC mixed sign comparison warning... " >&6; } ac_save_cc="$CC" diff --git a/configure.ac b/configure.ac index 0ec09369a9a0..2e6d8500831a 100644 --- a/configure.ac +++ b/configure.ac @@ -1666,6 +1666,26 @@ yes) CFLAGS_NODIST="$CFLAGS_NODIST -Wno-missing-field-initializers" fi + AC_MSG_CHECKING(if we can turn off $CC invalid function cast warning) + ac_save_cc="$CC" + CC="$CC -Wcast-function-type -Werror" + AC_CACHE_VAL(ac_cv_disable_cast_function_type, + AC_COMPILE_IFELSE( + [ + AC_LANG_PROGRAM([[]], [[]]) + ],[ + ac_cv_disable_cast_function_type=yes + ],[ + ac_cv_disable_cast_function_type=no + ])) + CC="$ac_save_cc" + AC_MSG_RESULT($ac_cv_disable_cast_function_type) + + if test $ac_cv_disable_cast_function_type = yes + then + CFLAGS_NODIST="$CFLAGS_NODIST -Wno-cast-function-type" + fi + AC_MSG_CHECKING(if we can turn on $CC mixed sign comparison warning) ac_save_cc="$CC" CC="$CC -Wsign-compare" From webhook-mailer at python.org Fri May 25 11:22:06 2018 From: webhook-mailer at python.org (Victor Stinner) Date: Fri, 25 May 2018 15:22:06 -0000 Subject: [Python-checkins] test.regrtest: flush stdout when display progress (#7105) Message-ID: <mailman.64.1527261728.18020.python-checkins@python.org> https://github.com/python/cpython/commit/4f0bc7f7ab6ec23594b0efe11d082f78ae42abed commit: 4f0bc7f7ab6ec23594b0efe11d082f78ae42abed branch: master author: Victor Stinner <vstinner at redhat.com> committer: GitHub <noreply at github.com> date: 2018-05-25T17:21:55+02:00 summary: test.regrtest: flush stdout when display progress (#7105) runtest_mp.py: call print() with flush=True. files: M Lib/test/libregrtest/runtest_mp.py diff --git a/Lib/test/libregrtest/runtest_mp.py b/Lib/test/libregrtest/runtest_mp.py index 31b830d75f4f..598754f279d8 100644 --- a/Lib/test/libregrtest/runtest_mp.py +++ b/Lib/test/libregrtest/runtest_mp.py @@ -183,7 +183,7 @@ def get_running(workers): except queue.Empty: running = get_running(workers) if running and not regrtest.ns.pgo: - print('running: %s' % ', '.join(running)) + print('running: %s' % ', '.join(running), flush=True) continue test, stdout, stderr, result = item @@ -235,6 +235,6 @@ def get_running(workers): line = "Waiting for %s (%s tests)" % (', '.join(running), len(running)) if dt >= WAIT_PROGRESS: line = "%s since %.0f sec" % (line, dt) - print(line) + print(line, flush=True) for worker in workers: worker.join(WAIT_PROGRESS) From webhook-mailer at python.org Fri May 25 12:46:43 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 25 May 2018 16:46:43 -0000 Subject: [Python-checkins] test.regrtest: flush stdout when display progress (GH-7105) Message-ID: <mailman.65.1527266804.18020.python-checkins@python.org> https://github.com/python/cpython/commit/af1d007bdb3d74cf107d1ad569f4d344f8c57fb8 commit: af1d007bdb3d74cf107d1ad569f4d344f8c57fb8 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-25T09:46:33-07:00 summary: test.regrtest: flush stdout when display progress (GH-7105) runtest_mp.py: call print() with flush=True. (cherry picked from commit 4f0bc7f7ab6ec23594b0efe11d082f78ae42abed) Co-authored-by: Victor Stinner <vstinner at redhat.com> files: M Lib/test/libregrtest/runtest_mp.py diff --git a/Lib/test/libregrtest/runtest_mp.py b/Lib/test/libregrtest/runtest_mp.py index 31b830d75f4f..598754f279d8 100644 --- a/Lib/test/libregrtest/runtest_mp.py +++ b/Lib/test/libregrtest/runtest_mp.py @@ -183,7 +183,7 @@ def get_running(workers): except queue.Empty: running = get_running(workers) if running and not regrtest.ns.pgo: - print('running: %s' % ', '.join(running)) + print('running: %s' % ', '.join(running), flush=True) continue test, stdout, stderr, result = item @@ -235,6 +235,6 @@ def get_running(workers): line = "Waiting for %s (%s tests)" % (', '.join(running), len(running)) if dt >= WAIT_PROGRESS: line = "%s since %.0f sec" % (line, dt) - print(line) + print(line, flush=True) for worker in workers: worker.join(WAIT_PROGRESS) From webhook-mailer at python.org Fri May 25 13:08:31 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 25 May 2018 17:08:31 -0000 Subject: [Python-checkins] test.regrtest: flush stdout when display progress (GH-7105) Message-ID: <mailman.66.1527268112.18020.python-checkins@python.org> https://github.com/python/cpython/commit/ecd0bb2693bfead04df543827cefc305bddd1ea7 commit: ecd0bb2693bfead04df543827cefc305bddd1ea7 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-25T10:08:23-07:00 summary: test.regrtest: flush stdout when display progress (GH-7105) runtest_mp.py: call print() with flush=True. (cherry picked from commit 4f0bc7f7ab6ec23594b0efe11d082f78ae42abed) Co-authored-by: Victor Stinner <vstinner at redhat.com> files: M Lib/test/libregrtest/runtest_mp.py diff --git a/Lib/test/libregrtest/runtest_mp.py b/Lib/test/libregrtest/runtest_mp.py index 779ff01a649c..899c57979f85 100644 --- a/Lib/test/libregrtest/runtest_mp.py +++ b/Lib/test/libregrtest/runtest_mp.py @@ -187,7 +187,7 @@ def get_running(workers): except queue.Empty: running = get_running(workers) if running and not regrtest.ns.pgo: - print('running: %s' % ', '.join(running)) + print('running: %s' % ', '.join(running), flush=True) continue test, stdout, stderr, result = item @@ -239,6 +239,6 @@ def get_running(workers): line = "Waiting for %s (%s tests)" % (', '.join(running), len(running)) if dt >= WAIT_PROGRESS: line = "%s since %.0f sec" % (line, dt) - print(line) + print(line, flush=True) for worker in workers: worker.join(WAIT_PROGRESS) From webhook-mailer at python.org Fri May 25 14:38:12 2018 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Fri, 25 May 2018 18:38:12 -0000 Subject: [Python-checkins] [2.7] bpo-33595: Fix lambda parameters being refered as arguments (GH-7037) (GH-7122) Message-ID: <mailman.67.1527273493.18020.python-checkins@python.org> https://github.com/python/cpython/commit/804fcf66559992db9d23695e501c502ab20b7712 commit: 804fcf66559992db9d23695e501c502ab20b7712 branch: 2.7 author: Terry Jan Reedy <tjreedy at udel.edu> committer: GitHub <noreply at github.com> date: 2018-05-25T14:38:09-04:00 summary: [2.7] bpo-33595: Fix lambda parameters being refered as arguments (GH-7037) (GH-7122) (cherry picked from commit 268cc7c) Co-authored-by: Andr?s Delfino adelfino at gmail.com files: M Doc/glossary.rst M Doc/reference/expressions.rst diff --git a/Doc/glossary.rst b/Doc/glossary.rst index feb40a88bbed..cacf3f6c24ac 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -457,7 +457,7 @@ Glossary lambda An anonymous inline function consisting of a single :term:`expression` which is evaluated when the function is called. The syntax to create - a lambda function is ``lambda [arguments]: expression`` + a lambda function is ``lambda [parameters]: expression`` LBYL Look before you leap. This coding style explicitly tests for diff --git a/Doc/reference/expressions.rst b/Doc/reference/expressions.rst index 8556fa810f6c..7fbfae747f6f 100644 --- a/Doc/reference/expressions.rst +++ b/Doc/reference/expressions.rst @@ -1390,10 +1390,10 @@ Lambdas Lambda expressions (sometimes called lambda forms) have the same syntactic position as expressions. They are a shorthand to create anonymous functions; the expression -``lambda arguments: expression`` yields a function object. The unnamed object +``lambda parameters: expression`` yields a function object. The unnamed object behaves like a function object defined with :: - def name(arguments): + def <lambda>(parameters): return expression See section :ref:`function` for the syntax of parameter lists. Note that From lp_benchmark_robot at intel.com Fri May 25 20:21:46 2018 From: lp_benchmark_robot at intel.com (lp_benchmark_robot at intel.com) Date: Fri, 25 May 2018 17:21:46 -0700 Subject: [Python-checkins] [65 flat] Results for Python (master branch) 2018-05-25 Message-ID: <080dd38b-84ec-4f54-9c4f-5ca7cf16bd81@orsmsx101.amr.corp.intel.com> Results for project python/master, build date: 2018-05-25 03:03:37-07:00. - commit: 6e413f4 - previous commit: 03c0d2e - revision date: 2018-05-24 21:33:55-07:00 - environment: Broadwell-EP - cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores, stepping 1, LLC 55 MB - mem: 128 GB - os: Ubuntu 16.04.2 LTS - kernel: 4.4.0-62-generic x86_64 GNU/Linux Baseline results were generated using release v3.6.0, with hash 5c4568a from 2016-12-22 23:38:47+00:00. +-----+------------------------+--------+------------+------------+------------+ | | |relative|change since|change since|current rev | | | benchmark|std_dev*| last run | baseline |run with PGO| +-----+------------------------+--------+------------+------------+------------+ | :-| | 2to3| 0.722% | -0.276% | +9.072% | +7.155% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method| 1.444% | -0.116% | +23.745% | +9.814% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_slots| 1.361% | -0.331% | +25.444% | +7.971% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_unknown| 0.953% | +0.060% | +22.357% | +9.745% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_simple| 1.620% | +0.735% | +11.187% | +12.654% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chameleon| 1.869% | -0.612% | +12.190% | +9.710% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chaos| 0.631% | +0.166% | +8.521% | +10.029% | +-----+------------------------+--------+------------+------------+------------+ | :-| | crypto_pyaes| 0.448% | -0.549% | -0.459% | +8.512% | +-----+------------------------+--------+------------+------------+------------+ | :-| | deltablue| 3.469% | +0.341% | +12.275% | +15.316% | +-----+------------------------+--------+------------+------------+------------+ | :-| | django_template| 1.283% | +1.139% | +22.380% | +11.124% | +-----+------------------------+--------+------------+------------+------------+ | :-| | dulwich_log| 1.148% | -0.071% | +5.188% | +7.126% | +-----+------------------------+--------+------------+------------+------------+ | :-| | fannkuch| 0.228% | -1.107% | +6.162% | +4.675% | +-----+------------------------+--------+------------+------------+------------+ | :-| | float| 1.347% | -0.276% | +2.092% | +7.072% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_text| 1.188% | -0.177% | +14.387% | +9.318% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_xml| 1.631% | +0.568% | +11.631% | +9.378% | +-----+------------------------+--------+------------+------------+------------+ | :-| | go| 5.849% | +0.279% | +5.222% | +11.556% | +-----+------------------------+--------+------------+------------+------------+ | :-| | hexiom| 0.616% | +0.031% | +11.971% | +11.508% | +-----+------------------------+--------+------------+------------+------------+ | :-| | html5lib| 3.078% | -0.500% | +11.598% | +10.356% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_dumps| 1.565% | -0.429% | +3.624% | +7.319% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_loads| 4.934% | -1.197% | -4.200% | +14.530% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_format| 1.519% | -0.448% | +17.215% | +14.489% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_silent| 2.565% | -0.382% | +47.971% | +11.026% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_simple| 1.239% | -0.978% | +12.115% | +14.587% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mako| 0.518% | -0.127% | +16.655% | +14.314% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mdp| 6.579% | -0.598% | +1.332% | +17.507% | +-----+------------------------+--------+------------+------------+------------+ | :-| | meteor_contest| 0.615% | -0.155% | +4.614% | +6.055% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nbody| 1.312% | -0.885% | -0.513% | -0.079% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nqueens| 0.459% | -0.418% | +5.370% | +8.002% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pathlib| 1.697% | -0.831% | +1.049% | +10.201% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle| 1.950% | -0.733% | -0.947% | +22.114% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_dict| 0.378% | +0.085% | +7.559% | +16.517% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_list| 0.644% | -0.037% | +6.698% | +17.028% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_pure_python| 4.266% | -0.003% | +11.861% | +10.919% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pidigits| 0.336% | -0.073% | +0.172% | +10.095% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup| 0.122% | -0.022% | +19.035% | +5.363% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup_no_site| 0.091% | -0.037% | +6.071% | +5.525% | +-----+------------------------+--------+------------+------------+------------+ | :-| | raytrace| 1.041% | +0.654% | +10.554% | +12.972% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_compile| 5.710% | -0.109% | +3.716% | +13.405% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_dna| 0.205% | -0.054% | -2.064% | +12.347% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_effbot| 3.456% | -4.325% | -6.903% | +8.310% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_v8| 1.370% | -0.294% | +4.035% | +8.166% | +-----+------------------------+--------+------------+------------+------------+ | :-| | richards| 2.242% | -0.165% | +9.267% | +14.333% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_fft| 0.997% | -0.370% | -1.617% | +3.758% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_lu| 3.562% | +0.500% | +22.423% | +13.152% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_monte_carlo| 1.814% | +0.798% | +5.107% | +4.341% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sor| 0.885% | -0.081% | +15.040% | +8.165% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sparse_mat_mult| 0.656% | +0.082% | -3.144% | -0.685% | +-----+------------------------+--------+------------+------------+------------+ | :-| | spectral_norm| 0.568% | +0.195% | +4.673% | +3.640% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_declarative| 1.808% | -0.003% | +7.526% | +6.549% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_imperative| 4.086% | +0.071% | +7.489% | +5.514% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlite_synth| 2.689% | +0.372% | +0.301% | +7.837% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_expand| 3.225% | -0.151% | +17.859% | +8.033% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_integrate| 1.924% | +0.270% | +18.722% | +6.620% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_str| 4.119% | +0.765% | +19.674% | +8.531% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_sum| 6.300% | -0.146% | +16.243% | +12.085% | +-----+------------------------+--------+------------+------------+------------+ | :-| | telco| 4.670% | -0.471% | +19.961% | +9.936% | +-----+------------------------+--------+------------+------------+------------+ | :-| | tornado_http| 1.029% | +0.213% | +7.683% | +5.313% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpack_sequence| 1.037% | -0.412% | +2.423% | +2.572% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle| 8.685% | -0.218% | +6.106% | +23.127% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_list| 1.228% | +1.420% | -2.934% | +14.867% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_pure_python| 1.526% | -0.262% | +7.216% | +7.722% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_generate| 1.085% | -0.226% | +2.519% | +12.411% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_iterparse| 1.668% | -0.431% | +4.270% | +7.283% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_parse| 1.502% | +0.043% | -5.309% | +10.856% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_process| 0.999% | -0.419% | +4.717% | +11.489% | +-----+------------------------+--------+------------+------------+------------+ * Relative Standard Deviation (Standard Deviation/Average) If this is not displayed properly please visit our results page here: http://languagesperformance.intel.com/65-flat-results-for-python-master-branch-2018-05-25 Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. From webhook-mailer at python.org Sat May 26 03:52:08 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sat, 26 May 2018 07:52:08 -0000 Subject: [Python-checkins] bpo-33644: Fix signatures of tp_finalize handlers in testing code. (GH-7111) Message-ID: <mailman.69.1527321132.18020.python-checkins@python.org> https://github.com/python/cpython/commit/19de8b3dd742fb53681478ad4fff57ed7c37a953 commit: 19de8b3dd742fb53681478ad4fff57ed7c37a953 branch: master author: Serhiy Storchaka <storchaka at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-26T10:51:58+03:00 summary: bpo-33644: Fix signatures of tp_finalize handlers in testing code. (GH-7111) files: M Modules/_testmultiphase.c M Modules/xxlimited.c diff --git a/Modules/_testmultiphase.c b/Modules/_testmultiphase.c index 8090a485f4a9..68404f2c6cdb 100644 --- a/Modules/_testmultiphase.c +++ b/Modules/_testmultiphase.c @@ -23,11 +23,10 @@ Example_traverse(ExampleObject *self, visitproc visit, void *arg) return 0; } -static int +static void Example_finalize(ExampleObject *self) { Py_CLEAR(self->x_attr); - return 0; } static PyObject * diff --git a/Modules/xxlimited.c b/Modules/xxlimited.c index 5041ac8284a3..5586989d039c 100644 --- a/Modules/xxlimited.c +++ b/Modules/xxlimited.c @@ -47,11 +47,10 @@ Xxo_traverse(XxoObject *self, visitproc visit, void *arg) return 0; } -static int +static void Xxo_finalize(XxoObject *self) { Py_CLEAR(self->x_attr); - return 0; } static PyObject * From webhook-mailer at python.org Sat May 26 04:33:33 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 26 May 2018 08:33:33 -0000 Subject: [Python-checkins] bpo-33644: Fix signatures of tp_finalize handlers in testing code. (GH-7111) Message-ID: <mailman.70.1527323616.18020.python-checkins@python.org> https://github.com/python/cpython/commit/14d289be60a2ad4cb65990a63ed2e75e9a8cb3ec commit: 14d289be60a2ad4cb65990a63ed2e75e9a8cb3ec branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-26T01:33:23-07:00 summary: bpo-33644: Fix signatures of tp_finalize handlers in testing code. (GH-7111) (cherry picked from commit 19de8b3dd742fb53681478ad4fff57ed7c37a953) Co-authored-by: Serhiy Storchaka <storchaka at gmail.com> files: M Modules/_testmultiphase.c M Modules/xxlimited.c diff --git a/Modules/_testmultiphase.c b/Modules/_testmultiphase.c index 8090a485f4a9..68404f2c6cdb 100644 --- a/Modules/_testmultiphase.c +++ b/Modules/_testmultiphase.c @@ -23,11 +23,10 @@ Example_traverse(ExampleObject *self, visitproc visit, void *arg) return 0; } -static int +static void Example_finalize(ExampleObject *self) { Py_CLEAR(self->x_attr); - return 0; } static PyObject * diff --git a/Modules/xxlimited.c b/Modules/xxlimited.c index 5041ac8284a3..5586989d039c 100644 --- a/Modules/xxlimited.c +++ b/Modules/xxlimited.c @@ -47,11 +47,10 @@ Xxo_traverse(XxoObject *self, visitproc visit, void *arg) return 0; } -static int +static void Xxo_finalize(XxoObject *self) { Py_CLEAR(self->x_attr); - return 0; } static PyObject * From solipsis at pitrou.net Sat May 26 05:10:00 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 26 May 2018 09:10:00 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=10 Message-ID: <20180526091000.1.9B8E1277B84E6833@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_collections leaked [7, -7, 8] memory blocks, sum=8 test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_forkserver leaked [-2, 2, -2] memory blocks, sum=-2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogYZxF7D', '--timeout', '7200'] From webhook-mailer at python.org Sat May 26 06:17:11 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sat, 26 May 2018 10:17:11 -0000 Subject: [Python-checkins] bpo-33644: Fix signatures of tp_finalize handlers in testing code. (GH-7111) (GH-7125) Message-ID: <mailman.71.1527329834.18020.python-checkins@python.org> https://github.com/python/cpython/commit/9ba3be4718bdf82e20280980807e054004a9bade commit: 9ba3be4718bdf82e20280980807e054004a9bade branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Serhiy Storchaka <storchaka at gmail.com> date: 2018-05-26T13:17:08+03:00 summary: bpo-33644: Fix signatures of tp_finalize handlers in testing code. (GH-7111) (GH-7125) (cherry picked from commit 19de8b3dd742fb53681478ad4fff57ed7c37a953) Co-authored-by: Serhiy Storchaka <storchaka at gmail.com> files: M Modules/_testmultiphase.c M Modules/xxlimited.c diff --git a/Modules/_testmultiphase.c b/Modules/_testmultiphase.c index 8891d8d21dfc..43f8034e8e9b 100644 --- a/Modules/_testmultiphase.c +++ b/Modules/_testmultiphase.c @@ -23,11 +23,10 @@ Example_traverse(ExampleObject *self, visitproc visit, void *arg) return 0; } -static int +static void Example_finalize(ExampleObject *self) { Py_CLEAR(self->x_attr); - return 0; } static PyObject * diff --git a/Modules/xxlimited.c b/Modules/xxlimited.c index 5041ac8284a3..5586989d039c 100644 --- a/Modules/xxlimited.c +++ b/Modules/xxlimited.c @@ -47,11 +47,10 @@ Xxo_traverse(XxoObject *self, visitproc visit, void *arg) return 0; } -static int +static void Xxo_finalize(XxoObject *self) { Py_CLEAR(self->x_attr); - return 0; } static PyObject * From webhook-mailer at python.org Sat May 26 08:43:43 2018 From: webhook-mailer at python.org (Ivan Levkivskyi) Date: Sat, 26 May 2018 12:43:43 -0000 Subject: [Python-checkins] bpo-32769: A new take on annotations/type hinting glossary entries (GH-6829) Message-ID: <mailman.72.1527338629.18020.python-checkins@python.org> https://github.com/python/cpython/commit/6e33f810c9e3a549c9379f24cf1d1752c29195f0 commit: 6e33f810c9e3a549c9379f24cf1d1752c29195f0 branch: master author: Andr?s Delfino <adelfino at gmail.com> committer: Ivan Levkivskyi <levkivskyi at gmail.com> date: 2018-05-26T05:43:39-07:00 summary: bpo-32769: A new take on annotations/type hinting glossary entries (GH-6829) files: M Doc/glossary.rst diff --git a/Doc/glossary.rst b/Doc/glossary.rst index 194788824792..bf98934ac66c 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -40,16 +40,18 @@ Glossary ABCs with the :mod:`abc` module. annotation - A metadata value associated with a global variable, a class attribute or a - function or method parameter or return value, that stores a - :term:`type hint`. + A label associated with a variable, a class + attribute or a function parameter or return value, + used by convention as a :term:`type hint`. - Annotations are stored in the :attr:`__annotations__` special attribute - of a module (when annotating a global variable), class (when annotating - one of its attributes) or function or method (when annotating a parameter or a - return value) and can be accessed using :func:`typing.get_type_hints`. + Annotations of local variables cannot be accesed at runtime, but + annotations of global variables, class attributes, and functions + are stored in the :attr:`__annotations__` + special attribute of modules, classes, and functions, + respectively. - See :pep:`484` and :pep:`526` which describe this functionality. + See :term:`variable annotation`, :term:`function annotation`, :pep:`484` + and :pep:`526`, which describe this functionality. argument A value passed to a :term:`function` (or :term:`method`) when calling the @@ -191,11 +193,6 @@ Glossary A variable defined in a class and intended to be modified only at class level (i.e., not in an instance of the class). - Class variables can be specified as such through - :term:`type hints <type hint>`. - - See :pep:`526` which describes class variable annotations. - coercion The implicit conversion of an instance of one type to another during an operation which involves two arguments of the same type. For example, @@ -388,19 +385,20 @@ Glossary and the :ref:`function` section. function annotation - An :term:`annotation` of a function, or a method. + An :term:`annotation` of a function parameter or return value. - For example, this function has its parameters annotated as taking - :class:`int` arguments and its return value annotated as being an - :class:`int` as well:: + Function annotations are usually used for + :term:`type hints <type hint>`: for example this function is expected to take two + :class:`int` arguments and is also expected to have an :class:`int` + return value:: def sum_two_numbers(a: int, b: int) -> int: return a + b - Its syntax is explained in section :ref:`function`. + Function annotation syntax is explained in section :ref:`function`. - See also the :term:`variable annotation` glossary entry, and :pep:`484`, - which describes this functionality. + See :term:`variable annotation` and :pep:`484`, + which describe this functionality. __future__ A pseudo-module which programmers can use to enable new language features @@ -1048,17 +1046,42 @@ Glossary :attr:`~instance.__class__` attribute or can be retrieved with ``type(obj)``. + type alias + A synonym for a type, created by assigning the type to an identifier. + + Type aliases are useful for simplifying :term:`type hints <type hint>`. + For example:: + + from typing import List, Tuple + + def remove_gray_shades( + colors: List[Tuple[int, int, int]]) -> List[Tuple[int, int, int]]: + pass + + could be made more readable like this:: + + from typing import List, Tuple + + Color = Tuple[int, int, int] + + def remove_gray_shades(colors: List[Color]) -> List[Color]: + pass + + See :mod:`typing` and :pep:`484`, which describe this functionality. + type hint - A specification about the expected type for a global variable, class - variable, function or method parameter or return value. + An :term:`annotation` that specifies the expected type for a variable, a class + attribute, or a function parameter or return value. - While type hints are optional and are not enforced by Python when used, - they are useful for static type analysis tools, and aid IDEs on code + Type hints are optional and are not enforced by Python but + they are useful to static type analysis tools, and aid IDEs with code completion and refactoring. - Type hints are stored in :term:`annotations <annotation>`. + Type hints of global variables, class attributes, and functions, + but not local variables, can be accessed using + :func:`typing.get_type_hints`. - See also :pep:`483` which describe this functionality. + See :mod:`typing` and :pep:`484`, which describe this functionality. universal newlines A manner of interpreting text streams in which all of the following are @@ -1068,21 +1091,23 @@ Glossary :func:`bytes.splitlines` for an additional use. variable annotation - An :term:`annotation` of a global variable, or a class attribute. + An :term:`annotation` of a variable or a class attribute. - For example, this variable is annotated as taking :class:`int` values:: + When annotating a variable or a class attribute, assignment is optional:: - count: int = 0 + class C: + field: 'annotation' - When annotating variables, assignment is optional:: + Variable annotations are usually used for + :term:`type hints <type hint>`: for example this variable is expected to take + :class:`int` values:: - class C: - field: int + count: int = 0 - Its syntax is explained in section :ref:`annassign`. + Variable annotation syntax is explained in section :ref:`annassign`. - See also the :term:`function annotation` glossary entry, and :pep:`484` - and :pep:`526` which describe this functionality. + See :term:`function annotation`, :pep:`484` + and :pep:`526`, which describe this functionality. virtual environment A cooperatively isolated runtime environment that allows Python users From webhook-mailer at python.org Sat May 26 13:17:37 2018 From: webhook-mailer at python.org (Guido van Rossum) Date: Sat, 26 May 2018 17:17:37 -0000 Subject: [Python-checkins] [3.7] bpo-32769: A new take on annotations/type hinting glossary entries (GH-6829) (#7127) Message-ID: <mailman.73.1527355057.18020.python-checkins@python.org> https://github.com/python/cpython/commit/e69657df244135a232117f692640e0568b04e999 commit: e69657df244135a232117f692640e0568b04e999 branch: 3.7 author: Andr?s Delfino <adelfino at gmail.com> committer: Guido van Rossum <guido at python.org> date: 2018-05-26T10:17:33-07:00 summary: [3.7] bpo-32769: A new take on annotations/type hinting glossary entries (GH-6829) (#7127) (cherry picked from commit 6e33f810c9e3a549c9379f24cf1d1752c29195f0) Co-authored-by: Andr?s Delfino <adelfino at gmail.com> files: M Doc/glossary.rst diff --git a/Doc/glossary.rst b/Doc/glossary.rst index 66964692ccba..1d68e499b528 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -39,6 +39,20 @@ Glossary and loaders (in the :mod:`importlib.abc` module). You can create your own ABCs with the :mod:`abc` module. + annotation + A label associated with a variable, a class + attribute or a function parameter or return value, + used by convention as a :term:`type hint`. + + Annotations of local variables cannot be accessed at runtime, but + annotations of global variables, class attributes, and functions + are stored in the :attr:`__annotations__` + special attribute of modules, classes, and functions, + respectively. + + See :term:`variable annotation`, :term:`function annotation`, :pep:`484` + and :pep:`526`, which describe this functionality. + argument A value passed to a :term:`function` (or :term:`method`) when calling the function. There are two kinds of argument: @@ -175,6 +189,10 @@ Glossary normally contain method definitions which operate on instances of the class. + class variable + A variable defined in a class and intended to be modified only at + class level (i.e., not in an instance of the class). + coercion The implicit conversion of an instance of one type to another during an operation which involves two arguments of the same type. For example, @@ -367,16 +385,20 @@ Glossary and the :ref:`function` section. function annotation - An arbitrary metadata value associated with a function parameter or return - value. Its syntax is explained in section :ref:`function`. Annotations - may be accessed via the :attr:`__annotations__` special attribute of a - function object. + An :term:`annotation` of a function parameter or return value. - See also the :term:`variable annotation` glossary entry. + Function annotations are usually used for + :term:`type hints <type hint>`: for example this function is expected to take two + :class:`int` arguments and is also expected to have an :class:`int` + return value:: - Annotations are meant to provide a standard way for programmers to - document types of functions they design. See :pep:`484`, which - describes this functionality. + def sum_two_numbers(a: int, b: int) -> int: + return a + b + + Function annotation syntax is explained in section :ref:`function`. + + See :term:`variable annotation` and :pep:`484`, + which describe this functionality. __future__ A pseudo-module which programmers can use to enable new language features @@ -1024,6 +1046,43 @@ Glossary :attr:`~instance.__class__` attribute or can be retrieved with ``type(obj)``. + type alias + A synonym for a type, created by assigning the type to an identifier. + + Type aliases are useful for simplifying :term:`type hints <type hint>`. + For example:: + + from typing import List, Tuple + + def remove_gray_shades( + colors: List[Tuple[int, int, int]]) -> List[Tuple[int, int, int]]: + pass + + could be made more readable like this:: + + from typing import List, Tuple + + Color = Tuple[int, int, int] + + def remove_gray_shades(colors: List[Color]) -> List[Color]: + pass + + See :mod:`typing` and :pep:`484`, which describe this functionality. + + type hint + An :term:`annotation` that specifies the expected type for a variable, a class + attribute, or a function parameter or return value. + + Type hints are optional and are not enforced by Python but + they are useful to static type analysis tools, and aid IDEs with code + completion and refactoring. + + Type hints of global variables, class attributes, and functions, + but not local variables, can be accessed using + :func:`typing.get_type_hints`. + + See :mod:`typing` and :pep:`484`, which describe this functionality. + universal newlines A manner of interpreting text streams in which all of the following are recognized as ending a line: the Unix end-of-line convention ``'\n'``, @@ -1032,17 +1091,23 @@ Glossary :func:`bytes.splitlines` for an additional use. variable annotation - A type metadata value associated with a module global variable or - a class attribute. Its syntax is explained in section :ref:`annassign`. - Annotations are stored in the :attr:`__annotations__` special - attribute of a class or module object and can be accessed using - :func:`typing.get_type_hints`. + An :term:`annotation` of a variable or a class attribute. - See also the :term:`function annotation` glossary entry. + When annotating a variable or a class attribute, assignment is optional:: - Annotations are meant to provide a standard way for programmers to - document types of functions they design. See :pep:`484` and :pep:`526` - which describe this functionality. + class C: + field: 'annotation' + + Variable annotations are usually used for + :term:`type hints <type hint>`: for example this variable is expected to take + :class:`int` values:: + + count: int = 0 + + Variable annotation syntax is explained in section :ref:`annassign`. + + See :term:`function annotation`, :pep:`484` + and :pep:`526`, which describe this functionality. virtual environment A cooperatively isolated runtime environment that allows Python users From webhook-mailer at python.org Sat May 26 13:41:16 2018 From: webhook-mailer at python.org (Ivan Levkivskyi) Date: Sat, 26 May 2018 17:41:16 -0000 Subject: [Python-checkins] [3.6] bpo-32769: A new take on annotations/type hinting glossary entries (GH-6829) (GH-7128) Message-ID: <mailman.74.1527356477.18020.python-checkins@python.org> https://github.com/python/cpython/commit/717204ffcccfe04a34b6c4a52f0e844fde3cdebe commit: 717204ffcccfe04a34b6c4a52f0e844fde3cdebe branch: 3.6 author: Andr?s Delfino <adelfino at gmail.com> committer: Ivan Levkivskyi <levkivskyi at gmail.com> date: 2018-05-26T10:41:12-07:00 summary: [3.6] bpo-32769: A new take on annotations/type hinting glossary entries (GH-6829) (GH-7128) * [3.6] bpo-32769: A new take on annotations/type hinting glossary entries (GH-6829). (cherry picked from commit 6e33f810c9e3a549c9379f24cf1d1752c29195f0) Co-authored-by: Andr?s Delfino <adelfino at gmail.com> * Typo fix spotted by Guido files: M Doc/glossary.rst diff --git a/Doc/glossary.rst b/Doc/glossary.rst index 5e25dbbdc06a..8f97b9940f20 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -39,6 +39,20 @@ Glossary and loaders (in the :mod:`importlib.abc` module). You can create your own ABCs with the :mod:`abc` module. + annotation + A label associated with a variable, a class + attribute or a function parameter or return value, + used by convention as a :term:`type hint`. + + Annotations of local variables cannot be accessed at runtime, but + annotations of global variables, class attributes, and functions + are stored in the :attr:`__annotations__` + special attribute of modules, classes, and functions, + respectively. + + See :term:`variable annotation`, :term:`function annotation`, :pep:`484` + and :pep:`526`, which describe this functionality. + argument A value passed to a :term:`function` (or :term:`method`) when calling the function. There are two kinds of argument: @@ -175,6 +189,10 @@ Glossary normally contain method definitions which operate on instances of the class. + class variable + A variable defined in a class and intended to be modified only at + class level (i.e., not in an instance of the class). + coercion The implicit conversion of an instance of one type to another during an operation which involves two arguments of the same type. For example, @@ -367,14 +385,20 @@ Glossary and the :ref:`function` section. function annotation - An arbitrary metadata value associated with a function parameter or return - value. Its syntax is explained in section :ref:`function`. Annotations - may be accessed via the :attr:`__annotations__` special attribute of a - function object. + An :term:`annotation` of a function parameter or return value. + + Function annotations are usually used for + :term:`type hints <type hint>`: for example this function is expected to take two + :class:`int` arguments and is also expected to have an :class:`int` + return value:: + + def sum_two_numbers(a: int, b: int) -> int: + return a + b + + Function annotation syntax is explained in section :ref:`function`. - Python itself does not assign any particular meaning to function - annotations. They are intended to be interpreted by third-party libraries - or tools. See :pep:`3107`, which describes some of their potential uses. + See :term:`variable annotation` and :pep:`484`, + which describe this functionality. __future__ A pseudo-module which programmers can use to enable new language features @@ -1016,6 +1040,43 @@ Glossary :attr:`~instance.__class__` attribute or can be retrieved with ``type(obj)``. + type alias + A synonym for a type, created by assigning the type to an identifier. + + Type aliases are useful for simplifying :term:`type hints <type hint>`. + For example:: + + from typing import List, Tuple + + def remove_gray_shades( + colors: List[Tuple[int, int, int]]) -> List[Tuple[int, int, int]]: + pass + + could be made more readable like this:: + + from typing import List, Tuple + + Color = Tuple[int, int, int] + + def remove_gray_shades(colors: List[Color]) -> List[Color]: + pass + + See :mod:`typing` and :pep:`484`, which describe this functionality. + + type hint + An :term:`annotation` that specifies the expected type for a variable, a class + attribute, or a function parameter or return value. + + Type hints are optional and are not enforced by Python but + they are useful to static type analysis tools, and aid IDEs with code + completion and refactoring. + + Type hints of global variables, class attributes, and functions, + but not local variables, can be accessed using + :func:`typing.get_type_hints`. + + See :mod:`typing` and :pep:`484`, which describe this functionality. + universal newlines A manner of interpreting text streams in which all of the following are recognized as ending a line: the Unix end-of-line convention ``'\n'``, @@ -1024,16 +1085,23 @@ Glossary :func:`bytes.splitlines` for an additional use. variable annotation - A type metadata value associated with a module global variable or - a class attribute. Its syntax is explained in section :ref:`annassign`. - Annotations are stored in the :attr:`__annotations__` special - attribute of a class or module object and can be accessed using - :func:`typing.get_type_hints`. + An :term:`annotation` of a variable or a class attribute. + + When annotating a variable or a class attribute, assignment is optional:: + + class C: + field: 'annotation' + + Variable annotations are usually used for + :term:`type hints <type hint>`: for example this variable is expected to take + :class:`int` values:: + + count: int = 0 + + Variable annotation syntax is explained in section :ref:`annassign`. - Python itself does not assign any particular meaning to variable - annotations. They are intended to be interpreted by third-party libraries - or type checking tools. See :pep:`526`, :pep:`484` which describe - some of their potential uses. + See :term:`function annotation`, :pep:`484` + and :pep:`526`, which describe this functionality. virtual environment A cooperatively isolated runtime environment that allows Python users From webhook-mailer at python.org Sat May 26 14:18:05 2018 From: webhook-mailer at python.org (Ivan Levkivskyi) Date: Sat, 26 May 2018 18:18:05 -0000 Subject: [Python-checkins] Fix typo spotted by Guido (GH-7131) Message-ID: <mailman.75.1527358686.18020.python-checkins@python.org> https://github.com/python/cpython/commit/2298c0e6a6eb93916625e73ffa8368b2a82786f7 commit: 2298c0e6a6eb93916625e73ffa8368b2a82786f7 branch: master author: Andr?s Delfino <adelfino at gmail.com> committer: Ivan Levkivskyi <levkivskyi at gmail.com> date: 2018-05-26T11:18:02-07:00 summary: Fix typo spotted by Guido (GH-7131) files: M Doc/glossary.rst diff --git a/Doc/glossary.rst b/Doc/glossary.rst index bf98934ac66c..1d68e499b528 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -44,7 +44,7 @@ Glossary attribute or a function parameter or return value, used by convention as a :term:`type hint`. - Annotations of local variables cannot be accesed at runtime, but + Annotations of local variables cannot be accessed at runtime, but annotations of global variables, class attributes, and functions are stored in the :attr:`__annotations__` special attribute of modules, classes, and functions, From webhook-mailer at python.org Sat May 26 14:19:29 2018 From: webhook-mailer at python.org (Ivan Levkivskyi) Date: Sat, 26 May 2018 18:19:29 -0000 Subject: [Python-checkins] bpo-33652: Improve pickle support in the typing module. (GH-7123) Message-ID: <mailman.76.1527358771.18020.python-checkins@python.org> https://github.com/python/cpython/commit/09f3221fbbf72692308149054e4f7668b08b22eb commit: 09f3221fbbf72692308149054e4f7668b08b22eb branch: master author: Serhiy Storchaka <storchaka at gmail.com> committer: Ivan Levkivskyi <levkivskyi at gmail.com> date: 2018-05-26T11:19:26-07:00 summary: bpo-33652: Improve pickle support in the typing module. (GH-7123) Pickles of type variables and subscripted generics are now future-proof and compatible with older Python versions. files: A Misc/NEWS.d/next/Library/2018-05-26-10-13-59.bpo-33652.humFJ1.rst M Lib/typing.py diff --git a/Lib/typing.py b/Lib/typing.py index 18b04cf4dbe2..e9265afce491 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -24,6 +24,7 @@ import collections.abc import contextlib import functools +import operator import re as stdlib_re # Avoid confusion with the re we export. import sys import types @@ -486,10 +487,6 @@ def __repr__(self): return f'ForwardRef({self.__forward_arg__!r})' -def _find_name(mod, name): - return getattr(sys.modules[mod], name) - - class TypeVar(_Final, _Immutable, _root=True): """Type variable. @@ -535,7 +532,7 @@ def longest(x: A, y: A) -> A: """ __slots__ = ('__name__', '__bound__', '__constraints__', - '__covariant__', '__contravariant__', '_def_mod') + '__covariant__', '__contravariant__') def __init__(self, name, *constraints, bound=None, covariant=False, contravariant=False): @@ -554,7 +551,9 @@ def __init__(self, name, *constraints, bound=None, self.__bound__ = _type_check(bound, "Bound must be a type.") else: self.__bound__ = None - self._def_mod = sys._getframe(1).f_globals['__name__'] # for pickling + def_mod = sys._getframe(1).f_globals['__name__'] # for pickling + if def_mod != 'typing': + self.__module__ = def_mod def __getstate__(self): return {'name': self.__name__, @@ -580,7 +579,7 @@ def __repr__(self): return prefix + self.__name__ def __reduce__(self): - return (_find_name, (self._def_mod, self.__name__)) + return self.__name__ # Special typing constructs Union, Optional, Generic, Callable and Tuple @@ -741,7 +740,19 @@ def __subclasscheck__(self, cls): def __reduce__(self): if self._special: return self._name - return super().__reduce__() + + if self._name: + origin = globals()[self._name] + else: + origin = self.__origin__ + if (origin is Callable and + not (len(self.__args__) == 2 and self.__args__[0] is Ellipsis)): + args = list(self.__args__[:-1]), self.__args__[-1] + else: + args = tuple(self.__args__) + if len(args) == 1 and not isinstance(args[0], tuple): + args, = args + return operator.getitem, (origin, args) class _VariadicGenericAlias(_GenericAlias, _root=True): diff --git a/Misc/NEWS.d/next/Library/2018-05-26-10-13-59.bpo-33652.humFJ1.rst b/Misc/NEWS.d/next/Library/2018-05-26-10-13-59.bpo-33652.humFJ1.rst new file mode 100644 index 000000000000..f5499f1b53ce --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-26-10-13-59.bpo-33652.humFJ1.rst @@ -0,0 +1,2 @@ +Pickles of type variables and subscripted generics are now future-proof and +compatible with older Python versions. From webhook-mailer at python.org Sat May 26 14:38:03 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 26 May 2018 18:38:03 -0000 Subject: [Python-checkins] bpo-33652: Improve pickle support in the typing module. (GH-7123) Message-ID: <mailman.77.1527359886.18020.python-checkins@python.org> https://github.com/python/cpython/commit/d49862582ed3513debed6e919fd4f92e9d4eebbd commit: d49862582ed3513debed6e919fd4f92e9d4eebbd branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-26T11:38:00-07:00 summary: bpo-33652: Improve pickle support in the typing module. (GH-7123) Pickles of type variables and subscripted generics are now future-proof and compatible with older Python versions. (cherry picked from commit 09f3221fbbf72692308149054e4f7668b08b22eb) Co-authored-by: Serhiy Storchaka <storchaka at gmail.com> files: A Misc/NEWS.d/next/Library/2018-05-26-10-13-59.bpo-33652.humFJ1.rst M Lib/typing.py diff --git a/Lib/typing.py b/Lib/typing.py index 18b04cf4dbe2..e9265afce491 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -24,6 +24,7 @@ import collections.abc import contextlib import functools +import operator import re as stdlib_re # Avoid confusion with the re we export. import sys import types @@ -486,10 +487,6 @@ def __repr__(self): return f'ForwardRef({self.__forward_arg__!r})' -def _find_name(mod, name): - return getattr(sys.modules[mod], name) - - class TypeVar(_Final, _Immutable, _root=True): """Type variable. @@ -535,7 +532,7 @@ def longest(x: A, y: A) -> A: """ __slots__ = ('__name__', '__bound__', '__constraints__', - '__covariant__', '__contravariant__', '_def_mod') + '__covariant__', '__contravariant__') def __init__(self, name, *constraints, bound=None, covariant=False, contravariant=False): @@ -554,7 +551,9 @@ def __init__(self, name, *constraints, bound=None, self.__bound__ = _type_check(bound, "Bound must be a type.") else: self.__bound__ = None - self._def_mod = sys._getframe(1).f_globals['__name__'] # for pickling + def_mod = sys._getframe(1).f_globals['__name__'] # for pickling + if def_mod != 'typing': + self.__module__ = def_mod def __getstate__(self): return {'name': self.__name__, @@ -580,7 +579,7 @@ def __repr__(self): return prefix + self.__name__ def __reduce__(self): - return (_find_name, (self._def_mod, self.__name__)) + return self.__name__ # Special typing constructs Union, Optional, Generic, Callable and Tuple @@ -741,7 +740,19 @@ def __subclasscheck__(self, cls): def __reduce__(self): if self._special: return self._name - return super().__reduce__() + + if self._name: + origin = globals()[self._name] + else: + origin = self.__origin__ + if (origin is Callable and + not (len(self.__args__) == 2 and self.__args__[0] is Ellipsis)): + args = list(self.__args__[:-1]), self.__args__[-1] + else: + args = tuple(self.__args__) + if len(args) == 1 and not isinstance(args[0], tuple): + args, = args + return operator.getitem, (origin, args) class _VariadicGenericAlias(_GenericAlias, _root=True): diff --git a/Misc/NEWS.d/next/Library/2018-05-26-10-13-59.bpo-33652.humFJ1.rst b/Misc/NEWS.d/next/Library/2018-05-26-10-13-59.bpo-33652.humFJ1.rst new file mode 100644 index 000000000000..f5499f1b53ce --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-26-10-13-59.bpo-33652.humFJ1.rst @@ -0,0 +1,2 @@ +Pickles of type variables and subscripted generics are now future-proof and +compatible with older Python versions. From webhook-mailer at python.org Sat May 26 14:39:55 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 26 May 2018 18:39:55 -0000 Subject: [Python-checkins] bpo-21983: Fix a crash in ctypes.cast() when passed a ctypes structured data type (GH-3859) Message-ID: <mailman.78.1527359999.18020.python-checkins@python.org> https://github.com/python/cpython/commit/e60f6e1864d80d80f8928afadec617d161a64150 commit: e60f6e1864d80d80f8928afadec617d161a64150 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-26T11:39:52-07:00 summary: bpo-21983: Fix a crash in ctypes.cast() when passed a ctypes structured data type (GH-3859) (cherry picked from commit d518d8bc8d5dac1a1270612f424d33e0e5afc2b5) Co-authored-by: Oren Milman <orenmn at gmail.com> files: A Misc/NEWS.d/next/Core and Builtins/2017-10-02-21-02-14.bpo-21983.UoC319.rst M Lib/ctypes/test/test_cast.py M Modules/_ctypes/_ctypes.c diff --git a/Lib/ctypes/test/test_cast.py b/Lib/ctypes/test/test_cast.py index 187d2bde143d..6878f9732826 100644 --- a/Lib/ctypes/test/test_cast.py +++ b/Lib/ctypes/test/test_cast.py @@ -82,5 +82,18 @@ def test_wchar_p(self): self.assertEqual(cast(cast(s, c_void_p), c_wchar_p).value, "hiho") + def test_bad_type_arg(self): + # The type argument must be a ctypes pointer type. + array_type = c_byte * sizeof(c_int) + array = array_type() + self.assertRaises(TypeError, cast, array, None) + self.assertRaises(TypeError, cast, array, array_type) + class Struct(Structure): + _fields_ = [("a", c_int)] + self.assertRaises(TypeError, cast, array, Struct) + class MyUnion(Union): + _fields_ = [("a", c_int)] + self.assertRaises(TypeError, cast, array, MyUnion) + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-10-02-21-02-14.bpo-21983.UoC319.rst b/Misc/NEWS.d/next/Core and Builtins/2017-10-02-21-02-14.bpo-21983.UoC319.rst new file mode 100644 index 000000000000..88a03685073c --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-10-02-21-02-14.bpo-21983.UoC319.rst @@ -0,0 +1,2 @@ +Fix a crash in `ctypes.cast()` in case the type argument is a ctypes +structured data type. Patch by Eryk Sun and Oren Milman. diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 66bce151eb70..3ae6348fef43 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -5319,7 +5319,7 @@ cast_check_pointertype(PyObject *arg) if (PyCFuncPtrTypeObject_Check(arg)) return 1; dict = PyType_stgdict(arg); - if (dict) { + if (dict != NULL && dict->proto != NULL) { if (PyUnicode_Check(dict->proto) && (strchr("sPzUZXO", PyUnicode_AsUTF8(dict->proto)[0]))) { /* simple pointer types, c_void_p, c_wchar_p, BSTR, ... */ From webhook-mailer at python.org Sat May 26 16:30:50 2018 From: webhook-mailer at python.org (Ned Deily) Date: Sat, 26 May 2018 20:30:50 -0000 Subject: [Python-checkins] bpo-33655: Also ignore test_posix_fallocate failures on BSD platforms (GH-7134) Message-ID: <mailman.79.1527366652.18020.python-checkins@python.org> https://github.com/python/cpython/commit/09c4a7dee2eb39b515e5f499f184257cdbe9cb42 commit: 09c4a7dee2eb39b515e5f499f184257cdbe9cb42 branch: master author: Ned Deily <nad at python.org> committer: GitHub <noreply at github.com> date: 2018-05-26T16:30:46-04:00 summary: bpo-33655: Also ignore test_posix_fallocate failures on BSD platforms (GH-7134) The failure may be due to the use oF ZFS, a case we already ignore for Solaris-based systems where ZFS is frequently used. files: A Misc/NEWS.d/next/Tests/2018-05-26-16-01-40.bpo-33655.Frb4LA.rst M Lib/test/test_posix.py diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py index ecf3e93eb048..e54484ce7da2 100644 --- a/Lib/test/test_posix.py +++ b/Lib/test/test_posix.py @@ -343,7 +343,12 @@ def test_posix_fallocate(self): except OSError as inst: # issue10812, ZFS doesn't appear to support posix_fallocate, # so skip Solaris-based since they are likely to have ZFS. - if inst.errno != errno.EINVAL or not sys.platform.startswith("sunos"): + # issue33655: Also ignore EINVAL on *BSD since ZFS is also + # often used there. + if inst.errno == errno.EINVAL and sys.platform.startswith( + ('sunos', 'freebsd', 'netbsd', 'openbsd', 'gnukfreebsd')): + raise unittest.SkipTest("test may fail on ZFS filesystems") + else: raise finally: os.close(fd) diff --git a/Misc/NEWS.d/next/Tests/2018-05-26-16-01-40.bpo-33655.Frb4LA.rst b/Misc/NEWS.d/next/Tests/2018-05-26-16-01-40.bpo-33655.Frb4LA.rst new file mode 100644 index 000000000000..7ed2ea232371 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2018-05-26-16-01-40.bpo-33655.Frb4LA.rst @@ -0,0 +1,2 @@ +Ignore test_posix_fallocate failures on BSD platforms that might be due to +running on ZFS. From webhook-mailer at python.org Sat May 26 16:38:36 2018 From: webhook-mailer at python.org (=?utf-8?q?=C5=81ukasz?= Langa) Date: Sat, 26 May 2018 20:38:36 -0000 Subject: [Python-checkins] bpo-32380: Create functools.singledispatchmethod (#6306) Message-ID: <mailman.80.1527367118.18020.python-checkins@python.org> https://github.com/python/cpython/commit/c651275afe8515b2cf70b8152e19ce39df88f0dd commit: c651275afe8515b2cf70b8152e19ce39df88f0dd branch: master author: Ethan Smith <ethan at ethanhs.me> committer: ?ukasz Langa <lukasz at langa.pl> date: 2018-05-26T13:38:33-07:00 summary: bpo-32380: Create functools.singledispatchmethod (#6306) files: A Misc/NEWS.d/next/Library/2018-03-29-03-09-22.bpo-32380.NhuGig.rst M Doc/library/functools.rst M Lib/functools.py M Lib/test/test_functools.py M Misc/ACKS diff --git a/Doc/library/functools.rst b/Doc/library/functools.rst index a81e819103ad..d0e3c7b201c2 100644 --- a/Doc/library/functools.rst +++ b/Doc/library/functools.rst @@ -383,6 +383,52 @@ The :mod:`functools` module defines the following functions: The :func:`register` attribute supports using type annotations. +.. class:: singledispatchmethod(func) + + Transform a method into a :term:`single-dispatch <single + dispatch>` :term:`generic function`. + + To define a generic method, decorate it with the ``@singledispatchmethod`` + decorator. Note that the dispatch happens on the type of the first non-self + or non-cls argument, create your function accordingly:: + + class Negator: + @singledispatchmethod + def neg(self, arg): + raise NotImplementedError("Cannot negate a") + + @neg.register + def _(self, arg: int): + return -arg + + @neg.register + def _(self, arg: bool): + return not arg + + ``@singledispatchmethod`` supports nesting with other decorators such as + ``@classmethod``. Note that to allow for ``dispatcher.register``, + ``singledispatchmethod`` must be the *outer most* decorator. Here is the + ``Negator`` class with the ``neg`` methods being class bound:: + + class Negator: + @singledispatchmethod + @classmethod + def neg(cls, arg): + raise NotImplementedError("Cannot negate a") + + @neg.register + @classmethod + def _(cls, arg: int): + return -arg + + @neg.register + @classmethod + def _(cls, arg: bool): + return not arg + + The same pattern can be used for other similar decorators: ``staticmethod``, + ``abstractmethod``, and others. + .. function:: update_wrapper(wrapper, wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES) Update a *wrapper* function to look like the *wrapped* function. The optional diff --git a/Lib/functools.py b/Lib/functools.py index c8b79c2a7c2b..d5f43935e6cf 100644 --- a/Lib/functools.py +++ b/Lib/functools.py @@ -11,7 +11,7 @@ __all__ = ['update_wrapper', 'wraps', 'WRAPPER_ASSIGNMENTS', 'WRAPPER_UPDATES', 'total_ordering', 'cmp_to_key', 'lru_cache', 'reduce', 'partial', - 'partialmethod', 'singledispatch'] + 'partialmethod', 'singledispatch', 'singledispatchmethod'] try: from _functools import reduce @@ -826,3 +826,40 @@ def wrapper(*args, **kw): wrapper._clear_cache = dispatch_cache.clear update_wrapper(wrapper, func) return wrapper + + +# Descriptor version +class singledispatchmethod: + """Single-dispatch generic method descriptor. + + Supports wrapping existing descriptors and handles non-descriptor + callables as instance methods. + """ + + def __init__(self, func): + if not callable(func) and not hasattr(func, "__get__"): + raise TypeError(f"{func!r} is not callable or a descriptor") + + self.dispatcher = singledispatch(func) + self.func = func + + def register(self, cls, method=None): + """generic_method.register(cls, func) -> func + + Registers a new implementation for the given *cls* on a *generic_method*. + """ + return self.dispatcher.register(cls, func=method) + + def __get__(self, obj, cls): + def _method(*args, **kwargs): + method = self.dispatcher.dispatch(args[0].__class__) + return method.__get__(obj, cls)(*args, **kwargs) + + _method.__isabstractmethod__ = self.__isabstractmethod__ + _method.register = self.register + update_wrapper(_method, self.func) + return _method + + @property + def __isabstractmethod__(self): + return getattr(self.func, '__isabstractmethod__', False) diff --git a/Lib/test/test_functools.py b/Lib/test/test_functools.py index 2245b9743397..7ffe000af04d 100644 --- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -2147,6 +2147,124 @@ def __eq__(self, other): return self.arg == other self.assertEqual(i("str"), "str") + def test_method_register(self): + class A: + @functools.singledispatchmethod + def t(self, arg): + self.arg = "base" + @t.register(int) + def _(self, arg): + self.arg = "int" + @t.register(str) + def _(self, arg): + self.arg = "str" + a = A() + + a.t(0) + self.assertEqual(a.arg, "int") + aa = A() + self.assertFalse(hasattr(aa, 'arg')) + a.t('') + self.assertEqual(a.arg, "str") + aa = A() + self.assertFalse(hasattr(aa, 'arg')) + a.t(0.0) + self.assertEqual(a.arg, "base") + aa = A() + self.assertFalse(hasattr(aa, 'arg')) + + def test_staticmethod_register(self): + class A: + @functools.singledispatchmethod + @staticmethod + def t(arg): + return arg + @t.register(int) + @staticmethod + def _(arg): + return isinstance(arg, int) + @t.register(str) + @staticmethod + def _(arg): + return isinstance(arg, str) + a = A() + + self.assertTrue(A.t(0)) + self.assertTrue(A.t('')) + self.assertEqual(A.t(0.0), 0.0) + + def test_classmethod_register(self): + class A: + def __init__(self, arg): + self.arg = arg + + @functools.singledispatchmethod + @classmethod + def t(cls, arg): + return cls("base") + @t.register(int) + @classmethod + def _(cls, arg): + return cls("int") + @t.register(str) + @classmethod + def _(cls, arg): + return cls("str") + + self.assertEqual(A.t(0).arg, "int") + self.assertEqual(A.t('').arg, "str") + self.assertEqual(A.t(0.0).arg, "base") + + def test_callable_register(self): + class A: + def __init__(self, arg): + self.arg = arg + + @functools.singledispatchmethod + @classmethod + def t(cls, arg): + return cls("base") + + @A.t.register(int) + @classmethod + def _(cls, arg): + return cls("int") + @A.t.register(str) + @classmethod + def _(cls, arg): + return cls("str") + + self.assertEqual(A.t(0).arg, "int") + self.assertEqual(A.t('').arg, "str") + self.assertEqual(A.t(0.0).arg, "base") + + def test_abstractmethod_register(self): + class Abstract(abc.ABCMeta): + + @functools.singledispatchmethod + @abc.abstractmethod + def add(self, x, y): + pass + + self.assertTrue(Abstract.add.__isabstractmethod__) + + def test_type_ann_register(self): + class A: + @functools.singledispatchmethod + def t(self, arg): + return "base" + @t.register + def _(self, arg: int): + return "int" + @t.register + def _(self, arg: str): + return "str" + a = A() + + self.assertEqual(a.t(0), "int") + self.assertEqual(a.t(''), "str") + self.assertEqual(a.t(0.0), "base") + def test_invalid_registrations(self): msg_prefix = "Invalid first argument to `register()`: " msg_suffix = ( diff --git a/Misc/ACKS b/Misc/ACKS index 4d295b60a065..42f1abc8da19 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1510,6 +1510,7 @@ V?clav ?milauer Allen W. Smith Christopher Smith Eric V. Smith +Ethan H. Smith Gregory P. Smith Mark Smith Nathaniel J. Smith diff --git a/Misc/NEWS.d/next/Library/2018-03-29-03-09-22.bpo-32380.NhuGig.rst b/Misc/NEWS.d/next/Library/2018-03-29-03-09-22.bpo-32380.NhuGig.rst new file mode 100644 index 000000000000..ab852a53e92a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-03-29-03-09-22.bpo-32380.NhuGig.rst @@ -0,0 +1,2 @@ +Create functools.singledispatchmethod to support generic single dispatch on +descriptors and methods. From webhook-mailer at python.org Sat May 26 17:57:04 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 26 May 2018 21:57:04 -0000 Subject: [Python-checkins] bpo-33655: Also ignore test_posix_fallocate failures on BSD platforms (GH-7134) Message-ID: <mailman.0.1527371828.2800.python-checkins@python.org> https://github.com/python/cpython/commit/96fb828da305b18336b8d74b14f479c4f286cf7b commit: 96fb828da305b18336b8d74b14f479c4f286cf7b branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-26T14:57:01-07:00 summary: bpo-33655: Also ignore test_posix_fallocate failures on BSD platforms (GH-7134) The failure may be due to the use oF ZFS, a case we already ignore for Solaris-based systems where ZFS is frequently used. (cherry picked from commit 09c4a7dee2eb39b515e5f499f184257cdbe9cb42) Co-authored-by: Ned Deily <nad at python.org> files: A Misc/NEWS.d/next/Tests/2018-05-26-16-01-40.bpo-33655.Frb4LA.rst M Lib/test/test_posix.py diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py index bf7c8c2119fb..7dea1beab2c2 100644 --- a/Lib/test/test_posix.py +++ b/Lib/test/test_posix.py @@ -343,7 +343,12 @@ def test_posix_fallocate(self): except OSError as inst: # issue10812, ZFS doesn't appear to support posix_fallocate, # so skip Solaris-based since they are likely to have ZFS. - if inst.errno != errno.EINVAL or not sys.platform.startswith("sunos"): + # issue33655: Also ignore EINVAL on *BSD since ZFS is also + # often used there. + if inst.errno == errno.EINVAL and sys.platform.startswith( + ('sunos', 'freebsd', 'netbsd', 'openbsd', 'gnukfreebsd')): + raise unittest.SkipTest("test may fail on ZFS filesystems") + else: raise finally: os.close(fd) diff --git a/Misc/NEWS.d/next/Tests/2018-05-26-16-01-40.bpo-33655.Frb4LA.rst b/Misc/NEWS.d/next/Tests/2018-05-26-16-01-40.bpo-33655.Frb4LA.rst new file mode 100644 index 000000000000..7ed2ea232371 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2018-05-26-16-01-40.bpo-33655.Frb4LA.rst @@ -0,0 +1,2 @@ +Ignore test_posix_fallocate failures on BSD platforms that might be due to +running on ZFS. From webhook-mailer at python.org Sat May 26 17:58:02 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 26 May 2018 21:58:02 -0000 Subject: [Python-checkins] bpo-33655: Also ignore test_posix_fallocate failures on BSD platforms (GH-7134) Message-ID: <mailman.1.1527371885.2800.python-checkins@python.org> https://github.com/python/cpython/commit/ae27dee0f8f364f0bbb170d918a28b87cd0753d9 commit: ae27dee0f8f364f0bbb170d918a28b87cd0753d9 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-26T14:57:59-07:00 summary: bpo-33655: Also ignore test_posix_fallocate failures on BSD platforms (GH-7134) The failure may be due to the use oF ZFS, a case we already ignore for Solaris-based systems where ZFS is frequently used. (cherry picked from commit 09c4a7dee2eb39b515e5f499f184257cdbe9cb42) Co-authored-by: Ned Deily <nad at python.org> files: A Misc/NEWS.d/next/Tests/2018-05-26-16-01-40.bpo-33655.Frb4LA.rst M Lib/test/test_posix.py diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py index 296e328a8044..eb3ef8494788 100644 --- a/Lib/test/test_posix.py +++ b/Lib/test/test_posix.py @@ -230,7 +230,12 @@ def test_posix_fallocate(self): except OSError as inst: # issue10812, ZFS doesn't appear to support posix_fallocate, # so skip Solaris-based since they are likely to have ZFS. - if inst.errno != errno.EINVAL or not sys.platform.startswith("sunos"): + # issue33655: Also ignore EINVAL on *BSD since ZFS is also + # often used there. + if inst.errno == errno.EINVAL and sys.platform.startswith( + ('sunos', 'freebsd', 'netbsd', 'openbsd', 'gnukfreebsd')): + raise unittest.SkipTest("test may fail on ZFS filesystems") + else: raise finally: os.close(fd) diff --git a/Misc/NEWS.d/next/Tests/2018-05-26-16-01-40.bpo-33655.Frb4LA.rst b/Misc/NEWS.d/next/Tests/2018-05-26-16-01-40.bpo-33655.Frb4LA.rst new file mode 100644 index 000000000000..7ed2ea232371 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2018-05-26-16-01-40.bpo-33655.Frb4LA.rst @@ -0,0 +1,2 @@ +Ignore test_posix_fallocate failures on BSD platforms that might be due to +running on ZFS. From solipsis at pitrou.net Sun May 27 05:11:38 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 27 May 2018 09:11:38 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=6 Message-ID: <20180527091138.1.49CA7A41C3F6BDC5@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_collections leaked [-7, 1, 7] memory blocks, sum=1 test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_spawn leaked [2, 0, -1] memory blocks, sum=1 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogNHRDpo', '--timeout', '7200'] From solipsis at pitrou.net Mon May 28 05:11:16 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Mon, 28 May 2018 09:11:16 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=12 Message-ID: <20180528091116.1.E9FDEEFAC2D66ADB@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_collections leaked [0, 0, 7] memory blocks, sum=7 test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_fork leaked [2, -1, -1] memory blocks, sum=0 test_multiprocessing_forkserver leaked [2, 0, -1] memory blocks, sum=1 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogos0w2P', '--timeout', '7200'] From webhook-mailer at python.org Mon May 28 06:54:59 2018 From: webhook-mailer at python.org (Ivan Levkivskyi) Date: Mon, 28 May 2018 10:54:59 -0000 Subject: [Python-checkins] bpo-33652: Remove __getstate__ and __setstate__ methods in typing. (GH-7144) Message-ID: <mailman.2.1527504902.2800.python-checkins@python.org> https://github.com/python/cpython/commit/97b523db7c79c18c48516fba9410014d9896abc4 commit: 97b523db7c79c18c48516fba9410014d9896abc4 branch: master author: Serhiy Storchaka <storchaka at gmail.com> committer: Ivan Levkivskyi <levkivskyi at gmail.com> date: 2018-05-28T11:54:56+01:00 summary: bpo-33652: Remove __getstate__ and __setstate__ methods in typing. (GH-7144) files: M Lib/typing.py diff --git a/Lib/typing.py b/Lib/typing.py index e9265afce491..a95eb2e184a0 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -294,13 +294,6 @@ class _SpecialForm(_Final, _Immutable, _root=True): __slots__ = ('_name', '_doc') - def __getstate__(self): - return {'name': self._name, 'doc': self._doc} - - def __setstate__(self, state): - self._name = state['name'] - self._doc = state['doc'] - def __new__(cls, *args, **kwds): """Constructor. @@ -555,20 +548,6 @@ def __init__(self, name, *constraints, bound=None, if def_mod != 'typing': self.__module__ = def_mod - def __getstate__(self): - return {'name': self.__name__, - 'bound': self.__bound__, - 'constraints': self.__constraints__, - 'co': self.__covariant__, - 'contra': self.__contravariant__} - - def __setstate__(self, state): - self.__name__ = state['name'] - self.__bound__ = state['bound'] - self.__constraints__ = state['constraints'] - self.__covariant__ = state['co'] - self.__contravariant__ = state['contra'] - def __repr__(self): if self.__covariant__: prefix = '+' From webhook-mailer at python.org Mon May 28 07:21:56 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 28 May 2018 11:21:56 -0000 Subject: [Python-checkins] bpo-33652: Remove __getstate__ and __setstate__ methods in typing. (GH-7144) Message-ID: <mailman.3.1527506519.2800.python-checkins@python.org> https://github.com/python/cpython/commit/98b089e2a178a309f20ac9ff498b230407da1f47 commit: 98b089e2a178a309f20ac9ff498b230407da1f47 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-28T04:21:44-07:00 summary: bpo-33652: Remove __getstate__ and __setstate__ methods in typing. (GH-7144) (cherry picked from commit 97b523db7c79c18c48516fba9410014d9896abc4) Co-authored-by: Serhiy Storchaka <storchaka at gmail.com> files: M Lib/typing.py diff --git a/Lib/typing.py b/Lib/typing.py index e9265afce491..a95eb2e184a0 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -294,13 +294,6 @@ class _SpecialForm(_Final, _Immutable, _root=True): __slots__ = ('_name', '_doc') - def __getstate__(self): - return {'name': self._name, 'doc': self._doc} - - def __setstate__(self, state): - self._name = state['name'] - self._doc = state['doc'] - def __new__(cls, *args, **kwds): """Constructor. @@ -555,20 +548,6 @@ def __init__(self, name, *constraints, bound=None, if def_mod != 'typing': self.__module__ = def_mod - def __getstate__(self): - return {'name': self.__name__, - 'bound': self.__bound__, - 'constraints': self.__constraints__, - 'co': self.__covariant__, - 'contra': self.__contravariant__} - - def __setstate__(self, state): - self.__name__ = state['name'] - self.__bound__ = state['bound'] - self.__constraints__ = state['constraints'] - self.__covariant__ = state['co'] - self.__contravariant__ = state['contra'] - def __repr__(self): if self.__covariant__: prefix = '+' From webhook-mailer at python.org Mon May 28 07:30:45 2018 From: webhook-mailer at python.org (Victor Stinner) Date: Mon, 28 May 2018 11:30:45 -0000 Subject: [Python-checkins] test.regrtest: flush stdout to display progress (#7120) Message-ID: <mailman.4.1527507046.2800.python-checkins@python.org> https://github.com/python/cpython/commit/1da37adc281286b8ef9ff3e882fe9de35c23507f commit: 1da37adc281286b8ef9ff3e882fe9de35c23507f branch: 2.7 author: Victor Stinner <vstinner at redhat.com> committer: GitHub <noreply at github.com> date: 2018-05-28T13:30:42+02:00 summary: test.regrtest: flush stdout to display progress (#7120) Call sys.stdout.flush() after displaying "running: ...". files: M Lib/test/regrtest.py diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py index 6df8f86d9579..c4f27814029c 100755 --- a/Lib/test/regrtest.py +++ b/Lib/test/regrtest.py @@ -782,6 +782,7 @@ def get_running(workers): running = get_running(workers) if running and not pgo: print('running: %s' % ', '.join(running)) + sys.stdout.flush() continue test, stdout, stderr, result = item @@ -802,7 +803,7 @@ def get_running(workers): display_progress(test_index, text) if stdout: - print stdout + print(stdout) sys.stdout.flush() if stderr and not pgo: print >>sys.stderr, stderr From webhook-mailer at python.org Mon May 28 08:11:23 2018 From: webhook-mailer at python.org (Petr Viktorin) Date: Mon, 28 May 2018 12:11:23 -0000 Subject: [Python-checkins] bpo-32374: Ignore Python-level exceptions in test_bad_traverse (GH-7145) Message-ID: <mailman.5.1527509487.2800.python-checkins@python.org> https://github.com/python/cpython/commit/08c5aca9d13b24b35faf89ebd26fc348ae1731b2 commit: 08c5aca9d13b24b35faf89ebd26fc348ae1731b2 branch: master author: Marcel Plch <gmarcel.plch at gmail.com> committer: Petr Viktorin <encukou at gmail.com> date: 2018-05-28T14:11:20+02:00 summary: bpo-32374: Ignore Python-level exceptions in test_bad_traverse (GH-7145) files: M Lib/test/test_importlib/extension/test_loader.py diff --git a/Lib/test/test_importlib/extension/test_loader.py b/Lib/test/test_importlib/extension/test_loader.py index 57ba7083d37d..9ad05fadef29 100644 --- a/Lib/test/test_importlib/extension/test_loader.py +++ b/Lib/test/test_importlib/extension/test_loader.py @@ -275,13 +275,19 @@ def test_bad_traverse(self): (Multiphase initialization modules only) ''' script = """if True: - from test import support - import importlib.util as util - spec = util.find_spec('_testmultiphase') - spec.name = '_testmultiphase_with_bad_traverse' - - with support.SuppressCrashReport(): - m = spec.loader.create_module(spec)""" + try: + from test import support + import importlib.util as util + spec = util.find_spec('_testmultiphase') + spec.name = '_testmultiphase_with_bad_traverse' + + with support.SuppressCrashReport(): + m = spec.loader.create_module(spec) + except: + # Prevent Python-level exceptions from + # ending the process with non-zero status + # (We are testing for a crash in C-code) + pass""" assert_python_failure("-c", script) From webhook-mailer at python.org Mon May 28 08:29:15 2018 From: webhook-mailer at python.org (Vinay Sajip) Date: Mon, 28 May 2018 12:29:15 -0000 Subject: [Python-checkins] bpo-33400: Clarified documentation to indicate no strict adherence to ISO 8601. (GH-6702) (GH-6704) Message-ID: <mailman.6.1527510557.2800.python-checkins@python.org> https://github.com/python/cpython/commit/eb8516becc267caeb0ca6f9c41e805d1ba1caaa3 commit: eb8516becc267caeb0ca6f9c41e805d1ba1caaa3 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Vinay Sajip <vinay_sajip at yahoo.co.uk> date: 2018-05-28T13:29:13+01:00 summary: bpo-33400: Clarified documentation to indicate no strict adherence to ISO 8601. (GH-6702) (GH-6704) (cherry picked from commit c4994dc00d9828a99510f3851da93b0e1c18361d) Co-authored-by: Vinay Sajip <vinay_sajip at yahoo.co.uk> files: M Doc/howto/logging.rst M Doc/library/logging.config.rst M Doc/library/logging.rst M Lib/logging/__init__.py diff --git a/Doc/howto/logging.rst b/Doc/howto/logging.rst index f8b78b618569..e9e5580df969 100644 --- a/Doc/howto/logging.rst +++ b/Doc/howto/logging.rst @@ -296,9 +296,9 @@ which should print something like this: 2010-12-12 11:41:42,612 is when this event was logged. -The default format for date/time display (shown above) is ISO8601. If you need -more control over the formatting of the date/time, provide a *datefmt* -argument to ``basicConfig``, as in this example:: +The default format for date/time display (shown above) is like ISO8601 or +RFC 3339. If you need more control over the formatting of the date/time, provide +a *datefmt* argument to ``basicConfig``, as in this example:: import logging logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p') diff --git a/Doc/library/logging.config.rst b/Doc/library/logging.config.rst index 1f9d7c7f220b..b5007610c40f 100644 --- a/Doc/library/logging.config.rst +++ b/Doc/library/logging.config.rst @@ -790,10 +790,10 @@ Sections which specify formatter configuration are typified by the following. The ``format`` entry is the overall format string, and the ``datefmt`` entry is the :func:`strftime`\ -compatible date/time format string. If empty, the -package substitutes ISO8601 format date/times, which is almost equivalent to -specifying the date format string ``'%Y-%m-%d %H:%M:%S'``. The ISO8601 format -also specifies milliseconds, which are appended to the result of using the above -format string, with a comma separator. An example time in ISO8601 format is +package substitutes ISO8601-style format date/times, which is almost equivalent to +specifying the date format string ``'%Y-%m-%d %H:%M:%S'``. This format also +specifies milliseconds, which are appended to the result of using the above +format string, with a comma separator. An example time in this format is ``2003-01-23 00:29:50,411``. The ``class`` entry is optional. It indicates the name of the formatter's class diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst index f9eda173ad0d..9a54bf9325a0 100644 --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -515,8 +515,9 @@ The useful mapping keys in a :class:`LogRecord` are given in the section on Returns a new instance of the :class:`Formatter` class. The instance is initialized with a format string for the message as a whole, as well as a format string for the date/time portion of a message. If no *fmt* is - specified, ``'%(message)s'`` is used. If no *datefmt* is specified, the - ISO8601 date format is used. + specified, ``'%(message)s'`` is used. If no *datefmt* is specified, an + ISO8601-like (or RFC3339-like) date format is used. See the + :meth:`formatTime` documentation for more details. The *style* parameter can be one of '%', '{' or '$' and determines how the format string will be merged with its data: using one of %-formatting, @@ -556,8 +557,8 @@ The useful mapping keys in a :class:`LogRecord` are given in the section on formatters to provide for any specific requirement, but the basic behavior is as follows: if *datefmt* (a string) is specified, it is used with :func:`time.strftime` to format the creation time of the - record. Otherwise, the ISO8601 format is used. The resulting string is - returned. + record. Otherwise, an ISO8601-like (or RDC 3339-like) format is used. The + resulting string is returned. This function uses a user-configurable function to convert the creation time to a tuple. By default, :func:`time.localtime` is used; to change @@ -568,7 +569,7 @@ The useful mapping keys in a :class:`LogRecord` are given in the section on attribute in the ``Formatter`` class. .. versionchanged:: 3.3 - Previously, the default ISO 8601 format was hard-coded as in this + Previously, the default ISO8601-like format was hard-coded as in this example: ``2010-09-06 22:38:15,292`` where the part before the comma is handled by a strptime format string (``'%Y-%m-%d %H:%M:%S'``), and the part after the comma is a millisecond value. Because strptime does not diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py index 9f2c0f0c58a3..46c590687c7d 100644 --- a/Lib/logging/__init__.py +++ b/Lib/logging/__init__.py @@ -466,7 +466,8 @@ def __init__(self, fmt=None, datefmt=None, style='%'): Initialize the formatter either with the specified format string, or a default as described above. Allow for specialized date formatting with - the optional datefmt argument (if omitted, you get the ISO8601 format). + the optional datefmt argument. If datefmt is omitted, you get an + ISO8601-like (or RFC 3339-like) format. Use a style parameter of '%', '{' or '$' to specify that you want to use one of %-formatting, :meth:`str.format` (``{}``) formatting or @@ -494,13 +495,13 @@ def formatTime(self, record, datefmt=None): in formatters to provide for any specific requirement, but the basic behaviour is as follows: if datefmt (a string) is specified, it is used with time.strftime() to format the creation time of the - record. Otherwise, the ISO8601 format is used. The resulting - string is returned. This function uses a user-configurable function - to convert the creation time to a tuple. By default, time.localtime() - is used; to change this for a particular formatter instance, set the - 'converter' attribute to a function with the same signature as - time.localtime() or time.gmtime(). To change it for all formatters, - for example if you want all logging times to be shown in GMT, + record. Otherwise, an ISO8601-like (or RFC 3339-like) format is used. + The resulting string is returned. This function uses a user-configurable + function to convert the creation time to a tuple. By default, + time.localtime() is used; to change this for a particular formatter + instance, set the 'converter' attribute to a function with the same + signature as time.localtime() or time.gmtime(). To change it for all + formatters, for example if you want all logging times to be shown in GMT, set the 'converter' attribute in the Formatter class. """ ct = self.converter(record.created) From webhook-mailer at python.org Mon May 28 08:52:09 2018 From: webhook-mailer at python.org (Petr Viktorin) Date: Mon, 28 May 2018 12:52:09 -0000 Subject: [Python-checkins] bpo-32374: Ignore Python-level exceptions in test_bad_traverse (GH-7145) (GH-7150) Message-ID: <mailman.7.1527511930.2800.python-checkins@python.org> https://github.com/python/cpython/commit/983c1ba94aef945386001932c5744f8ce9757fec commit: 983c1ba94aef945386001932c5744f8ce9757fec branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Petr Viktorin <encukou at gmail.com> date: 2018-05-28T14:52:03+02:00 summary: bpo-32374: Ignore Python-level exceptions in test_bad_traverse (GH-7145) (GH-7150) (cherry picked from commit 08c5aca9d13b24b35faf89ebd26fc348ae1731b2) Co-authored-by: Marcel Plch <gmarcel.plch at gmail.com> files: M Lib/test/test_importlib/extension/test_loader.py diff --git a/Lib/test/test_importlib/extension/test_loader.py b/Lib/test/test_importlib/extension/test_loader.py index 57ba7083d37d..9ad05fadef29 100644 --- a/Lib/test/test_importlib/extension/test_loader.py +++ b/Lib/test/test_importlib/extension/test_loader.py @@ -275,13 +275,19 @@ def test_bad_traverse(self): (Multiphase initialization modules only) ''' script = """if True: - from test import support - import importlib.util as util - spec = util.find_spec('_testmultiphase') - spec.name = '_testmultiphase_with_bad_traverse' - - with support.SuppressCrashReport(): - m = spec.loader.create_module(spec)""" + try: + from test import support + import importlib.util as util + spec = util.find_spec('_testmultiphase') + spec.name = '_testmultiphase_with_bad_traverse' + + with support.SuppressCrashReport(): + m = spec.loader.create_module(spec) + except: + # Prevent Python-level exceptions from + # ending the process with non-zero status + # (We are testing for a crash in C-code) + pass""" assert_python_failure("-c", script) From webhook-mailer at python.org Mon May 28 11:11:34 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Mon, 28 May 2018 15:11:34 -0000 Subject: [Python-checkins] bpo-33623: Fix possible SIGSGV when asyncio.Future is created in __del__ (#7080) Message-ID: <mailman.8.1527520298.2800.python-checkins@python.org> https://github.com/python/cpython/commit/35230d08e09de4e2e52658d5cb09e5b0ca965418 commit: 35230d08e09de4e2e52658d5cb09e5b0ca965418 branch: master author: Yury Selivanov <yury at magic.io> committer: GitHub <noreply at github.com> date: 2018-05-28T11:11:31-04:00 summary: bpo-33623: Fix possible SIGSGV when asyncio.Future is created in __del__ (#7080) files: A Misc/NEWS.d/next/Library/2018-05-23-14-58-05.bpo-33623.wAw1cF.rst M Modules/_asynciomodule.c diff --git a/Misc/NEWS.d/next/Library/2018-05-23-14-58-05.bpo-33623.wAw1cF.rst b/Misc/NEWS.d/next/Library/2018-05-23-14-58-05.bpo-33623.wAw1cF.rst new file mode 100644 index 000000000000..641874c3ca39 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-23-14-58-05.bpo-33623.wAw1cF.rst @@ -0,0 +1 @@ +Fix possible SIGSGV when asyncio.Future is created in __del__ diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 6d7249a58009..c4d19034ce45 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -501,7 +501,13 @@ future_init(FutureObj *fut, PyObject *loop) if (is_true < 0) { return -1; } - if (is_true) { + if (is_true && !_Py_IsFinalizing()) { + /* Only try to capture the traceback if the interpreter is not being + finalized. The original motivation to add a `_Py_IsFinalizing()` + call was to prevent SIGSEGV when a Future is created in a __del__ + method, which is called during the interpreter shutdown and the + traceback module is already unloaded. + */ fut->fut_source_tb = _PyObject_CallNoArg(traceback_extract_stack); if (fut->fut_source_tb == NULL) { return -1; From webhook-mailer at python.org Mon May 28 11:16:48 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Mon, 28 May 2018 15:16:48 -0000 Subject: [Python-checkins] bpo-31647: Fix write_eof() after close() for SelectorSocketTransport (GH-7149) Message-ID: <mailman.9.1527520611.2800.python-checkins@python.org> https://github.com/python/cpython/commit/23f587e395e41bd5e116312b036183f42bc4159b commit: 23f587e395e41bd5e116312b036183f42bc4159b branch: master author: twisteroid ambassador <twisteroidambassador at users.noreply.github.com> committer: Yury Selivanov <yury at magic.io> date: 2018-05-28T11:16:45-04:00 summary: bpo-31647: Fix write_eof() after close() for SelectorSocketTransport (GH-7149) Fixed bug where calling write_eof() on a _SelectorSocketTransport after it's already closed raises AttributeError. files: A Misc/NEWS.d/next/Library/2018-05-28-18-40-26.bpo-31467.s4Fad3.rst M Lib/asyncio/selector_events.py M Lib/test/test_asyncio/test_selector_events.py diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py index f9533a1d77be..5473c7055212 100644 --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -899,7 +899,7 @@ def _write_ready(self): self._sock.shutdown(socket.SHUT_WR) def write_eof(self): - if self._eof: + if self._closing or self._eof: return self._eof = True if not self._buffer: diff --git a/Lib/test/test_asyncio/test_selector_events.py b/Lib/test/test_asyncio/test_selector_events.py index 684c29dec3e2..5c4ff5745b62 100644 --- a/Lib/test/test_asyncio/test_selector_events.py +++ b/Lib/test/test_asyncio/test_selector_events.py @@ -1263,6 +1263,12 @@ def test_write_eof_buffer(self): self.sock.shutdown.assert_called_with(socket.SHUT_WR) tr.close() + def test_write_eof_after_close(self): + tr = self.socket_transport() + tr.close() + self.loop.run_until_complete(asyncio.sleep(0)) + tr.write_eof() + @mock.patch('asyncio.base_events.logger') def test_transport_close_remove_writer(self, m_log): remove_writer = self.loop._remove_writer = mock.Mock() diff --git a/Misc/NEWS.d/next/Library/2018-05-28-18-40-26.bpo-31467.s4Fad3.rst b/Misc/NEWS.d/next/Library/2018-05-28-18-40-26.bpo-31467.s4Fad3.rst new file mode 100644 index 000000000000..61cc8baa1cd5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-28-18-40-26.bpo-31467.s4Fad3.rst @@ -0,0 +1,2 @@ +Fixed bug where calling write_eof() on a _SelectorSocketTransport after it's +already closed raises AttributeError. From webhook-mailer at python.org Mon May 28 11:28:15 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 28 May 2018 15:28:15 -0000 Subject: [Python-checkins] bpo-33623: Fix possible SIGSGV when asyncio.Future is created in __del__ (GH-7080) Message-ID: <mailman.10.1527521298.2800.python-checkins@python.org> https://github.com/python/cpython/commit/51d0a2c8ddcb9f58d71ff0a62be4e31a1af3f139 commit: 51d0a2c8ddcb9f58d71ff0a62be4e31a1af3f139 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-28T08:28:12-07:00 summary: bpo-33623: Fix possible SIGSGV when asyncio.Future is created in __del__ (GH-7080) (cherry picked from commit 35230d08e09de4e2e52658d5cb09e5b0ca965418) Co-authored-by: Yury Selivanov <yury at magic.io> files: A Misc/NEWS.d/next/Library/2018-05-23-14-58-05.bpo-33623.wAw1cF.rst M Modules/_asynciomodule.c diff --git a/Misc/NEWS.d/next/Library/2018-05-23-14-58-05.bpo-33623.wAw1cF.rst b/Misc/NEWS.d/next/Library/2018-05-23-14-58-05.bpo-33623.wAw1cF.rst new file mode 100644 index 000000000000..641874c3ca39 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-23-14-58-05.bpo-33623.wAw1cF.rst @@ -0,0 +1 @@ +Fix possible SIGSGV when asyncio.Future is created in __del__ diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 6d7249a58009..c4d19034ce45 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -501,7 +501,13 @@ future_init(FutureObj *fut, PyObject *loop) if (is_true < 0) { return -1; } - if (is_true) { + if (is_true && !_Py_IsFinalizing()) { + /* Only try to capture the traceback if the interpreter is not being + finalized. The original motivation to add a `_Py_IsFinalizing()` + call was to prevent SIGSEGV when a Future is created in a __del__ + method, which is called during the interpreter shutdown and the + traceback module is already unloaded. + */ fut->fut_source_tb = _PyObject_CallNoArg(traceback_extract_stack); if (fut->fut_source_tb == NULL) { return -1; From webhook-mailer at python.org Mon May 28 12:04:12 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Mon, 28 May 2018 16:04:12 -0000 Subject: [Python-checkins] bpo-31647: Fix write_eof() after close() for SelectorSocketTransport (GH-7149) (GH-7153) Message-ID: <mailman.11.1527523455.2800.python-checkins@python.org> https://github.com/python/cpython/commit/1f21ae710d83a37c872355612b58958cef4d5f95 commit: 1f21ae710d83a37c872355612b58958cef4d5f95 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Yury Selivanov <yury at magic.io> date: 2018-05-28T12:04:09-04:00 summary: bpo-31647: Fix write_eof() after close() for SelectorSocketTransport (GH-7149) (GH-7153) Fixed bug where calling write_eof() on a _SelectorSocketTransport after it's already closed raises AttributeError. (cherry picked from commit 23f587e395e41bd5e116312b036183f42bc4159b) Co-authored-by: twisteroid ambassador <twisteroidambassador at users.noreply.github.com> files: A Misc/NEWS.d/next/Library/2018-05-28-18-40-26.bpo-31467.s4Fad3.rst M Lib/asyncio/selector_events.py M Lib/test/test_asyncio/test_selector_events.py diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py index f9533a1d77be..5473c7055212 100644 --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -899,7 +899,7 @@ def _write_ready(self): self._sock.shutdown(socket.SHUT_WR) def write_eof(self): - if self._eof: + if self._closing or self._eof: return self._eof = True if not self._buffer: diff --git a/Lib/test/test_asyncio/test_selector_events.py b/Lib/test/test_asyncio/test_selector_events.py index 684c29dec3e2..5c4ff5745b62 100644 --- a/Lib/test/test_asyncio/test_selector_events.py +++ b/Lib/test/test_asyncio/test_selector_events.py @@ -1263,6 +1263,12 @@ def test_write_eof_buffer(self): self.sock.shutdown.assert_called_with(socket.SHUT_WR) tr.close() + def test_write_eof_after_close(self): + tr = self.socket_transport() + tr.close() + self.loop.run_until_complete(asyncio.sleep(0)) + tr.write_eof() + @mock.patch('asyncio.base_events.logger') def test_transport_close_remove_writer(self, m_log): remove_writer = self.loop._remove_writer = mock.Mock() diff --git a/Misc/NEWS.d/next/Library/2018-05-28-18-40-26.bpo-31467.s4Fad3.rst b/Misc/NEWS.d/next/Library/2018-05-28-18-40-26.bpo-31467.s4Fad3.rst new file mode 100644 index 000000000000..61cc8baa1cd5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-28-18-40-26.bpo-31467.s4Fad3.rst @@ -0,0 +1,2 @@ +Fixed bug where calling write_eof() on a _SelectorSocketTransport after it's +already closed raises AttributeError. From webhook-mailer at python.org Mon May 28 12:37:15 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 28 May 2018 16:37:15 -0000 Subject: [Python-checkins] bpo-32374: Ignore Python-level exceptions in test_bad_traverse (GH-7145) Message-ID: <mailman.12.1527525439.2800.python-checkins@python.org> https://github.com/python/cpython/commit/6ec325d48348fb52a421354ba563ff9c1f368054 commit: 6ec325d48348fb52a421354ba563ff9c1f368054 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-28T09:37:10-07:00 summary: bpo-32374: Ignore Python-level exceptions in test_bad_traverse (GH-7145) (cherry picked from commit 08c5aca9d13b24b35faf89ebd26fc348ae1731b2) Co-authored-by: Marcel Plch <gmarcel.plch at gmail.com> files: M Lib/test/test_importlib/extension/test_loader.py diff --git a/Lib/test/test_importlib/extension/test_loader.py b/Lib/test/test_importlib/extension/test_loader.py index 57ba7083d37d..9ad05fadef29 100644 --- a/Lib/test/test_importlib/extension/test_loader.py +++ b/Lib/test/test_importlib/extension/test_loader.py @@ -275,13 +275,19 @@ def test_bad_traverse(self): (Multiphase initialization modules only) ''' script = """if True: - from test import support - import importlib.util as util - spec = util.find_spec('_testmultiphase') - spec.name = '_testmultiphase_with_bad_traverse' - - with support.SuppressCrashReport(): - m = spec.loader.create_module(spec)""" + try: + from test import support + import importlib.util as util + spec = util.find_spec('_testmultiphase') + spec.name = '_testmultiphase_with_bad_traverse' + + with support.SuppressCrashReport(): + m = spec.loader.create_module(spec) + except: + # Prevent Python-level exceptions from + # ending the process with non-zero status + # (We are testing for a crash in C-code) + pass""" assert_python_failure("-c", script) From webhook-mailer at python.org Mon May 28 12:42:08 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Mon, 28 May 2018 16:42:08 -0000 Subject: [Python-checkins] bpo-33505: Optimize asyncio.ensure_future by reordering if conditions (GH-6836) Message-ID: <mailman.13.1527525729.2800.python-checkins@python.org> https://github.com/python/cpython/commit/e549c4be5fb010f5faf12236af8faa720a1429be commit: e549c4be5fb010f5faf12236af8faa720a1429be branch: master author: jimmylai <albert_chs at yahoo.com.tw> committer: Yury Selivanov <yury at magic.io> date: 2018-05-28T12:42:05-04:00 summary: bpo-33505: Optimize asyncio.ensure_future by reordering if conditions (GH-6836) files: A Misc/NEWS.d/next/Library/2018-05-14-18-05-35.bpo-33505.L8pAyt.rst M Lib/asyncio/tasks.py diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index 5df1af6642e4..4a9db2a3a05c 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -542,17 +542,17 @@ def ensure_future(coro_or_future, *, loop=None): If the argument is a Future, it is returned directly. """ - if futures.isfuture(coro_or_future): - if loop is not None and loop is not futures._get_loop(coro_or_future): - raise ValueError('loop argument must agree with Future') - return coro_or_future - elif coroutines.iscoroutine(coro_or_future): + if coroutines.iscoroutine(coro_or_future): if loop is None: loop = events.get_event_loop() task = loop.create_task(coro_or_future) if task._source_traceback: del task._source_traceback[-1] return task + elif futures.isfuture(coro_or_future): + if loop is not None and loop is not futures._get_loop(coro_or_future): + raise ValueError('loop argument must agree with Future') + return coro_or_future elif inspect.isawaitable(coro_or_future): return ensure_future(_wrap_awaitable(coro_or_future), loop=loop) else: diff --git a/Misc/NEWS.d/next/Library/2018-05-14-18-05-35.bpo-33505.L8pAyt.rst b/Misc/NEWS.d/next/Library/2018-05-14-18-05-35.bpo-33505.L8pAyt.rst new file mode 100644 index 000000000000..201b02781c18 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-14-18-05-35.bpo-33505.L8pAyt.rst @@ -0,0 +1 @@ +Optimize asyncio.ensure_future() by reordering if checks: 1.17x faster. From webhook-mailer at python.org Mon May 28 14:31:31 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Mon, 28 May 2018 18:31:31 -0000 Subject: [Python-checkins] bpo-33654: Support BufferedProtocol in set_protocol() and start_tls() (GH-7130) Message-ID: <mailman.14.1527532292.2800.python-checkins@python.org> https://github.com/python/cpython/commit/dbf102271fcc316f353c7e0a283811b661d128f2 commit: dbf102271fcc316f353c7e0a283811b661d128f2 branch: master author: Yury Selivanov <yury at magic.io> committer: GitHub <noreply at github.com> date: 2018-05-28T14:31:28-04:00 summary: bpo-33654: Support BufferedProtocol in set_protocol() and start_tls() (GH-7130) In this commit: * Support BufferedProtocol in set_protocol() and start_tls() * Fix proactor to cancel readers reliably * Update tests to be compatible with OpenSSL 1.1.1 * Clarify BufferedProtocol docs * Bump TLS tests timeouts to 60 seconds; eliminate possible race from start_serving * Rewrite test_start_tls_server_1 files: A Misc/NEWS.d/next/Library/2018-05-26-13-09-34.bpo-33654.IbYWxA.rst M Doc/library/asyncio-protocol.rst M Lib/asyncio/base_events.py M Lib/asyncio/proactor_events.py M Lib/asyncio/protocols.py M Lib/asyncio/selector_events.py M Lib/asyncio/sslproto.py M Lib/asyncio/unix_events.py M Lib/test/test_asyncio/test_buffered_proto.py M Lib/test/test_asyncio/test_events.py M Lib/test/test_asyncio/test_proactor_events.py M Lib/test/test_asyncio/test_selector_events.py M Lib/test/test_asyncio/test_sslproto.py diff --git a/Doc/library/asyncio-protocol.rst b/Doc/library/asyncio-protocol.rst index ef6441605cd7..9a08a4a49021 100644 --- a/Doc/library/asyncio-protocol.rst +++ b/Doc/library/asyncio-protocol.rst @@ -463,16 +463,23 @@ The idea of BufferedProtocol is that it allows to manually allocate and control the receive buffer. Event loops can then use the buffer provided by the protocol to avoid unnecessary data copies. This can result in noticeable performance improvement for protocols that -receive big amounts of data. Sophisticated protocols can allocate -the buffer only once at creation time. +receive big amounts of data. Sophisticated protocols implementations +can allocate the buffer only once at creation time. The following callbacks are called on :class:`BufferedProtocol` instances: -.. method:: BufferedProtocol.get_buffer() +.. method:: BufferedProtocol.get_buffer(sizehint) - Called to allocate a new receive buffer. Must return an object - that implements the :ref:`buffer protocol <bufferobjects>`. + Called to allocate a new receive buffer. + + *sizehint* is a recommended minimal size for the returned + buffer. It is acceptable to return smaller or bigger buffers + than what *sizehint* suggests. When set to -1, the buffer size + can be arbitrary. It is an error to return a zero-sized buffer. + + Must return an object that implements the + :ref:`buffer protocol <bufferobjects>`. .. method:: BufferedProtocol.buffer_updated(nbytes) diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index 09eb440b0ef7..a0243f5bac9a 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -157,7 +157,6 @@ def _run_until_complete_cb(fut): futures._get_loop(fut).stop() - class _SendfileFallbackProtocol(protocols.Protocol): def __init__(self, transp): if not isinstance(transp, transports._FlowControlMixin): @@ -304,6 +303,9 @@ def close(self): async def start_serving(self): self._start_serving() + # Skip one loop iteration so that all 'loop.add_reader' + # go through. + await tasks.sleep(0, loop=self._loop) async def serve_forever(self): if self._serving_forever_fut is not None: @@ -1363,6 +1365,9 @@ def _check_sendfile_params(self, sock, file, offset, count): ssl, backlog, ssl_handshake_timeout) if start_serving: server._start_serving() + # Skip one loop iteration so that all 'loop.add_reader' + # go through. + await tasks.sleep(0, loop=self) if self._debug: logger.info("%r is serving", server) diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py index 877dfb074670..337ed0fb2047 100644 --- a/Lib/asyncio/proactor_events.py +++ b/Lib/asyncio/proactor_events.py @@ -30,7 +30,7 @@ def __init__(self, loop, sock, protocol, waiter=None, super().__init__(extra, loop) self._set_extra(sock) self._sock = sock - self._protocol = protocol + self.set_protocol(protocol) self._server = server self._buffer = None # None or bytearray. self._read_fut = None @@ -159,16 +159,26 @@ class _ProactorReadPipeTransport(_ProactorBasePipeTransport, def __init__(self, loop, sock, protocol, waiter=None, extra=None, server=None): + self._loop_reading_cb = None + self._paused = True super().__init__(loop, sock, protocol, waiter, extra, server) - self._paused = False + self._reschedule_on_resume = False + self._loop.call_soon(self._loop_reading) + self._paused = False - if protocols._is_buffered_protocol(protocol): - self._loop_reading = self._loop_reading__get_buffer + def set_protocol(self, protocol): + if isinstance(protocol, protocols.BufferedProtocol): + self._loop_reading_cb = self._loop_reading__get_buffer else: - self._loop_reading = self._loop_reading__data_received + self._loop_reading_cb = self._loop_reading__data_received - self._loop.call_soon(self._loop_reading) + super().set_protocol(protocol) + + if self.is_reading(): + # reset reading callback / buffers / self._read_fut + self.pause_reading() + self.resume_reading() def is_reading(self): return not self._paused and not self._closing @@ -179,6 +189,13 @@ def pause_reading(self): self._paused = True if self._read_fut is not None and not self._read_fut.done(): + # TODO: This is an ugly hack to cancel the current read future + # *and* avoid potential race conditions, as read cancellation + # goes through `future.cancel()` and `loop.call_soon()`. + # We then use this special attribute in the reader callback to + # exit *immediately* without doing any cleanup/rescheduling. + self._read_fut.__asyncio_cancelled_on_pause__ = True + self._read_fut.cancel() self._read_fut = None self._reschedule_on_resume = True @@ -210,7 +227,14 @@ def _loop_reading__on_eof(self): if not keep_open: self.close() - def _loop_reading__data_received(self, fut=None): + def _loop_reading(self, fut=None): + self._loop_reading_cb(fut) + + def _loop_reading__data_received(self, fut): + if (fut is not None and + getattr(fut, '__asyncio_cancelled_on_pause__', False)): + return + if self._paused: self._reschedule_on_resume = True return @@ -253,14 +277,18 @@ def _loop_reading__data_received(self, fut=None): if not self._closing: raise else: - self._read_fut.add_done_callback(self._loop_reading) + self._read_fut.add_done_callback(self._loop_reading__data_received) finally: if data: self._protocol.data_received(data) elif data == b'': self._loop_reading__on_eof() - def _loop_reading__get_buffer(self, fut=None): + def _loop_reading__get_buffer(self, fut): + if (fut is not None and + getattr(fut, '__asyncio_cancelled_on_pause__', False)): + return + if self._paused: self._reschedule_on_resume = True return @@ -310,7 +338,9 @@ def _loop_reading__get_buffer(self, fut=None): return try: - buf = self._protocol.get_buffer() + buf = self._protocol.get_buffer(-1) + if not len(buf): + raise RuntimeError('get_buffer() returned an empty buffer') except Exception as exc: self._fatal_error( exc, 'Fatal error: protocol.get_buffer() call failed.') @@ -319,7 +349,7 @@ def _loop_reading__get_buffer(self, fut=None): try: # schedule a new read self._read_fut = self._loop._proactor.recv_into(self._sock, buf) - self._read_fut.add_done_callback(self._loop_reading) + self._read_fut.add_done_callback(self._loop_reading__get_buffer) except ConnectionAbortedError as exc: if not self._closing: self._fatal_error(exc, 'Fatal read error on pipe transport') diff --git a/Lib/asyncio/protocols.py b/Lib/asyncio/protocols.py index dc298a8d5c95..b8d2e6be552e 100644 --- a/Lib/asyncio/protocols.py +++ b/Lib/asyncio/protocols.py @@ -130,11 +130,15 @@ class BufferedProtocol(BaseProtocol): * CL: connection_lost() """ - def get_buffer(self): + def get_buffer(self, sizehint): """Called to allocate a new receive buffer. + *sizehint* is a recommended minimal size for the returned + buffer. When set to -1, the buffer size can be arbitrary. + Must return an object that implements the :ref:`buffer protocol <bufferobjects>`. + It is an error to return a zero-sized buffer. """ def buffer_updated(self, nbytes): @@ -185,7 +189,3 @@ def pipe_connection_lost(self, fd, exc): def process_exited(self): """Called when subprocess has exited.""" - - -def _is_buffered_protocol(proto): - return hasattr(proto, 'get_buffer') and not hasattr(proto, 'data_received') diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py index 5473c7055212..116c08d6ff7f 100644 --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -597,8 +597,10 @@ def __init__(self, loop, sock, protocol, extra=None, server=None): self._extra['peername'] = None self._sock = sock self._sock_fd = sock.fileno() - self._protocol = protocol - self._protocol_connected = True + + self._protocol_connected = False + self.set_protocol(protocol) + self._server = server self._buffer = self._buffer_factory() self._conn_lost = 0 # Set when call to connection_lost scheduled. @@ -640,6 +642,7 @@ def abort(self): def set_protocol(self, protocol): self._protocol = protocol + self._protocol_connected = True def get_protocol(self): return self._protocol @@ -721,11 +724,7 @@ class _SelectorSocketTransport(_SelectorTransport): def __init__(self, loop, sock, protocol, waiter=None, extra=None, server=None): - if protocols._is_buffered_protocol(protocol): - self._read_ready = self._read_ready__get_buffer - else: - self._read_ready = self._read_ready__data_received - + self._read_ready_cb = None super().__init__(loop, sock, protocol, extra, server) self._eof = False self._paused = False @@ -745,6 +744,14 @@ def __init__(self, loop, sock, protocol, waiter=None, self._loop.call_soon(futures._set_result_unless_cancelled, waiter, None) + def set_protocol(self, protocol): + if isinstance(protocol, protocols.BufferedProtocol): + self._read_ready_cb = self._read_ready__get_buffer + else: + self._read_ready_cb = self._read_ready__data_received + + super().set_protocol(protocol) + def is_reading(self): return not self._paused and not self._closing @@ -764,12 +771,17 @@ def resume_reading(self): if self._loop.get_debug(): logger.debug("%r resumes reading", self) + def _read_ready(self): + self._read_ready_cb() + def _read_ready__get_buffer(self): if self._conn_lost: return try: - buf = self._protocol.get_buffer() + buf = self._protocol.get_buffer(-1) + if not len(buf): + raise RuntimeError('get_buffer() returned an empty buffer') except Exception as exc: self._fatal_error( exc, 'Fatal error: protocol.get_buffer() call failed.') diff --git a/Lib/asyncio/sslproto.py b/Lib/asyncio/sslproto.py index 2bbf134c0f7e..2bfa45dd1585 100644 --- a/Lib/asyncio/sslproto.py +++ b/Lib/asyncio/sslproto.py @@ -441,6 +441,8 @@ def __init__(self, loop, app_protocol, sslcontext, waiter, self._waiter = waiter self._loop = loop self._app_protocol = app_protocol + self._app_protocol_is_buffer = \ + isinstance(app_protocol, protocols.BufferedProtocol) self._app_transport = _SSLProtocolTransport(self._loop, self) # _SSLPipe instance (None until the connection is made) self._sslpipe = None @@ -522,7 +524,16 @@ def data_received(self, data): for chunk in appdata: if chunk: - self._app_protocol.data_received(chunk) + try: + if self._app_protocol_is_buffer: + _feed_data_to_bufferred_proto( + self._app_protocol, chunk) + else: + self._app_protocol.data_received(chunk) + except Exception as ex: + self._fatal_error( + ex, 'application protocol failed to receive SSL data') + return else: self._start_shutdown() break @@ -709,3 +720,22 @@ def _abort(self): self._transport.abort() finally: self._finalize() + + +def _feed_data_to_bufferred_proto(proto, data): + data_len = len(data) + while data_len: + buf = proto.get_buffer(data_len) + buf_len = len(buf) + if not buf_len: + raise RuntimeError('get_buffer() returned an empty buffer') + + if buf_len >= data_len: + buf[:data_len] = data + proto.buffer_updated(data_len) + return + else: + buf[:buf_len] = data[:buf_len] + proto.buffer_updated(buf_len) + data = data[buf_len:] + data_len = len(data) diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py index f64037a25c67..7cad7e3637a1 100644 --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -20,6 +20,7 @@ from . import events from . import futures from . import selector_events +from . import tasks from . import transports from .log import logger @@ -308,6 +309,9 @@ def _child_watcher_callback(self, pid, returncode, transp): ssl, backlog, ssl_handshake_timeout) if start_serving: server._start_serving() + # Skip one loop iteration so that all 'loop.add_reader' + # go through. + await tasks.sleep(0, loop=self) return server diff --git a/Lib/test/test_asyncio/test_buffered_proto.py b/Lib/test/test_asyncio/test_buffered_proto.py index 22f9269e814f..89d3df72d98b 100644 --- a/Lib/test/test_asyncio/test_buffered_proto.py +++ b/Lib/test/test_asyncio/test_buffered_proto.py @@ -9,7 +9,7 @@ def __init__(self, cb, con_lost_fut): self.cb = cb self.con_lost_fut = con_lost_fut - def get_buffer(self): + def get_buffer(self, sizehint): self.buffer = bytearray(100) return self.buffer diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index 64d726d16d1c..d7b0a665a0ab 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -2095,7 +2095,7 @@ def test_subprocess_shell_invalid_args(self): class SendfileBase: - DATA = b"12345abcde" * 16 * 1024 # 160 KiB + DATA = b"12345abcde" * 64 * 1024 # 64 KiB (don't use smaller sizes) @classmethod def setUpClass(cls): @@ -2452,7 +2452,7 @@ def test_sendfile_ssl_close_peer_after_receiving(self): self.assertEqual(srv_proto.data, self.DATA) self.assertEqual(self.file.tell(), len(self.DATA)) - def test_sendfile_close_peer_in_middle_of_receiving(self): + def test_sendfile_close_peer_in_the_middle_of_receiving(self): srv_proto, cli_proto = self.prepare_sendfile(close_after=1024) with self.assertRaises(ConnectionError): self.run_loop( @@ -2465,7 +2465,7 @@ def test_sendfile_close_peer_in_middle_of_receiving(self): self.file.tell()) self.assertTrue(cli_proto.transport.is_closing()) - def test_sendfile_fallback_close_peer_in_middle_of_receiving(self): + def test_sendfile_fallback_close_peer_in_the_middle_of_receiving(self): def sendfile_native(transp, file, offset, count): # to raise SendfileNotAvailableError diff --git a/Lib/test/test_asyncio/test_proactor_events.py b/Lib/test/test_asyncio/test_proactor_events.py index 6313d594477a..6da6b4a34db8 100644 --- a/Lib/test/test_asyncio/test_proactor_events.py +++ b/Lib/test/test_asyncio/test_proactor_events.py @@ -465,8 +465,8 @@ def setUp(self): self.loop._proactor = self.proactor self.protocol = test_utils.make_test_protocol(asyncio.BufferedProtocol) - self.buf = mock.Mock() - self.protocol.get_buffer.side_effect = lambda: self.buf + self.buf = bytearray(1) + self.protocol.get_buffer.side_effect = lambda hint: self.buf self.sock = mock.Mock(socket.socket) @@ -505,6 +505,64 @@ def test_get_buffer_error(self): self.assertTrue(self.protocol.get_buffer.called) self.assertFalse(self.protocol.buffer_updated.called) + def test_get_buffer_zerosized(self): + transport = self.socket_transport() + transport._fatal_error = mock.Mock() + + self.loop.call_exception_handler = mock.Mock() + self.protocol.get_buffer.side_effect = lambda hint: bytearray(0) + + transport._loop_reading() + + self.assertTrue(transport._fatal_error.called) + self.assertTrue(self.protocol.get_buffer.called) + self.assertFalse(self.protocol.buffer_updated.called) + + def test_proto_type_switch(self): + self.protocol = test_utils.make_test_protocol(asyncio.Protocol) + tr = self.socket_transport() + + res = asyncio.Future(loop=self.loop) + res.set_result(b'data') + + tr = self.socket_transport() + tr._read_fut = res + tr._loop_reading(res) + self.loop._proactor.recv.assert_called_with(self.sock, 32768) + self.protocol.data_received.assert_called_with(b'data') + + # switch protocol to a BufferedProtocol + + buf_proto = test_utils.make_test_protocol(asyncio.BufferedProtocol) + buf = bytearray(4) + buf_proto.get_buffer.side_effect = lambda hint: buf + + tr.set_protocol(buf_proto) + test_utils.run_briefly(self.loop) + res = asyncio.Future(loop=self.loop) + res.set_result(4) + + tr._read_fut = res + tr._loop_reading(res) + self.loop._proactor.recv_into.assert_called_with(self.sock, buf) + buf_proto.buffer_updated.assert_called_with(4) + + def test_proto_buf_switch(self): + tr = self.socket_transport() + test_utils.run_briefly(self.loop) + self.protocol.get_buffer.assert_called_with(-1) + + # switch protocol to *another* BufferedProtocol + + buf_proto = test_utils.make_test_protocol(asyncio.BufferedProtocol) + buf = bytearray(4) + buf_proto.get_buffer.side_effect = lambda hint: buf + tr._read_fut.done.side_effect = lambda: False + tr.set_protocol(buf_proto) + self.assertFalse(buf_proto.get_buffer.called) + test_utils.run_briefly(self.loop) + buf_proto.get_buffer.assert_called_with(-1) + def test_buffer_updated_error(self): transport = self.socket_transport() transport._fatal_error = mock.Mock() diff --git a/Lib/test/test_asyncio/test_selector_events.py b/Lib/test/test_asyncio/test_selector_events.py index 5c4ff5745b62..68b6ee9abbf1 100644 --- a/Lib/test/test_asyncio/test_selector_events.py +++ b/Lib/test/test_asyncio/test_selector_events.py @@ -772,7 +772,8 @@ def test_accept_connection_multiple(self): accept2_mock.return_value = None with mock_obj(self.loop, 'create_task') as task_mock: task_mock.return_value = None - self.loop._accept_connection(mock.Mock(), sock, backlog=backlog) + self.loop._accept_connection( + mock.Mock(), sock, backlog=backlog) self.assertEqual(sock.accept.call_count, backlog) @@ -1285,8 +1286,8 @@ def setUp(self): self.loop = self.new_test_loop() self.protocol = test_utils.make_test_protocol(asyncio.BufferedProtocol) - self.buf = mock.Mock() - self.protocol.get_buffer.side_effect = lambda: self.buf + self.buf = bytearray(1) + self.protocol.get_buffer.side_effect = lambda hint: self.buf self.sock = mock.Mock(socket.socket) self.sock_fd = self.sock.fileno.return_value = 7 @@ -1319,6 +1320,42 @@ def test_get_buffer_error(self): self.assertTrue(self.protocol.get_buffer.called) self.assertFalse(self.protocol.buffer_updated.called) + def test_get_buffer_zerosized(self): + transport = self.socket_transport() + transport._fatal_error = mock.Mock() + + self.loop.call_exception_handler = mock.Mock() + self.protocol.get_buffer.side_effect = lambda hint: bytearray(0) + + transport._read_ready() + + self.assertTrue(transport._fatal_error.called) + self.assertTrue(self.protocol.get_buffer.called) + self.assertFalse(self.protocol.buffer_updated.called) + + def test_proto_type_switch(self): + self.protocol = test_utils.make_test_protocol(asyncio.Protocol) + transport = self.socket_transport() + + self.sock.recv.return_value = b'data' + transport._read_ready() + + self.protocol.data_received.assert_called_with(b'data') + + # switch protocol to a BufferedProtocol + + buf_proto = test_utils.make_test_protocol(asyncio.BufferedProtocol) + buf = bytearray(4) + buf_proto.get_buffer.side_effect = lambda hint: buf + + transport.set_protocol(buf_proto) + + self.sock.recv_into.return_value = 10 + transport._read_ready() + + buf_proto.get_buffer.assert_called_with(-1) + buf_proto.buffer_updated.assert_called_with(10) + def test_buffer_updated_error(self): transport = self.socket_transport() transport._fatal_error = mock.Mock() @@ -1354,7 +1391,7 @@ def test_read_ready(self): self.sock.recv_into.return_value = 10 transport._read_ready() - self.protocol.get_buffer.assert_called_with() + self.protocol.get_buffer.assert_called_with(-1) self.protocol.buffer_updated.assert_called_with(10) def test_read_ready_eof(self): diff --git a/Lib/test/test_asyncio/test_sslproto.py b/Lib/test/test_asyncio/test_sslproto.py index c534a341352b..932487a9e3c6 100644 --- a/Lib/test/test_asyncio/test_sslproto.py +++ b/Lib/test/test_asyncio/test_sslproto.py @@ -1,8 +1,7 @@ """Tests for asyncio/sslproto.py.""" -import os import logging -import time +import socket import unittest from unittest import mock try: @@ -185,17 +184,67 @@ def test_write_after_closing(self): class BaseStartTLS(func_tests.FunctionalTestCaseMixin): + PAYLOAD_SIZE = 1024 * 100 + TIMEOUT = 60 + def new_loop(self): raise NotImplementedError - def test_start_tls_client_1(self): - HELLO_MSG = b'1' * 1024 * 1024 + def test_buf_feed_data(self): + + class Proto(asyncio.BufferedProtocol): + + def __init__(self, bufsize, usemv): + self.buf = bytearray(bufsize) + self.mv = memoryview(self.buf) + self.data = b'' + self.usemv = usemv + + def get_buffer(self, sizehint): + if self.usemv: + return self.mv + else: + return self.buf + + def buffer_updated(self, nsize): + if self.usemv: + self.data += self.mv[:nsize] + else: + self.data += self.buf[:nsize] + + for usemv in [False, True]: + proto = Proto(1, usemv) + sslproto._feed_data_to_bufferred_proto(proto, b'12345') + self.assertEqual(proto.data, b'12345') + + proto = Proto(2, usemv) + sslproto._feed_data_to_bufferred_proto(proto, b'12345') + self.assertEqual(proto.data, b'12345') + + proto = Proto(2, usemv) + sslproto._feed_data_to_bufferred_proto(proto, b'1234') + self.assertEqual(proto.data, b'1234') + + proto = Proto(4, usemv) + sslproto._feed_data_to_bufferred_proto(proto, b'1234') + self.assertEqual(proto.data, b'1234') + + proto = Proto(100, usemv) + sslproto._feed_data_to_bufferred_proto(proto, b'12345') + self.assertEqual(proto.data, b'12345') + + proto = Proto(0, usemv) + with self.assertRaisesRegex(RuntimeError, 'empty buffer'): + sslproto._feed_data_to_bufferred_proto(proto, b'12345') + + def test_start_tls_client_reg_proto_1(self): + HELLO_MSG = b'1' * self.PAYLOAD_SIZE server_context = test_utils.simple_server_sslcontext() client_context = test_utils.simple_client_sslcontext() def serve(sock): - sock.settimeout(5) + sock.settimeout(self.TIMEOUT) data = sock.recv_all(len(HELLO_MSG)) self.assertEqual(len(data), len(HELLO_MSG)) @@ -205,6 +254,8 @@ def serve(sock): sock.sendall(b'O') data = sock.recv_all(len(HELLO_MSG)) self.assertEqual(len(data), len(HELLO_MSG)) + + sock.shutdown(socket.SHUT_RDWR) sock.close() class ClientProto(asyncio.Protocol): @@ -246,17 +297,80 @@ def eof_received(self): self.loop.run_until_complete( asyncio.wait_for(client(srv.addr), loop=self.loop, timeout=10)) + def test_start_tls_client_buf_proto_1(self): + HELLO_MSG = b'1' * self.PAYLOAD_SIZE + + server_context = test_utils.simple_server_sslcontext() + client_context = test_utils.simple_client_sslcontext() + + def serve(sock): + sock.settimeout(self.TIMEOUT) + + data = sock.recv_all(len(HELLO_MSG)) + self.assertEqual(len(data), len(HELLO_MSG)) + + sock.start_tls(server_context, server_side=True) + + sock.sendall(b'O') + data = sock.recv_all(len(HELLO_MSG)) + self.assertEqual(len(data), len(HELLO_MSG)) + + sock.shutdown(socket.SHUT_RDWR) + sock.close() + + class ClientProto(asyncio.BufferedProtocol): + def __init__(self, on_data, on_eof): + self.on_data = on_data + self.on_eof = on_eof + self.con_made_cnt = 0 + self.buf = bytearray(1) + + def connection_made(proto, tr): + proto.con_made_cnt += 1 + # Ensure connection_made gets called only once. + self.assertEqual(proto.con_made_cnt, 1) + + def get_buffer(self, sizehint): + return self.buf + + def buffer_updated(self, nsize): + assert nsize == 1 + self.on_data.set_result(bytes(self.buf[:nsize])) + + def eof_received(self): + self.on_eof.set_result(True) + + async def client(addr): + await asyncio.sleep(0.5, loop=self.loop) + + on_data = self.loop.create_future() + on_eof = self.loop.create_future() + + tr, proto = await self.loop.create_connection( + lambda: ClientProto(on_data, on_eof), *addr) + + tr.write(HELLO_MSG) + new_tr = await self.loop.start_tls(tr, proto, client_context) + + self.assertEqual(await on_data, b'O') + new_tr.write(HELLO_MSG) + await on_eof + + new_tr.close() + + with self.tcp_server(serve) as srv: + self.loop.run_until_complete( + asyncio.wait_for(client(srv.addr), + loop=self.loop, timeout=self.TIMEOUT)) + def test_start_tls_server_1(self): - HELLO_MSG = b'1' * 1024 * 1024 + HELLO_MSG = b'1' * self.PAYLOAD_SIZE server_context = test_utils.simple_server_sslcontext() client_context = test_utils.simple_client_sslcontext() - # TODO: fix TLSv1.3 support - client_context.options |= ssl.OP_NO_TLSv1_3 def client(sock, addr): - time.sleep(0.5) - sock.settimeout(5) + sock.settimeout(self.TIMEOUT) sock.connect(addr) data = sock.recv_all(len(HELLO_MSG)) @@ -264,12 +378,15 @@ def client(sock, addr): sock.start_tls(client_context) sock.sendall(HELLO_MSG) + + sock.shutdown(socket.SHUT_RDWR) sock.close() class ServerProto(asyncio.Protocol): - def __init__(self, on_con, on_eof): + def __init__(self, on_con, on_eof, on_con_lost): self.on_con = on_con self.on_eof = on_eof + self.on_con_lost = on_con_lost self.data = b'' def connection_made(self, tr): @@ -281,7 +398,13 @@ def data_received(self, data): def eof_received(self): self.on_eof.set_result(1) - async def main(): + def connection_lost(self, exc): + if exc is None: + self.on_con_lost.set_result(None) + else: + self.on_con_lost.set_exception(exc) + + async def main(proto, on_con, on_eof, on_con_lost): tr = await on_con tr.write(HELLO_MSG) @@ -292,24 +415,29 @@ def eof_received(self): server_side=True) await on_eof + await on_con_lost self.assertEqual(proto.data, HELLO_MSG) new_tr.close() - server.close() - await server.wait_closed() + async def run_main(): + on_con = self.loop.create_future() + on_eof = self.loop.create_future() + on_con_lost = self.loop.create_future() + proto = ServerProto(on_con, on_eof, on_con_lost) - on_con = self.loop.create_future() - on_eof = self.loop.create_future() - proto = ServerProto(on_con, on_eof) + server = await self.loop.create_server( + lambda: proto, '127.0.0.1', 0) + addr = server.sockets[0].getsockname() - server = self.loop.run_until_complete( - self.loop.create_server( - lambda: proto, '127.0.0.1', 0)) - addr = server.sockets[0].getsockname() + with self.tcp_client(lambda sock: client(sock, addr)): + await asyncio.wait_for( + main(proto, on_con, on_eof, on_con_lost), + loop=self.loop, timeout=self.TIMEOUT) - with self.tcp_client(lambda sock: client(sock, addr)): - self.loop.run_until_complete( - asyncio.wait_for(main(), loop=self.loop, timeout=10)) + server.close() + await server.wait_closed() + + self.loop.run_until_complete(run_main()) def test_start_tls_wrong_args(self): async def main(): @@ -332,7 +460,6 @@ def new_loop(self): @unittest.skipIf(ssl is None, 'No ssl module') @unittest.skipUnless(hasattr(asyncio, 'ProactorEventLoop'), 'Windows only') - at unittest.skipIf(os.environ.get('APPVEYOR'), 'XXX: issue 32458') class ProactorStartTLSTests(BaseStartTLS, unittest.TestCase): def new_loop(self): diff --git a/Misc/NEWS.d/next/Library/2018-05-26-13-09-34.bpo-33654.IbYWxA.rst b/Misc/NEWS.d/next/Library/2018-05-26-13-09-34.bpo-33654.IbYWxA.rst new file mode 100644 index 000000000000..3ae506ddc55f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-26-13-09-34.bpo-33654.IbYWxA.rst @@ -0,0 +1,3 @@ +Fix transport.set_protocol() to support switching between asyncio.Protocol +and asyncio.BufferedProtocol. Fix loop.start_tls() to work with +asyncio.BufferedProtocols. From webhook-mailer at python.org Mon May 28 14:42:53 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Mon, 28 May 2018 18:42:53 -0000 Subject: [Python-checkins] bpo-33505: Optimize asyncio.ensure_future by reordering if conditions (GH-6836) (#7162) Message-ID: <mailman.15.1527532978.2800.python-checkins@python.org> https://github.com/python/cpython/commit/f8fdb368e3d8d048bffc248fbe1023651c276671 commit: f8fdb368e3d8d048bffc248fbe1023651c276671 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Yury Selivanov <yury at magic.io> date: 2018-05-28T14:42:50-04:00 summary: bpo-33505: Optimize asyncio.ensure_future by reordering if conditions (GH-6836) (#7162) (cherry picked from commit e549c4be5fb010f5faf12236af8faa720a1429be) Co-authored-by: jimmylai <albert_chs at yahoo.com.tw> files: A Misc/NEWS.d/next/Library/2018-05-14-18-05-35.bpo-33505.L8pAyt.rst M Lib/asyncio/tasks.py diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index 5df1af6642e4..4a9db2a3a05c 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -542,17 +542,17 @@ def ensure_future(coro_or_future, *, loop=None): If the argument is a Future, it is returned directly. """ - if futures.isfuture(coro_or_future): - if loop is not None and loop is not futures._get_loop(coro_or_future): - raise ValueError('loop argument must agree with Future') - return coro_or_future - elif coroutines.iscoroutine(coro_or_future): + if coroutines.iscoroutine(coro_or_future): if loop is None: loop = events.get_event_loop() task = loop.create_task(coro_or_future) if task._source_traceback: del task._source_traceback[-1] return task + elif futures.isfuture(coro_or_future): + if loop is not None and loop is not futures._get_loop(coro_or_future): + raise ValueError('loop argument must agree with Future') + return coro_or_future elif inspect.isawaitable(coro_or_future): return ensure_future(_wrap_awaitable(coro_or_future), loop=loop) else: diff --git a/Misc/NEWS.d/next/Library/2018-05-14-18-05-35.bpo-33505.L8pAyt.rst b/Misc/NEWS.d/next/Library/2018-05-14-18-05-35.bpo-33505.L8pAyt.rst new file mode 100644 index 000000000000..201b02781c18 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-14-18-05-35.bpo-33505.L8pAyt.rst @@ -0,0 +1 @@ +Optimize asyncio.ensure_future() by reordering if checks: 1.17x faster. From webhook-mailer at python.org Mon May 28 14:50:48 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 28 May 2018 18:50:48 -0000 Subject: [Python-checkins] bpo-33654: Support BufferedProtocol in set_protocol() and start_tls() (GH-7130) Message-ID: <mailman.16.1527533451.2800.python-checkins@python.org> https://github.com/python/cpython/commit/bc3a002e7d5a921e233a5ee0b0f5610c6510b647 commit: bc3a002e7d5a921e233a5ee0b0f5610c6510b647 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-28T11:50:45-07:00 summary: bpo-33654: Support BufferedProtocol in set_protocol() and start_tls() (GH-7130) In this commit: * Support BufferedProtocol in set_protocol() and start_tls() * Fix proactor to cancel readers reliably * Update tests to be compatible with OpenSSL 1.1.1 * Clarify BufferedProtocol docs * Bump TLS tests timeouts to 60 seconds; eliminate possible race from start_serving * Rewrite test_start_tls_server_1 (cherry picked from commit dbf102271fcc316f353c7e0a283811b661d128f2) Co-authored-by: Yury Selivanov <yury at magic.io> files: A Misc/NEWS.d/next/Library/2018-05-26-13-09-34.bpo-33654.IbYWxA.rst M Doc/library/asyncio-protocol.rst M Lib/asyncio/base_events.py M Lib/asyncio/proactor_events.py M Lib/asyncio/protocols.py M Lib/asyncio/selector_events.py M Lib/asyncio/sslproto.py M Lib/asyncio/unix_events.py M Lib/test/test_asyncio/test_buffered_proto.py M Lib/test/test_asyncio/test_events.py M Lib/test/test_asyncio/test_proactor_events.py M Lib/test/test_asyncio/test_selector_events.py M Lib/test/test_asyncio/test_sslproto.py diff --git a/Doc/library/asyncio-protocol.rst b/Doc/library/asyncio-protocol.rst index ef6441605cd7..9a08a4a49021 100644 --- a/Doc/library/asyncio-protocol.rst +++ b/Doc/library/asyncio-protocol.rst @@ -463,16 +463,23 @@ The idea of BufferedProtocol is that it allows to manually allocate and control the receive buffer. Event loops can then use the buffer provided by the protocol to avoid unnecessary data copies. This can result in noticeable performance improvement for protocols that -receive big amounts of data. Sophisticated protocols can allocate -the buffer only once at creation time. +receive big amounts of data. Sophisticated protocols implementations +can allocate the buffer only once at creation time. The following callbacks are called on :class:`BufferedProtocol` instances: -.. method:: BufferedProtocol.get_buffer() +.. method:: BufferedProtocol.get_buffer(sizehint) - Called to allocate a new receive buffer. Must return an object - that implements the :ref:`buffer protocol <bufferobjects>`. + Called to allocate a new receive buffer. + + *sizehint* is a recommended minimal size for the returned + buffer. It is acceptable to return smaller or bigger buffers + than what *sizehint* suggests. When set to -1, the buffer size + can be arbitrary. It is an error to return a zero-sized buffer. + + Must return an object that implements the + :ref:`buffer protocol <bufferobjects>`. .. method:: BufferedProtocol.buffer_updated(nbytes) diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index 09eb440b0ef7..a0243f5bac9a 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -157,7 +157,6 @@ def _run_until_complete_cb(fut): futures._get_loop(fut).stop() - class _SendfileFallbackProtocol(protocols.Protocol): def __init__(self, transp): if not isinstance(transp, transports._FlowControlMixin): @@ -304,6 +303,9 @@ def close(self): async def start_serving(self): self._start_serving() + # Skip one loop iteration so that all 'loop.add_reader' + # go through. + await tasks.sleep(0, loop=self._loop) async def serve_forever(self): if self._serving_forever_fut is not None: @@ -1363,6 +1365,9 @@ def _check_sendfile_params(self, sock, file, offset, count): ssl, backlog, ssl_handshake_timeout) if start_serving: server._start_serving() + # Skip one loop iteration so that all 'loop.add_reader' + # go through. + await tasks.sleep(0, loop=self) if self._debug: logger.info("%r is serving", server) diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py index 877dfb074670..337ed0fb2047 100644 --- a/Lib/asyncio/proactor_events.py +++ b/Lib/asyncio/proactor_events.py @@ -30,7 +30,7 @@ def __init__(self, loop, sock, protocol, waiter=None, super().__init__(extra, loop) self._set_extra(sock) self._sock = sock - self._protocol = protocol + self.set_protocol(protocol) self._server = server self._buffer = None # None or bytearray. self._read_fut = None @@ -159,16 +159,26 @@ class _ProactorReadPipeTransport(_ProactorBasePipeTransport, def __init__(self, loop, sock, protocol, waiter=None, extra=None, server=None): + self._loop_reading_cb = None + self._paused = True super().__init__(loop, sock, protocol, waiter, extra, server) - self._paused = False + self._reschedule_on_resume = False + self._loop.call_soon(self._loop_reading) + self._paused = False - if protocols._is_buffered_protocol(protocol): - self._loop_reading = self._loop_reading__get_buffer + def set_protocol(self, protocol): + if isinstance(protocol, protocols.BufferedProtocol): + self._loop_reading_cb = self._loop_reading__get_buffer else: - self._loop_reading = self._loop_reading__data_received + self._loop_reading_cb = self._loop_reading__data_received - self._loop.call_soon(self._loop_reading) + super().set_protocol(protocol) + + if self.is_reading(): + # reset reading callback / buffers / self._read_fut + self.pause_reading() + self.resume_reading() def is_reading(self): return not self._paused and not self._closing @@ -179,6 +189,13 @@ def pause_reading(self): self._paused = True if self._read_fut is not None and not self._read_fut.done(): + # TODO: This is an ugly hack to cancel the current read future + # *and* avoid potential race conditions, as read cancellation + # goes through `future.cancel()` and `loop.call_soon()`. + # We then use this special attribute in the reader callback to + # exit *immediately* without doing any cleanup/rescheduling. + self._read_fut.__asyncio_cancelled_on_pause__ = True + self._read_fut.cancel() self._read_fut = None self._reschedule_on_resume = True @@ -210,7 +227,14 @@ def _loop_reading__on_eof(self): if not keep_open: self.close() - def _loop_reading__data_received(self, fut=None): + def _loop_reading(self, fut=None): + self._loop_reading_cb(fut) + + def _loop_reading__data_received(self, fut): + if (fut is not None and + getattr(fut, '__asyncio_cancelled_on_pause__', False)): + return + if self._paused: self._reschedule_on_resume = True return @@ -253,14 +277,18 @@ def _loop_reading__data_received(self, fut=None): if not self._closing: raise else: - self._read_fut.add_done_callback(self._loop_reading) + self._read_fut.add_done_callback(self._loop_reading__data_received) finally: if data: self._protocol.data_received(data) elif data == b'': self._loop_reading__on_eof() - def _loop_reading__get_buffer(self, fut=None): + def _loop_reading__get_buffer(self, fut): + if (fut is not None and + getattr(fut, '__asyncio_cancelled_on_pause__', False)): + return + if self._paused: self._reschedule_on_resume = True return @@ -310,7 +338,9 @@ def _loop_reading__get_buffer(self, fut=None): return try: - buf = self._protocol.get_buffer() + buf = self._protocol.get_buffer(-1) + if not len(buf): + raise RuntimeError('get_buffer() returned an empty buffer') except Exception as exc: self._fatal_error( exc, 'Fatal error: protocol.get_buffer() call failed.') @@ -319,7 +349,7 @@ def _loop_reading__get_buffer(self, fut=None): try: # schedule a new read self._read_fut = self._loop._proactor.recv_into(self._sock, buf) - self._read_fut.add_done_callback(self._loop_reading) + self._read_fut.add_done_callback(self._loop_reading__get_buffer) except ConnectionAbortedError as exc: if not self._closing: self._fatal_error(exc, 'Fatal read error on pipe transport') diff --git a/Lib/asyncio/protocols.py b/Lib/asyncio/protocols.py index dc298a8d5c95..b8d2e6be552e 100644 --- a/Lib/asyncio/protocols.py +++ b/Lib/asyncio/protocols.py @@ -130,11 +130,15 @@ class BufferedProtocol(BaseProtocol): * CL: connection_lost() """ - def get_buffer(self): + def get_buffer(self, sizehint): """Called to allocate a new receive buffer. + *sizehint* is a recommended minimal size for the returned + buffer. When set to -1, the buffer size can be arbitrary. + Must return an object that implements the :ref:`buffer protocol <bufferobjects>`. + It is an error to return a zero-sized buffer. """ def buffer_updated(self, nbytes): @@ -185,7 +189,3 @@ def pipe_connection_lost(self, fd, exc): def process_exited(self): """Called when subprocess has exited.""" - - -def _is_buffered_protocol(proto): - return hasattr(proto, 'get_buffer') and not hasattr(proto, 'data_received') diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py index 5473c7055212..116c08d6ff7f 100644 --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -597,8 +597,10 @@ def __init__(self, loop, sock, protocol, extra=None, server=None): self._extra['peername'] = None self._sock = sock self._sock_fd = sock.fileno() - self._protocol = protocol - self._protocol_connected = True + + self._protocol_connected = False + self.set_protocol(protocol) + self._server = server self._buffer = self._buffer_factory() self._conn_lost = 0 # Set when call to connection_lost scheduled. @@ -640,6 +642,7 @@ def abort(self): def set_protocol(self, protocol): self._protocol = protocol + self._protocol_connected = True def get_protocol(self): return self._protocol @@ -721,11 +724,7 @@ class _SelectorSocketTransport(_SelectorTransport): def __init__(self, loop, sock, protocol, waiter=None, extra=None, server=None): - if protocols._is_buffered_protocol(protocol): - self._read_ready = self._read_ready__get_buffer - else: - self._read_ready = self._read_ready__data_received - + self._read_ready_cb = None super().__init__(loop, sock, protocol, extra, server) self._eof = False self._paused = False @@ -745,6 +744,14 @@ def __init__(self, loop, sock, protocol, waiter=None, self._loop.call_soon(futures._set_result_unless_cancelled, waiter, None) + def set_protocol(self, protocol): + if isinstance(protocol, protocols.BufferedProtocol): + self._read_ready_cb = self._read_ready__get_buffer + else: + self._read_ready_cb = self._read_ready__data_received + + super().set_protocol(protocol) + def is_reading(self): return not self._paused and not self._closing @@ -764,12 +771,17 @@ def resume_reading(self): if self._loop.get_debug(): logger.debug("%r resumes reading", self) + def _read_ready(self): + self._read_ready_cb() + def _read_ready__get_buffer(self): if self._conn_lost: return try: - buf = self._protocol.get_buffer() + buf = self._protocol.get_buffer(-1) + if not len(buf): + raise RuntimeError('get_buffer() returned an empty buffer') except Exception as exc: self._fatal_error( exc, 'Fatal error: protocol.get_buffer() call failed.') diff --git a/Lib/asyncio/sslproto.py b/Lib/asyncio/sslproto.py index 2bbf134c0f7e..2bfa45dd1585 100644 --- a/Lib/asyncio/sslproto.py +++ b/Lib/asyncio/sslproto.py @@ -441,6 +441,8 @@ def __init__(self, loop, app_protocol, sslcontext, waiter, self._waiter = waiter self._loop = loop self._app_protocol = app_protocol + self._app_protocol_is_buffer = \ + isinstance(app_protocol, protocols.BufferedProtocol) self._app_transport = _SSLProtocolTransport(self._loop, self) # _SSLPipe instance (None until the connection is made) self._sslpipe = None @@ -522,7 +524,16 @@ def data_received(self, data): for chunk in appdata: if chunk: - self._app_protocol.data_received(chunk) + try: + if self._app_protocol_is_buffer: + _feed_data_to_bufferred_proto( + self._app_protocol, chunk) + else: + self._app_protocol.data_received(chunk) + except Exception as ex: + self._fatal_error( + ex, 'application protocol failed to receive SSL data') + return else: self._start_shutdown() break @@ -709,3 +720,22 @@ def _abort(self): self._transport.abort() finally: self._finalize() + + +def _feed_data_to_bufferred_proto(proto, data): + data_len = len(data) + while data_len: + buf = proto.get_buffer(data_len) + buf_len = len(buf) + if not buf_len: + raise RuntimeError('get_buffer() returned an empty buffer') + + if buf_len >= data_len: + buf[:data_len] = data + proto.buffer_updated(data_len) + return + else: + buf[:buf_len] = data[:buf_len] + proto.buffer_updated(buf_len) + data = data[buf_len:] + data_len = len(data) diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py index 6cac137cacb3..639300f976ab 100644 --- a/Lib/asyncio/unix_events.py +++ b/Lib/asyncio/unix_events.py @@ -20,6 +20,7 @@ from . import events from . import futures from . import selector_events +from . import tasks from . import transports from .log import logger @@ -308,6 +309,9 @@ def _child_watcher_callback(self, pid, returncode, transp): ssl, backlog, ssl_handshake_timeout) if start_serving: server._start_serving() + # Skip one loop iteration so that all 'loop.add_reader' + # go through. + await tasks.sleep(0, loop=self) return server diff --git a/Lib/test/test_asyncio/test_buffered_proto.py b/Lib/test/test_asyncio/test_buffered_proto.py index 22f9269e814f..89d3df72d98b 100644 --- a/Lib/test/test_asyncio/test_buffered_proto.py +++ b/Lib/test/test_asyncio/test_buffered_proto.py @@ -9,7 +9,7 @@ def __init__(self, cb, con_lost_fut): self.cb = cb self.con_lost_fut = con_lost_fut - def get_buffer(self): + def get_buffer(self, sizehint): self.buffer = bytearray(100) return self.buffer diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index 64d726d16d1c..d7b0a665a0ab 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -2095,7 +2095,7 @@ def test_subprocess_shell_invalid_args(self): class SendfileBase: - DATA = b"12345abcde" * 16 * 1024 # 160 KiB + DATA = b"12345abcde" * 64 * 1024 # 64 KiB (don't use smaller sizes) @classmethod def setUpClass(cls): @@ -2452,7 +2452,7 @@ def test_sendfile_ssl_close_peer_after_receiving(self): self.assertEqual(srv_proto.data, self.DATA) self.assertEqual(self.file.tell(), len(self.DATA)) - def test_sendfile_close_peer_in_middle_of_receiving(self): + def test_sendfile_close_peer_in_the_middle_of_receiving(self): srv_proto, cli_proto = self.prepare_sendfile(close_after=1024) with self.assertRaises(ConnectionError): self.run_loop( @@ -2465,7 +2465,7 @@ def test_sendfile_close_peer_in_middle_of_receiving(self): self.file.tell()) self.assertTrue(cli_proto.transport.is_closing()) - def test_sendfile_fallback_close_peer_in_middle_of_receiving(self): + def test_sendfile_fallback_close_peer_in_the_middle_of_receiving(self): def sendfile_native(transp, file, offset, count): # to raise SendfileNotAvailableError diff --git a/Lib/test/test_asyncio/test_proactor_events.py b/Lib/test/test_asyncio/test_proactor_events.py index 6313d594477a..6da6b4a34db8 100644 --- a/Lib/test/test_asyncio/test_proactor_events.py +++ b/Lib/test/test_asyncio/test_proactor_events.py @@ -465,8 +465,8 @@ def setUp(self): self.loop._proactor = self.proactor self.protocol = test_utils.make_test_protocol(asyncio.BufferedProtocol) - self.buf = mock.Mock() - self.protocol.get_buffer.side_effect = lambda: self.buf + self.buf = bytearray(1) + self.protocol.get_buffer.side_effect = lambda hint: self.buf self.sock = mock.Mock(socket.socket) @@ -505,6 +505,64 @@ def test_get_buffer_error(self): self.assertTrue(self.protocol.get_buffer.called) self.assertFalse(self.protocol.buffer_updated.called) + def test_get_buffer_zerosized(self): + transport = self.socket_transport() + transport._fatal_error = mock.Mock() + + self.loop.call_exception_handler = mock.Mock() + self.protocol.get_buffer.side_effect = lambda hint: bytearray(0) + + transport._loop_reading() + + self.assertTrue(transport._fatal_error.called) + self.assertTrue(self.protocol.get_buffer.called) + self.assertFalse(self.protocol.buffer_updated.called) + + def test_proto_type_switch(self): + self.protocol = test_utils.make_test_protocol(asyncio.Protocol) + tr = self.socket_transport() + + res = asyncio.Future(loop=self.loop) + res.set_result(b'data') + + tr = self.socket_transport() + tr._read_fut = res + tr._loop_reading(res) + self.loop._proactor.recv.assert_called_with(self.sock, 32768) + self.protocol.data_received.assert_called_with(b'data') + + # switch protocol to a BufferedProtocol + + buf_proto = test_utils.make_test_protocol(asyncio.BufferedProtocol) + buf = bytearray(4) + buf_proto.get_buffer.side_effect = lambda hint: buf + + tr.set_protocol(buf_proto) + test_utils.run_briefly(self.loop) + res = asyncio.Future(loop=self.loop) + res.set_result(4) + + tr._read_fut = res + tr._loop_reading(res) + self.loop._proactor.recv_into.assert_called_with(self.sock, buf) + buf_proto.buffer_updated.assert_called_with(4) + + def test_proto_buf_switch(self): + tr = self.socket_transport() + test_utils.run_briefly(self.loop) + self.protocol.get_buffer.assert_called_with(-1) + + # switch protocol to *another* BufferedProtocol + + buf_proto = test_utils.make_test_protocol(asyncio.BufferedProtocol) + buf = bytearray(4) + buf_proto.get_buffer.side_effect = lambda hint: buf + tr._read_fut.done.side_effect = lambda: False + tr.set_protocol(buf_proto) + self.assertFalse(buf_proto.get_buffer.called) + test_utils.run_briefly(self.loop) + buf_proto.get_buffer.assert_called_with(-1) + def test_buffer_updated_error(self): transport = self.socket_transport() transport._fatal_error = mock.Mock() diff --git a/Lib/test/test_asyncio/test_selector_events.py b/Lib/test/test_asyncio/test_selector_events.py index 5c4ff5745b62..68b6ee9abbf1 100644 --- a/Lib/test/test_asyncio/test_selector_events.py +++ b/Lib/test/test_asyncio/test_selector_events.py @@ -772,7 +772,8 @@ def test_accept_connection_multiple(self): accept2_mock.return_value = None with mock_obj(self.loop, 'create_task') as task_mock: task_mock.return_value = None - self.loop._accept_connection(mock.Mock(), sock, backlog=backlog) + self.loop._accept_connection( + mock.Mock(), sock, backlog=backlog) self.assertEqual(sock.accept.call_count, backlog) @@ -1285,8 +1286,8 @@ def setUp(self): self.loop = self.new_test_loop() self.protocol = test_utils.make_test_protocol(asyncio.BufferedProtocol) - self.buf = mock.Mock() - self.protocol.get_buffer.side_effect = lambda: self.buf + self.buf = bytearray(1) + self.protocol.get_buffer.side_effect = lambda hint: self.buf self.sock = mock.Mock(socket.socket) self.sock_fd = self.sock.fileno.return_value = 7 @@ -1319,6 +1320,42 @@ def test_get_buffer_error(self): self.assertTrue(self.protocol.get_buffer.called) self.assertFalse(self.protocol.buffer_updated.called) + def test_get_buffer_zerosized(self): + transport = self.socket_transport() + transport._fatal_error = mock.Mock() + + self.loop.call_exception_handler = mock.Mock() + self.protocol.get_buffer.side_effect = lambda hint: bytearray(0) + + transport._read_ready() + + self.assertTrue(transport._fatal_error.called) + self.assertTrue(self.protocol.get_buffer.called) + self.assertFalse(self.protocol.buffer_updated.called) + + def test_proto_type_switch(self): + self.protocol = test_utils.make_test_protocol(asyncio.Protocol) + transport = self.socket_transport() + + self.sock.recv.return_value = b'data' + transport._read_ready() + + self.protocol.data_received.assert_called_with(b'data') + + # switch protocol to a BufferedProtocol + + buf_proto = test_utils.make_test_protocol(asyncio.BufferedProtocol) + buf = bytearray(4) + buf_proto.get_buffer.side_effect = lambda hint: buf + + transport.set_protocol(buf_proto) + + self.sock.recv_into.return_value = 10 + transport._read_ready() + + buf_proto.get_buffer.assert_called_with(-1) + buf_proto.buffer_updated.assert_called_with(10) + def test_buffer_updated_error(self): transport = self.socket_transport() transport._fatal_error = mock.Mock() @@ -1354,7 +1391,7 @@ def test_read_ready(self): self.sock.recv_into.return_value = 10 transport._read_ready() - self.protocol.get_buffer.assert_called_with() + self.protocol.get_buffer.assert_called_with(-1) self.protocol.buffer_updated.assert_called_with(10) def test_read_ready_eof(self): diff --git a/Lib/test/test_asyncio/test_sslproto.py b/Lib/test/test_asyncio/test_sslproto.py index c534a341352b..932487a9e3c6 100644 --- a/Lib/test/test_asyncio/test_sslproto.py +++ b/Lib/test/test_asyncio/test_sslproto.py @@ -1,8 +1,7 @@ """Tests for asyncio/sslproto.py.""" -import os import logging -import time +import socket import unittest from unittest import mock try: @@ -185,17 +184,67 @@ def test_write_after_closing(self): class BaseStartTLS(func_tests.FunctionalTestCaseMixin): + PAYLOAD_SIZE = 1024 * 100 + TIMEOUT = 60 + def new_loop(self): raise NotImplementedError - def test_start_tls_client_1(self): - HELLO_MSG = b'1' * 1024 * 1024 + def test_buf_feed_data(self): + + class Proto(asyncio.BufferedProtocol): + + def __init__(self, bufsize, usemv): + self.buf = bytearray(bufsize) + self.mv = memoryview(self.buf) + self.data = b'' + self.usemv = usemv + + def get_buffer(self, sizehint): + if self.usemv: + return self.mv + else: + return self.buf + + def buffer_updated(self, nsize): + if self.usemv: + self.data += self.mv[:nsize] + else: + self.data += self.buf[:nsize] + + for usemv in [False, True]: + proto = Proto(1, usemv) + sslproto._feed_data_to_bufferred_proto(proto, b'12345') + self.assertEqual(proto.data, b'12345') + + proto = Proto(2, usemv) + sslproto._feed_data_to_bufferred_proto(proto, b'12345') + self.assertEqual(proto.data, b'12345') + + proto = Proto(2, usemv) + sslproto._feed_data_to_bufferred_proto(proto, b'1234') + self.assertEqual(proto.data, b'1234') + + proto = Proto(4, usemv) + sslproto._feed_data_to_bufferred_proto(proto, b'1234') + self.assertEqual(proto.data, b'1234') + + proto = Proto(100, usemv) + sslproto._feed_data_to_bufferred_proto(proto, b'12345') + self.assertEqual(proto.data, b'12345') + + proto = Proto(0, usemv) + with self.assertRaisesRegex(RuntimeError, 'empty buffer'): + sslproto._feed_data_to_bufferred_proto(proto, b'12345') + + def test_start_tls_client_reg_proto_1(self): + HELLO_MSG = b'1' * self.PAYLOAD_SIZE server_context = test_utils.simple_server_sslcontext() client_context = test_utils.simple_client_sslcontext() def serve(sock): - sock.settimeout(5) + sock.settimeout(self.TIMEOUT) data = sock.recv_all(len(HELLO_MSG)) self.assertEqual(len(data), len(HELLO_MSG)) @@ -205,6 +254,8 @@ def serve(sock): sock.sendall(b'O') data = sock.recv_all(len(HELLO_MSG)) self.assertEqual(len(data), len(HELLO_MSG)) + + sock.shutdown(socket.SHUT_RDWR) sock.close() class ClientProto(asyncio.Protocol): @@ -246,17 +297,80 @@ def eof_received(self): self.loop.run_until_complete( asyncio.wait_for(client(srv.addr), loop=self.loop, timeout=10)) + def test_start_tls_client_buf_proto_1(self): + HELLO_MSG = b'1' * self.PAYLOAD_SIZE + + server_context = test_utils.simple_server_sslcontext() + client_context = test_utils.simple_client_sslcontext() + + def serve(sock): + sock.settimeout(self.TIMEOUT) + + data = sock.recv_all(len(HELLO_MSG)) + self.assertEqual(len(data), len(HELLO_MSG)) + + sock.start_tls(server_context, server_side=True) + + sock.sendall(b'O') + data = sock.recv_all(len(HELLO_MSG)) + self.assertEqual(len(data), len(HELLO_MSG)) + + sock.shutdown(socket.SHUT_RDWR) + sock.close() + + class ClientProto(asyncio.BufferedProtocol): + def __init__(self, on_data, on_eof): + self.on_data = on_data + self.on_eof = on_eof + self.con_made_cnt = 0 + self.buf = bytearray(1) + + def connection_made(proto, tr): + proto.con_made_cnt += 1 + # Ensure connection_made gets called only once. + self.assertEqual(proto.con_made_cnt, 1) + + def get_buffer(self, sizehint): + return self.buf + + def buffer_updated(self, nsize): + assert nsize == 1 + self.on_data.set_result(bytes(self.buf[:nsize])) + + def eof_received(self): + self.on_eof.set_result(True) + + async def client(addr): + await asyncio.sleep(0.5, loop=self.loop) + + on_data = self.loop.create_future() + on_eof = self.loop.create_future() + + tr, proto = await self.loop.create_connection( + lambda: ClientProto(on_data, on_eof), *addr) + + tr.write(HELLO_MSG) + new_tr = await self.loop.start_tls(tr, proto, client_context) + + self.assertEqual(await on_data, b'O') + new_tr.write(HELLO_MSG) + await on_eof + + new_tr.close() + + with self.tcp_server(serve) as srv: + self.loop.run_until_complete( + asyncio.wait_for(client(srv.addr), + loop=self.loop, timeout=self.TIMEOUT)) + def test_start_tls_server_1(self): - HELLO_MSG = b'1' * 1024 * 1024 + HELLO_MSG = b'1' * self.PAYLOAD_SIZE server_context = test_utils.simple_server_sslcontext() client_context = test_utils.simple_client_sslcontext() - # TODO: fix TLSv1.3 support - client_context.options |= ssl.OP_NO_TLSv1_3 def client(sock, addr): - time.sleep(0.5) - sock.settimeout(5) + sock.settimeout(self.TIMEOUT) sock.connect(addr) data = sock.recv_all(len(HELLO_MSG)) @@ -264,12 +378,15 @@ def client(sock, addr): sock.start_tls(client_context) sock.sendall(HELLO_MSG) + + sock.shutdown(socket.SHUT_RDWR) sock.close() class ServerProto(asyncio.Protocol): - def __init__(self, on_con, on_eof): + def __init__(self, on_con, on_eof, on_con_lost): self.on_con = on_con self.on_eof = on_eof + self.on_con_lost = on_con_lost self.data = b'' def connection_made(self, tr): @@ -281,7 +398,13 @@ def data_received(self, data): def eof_received(self): self.on_eof.set_result(1) - async def main(): + def connection_lost(self, exc): + if exc is None: + self.on_con_lost.set_result(None) + else: + self.on_con_lost.set_exception(exc) + + async def main(proto, on_con, on_eof, on_con_lost): tr = await on_con tr.write(HELLO_MSG) @@ -292,24 +415,29 @@ def eof_received(self): server_side=True) await on_eof + await on_con_lost self.assertEqual(proto.data, HELLO_MSG) new_tr.close() - server.close() - await server.wait_closed() + async def run_main(): + on_con = self.loop.create_future() + on_eof = self.loop.create_future() + on_con_lost = self.loop.create_future() + proto = ServerProto(on_con, on_eof, on_con_lost) - on_con = self.loop.create_future() - on_eof = self.loop.create_future() - proto = ServerProto(on_con, on_eof) + server = await self.loop.create_server( + lambda: proto, '127.0.0.1', 0) + addr = server.sockets[0].getsockname() - server = self.loop.run_until_complete( - self.loop.create_server( - lambda: proto, '127.0.0.1', 0)) - addr = server.sockets[0].getsockname() + with self.tcp_client(lambda sock: client(sock, addr)): + await asyncio.wait_for( + main(proto, on_con, on_eof, on_con_lost), + loop=self.loop, timeout=self.TIMEOUT) - with self.tcp_client(lambda sock: client(sock, addr)): - self.loop.run_until_complete( - asyncio.wait_for(main(), loop=self.loop, timeout=10)) + server.close() + await server.wait_closed() + + self.loop.run_until_complete(run_main()) def test_start_tls_wrong_args(self): async def main(): @@ -332,7 +460,6 @@ def new_loop(self): @unittest.skipIf(ssl is None, 'No ssl module') @unittest.skipUnless(hasattr(asyncio, 'ProactorEventLoop'), 'Windows only') - at unittest.skipIf(os.environ.get('APPVEYOR'), 'XXX: issue 32458') class ProactorStartTLSTests(BaseStartTLS, unittest.TestCase): def new_loop(self): diff --git a/Misc/NEWS.d/next/Library/2018-05-26-13-09-34.bpo-33654.IbYWxA.rst b/Misc/NEWS.d/next/Library/2018-05-26-13-09-34.bpo-33654.IbYWxA.rst new file mode 100644 index 000000000000..3ae506ddc55f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-26-13-09-34.bpo-33654.IbYWxA.rst @@ -0,0 +1,3 @@ +Fix transport.set_protocol() to support switching between asyncio.Protocol +and asyncio.BufferedProtocol. Fix loop.start_tls() to work with +asyncio.BufferedProtocols. From webhook-mailer at python.org Mon May 28 15:03:46 2018 From: webhook-mailer at python.org (Victor Stinner) Date: Mon, 28 May 2018 19:03:46 -0000 Subject: [Python-checkins] regrtest: repeat summary after re-run (GH-7159) Message-ID: <mailman.17.1527534227.2800.python-checkins@python.org> https://github.com/python/cpython/commit/c6c05d0e69cd5a7d0205019c29a1236b7bf3f5b9 commit: c6c05d0e69cd5a7d0205019c29a1236b7bf3f5b9 branch: master author: Victor Stinner <vstinner at redhat.com> committer: GitHub <noreply at github.com> date: 2018-05-28T21:03:43+02:00 summary: regrtest: repeat summary after re-run (GH-7159) Using -w, when failing tests are re-run in verbose mode, display again the tests results at the end. files: M Lib/test/libregrtest/main.py diff --git a/Lib/test/libregrtest/main.py b/Lib/test/libregrtest/main.py index ce01c8ce586d..1ab47bf58d67 100644 --- a/Lib/test/libregrtest/main.py +++ b/Lib/test/libregrtest/main.py @@ -88,6 +88,7 @@ def __init__(self): self.skipped = [] self.resource_denieds = [] self.environment_changed = [] + self.rerun = [] self.interrupted = False # used by --slow @@ -283,8 +284,10 @@ def rerun_failed_tests(self): self.ns.verbose3 = False self.ns.match_tests = None + print() print("Re-running failed tests in verbose mode") - for test in self.bad[:]: + self.rerun = self.bad[:] + for test in self.rerun: print("Re-running test %r in verbose mode" % test, flush=True) try: self.ns.verbose = True @@ -302,22 +305,32 @@ def rerun_failed_tests(self): print(count(len(self.bad), 'test'), "failed again:") printlist(self.bad) + self.display_result() + def display_result(self): + # If running the test suite for PGO then no one cares about results. + if self.ns.pgo: + return + + print() + print("== Tests result ==") + if self.interrupted: - # print a newline after ^C print() + # print a newline after ^C print("Test suite interrupted by signal SIGINT.") executed = set(self.good) | set(self.bad) | set(self.skipped) omitted = set(self.selected) - executed print(count(len(omitted), "test"), "omitted:") printlist(omitted) - # If running the test suite for PGO then no one cares about - # results. - if self.ns.pgo: - return + if self.rerun: + print() + print(count(len(self.rerun), "test"), "re-run tests:") + printlist(self.rerun) if self.good and not self.ns.quiet: + print() if (not self.bad and not self.skipped and not self.interrupted From webhook-mailer at python.org Mon May 28 15:32:10 2018 From: webhook-mailer at python.org (Steve Dower) Date: Mon, 28 May 2018 19:32:10 -0000 Subject: [Python-checkins] bpo-33614: Ensures module definition files for the stable ABI on Windows are correctly regenerated. (GH-7165) Message-ID: <mailman.18.1527535932.2800.python-checkins@python.org> https://github.com/python/cpython/commit/e97ba4c690613d734843db218aeedce2f0e5937f commit: e97ba4c690613d734843db218aeedce2f0e5937f branch: master author: Steve Dower <steve.dower at microsoft.com> committer: GitHub <noreply at github.com> date: 2018-05-28T12:32:05-07:00 summary: bpo-33614: Ensures module definition files for the stable ABI on Windows are correctly regenerated. (GH-7165) files: A Misc/NEWS.d/next/Build/2018-05-28-11-40-22.bpo-33614.28e0sE.rst M PCbuild/find_msbuild.bat M PCbuild/python3dll.vcxproj diff --git a/Misc/NEWS.d/next/Build/2018-05-28-11-40-22.bpo-33614.28e0sE.rst b/Misc/NEWS.d/next/Build/2018-05-28-11-40-22.bpo-33614.28e0sE.rst new file mode 100644 index 000000000000..9091c282ad0a --- /dev/null +++ b/Misc/NEWS.d/next/Build/2018-05-28-11-40-22.bpo-33614.28e0sE.rst @@ -0,0 +1,2 @@ +Ensures module definition files for the stable ABI on Windows are correctly +regenerated. diff --git a/PCbuild/find_msbuild.bat b/PCbuild/find_msbuild.bat index 1877906e00a5..24f5e2fb5d46 100644 --- a/PCbuild/find_msbuild.bat +++ b/PCbuild/find_msbuild.bat @@ -47,5 +47,13 @@ @exit /b 1 :found - at echo Using %MSBUILD% (found in the %_Py_MSBuild_Source%) + at pushd %MSBUILD% >nul 2>nul + at if not ERRORLEVEL 1 @( + @if exist msbuild.exe @(set MSBUILD="%CD%\msbuild.exe") else @(set MSBUILD=) + @popd +) + + at if defined MSBUILD @echo Using %MSBUILD% (found in the %_Py_MSBuild_Source%) + at if not defined MSBUILD @echo Failed to find MSBuild @set _Py_MSBuild_Source= + at if not defined MSBUILD @exit /b 1 diff --git a/PCbuild/python3dll.vcxproj b/PCbuild/python3dll.vcxproj index c66c8ef141a1..0ef7780248fb 100644 --- a/PCbuild/python3dll.vcxproj +++ b/PCbuild/python3dll.vcxproj @@ -89,14 +89,18 @@ <ImportGroup Label="ExtensionTargets"> </ImportGroup> - <Target Name="BuildPython3_dDef" BeforeTargets="BuildStubDef" Inputs="..\PC\python3.def" Outputs="$(IntDir)python3_d.def" Condition="$(Configuration) == 'Debug'"> + <Target Name="BuildPython3_dDef" BeforeTargets="BuildStubDef" Condition="$(Configuration) == 'Debug'"> <ItemGroup> <_DefLines Remove="@(_DefLines)" /> <_Lines Remove="@(_Lines)" /> + <_OriginalLines Remove="@(_OriginalLines)" /> </ItemGroup> <ReadLinesFromFile File="..\PC\python3.def"> <Output TaskParameter="Lines" ItemName="_DefLines" /> </ReadLinesFromFile> + <ReadLinesFromFile File="$(IntDir)python3_d.def" Condition="Exists('$(IntDir)python3_d.def')"> + <Output TaskParameter="Lines" ItemName="_OriginalLines" /> + </ReadLinesFromFile> <PropertyGroup> <_Pattern1>(=python$(MajorVersionNumber)$(MinorVersionNumber))\.</_Pattern1> <_Sub1>$1_d.</_Sub1> @@ -109,17 +113,23 @@ </_Lines> </ItemGroup> <MakeDir Directories="$(IntDir)" /> - <WriteLinesToFile File="$(IntDir)python3_d.def" Lines="@(_Lines->'%(New)')" Overwrite="true" /> + <Message Text="Updating python3_d.def" Condition="@(_Lines->'%(New)') != @(_OriginalLines)" Importance="high" /> + <WriteLinesToFile File="$(IntDir)python3_d.def" Lines="@(_Lines->'%(New)')" Overwrite="true" + Condition="@(_Lines->'%(New)') != @(_OriginalLines)" /> </Target> - <Target Name="BuildStubDef" BeforeTargets="PreLinkEvent" Inputs="..\PC\python3.def" Outputs="$(IntDir)python3stub.def"> + <Target Name="BuildStubDef" BeforeTargets="PreLinkEvent"> <ItemGroup> <_DefLines Remove="@(_DefLines)" /> <_Lines Remove="@(_Lines)" /> + <_OriginalLines Remove="@(_OriginalLines)" /> </ItemGroup> <ReadLinesFromFile File="..\PC\python3.def"> <Output TaskParameter="Lines" ItemName="_DefLines" /> </ReadLinesFromFile> + <ReadLinesFromFile File="$(IntDir)python3stub.def" Condition="Exists('$(IntDir)python3stub.def')"> + <Output TaskParameter="Lines" ItemName="_OriginalLines" /> + </ReadLinesFromFile> <PropertyGroup> <_Pattern>^[\w.]+=.+?\.([^ ]+).*$</_Pattern> <_Sub>$1</_Sub> @@ -132,6 +142,8 @@ <_Lines Include="@(_Symbols->'%(Symbol)')" /> </ItemGroup> <MakeDir Directories="$(IntDir)" /> - <WriteLinesToFile File="$(IntDir)python3stub.def" Lines="@(_Lines)" Overwrite="true" /> + <Message Text="Updating python3stub.def" Condition="@(_OriginalLines) != @(_Lines)" Importance="high" /> + <WriteLinesToFile File="$(IntDir)python3stub.def" Lines="@(_Lines)" Overwrite="true" + Condition="@(_DefLines) != @(_Lines)" /> </Target> </Project> \ No newline at end of file From webhook-mailer at python.org Mon May 28 15:49:02 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Mon, 28 May 2018 19:49:02 -0000 Subject: [Python-checkins] bpo-32458: Further tune start_tls tests (#7166) Message-ID: <mailman.19.1527536948.2800.python-checkins@python.org> https://github.com/python/cpython/commit/8267ea2e84d355f00654dec3ad782fc7b1f680f1 commit: 8267ea2e84d355f00654dec3ad782fc7b1f680f1 branch: master author: Yury Selivanov <yury at magic.io> committer: GitHub <noreply at github.com> date: 2018-05-28T15:48:59-04:00 summary: bpo-32458: Further tune start_tls tests (#7166) files: M Lib/test/test_asyncio/test_sslproto.py diff --git a/Lib/test/test_asyncio/test_sslproto.py b/Lib/test/test_asyncio/test_sslproto.py index 932487a9e3c6..1b2f9d2a3a2a 100644 --- a/Lib/test/test_asyncio/test_sslproto.py +++ b/Lib/test/test_asyncio/test_sslproto.py @@ -293,7 +293,7 @@ def eof_received(self): new_tr.close() - with self.tcp_server(serve) as srv: + with self.tcp_server(serve, timeout=self.TIMEOUT) as srv: self.loop.run_until_complete( asyncio.wait_for(client(srv.addr), loop=self.loop, timeout=10)) @@ -358,7 +358,7 @@ def eof_received(self): new_tr.close() - with self.tcp_server(serve) as srv: + with self.tcp_server(serve, timeout=self.TIMEOUT) as srv: self.loop.run_until_complete( asyncio.wait_for(client(srv.addr), loop=self.loop, timeout=self.TIMEOUT)) @@ -412,7 +412,8 @@ def connection_lost(self, exc): new_tr = await self.loop.start_tls( tr, proto, server_context, - server_side=True) + server_side=True, + ssl_handshake_timeout=self.TIMEOUT) await on_eof await on_con_lost @@ -429,7 +430,8 @@ def connection_lost(self, exc): lambda: proto, '127.0.0.1', 0) addr = server.sockets[0].getsockname() - with self.tcp_client(lambda sock: client(sock, addr)): + with self.tcp_client(lambda sock: client(sock, addr), + timeout=self.TIMEOUT): await asyncio.wait_for( main(proto, on_con, on_eof, on_con_lost), loop=self.loop, timeout=self.TIMEOUT) From webhook-mailer at python.org Mon May 28 15:51:19 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 28 May 2018 19:51:19 -0000 Subject: [Python-checkins] bpo-33614: Ensures module definition files for the stable ABI on Windows are correctly regenerated. (GH-7165) Message-ID: <mailman.20.1527537082.2800.python-checkins@python.org> https://github.com/python/cpython/commit/3757939e9c00a36f939d774ec5c79e5d6b9a77bb commit: 3757939e9c00a36f939d774ec5c79e5d6b9a77bb branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-28T12:51:16-07:00 summary: bpo-33614: Ensures module definition files for the stable ABI on Windows are correctly regenerated. (GH-7165) (cherry picked from commit e97ba4c690613d734843db218aeedce2f0e5937f) Co-authored-by: Steve Dower <steve.dower at microsoft.com> files: A Misc/NEWS.d/next/Build/2018-05-28-11-40-22.bpo-33614.28e0sE.rst M PCbuild/find_msbuild.bat M PCbuild/python3dll.vcxproj diff --git a/Misc/NEWS.d/next/Build/2018-05-28-11-40-22.bpo-33614.28e0sE.rst b/Misc/NEWS.d/next/Build/2018-05-28-11-40-22.bpo-33614.28e0sE.rst new file mode 100644 index 000000000000..9091c282ad0a --- /dev/null +++ b/Misc/NEWS.d/next/Build/2018-05-28-11-40-22.bpo-33614.28e0sE.rst @@ -0,0 +1,2 @@ +Ensures module definition files for the stable ABI on Windows are correctly +regenerated. diff --git a/PCbuild/find_msbuild.bat b/PCbuild/find_msbuild.bat index 1877906e00a5..24f5e2fb5d46 100644 --- a/PCbuild/find_msbuild.bat +++ b/PCbuild/find_msbuild.bat @@ -47,5 +47,13 @@ @exit /b 1 :found - at echo Using %MSBUILD% (found in the %_Py_MSBuild_Source%) + at pushd %MSBUILD% >nul 2>nul + at if not ERRORLEVEL 1 @( + @if exist msbuild.exe @(set MSBUILD="%CD%\msbuild.exe") else @(set MSBUILD=) + @popd +) + + at if defined MSBUILD @echo Using %MSBUILD% (found in the %_Py_MSBuild_Source%) + at if not defined MSBUILD @echo Failed to find MSBuild @set _Py_MSBuild_Source= + at if not defined MSBUILD @exit /b 1 diff --git a/PCbuild/python3dll.vcxproj b/PCbuild/python3dll.vcxproj index c66c8ef141a1..0ef7780248fb 100644 --- a/PCbuild/python3dll.vcxproj +++ b/PCbuild/python3dll.vcxproj @@ -89,14 +89,18 @@ <ImportGroup Label="ExtensionTargets"> </ImportGroup> - <Target Name="BuildPython3_dDef" BeforeTargets="BuildStubDef" Inputs="..\PC\python3.def" Outputs="$(IntDir)python3_d.def" Condition="$(Configuration) == 'Debug'"> + <Target Name="BuildPython3_dDef" BeforeTargets="BuildStubDef" Condition="$(Configuration) == 'Debug'"> <ItemGroup> <_DefLines Remove="@(_DefLines)" /> <_Lines Remove="@(_Lines)" /> + <_OriginalLines Remove="@(_OriginalLines)" /> </ItemGroup> <ReadLinesFromFile File="..\PC\python3.def"> <Output TaskParameter="Lines" ItemName="_DefLines" /> </ReadLinesFromFile> + <ReadLinesFromFile File="$(IntDir)python3_d.def" Condition="Exists('$(IntDir)python3_d.def')"> + <Output TaskParameter="Lines" ItemName="_OriginalLines" /> + </ReadLinesFromFile> <PropertyGroup> <_Pattern1>(=python$(MajorVersionNumber)$(MinorVersionNumber))\.</_Pattern1> <_Sub1>$1_d.</_Sub1> @@ -109,17 +113,23 @@ </_Lines> </ItemGroup> <MakeDir Directories="$(IntDir)" /> - <WriteLinesToFile File="$(IntDir)python3_d.def" Lines="@(_Lines->'%(New)')" Overwrite="true" /> + <Message Text="Updating python3_d.def" Condition="@(_Lines->'%(New)') != @(_OriginalLines)" Importance="high" /> + <WriteLinesToFile File="$(IntDir)python3_d.def" Lines="@(_Lines->'%(New)')" Overwrite="true" + Condition="@(_Lines->'%(New)') != @(_OriginalLines)" /> </Target> - <Target Name="BuildStubDef" BeforeTargets="PreLinkEvent" Inputs="..\PC\python3.def" Outputs="$(IntDir)python3stub.def"> + <Target Name="BuildStubDef" BeforeTargets="PreLinkEvent"> <ItemGroup> <_DefLines Remove="@(_DefLines)" /> <_Lines Remove="@(_Lines)" /> + <_OriginalLines Remove="@(_OriginalLines)" /> </ItemGroup> <ReadLinesFromFile File="..\PC\python3.def"> <Output TaskParameter="Lines" ItemName="_DefLines" /> </ReadLinesFromFile> + <ReadLinesFromFile File="$(IntDir)python3stub.def" Condition="Exists('$(IntDir)python3stub.def')"> + <Output TaskParameter="Lines" ItemName="_OriginalLines" /> + </ReadLinesFromFile> <PropertyGroup> <_Pattern>^[\w.]+=.+?\.([^ ]+).*$</_Pattern> <_Sub>$1</_Sub> @@ -132,6 +142,8 @@ <_Lines Include="@(_Symbols->'%(Symbol)')" /> </ItemGroup> <MakeDir Directories="$(IntDir)" /> - <WriteLinesToFile File="$(IntDir)python3stub.def" Lines="@(_Lines)" Overwrite="true" /> + <Message Text="Updating python3stub.def" Condition="@(_OriginalLines) != @(_Lines)" Importance="high" /> + <WriteLinesToFile File="$(IntDir)python3stub.def" Lines="@(_Lines)" Overwrite="true" + Condition="@(_DefLines) != @(_Lines)" /> </Target> </Project> \ No newline at end of file From webhook-mailer at python.org Mon May 28 16:16:11 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 28 May 2018 20:16:11 -0000 Subject: [Python-checkins] bpo-33614: Ensures module definition files for the stable ABI on Windows are correctly regenerated. (GH-7165) Message-ID: <mailman.21.1527538572.2800.python-checkins@python.org> https://github.com/python/cpython/commit/c489a767af46f33e73d96a5746e46a7365814db2 commit: c489a767af46f33e73d96a5746e46a7365814db2 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-28T13:16:07-07:00 summary: bpo-33614: Ensures module definition files for the stable ABI on Windows are correctly regenerated. (GH-7165) (cherry picked from commit e97ba4c690613d734843db218aeedce2f0e5937f) Co-authored-by: Steve Dower <steve.dower at microsoft.com> files: A Misc/NEWS.d/next/Build/2018-05-28-11-40-22.bpo-33614.28e0sE.rst M PCbuild/find_msbuild.bat M PCbuild/python3dll.vcxproj diff --git a/Misc/NEWS.d/next/Build/2018-05-28-11-40-22.bpo-33614.28e0sE.rst b/Misc/NEWS.d/next/Build/2018-05-28-11-40-22.bpo-33614.28e0sE.rst new file mode 100644 index 000000000000..9091c282ad0a --- /dev/null +++ b/Misc/NEWS.d/next/Build/2018-05-28-11-40-22.bpo-33614.28e0sE.rst @@ -0,0 +1,2 @@ +Ensures module definition files for the stable ABI on Windows are correctly +regenerated. diff --git a/PCbuild/find_msbuild.bat b/PCbuild/find_msbuild.bat index 2b7413fbcde8..1364a17432ef 100644 --- a/PCbuild/find_msbuild.bat +++ b/PCbuild/find_msbuild.bat @@ -48,5 +48,13 @@ @exit /b 1 :found - at echo Using %MSBUILD% (found in the %_Py_MSBuild_Source%) + at pushd %MSBUILD% >nul 2>nul + at if not ERRORLEVEL 1 @( + @if exist msbuild.exe @(set MSBUILD="%CD%\msbuild.exe") else @(set MSBUILD=) + @popd +) + + at if defined MSBUILD @echo Using %MSBUILD% (found in the %_Py_MSBuild_Source%) + at if not defined MSBUILD @echo Failed to find MSBuild @set _Py_MSBuild_Source= + at if not defined MSBUILD @exit /b 1 diff --git a/PCbuild/python3dll.vcxproj b/PCbuild/python3dll.vcxproj index c66c8ef141a1..0ef7780248fb 100644 --- a/PCbuild/python3dll.vcxproj +++ b/PCbuild/python3dll.vcxproj @@ -89,14 +89,18 @@ <ImportGroup Label="ExtensionTargets"> </ImportGroup> - <Target Name="BuildPython3_dDef" BeforeTargets="BuildStubDef" Inputs="..\PC\python3.def" Outputs="$(IntDir)python3_d.def" Condition="$(Configuration) == 'Debug'"> + <Target Name="BuildPython3_dDef" BeforeTargets="BuildStubDef" Condition="$(Configuration) == 'Debug'"> <ItemGroup> <_DefLines Remove="@(_DefLines)" /> <_Lines Remove="@(_Lines)" /> + <_OriginalLines Remove="@(_OriginalLines)" /> </ItemGroup> <ReadLinesFromFile File="..\PC\python3.def"> <Output TaskParameter="Lines" ItemName="_DefLines" /> </ReadLinesFromFile> + <ReadLinesFromFile File="$(IntDir)python3_d.def" Condition="Exists('$(IntDir)python3_d.def')"> + <Output TaskParameter="Lines" ItemName="_OriginalLines" /> + </ReadLinesFromFile> <PropertyGroup> <_Pattern1>(=python$(MajorVersionNumber)$(MinorVersionNumber))\.</_Pattern1> <_Sub1>$1_d.</_Sub1> @@ -109,17 +113,23 @@ </_Lines> </ItemGroup> <MakeDir Directories="$(IntDir)" /> - <WriteLinesToFile File="$(IntDir)python3_d.def" Lines="@(_Lines->'%(New)')" Overwrite="true" /> + <Message Text="Updating python3_d.def" Condition="@(_Lines->'%(New)') != @(_OriginalLines)" Importance="high" /> + <WriteLinesToFile File="$(IntDir)python3_d.def" Lines="@(_Lines->'%(New)')" Overwrite="true" + Condition="@(_Lines->'%(New)') != @(_OriginalLines)" /> </Target> - <Target Name="BuildStubDef" BeforeTargets="PreLinkEvent" Inputs="..\PC\python3.def" Outputs="$(IntDir)python3stub.def"> + <Target Name="BuildStubDef" BeforeTargets="PreLinkEvent"> <ItemGroup> <_DefLines Remove="@(_DefLines)" /> <_Lines Remove="@(_Lines)" /> + <_OriginalLines Remove="@(_OriginalLines)" /> </ItemGroup> <ReadLinesFromFile File="..\PC\python3.def"> <Output TaskParameter="Lines" ItemName="_DefLines" /> </ReadLinesFromFile> + <ReadLinesFromFile File="$(IntDir)python3stub.def" Condition="Exists('$(IntDir)python3stub.def')"> + <Output TaskParameter="Lines" ItemName="_OriginalLines" /> + </ReadLinesFromFile> <PropertyGroup> <_Pattern>^[\w.]+=.+?\.([^ ]+).*$</_Pattern> <_Sub>$1</_Sub> @@ -132,6 +142,8 @@ <_Lines Include="@(_Symbols->'%(Symbol)')" /> </ItemGroup> <MakeDir Directories="$(IntDir)" /> - <WriteLinesToFile File="$(IntDir)python3stub.def" Lines="@(_Lines)" Overwrite="true" /> + <Message Text="Updating python3stub.def" Condition="@(_OriginalLines) != @(_Lines)" Importance="high" /> + <WriteLinesToFile File="$(IntDir)python3stub.def" Lines="@(_Lines)" Overwrite="true" + Condition="@(_DefLines) != @(_Lines)" /> </Target> </Project> \ No newline at end of file From webhook-mailer at python.org Mon May 28 16:25:06 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Mon, 28 May 2018 20:25:06 -0000 Subject: [Python-checkins] bpo-31647: Fix write_eof() after close() for SelectorSocketTransport (GH-7149) (#7154) Message-ID: <mailman.22.1527539108.2800.python-checkins@python.org> https://github.com/python/cpython/commit/7e8819a589c7630db9d440826143ad0a1daf948e commit: 7e8819a589c7630db9d440826143ad0a1daf948e branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Yury Selivanov <yury at magic.io> date: 2018-05-28T16:25:03-04:00 summary: bpo-31647: Fix write_eof() after close() for SelectorSocketTransport (GH-7149) (#7154) Fixed bug where calling write_eof() on a _SelectorSocketTransport after it's already closed raises AttributeError. (cherry picked from commit 23f587e395e41bd5e116312b036183f42bc4159b) Co-authored-by: twisteroid ambassador <twisteroidambassador at users.noreply.github.com> files: A Misc/NEWS.d/next/Library/2018-05-28-18-40-26.bpo-31467.s4Fad3.rst M Lib/asyncio/selector_events.py M Lib/test/test_asyncio/test_selector_events.py diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py index c7e7909449eb..81dfd7651c5e 100644 --- a/Lib/asyncio/selector_events.py +++ b/Lib/asyncio/selector_events.py @@ -804,7 +804,7 @@ def _write_ready(self): self._sock.shutdown(socket.SHUT_WR) def write_eof(self): - if self._eof: + if self._closing or self._eof: return self._eof = True if not self._buffer: diff --git a/Lib/test/test_asyncio/test_selector_events.py b/Lib/test/test_asyncio/test_selector_events.py index 0794e994c9d4..c359b458029d 100644 --- a/Lib/test/test_asyncio/test_selector_events.py +++ b/Lib/test/test_asyncio/test_selector_events.py @@ -1187,6 +1187,12 @@ def test_write_eof_buffer(self): self.sock.shutdown.assert_called_with(socket.SHUT_WR) tr.close() + def test_write_eof_after_close(self): + tr = self.socket_transport() + tr.close() + self.loop.run_until_complete(asyncio.sleep(0)) + tr.write_eof() + @mock.patch('asyncio.base_events.logger') def test_transport_close_remove_writer(self, m_log): remove_writer = self.loop._remove_writer = mock.Mock() diff --git a/Misc/NEWS.d/next/Library/2018-05-28-18-40-26.bpo-31467.s4Fad3.rst b/Misc/NEWS.d/next/Library/2018-05-28-18-40-26.bpo-31467.s4Fad3.rst new file mode 100644 index 000000000000..61cc8baa1cd5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-28-18-40-26.bpo-31467.s4Fad3.rst @@ -0,0 +1,2 @@ +Fixed bug where calling write_eof() on a _SelectorSocketTransport after it's +already closed raises AttributeError. From webhook-mailer at python.org Mon May 28 16:27:36 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Mon, 28 May 2018 20:27:36 -0000 Subject: [Python-checkins] bpo-33672: Fix Task.__repr__ crash with Cython's bogus coroutines (GH-7161) Message-ID: <mailman.23.1527539259.2800.python-checkins@python.org> https://github.com/python/cpython/commit/989b9e0e6d7dd2fa911f9bfd4744e7f3a82d6006 commit: 989b9e0e6d7dd2fa911f9bfd4744e7f3a82d6006 branch: master author: Yury Selivanov <yury at magic.io> committer: GitHub <noreply at github.com> date: 2018-05-28T16:27:34-04:00 summary: bpo-33672: Fix Task.__repr__ crash with Cython's bogus coroutines (GH-7161) files: A Misc/NEWS.d/next/Library/2018-05-28-12-29-54.bpo-33672.GM_Xm_.rst M Lib/asyncio/coroutines.py M Lib/asyncio/format_helpers.py M Lib/test/test_asyncio/test_events.py diff --git a/Lib/asyncio/coroutines.py b/Lib/asyncio/coroutines.py index c7fcd4425584..c665ebe33ee1 100644 --- a/Lib/asyncio/coroutines.py +++ b/Lib/asyncio/coroutines.py @@ -189,56 +189,63 @@ def iscoroutine(obj): def _format_coroutine(coro): assert iscoroutine(coro) - if not hasattr(coro, 'cr_code') and not hasattr(coro, 'gi_code'): - # Most likely a built-in type or a Cython coroutine. - - # Built-in types might not have __qualname__ or __name__. - coro_name = getattr( - coro, '__qualname__', - getattr(coro, '__name__', type(coro).__name__)) - coro_name = f'{coro_name}()' + is_corowrapper = isinstance(coro, CoroWrapper) + + def get_name(coro): + # Coroutines compiled with Cython sometimes don't have + # proper __qualname__ or __name__. While that is a bug + # in Cython, asyncio shouldn't crash with an AttributeError + # in its __repr__ functions. + if is_corowrapper: + return format_helpers._format_callback(coro.func, (), {}) + + if hasattr(coro, '__qualname__') and coro.__qualname__: + coro_name = coro.__qualname__ + elif hasattr(coro, '__name__') and coro.__name__: + coro_name = coro.__name__ + else: + # Stop masking Cython bugs, expose them in a friendly way. + coro_name = f'<{type(coro).__name__} without __name__>' + return f'{coro_name}()' - running = False + def is_running(coro): try: - running = coro.cr_running + return coro.cr_running except AttributeError: try: - running = coro.gi_running + return coro.gi_running except AttributeError: - pass + return False - if running: + coro_code = None + if hasattr(coro, 'cr_code') and coro.cr_code: + coro_code = coro.cr_code + elif hasattr(coro, 'gi_code') and coro.gi_code: + coro_code = coro.gi_code + + coro_name = get_name(coro) + + if not coro_code: + # Built-in types might not have __qualname__ or __name__. + if is_running(coro): return f'{coro_name} running' else: return coro_name - coro_name = None - if isinstance(coro, CoroWrapper): - func = coro.func - coro_name = coro.__qualname__ - if coro_name is not None: - coro_name = f'{coro_name}()' - else: - func = coro - - if coro_name is None: - coro_name = format_helpers._format_callback(func, (), {}) - - try: - coro_code = coro.gi_code - except AttributeError: - coro_code = coro.cr_code - - try: + coro_frame = None + if hasattr(coro, 'gi_frame') and coro.gi_frame: coro_frame = coro.gi_frame - except AttributeError: + elif hasattr(coro, 'cr_frame') and coro.cr_frame: coro_frame = coro.cr_frame - filename = coro_code.co_filename + # If Cython's coroutine has a fake code object without proper + # co_filename -- expose that. + filename = coro_code.co_filename or '<empty co_filename>' + lineno = 0 - if (isinstance(coro, CoroWrapper) and - not inspect.isgeneratorfunction(coro.func) and - coro.func is not None): + if (is_corowrapper and + coro.func is not None and + not inspect.isgeneratorfunction(coro.func)): source = format_helpers._get_function_source(coro.func) if source is not None: filename, lineno = source @@ -246,9 +253,11 @@ def _format_coroutine(coro): coro_repr = f'{coro_name} done, defined at {filename}:{lineno}' else: coro_repr = f'{coro_name} running, defined at {filename}:{lineno}' + elif coro_frame is not None: lineno = coro_frame.f_lineno coro_repr = f'{coro_name} running at {filename}:{lineno}' + else: lineno = coro_code.co_firstlineno coro_repr = f'{coro_name} done, defined at {filename}:{lineno}' diff --git a/Lib/asyncio/format_helpers.py b/Lib/asyncio/format_helpers.py index 39cfcee0c1c8..27d11fd4fa95 100644 --- a/Lib/asyncio/format_helpers.py +++ b/Lib/asyncio/format_helpers.py @@ -1,6 +1,7 @@ import functools import inspect import reprlib +import sys import traceback from . import constants @@ -45,10 +46,10 @@ def _format_callback(func, args, kwargs, suffix=''): suffix = _format_args_and_kwargs(args, kwargs) + suffix return _format_callback(func.func, func.args, func.keywords, suffix) - if hasattr(func, '__qualname__'): - func_repr = getattr(func, '__qualname__') - elif hasattr(func, '__name__'): - func_repr = getattr(func, '__name__') + if hasattr(func, '__qualname__') and func.__qualname__: + func_repr = func.__qualname__ + elif hasattr(func, '__name__') and func.__name__: + func_repr = func.__name__ else: func_repr = repr(func) diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index d7b0a665a0ab..ba28e8ce875c 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -2784,11 +2784,21 @@ def test_coroutine_like_object_debug_formatting(self): coro.cr_running = True self.assertEqual(coroutines._format_coroutine(coro), 'BBB() running') + coro.__name__ = coro.__qualname__ = None + self.assertEqual(coroutines._format_coroutine(coro), + '<CoroLike without __name__>() running') + coro = CoroLike() + coro.__qualname__ = 'CoroLike' # Some coroutines might not have '__name__', such as # built-in async_gen.asend(). self.assertEqual(coroutines._format_coroutine(coro), 'CoroLike()') + coro = CoroLike() + coro.__qualname__ = 'AAA' + coro.cr_code = None + self.assertEqual(coroutines._format_coroutine(coro), 'AAA()') + class TimerTests(unittest.TestCase): diff --git a/Misc/NEWS.d/next/Library/2018-05-28-12-29-54.bpo-33672.GM_Xm_.rst b/Misc/NEWS.d/next/Library/2018-05-28-12-29-54.bpo-33672.GM_Xm_.rst new file mode 100644 index 000000000000..36373c028639 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-28-12-29-54.bpo-33672.GM_Xm_.rst @@ -0,0 +1 @@ +Fix Task.__repr__ crash with Cython's bogus coroutines From webhook-mailer at python.org Mon May 28 16:44:17 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 28 May 2018 20:44:17 -0000 Subject: [Python-checkins] bpo-32458: Further tune start_tls tests (GH-7166) Message-ID: <mailman.24.1527540260.2800.python-checkins@python.org> https://github.com/python/cpython/commit/4b828467a3fcec0c1947e8326f67b8db12a4f303 commit: 4b828467a3fcec0c1947e8326f67b8db12a4f303 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-28T13:44:12-07:00 summary: bpo-32458: Further tune start_tls tests (GH-7166) (cherry picked from commit 8267ea2e84d355f00654dec3ad782fc7b1f680f1) Co-authored-by: Yury Selivanov <yury at magic.io> files: M Lib/test/test_asyncio/test_sslproto.py diff --git a/Lib/test/test_asyncio/test_sslproto.py b/Lib/test/test_asyncio/test_sslproto.py index 932487a9e3c6..1b2f9d2a3a2a 100644 --- a/Lib/test/test_asyncio/test_sslproto.py +++ b/Lib/test/test_asyncio/test_sslproto.py @@ -293,7 +293,7 @@ def eof_received(self): new_tr.close() - with self.tcp_server(serve) as srv: + with self.tcp_server(serve, timeout=self.TIMEOUT) as srv: self.loop.run_until_complete( asyncio.wait_for(client(srv.addr), loop=self.loop, timeout=10)) @@ -358,7 +358,7 @@ def eof_received(self): new_tr.close() - with self.tcp_server(serve) as srv: + with self.tcp_server(serve, timeout=self.TIMEOUT) as srv: self.loop.run_until_complete( asyncio.wait_for(client(srv.addr), loop=self.loop, timeout=self.TIMEOUT)) @@ -412,7 +412,8 @@ def connection_lost(self, exc): new_tr = await self.loop.start_tls( tr, proto, server_context, - server_side=True) + server_side=True, + ssl_handshake_timeout=self.TIMEOUT) await on_eof await on_con_lost @@ -429,7 +430,8 @@ def connection_lost(self, exc): lambda: proto, '127.0.0.1', 0) addr = server.sockets[0].getsockname() - with self.tcp_client(lambda sock: client(sock, addr)): + with self.tcp_client(lambda sock: client(sock, addr), + timeout=self.TIMEOUT): await asyncio.wait_for( main(proto, on_con, on_eof, on_con_lost), loop=self.loop, timeout=self.TIMEOUT) From webhook-mailer at python.org Mon May 28 17:05:07 2018 From: webhook-mailer at python.org (Steve Dower) Date: Mon, 28 May 2018 21:05:07 -0000 Subject: [Python-checkins] bro-33614: Override exit code in find_msbuild.bat (GH-7169) Message-ID: <mailman.25.1527541509.2800.python-checkins@python.org> https://github.com/python/cpython/commit/f9b364fe51ac083e3e423b1e2cefe0e1ad7d9a60 commit: f9b364fe51ac083e3e423b1e2cefe0e1ad7d9a60 branch: master author: Steve Dower <steve.dower at microsoft.com> committer: GitHub <noreply at github.com> date: 2018-05-28T14:05:05-07:00 summary: bro-33614: Override exit code in find_msbuild.bat (GH-7169) files: M PCbuild/find_msbuild.bat M PCbuild/python3dll.vcxproj diff --git a/PCbuild/find_msbuild.bat b/PCbuild/find_msbuild.bat index 24f5e2fb5d46..57512a01927e 100644 --- a/PCbuild/find_msbuild.bat +++ b/PCbuild/find_msbuild.bat @@ -57,3 +57,4 @@ @if not defined MSBUILD @echo Failed to find MSBuild @set _Py_MSBuild_Source= @if not defined MSBUILD @exit /b 1 + at exit /b 0 diff --git a/PCbuild/python3dll.vcxproj b/PCbuild/python3dll.vcxproj index 0ef7780248fb..d2a9cae5d917 100644 --- a/PCbuild/python3dll.vcxproj +++ b/PCbuild/python3dll.vcxproj @@ -142,8 +142,8 @@ <_Lines Include="@(_Symbols->'%(Symbol)')" /> </ItemGroup> <MakeDir Directories="$(IntDir)" /> - <Message Text="Updating python3stub.def" Condition="@(_OriginalLines) != @(_Lines)" Importance="high" /> + <Message Text="Updating python3stub.def" Condition="@(_Lines) != @(_OriginalLines)" Importance="high" /> <WriteLinesToFile File="$(IntDir)python3stub.def" Lines="@(_Lines)" Overwrite="true" - Condition="@(_DefLines) != @(_Lines)" /> + Condition="@(_Lines) != @(_OriginalLines)" /> </Target> </Project> \ No newline at end of file From webhook-mailer at python.org Mon May 28 17:10:23 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Mon, 28 May 2018 21:10:23 -0000 Subject: [Python-checkins] bpo-33469: RuntimeError after closing loop that used run_in_executor (GH-7171) Message-ID: <mailman.26.1527541828.2800.python-checkins@python.org> https://github.com/python/cpython/commit/fdccfe09f0b10776645fdb04a0783d6864c32b21 commit: fdccfe09f0b10776645fdb04a0783d6864c32b21 branch: master author: Yury Selivanov <yury at magic.io> committer: GitHub <noreply at github.com> date: 2018-05-28T17:10:20-04:00 summary: bpo-33469: RuntimeError after closing loop that used run_in_executor (GH-7171) files: A Misc/NEWS.d/next/Library/2018-05-28-15-55-12.bpo-33469.hmXBpY.rst M Lib/asyncio/futures.py M Lib/test/test_asyncio/test_events.py diff --git a/Lib/asyncio/futures.py b/Lib/asyncio/futures.py index 4a56f32c7745..0e0e696a2535 100644 --- a/Lib/asyncio/futures.py +++ b/Lib/asyncio/futures.py @@ -353,6 +353,9 @@ def _call_check_cancel(destination): source_loop.call_soon_threadsafe(source.cancel) def _call_set_state(source): + if (destination.cancelled() and + dest_loop is not None and dest_loop.is_closed()): + return if dest_loop is None or dest_loop is source_loop: _set_state(destination, source) else: diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index ba28e8ce875c..39d85e8df07c 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -347,6 +347,24 @@ def run(arg): self.assertEqual(res, 'yo') self.assertNotEqual(thread_id, threading.get_ident()) + def test_run_in_executor_cancel(self): + called = False + + def patched_call_soon(*args): + nonlocal called + called = True + + def run(): + time.sleep(0.05) + + f2 = self.loop.run_in_executor(None, run) + f2.cancel() + self.loop.close() + self.loop.call_soon = patched_call_soon + self.loop.call_soon_threadsafe = patched_call_soon + time.sleep(0.4) + self.assertFalse(called) + def test_reader_callback(self): r, w = socket.socketpair() r.setblocking(False) diff --git a/Misc/NEWS.d/next/Library/2018-05-28-15-55-12.bpo-33469.hmXBpY.rst b/Misc/NEWS.d/next/Library/2018-05-28-15-55-12.bpo-33469.hmXBpY.rst new file mode 100644 index 000000000000..cc1b2e436f2a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-28-15-55-12.bpo-33469.hmXBpY.rst @@ -0,0 +1 @@ +Fix RuntimeError after closing loop that used run_in_executor From webhook-mailer at python.org Mon May 28 17:54:05 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Mon, 28 May 2018 21:54:05 -0000 Subject: [Python-checkins] bpo-32610: Fix asyncio.all_tasks() to return only pending tasks. (GH-7174) Message-ID: <mailman.27.1527544448.2800.python-checkins@python.org> https://github.com/python/cpython/commit/416c1ebd9896b394790dcb4f9f035b1a44ebe9ff commit: 416c1ebd9896b394790dcb4f9f035b1a44ebe9ff branch: master author: Yury Selivanov <yury at magic.io> committer: GitHub <noreply at github.com> date: 2018-05-28T17:54:02-04:00 summary: bpo-32610: Fix asyncio.all_tasks() to return only pending tasks. (GH-7174) files: A Misc/NEWS.d/next/Library/2018-05-28-16-40-32.bpo-32610.KvUAsL.rst M Doc/library/asyncio-task.rst M Lib/asyncio/__init__.py M Lib/asyncio/runners.py M Lib/asyncio/tasks.py M Lib/test/test_asyncio/test_tasks.py M Modules/_asynciomodule.c diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index 4892333d8cee..233cc9454967 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -443,6 +443,8 @@ Task Return a set of all tasks for an event loop. By default all tasks for the current event loop are returned. + If *loop* is ``None``, :func:`get_event_loop` function + is used to get the current loop. .. classmethod:: current_task(loop=None) @@ -567,8 +569,9 @@ Task functions Return a set of :class:`Task` objects created for the loop. - If *loop* is ``None`` :func:`get_event_loop` is used for getting - current loop. + If *loop* is ``None``, :func:`get_running_loop` is used for getting + current loop (contrary to the deprecated :meth:`Task.all_tasks` method + that uses :func:`get_event_loop`.) .. versionadded:: 3.7 diff --git a/Lib/asyncio/__init__.py b/Lib/asyncio/__init__.py index 23ea055912ea..26859024300e 100644 --- a/Lib/asyncio/__init__.py +++ b/Lib/asyncio/__init__.py @@ -18,6 +18,10 @@ from .tasks import * from .transports import * +# Exposed for _asynciomodule.c to implement now deprecated +# Task.all_tasks() method. This function will be removed in 3.9. +from .tasks import _all_tasks_compat # NoQA + __all__ = (base_events.__all__ + coroutines.__all__ + events.__all__ + diff --git a/Lib/asyncio/runners.py b/Lib/asyncio/runners.py index bb54b7252786..5fbab03dd001 100644 --- a/Lib/asyncio/runners.py +++ b/Lib/asyncio/runners.py @@ -51,8 +51,7 @@ def run(main, *, debug=False): def _cancel_all_tasks(loop): - to_cancel = [task for task in tasks.all_tasks(loop) - if not task.done()] + to_cancel = tasks.all_tasks(loop) if not to_cancel: return diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index 4a9db2a3a05c..67fb57c6a781 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -33,6 +33,16 @@ def current_task(loop=None): def all_tasks(loop=None): """Return a set of all tasks for the loop.""" + if loop is None: + loop = events.get_running_loop() + return {t for t in _all_tasks + if futures._get_loop(t) is loop and not t.done()} + + +def _all_tasks_compat(loop=None): + # Different from "all_task()" by returning *all* Tasks, including + # the completed ones. Used to implement deprecated "Tasks.all_task()" + # method. if loop is None: loop = events.get_event_loop() return {t for t in _all_tasks if futures._get_loop(t) is loop} @@ -82,7 +92,7 @@ def all_tasks(cls, loop=None): "use asyncio.all_tasks() instead", PendingDeprecationWarning, stacklevel=2) - return all_tasks(loop) + return _all_tasks_compat(loop) def __init__(self, coro, *, loop=None): super().__init__(loop=loop) diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index e5334c6ff914..33300c91a367 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -1897,8 +1897,10 @@ def kill_me(loop): # See http://bugs.python.org/issue29271 for details: asyncio.set_event_loop(self.loop) try: - self.assertEqual(asyncio.all_tasks(), {task}) - self.assertEqual(asyncio.all_tasks(None), {task}) + with self.assertWarns(PendingDeprecationWarning): + self.assertEqual(Task.all_tasks(), {task}) + with self.assertWarns(PendingDeprecationWarning): + self.assertEqual(Task.all_tasks(None), {task}) finally: asyncio.set_event_loop(None) @@ -2483,6 +2485,9 @@ class TaskLike: def _loop(self): return loop + def done(self): + return False + task = TaskLike() loop = mock.Mock() @@ -2496,6 +2501,9 @@ class TaskLike: def get_loop(self): return loop + def done(self): + return False + task = TaskLike() loop = mock.Mock() @@ -2504,6 +2512,23 @@ def get_loop(self): self.assertEqual(asyncio.all_tasks(loop), {task}) self._unregister_task(task) + def test__register_task_3(self): + class TaskLike: + def get_loop(self): + return loop + + def done(self): + return True + + task = TaskLike() + loop = mock.Mock() + + self.assertEqual(asyncio.all_tasks(loop), set()) + self._register_task(task) + self.assertEqual(asyncio.all_tasks(loop), set()) + self.assertEqual(asyncio.Task.all_tasks(loop), {task}) + self._unregister_task(task) + def test__enter_task(self): task = mock.Mock() loop = mock.Mock() diff --git a/Misc/NEWS.d/next/Library/2018-05-28-16-40-32.bpo-32610.KvUAsL.rst b/Misc/NEWS.d/next/Library/2018-05-28-16-40-32.bpo-32610.KvUAsL.rst new file mode 100644 index 000000000000..372908063247 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-28-16-40-32.bpo-32610.KvUAsL.rst @@ -0,0 +1 @@ +Make asyncio.all_tasks() return only pending tasks. diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index c4d19034ce45..e3537cc81c4c 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -11,7 +11,7 @@ module _asyncio /* identifiers used from some functions */ _Py_IDENTIFIER(__asyncio_running_event_loop__); _Py_IDENTIFIER(add_done_callback); -_Py_IDENTIFIER(all_tasks); +_Py_IDENTIFIER(_all_tasks_compat); _Py_IDENTIFIER(call_soon); _Py_IDENTIFIER(cancel); _Py_IDENTIFIER(current_task); @@ -2125,7 +2125,7 @@ _asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop) return NULL; } - all_tasks_func = _PyObject_GetAttrId(asyncio_mod, &PyId_all_tasks); + all_tasks_func = _PyObject_GetAttrId(asyncio_mod, &PyId__all_tasks_compat); if (all_tasks_func == NULL) { return NULL; } From webhook-mailer at python.org Mon May 28 18:31:11 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Mon, 28 May 2018 22:31:11 -0000 Subject: [Python-checkins] bpo-33672: Fix Task.__repr__ crash with Cython's bogus coroutines (GH-7161) (GH-7173) Message-ID: <mailman.28.1527546674.2800.python-checkins@python.org> https://github.com/python/cpython/commit/075c662086859f864aa1179f57367aa470ee6335 commit: 075c662086859f864aa1179f57367aa470ee6335 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Yury Selivanov <yury at magic.io> date: 2018-05-28T18:31:07-04:00 summary: bpo-33672: Fix Task.__repr__ crash with Cython's bogus coroutines (GH-7161) (GH-7173) (cherry picked from commit 989b9e0e6d7dd2fa911f9bfd4744e7f3a82d6006) Co-authored-by: Yury Selivanov <yury at magic.io> files: A Misc/NEWS.d/next/Library/2018-05-28-12-29-54.bpo-33672.GM_Xm_.rst M Lib/asyncio/coroutines.py M Lib/asyncio/format_helpers.py M Lib/test/test_asyncio/test_events.py diff --git a/Lib/asyncio/coroutines.py b/Lib/asyncio/coroutines.py index c7fcd4425584..c665ebe33ee1 100644 --- a/Lib/asyncio/coroutines.py +++ b/Lib/asyncio/coroutines.py @@ -189,56 +189,63 @@ def iscoroutine(obj): def _format_coroutine(coro): assert iscoroutine(coro) - if not hasattr(coro, 'cr_code') and not hasattr(coro, 'gi_code'): - # Most likely a built-in type or a Cython coroutine. - - # Built-in types might not have __qualname__ or __name__. - coro_name = getattr( - coro, '__qualname__', - getattr(coro, '__name__', type(coro).__name__)) - coro_name = f'{coro_name}()' + is_corowrapper = isinstance(coro, CoroWrapper) + + def get_name(coro): + # Coroutines compiled with Cython sometimes don't have + # proper __qualname__ or __name__. While that is a bug + # in Cython, asyncio shouldn't crash with an AttributeError + # in its __repr__ functions. + if is_corowrapper: + return format_helpers._format_callback(coro.func, (), {}) + + if hasattr(coro, '__qualname__') and coro.__qualname__: + coro_name = coro.__qualname__ + elif hasattr(coro, '__name__') and coro.__name__: + coro_name = coro.__name__ + else: + # Stop masking Cython bugs, expose them in a friendly way. + coro_name = f'<{type(coro).__name__} without __name__>' + return f'{coro_name}()' - running = False + def is_running(coro): try: - running = coro.cr_running + return coro.cr_running except AttributeError: try: - running = coro.gi_running + return coro.gi_running except AttributeError: - pass + return False - if running: + coro_code = None + if hasattr(coro, 'cr_code') and coro.cr_code: + coro_code = coro.cr_code + elif hasattr(coro, 'gi_code') and coro.gi_code: + coro_code = coro.gi_code + + coro_name = get_name(coro) + + if not coro_code: + # Built-in types might not have __qualname__ or __name__. + if is_running(coro): return f'{coro_name} running' else: return coro_name - coro_name = None - if isinstance(coro, CoroWrapper): - func = coro.func - coro_name = coro.__qualname__ - if coro_name is not None: - coro_name = f'{coro_name}()' - else: - func = coro - - if coro_name is None: - coro_name = format_helpers._format_callback(func, (), {}) - - try: - coro_code = coro.gi_code - except AttributeError: - coro_code = coro.cr_code - - try: + coro_frame = None + if hasattr(coro, 'gi_frame') and coro.gi_frame: coro_frame = coro.gi_frame - except AttributeError: + elif hasattr(coro, 'cr_frame') and coro.cr_frame: coro_frame = coro.cr_frame - filename = coro_code.co_filename + # If Cython's coroutine has a fake code object without proper + # co_filename -- expose that. + filename = coro_code.co_filename or '<empty co_filename>' + lineno = 0 - if (isinstance(coro, CoroWrapper) and - not inspect.isgeneratorfunction(coro.func) and - coro.func is not None): + if (is_corowrapper and + coro.func is not None and + not inspect.isgeneratorfunction(coro.func)): source = format_helpers._get_function_source(coro.func) if source is not None: filename, lineno = source @@ -246,9 +253,11 @@ def _format_coroutine(coro): coro_repr = f'{coro_name} done, defined at {filename}:{lineno}' else: coro_repr = f'{coro_name} running, defined at {filename}:{lineno}' + elif coro_frame is not None: lineno = coro_frame.f_lineno coro_repr = f'{coro_name} running at {filename}:{lineno}' + else: lineno = coro_code.co_firstlineno coro_repr = f'{coro_name} done, defined at {filename}:{lineno}' diff --git a/Lib/asyncio/format_helpers.py b/Lib/asyncio/format_helpers.py index 39cfcee0c1c8..27d11fd4fa95 100644 --- a/Lib/asyncio/format_helpers.py +++ b/Lib/asyncio/format_helpers.py @@ -1,6 +1,7 @@ import functools import inspect import reprlib +import sys import traceback from . import constants @@ -45,10 +46,10 @@ def _format_callback(func, args, kwargs, suffix=''): suffix = _format_args_and_kwargs(args, kwargs) + suffix return _format_callback(func.func, func.args, func.keywords, suffix) - if hasattr(func, '__qualname__'): - func_repr = getattr(func, '__qualname__') - elif hasattr(func, '__name__'): - func_repr = getattr(func, '__name__') + if hasattr(func, '__qualname__') and func.__qualname__: + func_repr = func.__qualname__ + elif hasattr(func, '__name__') and func.__name__: + func_repr = func.__name__ else: func_repr = repr(func) diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index d7b0a665a0ab..ba28e8ce875c 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -2784,11 +2784,21 @@ def test_coroutine_like_object_debug_formatting(self): coro.cr_running = True self.assertEqual(coroutines._format_coroutine(coro), 'BBB() running') + coro.__name__ = coro.__qualname__ = None + self.assertEqual(coroutines._format_coroutine(coro), + '<CoroLike without __name__>() running') + coro = CoroLike() + coro.__qualname__ = 'CoroLike' # Some coroutines might not have '__name__', such as # built-in async_gen.asend(). self.assertEqual(coroutines._format_coroutine(coro), 'CoroLike()') + coro = CoroLike() + coro.__qualname__ = 'AAA' + coro.cr_code = None + self.assertEqual(coroutines._format_coroutine(coro), 'AAA()') + class TimerTests(unittest.TestCase): diff --git a/Misc/NEWS.d/next/Library/2018-05-28-12-29-54.bpo-33672.GM_Xm_.rst b/Misc/NEWS.d/next/Library/2018-05-28-12-29-54.bpo-33672.GM_Xm_.rst new file mode 100644 index 000000000000..36373c028639 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-28-12-29-54.bpo-33672.GM_Xm_.rst @@ -0,0 +1 @@ +Fix Task.__repr__ crash with Cython's bogus coroutines From webhook-mailer at python.org Mon May 28 18:31:57 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Mon, 28 May 2018 22:31:57 -0000 Subject: [Python-checkins] bpo-32410: Avoid blocking on file IO in sendfile fallback code (GH-7172) Message-ID: <mailman.29.1527546721.2800.python-checkins@python.org> https://github.com/python/cpython/commit/7165754b6b5f3b7c07050d921fa1c58bba5f0ff1 commit: 7165754b6b5f3b7c07050d921fa1c58bba5f0ff1 branch: master author: Yury Selivanov <yury at magic.io> committer: GitHub <noreply at github.com> date: 2018-05-28T18:31:55-04:00 summary: bpo-32410: Avoid blocking on file IO in sendfile fallback code (GH-7172) files: A Misc/NEWS.d/next/Library/2018-05-28-16-19-35.bpo-32410.Z1DZaF.rst M Lib/asyncio/base_events.py M Lib/asyncio/constants.py M Lib/test/test_asyncio/test_base_events.py M Lib/test/test_asyncio/test_events.py diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index a0243f5bac9a..ffd2513e33a6 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -800,7 +800,10 @@ def _getaddrinfo_debug(self, host, port, family, type, proto, flags): async def _sock_sendfile_fallback(self, sock, file, offset, count): if offset: file.seek(offset) - blocksize = min(count, 16384) if count else 16384 + blocksize = ( + min(count, constants.SENDFILE_FALLBACK_READBUFFER_SIZE) + if count else constants.SENDFILE_FALLBACK_READBUFFER_SIZE + ) buf = bytearray(blocksize) total_sent = 0 try: @@ -810,7 +813,7 @@ def _getaddrinfo_debug(self, host, port, family, type, proto, flags): if blocksize <= 0: break view = memoryview(buf)[:blocksize] - read = file.readinto(view) + read = await self.run_in_executor(None, file.readinto, view) if not read: break # EOF await self.sock_sendall(sock, view) diff --git a/Lib/asyncio/constants.py b/Lib/asyncio/constants.py index 739b0a70c13e..d7ba49694289 100644 --- a/Lib/asyncio/constants.py +++ b/Lib/asyncio/constants.py @@ -14,6 +14,10 @@ # Number of seconds to wait for SSL handshake to complete SSL_HANDSHAKE_TIMEOUT = 10.0 +# Used in sendfile fallback code. We use fallback for platforms +# that don't support sendfile, or for TLS connections. +SENDFILE_FALLBACK_READBUFFER_SIZE = 1024 * 256 + # The enum should be here to break circular dependencies between # base_events and sslproto class _SendfileMode(enum.Enum): diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index 8566a9d5504f..11e9465d3921 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -1818,12 +1818,15 @@ def connection_lost(self, exc): @classmethod def setUpClass(cls): + cls.__old_bufsize = constants.SENDFILE_FALLBACK_READBUFFER_SIZE + constants.SENDFILE_FALLBACK_READBUFFER_SIZE = 1024 * 16 with open(support.TESTFN, 'wb') as fp: fp.write(cls.DATA) super().setUpClass() @classmethod def tearDownClass(cls): + constants.SENDFILE_FALLBACK_READBUFFER_SIZE = cls.__old_bufsize support.unlink(support.TESTFN) super().tearDownClass() diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index 39d85e8df07c..e7c4fa6cecec 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -2160,6 +2160,17 @@ def connection_lost(self, exc): async def wait_closed(self): await self.fut + @classmethod + def setUpClass(cls): + cls.__old_bufsize = constants.SENDFILE_FALLBACK_READBUFFER_SIZE + constants.SENDFILE_FALLBACK_READBUFFER_SIZE = 1024 * 16 + super().setUpClass() + + @classmethod + def tearDownClass(cls): + constants.SENDFILE_FALLBACK_READBUFFER_SIZE = cls.__old_bufsize + super().tearDownClass() + def set_socket_opts(self, sock): # On macOS, SO_SNDBUF is reset by connect(). So this method # should be called after the socket is connected. diff --git a/Misc/NEWS.d/next/Library/2018-05-28-16-19-35.bpo-32410.Z1DZaF.rst b/Misc/NEWS.d/next/Library/2018-05-28-16-19-35.bpo-32410.Z1DZaF.rst new file mode 100644 index 000000000000..2d7bb2032ac5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-28-16-19-35.bpo-32410.Z1DZaF.rst @@ -0,0 +1 @@ +Avoid blocking on file IO in sendfile fallback code From webhook-mailer at python.org Mon May 28 18:38:35 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 28 May 2018 22:38:35 -0000 Subject: [Python-checkins] bro-33614: Override exit code in find_msbuild.bat (GH-7169) Message-ID: <mailman.30.1527547116.2800.python-checkins@python.org> https://github.com/python/cpython/commit/100db0b5841e2e593bcdbf4a31c21c4075268cb5 commit: 100db0b5841e2e593bcdbf4a31c21c4075268cb5 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-28T15:38:30-07:00 summary: bro-33614: Override exit code in find_msbuild.bat (GH-7169) (cherry picked from commit f9b364fe51ac083e3e423b1e2cefe0e1ad7d9a60) Co-authored-by: Steve Dower <steve.dower at microsoft.com> files: M PCbuild/find_msbuild.bat M PCbuild/python3dll.vcxproj diff --git a/PCbuild/find_msbuild.bat b/PCbuild/find_msbuild.bat index 1364a17432ef..b20fc42125ca 100644 --- a/PCbuild/find_msbuild.bat +++ b/PCbuild/find_msbuild.bat @@ -58,3 +58,4 @@ @if not defined MSBUILD @echo Failed to find MSBuild @set _Py_MSBuild_Source= @if not defined MSBUILD @exit /b 1 + at exit /b 0 diff --git a/PCbuild/python3dll.vcxproj b/PCbuild/python3dll.vcxproj index 0ef7780248fb..d2a9cae5d917 100644 --- a/PCbuild/python3dll.vcxproj +++ b/PCbuild/python3dll.vcxproj @@ -142,8 +142,8 @@ <_Lines Include="@(_Symbols->'%(Symbol)')" /> </ItemGroup> <MakeDir Directories="$(IntDir)" /> - <Message Text="Updating python3stub.def" Condition="@(_OriginalLines) != @(_Lines)" Importance="high" /> + <Message Text="Updating python3stub.def" Condition="@(_Lines) != @(_OriginalLines)" Importance="high" /> <WriteLinesToFile File="$(IntDir)python3stub.def" Lines="@(_Lines)" Overwrite="true" - Condition="@(_DefLines) != @(_Lines)" /> + Condition="@(_Lines) != @(_OriginalLines)" /> </Target> </Project> \ No newline at end of file From webhook-mailer at python.org Mon May 28 18:39:28 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 28 May 2018 22:39:28 -0000 Subject: [Python-checkins] bro-33614: Override exit code in find_msbuild.bat (GH-7169) Message-ID: <mailman.31.1527547170.2800.python-checkins@python.org> https://github.com/python/cpython/commit/6025451d6fbebdb998b65705ccf0ead5d4355a75 commit: 6025451d6fbebdb998b65705ccf0ead5d4355a75 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-28T15:39:25-07:00 summary: bro-33614: Override exit code in find_msbuild.bat (GH-7169) (cherry picked from commit f9b364fe51ac083e3e423b1e2cefe0e1ad7d9a60) Co-authored-by: Steve Dower <steve.dower at microsoft.com> files: M PCbuild/find_msbuild.bat M PCbuild/python3dll.vcxproj diff --git a/PCbuild/find_msbuild.bat b/PCbuild/find_msbuild.bat index 24f5e2fb5d46..57512a01927e 100644 --- a/PCbuild/find_msbuild.bat +++ b/PCbuild/find_msbuild.bat @@ -57,3 +57,4 @@ @if not defined MSBUILD @echo Failed to find MSBuild @set _Py_MSBuild_Source= @if not defined MSBUILD @exit /b 1 + at exit /b 0 diff --git a/PCbuild/python3dll.vcxproj b/PCbuild/python3dll.vcxproj index 0ef7780248fb..d2a9cae5d917 100644 --- a/PCbuild/python3dll.vcxproj +++ b/PCbuild/python3dll.vcxproj @@ -142,8 +142,8 @@ <_Lines Include="@(_Symbols->'%(Symbol)')" /> </ItemGroup> <MakeDir Directories="$(IntDir)" /> - <Message Text="Updating python3stub.def" Condition="@(_OriginalLines) != @(_Lines)" Importance="high" /> + <Message Text="Updating python3stub.def" Condition="@(_Lines) != @(_OriginalLines)" Importance="high" /> <WriteLinesToFile File="$(IntDir)python3stub.def" Lines="@(_Lines)" Overwrite="true" - Condition="@(_DefLines) != @(_Lines)" /> + Condition="@(_Lines) != @(_OriginalLines)" /> </Target> </Project> \ No newline at end of file From webhook-mailer at python.org Mon May 28 18:50:05 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 28 May 2018 22:50:05 -0000 Subject: [Python-checkins] bpo-33469: RuntimeError after closing loop that used run_in_executor (GH-7171) Message-ID: <mailman.32.1527547806.2800.python-checkins@python.org> https://github.com/python/cpython/commit/8d8b86116fae91570c26fa48974b54986fbd1b72 commit: 8d8b86116fae91570c26fa48974b54986fbd1b72 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-28T15:50:02-07:00 summary: bpo-33469: RuntimeError after closing loop that used run_in_executor (GH-7171) (cherry picked from commit fdccfe09f0b10776645fdb04a0783d6864c32b21) Co-authored-by: Yury Selivanov <yury at magic.io> files: A Misc/NEWS.d/next/Library/2018-05-28-15-55-12.bpo-33469.hmXBpY.rst M Lib/asyncio/futures.py M Lib/test/test_asyncio/test_events.py diff --git a/Lib/asyncio/futures.py b/Lib/asyncio/futures.py index 4a56f32c7745..0e0e696a2535 100644 --- a/Lib/asyncio/futures.py +++ b/Lib/asyncio/futures.py @@ -353,6 +353,9 @@ def _call_check_cancel(destination): source_loop.call_soon_threadsafe(source.cancel) def _call_set_state(source): + if (destination.cancelled() and + dest_loop is not None and dest_loop.is_closed()): + return if dest_loop is None or dest_loop is source_loop: _set_state(destination, source) else: diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index ba28e8ce875c..39d85e8df07c 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -347,6 +347,24 @@ def run(arg): self.assertEqual(res, 'yo') self.assertNotEqual(thread_id, threading.get_ident()) + def test_run_in_executor_cancel(self): + called = False + + def patched_call_soon(*args): + nonlocal called + called = True + + def run(): + time.sleep(0.05) + + f2 = self.loop.run_in_executor(None, run) + f2.cancel() + self.loop.close() + self.loop.call_soon = patched_call_soon + self.loop.call_soon_threadsafe = patched_call_soon + time.sleep(0.4) + self.assertFalse(called) + def test_reader_callback(self): r, w = socket.socketpair() r.setblocking(False) diff --git a/Misc/NEWS.d/next/Library/2018-05-28-15-55-12.bpo-33469.hmXBpY.rst b/Misc/NEWS.d/next/Library/2018-05-28-15-55-12.bpo-33469.hmXBpY.rst new file mode 100644 index 000000000000..cc1b2e436f2a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-28-15-55-12.bpo-33469.hmXBpY.rst @@ -0,0 +1 @@ +Fix RuntimeError after closing loop that used run_in_executor From webhook-mailer at python.org Mon May 28 19:20:37 2018 From: webhook-mailer at python.org (Steve Dower) Date: Mon, 28 May 2018 23:20:37 -0000 Subject: [Python-checkins] bpo-33673: Install python-docs-theme even if Sphinx is already installed (GH-7163) Message-ID: <mailman.33.1527549639.2800.python-checkins@python.org> https://github.com/python/cpython/commit/3d3e66c2daebd8e6b18944eac7546168c0006c78 commit: 3d3e66c2daebd8e6b18944eac7546168c0006c78 branch: master author: Andr?s Delfino <adelfino at gmail.com> committer: Steve Dower <steve.dower at microsoft.com> date: 2018-05-28T16:20:34-07:00 summary: bpo-33673: Install python-docs-theme even if Sphinx is already installed (GH-7163) files: M Doc/make.bat diff --git a/Doc/make.bat b/Doc/make.bat index c69cfae31941..3a4b365689db 100644 --- a/Doc/make.bat +++ b/Doc/make.bat @@ -13,7 +13,13 @@ if not defined SPHINXBUILD ( %PYTHON% -c "import sphinx" > nul 2> nul if errorlevel 1 ( echo Installing sphinx with %PYTHON% - %PYTHON% -m pip install sphinx python-docs-theme + %PYTHON% -m pip install sphinx + if errorlevel 1 exit /B + ) + %PYTHON% -c "import python_docs_theme" > nul 2> nul + if errorlevel 1 ( + echo Installing python-docs-theme with %PYTHON% + %PYTHON% -m pip install python-docs-theme if errorlevel 1 exit /B ) set SPHINXBUILD=%PYTHON% -c "import sphinx, sys; sys.argv[0] = 'sphinx-build'; sphinx.main()" From webhook-mailer at python.org Mon May 28 19:28:24 2018 From: webhook-mailer at python.org (Steve Dower) Date: Mon, 28 May 2018 23:28:24 -0000 Subject: [Python-checkins] bpo-33670: Expose Sphinx errorlevel (GH-7156) Message-ID: <mailman.34.1527550107.2800.python-checkins@python.org> https://github.com/python/cpython/commit/8c1ad0c4f69390fded09012e1ed5242c45753bb4 commit: 8c1ad0c4f69390fded09012e1ed5242c45753bb4 branch: master author: Andr?s Delfino <adelfino at gmail.com> committer: Steve Dower <steve.dower at microsoft.com> date: 2018-05-28T16:28:22-07:00 summary: bpo-33670: Expose Sphinx errorlevel (GH-7156) files: M Doc/make.bat diff --git a/Doc/make.bat b/Doc/make.bat index 3a4b365689db..7ca84979a300 100644 --- a/Doc/make.bat +++ b/Doc/make.bat @@ -22,7 +22,7 @@ if not defined SPHINXBUILD ( %PYTHON% -m pip install python-docs-theme if errorlevel 1 exit /B ) - set SPHINXBUILD=%PYTHON% -c "import sphinx, sys; sys.argv[0] = 'sphinx-build'; sphinx.main()" + set SPHINXBUILD=%PYTHON% -c "import sphinx, sys; sys.argv[0] = 'sphinx-build'; sys.exit(sphinx.main())" ) if not defined BLURB ( From webhook-mailer at python.org Mon May 28 19:33:38 2018 From: webhook-mailer at python.org (Victor Stinner) Date: Mon, 28 May 2018 23:33:38 -0000 Subject: [Python-checkins] bpo-33674: asyncio: Fix SSLProtocol race (GH-7175) Message-ID: <mailman.35.1527550420.2800.python-checkins@python.org> https://github.com/python/cpython/commit/be00a5583a2cb696335c527b921d1868266a42c6 commit: be00a5583a2cb696335c527b921d1868266a42c6 branch: master author: Victor Stinner <vstinner at redhat.com> committer: GitHub <noreply at github.com> date: 2018-05-29T01:33:35+02:00 summary: bpo-33674: asyncio: Fix SSLProtocol race (GH-7175) Fix a race condition in SSLProtocol.connection_made() of asyncio.sslproto: start immediately the handshake instead of using call_soon(). Previously, data_received() could be called before the handshake started, causing the handshake to hang or fail. files: A Misc/NEWS.d/next/Library/2018-05-28-22-49-59.bpo-33674.6LFFj7.rst M Lib/asyncio/sslproto.py diff --git a/Lib/asyncio/sslproto.py b/Lib/asyncio/sslproto.py index 2bfa45dd1585..ab43e93b28bc 100644 --- a/Lib/asyncio/sslproto.py +++ b/Lib/asyncio/sslproto.py @@ -592,10 +592,10 @@ def _start_handshake(self): # (b'', 1) is a special value in _process_write_backlog() to do # the SSL handshake self._write_backlog.append((b'', 1)) - self._loop.call_soon(self._process_write_backlog) self._handshake_timeout_handle = \ self._loop.call_later(self._ssl_handshake_timeout, self._check_handshake_timeout) + self._process_write_backlog() def _check_handshake_timeout(self): if self._in_handshake is True: diff --git a/Misc/NEWS.d/next/Library/2018-05-28-22-49-59.bpo-33674.6LFFj7.rst b/Misc/NEWS.d/next/Library/2018-05-28-22-49-59.bpo-33674.6LFFj7.rst new file mode 100644 index 000000000000..1e9868073f78 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-28-22-49-59.bpo-33674.6LFFj7.rst @@ -0,0 +1,4 @@ +Fix a race condition in SSLProtocol.connection_made() of asyncio.sslproto: +start immediately the handshake instead of using call_soon(). Previously, +data_received() could be called before the handshake started, causing the +handshake to hang or fail. From webhook-mailer at python.org Mon May 28 20:16:47 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 29 May 2018 00:16:47 -0000 Subject: [Python-checkins] bpo-32610: Fix asyncio.all_tasks() to return only pending tasks. (GH-7174) Message-ID: <mailman.36.1527553007.2800.python-checkins@python.org> https://github.com/python/cpython/commit/ddc613f20394eba25f2420f6d2fa62b277c95058 commit: ddc613f20394eba25f2420f6d2fa62b277c95058 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-28T17:16:43-07:00 summary: bpo-32610: Fix asyncio.all_tasks() to return only pending tasks. (GH-7174) (cherry picked from commit 416c1ebd9896b394790dcb4f9f035b1a44ebe9ff) Co-authored-by: Yury Selivanov <yury at magic.io> files: A Misc/NEWS.d/next/Library/2018-05-28-16-40-32.bpo-32610.KvUAsL.rst M Doc/library/asyncio-task.rst M Lib/asyncio/__init__.py M Lib/asyncio/runners.py M Lib/asyncio/tasks.py M Lib/test/test_asyncio/test_tasks.py M Modules/_asynciomodule.c diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index 4892333d8cee..233cc9454967 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -443,6 +443,8 @@ Task Return a set of all tasks for an event loop. By default all tasks for the current event loop are returned. + If *loop* is ``None``, :func:`get_event_loop` function + is used to get the current loop. .. classmethod:: current_task(loop=None) @@ -567,8 +569,9 @@ Task functions Return a set of :class:`Task` objects created for the loop. - If *loop* is ``None`` :func:`get_event_loop` is used for getting - current loop. + If *loop* is ``None``, :func:`get_running_loop` is used for getting + current loop (contrary to the deprecated :meth:`Task.all_tasks` method + that uses :func:`get_event_loop`.) .. versionadded:: 3.7 diff --git a/Lib/asyncio/__init__.py b/Lib/asyncio/__init__.py index 23ea055912ea..26859024300e 100644 --- a/Lib/asyncio/__init__.py +++ b/Lib/asyncio/__init__.py @@ -18,6 +18,10 @@ from .tasks import * from .transports import * +# Exposed for _asynciomodule.c to implement now deprecated +# Task.all_tasks() method. This function will be removed in 3.9. +from .tasks import _all_tasks_compat # NoQA + __all__ = (base_events.__all__ + coroutines.__all__ + events.__all__ + diff --git a/Lib/asyncio/runners.py b/Lib/asyncio/runners.py index bb54b7252786..5fbab03dd001 100644 --- a/Lib/asyncio/runners.py +++ b/Lib/asyncio/runners.py @@ -51,8 +51,7 @@ def run(main, *, debug=False): def _cancel_all_tasks(loop): - to_cancel = [task for task in tasks.all_tasks(loop) - if not task.done()] + to_cancel = tasks.all_tasks(loop) if not to_cancel: return diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index 4a9db2a3a05c..67fb57c6a781 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -33,6 +33,16 @@ def current_task(loop=None): def all_tasks(loop=None): """Return a set of all tasks for the loop.""" + if loop is None: + loop = events.get_running_loop() + return {t for t in _all_tasks + if futures._get_loop(t) is loop and not t.done()} + + +def _all_tasks_compat(loop=None): + # Different from "all_task()" by returning *all* Tasks, including + # the completed ones. Used to implement deprecated "Tasks.all_task()" + # method. if loop is None: loop = events.get_event_loop() return {t for t in _all_tasks if futures._get_loop(t) is loop} @@ -82,7 +92,7 @@ def all_tasks(cls, loop=None): "use asyncio.all_tasks() instead", PendingDeprecationWarning, stacklevel=2) - return all_tasks(loop) + return _all_tasks_compat(loop) def __init__(self, coro, *, loop=None): super().__init__(loop=loop) diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index e5334c6ff914..33300c91a367 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -1897,8 +1897,10 @@ def kill_me(loop): # See http://bugs.python.org/issue29271 for details: asyncio.set_event_loop(self.loop) try: - self.assertEqual(asyncio.all_tasks(), {task}) - self.assertEqual(asyncio.all_tasks(None), {task}) + with self.assertWarns(PendingDeprecationWarning): + self.assertEqual(Task.all_tasks(), {task}) + with self.assertWarns(PendingDeprecationWarning): + self.assertEqual(Task.all_tasks(None), {task}) finally: asyncio.set_event_loop(None) @@ -2483,6 +2485,9 @@ class TaskLike: def _loop(self): return loop + def done(self): + return False + task = TaskLike() loop = mock.Mock() @@ -2496,6 +2501,9 @@ class TaskLike: def get_loop(self): return loop + def done(self): + return False + task = TaskLike() loop = mock.Mock() @@ -2504,6 +2512,23 @@ def get_loop(self): self.assertEqual(asyncio.all_tasks(loop), {task}) self._unregister_task(task) + def test__register_task_3(self): + class TaskLike: + def get_loop(self): + return loop + + def done(self): + return True + + task = TaskLike() + loop = mock.Mock() + + self.assertEqual(asyncio.all_tasks(loop), set()) + self._register_task(task) + self.assertEqual(asyncio.all_tasks(loop), set()) + self.assertEqual(asyncio.Task.all_tasks(loop), {task}) + self._unregister_task(task) + def test__enter_task(self): task = mock.Mock() loop = mock.Mock() diff --git a/Misc/NEWS.d/next/Library/2018-05-28-16-40-32.bpo-32610.KvUAsL.rst b/Misc/NEWS.d/next/Library/2018-05-28-16-40-32.bpo-32610.KvUAsL.rst new file mode 100644 index 000000000000..372908063247 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-28-16-40-32.bpo-32610.KvUAsL.rst @@ -0,0 +1 @@ +Make asyncio.all_tasks() return only pending tasks. diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index c4d19034ce45..e3537cc81c4c 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -11,7 +11,7 @@ module _asyncio /* identifiers used from some functions */ _Py_IDENTIFIER(__asyncio_running_event_loop__); _Py_IDENTIFIER(add_done_callback); -_Py_IDENTIFIER(all_tasks); +_Py_IDENTIFIER(_all_tasks_compat); _Py_IDENTIFIER(call_soon); _Py_IDENTIFIER(cancel); _Py_IDENTIFIER(current_task); @@ -2125,7 +2125,7 @@ _asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop) return NULL; } - all_tasks_func = _PyObject_GetAttrId(asyncio_mod, &PyId_all_tasks); + all_tasks_func = _PyObject_GetAttrId(asyncio_mod, &PyId__all_tasks_compat); if (all_tasks_func == NULL) { return NULL; } From webhook-mailer at python.org Mon May 28 20:24:39 2018 From: webhook-mailer at python.org (Steve Dower) Date: Tue, 29 May 2018 00:24:39 -0000 Subject: [Python-checkins] bpo-32878: Adds documentation for st_ino on Windows (GH-5764) Message-ID: <mailman.37.1527553480.2800.python-checkins@python.org> https://github.com/python/cpython/commit/3e51a3d5927c680d5410ff11ff8d5e5bb9ffb1e7 commit: 3e51a3d5927c680d5410ff11ff8d5e5bb9ffb1e7 branch: master author: Steve Dower <steve.dower at microsoft.com> committer: GitHub <noreply at github.com> date: 2018-05-28T17:24:36-07:00 summary: bpo-32878: Adds documentation for st_ino on Windows (GH-5764) files: M Doc/library/os.rst diff --git a/Doc/library/os.rst b/Doc/library/os.rst index 4b4e93106692..d5bc612f451c 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -2378,7 +2378,13 @@ features: .. attribute:: st_ino - Inode number. + Platform dependent, but if non-zero, uniquely identifies the + file for a given value of ``st_dev``. Typically: + + * the inode number on Unix, + * the `file index + <https://msdn.microsoft.com/en-us/library/aa363788>`_ on + Windows .. attribute:: st_dev @@ -2537,6 +2543,10 @@ features: .. versionadded:: 3.5 Added the :attr:`st_file_attributes` member on Windows. + .. versionchanged:: 3.5 + Windows now returns the file index as :attr:`st_ino` when + available. + .. versionadded:: 3.7 Added the :attr:`st_fstype` member to Solaris/derivatives. From webhook-mailer at python.org Mon May 28 21:03:41 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 29 May 2018 01:03:41 -0000 Subject: [Python-checkins] bpo-33673: Install python-docs-theme even if Sphinx is already installed (GH-7163) Message-ID: <mailman.38.1527555824.2800.python-checkins@python.org> https://github.com/python/cpython/commit/a379dea11e989da73c335a83ea7368c5e070987e commit: a379dea11e989da73c335a83ea7368c5e070987e branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-28T18:03:38-07:00 summary: bpo-33673: Install python-docs-theme even if Sphinx is already installed (GH-7163) (cherry picked from commit 3d3e66c2daebd8e6b18944eac7546168c0006c78) Co-authored-by: Andr?s Delfino <adelfino at gmail.com> files: M Doc/make.bat diff --git a/Doc/make.bat b/Doc/make.bat index c69cfae31941..3a4b365689db 100644 --- a/Doc/make.bat +++ b/Doc/make.bat @@ -13,7 +13,13 @@ if not defined SPHINXBUILD ( %PYTHON% -c "import sphinx" > nul 2> nul if errorlevel 1 ( echo Installing sphinx with %PYTHON% - %PYTHON% -m pip install sphinx python-docs-theme + %PYTHON% -m pip install sphinx + if errorlevel 1 exit /B + ) + %PYTHON% -c "import python_docs_theme" > nul 2> nul + if errorlevel 1 ( + echo Installing python-docs-theme with %PYTHON% + %PYTHON% -m pip install python-docs-theme if errorlevel 1 exit /B ) set SPHINXBUILD=%PYTHON% -c "import sphinx, sys; sys.argv[0] = 'sphinx-build'; sphinx.main()" From webhook-mailer at python.org Mon May 28 21:08:19 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 29 May 2018 01:08:19 -0000 Subject: [Python-checkins] bpo-33673: Install python-docs-theme even if Sphinx is already installed (GH-7163) Message-ID: <mailman.39.1527556102.2800.python-checkins@python.org> https://github.com/python/cpython/commit/d8af8302430d85589df0a76d43dda9bac5be27c4 commit: d8af8302430d85589df0a76d43dda9bac5be27c4 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-28T18:08:17-07:00 summary: bpo-33673: Install python-docs-theme even if Sphinx is already installed (GH-7163) (cherry picked from commit 3d3e66c2daebd8e6b18944eac7546168c0006c78) Co-authored-by: Andr?s Delfino <adelfino at gmail.com> files: M Doc/make.bat diff --git a/Doc/make.bat b/Doc/make.bat index c69cfae31941..3a4b365689db 100644 --- a/Doc/make.bat +++ b/Doc/make.bat @@ -13,7 +13,13 @@ if not defined SPHINXBUILD ( %PYTHON% -c "import sphinx" > nul 2> nul if errorlevel 1 ( echo Installing sphinx with %PYTHON% - %PYTHON% -m pip install sphinx python-docs-theme + %PYTHON% -m pip install sphinx + if errorlevel 1 exit /B + ) + %PYTHON% -c "import python_docs_theme" > nul 2> nul + if errorlevel 1 ( + echo Installing python-docs-theme with %PYTHON% + %PYTHON% -m pip install python-docs-theme if errorlevel 1 exit /B ) set SPHINXBUILD=%PYTHON% -c "import sphinx, sys; sys.argv[0] = 'sphinx-build'; sphinx.main()" From webhook-mailer at python.org Mon May 28 21:32:20 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 29 May 2018 01:32:20 -0000 Subject: [Python-checkins] bpo-33469: RuntimeError after closing loop that used run_in_executor (GH-7171) Message-ID: <mailman.40.1527557544.2800.python-checkins@python.org> https://github.com/python/cpython/commit/a6d6bd70ac95a0f7bbfe07d4e60b43afcec370d2 commit: a6d6bd70ac95a0f7bbfe07d4e60b43afcec370d2 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-28T18:32:17-07:00 summary: bpo-33469: RuntimeError after closing loop that used run_in_executor (GH-7171) (cherry picked from commit fdccfe09f0b10776645fdb04a0783d6864c32b21) Co-authored-by: Yury Selivanov <yury at magic.io> files: A Misc/NEWS.d/next/Library/2018-05-28-15-55-12.bpo-33469.hmXBpY.rst M Lib/asyncio/futures.py M Lib/test/test_asyncio/test_events.py diff --git a/Lib/asyncio/futures.py b/Lib/asyncio/futures.py index 9ff143039a32..3a0b57e30eab 100644 --- a/Lib/asyncio/futures.py +++ b/Lib/asyncio/futures.py @@ -408,6 +408,9 @@ def _call_check_cancel(destination): source_loop.call_soon_threadsafe(source.cancel) def _call_set_state(source): + if (destination.cancelled() and + dest_loop is not None and dest_loop.is_closed()): + return if dest_loop is None or dest_loop is source_loop: _set_state(destination, source) else: diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index 2c4629ab4924..1ecc89f2e758 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -362,6 +362,24 @@ def run(arg): self.assertEqual(res, 'yo') self.assertNotEqual(thread_id, threading.get_ident()) + def test_run_in_executor_cancel(self): + called = False + + def patched_call_soon(*args): + nonlocal called + called = True + + def run(): + time.sleep(0.05) + + f2 = self.loop.run_in_executor(None, run) + f2.cancel() + self.loop.close() + self.loop.call_soon = patched_call_soon + self.loop.call_soon_threadsafe = patched_call_soon + time.sleep(0.4) + self.assertFalse(called) + def test_reader_callback(self): r, w = test_utils.socketpair() r.setblocking(False) diff --git a/Misc/NEWS.d/next/Library/2018-05-28-15-55-12.bpo-33469.hmXBpY.rst b/Misc/NEWS.d/next/Library/2018-05-28-15-55-12.bpo-33469.hmXBpY.rst new file mode 100644 index 000000000000..cc1b2e436f2a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-28-15-55-12.bpo-33469.hmXBpY.rst @@ -0,0 +1 @@ +Fix RuntimeError after closing loop that used run_in_executor From webhook-mailer at python.org Mon May 28 21:42:48 2018 From: webhook-mailer at python.org (Ned Deily) Date: Tue, 29 May 2018 01:42:48 -0000 Subject: [Python-checkins] bpo-32410: Avoid blocking on file IO in sendfile fallback code (GH-7172) (#7182) Message-ID: <mailman.41.1527558169.2800.python-checkins@python.org> https://github.com/python/cpython/commit/420092e255389008b399efa61db300fe44356ee8 commit: 420092e255389008b399efa61db300fe44356ee8 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Ned Deily <nad at python.org> date: 2018-05-28T21:42:45-04:00 summary: bpo-32410: Avoid blocking on file IO in sendfile fallback code (GH-7172) (#7182) (cherry picked from commit 7165754b6b5f3b7c07050d921fa1c58bba5f0ff1) Co-authored-by: Yury Selivanov <yury at magic.io> files: A Misc/NEWS.d/next/Library/2018-05-28-16-19-35.bpo-32410.Z1DZaF.rst M Lib/asyncio/base_events.py M Lib/asyncio/constants.py M Lib/test/test_asyncio/test_base_events.py M Lib/test/test_asyncio/test_events.py diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index a0243f5bac9a..ffd2513e33a6 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -800,7 +800,10 @@ def _getaddrinfo_debug(self, host, port, family, type, proto, flags): async def _sock_sendfile_fallback(self, sock, file, offset, count): if offset: file.seek(offset) - blocksize = min(count, 16384) if count else 16384 + blocksize = ( + min(count, constants.SENDFILE_FALLBACK_READBUFFER_SIZE) + if count else constants.SENDFILE_FALLBACK_READBUFFER_SIZE + ) buf = bytearray(blocksize) total_sent = 0 try: @@ -810,7 +813,7 @@ def _getaddrinfo_debug(self, host, port, family, type, proto, flags): if blocksize <= 0: break view = memoryview(buf)[:blocksize] - read = file.readinto(view) + read = await self.run_in_executor(None, file.readinto, view) if not read: break # EOF await self.sock_sendall(sock, view) diff --git a/Lib/asyncio/constants.py b/Lib/asyncio/constants.py index 739b0a70c13e..d7ba49694289 100644 --- a/Lib/asyncio/constants.py +++ b/Lib/asyncio/constants.py @@ -14,6 +14,10 @@ # Number of seconds to wait for SSL handshake to complete SSL_HANDSHAKE_TIMEOUT = 10.0 +# Used in sendfile fallback code. We use fallback for platforms +# that don't support sendfile, or for TLS connections. +SENDFILE_FALLBACK_READBUFFER_SIZE = 1024 * 256 + # The enum should be here to break circular dependencies between # base_events and sslproto class _SendfileMode(enum.Enum): diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index 8566a9d5504f..11e9465d3921 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -1818,12 +1818,15 @@ def connection_lost(self, exc): @classmethod def setUpClass(cls): + cls.__old_bufsize = constants.SENDFILE_FALLBACK_READBUFFER_SIZE + constants.SENDFILE_FALLBACK_READBUFFER_SIZE = 1024 * 16 with open(support.TESTFN, 'wb') as fp: fp.write(cls.DATA) super().setUpClass() @classmethod def tearDownClass(cls): + constants.SENDFILE_FALLBACK_READBUFFER_SIZE = cls.__old_bufsize support.unlink(support.TESTFN) super().tearDownClass() diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index 39d85e8df07c..e7c4fa6cecec 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -2160,6 +2160,17 @@ def connection_lost(self, exc): async def wait_closed(self): await self.fut + @classmethod + def setUpClass(cls): + cls.__old_bufsize = constants.SENDFILE_FALLBACK_READBUFFER_SIZE + constants.SENDFILE_FALLBACK_READBUFFER_SIZE = 1024 * 16 + super().setUpClass() + + @classmethod + def tearDownClass(cls): + constants.SENDFILE_FALLBACK_READBUFFER_SIZE = cls.__old_bufsize + super().tearDownClass() + def set_socket_opts(self, sock): # On macOS, SO_SNDBUF is reset by connect(). So this method # should be called after the socket is connected. diff --git a/Misc/NEWS.d/next/Library/2018-05-28-16-19-35.bpo-32410.Z1DZaF.rst b/Misc/NEWS.d/next/Library/2018-05-28-16-19-35.bpo-32410.Z1DZaF.rst new file mode 100644 index 000000000000..2d7bb2032ac5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-28-16-19-35.bpo-32410.Z1DZaF.rst @@ -0,0 +1 @@ +Avoid blocking on file IO in sendfile fallback code From webhook-mailer at python.org Mon May 28 21:44:19 2018 From: webhook-mailer at python.org (Ned Deily) Date: Tue, 29 May 2018 01:44:19 -0000 Subject: [Python-checkins] bpo-33674: asyncio: Fix SSLProtocol race (GH-7175) (#7187) Message-ID: <mailman.42.1527558262.2800.python-checkins@python.org> https://github.com/python/cpython/commit/0dd8fd03584b61cd769be88f5a2fb59b0d8f6d18 commit: 0dd8fd03584b61cd769be88f5a2fb59b0d8f6d18 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Ned Deily <nad at python.org> date: 2018-05-28T21:44:16-04:00 summary: bpo-33674: asyncio: Fix SSLProtocol race (GH-7175) (#7187) Fix a race condition in SSLProtocol.connection_made() of asyncio.sslproto: start immediately the handshake instead of using call_soon(). Previously, data_received() could be called before the handshake started, causing the handshake to hang or fail. (cherry picked from commit be00a5583a2cb696335c527b921d1868266a42c6) Co-authored-by: Victor Stinner <vstinner at redhat.com> files: A Misc/NEWS.d/next/Library/2018-05-28-22-49-59.bpo-33674.6LFFj7.rst M Lib/asyncio/sslproto.py diff --git a/Lib/asyncio/sslproto.py b/Lib/asyncio/sslproto.py index 2bfa45dd1585..ab43e93b28bc 100644 --- a/Lib/asyncio/sslproto.py +++ b/Lib/asyncio/sslproto.py @@ -592,10 +592,10 @@ def _start_handshake(self): # (b'', 1) is a special value in _process_write_backlog() to do # the SSL handshake self._write_backlog.append((b'', 1)) - self._loop.call_soon(self._process_write_backlog) self._handshake_timeout_handle = \ self._loop.call_later(self._ssl_handshake_timeout, self._check_handshake_timeout) + self._process_write_backlog() def _check_handshake_timeout(self): if self._in_handshake is True: diff --git a/Misc/NEWS.d/next/Library/2018-05-28-22-49-59.bpo-33674.6LFFj7.rst b/Misc/NEWS.d/next/Library/2018-05-28-22-49-59.bpo-33674.6LFFj7.rst new file mode 100644 index 000000000000..1e9868073f78 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-28-22-49-59.bpo-33674.6LFFj7.rst @@ -0,0 +1,4 @@ +Fix a race condition in SSLProtocol.connection_made() of asyncio.sslproto: +start immediately the handshake instead of using call_soon(). Previously, +data_received() could be called before the handshake started, causing the +handshake to hang or fail. From webhook-mailer at python.org Mon May 28 21:45:37 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 29 May 2018 01:45:37 -0000 Subject: [Python-checkins] bpo-33670: Expose Sphinx errorlevel (GH-7156) Message-ID: <mailman.43.1527558340.2800.python-checkins@python.org> https://github.com/python/cpython/commit/1827615500e94801653f67fd026a2c95930faf59 commit: 1827615500e94801653f67fd026a2c95930faf59 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-28T18:45:34-07:00 summary: bpo-33670: Expose Sphinx errorlevel (GH-7156) (cherry picked from commit 8c1ad0c4f69390fded09012e1ed5242c45753bb4) Co-authored-by: Andr?s Delfino <adelfino at gmail.com> files: M Doc/make.bat diff --git a/Doc/make.bat b/Doc/make.bat index 3a4b365689db..7ca84979a300 100644 --- a/Doc/make.bat +++ b/Doc/make.bat @@ -22,7 +22,7 @@ if not defined SPHINXBUILD ( %PYTHON% -m pip install python-docs-theme if errorlevel 1 exit /B ) - set SPHINXBUILD=%PYTHON% -c "import sphinx, sys; sys.argv[0] = 'sphinx-build'; sphinx.main()" + set SPHINXBUILD=%PYTHON% -c "import sphinx, sys; sys.argv[0] = 'sphinx-build'; sys.exit(sphinx.main())" ) if not defined BLURB ( From webhook-mailer at python.org Mon May 28 21:49:45 2018 From: webhook-mailer at python.org (Ned Deily) Date: Tue, 29 May 2018 01:49:45 -0000 Subject: [Python-checkins] bpo-32878: Adds documentation for st_ino on Windows (GH-5764) (#7189) Message-ID: <mailman.44.1527558588.2800.python-checkins@python.org> https://github.com/python/cpython/commit/78e14f8eb4b4a96d0766f2857c00de21d3303b17 commit: 78e14f8eb4b4a96d0766f2857c00de21d3303b17 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Ned Deily <nad at python.org> date: 2018-05-28T21:49:42-04:00 summary: bpo-32878: Adds documentation for st_ino on Windows (GH-5764) (#7189) (cherry picked from commit 3e51a3d5927c680d5410ff11ff8d5e5bb9ffb1e7) Co-authored-by: Steve Dower <steve.dower at microsoft.com> files: M Doc/library/os.rst diff --git a/Doc/library/os.rst b/Doc/library/os.rst index 784acf0ac5d8..60ab94f4769e 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -2378,7 +2378,13 @@ features: .. attribute:: st_ino - Inode number. + Platform dependent, but if non-zero, uniquely identifies the + file for a given value of ``st_dev``. Typically: + + * the inode number on Unix, + * the `file index + <https://msdn.microsoft.com/en-us/library/aa363788>`_ on + Windows .. attribute:: st_dev @@ -2537,6 +2543,10 @@ features: .. versionadded:: 3.5 Added the :attr:`st_file_attributes` member on Windows. + .. versionchanged:: 3.5 + Windows now returns the file index as :attr:`st_ino` when + available. + .. versionadded:: 3.7 Added the :attr:`st_fstype` member to Solaris/derivatives. From webhook-mailer at python.org Mon May 28 21:49:53 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 29 May 2018 01:49:53 -0000 Subject: [Python-checkins] bpo-33670: Expose Sphinx errorlevel (GH-7156) Message-ID: <mailman.45.1527558597.2800.python-checkins@python.org> https://github.com/python/cpython/commit/08beaf7d60c247b485fb578be1ef14bbc796ca88 commit: 08beaf7d60c247b485fb578be1ef14bbc796ca88 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-28T18:49:50-07:00 summary: bpo-33670: Expose Sphinx errorlevel (GH-7156) (cherry picked from commit 8c1ad0c4f69390fded09012e1ed5242c45753bb4) Co-authored-by: Andr?s Delfino <adelfino at gmail.com> files: M Doc/make.bat diff --git a/Doc/make.bat b/Doc/make.bat index 3a4b365689db..7ca84979a300 100644 --- a/Doc/make.bat +++ b/Doc/make.bat @@ -22,7 +22,7 @@ if not defined SPHINXBUILD ( %PYTHON% -m pip install python-docs-theme if errorlevel 1 exit /B ) - set SPHINXBUILD=%PYTHON% -c "import sphinx, sys; sys.argv[0] = 'sphinx-build'; sphinx.main()" + set SPHINXBUILD=%PYTHON% -c "import sphinx, sys; sys.argv[0] = 'sphinx-build'; sys.exit(sphinx.main())" ) if not defined BLURB ( From webhook-mailer at python.org Mon May 28 22:27:16 2018 From: webhook-mailer at python.org (Steve Dower) Date: Tue, 29 May 2018 02:27:16 -0000 Subject: [Python-checkins] bpo-32878: Adds documentation for st_ino on Windows (GH-5764) (GH-7190) Message-ID: <mailman.46.1527560838.2800.python-checkins@python.org> https://github.com/python/cpython/commit/325320d5f5a4480a6f4f92dcf86b9dbb7eb5c791 commit: 325320d5f5a4480a6f4f92dcf86b9dbb7eb5c791 branch: 3.6 author: Steve Dower <steve.dower at microsoft.com> committer: GitHub <noreply at github.com> date: 2018-05-28T19:27:11-07:00 summary: bpo-32878: Adds documentation for st_ino on Windows (GH-5764) (GH-7190) files: M Doc/library/os.rst diff --git a/Doc/library/os.rst b/Doc/library/os.rst index b3179acac0d8..e9ee51416bc0 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -2263,7 +2263,13 @@ features: .. attribute:: st_ino - Inode number. + Platform dependent, but if non-zero, uniquely identifies the + file for a given value of ``st_dev``. Typically: + + * the inode number on Unix, + * the `file index + <https://msdn.microsoft.com/en-us/library/aa363788>`_ on + Windows .. attribute:: st_dev @@ -2416,6 +2422,10 @@ features: .. versionadded:: 3.5 Added the :attr:`st_file_attributes` member on Windows. + .. versionchanged:: 3.5 + Windows now returns the file index as :attr:`st_ino` when + available. + .. function:: stat_float_times([newvalue]) From webhook-mailer at python.org Tue May 29 00:46:53 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Tue, 29 May 2018 04:46:53 -0000 Subject: [Python-checkins] bpo-33674: asyncio: Fix SSLProtocol race (GH-7175) (GH-7188) Message-ID: <mailman.47.1527569217.2800.python-checkins@python.org> https://github.com/python/cpython/commit/7593b8a5075ff45d71be9f62980be6a9c005afa9 commit: 7593b8a5075ff45d71be9f62980be6a9c005afa9 branch: 3.6 author: Victor Stinner <vstinner at redhat.com> committer: Yury Selivanov <yury at magic.io> date: 2018-05-29T00:46:48-04:00 summary: bpo-33674: asyncio: Fix SSLProtocol race (GH-7175) (GH-7188) Fix a race condition in SSLProtocol.connection_made() of asyncio.sslproto: start immediately the handshake instead of using call_soon(). Previously, data_received() could be called before the handshake started, causing the handshake to hang or fail. (cherry picked from commit be00a5583a2cb696335c527b921d1868266a42c6) files: A Misc/NEWS.d/next/Library/2018-05-28-22-49-59.bpo-33674.6LFFj7.rst M Lib/asyncio/sslproto.py diff --git a/Lib/asyncio/sslproto.py b/Lib/asyncio/sslproto.py index a82babb6b9e2..367f7d07a418 100644 --- a/Lib/asyncio/sslproto.py +++ b/Lib/asyncio/sslproto.py @@ -574,7 +574,7 @@ def _start_handshake(self): # (b'', 1) is a special value in _process_write_backlog() to do # the SSL handshake self._write_backlog.append((b'', 1)) - self._loop.call_soon(self._process_write_backlog) + self._process_write_backlog() def _on_handshake_complete(self, handshake_exc): self._in_handshake = False diff --git a/Misc/NEWS.d/next/Library/2018-05-28-22-49-59.bpo-33674.6LFFj7.rst b/Misc/NEWS.d/next/Library/2018-05-28-22-49-59.bpo-33674.6LFFj7.rst new file mode 100644 index 000000000000..1e9868073f78 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-28-22-49-59.bpo-33674.6LFFj7.rst @@ -0,0 +1,4 @@ +Fix a race condition in SSLProtocol.connection_made() of asyncio.sslproto: +start immediately the handshake instead of using call_soon(). Previously, +data_received() could be called before the handshake started, causing the +handshake to hang or fail. From webhook-mailer at python.org Tue May 29 00:55:30 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Tue, 29 May 2018 04:55:30 -0000 Subject: [Python-checkins] bpo-33672: Fix Task.__repr__ crash with Cython's bogus coroutines (GH-7180) Message-ID: <mailman.48.1527569734.2800.python-checkins@python.org> https://github.com/python/cpython/commit/e151f83deab9819fb8d9dfc59f9baa4a7273226c commit: e151f83deab9819fb8d9dfc59f9baa4a7273226c branch: 3.6 author: Yury Selivanov <yury at magic.io> committer: GitHub <noreply at github.com> date: 2018-05-29T00:55:27-04:00 summary: bpo-33672: Fix Task.__repr__ crash with Cython's bogus coroutines (GH-7180) [3.6 backport of 989b9e0] files: A Misc/NEWS.d/next/Library/2018-05-28-17-45-06.bpo-33672.GM_Xm_.rst M Lib/asyncio/coroutines.py M Lib/asyncio/events.py M Lib/test/test_asyncio/test_events.py diff --git a/Lib/asyncio/coroutines.py b/Lib/asyncio/coroutines.py index 520a309f8460..a9022f92a52a 100644 --- a/Lib/asyncio/coroutines.py +++ b/Lib/asyncio/coroutines.py @@ -310,18 +310,25 @@ def _format_coroutine(coro): if coro_name is None: coro_name = events._format_callback(func, (), {}) - try: - coro_code = coro.gi_code - except AttributeError: + coro_code = None + if hasattr(coro, 'cr_code') and coro.cr_code: coro_code = coro.cr_code + elif hasattr(coro, 'gi_code') and coro.gi_code: + coro_code = coro.gi_code - try: - coro_frame = coro.gi_frame - except AttributeError: + coro_frame = None + if hasattr(coro, 'cr_frame') and coro.cr_frame: coro_frame = coro.cr_frame + elif hasattr(coro, 'gi_frame') and coro.gi_frame: + coro_frame = coro.gi_frame + + filename = '<empty co_filename>' + if coro_code and coro_code.co_filename: + filename = coro_code.co_filename - filename = coro_code.co_filename lineno = 0 + coro_repr = coro_name + if (isinstance(coro, CoroWrapper) and not inspect.isgeneratorfunction(coro.func) and coro.func is not None): @@ -338,7 +345,7 @@ def _format_coroutine(coro): lineno = coro_frame.f_lineno coro_repr = ('%s running at %s:%s' % (coro_name, filename, lineno)) - else: + elif coro_code: lineno = coro_code.co_firstlineno coro_repr = ('%s done, defined at %s:%s' % (coro_name, filename, lineno)) diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py index 05dc8969f44a..e654efc5526a 100644 --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -58,10 +58,10 @@ def _format_callback(func, args, kwargs, suffix=''): suffix = _format_args_and_kwargs(args, kwargs) + suffix return _format_callback(func.func, func.args, func.keywords, suffix) - if hasattr(func, '__qualname__'): - func_repr = getattr(func, '__qualname__') - elif hasattr(func, '__name__'): - func_repr = getattr(func, '__name__') + if hasattr(func, '__qualname__') and func.__qualname__: + func_repr = func.__qualname__ + elif hasattr(func, '__name__') and func.__name__: + func_repr = func.__name__ else: func_repr = repr(func) diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index 1ecc89f2e758..548a4610f772 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -2467,6 +2467,28 @@ def __await__(self): # built-in async_gen.asend(). self.assertEqual(coroutines._format_coroutine(coro), 'Coro()') + coro = Coro() + coro.__qualname__ = 'AAA' + coro.cr_code = None + self.assertEqual(coroutines._format_coroutine(coro), 'AAA()') + + coro = Coro() + coro.__qualname__ = 'AAA' + coro.cr_code = None + coro.cr_frame = None + self.assertEqual(coroutines._format_coroutine(coro), 'AAA()') + + coro = Coro() + coro.__qualname__ = None + coro.cr_code = None + coro.cr_frame = None + self.assertEqual(coroutines._format_coroutine(coro), f'{repr(coro)}()') + + coro = Coro() + coro.cr_code = None + coro.cr_frame = None + self.assertEqual(coroutines._format_coroutine(coro), f'{repr(coro)}()') + class TimerTests(unittest.TestCase): diff --git a/Misc/NEWS.d/next/Library/2018-05-28-17-45-06.bpo-33672.GM_Xm_.rst b/Misc/NEWS.d/next/Library/2018-05-28-17-45-06.bpo-33672.GM_Xm_.rst new file mode 100644 index 000000000000..36373c028639 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-28-17-45-06.bpo-33672.GM_Xm_.rst @@ -0,0 +1 @@ +Fix Task.__repr__ crash with Cython's bogus coroutines From webhook-mailer at python.org Tue May 29 01:00:14 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Tue, 29 May 2018 05:00:14 -0000 Subject: [Python-checkins] bpo-33674: Pause the transport as early as possible (#7192) Message-ID: <mailman.49.1527570016.2800.python-checkins@python.org> https://github.com/python/cpython/commit/f295587c45f96b62d24f9a12cef6931b0805f596 commit: f295587c45f96b62d24f9a12cef6931b0805f596 branch: master author: Yury Selivanov <yury at magic.io> committer: GitHub <noreply at github.com> date: 2018-05-29T01:00:12-04:00 summary: bpo-33674: Pause the transport as early as possible (#7192) files: A Misc/NEWS.d/next/Library/2018-05-29-00-37-56.bpo-33674.2IkGhL.rst M Lib/asyncio/base_events.py diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index ffd2513e33a6..61938e90c375 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -1106,10 +1106,13 @@ def _check_sendfile_params(self, sock, file, offset, count): ssl_handshake_timeout=ssl_handshake_timeout, call_connection_made=False) + # Pause early so that "ssl_protocol.data_received()" doesn't + # have a chance to get called before "ssl_protocol.connection_made()". + transport.pause_reading() + transport.set_protocol(ssl_protocol) self.call_soon(ssl_protocol.connection_made, transport) - if not transport.is_reading(): - self.call_soon(transport.resume_reading) + self.call_soon(transport.resume_reading) await waiter return ssl_protocol._app_transport diff --git a/Misc/NEWS.d/next/Library/2018-05-29-00-37-56.bpo-33674.2IkGhL.rst b/Misc/NEWS.d/next/Library/2018-05-29-00-37-56.bpo-33674.2IkGhL.rst new file mode 100644 index 000000000000..66baca16d69f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-29-00-37-56.bpo-33674.2IkGhL.rst @@ -0,0 +1,2 @@ +Pause the transport as early as possible to further reduce the risk of +data_received() being called before connection_made(). From webhook-mailer at python.org Tue May 29 01:59:06 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 29 May 2018 05:59:06 -0000 Subject: [Python-checkins] bpo-33674: Pause the transport as early as possible (GH-7192) Message-ID: <mailman.50.1527573549.2800.python-checkins@python.org> https://github.com/python/cpython/commit/eca085993cb8620ba9232560f46d91326a13cdd2 commit: eca085993cb8620ba9232560f46d91326a13cdd2 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-28T22:59:03-07:00 summary: bpo-33674: Pause the transport as early as possible (GH-7192) (cherry picked from commit f295587c45f96b62d24f9a12cef6931b0805f596) Co-authored-by: Yury Selivanov <yury at magic.io> files: A Misc/NEWS.d/next/Library/2018-05-29-00-37-56.bpo-33674.2IkGhL.rst M Lib/asyncio/base_events.py diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py index ffd2513e33a6..61938e90c375 100644 --- a/Lib/asyncio/base_events.py +++ b/Lib/asyncio/base_events.py @@ -1106,10 +1106,13 @@ def _check_sendfile_params(self, sock, file, offset, count): ssl_handshake_timeout=ssl_handshake_timeout, call_connection_made=False) + # Pause early so that "ssl_protocol.data_received()" doesn't + # have a chance to get called before "ssl_protocol.connection_made()". + transport.pause_reading() + transport.set_protocol(ssl_protocol) self.call_soon(ssl_protocol.connection_made, transport) - if not transport.is_reading(): - self.call_soon(transport.resume_reading) + self.call_soon(transport.resume_reading) await waiter return ssl_protocol._app_transport diff --git a/Misc/NEWS.d/next/Library/2018-05-29-00-37-56.bpo-33674.2IkGhL.rst b/Misc/NEWS.d/next/Library/2018-05-29-00-37-56.bpo-33674.2IkGhL.rst new file mode 100644 index 000000000000..66baca16d69f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-29-00-37-56.bpo-33674.2IkGhL.rst @@ -0,0 +1,2 @@ +Pause the transport as early as possible to further reduce the risk of +data_received() being called before connection_made(). From webhook-mailer at python.org Tue May 29 03:49:22 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Tue, 29 May 2018 07:49:22 -0000 Subject: [Python-checkins] bpo-32911: Revert bpo-29463. (GH-7121) Message-ID: <mailman.51.1527580166.2800.python-checkins@python.org> https://github.com/python/cpython/commit/2641ee5040abb090e66e4ff80c33b76729b36e75 commit: 2641ee5040abb090e66e4ff80c33b76729b36e75 branch: 3.7 author: Serhiy Storchaka <storchaka at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-29T10:49:10+03:00 summary: bpo-32911: Revert bpo-29463. (GH-7121) Remove the docstring attribute of AST types and restore docstring expression as a first stmt in their body. Co-authored-by: INADA Naoki <methane at users.noreply.github.com> files: A Misc/NEWS.d/next/Core and Builtins/2018-02-27-20-57-00.bpo-32911.cmKfco.rst M Doc/library/ast.rst M Doc/whatsnew/3.7.rst M Include/Python-ast.h M Lib/ast.py M Lib/importlib/_bootstrap_external.py M Lib/test/test_ast.py M Lib/test/test_opcodes.py M Misc/NEWS.d/3.7.0a1.rst M Parser/Python.asdl M Python/Python-ast.c M Python/ast.c M Python/ast_opt.c M Python/compile.c M Python/future.c M Python/importlib.h M Python/importlib_external.h M Tools/parser/unparse.py diff --git a/Doc/library/ast.rst b/Doc/library/ast.rst index a75a6afbf2d7..9ff422cdf503 100644 --- a/Doc/library/ast.rst +++ b/Doc/library/ast.rst @@ -151,10 +151,6 @@ and classes for traversing abstract syntax trees: .. versionchanged:: 3.5 :class:`AsyncFunctionDef` is now supported. - .. versionchanged:: 3.7 - The docstring is now exported from the node docstring field, instead of - the first body statement. - .. function:: fix_missing_locations(node) diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index b466e74cffb4..8b94cdcc9e6a 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -2161,13 +2161,6 @@ Changes in Python Behavior Changes in the Python API ------------------------- -* ``Module``, ``FunctionDef``, ``AsyncFunctionDef``, and - ``ClassDef`` AST nodes now have the new ``docstring`` attribute. - The first statement in their body is not considered as a docstring - anymore. ``co_firstlineno`` and ``co_lnotab`` of code object for class - and module are affected by this change. (Contributed by INADA Naoki and - Eugene Toder in :issue:`29463`.) - * :meth:`socketserver.ThreadingMixIn.server_close` now waits until all non-daemon threads complete. Set the new :attr:`socketserver.ThreadingMixIn.block_on_close` class attribute to diff --git a/Include/Python-ast.h b/Include/Python-ast.h index 26dfef8fe153..8e0f750a8250 100644 --- a/Include/Python-ast.h +++ b/Include/Python-ast.h @@ -46,7 +46,6 @@ struct _mod { union { struct { asdl_seq *body; - string docstring; } Module; struct { @@ -81,7 +80,6 @@ struct _stmt { asdl_seq *body; asdl_seq *decorator_list; expr_ty returns; - string docstring; } FunctionDef; struct { @@ -90,7 +88,6 @@ struct _stmt { asdl_seq *body; asdl_seq *decorator_list; expr_ty returns; - string docstring; } AsyncFunctionDef; struct { @@ -99,7 +96,6 @@ struct _stmt { asdl_seq *keywords; asdl_seq *body; asdl_seq *decorator_list; - string docstring; } ClassDef; struct { @@ -443,27 +439,26 @@ struct _withitem { }; -#define Module(a0, a1, a2) _Py_Module(a0, a1, a2) -mod_ty _Py_Module(asdl_seq * body, string docstring, PyArena *arena); +#define Module(a0, a1) _Py_Module(a0, a1) +mod_ty _Py_Module(asdl_seq * body, PyArena *arena); #define Interactive(a0, a1) _Py_Interactive(a0, a1) mod_ty _Py_Interactive(asdl_seq * body, PyArena *arena); #define Expression(a0, a1) _Py_Expression(a0, a1) mod_ty _Py_Expression(expr_ty body, PyArena *arena); #define Suite(a0, a1) _Py_Suite(a0, a1) mod_ty _Py_Suite(asdl_seq * body, PyArena *arena); -#define FunctionDef(a0, a1, a2, a3, a4, a5, a6, a7, a8) _Py_FunctionDef(a0, a1, a2, a3, a4, a5, a6, a7, a8) +#define FunctionDef(a0, a1, a2, a3, a4, a5, a6, a7) _Py_FunctionDef(a0, a1, a2, a3, a4, a5, a6, a7) stmt_ty _Py_FunctionDef(identifier name, arguments_ty args, asdl_seq * body, - asdl_seq * decorator_list, expr_ty returns, string - docstring, int lineno, int col_offset, PyArena *arena); -#define AsyncFunctionDef(a0, a1, a2, a3, a4, a5, a6, a7, a8) _Py_AsyncFunctionDef(a0, a1, a2, a3, a4, a5, a6, a7, a8) + asdl_seq * decorator_list, expr_ty returns, int lineno, + int col_offset, PyArena *arena); +#define AsyncFunctionDef(a0, a1, a2, a3, a4, a5, a6, a7) _Py_AsyncFunctionDef(a0, a1, a2, a3, a4, a5, a6, a7) stmt_ty _Py_AsyncFunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq * decorator_list, expr_ty returns, - string docstring, int lineno, int col_offset, - PyArena *arena); -#define ClassDef(a0, a1, a2, a3, a4, a5, a6, a7, a8) _Py_ClassDef(a0, a1, a2, a3, a4, a5, a6, a7, a8) + int lineno, int col_offset, PyArena *arena); +#define ClassDef(a0, a1, a2, a3, a4, a5, a6, a7) _Py_ClassDef(a0, a1, a2, a3, a4, a5, a6, a7) stmt_ty _Py_ClassDef(identifier name, asdl_seq * bases, asdl_seq * keywords, - asdl_seq * body, asdl_seq * decorator_list, string - docstring, int lineno, int col_offset, PyArena *arena); + asdl_seq * body, asdl_seq * decorator_list, int lineno, + int col_offset, PyArena *arena); #define Return(a0, a1, a2, a3) _Py_Return(a0, a1, a2, a3) stmt_ty _Py_Return(expr_ty value, int lineno, int col_offset, PyArena *arena); #define Delete(a0, a1, a2, a3) _Py_Delete(a0, a1, a2, a3) diff --git a/Lib/ast.py b/Lib/ast.py index 2ecb03f38bc0..134d9d27582e 100644 --- a/Lib/ast.py +++ b/Lib/ast.py @@ -206,7 +206,15 @@ def get_docstring(node, clean=True): """ if not isinstance(node, (AsyncFunctionDef, FunctionDef, ClassDef, Module)): raise TypeError("%r can't have docstrings" % node.__class__.__name__) - text = node.docstring + if not node.body: + return None + node = node.body[0].value + if isinstance(node, Str): + text = node.s + elif isinstance(node, Constant) and isinstance(node.value, str): + text = node.value + else: + return None if clean and text: import inspect text = inspect.cleandoc(text) diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index 490f20db49c6..f4be86274cab 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -246,6 +246,8 @@ def _write_atomic(path, data, mode=0o666): # Python 3.7a2 3391 (update GET_AITER #31709) # Python 3.7a4 3392 (PEP 552: Deterministic pycs #31650) # Python 3.7b1 3393 (remove STORE_ANNOTATION opcode #32550) +# Python 3.7rc1 3394 (restored docstring as the firts stmt in the body; +# this might affected the first line number #32911) # # MAGIC must change whenever the bytecode emitted by the compiler may no # longer be understood by older implementations of the eval loop (usually @@ -254,7 +256,7 @@ def _write_atomic(path, data, mode=0o666): # Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array # in PC/launcher.c must also be updated. -MAGIC_NUMBER = (3393).to_bytes(2, 'little') + b'\r\n' +MAGIC_NUMBER = (3394).to_bytes(2, 'little') + b'\r\n' _RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c _PYCACHE = '__pycache__' diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py index 67f363ad31f3..ab32d9d389e6 100644 --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -327,24 +327,9 @@ def test_classattrs(self): def test_module(self): body = [ast.Num(42)] - x = ast.Module(body, None) + x = ast.Module(body) self.assertEqual(x.body, body) - def test_docstring(self): - body = [] # AST nodes having docstring must accept empty body - x = ast.Module(body, "module docstring") - self.assertEqual(x.docstring, "module docstring") - - a = ast.arguments() - x = ast.FunctionDef("x", a, body, [], None, "func docstring") - self.assertEqual(x.docstring, "func docstring") - - x = ast.AsyncFunctionDef("x", a, body, [], None, "async func docstring") - self.assertEqual(x.docstring, "async func docstring") - - x = ast.ClassDef("x", [], [], body, [], "class docstring") - self.assertEqual(x.docstring, "class docstring") - def test_nodeclasses(self): # Zero arguments constructor explicitly allowed x = ast.BinOp() @@ -411,13 +396,13 @@ def test_pickling(self): def test_invalid_sum(self): pos = dict(lineno=2, col_offset=3) - m = ast.Module([ast.Expr(ast.expr(**pos), **pos)], "doc") + m = ast.Module([ast.Expr(ast.expr(**pos), **pos)]) with self.assertRaises(TypeError) as cm: compile(m, "<test>", "exec") self.assertIn("but got <_ast.expr", str(cm.exception)) def test_invalid_identitifer(self): - m = ast.Module([ast.Expr(ast.Name(42, ast.Load()))], None) + m = ast.Module([ast.Expr(ast.Name(42, ast.Load()))]) ast.fix_missing_locations(m) with self.assertRaises(TypeError) as cm: compile(m, "<test>", "exec") @@ -462,18 +447,18 @@ def test_dump(self): self.assertEqual(ast.dump(node), "Module(body=[Expr(value=Call(func=Name(id='spam', ctx=Load()), " "args=[Name(id='eggs', ctx=Load()), Str(s='and cheese')], " - "keywords=[]))], docstring=None)" + "keywords=[]))])" ) self.assertEqual(ast.dump(node, annotate_fields=False), "Module([Expr(Call(Name('spam', Load()), [Name('eggs', Load()), " - "Str('and cheese')], []))], None)" + "Str('and cheese')], []))])" ) self.assertEqual(ast.dump(node, include_attributes=True), "Module(body=[Expr(value=Call(func=Name(id='spam', ctx=Load(), " "lineno=1, col_offset=0), args=[Name(id='eggs', ctx=Load(), " "lineno=1, col_offset=5), Str(s='and cheese', lineno=1, " "col_offset=11)], keywords=[], " - "lineno=1, col_offset=0), lineno=1, col_offset=0)], docstring=None)" + "lineno=1, col_offset=0), lineno=1, col_offset=0)])" ) def test_copy_location(self): @@ -498,7 +483,7 @@ def test_fix_missing_locations(self): "Expr(value=Call(func=Name(id='spam', ctx=Load(), lineno=1, " "col_offset=0), args=[Str(s='eggs', lineno=1, col_offset=0)], " "keywords=[], lineno=1, " - "col_offset=0), lineno=1, col_offset=0)], docstring=None)" + "col_offset=0), lineno=1, col_offset=0)])" ) def test_increment_lineno(self): @@ -589,7 +574,7 @@ def test_bad_integer(self): names=[ast.alias(name='sleep')], level=None, lineno=None, col_offset=None)] - mod = ast.Module(body, None) + mod = ast.Module(body) with self.assertRaises(ValueError) as cm: compile(mod, 'test', 'exec') self.assertIn("invalid integer value: None", str(cm.exception)) @@ -599,7 +584,7 @@ def test_level_as_none(self): names=[ast.alias(name='sleep')], level=None, lineno=0, col_offset=0)] - mod = ast.Module(body, None) + mod = ast.Module(body) code = compile(mod, 'test', 'exec') ns = {} exec(code, ns) @@ -617,11 +602,11 @@ def mod(self, mod, msg=None, mode="exec", *, exc=ValueError): self.assertIn(msg, str(cm.exception)) def expr(self, node, msg=None, *, exc=ValueError): - mod = ast.Module([ast.Expr(node)], None) + mod = ast.Module([ast.Expr(node)]) self.mod(mod, msg, exc=exc) def stmt(self, stmt, msg=None): - mod = ast.Module([stmt], None) + mod = ast.Module([stmt]) self.mod(mod, msg) def test_module(self): @@ -663,16 +648,16 @@ def arguments(args=None, vararg=None, def test_funcdef(self): a = ast.arguments([], None, [], [], None, []) - f = ast.FunctionDef("x", a, [], [], None, None) + f = ast.FunctionDef("x", a, [], [], None) self.stmt(f, "empty body on FunctionDef") f = ast.FunctionDef("x", a, [ast.Pass()], [ast.Name("x", ast.Store())], - None, None) + None) self.stmt(f, "must have Load context") f = ast.FunctionDef("x", a, [ast.Pass()], [], - ast.Name("x", ast.Store()), None) + ast.Name("x", ast.Store())) self.stmt(f, "must have Load context") def fac(args): - return ast.FunctionDef("x", args, [ast.Pass()], [], None, None) + return ast.FunctionDef("x", args, [ast.Pass()], [], None) self._check_arguments(fac, self.stmt) def test_classdef(self): @@ -686,7 +671,7 @@ def cls(bases=None, keywords=None, body=None, decorator_list=None): if decorator_list is None: decorator_list = [] return ast.ClassDef("myclass", bases, keywords, - body, decorator_list, None) + body, decorator_list) self.stmt(cls(bases=[ast.Name("x", ast.Store())]), "must have Load context") self.stmt(cls(keywords=[ast.keyword("x", ast.Name("x", ast.Store()))]), @@ -1124,53 +1109,53 @@ def main(): #### EVERYTHING BELOW IS GENERATED ##### exec_results = [ -('Module', [('Expr', (1, 0), ('NameConstant', (1, 0), None))], None), -('Module', [], 'module docstring'), -('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('Pass', (1, 9))], [], None, None)], None), -('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [], [], None, 'function docstring')], None), -('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None)], None, [], [], None, []), [('Pass', (1, 10))], [], None, None)], None), -('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None)], None, [], [], None, [('Num', (1, 8), 0)]), [('Pass', (1, 12))], [], None, None)], None), -('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], ('arg', (1, 7), 'args', None), [], [], None, []), [('Pass', (1, 14))], [], None, None)], None), -('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], ('arg', (1, 8), 'kwargs', None), []), [('Pass', (1, 17))], [], None, None)], None), -('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None), ('arg', (1, 9), 'b', None), ('arg', (1, 14), 'c', None), ('arg', (1, 22), 'd', None), ('arg', (1, 28), 'e', None)], ('arg', (1, 35), 'args', None), [('arg', (1, 41), 'f', None)], [('Num', (1, 43), 42)], ('arg', (1, 49), 'kwargs', None), [('Num', (1, 11), 1), ('NameConstant', (1, 16), None), ('List', (1, 24), [], ('Load',)), ('Dict', (1, 30), [], [])]), [], [], None, 'doc for f()')], None), -('Module', [('ClassDef', (1, 0), 'C', [], [], [('Pass', (1, 8))], [], None)], None), -('Module', [('ClassDef', (1, 0), 'C', [], [], [], [], 'docstring for class C')], None), -('Module', [('ClassDef', (1, 0), 'C', [('Name', (1, 8), 'object', ('Load',))], [], [('Pass', (1, 17))], [], None)], None), -('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('Return', (1, 8), ('Num', (1, 15), 1))], [], None, None)], None), -('Module', [('Delete', (1, 0), [('Name', (1, 4), 'v', ('Del',))])], None), -('Module', [('Assign', (1, 0), [('Name', (1, 0), 'v', ('Store',))], ('Num', (1, 4), 1))], None), -('Module', [('AugAssign', (1, 0), ('Name', (1, 0), 'v', ('Store',)), ('Add',), ('Num', (1, 5), 1))], None), -('Module', [('For', (1, 0), ('Name', (1, 4), 'v', ('Store',)), ('Name', (1, 9), 'v', ('Load',)), [('Pass', (1, 11))], [])], None), -('Module', [('While', (1, 0), ('Name', (1, 6), 'v', ('Load',)), [('Pass', (1, 8))], [])], None), -('Module', [('If', (1, 0), ('Name', (1, 3), 'v', ('Load',)), [('Pass', (1, 5))], [])], None), -('Module', [('With', (1, 0), [('withitem', ('Name', (1, 5), 'x', ('Load',)), ('Name', (1, 10), 'y', ('Store',)))], [('Pass', (1, 13))])], None), -('Module', [('With', (1, 0), [('withitem', ('Name', (1, 5), 'x', ('Load',)), ('Name', (1, 10), 'y', ('Store',))), ('withitem', ('Name', (1, 13), 'z', ('Load',)), ('Name', (1, 18), 'q', ('Store',)))], [('Pass', (1, 21))])], None), -('Module', [('Raise', (1, 0), ('Call', (1, 6), ('Name', (1, 6), 'Exception', ('Load',)), [('Str', (1, 16), 'string')], []), None)], None), -('Module', [('Try', (1, 0), [('Pass', (2, 2))], [('ExceptHandler', (3, 0), ('Name', (3, 7), 'Exception', ('Load',)), None, [('Pass', (4, 2))])], [], [])], None), -('Module', [('Try', (1, 0), [('Pass', (2, 2))], [], [], [('Pass', (4, 2))])], None), -('Module', [('Assert', (1, 0), ('Name', (1, 7), 'v', ('Load',)), None)], None), -('Module', [('Import', (1, 0), [('alias', 'sys', None)])], None), -('Module', [('ImportFrom', (1, 0), 'sys', [('alias', 'v', None)], 0)], None), -('Module', [('Global', (1, 0), ['v'])], None), -('Module', [('Expr', (1, 0), ('Num', (1, 0), 1))], None), -('Module', [('Pass', (1, 0))], None), -('Module', [('For', (1, 0), ('Name', (1, 4), 'v', ('Store',)), ('Name', (1, 9), 'v', ('Load',)), [('Break', (1, 11))], [])], None), -('Module', [('For', (1, 0), ('Name', (1, 4), 'v', ('Store',)), ('Name', (1, 9), 'v', ('Load',)), [('Continue', (1, 11))], [])], None), -('Module', [('For', (1, 0), ('Tuple', (1, 4), [('Name', (1, 4), 'a', ('Store',)), ('Name', (1, 6), 'b', ('Store',))], ('Store',)), ('Name', (1, 11), 'c', ('Load',)), [('Pass', (1, 14))], [])], None), -('Module', [('Expr', (1, 0), ('ListComp', (1, 1), ('Tuple', (1, 2), [('Name', (1, 2), 'a', ('Load',)), ('Name', (1, 4), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 11), [('Name', (1, 11), 'a', ('Store',)), ('Name', (1, 13), 'b', ('Store',))], ('Store',)), ('Name', (1, 18), 'c', ('Load',)), [], 0)]))], None), -('Module', [('Expr', (1, 0), ('GeneratorExp', (1, 1), ('Tuple', (1, 2), [('Name', (1, 2), 'a', ('Load',)), ('Name', (1, 4), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 11), [('Name', (1, 11), 'a', ('Store',)), ('Name', (1, 13), 'b', ('Store',))], ('Store',)), ('Name', (1, 18), 'c', ('Load',)), [], 0)]))], None), -('Module', [('Expr', (1, 0), ('GeneratorExp', (1, 1), ('Tuple', (1, 2), [('Name', (1, 2), 'a', ('Load',)), ('Name', (1, 4), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 12), [('Name', (1, 12), 'a', ('Store',)), ('Name', (1, 14), 'b', ('Store',))], ('Store',)), ('Name', (1, 20), 'c', ('Load',)), [], 0)]))], None), -('Module', [('Expr', (1, 0), ('GeneratorExp', (2, 4), ('Tuple', (3, 4), [('Name', (3, 4), 'Aa', ('Load',)), ('Name', (5, 7), 'Bb', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (8, 4), [('Name', (8, 4), 'Aa', ('Store',)), ('Name', (10, 4), 'Bb', ('Store',))], ('Store',)), ('Name', (10, 10), 'Cc', ('Load',)), [], 0)]))], None), -('Module', [('Expr', (1, 0), ('DictComp', (1, 0), ('Name', (1, 1), 'a', ('Load',)), ('Name', (1, 5), 'b', ('Load',)), [('comprehension', ('Name', (1, 11), 'w', ('Store',)), ('Name', (1, 16), 'x', ('Load',)), [], 0), ('comprehension', ('Name', (1, 22), 'm', ('Store',)), ('Name', (1, 27), 'p', ('Load',)), [('Name', (1, 32), 'g', ('Load',))], 0)]))], None), -('Module', [('Expr', (1, 0), ('DictComp', (1, 0), ('Name', (1, 1), 'a', ('Load',)), ('Name', (1, 5), 'b', ('Load',)), [('comprehension', ('Tuple', (1, 11), [('Name', (1, 11), 'v', ('Store',)), ('Name', (1, 13), 'w', ('Store',))], ('Store',)), ('Name', (1, 18), 'x', ('Load',)), [], 0)]))], None), -('Module', [('Expr', (1, 0), ('SetComp', (1, 0), ('Name', (1, 1), 'r', ('Load',)), [('comprehension', ('Name', (1, 7), 'l', ('Store',)), ('Name', (1, 12), 'x', ('Load',)), [('Name', (1, 17), 'g', ('Load',))], 0)]))], None), -('Module', [('Expr', (1, 0), ('SetComp', (1, 0), ('Name', (1, 1), 'r', ('Load',)), [('comprehension', ('Tuple', (1, 7), [('Name', (1, 7), 'l', ('Store',)), ('Name', (1, 9), 'm', ('Store',))], ('Store',)), ('Name', (1, 14), 'x', ('Load',)), [], 0)]))], None), -('Module', [('AsyncFunctionDef', (1, 6), 'f', ('arguments', [], None, [], [], None, []), [('Expr', (3, 1), ('Await', (3, 1), ('Call', (3, 7), ('Name', (3, 7), 'something', ('Load',)), [], [])))], [], None, 'async function')], None), -('Module', [('AsyncFunctionDef', (1, 6), 'f', ('arguments', [], None, [], [], None, []), [('AsyncFor', (2, 7), ('Name', (2, 11), 'e', ('Store',)), ('Name', (2, 16), 'i', ('Load',)), [('Expr', (2, 19), ('Num', (2, 19), 1))], [('Expr', (3, 7), ('Num', (3, 7), 2))])], [], None, None)], None), -('Module', [('AsyncFunctionDef', (1, 6), 'f', ('arguments', [], None, [], [], None, []), [('AsyncWith', (2, 7), [('withitem', ('Name', (2, 12), 'a', ('Load',)), ('Name', (2, 17), 'b', ('Store',)))], [('Expr', (2, 20), ('Num', (2, 20), 1))])], [], None, None)], None), -('Module', [('Expr', (1, 0), ('Dict', (1, 0), [None, ('Num', (1, 10), 2)], [('Dict', (1, 3), [('Num', (1, 4), 1)], [('Num', (1, 6), 2)]), ('Num', (1, 12), 3)]))], None), -('Module', [('Expr', (1, 0), ('Set', (1, 0), [('Starred', (1, 1), ('Set', (1, 2), [('Num', (1, 3), 1), ('Num', (1, 6), 2)]), ('Load',)), ('Num', (1, 10), 3)]))], None), -('Module', [('AsyncFunctionDef', (1, 6), 'f', ('arguments', [], None, [], [], None, []), [('Expr', (2, 1), ('ListComp', (2, 2), ('Name', (2, 2), 'i', ('Load',)), [('comprehension', ('Name', (2, 14), 'b', ('Store',)), ('Name', (2, 19), 'c', ('Load',)), [], 1)]))], [], None, None)], None), +('Module', [('Expr', (1, 0), ('NameConstant', (1, 0), None))]), +('Module', [('Expr', (1, 0), ('Str', (1, 0), 'module docstring'))]), +('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('Pass', (1, 9))], [], None)]), +('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('Expr', (1, 9), ('Str', (1, 9), 'function docstring'))], [], None)]), +('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None)], None, [], [], None, []), [('Pass', (1, 10))], [], None)]), +('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None)], None, [], [], None, [('Num', (1, 8), 0)]), [('Pass', (1, 12))], [], None)]), +('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], ('arg', (1, 7), 'args', None), [], [], None, []), [('Pass', (1, 14))], [], None)]), +('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], ('arg', (1, 8), 'kwargs', None), []), [('Pass', (1, 17))], [], None)]), +('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None), ('arg', (1, 9), 'b', None), ('arg', (1, 14), 'c', None), ('arg', (1, 22), 'd', None), ('arg', (1, 28), 'e', None)], ('arg', (1, 35), 'args', None), [('arg', (1, 41), 'f', None)], [('Num', (1, 43), 42)], ('arg', (1, 49), 'kwargs', None), [('Num', (1, 11), 1), ('NameConstant', (1, 16), None), ('List', (1, 24), [], ('Load',)), ('Dict', (1, 30), [], [])]), [('Expr', (1, 58), ('Str', (1, 58), 'doc for f()'))], [], None)]), +('Module', [('ClassDef', (1, 0), 'C', [], [], [('Pass', (1, 8))], [])]), +('Module', [('ClassDef', (1, 0), 'C', [], [], [('Expr', (1, 9), ('Str', (1, 9), 'docstring for class C'))], [])]), +('Module', [('ClassDef', (1, 0), 'C', [('Name', (1, 8), 'object', ('Load',))], [], [('Pass', (1, 17))], [])]), +('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('Return', (1, 8), ('Num', (1, 15), 1))], [], None)]), +('Module', [('Delete', (1, 0), [('Name', (1, 4), 'v', ('Del',))])]), +('Module', [('Assign', (1, 0), [('Name', (1, 0), 'v', ('Store',))], ('Num', (1, 4), 1))]), +('Module', [('AugAssign', (1, 0), ('Name', (1, 0), 'v', ('Store',)), ('Add',), ('Num', (1, 5), 1))]), +('Module', [('For', (1, 0), ('Name', (1, 4), 'v', ('Store',)), ('Name', (1, 9), 'v', ('Load',)), [('Pass', (1, 11))], [])]), +('Module', [('While', (1, 0), ('Name', (1, 6), 'v', ('Load',)), [('Pass', (1, 8))], [])]), +('Module', [('If', (1, 0), ('Name', (1, 3), 'v', ('Load',)), [('Pass', (1, 5))], [])]), +('Module', [('With', (1, 0), [('withitem', ('Name', (1, 5), 'x', ('Load',)), ('Name', (1, 10), 'y', ('Store',)))], [('Pass', (1, 13))])]), +('Module', [('With', (1, 0), [('withitem', ('Name', (1, 5), 'x', ('Load',)), ('Name', (1, 10), 'y', ('Store',))), ('withitem', ('Name', (1, 13), 'z', ('Load',)), ('Name', (1, 18), 'q', ('Store',)))], [('Pass', (1, 21))])]), +('Module', [('Raise', (1, 0), ('Call', (1, 6), ('Name', (1, 6), 'Exception', ('Load',)), [('Str', (1, 16), 'string')], []), None)]), +('Module', [('Try', (1, 0), [('Pass', (2, 2))], [('ExceptHandler', (3, 0), ('Name', (3, 7), 'Exception', ('Load',)), None, [('Pass', (4, 2))])], [], [])]), +('Module', [('Try', (1, 0), [('Pass', (2, 2))], [], [], [('Pass', (4, 2))])]), +('Module', [('Assert', (1, 0), ('Name', (1, 7), 'v', ('Load',)), None)]), +('Module', [('Import', (1, 0), [('alias', 'sys', None)])]), +('Module', [('ImportFrom', (1, 0), 'sys', [('alias', 'v', None)], 0)]), +('Module', [('Global', (1, 0), ['v'])]), +('Module', [('Expr', (1, 0), ('Num', (1, 0), 1))]), +('Module', [('Pass', (1, 0))]), +('Module', [('For', (1, 0), ('Name', (1, 4), 'v', ('Store',)), ('Name', (1, 9), 'v', ('Load',)), [('Break', (1, 11))], [])]), +('Module', [('For', (1, 0), ('Name', (1, 4), 'v', ('Store',)), ('Name', (1, 9), 'v', ('Load',)), [('Continue', (1, 11))], [])]), +('Module', [('For', (1, 0), ('Tuple', (1, 4), [('Name', (1, 4), 'a', ('Store',)), ('Name', (1, 6), 'b', ('Store',))], ('Store',)), ('Name', (1, 11), 'c', ('Load',)), [('Pass', (1, 14))], [])]), +('Module', [('Expr', (1, 0), ('ListComp', (1, 1), ('Tuple', (1, 2), [('Name', (1, 2), 'a', ('Load',)), ('Name', (1, 4), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 11), [('Name', (1, 11), 'a', ('Store',)), ('Name', (1, 13), 'b', ('Store',))], ('Store',)), ('Name', (1, 18), 'c', ('Load',)), [], 0)]))]), +('Module', [('Expr', (1, 0), ('GeneratorExp', (1, 1), ('Tuple', (1, 2), [('Name', (1, 2), 'a', ('Load',)), ('Name', (1, 4), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 11), [('Name', (1, 11), 'a', ('Store',)), ('Name', (1, 13), 'b', ('Store',))], ('Store',)), ('Name', (1, 18), 'c', ('Load',)), [], 0)]))]), +('Module', [('Expr', (1, 0), ('GeneratorExp', (1, 1), ('Tuple', (1, 2), [('Name', (1, 2), 'a', ('Load',)), ('Name', (1, 4), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 12), [('Name', (1, 12), 'a', ('Store',)), ('Name', (1, 14), 'b', ('Store',))], ('Store',)), ('Name', (1, 20), 'c', ('Load',)), [], 0)]))]), +('Module', [('Expr', (1, 0), ('GeneratorExp', (2, 4), ('Tuple', (3, 4), [('Name', (3, 4), 'Aa', ('Load',)), ('Name', (5, 7), 'Bb', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (8, 4), [('Name', (8, 4), 'Aa', ('Store',)), ('Name', (10, 4), 'Bb', ('Store',))], ('Store',)), ('Name', (10, 10), 'Cc', ('Load',)), [], 0)]))]), +('Module', [('Expr', (1, 0), ('DictComp', (1, 0), ('Name', (1, 1), 'a', ('Load',)), ('Name', (1, 5), 'b', ('Load',)), [('comprehension', ('Name', (1, 11), 'w', ('Store',)), ('Name', (1, 16), 'x', ('Load',)), [], 0), ('comprehension', ('Name', (1, 22), 'm', ('Store',)), ('Name', (1, 27), 'p', ('Load',)), [('Name', (1, 32), 'g', ('Load',))], 0)]))]), +('Module', [('Expr', (1, 0), ('DictComp', (1, 0), ('Name', (1, 1), 'a', ('Load',)), ('Name', (1, 5), 'b', ('Load',)), [('comprehension', ('Tuple', (1, 11), [('Name', (1, 11), 'v', ('Store',)), ('Name', (1, 13), 'w', ('Store',))], ('Store',)), ('Name', (1, 18), 'x', ('Load',)), [], 0)]))]), +('Module', [('Expr', (1, 0), ('SetComp', (1, 0), ('Name', (1, 1), 'r', ('Load',)), [('comprehension', ('Name', (1, 7), 'l', ('Store',)), ('Name', (1, 12), 'x', ('Load',)), [('Name', (1, 17), 'g', ('Load',))], 0)]))]), +('Module', [('Expr', (1, 0), ('SetComp', (1, 0), ('Name', (1, 1), 'r', ('Load',)), [('comprehension', ('Tuple', (1, 7), [('Name', (1, 7), 'l', ('Store',)), ('Name', (1, 9), 'm', ('Store',))], ('Store',)), ('Name', (1, 14), 'x', ('Load',)), [], 0)]))]), +('Module', [('AsyncFunctionDef', (1, 6), 'f', ('arguments', [], None, [], [], None, []), [('Expr', (2, 1), ('Str', (2, 1), 'async function')), ('Expr', (3, 1), ('Await', (3, 1), ('Call', (3, 7), ('Name', (3, 7), 'something', ('Load',)), [], [])))], [], None)]), +('Module', [('AsyncFunctionDef', (1, 6), 'f', ('arguments', [], None, [], [], None, []), [('AsyncFor', (2, 7), ('Name', (2, 11), 'e', ('Store',)), ('Name', (2, 16), 'i', ('Load',)), [('Expr', (2, 19), ('Num', (2, 19), 1))], [('Expr', (3, 7), ('Num', (3, 7), 2))])], [], None)]), +('Module', [('AsyncFunctionDef', (1, 6), 'f', ('arguments', [], None, [], [], None, []), [('AsyncWith', (2, 7), [('withitem', ('Name', (2, 12), 'a', ('Load',)), ('Name', (2, 17), 'b', ('Store',)))], [('Expr', (2, 20), ('Num', (2, 20), 1))])], [], None)]), +('Module', [('Expr', (1, 0), ('Dict', (1, 0), [None, ('Num', (1, 10), 2)], [('Dict', (1, 3), [('Num', (1, 4), 1)], [('Num', (1, 6), 2)]), ('Num', (1, 12), 3)]))]), +('Module', [('Expr', (1, 0), ('Set', (1, 0), [('Starred', (1, 1), ('Set', (1, 2), [('Num', (1, 3), 1), ('Num', (1, 6), 2)]), ('Load',)), ('Num', (1, 10), 3)]))]), +('Module', [('AsyncFunctionDef', (1, 6), 'f', ('arguments', [], None, [], [], None, []), [('Expr', (2, 1), ('ListComp', (2, 2), ('Name', (2, 2), 'i', ('Load',)), [('comprehension', ('Name', (2, 14), 'b', ('Store',)), ('Name', (2, 19), 'c', ('Load',)), [], 1)]))], [], None)]), ] single_results = [ ('Interactive', [('Expr', (1, 0), ('BinOp', (1, 0), ('Num', (1, 0), 1), ('Add',), ('Num', (1, 2), 2)))]), diff --git a/Lib/test/test_opcodes.py b/Lib/test/test_opcodes.py index 8af098fb206b..6806c616cbef 100644 --- a/Lib/test/test_opcodes.py +++ b/Lib/test/test_opcodes.py @@ -27,7 +27,7 @@ def test_setup_annotations_line(self): with open(ann_module.__file__) as f: txt = f.read() co = compile(txt, ann_module.__file__, 'exec') - self.assertEqual(co.co_firstlineno, 8) + self.assertEqual(co.co_firstlineno, 6) except OSError: pass diff --git a/Misc/NEWS.d/3.7.0a1.rst b/Misc/NEWS.d/3.7.0a1.rst index 3962923a2d24..acecfcf55720 100644 --- a/Misc/NEWS.d/3.7.0a1.rst +++ b/Misc/NEWS.d/3.7.0a1.rst @@ -788,7 +788,7 @@ objects. Add ``docstring`` field to Module, ClassDef, FunctionDef, and AsyncFunctionDef ast nodes. docstring is not first stmt in their body anymore. It affects ``co_firstlineno`` and ``co_lnotab`` of code object for -module and class. +module and class. (Reverted in :issue:`32911`.) .. diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-02-27-20-57-00.bpo-32911.cmKfco.rst b/Misc/NEWS.d/next/Core and Builtins/2018-02-27-20-57-00.bpo-32911.cmKfco.rst new file mode 100644 index 000000000000..0c2ae756b65c --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-02-27-20-57-00.bpo-32911.cmKfco.rst @@ -0,0 +1,5 @@ +Due to unexpected compatibility issues discovered during downstream beta +testing, reverted :issue:`29463`. ``docstring`` field is removed from Module, +ClassDef, FunctionDef, and AsyncFunctionDef ast nodes which was added in +3.7a1. Docstring expression is restored as a first statement in their body. +Based on patch by Inada Naoki. diff --git a/Parser/Python.asdl b/Parser/Python.asdl index 526cffbce028..f470ad13b655 100644 --- a/Parser/Python.asdl +++ b/Parser/Python.asdl @@ -6,7 +6,7 @@ module Python { - mod = Module(stmt* body, string? docstring) + mod = Module(stmt* body) | Interactive(stmt* body) | Expression(expr body) @@ -14,18 +14,15 @@ module Python | Suite(stmt* body) stmt = FunctionDef(identifier name, arguments args, - stmt* body, expr* decorator_list, expr? returns, - string? docstring) + stmt* body, expr* decorator_list, expr? returns) | AsyncFunctionDef(identifier name, arguments args, - stmt* body, expr* decorator_list, expr? returns, - string? docstring) + stmt* body, expr* decorator_list, expr? returns) | ClassDef(identifier name, expr* bases, keyword* keywords, stmt* body, - expr* decorator_list, - string? docstring) + expr* decorator_list) | Return(expr? value) | Delete(expr* targets) diff --git a/Python/Python-ast.c b/Python/Python-ast.c index f7a056845e95..38b9292577f2 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -10,10 +10,8 @@ static PyTypeObject *mod_type; static PyObject* ast2obj_mod(void*); static PyTypeObject *Module_type; _Py_IDENTIFIER(body); -_Py_IDENTIFIER(docstring); static char *Module_fields[]={ "body", - "docstring", }; static PyTypeObject *Interactive_type; static char *Interactive_fields[]={ @@ -46,7 +44,6 @@ static char *FunctionDef_fields[]={ "body", "decorator_list", "returns", - "docstring", }; static PyTypeObject *AsyncFunctionDef_type; static char *AsyncFunctionDef_fields[]={ @@ -55,7 +52,6 @@ static char *AsyncFunctionDef_fields[]={ "body", "decorator_list", "returns", - "docstring", }; static PyTypeObject *ClassDef_type; _Py_IDENTIFIER(bases); @@ -66,7 +62,6 @@ static char *ClassDef_fields[]={ "keywords", "body", "decorator_list", - "docstring", }; static PyTypeObject *Return_type; _Py_IDENTIFIER(value); @@ -847,7 +842,7 @@ static int init_types(void) mod_type = make_type("mod", &AST_type, NULL, 0); if (!mod_type) return 0; if (!add_attributes(mod_type, NULL, 0)) return 0; - Module_type = make_type("Module", mod_type, Module_fields, 2); + Module_type = make_type("Module", mod_type, Module_fields, 1); if (!Module_type) return 0; Interactive_type = make_type("Interactive", mod_type, Interactive_fields, 1); @@ -860,12 +855,12 @@ static int init_types(void) if (!stmt_type) return 0; if (!add_attributes(stmt_type, stmt_attributes, 2)) return 0; FunctionDef_type = make_type("FunctionDef", stmt_type, FunctionDef_fields, - 6); + 5); if (!FunctionDef_type) return 0; AsyncFunctionDef_type = make_type("AsyncFunctionDef", stmt_type, - AsyncFunctionDef_fields, 6); + AsyncFunctionDef_fields, 5); if (!AsyncFunctionDef_type) return 0; - ClassDef_type = make_type("ClassDef", stmt_type, ClassDef_fields, 6); + ClassDef_type = make_type("ClassDef", stmt_type, ClassDef_fields, 5); if (!ClassDef_type) return 0; Return_type = make_type("Return", stmt_type, Return_fields, 1); if (!Return_type) return 0; @@ -1192,7 +1187,7 @@ static int obj2ast_alias(PyObject* obj, alias_ty* out, PyArena* arena); static int obj2ast_withitem(PyObject* obj, withitem_ty* out, PyArena* arena); mod_ty -Module(asdl_seq * body, string docstring, PyArena *arena) +Module(asdl_seq * body, PyArena *arena) { mod_ty p; p = (mod_ty)PyArena_Malloc(arena, sizeof(*p)); @@ -1200,7 +1195,6 @@ Module(asdl_seq * body, string docstring, PyArena *arena) return NULL; p->kind = Module_kind; p->v.Module.body = body; - p->v.Module.docstring = docstring; return p; } @@ -1247,8 +1241,8 @@ Suite(asdl_seq * body, PyArena *arena) stmt_ty FunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq * - decorator_list, expr_ty returns, string docstring, int lineno, int - col_offset, PyArena *arena) + decorator_list, expr_ty returns, int lineno, int col_offset, + PyArena *arena) { stmt_ty p; if (!name) { @@ -1270,7 +1264,6 @@ FunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq * p->v.FunctionDef.body = body; p->v.FunctionDef.decorator_list = decorator_list; p->v.FunctionDef.returns = returns; - p->v.FunctionDef.docstring = docstring; p->lineno = lineno; p->col_offset = col_offset; return p; @@ -1278,8 +1271,8 @@ FunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq * stmt_ty AsyncFunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq - * decorator_list, expr_ty returns, string docstring, int - lineno, int col_offset, PyArena *arena) + * decorator_list, expr_ty returns, int lineno, int col_offset, + PyArena *arena) { stmt_ty p; if (!name) { @@ -1301,7 +1294,6 @@ AsyncFunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq p->v.AsyncFunctionDef.body = body; p->v.AsyncFunctionDef.decorator_list = decorator_list; p->v.AsyncFunctionDef.returns = returns; - p->v.AsyncFunctionDef.docstring = docstring; p->lineno = lineno; p->col_offset = col_offset; return p; @@ -1309,8 +1301,8 @@ AsyncFunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq stmt_ty ClassDef(identifier name, asdl_seq * bases, asdl_seq * keywords, asdl_seq * - body, asdl_seq * decorator_list, string docstring, int lineno, int - col_offset, PyArena *arena) + body, asdl_seq * decorator_list, int lineno, int col_offset, PyArena + *arena) { stmt_ty p; if (!name) { @@ -1327,7 +1319,6 @@ ClassDef(identifier name, asdl_seq * bases, asdl_seq * keywords, asdl_seq * p->v.ClassDef.keywords = keywords; p->v.ClassDef.body = body; p->v.ClassDef.decorator_list = decorator_list; - p->v.ClassDef.docstring = docstring; p->lineno = lineno; p->col_offset = col_offset; return p; @@ -2591,11 +2582,6 @@ ast2obj_mod(void* _o) if (_PyObject_SetAttrId(result, &PyId_body, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_string(o->v.Module.docstring); - if (!value) goto failed; - if (_PyObject_SetAttrId(result, &PyId_docstring, value) == -1) - goto failed; - Py_DECREF(value); break; case Interactive_kind: result = PyType_GenericNew(Interactive_type, NULL, NULL); @@ -2670,11 +2656,6 @@ ast2obj_stmt(void* _o) if (_PyObject_SetAttrId(result, &PyId_returns, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_string(o->v.FunctionDef.docstring); - if (!value) goto failed; - if (_PyObject_SetAttrId(result, &PyId_docstring, value) == -1) - goto failed; - Py_DECREF(value); break; case AsyncFunctionDef_kind: result = PyType_GenericNew(AsyncFunctionDef_type, NULL, NULL); @@ -2705,11 +2686,6 @@ ast2obj_stmt(void* _o) if (_PyObject_SetAttrId(result, &PyId_returns, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_string(o->v.AsyncFunctionDef.docstring); - if (!value) goto failed; - if (_PyObject_SetAttrId(result, &PyId_docstring, value) == -1) - goto failed; - Py_DECREF(value); break; case ClassDef_kind: result = PyType_GenericNew(ClassDef_type, NULL, NULL); @@ -2739,11 +2715,6 @@ ast2obj_stmt(void* _o) if (_PyObject_SetAttrId(result, &PyId_decorator_list, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_string(o->v.ClassDef.docstring); - if (!value) goto failed; - if (_PyObject_SetAttrId(result, &PyId_docstring, value) == -1) - goto failed; - Py_DECREF(value); break; case Return_kind: result = PyType_GenericNew(Return_type, NULL, NULL); @@ -3984,7 +3955,6 @@ obj2ast_mod(PyObject* obj, mod_ty* out, PyArena* arena) } if (isinstance) { asdl_seq* body; - string docstring; if (_PyObject_LookupAttrId(obj, &PyId_body, &tmp) < 0) { return 1; @@ -4016,20 +3986,7 @@ obj2ast_mod(PyObject* obj, mod_ty* out, PyArena* arena) } Py_CLEAR(tmp); } - if (_PyObject_LookupAttrId(obj, &PyId_docstring, &tmp) < 0) { - return 1; - } - if (tmp == NULL || tmp == Py_None) { - Py_CLEAR(tmp); - docstring = NULL; - } - else { - int res; - res = obj2ast_string(tmp, &docstring, arena); - if (res != 0) goto failed; - Py_CLEAR(tmp); - } - *out = Module(body, docstring, arena); + *out = Module(body, arena); if (*out == NULL) goto failed; return 0; } @@ -4195,7 +4152,6 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) asdl_seq* body; asdl_seq* decorator_list; expr_ty returns; - string docstring; if (_PyObject_LookupAttrId(obj, &PyId_name, &tmp) < 0) { return 1; @@ -4296,21 +4252,8 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) if (res != 0) goto failed; Py_CLEAR(tmp); } - if (_PyObject_LookupAttrId(obj, &PyId_docstring, &tmp) < 0) { - return 1; - } - if (tmp == NULL || tmp == Py_None) { - Py_CLEAR(tmp); - docstring = NULL; - } - else { - int res; - res = obj2ast_string(tmp, &docstring, arena); - if (res != 0) goto failed; - Py_CLEAR(tmp); - } - *out = FunctionDef(name, args, body, decorator_list, returns, - docstring, lineno, col_offset, arena); + *out = FunctionDef(name, args, body, decorator_list, returns, lineno, + col_offset, arena); if (*out == NULL) goto failed; return 0; } @@ -4324,7 +4267,6 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) asdl_seq* body; asdl_seq* decorator_list; expr_ty returns; - string docstring; if (_PyObject_LookupAttrId(obj, &PyId_name, &tmp) < 0) { return 1; @@ -4425,21 +4367,8 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) if (res != 0) goto failed; Py_CLEAR(tmp); } - if (_PyObject_LookupAttrId(obj, &PyId_docstring, &tmp) < 0) { - return 1; - } - if (tmp == NULL || tmp == Py_None) { - Py_CLEAR(tmp); - docstring = NULL; - } - else { - int res; - res = obj2ast_string(tmp, &docstring, arena); - if (res != 0) goto failed; - Py_CLEAR(tmp); - } *out = AsyncFunctionDef(name, args, body, decorator_list, returns, - docstring, lineno, col_offset, arena); + lineno, col_offset, arena); if (*out == NULL) goto failed; return 0; } @@ -4453,7 +4382,6 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) asdl_seq* keywords; asdl_seq* body; asdl_seq* decorator_list; - string docstring; if (_PyObject_LookupAttrId(obj, &PyId_name, &tmp) < 0) { return 1; @@ -4588,21 +4516,8 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) } Py_CLEAR(tmp); } - if (_PyObject_LookupAttrId(obj, &PyId_docstring, &tmp) < 0) { - return 1; - } - if (tmp == NULL || tmp == Py_None) { - Py_CLEAR(tmp); - docstring = NULL; - } - else { - int res; - res = obj2ast_string(tmp, &docstring, arena); - if (res != 0) goto failed; - Py_CLEAR(tmp); - } - *out = ClassDef(name, bases, keywords, body, decorator_list, docstring, - lineno, col_offset, arena); + *out = ClassDef(name, bases, keywords, body, decorator_list, lineno, + col_offset, arena); if (*out == NULL) goto failed; return 0; } diff --git a/Python/ast.c b/Python/ast.c index e2092f0f8543..6e1793dc3375 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -367,12 +367,9 @@ validate_assignlist(asdl_seq *targets, expr_context_ty ctx) } static int -validate_body(asdl_seq *body, const char *owner, int allowempty) +validate_body(asdl_seq *body, const char *owner) { - if (!allowempty && !validate_nonempty_seq(body, "body", owner)) { - return 0; - } - return validate_stmts(body); + return validate_nonempty_seq(body, "body", owner) && validate_stmts(body); } static int @@ -381,15 +378,13 @@ validate_stmt(stmt_ty stmt) int i; switch (stmt->kind) { case FunctionDef_kind: - return validate_body(stmt->v.FunctionDef.body, "FunctionDef", - stmt->v.FunctionDef.docstring != NULL) && + return validate_body(stmt->v.FunctionDef.body, "FunctionDef") && validate_arguments(stmt->v.FunctionDef.args) && validate_exprs(stmt->v.FunctionDef.decorator_list, Load, 0) && (!stmt->v.FunctionDef.returns || validate_expr(stmt->v.FunctionDef.returns, Load)); case ClassDef_kind: - return validate_body(stmt->v.ClassDef.body, "ClassDef", - stmt->v.ClassDef.docstring != NULL) && + return validate_body(stmt->v.ClassDef.body, "ClassDef") && validate_exprs(stmt->v.ClassDef.bases, Load, 0) && validate_keywords(stmt->v.ClassDef.keywords) && validate_exprs(stmt->v.ClassDef.decorator_list, Load, 0); @@ -417,20 +412,20 @@ validate_stmt(stmt_ty stmt) case For_kind: return validate_expr(stmt->v.For.target, Store) && validate_expr(stmt->v.For.iter, Load) && - validate_body(stmt->v.For.body, "For", 0) && + validate_body(stmt->v.For.body, "For") && validate_stmts(stmt->v.For.orelse); case AsyncFor_kind: return validate_expr(stmt->v.AsyncFor.target, Store) && validate_expr(stmt->v.AsyncFor.iter, Load) && - validate_body(stmt->v.AsyncFor.body, "AsyncFor", 0) && + validate_body(stmt->v.AsyncFor.body, "AsyncFor") && validate_stmts(stmt->v.AsyncFor.orelse); case While_kind: return validate_expr(stmt->v.While.test, Load) && - validate_body(stmt->v.While.body, "While", 0) && + validate_body(stmt->v.While.body, "While") && validate_stmts(stmt->v.While.orelse); case If_kind: return validate_expr(stmt->v.If.test, Load) && - validate_body(stmt->v.If.body, "If", 0) && + validate_body(stmt->v.If.body, "If") && validate_stmts(stmt->v.If.orelse); case With_kind: if (!validate_nonempty_seq(stmt->v.With.items, "items", "With")) @@ -441,7 +436,7 @@ validate_stmt(stmt_ty stmt) (item->optional_vars && !validate_expr(item->optional_vars, Store))) return 0; } - return validate_body(stmt->v.With.body, "With", 0); + return validate_body(stmt->v.With.body, "With"); case AsyncWith_kind: if (!validate_nonempty_seq(stmt->v.AsyncWith.items, "items", "AsyncWith")) return 0; @@ -451,7 +446,7 @@ validate_stmt(stmt_ty stmt) (item->optional_vars && !validate_expr(item->optional_vars, Store))) return 0; } - return validate_body(stmt->v.AsyncWith.body, "AsyncWith", 0); + return validate_body(stmt->v.AsyncWith.body, "AsyncWith"); case Raise_kind: if (stmt->v.Raise.exc) { return validate_expr(stmt->v.Raise.exc, Load) && @@ -463,7 +458,7 @@ validate_stmt(stmt_ty stmt) } return 1; case Try_kind: - if (!validate_body(stmt->v.Try.body, "Try", 0)) + if (!validate_body(stmt->v.Try.body, "Try")) return 0; if (!asdl_seq_LEN(stmt->v.Try.handlers) && !asdl_seq_LEN(stmt->v.Try.finalbody)) { @@ -479,7 +474,7 @@ validate_stmt(stmt_ty stmt) excepthandler_ty handler = asdl_seq_GET(stmt->v.Try.handlers, i); if ((handler->v.ExceptHandler.type && !validate_expr(handler->v.ExceptHandler.type, Load)) || - !validate_body(handler->v.ExceptHandler.body, "ExceptHandler", 0)) + !validate_body(handler->v.ExceptHandler.body, "ExceptHandler")) return 0; } return (!asdl_seq_LEN(stmt->v.Try.finalbody) || @@ -504,8 +499,7 @@ validate_stmt(stmt_ty stmt) case Expr_kind: return validate_expr(stmt->v.Expr.value, Load); case AsyncFunctionDef_kind: - return validate_body(stmt->v.AsyncFunctionDef.body, "AsyncFunctionDef", - stmt->v.AsyncFunctionDef.docstring != NULL) && + return validate_body(stmt->v.AsyncFunctionDef.body, "AsyncFunctionDef") && validate_arguments(stmt->v.AsyncFunctionDef.args) && validate_exprs(stmt->v.AsyncFunctionDef.decorator_list, Load, 0) && (!stmt->v.AsyncFunctionDef.returns || @@ -600,9 +594,7 @@ struct compiling { static asdl_seq *seq_for_testlist(struct compiling *, const node *); static expr_ty ast_for_expr(struct compiling *, const node *); static stmt_ty ast_for_stmt(struct compiling *, const node *); -static asdl_seq *ast_for_body(struct compiling *c, const node *n, - string *docstring); -static string docstring_from_stmts(asdl_seq *stmts); +static asdl_seq *ast_for_suite(struct compiling *c, const node *n); static asdl_seq *ast_for_exprlist(struct compiling *, const node *, expr_context_ty); static expr_ty ast_for_testlist(struct compiling *, const node *); @@ -820,7 +812,7 @@ PyAST_FromNodeObject(const node *n, PyCompilerFlags *flags, } } } - res = Module(stmts, docstring_from_stmts(stmts), arena); + res = Module(stmts, arena); break; case eval_input: { expr_ty testlist_ast; @@ -1585,7 +1577,6 @@ ast_for_funcdef_impl(struct compiling *c, const node *n, arguments_ty args; asdl_seq *body; expr_ty returns = NULL; - string docstring; int name_i = 1; REQ(n, funcdef); @@ -1604,18 +1595,16 @@ ast_for_funcdef_impl(struct compiling *c, const node *n, return NULL; name_i += 2; } - body = ast_for_body(c, CHILD(n, name_i + 3), &docstring); + body = ast_for_suite(c, CHILD(n, name_i + 3)); if (!body) return NULL; if (is_async) return AsyncFunctionDef(name, args, body, decorator_seq, returns, - docstring, LINENO(n), - n->n_col_offset, c->c_arena); + LINENO(n), n->n_col_offset, c->c_arena); else return FunctionDef(name, args, body, decorator_seq, returns, - docstring, LINENO(n), - n->n_col_offset, c->c_arena); + LINENO(n), n->n_col_offset, c->c_arena); } static stmt_ty @@ -3528,32 +3517,6 @@ ast_for_suite(struct compiling *c, const node *n) return seq; } -static string -docstring_from_stmts(asdl_seq *stmts) -{ - if (stmts && stmts->size) { - stmt_ty s = (stmt_ty)asdl_seq_GET(stmts, 0); - /* If first statement is a literal string, it's the doc string. */ - if (s->kind == Expr_kind && s->v.Expr.value->kind == Str_kind) { - string doc = s->v.Expr.value->v.Str.s; - /* not very efficient, but simple */ - memmove(&asdl_seq_GET(stmts, 0), &asdl_seq_GET(stmts, 1), - (stmts->size - 1) * sizeof(void*)); - stmts->size--; - return doc; - } - } - return NULL; -} - -static asdl_seq * -ast_for_body(struct compiling *c, const node *n, string *docstring) -{ - asdl_seq *stmts = ast_for_suite(c, n); - *docstring = docstring_from_stmts(stmts); - return stmts; -} - static stmt_ty ast_for_if_stmt(struct compiling *c, const node *n) { @@ -3938,13 +3901,12 @@ ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq) /* classdef: 'class' NAME ['(' arglist ')'] ':' suite */ PyObject *classname; asdl_seq *s; - string docstring; expr_ty call; REQ(n, classdef); if (NCH(n) == 4) { /* class NAME ':' suite */ - s = ast_for_body(c, CHILD(n, 3), &docstring); + s = ast_for_suite(c, CHILD(n, 3)); if (!s) return NULL; classname = NEW_IDENTIFIER(CHILD(n, 1)); @@ -3952,12 +3914,12 @@ ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq) return NULL; if (forbidden_name(c, classname, CHILD(n, 3), 0)) return NULL; - return ClassDef(classname, NULL, NULL, s, decorator_seq, docstring, + return ClassDef(classname, NULL, NULL, s, decorator_seq, LINENO(n), n->n_col_offset, c->c_arena); } if (TYPE(CHILD(n, 3)) == RPAR) { /* class NAME '(' ')' ':' suite */ - s = ast_for_body(c, CHILD(n, 5), &docstring); + s = ast_for_suite(c, CHILD(n, 5)); if (!s) return NULL; classname = NEW_IDENTIFIER(CHILD(n, 1)); @@ -3965,7 +3927,7 @@ ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq) return NULL; if (forbidden_name(c, classname, CHILD(n, 3), 0)) return NULL; - return ClassDef(classname, NULL, NULL, s, decorator_seq, docstring, + return ClassDef(classname, NULL, NULL, s, decorator_seq, LINENO(n), n->n_col_offset, c->c_arena); } @@ -3982,7 +3944,7 @@ ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq) if (!call) return NULL; } - s = ast_for_body(c, CHILD(n, 6), &docstring); + s = ast_for_suite(c, CHILD(n, 6)); if (!s) return NULL; classname = NEW_IDENTIFIER(CHILD(n, 1)); @@ -3992,8 +3954,7 @@ ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq) return NULL; return ClassDef(classname, call->v.Call.args, call->v.Call.keywords, s, - decorator_seq, docstring, LINENO(n), n->n_col_offset, - c->c_arena); + decorator_seq, LINENO(n), n->n_col_offset, c->c_arena); } static stmt_ty diff --git a/Python/ast_opt.c b/Python/ast_opt.c index 65cf3c126417..7bc681a421d6 100644 --- a/Python/ast_opt.c +++ b/Python/ast_opt.c @@ -452,12 +452,51 @@ static int astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, int opti } \ } +static int +isdocstring(stmt_ty s) +{ + if (s->kind != Expr_kind) + return 0; + if (s->v.Expr.value->kind == Str_kind) + return 1; + if (s->v.Expr.value->kind == Constant_kind) + return PyUnicode_CheckExact(s->v.Expr.value->v.Constant.value); + return 0; +} + +static int +astfold_body(asdl_seq *stmts, PyArena *ctx_, int optimize_) +{ + if (!asdl_seq_LEN(stmts)) { + return 1; + } + int docstring = isdocstring((stmt_ty)asdl_seq_GET(stmts, 0)); + CALL_SEQ(astfold_stmt, stmt_ty, stmts); + if (docstring) { + return 1; + } + stmt_ty st = (stmt_ty)asdl_seq_GET(stmts, 0); + if (isdocstring(st)) { + asdl_seq *values = _Py_asdl_seq_new(1, ctx_); + if (!values) { + return 0; + } + asdl_seq_SET(values, 0, st->v.Expr.value); + expr_ty expr = _Py_JoinedStr(values, st->lineno, st->col_offset, ctx_); + if (!expr) { + return 0; + } + st->v.Expr.value = expr; + } + return 1; +} + static int astfold_mod(mod_ty node_, PyArena *ctx_, int optimize_) { switch (node_->kind) { case Module_kind: - CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Module.body); + CALL(astfold_body, asdl_seq, node_->v.Module.body); break; case Interactive_kind: CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Interactive.body); @@ -642,20 +681,20 @@ astfold_stmt(stmt_ty node_, PyArena *ctx_, int optimize_) switch (node_->kind) { case FunctionDef_kind: CALL(astfold_arguments, arguments_ty, node_->v.FunctionDef.args); - CALL_SEQ(astfold_stmt, stmt_ty, node_->v.FunctionDef.body); + CALL(astfold_body, asdl_seq, node_->v.FunctionDef.body); CALL_SEQ(astfold_expr, expr_ty, node_->v.FunctionDef.decorator_list); CALL_OPT(astfold_expr, expr_ty, node_->v.FunctionDef.returns); break; case AsyncFunctionDef_kind: CALL(astfold_arguments, arguments_ty, node_->v.AsyncFunctionDef.args); - CALL_SEQ(astfold_stmt, stmt_ty, node_->v.AsyncFunctionDef.body); + CALL(astfold_body, asdl_seq, node_->v.AsyncFunctionDef.body); CALL_SEQ(astfold_expr, expr_ty, node_->v.AsyncFunctionDef.decorator_list); CALL_OPT(astfold_expr, expr_ty, node_->v.AsyncFunctionDef.returns); break; case ClassDef_kind: CALL_SEQ(astfold_expr, expr_ty, node_->v.ClassDef.bases); CALL_SEQ(astfold_keyword, keyword_ty, node_->v.ClassDef.keywords); - CALL_SEQ(astfold_stmt, stmt_ty, node_->v.ClassDef.body); + CALL(astfold_body, asdl_seq, node_->v.ClassDef.body); CALL_SEQ(astfold_expr, expr_ty, node_->v.ClassDef.decorator_list); break; case Return_kind: diff --git a/Python/compile.c b/Python/compile.c index c38a0d1b1a31..b459096c6f00 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1364,6 +1364,18 @@ compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute) } \ } +static int +compiler_isdocstring(stmt_ty s) +{ + if (s->kind != Expr_kind) + return 0; + if (s->v.Expr.value->kind == Str_kind) + return 1; + if (s->v.Expr.value->kind == Constant_kind) + return PyUnicode_CheckExact(s->v.Expr.value->v.Constant.value); + return 0; +} + static int is_const(expr_ty e) { @@ -1462,27 +1474,37 @@ find_ann(asdl_seq *stmts) and for annotations. */ static int -compiler_body(struct compiler *c, asdl_seq *stmts, string docstring) +compiler_body(struct compiler *c, asdl_seq *stmts) { + int i = 0; + stmt_ty st; + /* Set current line number to the line number of first statement. This way line number for SETUP_ANNOTATIONS will always coincide with the line number of first "real" statement in module. If body is empy, then lineno will be set later in assemble. */ if (c->u->u_scope_type == COMPILER_SCOPE_MODULE && !c->u->u_lineno && asdl_seq_LEN(stmts)) { - stmt_ty st = (stmt_ty)asdl_seq_GET(stmts, 0); + st = (stmt_ty)asdl_seq_GET(stmts, 0); c->u->u_lineno = st->lineno; } /* Every annotated class and module should have __annotations__. */ if (find_ann(stmts)) { ADDOP(c, SETUP_ANNOTATIONS); } + if (!asdl_seq_LEN(stmts)) + return 1; + st = (stmt_ty)asdl_seq_GET(stmts, 0); /* if not -OO mode, set docstring */ - if (c->c_optimize < 2 && docstring) { - ADDOP_O(c, LOAD_CONST, docstring, consts); - ADDOP_NAME(c, STORE_NAME, __doc__, names); + if (compiler_isdocstring(st) && c->c_optimize < 2) { + /* don't generate docstrings if -OO */ + i = 1; + VISIT(c, expr, st->v.Expr.value); + if (!compiler_nameop(c, __doc__, Store)) + return 0; } - VISIT_SEQ(c, stmt, stmts); + for (; i < asdl_seq_LEN(stmts); i++) + VISIT(c, stmt, (stmt_ty)asdl_seq_GET(stmts, i)); return 1; } @@ -1502,7 +1524,7 @@ compiler_mod(struct compiler *c, mod_ty mod) return NULL; switch (mod->kind) { case Module_kind: - if (!compiler_body(c, mod->v.Module.body, mod->v.Module.docstring)) { + if (!compiler_body(c, mod->v.Module.body)) { compiler_exit_scope(c); return 0; } @@ -1847,13 +1869,15 @@ static int compiler_function(struct compiler *c, stmt_ty s, int is_async) { PyCodeObject *co; - PyObject *qualname, *docstring = Py_None; + PyObject *qualname, *first_const = Py_None; arguments_ty args; expr_ty returns; identifier name; asdl_seq* decos; asdl_seq *body; + stmt_ty st; Py_ssize_t i, funcflags; + int docstring; int annotations; int scope_type; @@ -1899,17 +1923,21 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async) return 0; } - /* if not -OO mode, add docstring */ - if (c->c_optimize < 2 && s->v.FunctionDef.docstring) - docstring = s->v.FunctionDef.docstring; - if (compiler_add_o(c, c->u->u_consts, docstring) < 0) { + st = (stmt_ty)asdl_seq_GET(body, 0); + docstring = compiler_isdocstring(st); + if (docstring && c->c_optimize < 2) { + if (st->v.Expr.value->kind == Constant_kind) + first_const = st->v.Expr.value->v.Constant.value; + else + first_const = st->v.Expr.value->v.Str.s; + } + if (compiler_add_o(c, c->u->u_consts, first_const) < 0) { compiler_exit_scope(c); return 0; } c->u->u_argcount = asdl_seq_LEN(args->args); c->u->u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs); - /* if there was a docstring, we need to skip the first statement */ VISIT_SEQ_IN_SCOPE(c, stmt, body); co = assemble(c, 1); qualname = c->u->u_qualname; @@ -1991,7 +2019,7 @@ compiler_class(struct compiler *c, stmt_ty s) } Py_DECREF(str); /* compile the body proper */ - if (!compiler_body(c, s->v.ClassDef.body, s->v.ClassDef.docstring)) { + if (!compiler_body(c, s->v.ClassDef.body)) { compiler_exit_scope(c); return 0; } diff --git a/Python/future.c b/Python/future.c index ade647f25baf..03a97c865a82 100644 --- a/Python/future.c +++ b/Python/future.c @@ -63,6 +63,7 @@ static int future_parse(PyFutureFeatures *ff, mod_ty mod, PyObject *filename) { int i, done = 0, prev_line = 0; + stmt_ty first; if (!(mod->kind == Module_kind || mod->kind == Interactive_kind)) return 1; @@ -78,7 +79,15 @@ future_parse(PyFutureFeatures *ff, mod_ty mod, PyObject *filename) but is preceded by a regular import. */ - for (i = 0; i < asdl_seq_LEN(mod->v.Module.body); i++) { + i = 0; + first = (stmt_ty)asdl_seq_GET(mod->v.Module.body, i); + if (first->kind == Expr_kind + && (first->v.Expr.value->kind == Str_kind + || (first->v.Expr.value->kind == Constant_kind + && PyUnicode_CheckExact(first->v.Expr.value->v.Constant.value)))) + i++; + + for (; i < asdl_seq_LEN(mod->v.Module.body); i++) { stmt_ty s = (stmt_ty)asdl_seq_GET(mod->v.Module.body, i); if (done && s->lineno > prev_line) diff --git a/Python/importlib.h b/Python/importlib.h index 822ffa0c067e..0a92e69f62d2 100644 --- a/Python/importlib.h +++ b/Python/importlib.h @@ -205,1619 +205,1620 @@ const unsigned char _Py_M__importlib[] = { 27,0,0,0,114,32,0,0,0,114,34,0,0,0,114,35, 0,0,0,114,40,0,0,0,114,10,0,0,0,114,10,0, 0,0,114,10,0,0,0,114,11,0,0,0,114,18,0,0, - 0,52,0,0,0,115,10,0,0,0,12,6,8,8,8,12, - 8,25,8,13,114,18,0,0,0,99,0,0,0,0,0,0, - 0,0,0,0,0,0,2,0,0,0,64,0,0,0,115,48, - 0,0,0,101,0,90,1,100,0,90,2,100,1,90,3,100, - 2,100,3,132,0,90,4,100,4,100,5,132,0,90,5,100, - 6,100,7,132,0,90,6,100,8,100,9,132,0,90,7,100, - 10,83,0,41,11,218,16,95,68,117,109,109,121,77,111,100, - 117,108,101,76,111,99,107,122,86,65,32,115,105,109,112,108, - 101,32,95,77,111,100,117,108,101,76,111,99,107,32,101,113, - 117,105,118,97,108,101,110,116,32,102,111,114,32,80,121,116, - 104,111,110,32,98,117,105,108,100,115,32,119,105,116,104,111, - 117,116,10,32,32,32,32,109,117,108,116,105,45,116,104,114, - 101,97,100,105,110,103,32,115,117,112,112,111,114,116,46,99, - 2,0,0,0,0,0,0,0,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,41,2,78,114,19,0,0, - 0,41,2,114,15,0,0,0,114,24,0,0,0,41,2,114, + 0,52,0,0,0,115,12,0,0,0,8,4,4,2,8,8, + 8,12,8,25,8,13,114,18,0,0,0,99,0,0,0,0, + 0,0,0,0,0,0,0,0,2,0,0,0,64,0,0,0, + 115,48,0,0,0,101,0,90,1,100,0,90,2,100,1,90, + 3,100,2,100,3,132,0,90,4,100,4,100,5,132,0,90, + 5,100,6,100,7,132,0,90,6,100,8,100,9,132,0,90, + 7,100,10,83,0,41,11,218,16,95,68,117,109,109,121,77, + 111,100,117,108,101,76,111,99,107,122,86,65,32,115,105,109, + 112,108,101,32,95,77,111,100,117,108,101,76,111,99,107,32, + 101,113,117,105,118,97,108,101,110,116,32,102,111,114,32,80, + 121,116,104,111,110,32,98,117,105,108,100,115,32,119,105,116, + 104,111,117,116,10,32,32,32,32,109,117,108,116,105,45,116, + 104,114,101,97,100,105,110,103,32,115,117,112,112,111,114,116, + 46,99,2,0,0,0,0,0,0,0,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,41,2,78,114,19, + 0,0,0,41,2,114,15,0,0,0,114,24,0,0,0,41, + 2,114,26,0,0,0,114,15,0,0,0,114,10,0,0,0, + 114,10,0,0,0,114,11,0,0,0,114,27,0,0,0,124, + 0,0,0,115,4,0,0,0,0,1,6,1,122,25,95,68, + 117,109,109,121,77,111,100,117,108,101,76,111,99,107,46,95, + 95,105,110,105,116,95,95,99,1,0,0,0,0,0,0,0, + 1,0,0,0,3,0,0,0,67,0,0,0,115,18,0,0, + 0,124,0,4,0,106,0,100,1,55,0,2,0,95,0,100, + 2,83,0,41,3,78,114,33,0,0,0,84,41,1,114,24, + 0,0,0,41,1,114,26,0,0,0,114,10,0,0,0,114, + 10,0,0,0,114,11,0,0,0,114,34,0,0,0,128,0, + 0,0,115,4,0,0,0,0,1,14,1,122,24,95,68,117, + 109,109,121,77,111,100,117,108,101,76,111,99,107,46,97,99, + 113,117,105,114,101,99,1,0,0,0,0,0,0,0,1,0, + 0,0,3,0,0,0,67,0,0,0,115,36,0,0,0,124, + 0,106,0,100,1,107,2,114,18,116,1,100,2,131,1,130, + 1,124,0,4,0,106,0,100,3,56,0,2,0,95,0,100, + 0,83,0,41,4,78,114,19,0,0,0,122,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,33,0,0, + 0,41,2,114,24,0,0,0,114,36,0,0,0,41,1,114, + 26,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, + 0,0,0,114,35,0,0,0,132,0,0,0,115,6,0,0, + 0,0,1,10,1,8,1,122,24,95,68,117,109,109,121,77, + 111,100,117,108,101,76,111,99,107,46,114,101,108,101,97,115, + 101,99,1,0,0,0,0,0,0,0,1,0,0,0,5,0, + 0,0,67,0,0,0,115,18,0,0,0,100,1,160,0,124, + 0,106,1,116,2,124,0,131,1,161,2,83,0,41,2,78, + 122,28,95,68,117,109,109,121,77,111,100,117,108,101,76,111, + 99,107,40,123,33,114,125,41,32,97,116,32,123,125,41,3, + 114,38,0,0,0,114,15,0,0,0,114,39,0,0,0,41, + 1,114,26,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,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,27,0,0,0,114,34,0,0, + 0,114,35,0,0,0,114,40,0,0,0,114,10,0,0,0, + 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,114, + 41,0,0,0,120,0,0,0,115,10,0,0,0,8,2,4, + 2,8,4,8,4,8,5,114,41,0,0,0,99,0,0,0, + 0,0,0,0,0,0,0,0,0,2,0,0,0,64,0,0, + 0,115,36,0,0,0,101,0,90,1,100,0,90,2,100,1, + 100,2,132,0,90,3,100,3,100,4,132,0,90,4,100,5, + 100,6,132,0,90,5,100,7,83,0,41,8,218,18,95,77, + 111,100,117,108,101,76,111,99,107,77,97,110,97,103,101,114, + 99,2,0,0,0,0,0,0,0,2,0,0,0,2,0,0, + 0,67,0,0,0,115,16,0,0,0,124,1,124,0,95,0, + 100,0,124,0,95,1,100,0,83,0,41,1,78,41,2,218, + 5,95,110,97,109,101,218,5,95,108,111,99,107,41,2,114, 26,0,0,0,114,15,0,0,0,114,10,0,0,0,114,10, - 0,0,0,114,11,0,0,0,114,27,0,0,0,124,0,0, - 0,115,4,0,0,0,0,1,6,1,122,25,95,68,117,109, - 109,121,77,111,100,117,108,101,76,111,99,107,46,95,95,105, - 110,105,116,95,95,99,1,0,0,0,0,0,0,0,1,0, - 0,0,3,0,0,0,67,0,0,0,115,18,0,0,0,124, - 0,4,0,106,0,100,1,55,0,2,0,95,0,100,2,83, - 0,41,3,78,114,33,0,0,0,84,41,1,114,24,0,0, + 0,0,0,114,11,0,0,0,114,27,0,0,0,143,0,0, + 0,115,4,0,0,0,0,1,6,1,122,27,95,77,111,100, + 117,108,101,76,111,99,107,77,97,110,97,103,101,114,46,95, + 95,105,110,105,116,95,95,99,1,0,0,0,0,0,0,0, + 1,0,0,0,2,0,0,0,67,0,0,0,115,26,0,0, + 0,116,0,124,0,106,1,131,1,124,0,95,2,124,0,106, + 2,160,3,161,0,1,0,100,0,83,0,41,1,78,41,4, + 218,16,95,103,101,116,95,109,111,100,117,108,101,95,108,111, + 99,107,114,43,0,0,0,114,44,0,0,0,114,34,0,0, 0,41,1,114,26,0,0,0,114,10,0,0,0,114,10,0, - 0,0,114,11,0,0,0,114,34,0,0,0,128,0,0,0, - 115,4,0,0,0,0,1,14,1,122,24,95,68,117,109,109, - 121,77,111,100,117,108,101,76,111,99,107,46,97,99,113,117, - 105,114,101,99,1,0,0,0,0,0,0,0,1,0,0,0, - 3,0,0,0,67,0,0,0,115,36,0,0,0,124,0,106, - 0,100,1,107,2,114,18,116,1,100,2,131,1,130,1,124, - 0,4,0,106,0,100,3,56,0,2,0,95,0,100,0,83, - 0,41,4,78,114,19,0,0,0,122,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,33,0,0,0,41, - 2,114,24,0,0,0,114,36,0,0,0,41,1,114,26,0, - 0,0,114,10,0,0,0,114,10,0,0,0,114,11,0,0, - 0,114,35,0,0,0,132,0,0,0,115,6,0,0,0,0, - 1,10,1,8,1,122,24,95,68,117,109,109,121,77,111,100, - 117,108,101,76,111,99,107,46,114,101,108,101,97,115,101,99, - 1,0,0,0,0,0,0,0,1,0,0,0,5,0,0,0, - 67,0,0,0,115,18,0,0,0,100,1,160,0,124,0,106, - 1,116,2,124,0,131,1,161,2,83,0,41,2,78,122,28, - 95,68,117,109,109,121,77,111,100,117,108,101,76,111,99,107, - 40,123,33,114,125,41,32,97,116,32,123,125,41,3,114,38, - 0,0,0,114,15,0,0,0,114,39,0,0,0,41,1,114, - 26,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,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,27,0,0,0,114,34,0,0,0,114, - 35,0,0,0,114,40,0,0,0,114,10,0,0,0,114,10, - 0,0,0,114,10,0,0,0,114,11,0,0,0,114,41,0, - 0,0,120,0,0,0,115,8,0,0,0,12,4,8,4,8, - 4,8,5,114,41,0,0,0,99,0,0,0,0,0,0,0, - 0,0,0,0,0,2,0,0,0,64,0,0,0,115,36,0, - 0,0,101,0,90,1,100,0,90,2,100,1,100,2,132,0, - 90,3,100,3,100,4,132,0,90,4,100,5,100,6,132,0, - 90,5,100,7,83,0,41,8,218,18,95,77,111,100,117,108, - 101,76,111,99,107,77,97,110,97,103,101,114,99,2,0,0, - 0,0,0,0,0,2,0,0,0,2,0,0,0,67,0,0, - 0,115,16,0,0,0,124,1,124,0,95,0,100,0,124,0, - 95,1,100,0,83,0,41,1,78,41,2,218,5,95,110,97, - 109,101,218,5,95,108,111,99,107,41,2,114,26,0,0,0, + 0,0,114,11,0,0,0,218,9,95,95,101,110,116,101,114, + 95,95,147,0,0,0,115,4,0,0,0,0,1,12,1,122, + 28,95,77,111,100,117,108,101,76,111,99,107,77,97,110,97, + 103,101,114,46,95,95,101,110,116,101,114,95,95,99,1,0, + 0,0,0,0,0,0,3,0,0,0,2,0,0,0,79,0, + 0,0,115,14,0,0,0,124,0,106,0,160,1,161,0,1, + 0,100,0,83,0,41,1,78,41,2,114,44,0,0,0,114, + 35,0,0,0,41,3,114,26,0,0,0,218,4,97,114,103, + 115,90,6,107,119,97,114,103,115,114,10,0,0,0,114,10, + 0,0,0,114,11,0,0,0,218,8,95,95,101,120,105,116, + 95,95,151,0,0,0,115,2,0,0,0,0,1,122,27,95, + 77,111,100,117,108,101,76,111,99,107,77,97,110,97,103,101, + 114,46,95,95,101,120,105,116,95,95,78,41,6,114,1,0, + 0,0,114,0,0,0,0,114,2,0,0,0,114,27,0,0, + 0,114,46,0,0,0,114,48,0,0,0,114,10,0,0,0, + 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,114, + 42,0,0,0,141,0,0,0,115,6,0,0,0,8,2,8, + 4,8,4,114,42,0,0,0,99,1,0,0,0,0,0,0, + 0,3,0,0,0,8,0,0,0,67,0,0,0,115,130,0, + 0,0,116,0,160,1,161,0,1,0,122,106,121,14,116,2, + 124,0,25,0,131,0,125,1,87,0,110,24,4,0,116,3, + 107,10,114,48,1,0,1,0,1,0,100,1,125,1,89,0, + 110,2,88,0,124,1,100,1,107,8,114,112,116,4,100,1, + 107,8,114,76,116,5,124,0,131,1,125,1,110,8,116,6, + 124,0,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,100,1,116,0,160,9,161,0,1,0,88,0, + 124,1,83,0,41,4,122,139,71,101,116,32,111,114,32,99, + 114,101,97,116,101,32,116,104,101,32,109,111,100,117,108,101, + 32,108,111,99,107,32,102,111,114,32,97,32,103,105,118,101, + 110,32,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,2,0,0, + 0,8,0,0,0,83,0,0,0,115,48,0,0,0,116,0, + 160,1,161,0,1,0,122,24,116,2,160,3,124,1,161,1, + 124,0,107,8,114,30,116,2,124,1,61,0,87,0,100,0, + 116,0,160,4,161,0,1,0,88,0,100,0,83,0,41,1, + 78,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,30,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,15,0,0,0,114,10,0,0,0,114,10,0,0,0,114, - 11,0,0,0,114,27,0,0,0,143,0,0,0,115,4,0, - 0,0,0,1,6,1,122,27,95,77,111,100,117,108,101,76, - 111,99,107,77,97,110,97,103,101,114,46,95,95,105,110,105, - 116,95,95,99,1,0,0,0,0,0,0,0,1,0,0,0, - 2,0,0,0,67,0,0,0,115,26,0,0,0,116,0,124, - 0,106,1,131,1,124,0,95,2,124,0,106,2,160,3,161, - 0,1,0,100,0,83,0,41,1,78,41,4,218,16,95,103, - 101,116,95,109,111,100,117,108,101,95,108,111,99,107,114,43, - 0,0,0,114,44,0,0,0,114,34,0,0,0,41,1,114, - 26,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, - 0,0,0,218,9,95,95,101,110,116,101,114,95,95,147,0, - 0,0,115,4,0,0,0,0,1,12,1,122,28,95,77,111, - 100,117,108,101,76,111,99,107,77,97,110,97,103,101,114,46, - 95,95,101,110,116,101,114,95,95,99,1,0,0,0,0,0, - 0,0,3,0,0,0,2,0,0,0,79,0,0,0,115,14, - 0,0,0,124,0,106,0,160,1,161,0,1,0,100,0,83, - 0,41,1,78,41,2,114,44,0,0,0,114,35,0,0,0, - 41,3,114,26,0,0,0,218,4,97,114,103,115,90,6,107, - 119,97,114,103,115,114,10,0,0,0,114,10,0,0,0,114, - 11,0,0,0,218,8,95,95,101,120,105,116,95,95,151,0, - 0,0,115,2,0,0,0,0,1,122,27,95,77,111,100,117, - 108,101,76,111,99,107,77,97,110,97,103,101,114,46,95,95, - 101,120,105,116,95,95,78,41,6,114,1,0,0,0,114,0, - 0,0,0,114,2,0,0,0,114,27,0,0,0,114,46,0, - 0,0,114,48,0,0,0,114,10,0,0,0,114,10,0,0, - 0,114,10,0,0,0,114,11,0,0,0,114,42,0,0,0, - 141,0,0,0,115,6,0,0,0,8,2,8,4,8,4,114, - 42,0,0,0,99,1,0,0,0,0,0,0,0,3,0,0, - 0,8,0,0,0,67,0,0,0,115,130,0,0,0,116,0, - 160,1,161,0,1,0,122,106,121,14,116,2,124,0,25,0, - 131,0,125,1,87,0,110,24,4,0,116,3,107,10,114,48, - 1,0,1,0,1,0,100,1,125,1,89,0,110,2,88,0, - 124,1,100,1,107,8,114,112,116,4,100,1,107,8,114,76, - 116,5,124,0,131,1,125,1,110,8,116,6,124,0,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, - 100,1,116,0,160,9,161,0,1,0,88,0,124,1,83,0, - 41,4,122,139,71,101,116,32,111,114,32,99,114,101,97,116, - 101,32,116,104,101,32,109,111,100,117,108,101,32,108,111,99, - 107,32,102,111,114,32,97,32,103,105,118,101,110,32,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,2,0,0,0,8,0,0, - 0,83,0,0,0,115,48,0,0,0,116,0,160,1,161,0, - 1,0,122,24,116,2,160,3,124,1,161,1,124,0,107,8, - 114,30,116,2,124,1,61,0,87,0,100,0,116,0,160,4, - 161,0,1,0,88,0,100,0,83,0,41,1,78,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,30,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,15,0,0, - 0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, - 218,2,99,98,176,0,0,0,115,10,0,0,0,0,1,8, - 1,2,4,14,1,10,2,122,28,95,103,101,116,95,109,111, - 100,117,108,101,95,108,111,99,107,46,60,108,111,99,97,108, - 115,62,46,99,98,41,10,114,49,0,0,0,114,50,0,0, - 0,114,51,0,0,0,218,8,75,101,121,69,114,114,111,114, - 114,20,0,0,0,114,41,0,0,0,114,18,0,0,0,218, - 8,95,119,101,97,107,114,101,102,114,53,0,0,0,114,52, - 0,0,0,41,3,114,15,0,0,0,114,21,0,0,0,114, - 54,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, - 0,0,0,114,45,0,0,0,157,0,0,0,115,28,0,0, - 0,0,6,8,1,2,1,2,1,14,1,14,1,10,2,8, - 1,8,1,10,2,8,2,12,11,20,2,10,2,114,45,0, - 0,0,99,1,0,0,0,0,0,0,0,2,0,0,0,8, - 0,0,0,67,0,0,0,115,54,0,0,0,116,0,124,0, - 131,1,125,1,121,12,124,1,160,1,161,0,1,0,87,0, - 110,20,4,0,116,2,107,10,114,40,1,0,1,0,1,0, - 89,0,110,10,88,0,124,1,160,3,161,0,1,0,100,1, - 83,0,41,2,122,189,65,99,113,117,105,114,101,115,32,116, - 104,101,110,32,114,101,108,101,97,115,101,115,32,116,104,101, - 32,109,111,100,117,108,101,32,108,111,99,107,32,102,111,114, - 32,97,32,103,105,118,101,110,32,109,111,100,117,108,101,32, - 110,97,109,101,46,10,10,32,32,32,32,84,104,105,115,32, - 105,115,32,117,115,101,100,32,116,111,32,101,110,115,117,114, - 101,32,97,32,109,111,100,117,108,101,32,105,115,32,99,111, - 109,112,108,101,116,101,108,121,32,105,110,105,116,105,97,108, - 105,122,101,100,44,32,105,110,32,116,104,101,10,32,32,32, - 32,101,118,101,110,116,32,105,116,32,105,115,32,98,101,105, - 110,103,32,105,109,112,111,114,116,101,100,32,98,121,32,97, - 110,111,116,104,101,114,32,116,104,114,101,97,100,46,10,32, - 32,32,32,78,41,4,114,45,0,0,0,114,34,0,0,0, - 114,17,0,0,0,114,35,0,0,0,41,2,114,15,0,0, - 0,114,21,0,0,0,114,10,0,0,0,114,10,0,0,0, - 114,11,0,0,0,218,19,95,108,111,99,107,95,117,110,108, - 111,99,107,95,109,111,100,117,108,101,194,0,0,0,115,12, - 0,0,0,0,6,8,1,2,1,12,1,14,3,6,2,114, - 57,0,0,0,99,1,0,0,0,0,0,0,0,3,0,0, - 0,3,0,0,0,79,0,0,0,115,10,0,0,0,124,0, - 124,1,124,2,142,1,83,0,41,1,97,46,1,0,0,114, - 101,109,111,118,101,95,105,109,112,111,114,116,108,105,98,95, - 102,114,97,109,101,115,32,105,110,32,105,109,112,111,114,116, - 46,99,32,119,105,108,108,32,97,108,119,97,121,115,32,114, - 101,109,111,118,101,32,115,101,113,117,101,110,99,101,115,10, - 32,32,32,32,111,102,32,105,109,112,111,114,116,108,105,98, - 32,102,114,97,109,101,115,32,116,104,97,116,32,101,110,100, - 32,119,105,116,104,32,97,32,99,97,108,108,32,116,111,32, - 116,104,105,115,32,102,117,110,99,116,105,111,110,10,10,32, - 32,32,32,85,115,101,32,105,116,32,105,110,115,116,101,97, - 100,32,111,102,32,97,32,110,111,114,109,97,108,32,99,97, - 108,108,32,105,110,32,112,108,97,99,101,115,32,119,104,101, - 114,101,32,105,110,99,108,117,100,105,110,103,32,116,104,101, - 32,105,109,112,111,114,116,108,105,98,10,32,32,32,32,102, - 114,97,109,101,115,32,105,110,116,114,111,100,117,99,101,115, - 32,117,110,119,97,110,116,101,100,32,110,111,105,115,101,32, - 105,110,116,111,32,116,104,101,32,116,114,97,99,101,98,97, - 99,107,32,40,101,46,103,46,32,119,104,101,110,32,101,120, - 101,99,117,116,105,110,103,10,32,32,32,32,109,111,100,117, - 108,101,32,99,111,100,101,41,10,32,32,32,32,114,10,0, - 0,0,41,3,218,1,102,114,47,0,0,0,90,4,107,119, - 100,115,114,10,0,0,0,114,10,0,0,0,114,11,0,0, - 0,218,25,95,99,97,108,108,95,119,105,116,104,95,102,114, - 97,109,101,115,95,114,101,109,111,118,101,100,211,0,0,0, - 115,2,0,0,0,0,8,114,59,0,0,0,114,33,0,0, - 0,41,1,218,9,118,101,114,98,111,115,105,116,121,99,1, - 0,0,0,1,0,0,0,3,0,0,0,4,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,14,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,38,0,0,0,218,6,115,116,100,101,114, - 114,41,3,218,7,109,101,115,115,97,103,101,114,60,0,0, - 0,114,47,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,68,0,0,0,99,1,0, - 0,0,0,0,0,0,2,0,0,0,3,0,0,0,3,0, - 0,0,115,26,0,0,0,135,0,102,1,100,1,100,2,132, - 8,125,1,116,0,124,1,136,0,131,2,1,0,124,1,83, - 0,41,3,122,49,68,101,99,111,114,97,116,111,114,32,116, - 111,32,118,101,114,105,102,121,32,116,104,101,32,110,97,109, - 101,100,32,109,111,100,117,108,101,32,105,115,32,98,117,105, - 108,116,45,105,110,46,99,2,0,0,0,0,0,0,0,2, - 0,0,0,4,0,0,0,19,0,0,0,115,38,0,0,0, - 124,1,116,0,106,1,107,7,114,28,116,2,100,1,160,3, - 124,1,161,1,124,1,100,2,141,2,130,1,136,0,124,0, - 124,1,131,2,83,0,41,3,78,122,29,123,33,114,125,32, - 105,115,32,110,111,116,32,97,32,98,117,105,108,116,45,105, + 11,0,0,0,218,2,99,98,176,0,0,0,115,10,0,0, + 0,0,1,8,1,2,4,14,1,10,2,122,28,95,103,101, + 116,95,109,111,100,117,108,101,95,108,111,99,107,46,60,108, + 111,99,97,108,115,62,46,99,98,41,10,114,49,0,0,0, + 114,50,0,0,0,114,51,0,0,0,218,8,75,101,121,69, + 114,114,111,114,114,20,0,0,0,114,41,0,0,0,114,18, + 0,0,0,218,8,95,119,101,97,107,114,101,102,114,53,0, + 0,0,114,52,0,0,0,41,3,114,15,0,0,0,114,21, + 0,0,0,114,54,0,0,0,114,10,0,0,0,114,10,0, + 0,0,114,11,0,0,0,114,45,0,0,0,157,0,0,0, + 115,28,0,0,0,0,6,8,1,2,1,2,1,14,1,14, + 1,10,2,8,1,8,1,10,2,8,2,12,11,20,2,10, + 2,114,45,0,0,0,99,1,0,0,0,0,0,0,0,2, + 0,0,0,8,0,0,0,67,0,0,0,115,54,0,0,0, + 116,0,124,0,131,1,125,1,121,12,124,1,160,1,161,0, + 1,0,87,0,110,20,4,0,116,2,107,10,114,40,1,0, + 1,0,1,0,89,0,110,10,88,0,124,1,160,3,161,0, + 1,0,100,1,83,0,41,2,122,189,65,99,113,117,105,114, + 101,115,32,116,104,101,110,32,114,101,108,101,97,115,101,115, + 32,116,104,101,32,109,111,100,117,108,101,32,108,111,99,107, + 32,102,111,114,32,97,32,103,105,118,101,110,32,109,111,100, + 117,108,101,32,110,97,109,101,46,10,10,32,32,32,32,84, + 104,105,115,32,105,115,32,117,115,101,100,32,116,111,32,101, + 110,115,117,114,101,32,97,32,109,111,100,117,108,101,32,105, + 115,32,99,111,109,112,108,101,116,101,108,121,32,105,110,105, + 116,105,97,108,105,122,101,100,44,32,105,110,32,116,104,101, + 10,32,32,32,32,101,118,101,110,116,32,105,116,32,105,115, + 32,98,101,105,110,103,32,105,109,112,111,114,116,101,100,32, + 98,121,32,97,110,111,116,104,101,114,32,116,104,114,101,97, + 100,46,10,32,32,32,32,78,41,4,114,45,0,0,0,114, + 34,0,0,0,114,17,0,0,0,114,35,0,0,0,41,2, + 114,15,0,0,0,114,21,0,0,0,114,10,0,0,0,114, + 10,0,0,0,114,11,0,0,0,218,19,95,108,111,99,107, + 95,117,110,108,111,99,107,95,109,111,100,117,108,101,194,0, + 0,0,115,12,0,0,0,0,6,8,1,2,1,12,1,14, + 3,6,2,114,57,0,0,0,99,1,0,0,0,0,0,0, + 0,3,0,0,0,3,0,0,0,79,0,0,0,115,10,0, + 0,0,124,0,124,1,124,2,142,1,83,0,41,1,97,46, + 1,0,0,114,101,109,111,118,101,95,105,109,112,111,114,116, + 108,105,98,95,102,114,97,109,101,115,32,105,110,32,105,109, + 112,111,114,116,46,99,32,119,105,108,108,32,97,108,119,97, + 121,115,32,114,101,109,111,118,101,32,115,101,113,117,101,110, + 99,101,115,10,32,32,32,32,111,102,32,105,109,112,111,114, + 116,108,105,98,32,102,114,97,109,101,115,32,116,104,97,116, + 32,101,110,100,32,119,105,116,104,32,97,32,99,97,108,108, + 32,116,111,32,116,104,105,115,32,102,117,110,99,116,105,111, + 110,10,10,32,32,32,32,85,115,101,32,105,116,32,105,110, + 115,116,101,97,100,32,111,102,32,97,32,110,111,114,109,97, + 108,32,99,97,108,108,32,105,110,32,112,108,97,99,101,115, + 32,119,104,101,114,101,32,105,110,99,108,117,100,105,110,103, + 32,116,104,101,32,105,109,112,111,114,116,108,105,98,10,32, + 32,32,32,102,114,97,109,101,115,32,105,110,116,114,111,100, + 117,99,101,115,32,117,110,119,97,110,116,101,100,32,110,111, + 105,115,101,32,105,110,116,111,32,116,104,101,32,116,114,97, + 99,101,98,97,99,107,32,40,101,46,103,46,32,119,104,101, + 110,32,101,120,101,99,117,116,105,110,103,10,32,32,32,32, + 109,111,100,117,108,101,32,99,111,100,101,41,10,32,32,32, + 32,114,10,0,0,0,41,3,218,1,102,114,47,0,0,0, + 90,4,107,119,100,115,114,10,0,0,0,114,10,0,0,0, + 114,11,0,0,0,218,25,95,99,97,108,108,95,119,105,116, + 104,95,102,114,97,109,101,115,95,114,101,109,111,118,101,100, + 211,0,0,0,115,2,0,0,0,0,8,114,59,0,0,0, + 114,33,0,0,0,41,1,218,9,118,101,114,98,111,115,105, + 116,121,99,1,0,0,0,1,0,0,0,3,0,0,0,4, + 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,14,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,38,0,0,0,218,6,115, + 116,100,101,114,114,41,3,218,7,109,101,115,115,97,103,101, + 114,60,0,0,0,114,47,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,68,0,0, + 0,99,1,0,0,0,0,0,0,0,2,0,0,0,3,0, + 0,0,3,0,0,0,115,26,0,0,0,135,0,102,1,100, + 1,100,2,132,8,125,1,116,0,124,1,136,0,131,2,1, + 0,124,1,83,0,41,3,122,49,68,101,99,111,114,97,116, + 111,114,32,116,111,32,118,101,114,105,102,121,32,116,104,101, + 32,110,97,109,101,100,32,109,111,100,117,108,101,32,105,115, + 32,98,117,105,108,116,45,105,110,46,99,2,0,0,0,0, + 0,0,0,2,0,0,0,4,0,0,0,19,0,0,0,115, + 38,0,0,0,124,1,116,0,106,1,107,7,114,28,116,2, + 100,1,160,3,124,1,161,1,124,1,100,2,141,2,130,1, + 136,0,124,0,124,1,131,2,83,0,41,3,78,122,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,41,1,114,15, + 0,0,0,41,4,114,14,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,38,0, + 0,0,41,2,114,26,0,0,0,218,8,102,117,108,108,110, + 97,109,101,41,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,8,0,0,0,0,1,10,1,10,1,8,1, + 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,41,1,114,12,0,0,0,41,2,114, + 72,0,0,0,114,73,0,0,0,114,10,0,0,0,41,1, + 114,72,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,74,0,0, + 0,99,1,0,0,0,0,0,0,0,2,0,0,0,3,0, + 0,0,3,0,0,0,115,26,0,0,0,135,0,102,1,100, + 1,100,2,132,8,125,1,116,0,124,1,136,0,131,2,1, + 0,124,1,83,0,41,3,122,47,68,101,99,111,114,97,116, + 111,114,32,116,111,32,118,101,114,105,102,121,32,116,104,101, + 32,110,97,109,101,100,32,109,111,100,117,108,101,32,105,115, + 32,102,114,111,122,101,110,46,99,2,0,0,0,0,0,0, + 0,2,0,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,41,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,41,1,114,15,0,0,0,41, - 4,114,14,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,38,0,0,0,41,2, - 114,26,0,0,0,218,8,102,117,108,108,110,97,109,101,41, - 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, - 8,0,0,0,0,1,10,1,10,1,8,1,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,41,1,114,12,0,0,0,41,2,114,72,0,0,0, - 114,73,0,0,0,114,10,0,0,0,41,1,114,72,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,74,0,0,0,99,1,0, - 0,0,0,0,0,0,2,0,0,0,3,0,0,0,3,0, - 0,0,115,26,0,0,0,135,0,102,1,100,1,100,2,132, - 8,125,1,116,0,124,1,136,0,131,2,1,0,124,1,83, - 0,41,3,122,47,68,101,99,111,114,97,116,111,114,32,116, - 111,32,118,101,114,105,102,121,32,116,104,101,32,110,97,109, - 101,100,32,109,111,100,117,108,101,32,105,115,32,102,114,111, - 122,101,110,46,99,2,0,0,0,0,0,0,0,2,0,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,41,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,41,1,114,15,0,0,0,41,4,114,49,0, - 0,0,218,9,105,115,95,102,114,111,122,101,110,114,70,0, - 0,0,114,38,0,0,0,41,2,114,26,0,0,0,114,71, - 0,0,0,41,1,114,72,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,8,0,0,0,0,1,10,1,10,1,8,1,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,41,1,114,12,0,0,0,41,2,114,72,0,0, - 0,114,76,0,0,0,114,10,0,0,0,41,1,114,72,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,77,0,0,0,99,2,0, - 0,0,0,0,0,0,4,0,0,0,3,0,0,0,67,0, - 0,0,115,62,0,0,0,116,0,124,1,124,0,131,2,125, - 2,124,1,116,1,106,2,107,6,114,50,116,1,106,2,124, - 1,25,0,125,3,116,3,124,2,124,3,131,2,1,0,116, - 1,106,2,124,1,25,0,83,0,116,4,124,2,131,1,83, - 0,100,1,83,0,41,2,122,128,76,111,97,100,32,116,104, - 101,32,115,112,101,99,105,102,105,101,100,32,109,111,100,117, - 108,101,32,105,110,116,111,32,115,121,115,46,109,111,100,117, - 108,101,115,32,97,110,100,32,114,101,116,117,114,110,32,105, - 116,46,10,10,32,32,32,32,84,104,105,115,32,109,101,116, - 104,111,100,32,105,115,32,100,101,112,114,101,99,97,116,101, - 100,46,32,32,85,115,101,32,108,111,97,100,101,114,46,101, - 120,101,99,95,109,111,100,117,108,101,32,105,110,115,116,101, - 97,100,46,10,10,32,32,32,32,78,41,5,218,16,115,112, - 101,99,95,102,114,111,109,95,108,111,97,100,101,114,114,14, - 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,26,0,0, - 0,114,71,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,84,0,0,0, - 99,1,0,0,0,0,0,0,0,5,0,0,0,8,0,0, - 0,67,0,0,0,115,216,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, - 121,10,124,1,160,2,124,0,161,1,83,0,4,0,116,3, - 107,10,114,52,1,0,1,0,1,0,89,0,110,2,88,0, - 121,10,124,0,106,4,125,2,87,0,110,20,4,0,116,5, - 107,10,114,84,1,0,1,0,1,0,89,0,110,18,88,0, - 124,2,100,0,107,9,114,102,116,6,124,2,131,1,83,0, - 121,10,124,0,106,7,125,3,87,0,110,24,4,0,116,5, - 107,10,114,136,1,0,1,0,1,0,100,3,125,3,89,0, - 110,2,88,0,121,10,124,0,106,8,125,4,87,0,110,50, - 4,0,116,5,107,10,114,198,1,0,1,0,1,0,124,1, - 100,0,107,8,114,182,100,4,160,9,124,3,161,1,83,0, - 100,5,160,9,124,3,124,1,161,2,83,0,89,0,110,14, - 88,0,100,6,160,9,124,3,124,4,161,2,83,0,100,0, - 83,0,41,7,78,218,10,95,95,108,111,97,100,101,114,95, - 95,218,11,109,111,100,117,108,101,95,114,101,112,114,250,1, - 63,122,13,60,109,111,100,117,108,101,32,123,33,114,125,62, - 122,20,60,109,111,100,117,108,101,32,123,33,114,125,32,40, - 123,33,114,125,41,62,122,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,86,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,38,0,0, - 0,41,5,114,83,0,0,0,218,6,108,111,97,100,101,114, - 114,82,0,0,0,114,15,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,10,1,14,1,6,1,2,1,10,1,14,1,6,2, - 8,1,8,4,2,1,10,1,14,1,10,1,2,1,10,1, - 14,1,8,1,10,2,18,2,114,95,0,0,0,99,0,0, - 0,0,0,0,0,0,0,0,0,0,2,0,0,0,64,0, - 0,0,115,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,17,95, - 105,110,115,116,97,108,108,101,100,95,115,97,102,101,108,121, - 99,2,0,0,0,0,0,0,0,2,0,0,0,2,0,0, - 0,67,0,0,0,115,18,0,0,0,124,1,124,0,95,0, - 124,1,106,1,124,0,95,2,100,0,83,0,41,1,78,41, - 3,218,7,95,109,111,100,117,108,101,114,89,0,0,0,218, - 5,95,115,112,101,99,41,2,114,26,0,0,0,114,83,0, + 4,114,49,0,0,0,218,9,105,115,95,102,114,111,122,101, + 110,114,70,0,0,0,114,38,0,0,0,41,2,114,26,0, + 0,0,114,71,0,0,0,41,1,114,72,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,8,0,0,0,0,1,10,1,10, + 1,8,1,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,41,1,114,12,0,0,0,41,2, + 114,72,0,0,0,114,76,0,0,0,114,10,0,0,0,41, + 1,114,72,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,77,0,0, + 0,99,2,0,0,0,0,0,0,0,4,0,0,0,3,0, + 0,0,67,0,0,0,115,62,0,0,0,116,0,124,1,124, + 0,131,2,125,2,124,1,116,1,106,2,107,6,114,50,116, + 1,106,2,124,1,25,0,125,3,116,3,124,2,124,3,131, + 2,1,0,116,1,106,2,124,1,25,0,83,0,116,4,124, + 2,131,1,83,0,100,1,83,0,41,2,122,128,76,111,97, + 100,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32, + 109,111,100,117,108,101,32,105,110,116,111,32,115,121,115,46, + 109,111,100,117,108,101,115,32,97,110,100,32,114,101,116,117, + 114,110,32,105,116,46,10,10,32,32,32,32,84,104,105,115, + 32,109,101,116,104,111,100,32,105,115,32,100,101,112,114,101, + 99,97,116,101,100,46,32,32,85,115,101,32,108,111,97,100, + 101,114,46,101,120,101,99,95,109,111,100,117,108,101,32,105, + 110,115,116,101,97,100,46,10,10,32,32,32,32,78,41,5, + 218,16,115,112,101,99,95,102,114,111,109,95,108,111,97,100, + 101,114,114,14,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,26,0,0,0,114,71,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, + 84,0,0,0,99,1,0,0,0,0,0,0,0,5,0,0, + 0,8,0,0,0,67,0,0,0,115,216,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,121,10,124,1,160,2,124,0,161,1,83,0, + 4,0,116,3,107,10,114,52,1,0,1,0,1,0,89,0, + 110,2,88,0,121,10,124,0,106,4,125,2,87,0,110,20, + 4,0,116,5,107,10,114,84,1,0,1,0,1,0,89,0, + 110,18,88,0,124,2,100,0,107,9,114,102,116,6,124,2, + 131,1,83,0,121,10,124,0,106,7,125,3,87,0,110,24, + 4,0,116,5,107,10,114,136,1,0,1,0,1,0,100,3, + 125,3,89,0,110,2,88,0,121,10,124,0,106,8,125,4, + 87,0,110,50,4,0,116,5,107,10,114,198,1,0,1,0, + 1,0,124,1,100,0,107,8,114,182,100,4,160,9,124,3, + 161,1,83,0,100,5,160,9,124,3,124,1,161,2,83,0, + 89,0,110,14,88,0,100,6,160,9,124,3,124,4,161,2, + 83,0,100,0,83,0,41,7,78,218,10,95,95,108,111,97, + 100,101,114,95,95,218,11,109,111,100,117,108,101,95,114,101, + 112,114,250,1,63,122,13,60,109,111,100,117,108,101,32,123, + 33,114,125,62,122,20,60,109,111,100,117,108,101,32,123,33, + 114,125,32,40,123,33,114,125,41,62,122,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, + 86,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,38,0,0,0,41,5,114,83,0,0,0,218,6,108,111, + 97,100,101,114,114,82,0,0,0,114,15,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,10,1,14,1,6,1,2,1,10,1, + 14,1,6,2,8,1,8,4,2,1,10,1,14,1,10,1, + 2,1,10,1,14,1,8,1,10,2,18,2,114,95,0,0, + 0,99,0,0,0,0,0,0,0,0,0,0,0,0,2,0, + 0,0,64,0,0,0,115,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,17,95,105,110,115,116,97,108,108,101,100,95,115,97, + 102,101,108,121,99,2,0,0,0,0,0,0,0,2,0,0, + 0,2,0,0,0,67,0,0,0,115,18,0,0,0,124,1, + 124,0,95,0,124,1,106,1,124,0,95,2,100,0,83,0, + 41,1,78,41,3,218,7,95,109,111,100,117,108,101,114,89, + 0,0,0,218,5,95,115,112,101,99,41,2,114,26,0,0, + 0,114,83,0,0,0,114,10,0,0,0,114,10,0,0,0, + 114,11,0,0,0,114,27,0,0,0,51,1,0,0,115,4, + 0,0,0,0,1,6,1,122,26,95,105,110,115,116,97,108, + 108,101,100,95,115,97,102,101,108,121,46,95,95,105,110,105, + 116,95,95,99,1,0,0,0,0,0,0,0,1,0,0,0, + 3,0,0,0,67,0,0,0,115,28,0,0,0,100,1,124, + 0,106,0,95,1,124,0,106,2,116,3,106,4,124,0,106, + 0,106,5,60,0,100,0,83,0,41,2,78,84,41,6,114, + 98,0,0,0,218,13,95,105,110,105,116,105,97,108,105,122, + 105,110,103,114,97,0,0,0,114,14,0,0,0,114,79,0, + 0,0,114,15,0,0,0,41,1,114,26,0,0,0,114,10, + 0,0,0,114,10,0,0,0,114,11,0,0,0,114,46,0, + 0,0,55,1,0,0,115,4,0,0,0,0,4,8,1,122, + 27,95,105,110,115,116,97,108,108,101,100,95,115,97,102,101, + 108,121,46,95,95,101,110,116,101,114,95,95,99,1,0,0, + 0,0,0,0,0,3,0,0,0,8,0,0,0,71,0,0, + 0,115,98,0,0,0,122,82,124,0,106,0,125,2,116,1, + 100,1,100,2,132,0,124,1,68,0,131,1,131,1,114,64, + 121,14,116,2,106,3,124,2,106,4,61,0,87,0,113,80, + 4,0,116,5,107,10,114,60,1,0,1,0,1,0,89,0, + 113,80,88,0,110,16,116,6,100,3,124,2,106,4,124,2, + 106,7,131,3,1,0,87,0,100,0,100,4,124,0,106,0, + 95,8,88,0,100,0,83,0,41,5,78,99,1,0,0,0, + 0,0,0,0,2,0,0,0,3,0,0,0,115,0,0,0, + 115,22,0,0,0,124,0,93,14,125,1,124,1,100,0,107, + 9,86,0,1,0,113,2,100,0,83,0,41,1,78,114,10, + 0,0,0,41,2,90,2,46,48,90,3,97,114,103,114,10, + 0,0,0,114,10,0,0,0,114,11,0,0,0,250,9,60, + 103,101,110,101,120,112,114,62,65,1,0,0,115,2,0,0, + 0,4,0,122,45,95,105,110,115,116,97,108,108,101,100,95, + 115,97,102,101,108,121,46,95,95,101,120,105,116,95,95,46, + 60,108,111,99,97,108,115,62,46,60,103,101,110,101,120,112, + 114,62,122,18,105,109,112,111,114,116,32,123,33,114,125,32, + 35,32,123,33,114,125,70,41,9,114,98,0,0,0,218,3, + 97,110,121,114,14,0,0,0,114,79,0,0,0,114,15,0, + 0,0,114,55,0,0,0,114,68,0,0,0,114,93,0,0, + 0,114,99,0,0,0,41,3,114,26,0,0,0,114,47,0, + 0,0,114,82,0,0,0,114,10,0,0,0,114,10,0,0, + 0,114,11,0,0,0,114,48,0,0,0,62,1,0,0,115, + 18,0,0,0,0,1,2,1,6,1,18,1,2,1,14,1, + 14,1,8,2,20,2,122,26,95,105,110,115,116,97,108,108, + 101,100,95,115,97,102,101,108,121,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,27,0,0,0,114,46,0,0,0,114,48, + 0,0,0,114,10,0,0,0,114,10,0,0,0,114,10,0, + 0,0,114,11,0,0,0,114,96,0,0,0,49,1,0,0, + 115,6,0,0,0,8,2,8,4,8,7,114,96,0,0,0, + 99,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0, + 0,64,0,0,0,115,114,0,0,0,101,0,90,1,100,0, + 90,2,100,1,90,3,100,2,100,2,100,2,100,3,156,3, + 100,4,100,5,132,2,90,4,100,6,100,7,132,0,90,5, + 100,8,100,9,132,0,90,6,101,7,100,10,100,11,132,0, + 131,1,90,8,101,8,106,9,100,12,100,11,132,0,131,1, + 90,8,101,7,100,13,100,14,132,0,131,1,90,10,101,7, + 100,15,100,16,132,0,131,1,90,11,101,11,106,9,100,17, + 100,16,132,0,131,1,90,11,100,2,83,0,41,18,218,10, + 77,111,100,117,108,101,83,112,101,99,97,208,5,0,0,84, + 104,101,32,115,112,101,99,105,102,105,99,97,116,105,111,110, + 32,102,111,114,32,97,32,109,111,100,117,108,101,44,32,117, + 115,101,100,32,102,111,114,32,108,111,97,100,105,110,103,46, + 10,10,32,32,32,32,65,32,109,111,100,117,108,101,39,115, + 32,115,112,101,99,32,105,115,32,116,104,101,32,115,111,117, + 114,99,101,32,102,111,114,32,105,110,102,111,114,109,97,116, + 105,111,110,32,97,98,111,117,116,32,116,104,101,32,109,111, + 100,117,108,101,46,32,32,70,111,114,10,32,32,32,32,100, + 97,116,97,32,97,115,115,111,99,105,97,116,101,100,32,119, + 105,116,104,32,116,104,101,32,109,111,100,117,108,101,44,32, + 105,110,99,108,117,100,105,110,103,32,115,111,117,114,99,101, + 44,32,117,115,101,32,116,104,101,32,115,112,101,99,39,115, + 10,32,32,32,32,108,111,97,100,101,114,46,10,10,32,32, + 32,32,96,110,97,109,101,96,32,105,115,32,116,104,101,32, + 97,98,115,111,108,117,116,101,32,110,97,109,101,32,111,102, + 32,116,104,101,32,109,111,100,117,108,101,46,32,32,96,108, + 111,97,100,101,114,96,32,105,115,32,116,104,101,32,108,111, + 97,100,101,114,10,32,32,32,32,116,111,32,117,115,101,32, + 119,104,101,110,32,108,111,97,100,105,110,103,32,116,104,101, + 32,109,111,100,117,108,101,46,32,32,96,112,97,114,101,110, + 116,96,32,105,115,32,116,104,101,32,110,97,109,101,32,111, + 102,32,116,104,101,10,32,32,32,32,112,97,99,107,97,103, + 101,32,116,104,101,32,109,111,100,117,108,101,32,105,115,32, + 105,110,46,32,32,84,104,101,32,112,97,114,101,110,116,32, + 105,115,32,100,101,114,105,118,101,100,32,102,114,111,109,32, + 116,104,101,32,110,97,109,101,46,10,10,32,32,32,32,96, + 105,115,95,112,97,99,107,97,103,101,96,32,100,101,116,101, + 114,109,105,110,101,115,32,105,102,32,116,104,101,32,109,111, + 100,117,108,101,32,105,115,32,99,111,110,115,105,100,101,114, + 101,100,32,97,32,112,97,99,107,97,103,101,32,111,114,10, + 32,32,32,32,110,111,116,46,32,32,79,110,32,109,111,100, + 117,108,101,115,32,116,104,105,115,32,105,115,32,114,101,102, + 108,101,99,116,101,100,32,98,121,32,116,104,101,32,96,95, + 95,112,97,116,104,95,95,96,32,97,116,116,114,105,98,117, + 116,101,46,10,10,32,32,32,32,96,111,114,105,103,105,110, + 96,32,105,115,32,116,104,101,32,115,112,101,99,105,102,105, + 99,32,108,111,99,97,116,105,111,110,32,117,115,101,100,32, + 98,121,32,116,104,101,32,108,111,97,100,101,114,32,102,114, + 111,109,32,119,104,105,99,104,32,116,111,10,32,32,32,32, + 108,111,97,100,32,116,104,101,32,109,111,100,117,108,101,44, + 32,105,102,32,116,104,97,116,32,105,110,102,111,114,109,97, + 116,105,111,110,32,105,115,32,97,118,97,105,108,97,98,108, + 101,46,32,32,87,104,101,110,32,102,105,108,101,110,97,109, + 101,32,105,115,10,32,32,32,32,115,101,116,44,32,111,114, + 105,103,105,110,32,119,105,108,108,32,109,97,116,99,104,46, + 10,10,32,32,32,32,96,104,97,115,95,108,111,99,97,116, + 105,111,110,96,32,105,110,100,105,99,97,116,101,115,32,116, + 104,97,116,32,97,32,115,112,101,99,39,115,32,34,111,114, + 105,103,105,110,34,32,114,101,102,108,101,99,116,115,32,97, + 32,108,111,99,97,116,105,111,110,46,10,32,32,32,32,87, + 104,101,110,32,116,104,105,115,32,105,115,32,84,114,117,101, + 44,32,96,95,95,102,105,108,101,95,95,96,32,97,116,116, + 114,105,98,117,116,101,32,111,102,32,116,104,101,32,109,111, + 100,117,108,101,32,105,115,32,115,101,116,46,10,10,32,32, + 32,32,96,99,97,99,104,101,100,96,32,105,115,32,116,104, + 101,32,108,111,99,97,116,105,111,110,32,111,102,32,116,104, + 101,32,99,97,99,104,101,100,32,98,121,116,101,99,111,100, + 101,32,102,105,108,101,44,32,105,102,32,97,110,121,46,32, + 32,73,116,10,32,32,32,32,99,111,114,114,101,115,112,111, + 110,100,115,32,116,111,32,116,104,101,32,96,95,95,99,97, + 99,104,101,100,95,95,96,32,97,116,116,114,105,98,117,116, + 101,46,10,10,32,32,32,32,96,115,117,98,109,111,100,117, + 108,101,95,115,101,97,114,99,104,95,108,111,99,97,116,105, + 111,110,115,96,32,105,115,32,116,104,101,32,115,101,113,117, + 101,110,99,101,32,111,102,32,112,97,116,104,32,101,110,116, + 114,105,101,115,32,116,111,10,32,32,32,32,115,101,97,114, + 99,104,32,119,104,101,110,32,105,109,112,111,114,116,105,110, + 103,32,115,117,98,109,111,100,117,108,101,115,46,32,32,73, + 102,32,115,101,116,44,32,105,115,95,112,97,99,107,97,103, + 101,32,115,104,111,117,108,100,32,98,101,10,32,32,32,32, + 84,114,117,101,45,45,97,110,100,32,70,97,108,115,101,32, + 111,116,104,101,114,119,105,115,101,46,10,10,32,32,32,32, + 80,97,99,107,97,103,101,115,32,97,114,101,32,115,105,109, + 112,108,121,32,109,111,100,117,108,101,115,32,116,104,97,116, + 32,40,109,97,121,41,32,104,97,118,101,32,115,117,98,109, + 111,100,117,108,101,115,46,32,32,73,102,32,97,32,115,112, + 101,99,10,32,32,32,32,104,97,115,32,97,32,110,111,110, + 45,78,111,110,101,32,118,97,108,117,101,32,105,110,32,96, + 115,117,98,109,111,100,117,108,101,95,115,101,97,114,99,104, + 95,108,111,99,97,116,105,111,110,115,96,44,32,116,104,101, + 32,105,109,112,111,114,116,10,32,32,32,32,115,121,115,116, + 101,109,32,119,105,108,108,32,99,111,110,115,105,100,101,114, + 32,109,111,100,117,108,101,115,32,108,111,97,100,101,100,32, + 102,114,111,109,32,116,104,101,32,115,112,101,99,32,97,115, + 32,112,97,99,107,97,103,101,115,46,10,10,32,32,32,32, + 79,110,108,121,32,102,105,110,100,101,114,115,32,40,115,101, + 101,32,105,109,112,111,114,116,108,105,98,46,97,98,99,46, + 77,101,116,97,80,97,116,104,70,105,110,100,101,114,32,97, + 110,100,10,32,32,32,32,105,109,112,111,114,116,108,105,98, + 46,97,98,99,46,80,97,116,104,69,110,116,114,121,70,105, + 110,100,101,114,41,32,115,104,111,117,108,100,32,109,111,100, + 105,102,121,32,77,111,100,117,108,101,83,112,101,99,32,105, + 110,115,116,97,110,99,101,115,46,10,10,32,32,32,32,78, + 41,3,218,6,111,114,105,103,105,110,218,12,108,111,97,100, + 101,114,95,115,116,97,116,101,218,10,105,115,95,112,97,99, + 107,97,103,101,99,3,0,0,0,3,0,0,0,6,0,0, + 0,2,0,0,0,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,15,0,0,0,114, + 93,0,0,0,114,103,0,0,0,114,104,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,26,0,0,0,114,15,0,0,0,114,93, + 0,0,0,114,103,0,0,0,114,104,0,0,0,114,105,0, 0,0,114,10,0,0,0,114,10,0,0,0,114,11,0,0, - 0,114,27,0,0,0,51,1,0,0,115,4,0,0,0,0, - 1,6,1,122,26,95,105,110,115,116,97,108,108,101,100,95, - 115,97,102,101,108,121,46,95,95,105,110,105,116,95,95,99, - 1,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0, - 67,0,0,0,115,28,0,0,0,100,1,124,0,106,0,95, - 1,124,0,106,2,116,3,106,4,124,0,106,0,106,5,60, - 0,100,0,83,0,41,2,78,84,41,6,114,98,0,0,0, - 218,13,95,105,110,105,116,105,97,108,105,122,105,110,103,114, - 97,0,0,0,114,14,0,0,0,114,79,0,0,0,114,15, - 0,0,0,41,1,114,26,0,0,0,114,10,0,0,0,114, - 10,0,0,0,114,11,0,0,0,114,46,0,0,0,55,1, - 0,0,115,4,0,0,0,0,4,8,1,122,27,95,105,110, - 115,116,97,108,108,101,100,95,115,97,102,101,108,121,46,95, - 95,101,110,116,101,114,95,95,99,1,0,0,0,0,0,0, - 0,3,0,0,0,8,0,0,0,71,0,0,0,115,98,0, - 0,0,122,82,124,0,106,0,125,2,116,1,100,1,100,2, - 132,0,124,1,68,0,131,1,131,1,114,64,121,14,116,2, - 106,3,124,2,106,4,61,0,87,0,113,80,4,0,116,5, - 107,10,114,60,1,0,1,0,1,0,89,0,113,80,88,0, - 110,16,116,6,100,3,124,2,106,4,124,2,106,7,131,3, - 1,0,87,0,100,0,100,4,124,0,106,0,95,8,88,0, - 100,0,83,0,41,5,78,99,1,0,0,0,0,0,0,0, - 2,0,0,0,3,0,0,0,115,0,0,0,115,22,0,0, - 0,124,0,93,14,125,1,124,1,100,0,107,9,86,0,1, - 0,113,2,100,0,83,0,41,1,78,114,10,0,0,0,41, - 2,90,2,46,48,90,3,97,114,103,114,10,0,0,0,114, - 10,0,0,0,114,11,0,0,0,250,9,60,103,101,110,101, - 120,112,114,62,65,1,0,0,115,2,0,0,0,4,0,122, - 45,95,105,110,115,116,97,108,108,101,100,95,115,97,102,101, - 108,121,46,95,95,101,120,105,116,95,95,46,60,108,111,99, - 97,108,115,62,46,60,103,101,110,101,120,112,114,62,122,18, - 105,109,112,111,114,116,32,123,33,114,125,32,35,32,123,33, - 114,125,70,41,9,114,98,0,0,0,218,3,97,110,121,114, - 14,0,0,0,114,79,0,0,0,114,15,0,0,0,114,55, - 0,0,0,114,68,0,0,0,114,93,0,0,0,114,99,0, - 0,0,41,3,114,26,0,0,0,114,47,0,0,0,114,82, - 0,0,0,114,10,0,0,0,114,10,0,0,0,114,11,0, - 0,0,114,48,0,0,0,62,1,0,0,115,18,0,0,0, - 0,1,2,1,6,1,18,1,2,1,14,1,14,1,8,2, - 20,2,122,26,95,105,110,115,116,97,108,108,101,100,95,115, - 97,102,101,108,121,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,27,0,0,0,114,46,0,0,0,114,48,0,0,0,114, - 10,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, - 0,0,0,114,96,0,0,0,49,1,0,0,115,6,0,0, - 0,8,2,8,4,8,7,114,96,0,0,0,99,0,0,0, - 0,0,0,0,0,0,0,0,0,4,0,0,0,64,0,0, - 0,115,114,0,0,0,101,0,90,1,100,0,90,2,100,1, - 90,3,100,2,100,2,100,2,100,3,156,3,100,4,100,5, - 132,2,90,4,100,6,100,7,132,0,90,5,100,8,100,9, - 132,0,90,6,101,7,100,10,100,11,132,0,131,1,90,8, - 101,8,106,9,100,12,100,11,132,0,131,1,90,8,101,7, - 100,13,100,14,132,0,131,1,90,10,101,7,100,15,100,16, - 132,0,131,1,90,11,101,11,106,9,100,17,100,16,132,0, - 131,1,90,11,100,2,83,0,41,18,218,10,77,111,100,117, - 108,101,83,112,101,99,97,208,5,0,0,84,104,101,32,115, - 112,101,99,105,102,105,99,97,116,105,111,110,32,102,111,114, - 32,97,32,109,111,100,117,108,101,44,32,117,115,101,100,32, - 102,111,114,32,108,111,97,100,105,110,103,46,10,10,32,32, - 32,32,65,32,109,111,100,117,108,101,39,115,32,115,112,101, - 99,32,105,115,32,116,104,101,32,115,111,117,114,99,101,32, - 102,111,114,32,105,110,102,111,114,109,97,116,105,111,110,32, - 97,98,111,117,116,32,116,104,101,32,109,111,100,117,108,101, - 46,32,32,70,111,114,10,32,32,32,32,100,97,116,97,32, - 97,115,115,111,99,105,97,116,101,100,32,119,105,116,104,32, - 116,104,101,32,109,111,100,117,108,101,44,32,105,110,99,108, - 117,100,105,110,103,32,115,111,117,114,99,101,44,32,117,115, - 101,32,116,104,101,32,115,112,101,99,39,115,10,32,32,32, - 32,108,111,97,100,101,114,46,10,10,32,32,32,32,96,110, - 97,109,101,96,32,105,115,32,116,104,101,32,97,98,115,111, - 108,117,116,101,32,110,97,109,101,32,111,102,32,116,104,101, - 32,109,111,100,117,108,101,46,32,32,96,108,111,97,100,101, - 114,96,32,105,115,32,116,104,101,32,108,111,97,100,101,114, - 10,32,32,32,32,116,111,32,117,115,101,32,119,104,101,110, - 32,108,111,97,100,105,110,103,32,116,104,101,32,109,111,100, - 117,108,101,46,32,32,96,112,97,114,101,110,116,96,32,105, - 115,32,116,104,101,32,110,97,109,101,32,111,102,32,116,104, - 101,10,32,32,32,32,112,97,99,107,97,103,101,32,116,104, - 101,32,109,111,100,117,108,101,32,105,115,32,105,110,46,32, - 32,84,104,101,32,112,97,114,101,110,116,32,105,115,32,100, - 101,114,105,118,101,100,32,102,114,111,109,32,116,104,101,32, - 110,97,109,101,46,10,10,32,32,32,32,96,105,115,95,112, - 97,99,107,97,103,101,96,32,100,101,116,101,114,109,105,110, - 101,115,32,105,102,32,116,104,101,32,109,111,100,117,108,101, - 32,105,115,32,99,111,110,115,105,100,101,114,101,100,32,97, - 32,112,97,99,107,97,103,101,32,111,114,10,32,32,32,32, - 110,111,116,46,32,32,79,110,32,109,111,100,117,108,101,115, - 32,116,104,105,115,32,105,115,32,114,101,102,108,101,99,116, - 101,100,32,98,121,32,116,104,101,32,96,95,95,112,97,116, - 104,95,95,96,32,97,116,116,114,105,98,117,116,101,46,10, - 10,32,32,32,32,96,111,114,105,103,105,110,96,32,105,115, - 32,116,104,101,32,115,112,101,99,105,102,105,99,32,108,111, - 99,97,116,105,111,110,32,117,115,101,100,32,98,121,32,116, - 104,101,32,108,111,97,100,101,114,32,102,114,111,109,32,119, - 104,105,99,104,32,116,111,10,32,32,32,32,108,111,97,100, - 32,116,104,101,32,109,111,100,117,108,101,44,32,105,102,32, - 116,104,97,116,32,105,110,102,111,114,109,97,116,105,111,110, - 32,105,115,32,97,118,97,105,108,97,98,108,101,46,32,32, - 87,104,101,110,32,102,105,108,101,110,97,109,101,32,105,115, - 10,32,32,32,32,115,101,116,44,32,111,114,105,103,105,110, - 32,119,105,108,108,32,109,97,116,99,104,46,10,10,32,32, - 32,32,96,104,97,115,95,108,111,99,97,116,105,111,110,96, - 32,105,110,100,105,99,97,116,101,115,32,116,104,97,116,32, - 97,32,115,112,101,99,39,115,32,34,111,114,105,103,105,110, - 34,32,114,101,102,108,101,99,116,115,32,97,32,108,111,99, - 97,116,105,111,110,46,10,32,32,32,32,87,104,101,110,32, - 116,104,105,115,32,105,115,32,84,114,117,101,44,32,96,95, - 95,102,105,108,101,95,95,96,32,97,116,116,114,105,98,117, - 116,101,32,111,102,32,116,104,101,32,109,111,100,117,108,101, - 32,105,115,32,115,101,116,46,10,10,32,32,32,32,96,99, - 97,99,104,101,100,96,32,105,115,32,116,104,101,32,108,111, - 99,97,116,105,111,110,32,111,102,32,116,104,101,32,99,97, - 99,104,101,100,32,98,121,116,101,99,111,100,101,32,102,105, - 108,101,44,32,105,102,32,97,110,121,46,32,32,73,116,10, - 32,32,32,32,99,111,114,114,101,115,112,111,110,100,115,32, - 116,111,32,116,104,101,32,96,95,95,99,97,99,104,101,100, - 95,95,96,32,97,116,116,114,105,98,117,116,101,46,10,10, - 32,32,32,32,96,115,117,98,109,111,100,117,108,101,95,115, - 101,97,114,99,104,95,108,111,99,97,116,105,111,110,115,96, - 32,105,115,32,116,104,101,32,115,101,113,117,101,110,99,101, - 32,111,102,32,112,97,116,104,32,101,110,116,114,105,101,115, - 32,116,111,10,32,32,32,32,115,101,97,114,99,104,32,119, - 104,101,110,32,105,109,112,111,114,116,105,110,103,32,115,117, - 98,109,111,100,117,108,101,115,46,32,32,73,102,32,115,101, - 116,44,32,105,115,95,112,97,99,107,97,103,101,32,115,104, - 111,117,108,100,32,98,101,10,32,32,32,32,84,114,117,101, - 45,45,97,110,100,32,70,97,108,115,101,32,111,116,104,101, - 114,119,105,115,101,46,10,10,32,32,32,32,80,97,99,107, - 97,103,101,115,32,97,114,101,32,115,105,109,112,108,121,32, - 109,111,100,117,108,101,115,32,116,104,97,116,32,40,109,97, - 121,41,32,104,97,118,101,32,115,117,98,109,111,100,117,108, - 101,115,46,32,32,73,102,32,97,32,115,112,101,99,10,32, - 32,32,32,104,97,115,32,97,32,110,111,110,45,78,111,110, - 101,32,118,97,108,117,101,32,105,110,32,96,115,117,98,109, - 111,100,117,108,101,95,115,101,97,114,99,104,95,108,111,99, - 97,116,105,111,110,115,96,44,32,116,104,101,32,105,109,112, - 111,114,116,10,32,32,32,32,115,121,115,116,101,109,32,119, - 105,108,108,32,99,111,110,115,105,100,101,114,32,109,111,100, - 117,108,101,115,32,108,111,97,100,101,100,32,102,114,111,109, - 32,116,104,101,32,115,112,101,99,32,97,115,32,112,97,99, - 107,97,103,101,115,46,10,10,32,32,32,32,79,110,108,121, - 32,102,105,110,100,101,114,115,32,40,115,101,101,32,105,109, - 112,111,114,116,108,105,98,46,97,98,99,46,77,101,116,97, - 80,97,116,104,70,105,110,100,101,114,32,97,110,100,10,32, - 32,32,32,105,109,112,111,114,116,108,105,98,46,97,98,99, - 46,80,97,116,104,69,110,116,114,121,70,105,110,100,101,114, - 41,32,115,104,111,117,108,100,32,109,111,100,105,102,121,32, - 77,111,100,117,108,101,83,112,101,99,32,105,110,115,116,97, - 110,99,101,115,46,10,10,32,32,32,32,78,41,3,218,6, - 111,114,105,103,105,110,218,12,108,111,97,100,101,114,95,115, - 116,97,116,101,218,10,105,115,95,112,97,99,107,97,103,101, - 99,3,0,0,0,3,0,0,0,6,0,0,0,2,0,0, - 0,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,15,0,0,0,114,93,0,0,0, - 114,103,0,0,0,114,104,0,0,0,218,26,115,117,98,109, + 0,114,27,0,0,0,113,1,0,0,115,14,0,0,0,0, + 2,6,1,6,1,6,1,6,1,14,3,6,1,122,19,77, + 111,100,117,108,101,83,112,101,99,46,95,95,105,110,105,116, + 95,95,99,1,0,0,0,0,0,0,0,2,0,0,0,6, + 0,0,0,67,0,0,0,115,102,0,0,0,100,1,160,0, + 124,0,106,1,161,1,100,2,160,0,124,0,106,2,161,1, + 103,2,125,1,124,0,106,3,100,0,107,9,114,52,124,1, + 160,4,100,3,160,0,124,0,106,3,161,1,161,1,1,0, + 124,0,106,5,100,0,107,9,114,80,124,1,160,4,100,4, + 160,0,124,0,106,5,161,1,161,1,1,0,100,5,160,0, + 124,0,106,6,106,7,100,6,160,8,124,1,161,1,161,2, + 83,0,41,7,78,122,9,110,97,109,101,61,123,33,114,125, + 122,11,108,111,97,100,101,114,61,123,33,114,125,122,11,111, + 114,105,103,105,110,61,123,33,114,125,122,29,115,117,98,109, 111,100,117,108,101,95,115,101,97,114,99,104,95,108,111,99, - 97,116,105,111,110,115,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,26,0,0,0,114,15,0,0,0,114,93,0,0,0,114, - 103,0,0,0,114,104,0,0,0,114,105,0,0,0,114,10, - 0,0,0,114,10,0,0,0,114,11,0,0,0,114,27,0, - 0,0,113,1,0,0,115,14,0,0,0,0,2,6,1,6, - 1,6,1,6,1,14,3,6,1,122,19,77,111,100,117,108, - 101,83,112,101,99,46,95,95,105,110,105,116,95,95,99,1, - 0,0,0,0,0,0,0,2,0,0,0,6,0,0,0,67, - 0,0,0,115,102,0,0,0,100,1,160,0,124,0,106,1, - 161,1,100,2,160,0,124,0,106,2,161,1,103,2,125,1, - 124,0,106,3,100,0,107,9,114,52,124,1,160,4,100,3, - 160,0,124,0,106,3,161,1,161,1,1,0,124,0,106,5, - 100,0,107,9,114,80,124,1,160,4,100,4,160,0,124,0, - 106,5,161,1,161,1,1,0,100,5,160,0,124,0,106,6, - 106,7,100,6,160,8,124,1,161,1,161,2,83,0,41,7, - 78,122,9,110,97,109,101,61,123,33,114,125,122,11,108,111, - 97,100,101,114,61,123,33,114,125,122,11,111,114,105,103,105, - 110,61,123,33,114,125,122,29,115,117,98,109,111,100,117,108, - 101,95,115,101,97,114,99,104,95,108,111,99,97,116,105,111, - 110,115,61,123,125,122,6,123,125,40,123,125,41,122,2,44, - 32,41,9,114,38,0,0,0,114,15,0,0,0,114,93,0, - 0,0,114,103,0,0,0,218,6,97,112,112,101,110,100,114, - 106,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,26,0,0, - 0,114,47,0,0,0,114,10,0,0,0,114,10,0,0,0, - 114,11,0,0,0,114,40,0,0,0,125,1,0,0,115,16, - 0,0,0,0,1,10,1,14,1,10,1,18,1,10,1,8, - 1,10,1,122,19,77,111,100,117,108,101,83,112,101,99,46, - 95,95,114,101,112,114,95,95,99,2,0,0,0,0,0,0, - 0,3,0,0,0,8,0,0,0,67,0,0,0,115,102,0, - 0,0,124,0,106,0,125,2,121,70,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,83,0, - 4,0,116,6,107,10,114,96,1,0,1,0,1,0,100,1, - 83,0,88,0,100,0,83,0,41,2,78,70,41,7,114,106, - 0,0,0,114,15,0,0,0,114,93,0,0,0,114,103,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,90,0,0,0,41,3,114, - 26,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,135,1,0,0,115,20,0,0, - 0,0,1,6,1,2,1,12,1,12,1,12,1,10,1,12, - 1,12,1,14,1,122,17,77,111,100,117,108,101,83,112,101, - 99,46,95,95,101,113,95,95,99,1,0,0,0,0,0,0, - 0,1,0,0,0,3,0,0,0,67,0,0,0,115,58,0, - 0,0,124,0,106,0,100,0,107,8,114,52,124,0,106,1, - 100,0,107,9,114,52,124,0,106,2,114,52,116,3,100,0, - 107,8,114,38,116,4,130,1,116,3,160,5,124,0,106,1, - 161,1,124,0,95,0,124,0,106,0,83,0,41,1,78,41, - 6,114,108,0,0,0,114,103,0,0,0,114,107,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,41,1,114,26,0,0,0,114,10, - 0,0,0,114,10,0,0,0,114,11,0,0,0,114,112,0, - 0,0,147,1,0,0,115,12,0,0,0,0,2,10,1,16, - 1,8,1,4,1,14,1,122,17,77,111,100,117,108,101,83, - 112,101,99,46,99,97,99,104,101,100,99,2,0,0,0,0, - 0,0,0,2,0,0,0,2,0,0,0,67,0,0,0,115, - 10,0,0,0,124,1,124,0,95,0,100,0,83,0,41,1, - 78,41,1,114,108,0,0,0,41,2,114,26,0,0,0,114, - 112,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, - 0,0,0,114,112,0,0,0,156,1,0,0,115,2,0,0, - 0,0,2,99,1,0,0,0,0,0,0,0,1,0,0,0, - 3,0,0,0,67,0,0,0,115,36,0,0,0,124,0,106, - 0,100,1,107,8,114,26,124,0,106,1,160,2,100,2,161, - 1,100,3,25,0,83,0,124,0,106,1,83,0,100,1,83, - 0,41,4,122,32,84,104,101,32,110,97,109,101,32,111,102, - 32,116,104,101,32,109,111,100,117,108,101,39,115,32,112,97, - 114,101,110,116,46,78,218,1,46,114,19,0,0,0,41,3, - 114,106,0,0,0,114,15,0,0,0,218,10,114,112,97,114, - 116,105,116,105,111,110,41,1,114,26,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,160,1,0,0,115,6,0,0,0,0,3,10, - 1,16,2,122,17,77,111,100,117,108,101,83,112,101,99,46, - 112,97,114,101,110,116,99,1,0,0,0,0,0,0,0,1, - 0,0,0,1,0,0,0,67,0,0,0,115,6,0,0,0, - 124,0,106,0,83,0,41,1,78,41,1,114,107,0,0,0, - 41,1,114,26,0,0,0,114,10,0,0,0,114,10,0,0, - 0,114,11,0,0,0,114,113,0,0,0,168,1,0,0,115, - 2,0,0,0,0,2,122,23,77,111,100,117,108,101,83,112, - 101,99,46,104,97,115,95,108,111,99,97,116,105,111,110,99, - 2,0,0,0,0,0,0,0,2,0,0,0,2,0,0,0, - 67,0,0,0,115,14,0,0,0,116,0,124,1,131,1,124, - 0,95,1,100,0,83,0,41,1,78,41,2,218,4,98,111, - 111,108,114,107,0,0,0,41,2,114,26,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,113,0,0,0,172,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,27,0,0,0,114, - 40,0,0,0,114,114,0,0,0,218,8,112,114,111,112,101, - 114,116,121,114,112,0,0,0,218,6,115,101,116,116,101,114, - 114,119,0,0,0,114,113,0,0,0,114,10,0,0,0,114, - 10,0,0,0,114,10,0,0,0,114,11,0,0,0,114,102, - 0,0,0,76,1,0,0,115,18,0,0,0,12,37,4,1, - 14,11,8,10,8,12,12,9,14,4,12,8,12,4,114,102, - 0,0,0,41,2,114,103,0,0,0,114,105,0,0,0,99, - 2,0,0,0,2,0,0,0,6,0,0,0,8,0,0,0, - 67,0,0,0,115,154,0,0,0,116,0,124,1,100,1,131, - 2,114,74,116,1,100,2,107,8,114,22,116,2,130,1,116, - 1,106,3,125,4,124,3,100,2,107,8,114,48,124,4,124, - 0,124,1,100,3,141,2,83,0,124,3,114,56,103,0,110, - 2,100,2,125,5,124,4,124,0,124,1,124,5,100,4,141, - 3,83,0,124,3,100,2,107,8,114,138,116,0,124,1,100, - 5,131,2,114,134,121,14,124,1,160,4,124,0,161,1,125, - 3,87,0,113,138,4,0,116,5,107,10,114,130,1,0,1, - 0,1,0,100,2,125,3,89,0,113,138,88,0,110,4,100, - 6,125,3,116,6,124,0,124,1,124,2,124,3,100,7,141, - 4,83,0,41,8,122,53,82,101,116,117,114,110,32,97,32, - 109,111,100,117,108,101,32,115,112,101,99,32,98,97,115,101, - 100,32,111,110,32,118,97,114,105,111,117,115,32,108,111,97, - 100,101,114,32,109,101,116,104,111,100,115,46,90,12,103,101, - 116,95,102,105,108,101,110,97,109,101,78,41,1,114,93,0, - 0,0,41,2,114,93,0,0,0,114,106,0,0,0,114,105, - 0,0,0,70,41,2,114,103,0,0,0,114,105,0,0,0, - 41,7,114,4,0,0,0,114,115,0,0,0,114,116,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,105,0,0,0,114, - 70,0,0,0,114,102,0,0,0,41,6,114,15,0,0,0, - 114,93,0,0,0,114,103,0,0,0,114,105,0,0,0,114, - 124,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,78,0,0,0, - 177,1,0,0,115,34,0,0,0,0,2,10,1,8,1,4, - 1,6,2,8,1,12,1,12,1,6,1,8,2,8,1,10, - 1,2,1,14,1,14,1,12,3,4,2,114,78,0,0,0, - 99,3,0,0,0,0,0,0,0,8,0,0,0,8,0,0, - 0,67,0,0,0,115,56,1,0,0,121,10,124,0,106,0, - 125,3,87,0,110,20,4,0,116,1,107,10,114,30,1,0, - 1,0,1,0,89,0,110,14,88,0,124,3,100,0,107,9, - 114,44,124,3,83,0,124,0,106,2,125,4,124,1,100,0, - 107,8,114,90,121,10,124,0,106,3,125,1,87,0,110,20, - 4,0,116,1,107,10,114,88,1,0,1,0,1,0,89,0, - 110,2,88,0,121,10,124,0,106,4,125,5,87,0,110,24, - 4,0,116,1,107,10,114,124,1,0,1,0,1,0,100,0, - 125,5,89,0,110,2,88,0,124,2,100,0,107,8,114,184, - 124,5,100,0,107,8,114,180,121,10,124,1,106,5,125,2, - 87,0,113,184,4,0,116,1,107,10,114,176,1,0,1,0, - 1,0,100,0,125,2,89,0,113,184,88,0,110,4,124,5, - 125,2,121,10,124,0,106,6,125,6,87,0,110,24,4,0, - 116,1,107,10,114,218,1,0,1,0,1,0,100,0,125,6, - 89,0,110,2,88,0,121,14,116,7,124,0,106,8,131,1, - 125,7,87,0,110,26,4,0,116,1,107,10,144,1,114,4, - 1,0,1,0,1,0,100,0,125,7,89,0,110,2,88,0, - 116,9,124,4,124,1,124,2,100,1,141,3,125,3,124,5, - 100,0,107,8,144,1,114,34,100,2,110,2,100,3,124,3, - 95,10,124,6,124,3,95,11,124,7,124,3,95,12,124,3, - 83,0,41,4,78,41,1,114,103,0,0,0,70,84,41,13, - 114,89,0,0,0,114,90,0,0,0,114,1,0,0,0,114, - 85,0,0,0,114,92,0,0,0,90,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,102, - 0,0,0,114,107,0,0,0,114,112,0,0,0,114,106,0, - 0,0,41,8,114,83,0,0,0,114,93,0,0,0,114,103, - 0,0,0,114,82,0,0,0,114,15,0,0,0,90,8,108, - 111,99,97,116,105,111,110,114,112,0,0,0,114,106,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,203,1,0,0,115,72,0,0,0,0,2,2,1, - 10,1,14,1,6,2,8,1,4,2,6,1,8,1,2,1, - 10,1,14,2,6,1,2,1,10,1,14,1,10,1,8,1, - 8,1,2,1,10,1,14,1,12,2,4,1,2,1,10,1, - 14,1,10,1,2,1,14,1,16,1,10,2,14,1,20,1, - 6,1,6,1,114,128,0,0,0,70,41,1,218,8,111,118, - 101,114,114,105,100,101,99,2,0,0,0,1,0,0,0,5, - 0,0,0,8,0,0,0,67,0,0,0,115,226,1,0,0, - 124,2,115,20,116,0,124,1,100,1,100,0,131,3,100,0, - 107,8,114,54,121,12,124,0,106,1,124,1,95,2,87,0, - 110,20,4,0,116,3,107,10,114,52,1,0,1,0,1,0, - 89,0,110,2,88,0,124,2,115,74,116,0,124,1,100,2, - 100,0,131,3,100,0,107,8,114,178,124,0,106,4,125,3, - 124,3,100,0,107,8,114,146,124,0,106,5,100,0,107,9, - 114,146,116,6,100,0,107,8,114,110,116,7,130,1,116,6, - 106,8,125,4,124,4,160,9,124,4,161,1,125,3,124,0, - 106,5,124,3,95,10,124,3,124,0,95,4,100,0,124,1, - 95,11,121,10,124,3,124,1,95,12,87,0,110,20,4,0, - 116,3,107,10,114,176,1,0,1,0,1,0,89,0,110,2, - 88,0,124,2,115,198,116,0,124,1,100,3,100,0,131,3, - 100,0,107,8,114,232,121,12,124,0,106,13,124,1,95,14, - 87,0,110,20,4,0,116,3,107,10,114,230,1,0,1,0, - 1,0,89,0,110,2,88,0,121,10,124,0,124,1,95,15, - 87,0,110,22,4,0,116,3,107,10,144,1,114,8,1,0, - 1,0,1,0,89,0,110,2,88,0,124,2,144,1,115,34, - 116,0,124,1,100,4,100,0,131,3,100,0,107,8,144,1, - 114,82,124,0,106,5,100,0,107,9,144,1,114,82,121,12, - 124,0,106,5,124,1,95,16,87,0,110,22,4,0,116,3, - 107,10,144,1,114,80,1,0,1,0,1,0,89,0,110,2, - 88,0,124,0,106,17,144,1,114,222,124,2,144,1,115,114, - 116,0,124,1,100,5,100,0,131,3,100,0,107,8,144,1, - 114,150,121,12,124,0,106,18,124,1,95,11,87,0,110,22, - 4,0,116,3,107,10,144,1,114,148,1,0,1,0,1,0, - 89,0,110,2,88,0,124,2,144,1,115,174,116,0,124,1, - 100,6,100,0,131,3,100,0,107,8,144,1,114,222,124,0, - 106,19,100,0,107,9,144,1,114,222,121,12,124,0,106,19, - 124,1,95,20,87,0,110,22,4,0,116,3,107,10,144,1, - 114,220,1,0,1,0,1,0,89,0,110,2,88,0,124,1, - 83,0,41,7,78,114,1,0,0,0,114,85,0,0,0,218, - 11,95,95,112,97,99,107,97,103,101,95,95,114,127,0,0, - 0,114,92,0,0,0,114,125,0,0,0,41,21,114,6,0, - 0,0,114,15,0,0,0,114,1,0,0,0,114,90,0,0, - 0,114,93,0,0,0,114,106,0,0,0,114,115,0,0,0, - 114,116,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,92,0,0,0,114,85,0,0, - 0,114,119,0,0,0,114,130,0,0,0,114,89,0,0,0, - 114,127,0,0,0,114,113,0,0,0,114,103,0,0,0,114, - 112,0,0,0,114,125,0,0,0,41,5,114,82,0,0,0, - 114,83,0,0,0,114,129,0,0,0,114,93,0,0,0,114, - 131,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,248,1,0,0,115,96,0,0,0, - 0,4,20,1,2,1,12,1,14,1,6,2,20,1,6,1, - 8,2,10,1,8,1,4,1,6,2,10,1,8,1,6,11, - 6,1,2,1,10,1,14,1,6,2,20,1,2,1,12,1, - 14,1,6,2,2,1,10,1,16,1,6,2,24,1,12,1, - 2,1,12,1,16,1,6,2,8,1,24,1,2,1,12,1, - 16,1,6,2,24,1,12,1,2,1,12,1,16,1,6,1, - 114,133,0,0,0,99,1,0,0,0,0,0,0,0,2,0, - 0,0,3,0,0,0,67,0,0,0,115,82,0,0,0,100, - 1,125,1,116,0,124,0,106,1,100,2,131,2,114,30,124, - 0,106,1,160,2,124,0,161,1,125,1,110,20,116,0,124, - 0,106,1,100,3,131,2,114,50,116,3,100,4,131,1,130, - 1,124,1,100,1,107,8,114,68,116,4,124,0,106,5,131, - 1,125,1,116,6,124,0,124,1,131,2,1,0,124,1,83, - 0,41,5,122,43,67,114,101,97,116,101,32,97,32,109,111, - 100,117,108,101,32,98,97,115,101,100,32,111,110,32,116,104, - 101,32,112,114,111,118,105,100,101,100,32,115,112,101,99,46, - 78,218,13,99,114,101,97,116,101,95,109,111,100,117,108,101, - 218,11,101,120,101,99,95,109,111,100,117,108,101,122,66,108, - 111,97,100,101,114,115,32,116,104,97,116,32,100,101,102,105, - 110,101,32,101,120,101,99,95,109,111,100,117,108,101,40,41, - 32,109,117,115,116,32,97,108,115,111,32,100,101,102,105,110, - 101,32,99,114,101,97,116,101,95,109,111,100,117,108,101,40, - 41,41,7,114,4,0,0,0,114,93,0,0,0,114,134,0, - 0,0,114,70,0,0,0,114,16,0,0,0,114,15,0,0, - 0,114,133,0,0,0,41,2,114,82,0,0,0,114,83,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,64,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,136, - 0,0,0,99,1,0,0,0,0,0,0,0,2,0,0,0, - 4,0,0,0,67,0,0,0,115,106,0,0,0,124,0,106, - 0,100,1,107,8,114,14,100,2,110,4,124,0,106,0,125, - 1,124,0,106,1,100,1,107,8,114,66,124,0,106,2,100, - 1,107,8,114,50,100,3,160,3,124,1,161,1,83,0,100, - 4,160,3,124,1,124,0,106,2,161,2,83,0,110,36,124, - 0,106,4,114,86,100,5,160,3,124,1,124,0,106,1,161, - 2,83,0,100,6,160,3,124,0,106,0,124,0,106,1,161, - 2,83,0,100,1,83,0,41,7,122,38,82,101,116,117,114, - 110,32,116,104,101,32,114,101,112,114,32,116,111,32,117,115, - 101,32,102,111,114,32,116,104,101,32,109,111,100,117,108,101, - 46,78,114,87,0,0,0,122,13,60,109,111,100,117,108,101, - 32,123,33,114,125,62,122,20,60,109,111,100,117,108,101,32, - 123,33,114,125,32,40,123,33,114,125,41,62,122,23,60,109, - 111,100,117,108,101,32,123,33,114,125,32,102,114,111,109,32, - 123,33,114,125,62,122,18,60,109,111,100,117,108,101,32,123, - 33,114,125,32,40,123,125,41,62,41,5,114,15,0,0,0, - 114,103,0,0,0,114,93,0,0,0,114,38,0,0,0,114, - 113,0,0,0,41,2,114,82,0,0,0,114,15,0,0,0, - 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,114, - 91,0,0,0,81,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,91,0, - 0,0,99,2,0,0,0,0,0,0,0,4,0,0,0,9, - 0,0,0,67,0,0,0,115,178,0,0,0,124,0,106,0, - 125,2,116,1,124,2,131,1,143,148,1,0,116,2,106,3, - 160,4,124,2,161,1,124,1,107,9,114,54,100,1,160,5, - 124,2,161,1,125,3,116,6,124,3,124,2,100,2,141,2, - 130,1,124,0,106,7,100,3,107,8,114,106,124,0,106,8, - 100,3,107,8,114,88,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,124,1,83,0,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,100,3,81,0, - 82,0,88,0,116,2,106,3,124,2,25,0,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,41,1,114,15,0,0,0,78, - 122,14,109,105,115,115,105,110,103,32,108,111,97,100,101,114, - 84,41,1,114,129,0,0,0,114,135,0,0,0,41,13,114, - 15,0,0,0,114,42,0,0,0,114,14,0,0,0,114,79, - 0,0,0,114,30,0,0,0,114,38,0,0,0,114,70,0, - 0,0,114,93,0,0,0,114,106,0,0,0,114,133,0,0, - 0,114,4,0,0,0,218,11,108,111,97,100,95,109,111,100, - 117,108,101,114,135,0,0,0,41,4,114,82,0,0,0,114, - 83,0,0,0,114,15,0,0,0,218,3,109,115,103,114,10, - 0,0,0,114,10,0,0,0,114,11,0,0,0,114,80,0, - 0,0,98,2,0,0,115,30,0,0,0,0,2,6,1,10, - 1,16,1,10,1,12,1,10,1,10,1,14,2,14,1,4, - 1,14,1,12,4,14,2,22,1,114,80,0,0,0,99,1, - 0,0,0,0,0,0,0,2,0,0,0,8,0,0,0,67, - 0,0,0,115,206,0,0,0,124,0,106,0,160,1,124,0, - 106,2,161,1,1,0,116,3,106,4,124,0,106,2,25,0, - 125,1,116,5,124,1,100,1,100,0,131,3,100,0,107,8, - 114,76,121,12,124,0,106,0,124,1,95,6,87,0,110,20, - 4,0,116,7,107,10,114,74,1,0,1,0,1,0,89,0, - 110,2,88,0,116,5,124,1,100,2,100,0,131,3,100,0, - 107,8,114,154,121,40,124,1,106,8,124,1,95,9,116,10, - 124,1,100,3,131,2,115,130,124,0,106,2,160,11,100,4, - 161,1,100,5,25,0,124,1,95,9,87,0,110,20,4,0, - 116,7,107,10,114,152,1,0,1,0,1,0,89,0,110,2, - 88,0,116,5,124,1,100,6,100,0,131,3,100,0,107,8, - 114,202,121,10,124,0,124,1,95,12,87,0,110,20,4,0, - 116,7,107,10,114,200,1,0,1,0,1,0,89,0,110,2, - 88,0,124,1,83,0,41,7,78,114,85,0,0,0,114,130, - 0,0,0,114,127,0,0,0,114,117,0,0,0,114,19,0, - 0,0,114,89,0,0,0,41,13,114,93,0,0,0,114,137, - 0,0,0,114,15,0,0,0,114,14,0,0,0,114,79,0, - 0,0,114,6,0,0,0,114,85,0,0,0,114,90,0,0, - 0,114,1,0,0,0,114,130,0,0,0,114,4,0,0,0, - 114,118,0,0,0,114,89,0,0,0,41,2,114,82,0,0, - 0,114,83,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, - 122,2,0,0,115,40,0,0,0,0,4,14,2,12,1,16, - 1,2,1,12,1,14,1,6,1,16,1,2,4,8,1,10, - 1,22,1,14,1,6,1,16,1,2,1,10,1,14,1,6, - 1,114,139,0,0,0,99,1,0,0,0,0,0,0,0,2, - 0,0,0,9,0,0,0,67,0,0,0,115,118,0,0,0, - 124,0,106,0,100,0,107,9,114,30,116,1,124,0,106,0, - 100,1,131,2,115,30,116,2,124,0,131,1,83,0,116,3, - 124,0,131,1,125,1,116,4,124,1,131,1,143,54,1,0, - 124,0,106,0,100,0,107,8,114,84,124,0,106,5,100,0, - 107,8,114,96,116,6,100,2,124,0,106,7,100,3,141,2, - 130,1,110,12,124,0,106,0,160,8,124,1,161,1,1,0, - 87,0,100,0,81,0,82,0,88,0,116,9,106,10,124,0, - 106,7,25,0,83,0,41,4,78,114,135,0,0,0,122,14, - 109,105,115,115,105,110,103,32,108,111,97,100,101,114,41,1, - 114,15,0,0,0,41,11,114,93,0,0,0,114,4,0,0, - 0,114,139,0,0,0,114,136,0,0,0,114,96,0,0,0, - 114,106,0,0,0,114,70,0,0,0,114,15,0,0,0,114, - 135,0,0,0,114,14,0,0,0,114,79,0,0,0,41,2, - 114,82,0,0,0,114,83,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,151,2,0,0,115,20,0, - 0,0,0,2,10,2,12,1,8,2,8,1,10,1,10,1, - 10,1,16,3,22,5,114,140,0,0,0,99,1,0,0,0, - 0,0,0,0,1,0,0,0,9,0,0,0,67,0,0,0, - 115,30,0,0,0,116,0,124,0,106,1,131,1,143,10,1, - 0,116,2,124,0,131,1,83,0,81,0,82,0,88,0,100, - 1,83,0,41,2,122,191,82,101,116,117,114,110,32,97,32, - 110,101,119,32,109,111,100,117,108,101,32,111,98,106,101,99, - 116,44,32,108,111,97,100,101,100,32,98,121,32,116,104,101, - 32,115,112,101,99,39,115,32,108,111,97,100,101,114,46,10, - 10,32,32,32,32,84,104,101,32,109,111,100,117,108,101,32, - 105,115,32,110,111,116,32,97,100,100,101,100,32,116,111,32, - 105,116,115,32,112,97,114,101,110,116,46,10,10,32,32,32, - 32,73,102,32,97,32,109,111,100,117,108,101,32,105,115,32, - 97,108,114,101,97,100,121,32,105,110,32,115,121,115,46,109, - 111,100,117,108,101,115,44,32,116,104,97,116,32,101,120,105, - 115,116,105,110,103,32,109,111,100,117,108,101,32,103,101,116, - 115,10,32,32,32,32,99,108,111,98,98,101,114,101,100,46, - 10,10,32,32,32,32,78,41,3,114,42,0,0,0,114,15, - 0,0,0,114,140,0,0,0,41,1,114,82,0,0,0,114, - 10,0,0,0,114,10,0,0,0,114,11,0,0,0,114,81, - 0,0,0,174,2,0,0,115,4,0,0,0,0,9,12,1, - 114,81,0,0,0,99,0,0,0,0,0,0,0,0,0,0, - 0,0,4,0,0,0,64,0,0,0,115,136,0,0,0,101, - 0,90,1,100,0,90,2,100,1,90,3,101,4,100,2,100, - 3,132,0,131,1,90,5,101,6,100,19,100,5,100,6,132, - 1,131,1,90,7,101,6,100,20,100,7,100,8,132,1,131, - 1,90,8,101,6,100,9,100,10,132,0,131,1,90,9,101, - 6,100,11,100,12,132,0,131,1,90,10,101,6,101,11,100, - 13,100,14,132,0,131,1,131,1,90,12,101,6,101,11,100, - 15,100,16,132,0,131,1,131,1,90,13,101,6,101,11,100, - 17,100,18,132,0,131,1,131,1,90,14,101,6,101,15,131, - 1,90,16,100,4,83,0,41,21,218,15,66,117,105,108,116, - 105,110,73,109,112,111,114,116,101,114,122,144,77,101,116,97, - 32,112,97,116,104,32,105,109,112,111,114,116,32,102,111,114, - 32,98,117,105,108,116,45,105,110,32,109,111,100,117,108,101, - 115,46,10,10,32,32,32,32,65,108,108,32,109,101,116,104, - 111,100,115,32,97,114,101,32,101,105,116,104,101,114,32,99, - 108,97,115,115,32,111,114,32,115,116,97,116,105,99,32,109, - 101,116,104,111,100,115,32,116,111,32,97,118,111,105,100,32, - 116,104,101,32,110,101,101,100,32,116,111,10,32,32,32,32, - 105,110,115,116,97,110,116,105,97,116,101,32,116,104,101,32, - 99,108,97,115,115,46,10,10,32,32,32,32,99,1,0,0, + 97,116,105,111,110,115,61,123,125,122,6,123,125,40,123,125, + 41,122,2,44,32,41,9,114,38,0,0,0,114,15,0,0, + 0,114,93,0,0,0,114,103,0,0,0,218,6,97,112,112, + 101,110,100,114,106,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,26,0,0,0,114,47,0,0,0,114,10,0,0,0,114, + 10,0,0,0,114,11,0,0,0,114,40,0,0,0,125,1, + 0,0,115,16,0,0,0,0,1,10,1,14,1,10,1,18, + 1,10,1,8,1,10,1,122,19,77,111,100,117,108,101,83, + 112,101,99,46,95,95,114,101,112,114,95,95,99,2,0,0, + 0,0,0,0,0,3,0,0,0,8,0,0,0,67,0,0, + 0,115,102,0,0,0,124,0,106,0,125,2,121,70,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,83,0,4,0,116,6,107,10,114,96,1,0,1,0, + 1,0,100,1,83,0,88,0,100,0,83,0,41,2,78,70, + 41,7,114,106,0,0,0,114,15,0,0,0,114,93,0,0, + 0,114,103,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,90,0,0, + 0,41,3,114,26,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,135,1,0,0, + 115,20,0,0,0,0,1,6,1,2,1,12,1,12,1,12, + 1,10,1,12,1,12,1,14,1,122,17,77,111,100,117,108, + 101,83,112,101,99,46,95,95,101,113,95,95,99,1,0,0, 0,0,0,0,0,1,0,0,0,3,0,0,0,67,0,0, - 0,115,12,0,0,0,100,1,160,0,124,0,106,1,161,1, - 83,0,41,2,122,115,82,101,116,117,114,110,32,114,101,112, - 114,32,102,111,114,32,116,104,101,32,109,111,100,117,108,101, - 46,10,10,32,32,32,32,32,32,32,32,84,104,101,32,109, - 101,116,104,111,100,32,105,115,32,100,101,112,114,101,99,97, - 116,101,100,46,32,32,84,104,101,32,105,109,112,111,114,116, - 32,109,97,99,104,105,110,101,114,121,32,100,111,101,115,32, - 116,104,101,32,106,111,98,32,105,116,115,101,108,102,46,10, - 10,32,32,32,32,32,32,32,32,122,24,60,109,111,100,117, - 108,101,32,123,33,114,125,32,40,98,117,105,108,116,45,105, - 110,41,62,41,2,114,38,0,0,0,114,1,0,0,0,41, - 1,114,83,0,0,0,114,10,0,0,0,114,10,0,0,0, - 114,11,0,0,0,114,86,0,0,0,198,2,0,0,115,2, - 0,0,0,0,7,122,27,66,117,105,108,116,105,110,73,109, - 112,111,114,116,101,114,46,109,111,100,117,108,101,95,114,101, - 112,114,78,99,4,0,0,0,0,0,0,0,4,0,0,0, - 5,0,0,0,67,0,0,0,115,44,0,0,0,124,2,100, - 0,107,9,114,12,100,0,83,0,116,0,160,1,124,1,161, - 1,114,36,116,2,124,1,124,0,100,1,100,2,141,3,83, - 0,100,0,83,0,100,0,83,0,41,3,78,122,8,98,117, - 105,108,116,45,105,110,41,1,114,103,0,0,0,41,3,114, - 49,0,0,0,90,10,105,115,95,98,117,105,108,116,105,110, - 114,78,0,0,0,41,4,218,3,99,108,115,114,71,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,207,2,0,0,115,10,0, - 0,0,0,2,8,1,4,1,10,1,14,2,122,25,66,117, - 105,108,116,105,110,73,109,112,111,114,116,101,114,46,102,105, - 110,100,95,115,112,101,99,99,3,0,0,0,0,0,0,0, - 4,0,0,0,4,0,0,0,67,0,0,0,115,30,0,0, - 0,124,0,160,0,124,1,124,2,161,2,125,3,124,3,100, - 1,107,9,114,26,124,3,106,1,83,0,100,1,83,0,41, - 2,122,175,70,105,110,100,32,116,104,101,32,98,117,105,108, - 116,45,105,110,32,109,111,100,117,108,101,46,10,10,32,32, - 32,32,32,32,32,32,73,102,32,39,112,97,116,104,39,32, - 105,115,32,101,118,101,114,32,115,112,101,99,105,102,105,101, - 100,32,116,104,101,110,32,116,104,101,32,115,101,97,114,99, - 104,32,105,115,32,99,111,110,115,105,100,101,114,101,100,32, - 97,32,102,97,105,108,117,114,101,46,10,10,32,32,32,32, - 32,32,32,32,84,104,105,115,32,109,101,116,104,111,100,32, - 105,115,32,100,101,112,114,101,99,97,116,101,100,46,32,32, - 85,115,101,32,102,105,110,100,95,115,112,101,99,40,41,32, - 105,110,115,116,101,97,100,46,10,10,32,32,32,32,32,32, - 32,32,78,41,2,114,145,0,0,0,114,93,0,0,0,41, - 4,114,142,0,0,0,114,71,0,0,0,114,143,0,0,0, - 114,82,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,216,2,0,0,115,4,0,0,0,0,9,12,1,122,27, - 66,117,105,108,116,105,110,73,109,112,111,114,116,101,114,46, - 102,105,110,100,95,109,111,100,117,108,101,99,2,0,0,0, - 0,0,0,0,2,0,0,0,4,0,0,0,67,0,0,0, - 115,46,0,0,0,124,1,106,0,116,1,106,2,107,7,114, - 34,116,3,100,1,160,4,124,1,106,0,161,1,124,1,106, - 0,100,2,141,2,130,1,116,5,116,6,106,7,124,1,131, - 2,83,0,41,3,122,24,67,114,101,97,116,101,32,97,32, - 98,117,105,108,116,45,105,110,32,109,111,100,117,108,101,122, - 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,41,1, - 114,15,0,0,0,41,8,114,15,0,0,0,114,14,0,0, - 0,114,69,0,0,0,114,70,0,0,0,114,38,0,0,0, - 114,59,0,0,0,114,49,0,0,0,90,14,99,114,101,97, - 116,101,95,98,117,105,108,116,105,110,41,2,114,26,0,0, - 0,114,82,0,0,0,114,10,0,0,0,114,10,0,0,0, - 114,11,0,0,0,114,134,0,0,0,228,2,0,0,115,8, - 0,0,0,0,3,12,1,12,1,10,1,122,29,66,117,105, - 108,116,105,110,73,109,112,111,114,116,101,114,46,99,114,101, - 97,116,101,95,109,111,100,117,108,101,99,2,0,0,0,0, - 0,0,0,2,0,0,0,3,0,0,0,67,0,0,0,115, - 16,0,0,0,116,0,116,1,106,2,124,1,131,2,1,0, - 100,1,83,0,41,2,122,22,69,120,101,99,32,97,32,98, - 117,105,108,116,45,105,110,32,109,111,100,117,108,101,78,41, - 3,114,59,0,0,0,114,49,0,0,0,90,12,101,120,101, - 99,95,98,117,105,108,116,105,110,41,2,114,26,0,0,0, - 114,83,0,0,0,114,10,0,0,0,114,10,0,0,0,114, - 11,0,0,0,114,135,0,0,0,236,2,0,0,115,2,0, - 0,0,0,3,122,27,66,117,105,108,116,105,110,73,109,112, - 111,114,116,101,114,46,101,120,101,99,95,109,111,100,117,108, - 101,99,2,0,0,0,0,0,0,0,2,0,0,0,1,0, - 0,0,67,0,0,0,115,4,0,0,0,100,1,83,0,41, - 2,122,57,82,101,116,117,114,110,32,78,111,110,101,32,97, - 115,32,98,117,105,108,116,45,105,110,32,109,111,100,117,108, - 101,115,32,100,111,32,110,111,116,32,104,97,118,101,32,99, - 111,100,101,32,111,98,106,101,99,116,115,46,78,114,10,0, - 0,0,41,2,114,142,0,0,0,114,71,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,241,2,0,0,115,2,0,0,0, - 0,4,122,24,66,117,105,108,116,105,110,73,109,112,111,114, - 116,101,114,46,103,101,116,95,99,111,100,101,99,2,0,0, - 0,0,0,0,0,2,0,0,0,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,41,2,114,142, - 0,0,0,114,71,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,247,2,0,0,115,2,0,0,0,0,4,122,26, - 66,117,105,108,116,105,110,73,109,112,111,114,116,101,114,46, - 103,101,116,95,115,111,117,114,99,101,99,2,0,0,0,0, - 0,0,0,2,0,0,0,1,0,0,0,67,0,0,0,115, - 4,0,0,0,100,1,83,0,41,2,122,52,82,101,116,117, - 114,110,32,70,97,108,115,101,32,97,115,32,98,117,105,108, - 116,45,105,110,32,109,111,100,117,108,101,115,32,97,114,101, - 32,110,101,118,101,114,32,112,97,99,107,97,103,101,115,46, - 70,114,10,0,0,0,41,2,114,142,0,0,0,114,71,0, + 0,115,58,0,0,0,124,0,106,0,100,0,107,8,114,52, + 124,0,106,1,100,0,107,9,114,52,124,0,106,2,114,52, + 116,3,100,0,107,8,114,38,116,4,130,1,116,3,160,5, + 124,0,106,1,161,1,124,0,95,0,124,0,106,0,83,0, + 41,1,78,41,6,114,108,0,0,0,114,103,0,0,0,114, + 107,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,41,1,114,26,0, 0,0,114,10,0,0,0,114,10,0,0,0,114,11,0,0, - 0,114,105,0,0,0,253,2,0,0,115,2,0,0,0,0, - 4,122,26,66,117,105,108,116,105,110,73,109,112,111,114,116, - 101,114,46,105,115,95,112,97,99,107,97,103,101,41,2,78, - 78,41,1,78,41,17,114,1,0,0,0,114,0,0,0,0, - 114,2,0,0,0,114,3,0,0,0,218,12,115,116,97,116, - 105,99,109,101,116,104,111,100,114,86,0,0,0,218,11,99, - 108,97,115,115,109,101,116,104,111,100,114,145,0,0,0,114, - 146,0,0,0,114,134,0,0,0,114,135,0,0,0,114,74, - 0,0,0,114,147,0,0,0,114,148,0,0,0,114,105,0, - 0,0,114,84,0,0,0,114,137,0,0,0,114,10,0,0, + 0,114,112,0,0,0,147,1,0,0,115,12,0,0,0,0, + 2,10,1,16,1,8,1,4,1,14,1,122,17,77,111,100, + 117,108,101,83,112,101,99,46,99,97,99,104,101,100,99,2, + 0,0,0,0,0,0,0,2,0,0,0,2,0,0,0,67, + 0,0,0,115,10,0,0,0,124,1,124,0,95,0,100,0, + 83,0,41,1,78,41,1,114,108,0,0,0,41,2,114,26, + 0,0,0,114,112,0,0,0,114,10,0,0,0,114,10,0, + 0,0,114,11,0,0,0,114,112,0,0,0,156,1,0,0, + 115,2,0,0,0,0,2,99,1,0,0,0,0,0,0,0, + 1,0,0,0,3,0,0,0,67,0,0,0,115,36,0,0, + 0,124,0,106,0,100,1,107,8,114,26,124,0,106,1,160, + 2,100,2,161,1,100,3,25,0,83,0,124,0,106,1,83, + 0,100,1,83,0,41,4,122,32,84,104,101,32,110,97,109, + 101,32,111,102,32,116,104,101,32,109,111,100,117,108,101,39, + 115,32,112,97,114,101,110,116,46,78,218,1,46,114,19,0, + 0,0,41,3,114,106,0,0,0,114,15,0,0,0,218,10, + 114,112,97,114,116,105,116,105,111,110,41,1,114,26,0,0, 0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, - 114,141,0,0,0,189,2,0,0,115,28,0,0,0,12,9, - 12,9,2,1,12,8,2,1,12,11,12,8,12,5,2,1, - 14,5,2,1,14,5,2,1,14,5,114,141,0,0,0,99, - 0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0, - 64,0,0,0,115,140,0,0,0,101,0,90,1,100,0,90, - 2,100,1,90,3,101,4,100,2,100,3,132,0,131,1,90, - 5,101,6,100,21,100,5,100,6,132,1,131,1,90,7,101, - 6,100,22,100,7,100,8,132,1,131,1,90,8,101,6,100, - 9,100,10,132,0,131,1,90,9,101,4,100,11,100,12,132, - 0,131,1,90,10,101,6,100,13,100,14,132,0,131,1,90, - 11,101,6,101,12,100,15,100,16,132,0,131,1,131,1,90, - 13,101,6,101,12,100,17,100,18,132,0,131,1,131,1,90, - 14,101,6,101,12,100,19,100,20,132,0,131,1,131,1,90, - 15,100,4,83,0,41,23,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,99,1,0,0,0,0,0,0,0, - 1,0,0,0,3,0,0,0,67,0,0,0,115,12,0,0, - 0,100,1,160,0,124,0,106,1,161,1,83,0,41,2,122, - 115,82,101,116,117,114,110,32,114,101,112,114,32,102,111,114, - 32,116,104,101,32,109,111,100,117,108,101,46,10,10,32,32, - 32,32,32,32,32,32,84,104,101,32,109,101,116,104,111,100, - 32,105,115,32,100,101,112,114,101,99,97,116,101,100,46,32, - 32,84,104,101,32,105,109,112,111,114,116,32,109,97,99,104, - 105,110,101,114,121,32,100,111,101,115,32,116,104,101,32,106, - 111,98,32,105,116,115,101,108,102,46,10,10,32,32,32,32, - 32,32,32,32,122,22,60,109,111,100,117,108,101,32,123,33, - 114,125,32,40,102,114,111,122,101,110,41,62,41,2,114,38, - 0,0,0,114,1,0,0,0,41,1,218,1,109,114,10,0, - 0,0,114,10,0,0,0,114,11,0,0,0,114,86,0,0, - 0,15,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, + 218,6,112,97,114,101,110,116,160,1,0,0,115,6,0,0, + 0,0,3,10,1,16,2,122,17,77,111,100,117,108,101,83, + 112,101,99,46,112,97,114,101,110,116,99,1,0,0,0,0, + 0,0,0,1,0,0,0,1,0,0,0,67,0,0,0,115, + 6,0,0,0,124,0,106,0,83,0,41,1,78,41,1,114, + 107,0,0,0,41,1,114,26,0,0,0,114,10,0,0,0, + 114,10,0,0,0,114,11,0,0,0,114,113,0,0,0,168, + 1,0,0,115,2,0,0,0,0,2,122,23,77,111,100,117, + 108,101,83,112,101,99,46,104,97,115,95,108,111,99,97,116, + 105,111,110,99,2,0,0,0,0,0,0,0,2,0,0,0, + 2,0,0,0,67,0,0,0,115,14,0,0,0,116,0,124, + 1,131,1,124,0,95,1,100,0,83,0,41,1,78,41,2, + 218,4,98,111,111,108,114,107,0,0,0,41,2,114,26,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,113,0,0,0,172,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,27, + 0,0,0,114,40,0,0,0,114,114,0,0,0,218,8,112, + 114,111,112,101,114,116,121,114,112,0,0,0,218,6,115,101, + 116,116,101,114,114,119,0,0,0,114,113,0,0,0,114,10, + 0,0,0,114,10,0,0,0,114,10,0,0,0,114,11,0, + 0,0,114,102,0,0,0,76,1,0,0,115,20,0,0,0, + 8,35,4,2,4,1,14,11,8,10,8,12,12,9,14,4, + 12,8,12,4,114,102,0,0,0,41,2,114,103,0,0,0, + 114,105,0,0,0,99,2,0,0,0,2,0,0,0,6,0, + 0,0,8,0,0,0,67,0,0,0,115,154,0,0,0,116, + 0,124,1,100,1,131,2,114,74,116,1,100,2,107,8,114, + 22,116,2,130,1,116,1,106,3,125,4,124,3,100,2,107, + 8,114,48,124,4,124,0,124,1,100,3,141,2,83,0,124, + 3,114,56,103,0,110,2,100,2,125,5,124,4,124,0,124, + 1,124,5,100,4,141,3,83,0,124,3,100,2,107,8,114, + 138,116,0,124,1,100,5,131,2,114,134,121,14,124,1,160, + 4,124,0,161,1,125,3,87,0,113,138,4,0,116,5,107, + 10,114,130,1,0,1,0,1,0,100,2,125,3,89,0,113, + 138,88,0,110,4,100,6,125,3,116,6,124,0,124,1,124, + 2,124,3,100,7,141,4,83,0,41,8,122,53,82,101,116, + 117,114,110,32,97,32,109,111,100,117,108,101,32,115,112,101, + 99,32,98,97,115,101,100,32,111,110,32,118,97,114,105,111, + 117,115,32,108,111,97,100,101,114,32,109,101,116,104,111,100, + 115,46,90,12,103,101,116,95,102,105,108,101,110,97,109,101, + 78,41,1,114,93,0,0,0,41,2,114,93,0,0,0,114, + 106,0,0,0,114,105,0,0,0,70,41,2,114,103,0,0, + 0,114,105,0,0,0,41,7,114,4,0,0,0,114,115,0, + 0,0,114,116,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,105,0,0,0,114,70,0,0,0,114,102,0,0,0,41, + 6,114,15,0,0,0,114,93,0,0,0,114,103,0,0,0, + 114,105,0,0,0,114,124,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,78,0,0,0,177,1,0,0,115,34,0,0,0,0, + 2,10,1,8,1,4,1,6,2,8,1,12,1,12,1,6, + 1,8,2,8,1,10,1,2,1,14,1,14,1,12,3,4, + 2,114,78,0,0,0,99,3,0,0,0,0,0,0,0,8, + 0,0,0,8,0,0,0,67,0,0,0,115,56,1,0,0, + 121,10,124,0,106,0,125,3,87,0,110,20,4,0,116,1, + 107,10,114,30,1,0,1,0,1,0,89,0,110,14,88,0, + 124,3,100,0,107,9,114,44,124,3,83,0,124,0,106,2, + 125,4,124,1,100,0,107,8,114,90,121,10,124,0,106,3, + 125,1,87,0,110,20,4,0,116,1,107,10,114,88,1,0, + 1,0,1,0,89,0,110,2,88,0,121,10,124,0,106,4, + 125,5,87,0,110,24,4,0,116,1,107,10,114,124,1,0, + 1,0,1,0,100,0,125,5,89,0,110,2,88,0,124,2, + 100,0,107,8,114,184,124,5,100,0,107,8,114,180,121,10, + 124,1,106,5,125,2,87,0,113,184,4,0,116,1,107,10, + 114,176,1,0,1,0,1,0,100,0,125,2,89,0,113,184, + 88,0,110,4,124,5,125,2,121,10,124,0,106,6,125,6, + 87,0,110,24,4,0,116,1,107,10,114,218,1,0,1,0, + 1,0,100,0,125,6,89,0,110,2,88,0,121,14,116,7, + 124,0,106,8,131,1,125,7,87,0,110,26,4,0,116,1, + 107,10,144,1,114,4,1,0,1,0,1,0,100,0,125,7, + 89,0,110,2,88,0,116,9,124,4,124,1,124,2,100,1, + 141,3,125,3,124,5,100,0,107,8,144,1,114,34,100,2, + 110,2,100,3,124,3,95,10,124,6,124,3,95,11,124,7, + 124,3,95,12,124,3,83,0,41,4,78,41,1,114,103,0, + 0,0,70,84,41,13,114,89,0,0,0,114,90,0,0,0, + 114,1,0,0,0,114,85,0,0,0,114,92,0,0,0,90, + 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,102,0,0,0,114,107,0,0,0,114,112, + 0,0,0,114,106,0,0,0,41,8,114,83,0,0,0,114, + 93,0,0,0,114,103,0,0,0,114,82,0,0,0,114,15, + 0,0,0,90,8,108,111,99,97,116,105,111,110,114,112,0, + 0,0,114,106,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,203,1,0,0,115,72,0, + 0,0,0,2,2,1,10,1,14,1,6,2,8,1,4,2, + 6,1,8,1,2,1,10,1,14,2,6,1,2,1,10,1, + 14,1,10,1,8,1,8,1,2,1,10,1,14,1,12,2, + 4,1,2,1,10,1,14,1,10,1,2,1,14,1,16,1, + 10,2,14,1,20,1,6,1,6,1,114,128,0,0,0,70, + 41,1,218,8,111,118,101,114,114,105,100,101,99,2,0,0, + 0,1,0,0,0,5,0,0,0,8,0,0,0,67,0,0, + 0,115,226,1,0,0,124,2,115,20,116,0,124,1,100,1, + 100,0,131,3,100,0,107,8,114,54,121,12,124,0,106,1, + 124,1,95,2,87,0,110,20,4,0,116,3,107,10,114,52, + 1,0,1,0,1,0,89,0,110,2,88,0,124,2,115,74, + 116,0,124,1,100,2,100,0,131,3,100,0,107,8,114,178, + 124,0,106,4,125,3,124,3,100,0,107,8,114,146,124,0, + 106,5,100,0,107,9,114,146,116,6,100,0,107,8,114,110, + 116,7,130,1,116,6,106,8,125,4,124,4,160,9,124,4, + 161,1,125,3,124,0,106,5,124,3,95,10,124,3,124,0, + 95,4,100,0,124,1,95,11,121,10,124,3,124,1,95,12, + 87,0,110,20,4,0,116,3,107,10,114,176,1,0,1,0, + 1,0,89,0,110,2,88,0,124,2,115,198,116,0,124,1, + 100,3,100,0,131,3,100,0,107,8,114,232,121,12,124,0, + 106,13,124,1,95,14,87,0,110,20,4,0,116,3,107,10, + 114,230,1,0,1,0,1,0,89,0,110,2,88,0,121,10, + 124,0,124,1,95,15,87,0,110,22,4,0,116,3,107,10, + 144,1,114,8,1,0,1,0,1,0,89,0,110,2,88,0, + 124,2,144,1,115,34,116,0,124,1,100,4,100,0,131,3, + 100,0,107,8,144,1,114,82,124,0,106,5,100,0,107,9, + 144,1,114,82,121,12,124,0,106,5,124,1,95,16,87,0, + 110,22,4,0,116,3,107,10,144,1,114,80,1,0,1,0, + 1,0,89,0,110,2,88,0,124,0,106,17,144,1,114,222, + 124,2,144,1,115,114,116,0,124,1,100,5,100,0,131,3, + 100,0,107,8,144,1,114,150,121,12,124,0,106,18,124,1, + 95,11,87,0,110,22,4,0,116,3,107,10,144,1,114,148, + 1,0,1,0,1,0,89,0,110,2,88,0,124,2,144,1, + 115,174,116,0,124,1,100,6,100,0,131,3,100,0,107,8, + 144,1,114,222,124,0,106,19,100,0,107,9,144,1,114,222, + 121,12,124,0,106,19,124,1,95,20,87,0,110,22,4,0, + 116,3,107,10,144,1,114,220,1,0,1,0,1,0,89,0, + 110,2,88,0,124,1,83,0,41,7,78,114,1,0,0,0, + 114,85,0,0,0,218,11,95,95,112,97,99,107,97,103,101, + 95,95,114,127,0,0,0,114,92,0,0,0,114,125,0,0, + 0,41,21,114,6,0,0,0,114,15,0,0,0,114,1,0, + 0,0,114,90,0,0,0,114,93,0,0,0,114,106,0,0, + 0,114,115,0,0,0,114,116,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,92,0, + 0,0,114,85,0,0,0,114,119,0,0,0,114,130,0,0, + 0,114,89,0,0,0,114,127,0,0,0,114,113,0,0,0, + 114,103,0,0,0,114,112,0,0,0,114,125,0,0,0,41, + 5,114,82,0,0,0,114,83,0,0,0,114,129,0,0,0, + 114,93,0,0,0,114,131,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,248,1,0, + 0,115,96,0,0,0,0,4,20,1,2,1,12,1,14,1, + 6,2,20,1,6,1,8,2,10,1,8,1,4,1,6,2, + 10,1,8,1,6,11,6,1,2,1,10,1,14,1,6,2, + 20,1,2,1,12,1,14,1,6,2,2,1,10,1,16,1, + 6,2,24,1,12,1,2,1,12,1,16,1,6,2,8,1, + 24,1,2,1,12,1,16,1,6,2,24,1,12,1,2,1, + 12,1,16,1,6,1,114,133,0,0,0,99,1,0,0,0, + 0,0,0,0,2,0,0,0,3,0,0,0,67,0,0,0, + 115,82,0,0,0,100,1,125,1,116,0,124,0,106,1,100, + 2,131,2,114,30,124,0,106,1,160,2,124,0,161,1,125, + 1,110,20,116,0,124,0,106,1,100,3,131,2,114,50,116, + 3,100,4,131,1,130,1,124,1,100,1,107,8,114,68,116, + 4,124,0,106,5,131,1,125,1,116,6,124,0,124,1,131, + 2,1,0,124,1,83,0,41,5,122,43,67,114,101,97,116, + 101,32,97,32,109,111,100,117,108,101,32,98,97,115,101,100, + 32,111,110,32,116,104,101,32,112,114,111,118,105,100,101,100, + 32,115,112,101,99,46,78,218,13,99,114,101,97,116,101,95, + 109,111,100,117,108,101,218,11,101,120,101,99,95,109,111,100, + 117,108,101,122,66,108,111,97,100,101,114,115,32,116,104,97, + 116,32,100,101,102,105,110,101,32,101,120,101,99,95,109,111, + 100,117,108,101,40,41,32,109,117,115,116,32,97,108,115,111, + 32,100,101,102,105,110,101,32,99,114,101,97,116,101,95,109, + 111,100,117,108,101,40,41,41,7,114,4,0,0,0,114,93, + 0,0,0,114,134,0,0,0,114,70,0,0,0,114,16,0, + 0,0,114,15,0,0,0,114,133,0,0,0,41,2,114,82, + 0,0,0,114,83,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,64,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,136,0,0,0,99,1,0,0,0,0,0, + 0,0,2,0,0,0,4,0,0,0,67,0,0,0,115,106, + 0,0,0,124,0,106,0,100,1,107,8,114,14,100,2,110, + 4,124,0,106,0,125,1,124,0,106,1,100,1,107,8,114, + 66,124,0,106,2,100,1,107,8,114,50,100,3,160,3,124, + 1,161,1,83,0,100,4,160,3,124,1,124,0,106,2,161, + 2,83,0,110,36,124,0,106,4,114,86,100,5,160,3,124, + 1,124,0,106,1,161,2,83,0,100,6,160,3,124,0,106, + 0,124,0,106,1,161,2,83,0,100,1,83,0,41,7,122, + 38,82,101,116,117,114,110,32,116,104,101,32,114,101,112,114, + 32,116,111,32,117,115,101,32,102,111,114,32,116,104,101,32, + 109,111,100,117,108,101,46,78,114,87,0,0,0,122,13,60, + 109,111,100,117,108,101,32,123,33,114,125,62,122,20,60,109, + 111,100,117,108,101,32,123,33,114,125,32,40,123,33,114,125, + 41,62,122,23,60,109,111,100,117,108,101,32,123,33,114,125, + 32,102,114,111,109,32,123,33,114,125,62,122,18,60,109,111, + 100,117,108,101,32,123,33,114,125,32,40,123,125,41,62,41, + 5,114,15,0,0,0,114,103,0,0,0,114,93,0,0,0, + 114,38,0,0,0,114,113,0,0,0,41,2,114,82,0,0, + 0,114,15,0,0,0,114,10,0,0,0,114,10,0,0,0, + 114,11,0,0,0,114,91,0,0,0,81,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,91,0,0,0,99,2,0,0,0,0,0,0, + 0,4,0,0,0,9,0,0,0,67,0,0,0,115,178,0, + 0,0,124,0,106,0,125,2,116,1,124,2,131,1,143,148, + 1,0,116,2,106,3,160,4,124,2,161,1,124,1,107,9, + 114,54,100,1,160,5,124,2,161,1,125,3,116,6,124,3, + 124,2,100,2,141,2,130,1,124,0,106,7,100,3,107,8, + 114,106,124,0,106,8,100,3,107,8,114,88,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,124,1,83,0,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,100,3,81,0,82,0,88,0,116,2,106,3,124,2, + 25,0,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,41,1, + 114,15,0,0,0,78,122,14,109,105,115,115,105,110,103,32, + 108,111,97,100,101,114,84,41,1,114,129,0,0,0,114,135, + 0,0,0,41,13,114,15,0,0,0,114,42,0,0,0,114, + 14,0,0,0,114,79,0,0,0,114,30,0,0,0,114,38, + 0,0,0,114,70,0,0,0,114,93,0,0,0,114,106,0, + 0,0,114,133,0,0,0,114,4,0,0,0,218,11,108,111, + 97,100,95,109,111,100,117,108,101,114,135,0,0,0,41,4, + 114,82,0,0,0,114,83,0,0,0,114,15,0,0,0,218, + 3,109,115,103,114,10,0,0,0,114,10,0,0,0,114,11, + 0,0,0,114,80,0,0,0,98,2,0,0,115,30,0,0, + 0,0,2,6,1,10,1,16,1,10,1,12,1,10,1,10, + 1,14,2,14,1,4,1,14,1,12,4,14,2,22,1,114, + 80,0,0,0,99,1,0,0,0,0,0,0,0,2,0,0, + 0,8,0,0,0,67,0,0,0,115,206,0,0,0,124,0, + 106,0,160,1,124,0,106,2,161,1,1,0,116,3,106,4, + 124,0,106,2,25,0,125,1,116,5,124,1,100,1,100,0, + 131,3,100,0,107,8,114,76,121,12,124,0,106,0,124,1, + 95,6,87,0,110,20,4,0,116,7,107,10,114,74,1,0, + 1,0,1,0,89,0,110,2,88,0,116,5,124,1,100,2, + 100,0,131,3,100,0,107,8,114,154,121,40,124,1,106,8, + 124,1,95,9,116,10,124,1,100,3,131,2,115,130,124,0, + 106,2,160,11,100,4,161,1,100,5,25,0,124,1,95,9, + 87,0,110,20,4,0,116,7,107,10,114,152,1,0,1,0, + 1,0,89,0,110,2,88,0,116,5,124,1,100,6,100,0, + 131,3,100,0,107,8,114,202,121,10,124,0,124,1,95,12, + 87,0,110,20,4,0,116,7,107,10,114,200,1,0,1,0, + 1,0,89,0,110,2,88,0,124,1,83,0,41,7,78,114, + 85,0,0,0,114,130,0,0,0,114,127,0,0,0,114,117, + 0,0,0,114,19,0,0,0,114,89,0,0,0,41,13,114, + 93,0,0,0,114,137,0,0,0,114,15,0,0,0,114,14, + 0,0,0,114,79,0,0,0,114,6,0,0,0,114,85,0, + 0,0,114,90,0,0,0,114,1,0,0,0,114,130,0,0, + 0,114,4,0,0,0,114,118,0,0,0,114,89,0,0,0, + 41,2,114,82,0,0,0,114,83,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,122,2,0,0,115,40,0,0,0,0, + 4,14,2,12,1,16,1,2,1,12,1,14,1,6,1,16, + 1,2,4,8,1,10,1,22,1,14,1,6,1,16,1,2, + 1,10,1,14,1,6,1,114,139,0,0,0,99,1,0,0, + 0,0,0,0,0,2,0,0,0,9,0,0,0,67,0,0, + 0,115,118,0,0,0,124,0,106,0,100,0,107,9,114,30, + 116,1,124,0,106,0,100,1,131,2,115,30,116,2,124,0, + 131,1,83,0,116,3,124,0,131,1,125,1,116,4,124,1, + 131,1,143,54,1,0,124,0,106,0,100,0,107,8,114,84, + 124,0,106,5,100,0,107,8,114,96,116,6,100,2,124,0, + 106,7,100,3,141,2,130,1,110,12,124,0,106,0,160,8, + 124,1,161,1,1,0,87,0,100,0,81,0,82,0,88,0, + 116,9,106,10,124,0,106,7,25,0,83,0,41,4,78,114, + 135,0,0,0,122,14,109,105,115,115,105,110,103,32,108,111, + 97,100,101,114,41,1,114,15,0,0,0,41,11,114,93,0, + 0,0,114,4,0,0,0,114,139,0,0,0,114,136,0,0, + 0,114,96,0,0,0,114,106,0,0,0,114,70,0,0,0, + 114,15,0,0,0,114,135,0,0,0,114,14,0,0,0,114, + 79,0,0,0,41,2,114,82,0,0,0,114,83,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,151, + 2,0,0,115,20,0,0,0,0,2,10,2,12,1,8,2, + 8,1,10,1,10,1,10,1,16,3,22,5,114,140,0,0, + 0,99,1,0,0,0,0,0,0,0,1,0,0,0,9,0, + 0,0,67,0,0,0,115,30,0,0,0,116,0,124,0,106, + 1,131,1,143,10,1,0,116,2,124,0,131,1,83,0,81, + 0,82,0,88,0,100,1,83,0,41,2,122,191,82,101,116, + 117,114,110,32,97,32,110,101,119,32,109,111,100,117,108,101, + 32,111,98,106,101,99,116,44,32,108,111,97,100,101,100,32, + 98,121,32,116,104,101,32,115,112,101,99,39,115,32,108,111, + 97,100,101,114,46,10,10,32,32,32,32,84,104,101,32,109, + 111,100,117,108,101,32,105,115,32,110,111,116,32,97,100,100, + 101,100,32,116,111,32,105,116,115,32,112,97,114,101,110,116, + 46,10,10,32,32,32,32,73,102,32,97,32,109,111,100,117, + 108,101,32,105,115,32,97,108,114,101,97,100,121,32,105,110, + 32,115,121,115,46,109,111,100,117,108,101,115,44,32,116,104, + 97,116,32,101,120,105,115,116,105,110,103,32,109,111,100,117, + 108,101,32,103,101,116,115,10,32,32,32,32,99,108,111,98, + 98,101,114,101,100,46,10,10,32,32,32,32,78,41,3,114, + 42,0,0,0,114,15,0,0,0,114,140,0,0,0,41,1, + 114,82,0,0,0,114,10,0,0,0,114,10,0,0,0,114, + 11,0,0,0,114,81,0,0,0,174,2,0,0,115,4,0, + 0,0,0,9,12,1,114,81,0,0,0,99,0,0,0,0, + 0,0,0,0,0,0,0,0,4,0,0,0,64,0,0,0, + 115,136,0,0,0,101,0,90,1,100,0,90,2,100,1,90, + 3,101,4,100,2,100,3,132,0,131,1,90,5,101,6,100, + 19,100,5,100,6,132,1,131,1,90,7,101,6,100,20,100, + 7,100,8,132,1,131,1,90,8,101,6,100,9,100,10,132, + 0,131,1,90,9,101,6,100,11,100,12,132,0,131,1,90, + 10,101,6,101,11,100,13,100,14,132,0,131,1,131,1,90, + 12,101,6,101,11,100,15,100,16,132,0,131,1,131,1,90, + 13,101,6,101,11,100,17,100,18,132,0,131,1,131,1,90, + 14,101,6,101,15,131,1,90,16,100,4,83,0,41,21,218, + 15,66,117,105,108,116,105,110,73,109,112,111,114,116,101,114, + 122,144,77,101,116,97,32,112,97,116,104,32,105,109,112,111, + 114,116,32,102,111,114,32,98,117,105,108,116,45,105,110,32, + 109,111,100,117,108,101,115,46,10,10,32,32,32,32,65,108, + 108,32,109,101,116,104,111,100,115,32,97,114,101,32,101,105, + 116,104,101,114,32,99,108,97,115,115,32,111,114,32,115,116, + 97,116,105,99,32,109,101,116,104,111,100,115,32,116,111,32, + 97,118,111,105,100,32,116,104,101,32,110,101,101,100,32,116, + 111,10,32,32,32,32,105,110,115,116,97,110,116,105,97,116, + 101,32,116,104,101,32,99,108,97,115,115,46,10,10,32,32, + 32,32,99,1,0,0,0,0,0,0,0,1,0,0,0,3, + 0,0,0,67,0,0,0,115,12,0,0,0,100,1,160,0, + 124,0,106,1,161,1,83,0,41,2,122,115,82,101,116,117, + 114,110,32,114,101,112,114,32,102,111,114,32,116,104,101,32, + 109,111,100,117,108,101,46,10,10,32,32,32,32,32,32,32, + 32,84,104,101,32,109,101,116,104,111,100,32,105,115,32,100, + 101,112,114,101,99,97,116,101,100,46,32,32,84,104,101,32, + 105,109,112,111,114,116,32,109,97,99,104,105,110,101,114,121, + 32,100,111,101,115,32,116,104,101,32,106,111,98,32,105,116, + 115,101,108,102,46,10,10,32,32,32,32,32,32,32,32,122, + 24,60,109,111,100,117,108,101,32,123,33,114,125,32,40,98, + 117,105,108,116,45,105,110,41,62,41,2,114,38,0,0,0, + 114,1,0,0,0,41,1,114,83,0,0,0,114,10,0,0, + 0,114,10,0,0,0,114,11,0,0,0,114,86,0,0,0, + 198,2,0,0,115,2,0,0,0,0,7,122,27,66,117,105, + 108,116,105,110,73,109,112,111,114,116,101,114,46,109,111,100, 117,108,101,95,114,101,112,114,78,99,4,0,0,0,0,0, - 0,0,4,0,0,0,5,0,0,0,67,0,0,0,115,32, - 0,0,0,116,0,160,1,124,1,161,1,114,24,116,2,124, - 1,124,0,100,1,100,2,141,3,83,0,100,0,83,0,100, - 0,83,0,41,3,78,90,6,102,114,111,122,101,110,41,1, - 114,103,0,0,0,41,3,114,49,0,0,0,114,75,0,0, - 0,114,78,0,0,0,41,4,114,142,0,0,0,114,71,0, - 0,0,114,143,0,0,0,114,144,0,0,0,114,10,0,0, - 0,114,10,0,0,0,114,11,0,0,0,114,145,0,0,0, - 24,3,0,0,115,6,0,0,0,0,2,10,1,14,2,122, - 24,70,114,111,122,101,110,73,109,112,111,114,116,101,114,46, - 102,105,110,100,95,115,112,101,99,99,3,0,0,0,0,0, - 0,0,3,0,0,0,3,0,0,0,67,0,0,0,115,18, - 0,0,0,116,0,160,1,124,1,161,1,114,14,124,0,83, - 0,100,1,83,0,41,2,122,93,70,105,110,100,32,97,32, - 102,114,111,122,101,110,32,109,111,100,117,108,101,46,10,10, - 32,32,32,32,32,32,32,32,84,104,105,115,32,109,101,116, - 104,111,100,32,105,115,32,100,101,112,114,101,99,97,116,101, - 100,46,32,32,85,115,101,32,102,105,110,100,95,115,112,101, - 99,40,41,32,105,110,115,116,101,97,100,46,10,10,32,32, - 32,32,32,32,32,32,78,41,2,114,49,0,0,0,114,75, - 0,0,0,41,3,114,142,0,0,0,114,71,0,0,0,114, - 143,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, - 0,0,0,114,146,0,0,0,31,3,0,0,115,2,0,0, - 0,0,7,122,26,70,114,111,122,101,110,73,109,112,111,114, - 116,101,114,46,102,105,110,100,95,109,111,100,117,108,101,99, - 2,0,0,0,0,0,0,0,2,0,0,0,1,0,0,0, - 67,0,0,0,115,4,0,0,0,100,1,83,0,41,2,122, - 42,85,115,101,32,100,101,102,97,117,108,116,32,115,101,109, - 97,110,116,105,99,115,32,102,111,114,32,109,111,100,117,108, - 101,32,99,114,101,97,116,105,111,110,46,78,114,10,0,0, - 0,41,2,114,142,0,0,0,114,82,0,0,0,114,10,0, - 0,0,114,10,0,0,0,114,11,0,0,0,114,134,0,0, - 0,40,3,0,0,115,0,0,0,0,122,28,70,114,111,122, - 101,110,73,109,112,111,114,116,101,114,46,99,114,101,97,116, - 101,95,109,111,100,117,108,101,99,1,0,0,0,0,0,0, - 0,3,0,0,0,4,0,0,0,67,0,0,0,115,64,0, - 0,0,124,0,106,0,106,1,125,1,116,2,160,3,124,1, - 161,1,115,36,116,4,100,1,160,5,124,1,161,1,124,1, - 100,2,141,2,130,1,116,6,116,2,106,7,124,1,131,2, - 125,2,116,8,124,2,124,0,106,9,131,2,1,0,100,0, - 83,0,41,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,41,1,114,15,0,0,0,41,10,114,89,0,0,0, - 114,15,0,0,0,114,49,0,0,0,114,75,0,0,0,114, - 70,0,0,0,114,38,0,0,0,114,59,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,83, - 0,0,0,114,15,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,135,0, - 0,0,44,3,0,0,115,12,0,0,0,0,2,8,1,10, - 1,10,1,8,1,12,1,122,26,70,114,111,122,101,110,73, - 109,112,111,114,116,101,114,46,101,120,101,99,95,109,111,100, - 117,108,101,99,2,0,0,0,0,0,0,0,2,0,0,0, - 3,0,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, + 0,0,4,0,0,0,5,0,0,0,67,0,0,0,115,44, + 0,0,0,124,2,100,0,107,9,114,12,100,0,83,0,116, + 0,160,1,124,1,161,1,114,36,116,2,124,1,124,0,100, + 1,100,2,141,3,83,0,100,0,83,0,100,0,83,0,41, + 3,78,122,8,98,117,105,108,116,45,105,110,41,1,114,103, + 0,0,0,41,3,114,49,0,0,0,90,10,105,115,95,98, + 117,105,108,116,105,110,114,78,0,0,0,41,4,218,3,99, + 108,115,114,71,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,207, + 2,0,0,115,10,0,0,0,0,2,8,1,4,1,10,1, + 14,2,122,25,66,117,105,108,116,105,110,73,109,112,111,114, + 116,101,114,46,102,105,110,100,95,115,112,101,99,99,3,0, + 0,0,0,0,0,0,4,0,0,0,4,0,0,0,67,0, + 0,0,115,30,0,0,0,124,0,160,0,124,1,124,2,161, + 2,125,3,124,3,100,1,107,9,114,26,124,3,106,1,83, + 0,100,1,83,0,41,2,122,175,70,105,110,100,32,116,104, + 101,32,98,117,105,108,116,45,105,110,32,109,111,100,117,108, + 101,46,10,10,32,32,32,32,32,32,32,32,73,102,32,39, + 112,97,116,104,39,32,105,115,32,101,118,101,114,32,115,112, + 101,99,105,102,105,101,100,32,116,104,101,110,32,116,104,101, + 32,115,101,97,114,99,104,32,105,115,32,99,111,110,115,105, + 100,101,114,101,100,32,97,32,102,97,105,108,117,114,101,46, 10,10,32,32,32,32,32,32,32,32,84,104,105,115,32,109, 101,116,104,111,100,32,105,115,32,100,101,112,114,101,99,97, - 116,101,100,46,32,32,85,115,101,32,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,84,0,0, - 0,41,2,114,142,0,0,0,114,71,0,0,0,114,10,0, - 0,0,114,10,0,0,0,114,11,0,0,0,114,137,0,0, - 0,53,3,0,0,115,2,0,0,0,0,7,122,26,70,114, - 111,122,101,110,73,109,112,111,114,116,101,114,46,108,111,97, - 100,95,109,111,100,117,108,101,99,2,0,0,0,0,0,0, - 0,2,0,0,0,3,0,0,0,67,0,0,0,115,10,0, - 0,0,116,0,160,1,124,1,161,1,83,0,41,1,122,45, - 82,101,116,117,114,110,32,116,104,101,32,99,111,100,101,32, - 111,98,106,101,99,116,32,102,111,114,32,116,104,101,32,102, - 114,111,122,101,110,32,109,111,100,117,108,101,46,41,2,114, - 49,0,0,0,114,153,0,0,0,41,2,114,142,0,0,0, - 114,71,0,0,0,114,10,0,0,0,114,10,0,0,0,114, - 11,0,0,0,114,147,0,0,0,62,3,0,0,115,2,0, - 0,0,0,4,122,23,70,114,111,122,101,110,73,109,112,111, - 114,116,101,114,46,103,101,116,95,99,111,100,101,99,2,0, - 0,0,0,0,0,0,2,0,0,0,1,0,0,0,67,0, - 0,0,115,4,0,0,0,100,1,83,0,41,2,122,54,82, - 101,116,117,114,110,32,78,111,110,101,32,97,115,32,102,114, - 111,122,101,110,32,109,111,100,117,108,101,115,32,100,111,32, - 110,111,116,32,104,97,118,101,32,115,111,117,114,99,101,32, - 99,111,100,101,46,78,114,10,0,0,0,41,2,114,142,0, + 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,145,0,0,0, + 114,93,0,0,0,41,4,114,142,0,0,0,114,71,0,0, + 0,114,143,0,0,0,114,82,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,216,2,0,0,115,4,0,0,0, + 0,9,12,1,122,27,66,117,105,108,116,105,110,73,109,112, + 111,114,116,101,114,46,102,105,110,100,95,109,111,100,117,108, + 101,99,2,0,0,0,0,0,0,0,2,0,0,0,4,0, + 0,0,67,0,0,0,115,46,0,0,0,124,1,106,0,116, + 1,106,2,107,7,114,34,116,3,100,1,160,4,124,1,106, + 0,161,1,124,1,106,0,100,2,141,2,130,1,116,5,116, + 6,106,7,124,1,131,2,83,0,41,3,122,24,67,114,101, + 97,116,101,32,97,32,98,117,105,108,116,45,105,110,32,109, + 111,100,117,108,101,122,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,41,1,114,15,0,0,0,41,8,114,15,0, + 0,0,114,14,0,0,0,114,69,0,0,0,114,70,0,0, + 0,114,38,0,0,0,114,59,0,0,0,114,49,0,0,0, + 90,14,99,114,101,97,116,101,95,98,117,105,108,116,105,110, + 41,2,114,26,0,0,0,114,82,0,0,0,114,10,0,0, + 0,114,10,0,0,0,114,11,0,0,0,114,134,0,0,0, + 228,2,0,0,115,8,0,0,0,0,3,12,1,12,1,10, + 1,122,29,66,117,105,108,116,105,110,73,109,112,111,114,116, + 101,114,46,99,114,101,97,116,101,95,109,111,100,117,108,101, + 99,2,0,0,0,0,0,0,0,2,0,0,0,3,0,0, + 0,67,0,0,0,115,16,0,0,0,116,0,116,1,106,2, + 124,1,131,2,1,0,100,1,83,0,41,2,122,22,69,120, + 101,99,32,97,32,98,117,105,108,116,45,105,110,32,109,111, + 100,117,108,101,78,41,3,114,59,0,0,0,114,49,0,0, + 0,90,12,101,120,101,99,95,98,117,105,108,116,105,110,41, + 2,114,26,0,0,0,114,83,0,0,0,114,10,0,0,0, + 114,10,0,0,0,114,11,0,0,0,114,135,0,0,0,236, + 2,0,0,115,2,0,0,0,0,3,122,27,66,117,105,108, + 116,105,110,73,109,112,111,114,116,101,114,46,101,120,101,99, + 95,109,111,100,117,108,101,99,2,0,0,0,0,0,0,0, + 2,0,0,0,1,0,0,0,67,0,0,0,115,4,0,0, + 0,100,1,83,0,41,2,122,57,82,101,116,117,114,110,32, + 78,111,110,101,32,97,115,32,98,117,105,108,116,45,105,110, + 32,109,111,100,117,108,101,115,32,100,111,32,110,111,116,32, + 104,97,118,101,32,99,111,100,101,32,111,98,106,101,99,116, + 115,46,78,114,10,0,0,0,41,2,114,142,0,0,0,114, + 71,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,241,2,0, + 0,115,2,0,0,0,0,4,122,24,66,117,105,108,116,105, + 110,73,109,112,111,114,116,101,114,46,103,101,116,95,99,111, + 100,101,99,2,0,0,0,0,0,0,0,2,0,0,0,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,41,2,114,142,0,0,0,114,71,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,247,2,0,0,115,2,0, + 0,0,0,4,122,26,66,117,105,108,116,105,110,73,109,112, + 111,114,116,101,114,46,103,101,116,95,115,111,117,114,99,101, + 99,2,0,0,0,0,0,0,0,2,0,0,0,1,0,0, + 0,67,0,0,0,115,4,0,0,0,100,1,83,0,41,2, + 122,52,82,101,116,117,114,110,32,70,97,108,115,101,32,97, + 115,32,98,117,105,108,116,45,105,110,32,109,111,100,117,108, + 101,115,32,97,114,101,32,110,101,118,101,114,32,112,97,99, + 107,97,103,101,115,46,70,114,10,0,0,0,41,2,114,142, + 0,0,0,114,71,0,0,0,114,10,0,0,0,114,10,0, + 0,0,114,11,0,0,0,114,105,0,0,0,253,2,0,0, + 115,2,0,0,0,0,4,122,26,66,117,105,108,116,105,110, + 73,109,112,111,114,116,101,114,46,105,115,95,112,97,99,107, + 97,103,101,41,2,78,78,41,1,78,41,17,114,1,0,0, + 0,114,0,0,0,0,114,2,0,0,0,114,3,0,0,0, + 218,12,115,116,97,116,105,99,109,101,116,104,111,100,114,86, + 0,0,0,218,11,99,108,97,115,115,109,101,116,104,111,100, + 114,145,0,0,0,114,146,0,0,0,114,134,0,0,0,114, + 135,0,0,0,114,74,0,0,0,114,147,0,0,0,114,148, + 0,0,0,114,105,0,0,0,114,84,0,0,0,114,137,0, + 0,0,114,10,0,0,0,114,10,0,0,0,114,10,0,0, + 0,114,11,0,0,0,114,141,0,0,0,189,2,0,0,115, + 30,0,0,0,8,7,4,2,12,9,2,1,12,8,2,1, + 12,11,12,8,12,5,2,1,14,5,2,1,14,5,2,1, + 14,5,114,141,0,0,0,99,0,0,0,0,0,0,0,0, + 0,0,0,0,4,0,0,0,64,0,0,0,115,140,0,0, + 0,101,0,90,1,100,0,90,2,100,1,90,3,101,4,100, + 2,100,3,132,0,131,1,90,5,101,6,100,21,100,5,100, + 6,132,1,131,1,90,7,101,6,100,22,100,7,100,8,132, + 1,131,1,90,8,101,6,100,9,100,10,132,0,131,1,90, + 9,101,4,100,11,100,12,132,0,131,1,90,10,101,6,100, + 13,100,14,132,0,131,1,90,11,101,6,101,12,100,15,100, + 16,132,0,131,1,131,1,90,13,101,6,101,12,100,17,100, + 18,132,0,131,1,131,1,90,14,101,6,101,12,100,19,100, + 20,132,0,131,1,131,1,90,15,100,4,83,0,41,23,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,99, + 1,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0, + 67,0,0,0,115,12,0,0,0,100,1,160,0,124,0,106, + 1,161,1,83,0,41,2,122,115,82,101,116,117,114,110,32, + 114,101,112,114,32,102,111,114,32,116,104,101,32,109,111,100, + 117,108,101,46,10,10,32,32,32,32,32,32,32,32,84,104, + 101,32,109,101,116,104,111,100,32,105,115,32,100,101,112,114, + 101,99,97,116,101,100,46,32,32,84,104,101,32,105,109,112, + 111,114,116,32,109,97,99,104,105,110,101,114,121,32,100,111, + 101,115,32,116,104,101,32,106,111,98,32,105,116,115,101,108, + 102,46,10,10,32,32,32,32,32,32,32,32,122,22,60,109, + 111,100,117,108,101,32,123,33,114,125,32,40,102,114,111,122, + 101,110,41,62,41,2,114,38,0,0,0,114,1,0,0,0, + 41,1,218,1,109,114,10,0,0,0,114,10,0,0,0,114, + 11,0,0,0,114,86,0,0,0,15,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,4,0,0,0,5,0, + 0,0,67,0,0,0,115,32,0,0,0,116,0,160,1,124, + 1,161,1,114,24,116,2,124,1,124,0,100,1,100,2,141, + 3,83,0,100,0,83,0,100,0,83,0,41,3,78,90,6, + 102,114,111,122,101,110,41,1,114,103,0,0,0,41,3,114, + 49,0,0,0,114,75,0,0,0,114,78,0,0,0,41,4, + 114,142,0,0,0,114,71,0,0,0,114,143,0,0,0,114, + 144,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, + 0,0,0,114,145,0,0,0,24,3,0,0,115,6,0,0, + 0,0,2,10,1,14,2,122,24,70,114,111,122,101,110,73, + 109,112,111,114,116,101,114,46,102,105,110,100,95,115,112,101, + 99,99,3,0,0,0,0,0,0,0,3,0,0,0,3,0, + 0,0,67,0,0,0,115,18,0,0,0,116,0,160,1,124, + 1,161,1,114,14,124,0,83,0,100,1,83,0,41,2,122, + 93,70,105,110,100,32,97,32,102,114,111,122,101,110,32,109, + 111,100,117,108,101,46,10,10,32,32,32,32,32,32,32,32, + 84,104,105,115,32,109,101,116,104,111,100,32,105,115,32,100, + 101,112,114,101,99,97,116,101,100,46,32,32,85,115,101,32, + 102,105,110,100,95,115,112,101,99,40,41,32,105,110,115,116, + 101,97,100,46,10,10,32,32,32,32,32,32,32,32,78,41, + 2,114,49,0,0,0,114,75,0,0,0,41,3,114,142,0, + 0,0,114,71,0,0,0,114,143,0,0,0,114,10,0,0, + 0,114,10,0,0,0,114,11,0,0,0,114,146,0,0,0, + 31,3,0,0,115,2,0,0,0,0,7,122,26,70,114,111, + 122,101,110,73,109,112,111,114,116,101,114,46,102,105,110,100, + 95,109,111,100,117,108,101,99,2,0,0,0,0,0,0,0, + 2,0,0,0,1,0,0,0,67,0,0,0,115,4,0,0, + 0,100,1,83,0,41,2,122,42,85,115,101,32,100,101,102, + 97,117,108,116,32,115,101,109,97,110,116,105,99,115,32,102, + 111,114,32,109,111,100,117,108,101,32,99,114,101,97,116,105, + 111,110,46,78,114,10,0,0,0,41,2,114,142,0,0,0, + 114,82,0,0,0,114,10,0,0,0,114,10,0,0,0,114, + 11,0,0,0,114,134,0,0,0,40,3,0,0,115,2,0, + 0,0,0,2,122,28,70,114,111,122,101,110,73,109,112,111, + 114,116,101,114,46,99,114,101,97,116,101,95,109,111,100,117, + 108,101,99,1,0,0,0,0,0,0,0,3,0,0,0,4, + 0,0,0,67,0,0,0,115,64,0,0,0,124,0,106,0, + 106,1,125,1,116,2,160,3,124,1,161,1,115,36,116,4, + 100,1,160,5,124,1,161,1,124,1,100,2,141,2,130,1, + 116,6,116,2,106,7,124,1,131,2,125,2,116,8,124,2, + 124,0,106,9,131,2,1,0,100,0,83,0,41,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,41,1,114,15, + 0,0,0,41,10,114,89,0,0,0,114,15,0,0,0,114, + 49,0,0,0,114,75,0,0,0,114,70,0,0,0,114,38, + 0,0,0,114,59,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,83,0,0,0,114,15,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,135,0,0,0,44,3,0,0, + 115,12,0,0,0,0,2,8,1,10,1,10,1,8,1,12, + 1,122,26,70,114,111,122,101,110,73,109,112,111,114,116,101, + 114,46,101,120,101,99,95,109,111,100,117,108,101,99,2,0, + 0,0,0,0,0,0,2,0,0,0,3,0,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,84,0,0,0,41,2,114,142,0, + 0,0,114,71,0,0,0,114,10,0,0,0,114,10,0,0, + 0,114,11,0,0,0,114,137,0,0,0,53,3,0,0,115, + 2,0,0,0,0,7,122,26,70,114,111,122,101,110,73,109, + 112,111,114,116,101,114,46,108,111,97,100,95,109,111,100,117, + 108,101,99,2,0,0,0,0,0,0,0,2,0,0,0,3, + 0,0,0,67,0,0,0,115,10,0,0,0,116,0,160,1, + 124,1,161,1,83,0,41,1,122,45,82,101,116,117,114,110, + 32,116,104,101,32,99,111,100,101,32,111,98,106,101,99,116, + 32,102,111,114,32,116,104,101,32,102,114,111,122,101,110,32, + 109,111,100,117,108,101,46,41,2,114,49,0,0,0,114,153, + 0,0,0,41,2,114,142,0,0,0,114,71,0,0,0,114, + 10,0,0,0,114,10,0,0,0,114,11,0,0,0,114,147, + 0,0,0,62,3,0,0,115,2,0,0,0,0,4,122,23, + 70,114,111,122,101,110,73,109,112,111,114,116,101,114,46,103, + 101,116,95,99,111,100,101,99,2,0,0,0,0,0,0,0, + 2,0,0,0,1,0,0,0,67,0,0,0,115,4,0,0, + 0,100,1,83,0,41,2,122,54,82,101,116,117,114,110,32, + 78,111,110,101,32,97,115,32,102,114,111,122,101,110,32,109, + 111,100,117,108,101,115,32,100,111,32,110,111,116,32,104,97, + 118,101,32,115,111,117,114,99,101,32,99,111,100,101,46,78, + 114,10,0,0,0,41,2,114,142,0,0,0,114,71,0,0, + 0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, + 114,148,0,0,0,68,3,0,0,115,2,0,0,0,0,4, + 122,25,70,114,111,122,101,110,73,109,112,111,114,116,101,114, + 46,103,101,116,95,115,111,117,114,99,101,99,2,0,0,0, + 0,0,0,0,2,0,0,0,3,0,0,0,67,0,0,0, + 115,10,0,0,0,116,0,160,1,124,1,161,1,83,0,41, + 1,122,46,82,101,116,117,114,110,32,84,114,117,101,32,105, + 102,32,116,104,101,32,102,114,111,122,101,110,32,109,111,100, + 117,108,101,32,105,115,32,97,32,112,97,99,107,97,103,101, + 46,41,2,114,49,0,0,0,90,17,105,115,95,102,114,111, + 122,101,110,95,112,97,99,107,97,103,101,41,2,114,142,0, 0,0,114,71,0,0,0,114,10,0,0,0,114,10,0,0, - 0,114,11,0,0,0,114,148,0,0,0,68,3,0,0,115, + 0,114,11,0,0,0,114,105,0,0,0,74,3,0,0,115, 2,0,0,0,0,4,122,25,70,114,111,122,101,110,73,109, - 112,111,114,116,101,114,46,103,101,116,95,115,111,117,114,99, - 101,99,2,0,0,0,0,0,0,0,2,0,0,0,3,0, - 0,0,67,0,0,0,115,10,0,0,0,116,0,160,1,124, - 1,161,1,83,0,41,1,122,46,82,101,116,117,114,110,32, - 84,114,117,101,32,105,102,32,116,104,101,32,102,114,111,122, - 101,110,32,109,111,100,117,108,101,32,105,115,32,97,32,112, - 97,99,107,97,103,101,46,41,2,114,49,0,0,0,90,17, - 105,115,95,102,114,111,122,101,110,95,112,97,99,107,97,103, - 101,41,2,114,142,0,0,0,114,71,0,0,0,114,10,0, - 0,0,114,10,0,0,0,114,11,0,0,0,114,105,0,0, - 0,74,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,16, - 114,1,0,0,0,114,0,0,0,0,114,2,0,0,0,114, - 3,0,0,0,114,149,0,0,0,114,86,0,0,0,114,150, - 0,0,0,114,145,0,0,0,114,146,0,0,0,114,134,0, - 0,0,114,135,0,0,0,114,137,0,0,0,114,77,0,0, - 0,114,147,0,0,0,114,148,0,0,0,114,105,0,0,0, - 114,10,0,0,0,114,10,0,0,0,114,10,0,0,0,114, - 11,0,0,0,114,151,0,0,0,6,3,0,0,115,28,0, - 0,0,12,9,12,9,2,1,12,6,2,1,12,8,12,4, - 12,9,12,9,2,1,14,5,2,1,14,5,2,1,114,151, - 0,0,0,99,0,0,0,0,0,0,0,0,0,0,0,0, - 2,0,0,0,64,0,0,0,115,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,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,49, - 0,0,0,114,50,0,0,0,41,1,114,26,0,0,0,114, - 10,0,0,0,114,10,0,0,0,114,11,0,0,0,114,46, - 0,0,0,87,3,0,0,115,2,0,0,0,0,2,122,28, - 95,73,109,112,111,114,116,76,111,99,107,67,111,110,116,101, - 120,116,46,95,95,101,110,116,101,114,95,95,99,4,0,0, - 0,0,0,0,0,4,0,0,0,2,0,0,0,67,0,0, - 0,115,12,0,0,0,116,0,160,1,161,0,1,0,100,1, - 83,0,41,2,122,60,82,101,108,101,97,115,101,32,116,104, - 101,32,105,109,112,111,114,116,32,108,111,99,107,32,114,101, - 103,97,114,100,108,101,115,115,32,111,102,32,97,110,121,32, - 114,97,105,115,101,100,32,101,120,99,101,112,116,105,111,110, - 115,46,78,41,2,114,49,0,0,0,114,52,0,0,0,41, - 4,114,26,0,0,0,90,8,101,120,99,95,116,121,112,101, - 90,9,101,120,99,95,118,97,108,117,101,90,13,101,120,99, - 95,116,114,97,99,101,98,97,99,107,114,10,0,0,0,114, - 10,0,0,0,114,11,0,0,0,114,48,0,0,0,91,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,46,0, - 0,0,114,48,0,0,0,114,10,0,0,0,114,10,0,0, - 0,114,10,0,0,0,114,11,0,0,0,114,156,0,0,0, - 83,3,0,0,115,4,0,0,0,12,4,8,4,114,156,0, - 0,0,99,3,0,0,0,0,0,0,0,5,0,0,0,5, - 0,0,0,67,0,0,0,115,64,0,0,0,124,1,160,0, - 100,1,124,2,100,2,24,0,161,2,125,3,116,1,124,3, - 131,1,124,2,107,0,114,36,116,2,100,3,131,1,130,1, - 124,3,100,4,25,0,125,4,124,0,114,60,100,5,160,3, - 124,4,124,0,161,2,83,0,124,4,83,0,41,6,122,50, - 82,101,115,111,108,118,101,32,97,32,114,101,108,97,116,105, - 118,101,32,109,111,100,117,108,101,32,110,97,109,101,32,116, - 111,32,97,110,32,97,98,115,111,108,117,116,101,32,111,110, - 101,46,114,117,0,0,0,114,33,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,19,0,0,0,122,5,123,125,46,123,125,41,4,218,6, - 114,115,112,108,105,116,218,3,108,101,110,218,10,86,97,108, - 117,101,69,114,114,111,114,114,38,0,0,0,41,5,114,15, - 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,96,3,0, - 0,115,10,0,0,0,0,2,16,1,12,1,8,1,8,1, - 114,162,0,0,0,99,3,0,0,0,0,0,0,0,4,0, - 0,0,4,0,0,0,67,0,0,0,115,34,0,0,0,124, - 0,160,0,124,1,124,2,161,2,125,3,124,3,100,0,107, - 8,114,24,100,0,83,0,116,1,124,1,124,3,131,2,83, - 0,41,1,78,41,2,114,146,0,0,0,114,78,0,0,0, - 41,4,218,6,102,105,110,100,101,114,114,15,0,0,0,114, - 143,0,0,0,114,93,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,105,3,0,0,115, - 8,0,0,0,0,3,12,1,8,1,4,1,114,164,0,0, - 0,99,3,0,0,0,0,0,0,0,10,0,0,0,10,0, - 0,0,67,0,0,0,115,240,0,0,0,116,0,106,1,125, - 3,124,3,100,1,107,8,114,22,116,2,100,2,131,1,130, - 1,124,3,115,38,116,3,160,4,100,3,116,5,161,2,1, - 0,124,0,116,0,106,6,107,6,125,4,120,186,124,3,68, - 0,93,174,125,5,116,7,131,0,143,72,1,0,121,10,124, - 5,106,8,125,6,87,0,110,42,4,0,116,9,107,10,114, - 118,1,0,1,0,1,0,116,10,124,5,124,0,124,1,131, - 3,125,7,124,7,100,1,107,8,114,114,119,54,89,0,110, - 14,88,0,124,6,124,0,124,1,124,2,131,3,125,7,87, - 0,100,1,81,0,82,0,88,0,124,7,100,1,107,9,114, - 54,124,4,115,224,124,0,116,0,106,6,107,6,114,224,116, - 0,106,6,124,0,25,0,125,8,121,10,124,8,106,11,125, - 9,87,0,110,20,4,0,116,9,107,10,114,204,1,0,1, - 0,1,0,124,7,83,0,88,0,124,9,100,1,107,8,114, - 218,124,7,83,0,124,9,83,0,113,54,124,7,83,0,113, - 54,87,0,100,1,83,0,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,14,0,0,0,218,9,109,101,116, - 97,95,112,97,116,104,114,70,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,79,0,0,0, - 114,156,0,0,0,114,145,0,0,0,114,90,0,0,0,114, - 164,0,0,0,114,89,0,0,0,41,10,114,15,0,0,0, - 114,143,0,0,0,114,144,0,0,0,114,165,0,0,0,90, - 9,105,115,95,114,101,108,111,97,100,114,163,0,0,0,114, - 145,0,0,0,114,82,0,0,0,114,83,0,0,0,114,89, - 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,114,3, - 0,0,115,54,0,0,0,0,2,6,1,8,2,8,3,4, - 1,12,5,10,1,10,1,8,1,2,1,10,1,14,1,12, - 1,8,1,8,2,22,1,8,2,14,1,10,1,2,1,10, - 1,14,4,6,2,8,1,4,2,6,2,8,2,114,169,0, - 0,0,99,3,0,0,0,0,0,0,0,3,0,0,0,5, - 0,0,0,67,0,0,0,115,108,0,0,0,116,0,124,0, - 116,1,131,2,115,28,116,2,100,1,160,3,116,4,124,0, - 131,1,161,1,131,1,130,1,124,2,100,2,107,0,114,44, - 116,5,100,3,131,1,130,1,124,2,100,2,107,4,114,84, - 116,0,124,1,116,1,131,2,115,72,116,2,100,4,131,1, - 130,1,110,12,124,1,115,84,116,6,100,5,131,1,130,1, - 124,0,115,104,124,2,100,2,107,2,114,104,116,5,100,6, - 131,1,130,1,100,7,83,0,41,8,122,28,86,101,114,105, - 102,121,32,97,114,103,117,109,101,110,116,115,32,97,114,101, - 32,34,115,97,110,101,34,46,122,31,109,111,100,117,108,101, - 32,110,97,109,101,32,109,117,115,116,32,98,101,32,115,116, - 114,44,32,110,111,116,32,123,125,114,19,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,38,0, - 0,0,114,13,0,0,0,114,159,0,0,0,114,70,0,0, - 0,41,3,114,15,0,0,0,114,160,0,0,0,114,161,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, - 161,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, - 173,0,0,0,122,16,78,111,32,109,111,100,117,108,101,32, - 110,97,109,101,100,32,122,4,123,33,114,125,99,2,0,0, - 0,0,0,0,0,8,0,0,0,8,0,0,0,67,0,0, - 0,115,220,0,0,0,100,0,125,2,124,0,160,0,100,1, - 161,1,100,2,25,0,125,3,124,3,114,134,124,3,116,1, - 106,2,107,7,114,42,116,3,124,1,124,3,131,2,1,0, - 124,0,116,1,106,2,107,6,114,62,116,1,106,2,124,0, - 25,0,83,0,116,1,106,2,124,3,25,0,125,4,121,10, - 124,4,106,4,125,2,87,0,110,50,4,0,116,5,107,10, - 114,132,1,0,1,0,1,0,116,6,100,3,23,0,160,7, - 124,0,124,3,161,2,125,5,116,8,124,5,124,0,100,4, - 141,2,100,0,130,2,89,0,110,2,88,0,116,9,124,0, - 124,2,131,2,125,6,124,6,100,0,107,8,114,172,116,8, - 116,6,160,7,124,0,161,1,124,0,100,4,141,2,130,1, - 110,8,116,10,124,6,131,1,125,7,124,3,114,216,116,1, - 106,2,124,3,25,0,125,4,116,11,124,4,124,0,160,0, - 100,1,161,1,100,5,25,0,124,7,131,3,1,0,124,7, - 83,0,41,6,78,114,117,0,0,0,114,19,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,41,1,114,15,0,0,0,233, - 2,0,0,0,41,12,114,118,0,0,0,114,14,0,0,0, - 114,79,0,0,0,114,59,0,0,0,114,127,0,0,0,114, - 90,0,0,0,218,8,95,69,82,82,95,77,83,71,114,38, - 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,169,0,0,0,114,140,0, - 0,0,114,5,0,0,0,41,8,114,15,0,0,0,218,7, - 105,109,112,111,114,116,95,114,143,0,0,0,114,119,0,0, - 0,90,13,112,97,114,101,110,116,95,109,111,100,117,108,101, - 114,138,0,0,0,114,82,0,0,0,114,83,0,0,0,114, - 10,0,0,0,114,10,0,0,0,114,11,0,0,0,218,23, - 95,102,105,110,100,95,97,110,100,95,108,111,97,100,95,117, - 110,108,111,99,107,101,100,180,3,0,0,115,42,0,0,0, - 0,1,4,1,14,1,4,1,10,1,10,2,10,1,10,1, - 10,1,2,1,10,1,14,1,16,1,20,1,10,1,8,1, - 20,2,8,1,4,2,10,1,22,1,114,178,0,0,0,99, - 2,0,0,0,0,0,0,0,4,0,0,0,9,0,0,0, - 67,0,0,0,115,94,0,0,0,116,0,124,0,131,1,143, - 38,1,0,116,1,106,2,160,3,124,0,116,4,161,2,125, - 2,124,2,116,4,107,8,114,42,116,5,124,0,124,1,131, - 2,83,0,87,0,100,1,81,0,82,0,88,0,124,2,100, - 1,107,8,114,82,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,41, - 1,114,15,0,0,0,41,9,114,42,0,0,0,114,14,0, - 0,0,114,79,0,0,0,114,30,0,0,0,218,14,95,78, - 69,69,68,83,95,76,79,65,68,73,78,71,114,178,0,0, - 0,114,38,0,0,0,114,176,0,0,0,114,57,0,0,0, - 41,4,114,15,0,0,0,114,177,0,0,0,114,83,0,0, - 0,114,67,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,210,3,0,0,115,20,0,0,0,0,2, - 10,1,14,1,8,1,20,2,8,1,4,1,6,1,12,2, - 8,1,114,180,0,0,0,114,19,0,0,0,99,3,0,0, - 0,0,0,0,0,3,0,0,0,4,0,0,0,67,0,0, - 0,115,42,0,0,0,116,0,124,0,124,1,124,2,131,3, - 1,0,124,2,100,1,107,4,114,32,116,1,124,0,124,1, - 124,2,131,3,125,0,116,2,124,0,116,3,131,2,83,0, - 41,2,97,50,1,0,0,73,109,112,111,114,116,32,97,110, - 100,32,114,101,116,117,114,110,32,116,104,101,32,109,111,100, - 117,108,101,32,98,97,115,101,100,32,111,110,32,105,116,115, - 32,110,97,109,101,44,32,116,104,101,32,112,97,99,107,97, - 103,101,32,116,104,101,32,99,97,108,108,32,105,115,10,32, - 32,32,32,98,101,105,110,103,32,109,97,100,101,32,102,114, - 111,109,44,32,97,110,100,32,116,104,101,32,108,101,118,101, - 108,32,97,100,106,117,115,116,109,101,110,116,46,10,10,32, - 32,32,32,84,104,105,115,32,102,117,110,99,116,105,111,110, - 32,114,101,112,114,101,115,101,110,116,115,32,116,104,101,32, - 103,114,101,97,116,101,115,116,32,99,111,109,109,111,110,32, - 100,101,110,111,109,105,110,97,116,111,114,32,111,102,32,102, - 117,110,99,116,105,111,110,97,108,105,116,121,10,32,32,32, - 32,98,101,116,119,101,101,110,32,105,109,112,111,114,116,95, - 109,111,100,117,108,101,32,97,110,100,32,95,95,105,109,112, - 111,114,116,95,95,46,32,84,104,105,115,32,105,110,99,108, - 117,100,101,115,32,115,101,116,116,105,110,103,32,95,95,112, - 97,99,107,97,103,101,95,95,32,105,102,10,32,32,32,32, - 116,104,101,32,108,111,97,100,101,114,32,100,105,100,32,110, - 111,116,46,10,10,32,32,32,32,114,19,0,0,0,41,4, - 114,173,0,0,0,114,162,0,0,0,114,180,0,0,0,218, - 11,95,103,99,100,95,105,109,112,111,114,116,41,3,114,15, - 0,0,0,114,160,0,0,0,114,161,0,0,0,114,10,0, - 0,0,114,10,0,0,0,114,11,0,0,0,114,181,0,0, - 0,226,3,0,0,115,8,0,0,0,0,9,12,1,8,1, - 12,1,114,181,0,0,0,41,1,218,9,114,101,99,117,114, - 115,105,118,101,99,3,0,0,0,1,0,0,0,8,0,0, - 0,11,0,0,0,67,0,0,0,115,234,0,0,0,116,0, - 124,0,100,1,131,2,114,230,120,218,124,1,68,0,93,210, - 125,4,116,1,124,4,116,2,131,2,115,78,124,3,114,46, - 124,0,106,3,100,2,23,0,125,5,110,4,100,3,125,5, - 116,4,100,4,124,5,155,0,100,5,116,5,124,4,131,1, - 106,3,155,0,157,4,131,1,130,1,113,16,124,4,100,6, - 107,2,114,120,124,3,115,226,116,0,124,0,100,7,131,2, - 114,226,116,6,124,0,124,0,106,7,124,2,100,8,100,9, - 141,4,1,0,113,16,116,0,124,0,124,4,131,2,115,16, - 100,10,160,8,124,0,106,3,124,4,161,2,125,6,121,14, - 116,9,124,2,124,6,131,2,1,0,87,0,113,16,4,0, - 116,10,107,10,114,224,1,0,125,7,1,0,122,36,124,7, - 106,11,124,6,107,2,114,206,116,12,106,13,160,14,124,6, - 116,15,161,2,100,11,107,9,114,206,119,16,130,0,87,0, - 100,11,100,11,125,7,126,7,88,0,89,0,113,16,88,0, - 113,16,87,0,124,0,83,0,41,12,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,114,127,0,0,0,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,41,1,114,182,0,0,0,122,5,123,125,46,123, - 125,78,41,16,114,4,0,0,0,114,170,0,0,0,114,171, - 0,0,0,114,1,0,0,0,114,172,0,0,0,114,13,0, - 0,0,218,16,95,104,97,110,100,108,101,95,102,114,111,109, - 108,105,115,116,114,184,0,0,0,114,38,0,0,0,114,59, - 0,0,0,114,176,0,0,0,114,15,0,0,0,114,14,0, - 0,0,114,79,0,0,0,114,30,0,0,0,114,179,0,0, - 0,41,8,114,83,0,0,0,218,8,102,114,111,109,108,105, - 115,116,114,177,0,0,0,114,182,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,185,0,0,0,241,3,0,0,115,42, - 0,0,0,0,10,10,1,10,1,10,1,4,1,12,2,4, - 1,28,2,8,1,14,1,10,1,10,1,10,1,14,1,2, - 1,14,1,16,4,10,1,18,1,2,1,24,1,114,185,0, - 0,0,99,1,0,0,0,0,0,0,0,3,0,0,0,6, - 0,0,0,67,0,0,0,115,146,0,0,0,124,0,160,0, - 100,1,161,1,125,1,124,0,160,0,100,2,161,1,125,2, - 124,1,100,3,107,9,114,82,124,2,100,3,107,9,114,78, - 124,1,124,2,106,1,107,3,114,78,116,2,106,3,100,4, - 124,1,155,2,100,5,124,2,106,1,155,2,100,6,157,5, - 116,4,100,7,100,8,141,3,1,0,124,1,83,0,124,2, - 100,3,107,9,114,96,124,2,106,1,83,0,116,2,106,3, - 100,9,116,4,100,7,100,8,141,3,1,0,124,0,100,10, - 25,0,125,1,100,11,124,0,107,7,114,142,124,1,160,5, - 100,12,161,1,100,13,25,0,125,1,124,1,83,0,41,14, - 122,167,67,97,108,99,117,108,97,116,101,32,119,104,97,116, - 32,95,95,112,97,99,107,97,103,101,95,95,32,115,104,111, - 117,108,100,32,98,101,46,10,10,32,32,32,32,95,95,112, - 97,99,107,97,103,101,95,95,32,105,115,32,110,111,116,32, - 103,117,97,114,97,110,116,101,101,100,32,116,111,32,98,101, - 32,100,101,102,105,110,101,100,32,111,114,32,99,111,117,108, - 100,32,98,101,32,115,101,116,32,116,111,32,78,111,110,101, - 10,32,32,32,32,116,111,32,114,101,112,114,101,115,101,110, - 116,32,116,104,97,116,32,105,116,115,32,112,114,111,112,101, - 114,32,118,97,108,117,101,32,105,115,32,117,110,107,110,111, - 119,110,46,10,10,32,32,32,32,114,130,0,0,0,114,89, - 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,127,0,0,0,114,117,0,0,0,114,19,0,0, - 0,41,6,114,30,0,0,0,114,119,0,0,0,114,166,0, - 0,0,114,167,0,0,0,114,168,0,0,0,114,118,0,0, - 0,41,3,218,7,103,108,111,98,97,108,115,114,160,0,0, - 0,114,82,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,23,4,0,0,115,30,0,0, - 0,0,7,10,1,10,1,8,1,18,1,22,2,10,1,4, - 1,8,1,6,2,6,2,10,1,8,1,8,1,14,1,114, - 191,0,0,0,114,10,0,0,0,99,5,0,0,0,0,0, - 0,0,9,0,0,0,5,0,0,0,67,0,0,0,115,166, - 0,0,0,124,4,100,1,107,2,114,18,116,0,124,0,131, - 1,125,5,110,36,124,1,100,2,107,9,114,30,124,1,110, - 2,105,0,125,6,116,1,124,6,131,1,125,7,116,0,124, - 0,124,7,124,4,131,3,125,5,124,3,115,150,124,4,100, - 1,107,2,114,84,116,0,124,0,160,2,100,3,161,1,100, - 1,25,0,131,1,83,0,124,0,115,92,124,5,83,0,116, - 3,124,0,131,1,116,3,124,0,160,2,100,3,161,1,100, - 1,25,0,131,1,24,0,125,8,116,4,106,5,124,5,106, - 6,100,2,116,3,124,5,106,6,131,1,124,8,24,0,133, - 2,25,0,25,0,83,0,110,12,116,7,124,5,124,3,116, - 0,131,3,83,0,100,2,83,0,41,4,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,19,0,0,0,78,114,117,0, - 0,0,41,8,114,181,0,0,0,114,191,0,0,0,218,9, - 112,97,114,116,105,116,105,111,110,114,158,0,0,0,114,14, - 0,0,0,114,79,0,0,0,114,1,0,0,0,114,185,0, - 0,0,41,9,114,15,0,0,0,114,190,0,0,0,218,6, - 108,111,99,97,108,115,114,186,0,0,0,114,161,0,0,0, - 114,83,0,0,0,90,8,103,108,111,98,97,108,115,95,114, - 160,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,50,4,0,0,115,26,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,2,114,194,0,0,0, - 99,1,0,0,0,0,0,0,0,2,0,0,0,3,0,0, - 0,67,0,0,0,115,38,0,0,0,116,0,160,1,124,0, - 161,1,125,1,124,1,100,0,107,8,114,30,116,2,100,1, - 124,0,23,0,131,1,130,1,116,3,124,1,131,1,83,0, - 41,2,78,122,25,110,111,32,98,117,105,108,116,45,105,110, - 32,109,111,100,117,108,101,32,110,97,109,101,100,32,41,4, - 114,141,0,0,0,114,145,0,0,0,114,70,0,0,0,114, - 140,0,0,0,41,2,114,15,0,0,0,114,82,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,85,4,0,0,115,8,0,0,0,0,1,10,1, - 8,1,12,1,114,195,0,0,0,99,2,0,0,0,0,0, - 0,0,10,0,0,0,5,0,0,0,67,0,0,0,115,174, - 0,0,0,124,1,97,0,124,0,97,1,116,2,116,1,131, - 1,125,2,120,86,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, - 28,124,3,116,1,106,6,107,6,114,62,116,7,125,5,110, - 18,116,0,160,8,124,3,161,1,114,28,116,9,125,5,110, - 2,113,28,116,10,124,4,124,5,131,2,125,6,116,11,124, - 6,124,4,131,2,1,0,113,28,87,0,116,1,106,3,116, - 12,25,0,125,7,120,54,100,1,68,0,93,46,125,8,124, - 8,116,1,106,3,107,7,114,144,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,120,87,0,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,20,0,0,0,114,166,0,0,0,114,56,0,0,0, - 78,41,15,114,49,0,0,0,114,14,0,0,0,114,13,0, - 0,0,114,79,0,0,0,218,5,105,116,101,109,115,114,170, - 0,0,0,114,69,0,0,0,114,141,0,0,0,114,75,0, - 0,0,114,151,0,0,0,114,128,0,0,0,114,133,0,0, - 0,114,1,0,0,0,114,195,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,15,0,0,0,114,83,0, - 0,0,114,93,0,0,0,114,82,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,92,4, - 0,0,115,36,0,0,0,0,9,4,1,4,3,8,1,20, - 1,10,1,10,1,6,1,10,1,6,2,2,1,10,1,14, - 3,10,1,10,1,10,1,10,2,10,1,114,199,0,0,0, - 99,2,0,0,0,0,0,0,0,2,0,0,0,3,0,0, - 0,67,0,0,0,115,38,0,0,0,116,0,124,0,124,1, - 131,2,1,0,116,1,106,2,160,3,116,4,161,1,1,0, - 116,1,106,2,160,3,116,5,161,1,1,0,100,1,83,0, - 41,2,122,48,73,110,115,116,97,108,108,32,105,109,112,111, - 114,116,101,114,115,32,102,111,114,32,98,117,105,108,116,105, - 110,32,97,110,100,32,102,114,111,122,101,110,32,109,111,100, - 117,108,101,115,78,41,6,114,199,0,0,0,114,14,0,0, - 0,114,165,0,0,0,114,109,0,0,0,114,141,0,0,0, - 114,151,0,0,0,41,2,114,197,0,0,0,114,198,0,0, + 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,16,114,1,0,0,0,114, + 0,0,0,0,114,2,0,0,0,114,3,0,0,0,114,149, + 0,0,0,114,86,0,0,0,114,150,0,0,0,114,145,0, + 0,0,114,146,0,0,0,114,134,0,0,0,114,135,0,0, + 0,114,137,0,0,0,114,77,0,0,0,114,147,0,0,0, + 114,148,0,0,0,114,105,0,0,0,114,10,0,0,0,114, + 10,0,0,0,114,10,0,0,0,114,11,0,0,0,114,151, + 0,0,0,6,3,0,0,115,30,0,0,0,8,7,4,2, + 12,9,2,1,12,6,2,1,12,8,12,4,12,9,12,9, + 2,1,14,5,2,1,14,5,2,1,114,151,0,0,0,99, + 0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0, + 64,0,0,0,115,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,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,49,0,0,0,114, + 50,0,0,0,41,1,114,26,0,0,0,114,10,0,0,0, + 114,10,0,0,0,114,11,0,0,0,114,46,0,0,0,87, + 3,0,0,115,2,0,0,0,0,2,122,28,95,73,109,112, + 111,114,116,76,111,99,107,67,111,110,116,101,120,116,46,95, + 95,101,110,116,101,114,95,95,99,4,0,0,0,0,0,0, + 0,4,0,0,0,2,0,0,0,67,0,0,0,115,12,0, + 0,0,116,0,160,1,161,0,1,0,100,1,83,0,41,2, + 122,60,82,101,108,101,97,115,101,32,116,104,101,32,105,109, + 112,111,114,116,32,108,111,99,107,32,114,101,103,97,114,100, + 108,101,115,115,32,111,102,32,97,110,121,32,114,97,105,115, + 101,100,32,101,120,99,101,112,116,105,111,110,115,46,78,41, + 2,114,49,0,0,0,114,52,0,0,0,41,4,114,26,0, + 0,0,90,8,101,120,99,95,116,121,112,101,90,9,101,120, + 99,95,118,97,108,117,101,90,13,101,120,99,95,116,114,97, + 99,101,98,97,99,107,114,10,0,0,0,114,10,0,0,0, + 114,11,0,0,0,114,48,0,0,0,91,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,46,0,0,0,114,48, + 0,0,0,114,10,0,0,0,114,10,0,0,0,114,10,0, + 0,0,114,11,0,0,0,114,156,0,0,0,83,3,0,0, + 115,6,0,0,0,8,2,4,2,8,4,114,156,0,0,0, + 99,3,0,0,0,0,0,0,0,5,0,0,0,5,0,0, + 0,67,0,0,0,115,64,0,0,0,124,1,160,0,100,1, + 124,2,100,2,24,0,161,2,125,3,116,1,124,3,131,1, + 124,2,107,0,114,36,116,2,100,3,131,1,130,1,124,3, + 100,4,25,0,125,4,124,0,114,60,100,5,160,3,124,4, + 124,0,161,2,83,0,124,4,83,0,41,6,122,50,82,101, + 115,111,108,118,101,32,97,32,114,101,108,97,116,105,118,101, + 32,109,111,100,117,108,101,32,110,97,109,101,32,116,111,32, + 97,110,32,97,98,115,111,108,117,116,101,32,111,110,101,46, + 114,117,0,0,0,114,33,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,19, + 0,0,0,122,5,123,125,46,123,125,41,4,218,6,114,115, + 112,108,105,116,218,3,108,101,110,218,10,86,97,108,117,101, + 69,114,114,111,114,114,38,0,0,0,41,5,114,15,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,96,3,0,0,115, + 10,0,0,0,0,2,16,1,12,1,8,1,8,1,114,162, + 0,0,0,99,3,0,0,0,0,0,0,0,4,0,0,0, + 4,0,0,0,67,0,0,0,115,34,0,0,0,124,0,160, + 0,124,1,124,2,161,2,125,3,124,3,100,0,107,8,114, + 24,100,0,83,0,116,1,124,1,124,3,131,2,83,0,41, + 1,78,41,2,114,146,0,0,0,114,78,0,0,0,41,4, + 218,6,102,105,110,100,101,114,114,15,0,0,0,114,143,0, + 0,0,114,93,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,105,3,0,0,115,8,0, + 0,0,0,3,12,1,8,1,4,1,114,164,0,0,0,99, + 3,0,0,0,0,0,0,0,10,0,0,0,10,0,0,0, + 67,0,0,0,115,240,0,0,0,116,0,106,1,125,3,124, + 3,100,1,107,8,114,22,116,2,100,2,131,1,130,1,124, + 3,115,38,116,3,160,4,100,3,116,5,161,2,1,0,124, + 0,116,0,106,6,107,6,125,4,120,186,124,3,68,0,93, + 174,125,5,116,7,131,0,143,72,1,0,121,10,124,5,106, + 8,125,6,87,0,110,42,4,0,116,9,107,10,114,118,1, + 0,1,0,1,0,116,10,124,5,124,0,124,1,131,3,125, + 7,124,7,100,1,107,8,114,114,119,54,89,0,110,14,88, + 0,124,6,124,0,124,1,124,2,131,3,125,7,87,0,100, + 1,81,0,82,0,88,0,124,7,100,1,107,9,114,54,124, + 4,115,224,124,0,116,0,106,6,107,6,114,224,116,0,106, + 6,124,0,25,0,125,8,121,10,124,8,106,11,125,9,87, + 0,110,20,4,0,116,9,107,10,114,204,1,0,1,0,1, + 0,124,7,83,0,88,0,124,9,100,1,107,8,114,218,124, + 7,83,0,124,9,83,0,113,54,124,7,83,0,113,54,87, + 0,100,1,83,0,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,14,0,0,0,218,9,109,101,116,97,95, + 112,97,116,104,114,70,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,79,0,0,0,114,156, + 0,0,0,114,145,0,0,0,114,90,0,0,0,114,164,0, + 0,0,114,89,0,0,0,41,10,114,15,0,0,0,114,143, + 0,0,0,114,144,0,0,0,114,165,0,0,0,90,9,105, + 115,95,114,101,108,111,97,100,114,163,0,0,0,114,145,0, + 0,0,114,82,0,0,0,114,83,0,0,0,114,89,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,127,4,0,0,115,6, - 0,0,0,0,2,10,2,12,1,114,200,0,0,0,99,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,19,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,115,0,0,0,114,200, - 0,0,0,114,14,0,0,0,114,79,0,0,0,114,1,0, - 0,0,41,1,114,201,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,135,4,0,0,115,6,0,0,0,0,3, - 8,1,4,1,114,202,0,0,0,41,2,78,78,41,1,78, - 41,2,78,114,19,0,0,0,41,4,78,78,114,10,0,0, - 0,114,19,0,0,0,41,51,114,3,0,0,0,114,115,0, - 0,0,114,12,0,0,0,114,16,0,0,0,114,51,0,0, - 0,114,29,0,0,0,114,36,0,0,0,114,17,0,0,0, - 114,18,0,0,0,114,41,0,0,0,114,42,0,0,0,114, - 45,0,0,0,114,57,0,0,0,114,59,0,0,0,114,68, - 0,0,0,114,74,0,0,0,114,77,0,0,0,114,84,0, - 0,0,114,95,0,0,0,114,96,0,0,0,114,102,0,0, - 0,114,78,0,0,0,114,128,0,0,0,114,133,0,0,0, - 114,136,0,0,0,114,91,0,0,0,114,80,0,0,0,114, - 139,0,0,0,114,140,0,0,0,114,81,0,0,0,114,141, - 0,0,0,114,151,0,0,0,114,156,0,0,0,114,162,0, - 0,0,114,164,0,0,0,114,169,0,0,0,114,173,0,0, - 0,90,15,95,69,82,82,95,77,83,71,95,80,82,69,70, - 73,88,114,175,0,0,0,114,178,0,0,0,218,6,111,98, - 106,101,99,116,114,179,0,0,0,114,180,0,0,0,114,181, - 0,0,0,114,185,0,0,0,114,191,0,0,0,114,194,0, - 0,0,114,195,0,0,0,114,199,0,0,0,114,200,0,0, - 0,114,202,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,25,0,0,0,115,96,0,0,0,4,0,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,27,14,101,16,26,10,45,14,72,8,17,8,17,8, - 24,8,29,8,23,8,15,14,73,14,77,14,13,8,9,8, - 9,10,47,8,16,4,1,8,2,8,27,6,3,8,16,10, - 15,14,38,8,27,10,35,8,7,8,35,8,8, + 218,10,95,102,105,110,100,95,115,112,101,99,114,3,0,0, + 115,54,0,0,0,0,2,6,1,8,2,8,3,4,1,12, + 5,10,1,10,1,8,1,2,1,10,1,14,1,12,1,8, + 1,8,2,22,1,8,2,14,1,10,1,2,1,10,1,14, + 4,6,2,8,1,4,2,6,2,8,2,114,169,0,0,0, + 99,3,0,0,0,0,0,0,0,3,0,0,0,5,0,0, + 0,67,0,0,0,115,108,0,0,0,116,0,124,0,116,1, + 131,2,115,28,116,2,100,1,160,3,116,4,124,0,131,1, + 161,1,131,1,130,1,124,2,100,2,107,0,114,44,116,5, + 100,3,131,1,130,1,124,2,100,2,107,4,114,84,116,0, + 124,1,116,1,131,2,115,72,116,2,100,4,131,1,130,1, + 110,12,124,1,115,84,116,6,100,5,131,1,130,1,124,0, + 115,104,124,2,100,2,107,2,114,104,116,5,100,6,131,1, + 130,1,100,7,83,0,41,8,122,28,86,101,114,105,102,121, + 32,97,114,103,117,109,101,110,116,115,32,97,114,101,32,34, + 115,97,110,101,34,46,122,31,109,111,100,117,108,101,32,110, + 97,109,101,32,109,117,115,116,32,98,101,32,115,116,114,44, + 32,110,111,116,32,123,125,114,19,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,38,0,0,0, + 114,13,0,0,0,114,159,0,0,0,114,70,0,0,0,41, + 3,114,15,0,0,0,114,160,0,0,0,114,161,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,161,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,173,0, + 0,0,122,16,78,111,32,109,111,100,117,108,101,32,110,97, + 109,101,100,32,122,4,123,33,114,125,99,2,0,0,0,0, + 0,0,0,8,0,0,0,8,0,0,0,67,0,0,0,115, + 220,0,0,0,100,0,125,2,124,0,160,0,100,1,161,1, + 100,2,25,0,125,3,124,3,114,134,124,3,116,1,106,2, + 107,7,114,42,116,3,124,1,124,3,131,2,1,0,124,0, + 116,1,106,2,107,6,114,62,116,1,106,2,124,0,25,0, + 83,0,116,1,106,2,124,3,25,0,125,4,121,10,124,4, + 106,4,125,2,87,0,110,50,4,0,116,5,107,10,114,132, + 1,0,1,0,1,0,116,6,100,3,23,0,160,7,124,0, + 124,3,161,2,125,5,116,8,124,5,124,0,100,4,141,2, + 100,0,130,2,89,0,110,2,88,0,116,9,124,0,124,2, + 131,2,125,6,124,6,100,0,107,8,114,172,116,8,116,6, + 160,7,124,0,161,1,124,0,100,4,141,2,130,1,110,8, + 116,10,124,6,131,1,125,7,124,3,114,216,116,1,106,2, + 124,3,25,0,125,4,116,11,124,4,124,0,160,0,100,1, + 161,1,100,5,25,0,124,7,131,3,1,0,124,7,83,0, + 41,6,78,114,117,0,0,0,114,19,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,41,1,114,15,0,0,0,233,2,0, + 0,0,41,12,114,118,0,0,0,114,14,0,0,0,114,79, + 0,0,0,114,59,0,0,0,114,127,0,0,0,114,90,0, + 0,0,218,8,95,69,82,82,95,77,83,71,114,38,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,169,0,0,0,114,140,0,0,0, + 114,5,0,0,0,41,8,114,15,0,0,0,218,7,105,109, + 112,111,114,116,95,114,143,0,0,0,114,119,0,0,0,90, + 13,112,97,114,101,110,116,95,109,111,100,117,108,101,114,138, + 0,0,0,114,82,0,0,0,114,83,0,0,0,114,10,0, + 0,0,114,10,0,0,0,114,11,0,0,0,218,23,95,102, + 105,110,100,95,97,110,100,95,108,111,97,100,95,117,110,108, + 111,99,107,101,100,180,3,0,0,115,42,0,0,0,0,1, + 4,1,14,1,4,1,10,1,10,2,10,1,10,1,10,1, + 2,1,10,1,14,1,16,1,20,1,10,1,8,1,20,2, + 8,1,4,2,10,1,22,1,114,178,0,0,0,99,2,0, + 0,0,0,0,0,0,4,0,0,0,9,0,0,0,67,0, + 0,0,115,94,0,0,0,116,0,124,0,131,1,143,38,1, + 0,116,1,106,2,160,3,124,0,116,4,161,2,125,2,124, + 2,116,4,107,8,114,42,116,5,124,0,124,1,131,2,83, + 0,87,0,100,1,81,0,82,0,88,0,124,2,100,1,107, + 8,114,82,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,41,1,114, + 15,0,0,0,41,9,114,42,0,0,0,114,14,0,0,0, + 114,79,0,0,0,114,30,0,0,0,218,14,95,78,69,69, + 68,83,95,76,79,65,68,73,78,71,114,178,0,0,0,114, + 38,0,0,0,114,176,0,0,0,114,57,0,0,0,41,4, + 114,15,0,0,0,114,177,0,0,0,114,83,0,0,0,114, + 67,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,210,3,0,0,115,20,0,0,0,0,2,10,1, + 14,1,8,1,20,2,8,1,4,1,6,1,12,2,8,1, + 114,180,0,0,0,114,19,0,0,0,99,3,0,0,0,0, + 0,0,0,3,0,0,0,4,0,0,0,67,0,0,0,115, + 42,0,0,0,116,0,124,0,124,1,124,2,131,3,1,0, + 124,2,100,1,107,4,114,32,116,1,124,0,124,1,124,2, + 131,3,125,0,116,2,124,0,116,3,131,2,83,0,41,2, + 97,50,1,0,0,73,109,112,111,114,116,32,97,110,100,32, + 114,101,116,117,114,110,32,116,104,101,32,109,111,100,117,108, + 101,32,98,97,115,101,100,32,111,110,32,105,116,115,32,110, + 97,109,101,44,32,116,104,101,32,112,97,99,107,97,103,101, + 32,116,104,101,32,99,97,108,108,32,105,115,10,32,32,32, + 32,98,101,105,110,103,32,109,97,100,101,32,102,114,111,109, + 44,32,97,110,100,32,116,104,101,32,108,101,118,101,108,32, + 97,100,106,117,115,116,109,101,110,116,46,10,10,32,32,32, + 32,84,104,105,115,32,102,117,110,99,116,105,111,110,32,114, + 101,112,114,101,115,101,110,116,115,32,116,104,101,32,103,114, + 101,97,116,101,115,116,32,99,111,109,109,111,110,32,100,101, + 110,111,109,105,110,97,116,111,114,32,111,102,32,102,117,110, + 99,116,105,111,110,97,108,105,116,121,10,32,32,32,32,98, + 101,116,119,101,101,110,32,105,109,112,111,114,116,95,109,111, + 100,117,108,101,32,97,110,100,32,95,95,105,109,112,111,114, + 116,95,95,46,32,84,104,105,115,32,105,110,99,108,117,100, + 101,115,32,115,101,116,116,105,110,103,32,95,95,112,97,99, + 107,97,103,101,95,95,32,105,102,10,32,32,32,32,116,104, + 101,32,108,111,97,100,101,114,32,100,105,100,32,110,111,116, + 46,10,10,32,32,32,32,114,19,0,0,0,41,4,114,173, + 0,0,0,114,162,0,0,0,114,180,0,0,0,218,11,95, + 103,99,100,95,105,109,112,111,114,116,41,3,114,15,0,0, + 0,114,160,0,0,0,114,161,0,0,0,114,10,0,0,0, + 114,10,0,0,0,114,11,0,0,0,114,181,0,0,0,226, + 3,0,0,115,8,0,0,0,0,9,12,1,8,1,12,1, + 114,181,0,0,0,41,1,218,9,114,101,99,117,114,115,105, + 118,101,99,3,0,0,0,1,0,0,0,8,0,0,0,11, + 0,0,0,67,0,0,0,115,234,0,0,0,116,0,124,0, + 100,1,131,2,114,230,120,218,124,1,68,0,93,210,125,4, + 116,1,124,4,116,2,131,2,115,78,124,3,114,46,124,0, + 106,3,100,2,23,0,125,5,110,4,100,3,125,5,116,4, + 100,4,124,5,155,0,100,5,116,5,124,4,131,1,106,3, + 155,0,157,4,131,1,130,1,113,16,124,4,100,6,107,2, + 114,120,124,3,115,226,116,0,124,0,100,7,131,2,114,226, + 116,6,124,0,124,0,106,7,124,2,100,8,100,9,141,4, + 1,0,113,16,116,0,124,0,124,4,131,2,115,16,100,10, + 160,8,124,0,106,3,124,4,161,2,125,6,121,14,116,9, + 124,2,124,6,131,2,1,0,87,0,113,16,4,0,116,10, + 107,10,114,224,1,0,125,7,1,0,122,36,124,7,106,11, + 124,6,107,2,114,206,116,12,106,13,160,14,124,6,116,15, + 161,2,100,11,107,9,114,206,119,16,130,0,87,0,100,11, + 100,11,125,7,126,7,88,0,89,0,113,16,88,0,113,16, + 87,0,124,0,83,0,41,12,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,114,127,0,0,0,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,41,1,114,182,0,0,0,122,5,123,125,46,123,125,78, + 41,16,114,4,0,0,0,114,170,0,0,0,114,171,0,0, + 0,114,1,0,0,0,114,172,0,0,0,114,13,0,0,0, + 218,16,95,104,97,110,100,108,101,95,102,114,111,109,108,105, + 115,116,114,184,0,0,0,114,38,0,0,0,114,59,0,0, + 0,114,176,0,0,0,114,15,0,0,0,114,14,0,0,0, + 114,79,0,0,0,114,30,0,0,0,114,179,0,0,0,41, + 8,114,83,0,0,0,218,8,102,114,111,109,108,105,115,116, + 114,177,0,0,0,114,182,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,185,0,0,0,241,3,0,0,115,42,0,0, + 0,0,10,10,1,10,1,10,1,4,1,12,2,4,1,28, + 2,8,1,14,1,10,1,10,1,10,1,14,1,2,1,14, + 1,16,4,10,1,18,1,2,1,24,1,114,185,0,0,0, + 99,1,0,0,0,0,0,0,0,3,0,0,0,6,0,0, + 0,67,0,0,0,115,146,0,0,0,124,0,160,0,100,1, + 161,1,125,1,124,0,160,0,100,2,161,1,125,2,124,1, + 100,3,107,9,114,82,124,2,100,3,107,9,114,78,124,1, + 124,2,106,1,107,3,114,78,116,2,106,3,100,4,124,1, + 155,2,100,5,124,2,106,1,155,2,100,6,157,5,116,4, + 100,7,100,8,141,3,1,0,124,1,83,0,124,2,100,3, + 107,9,114,96,124,2,106,1,83,0,116,2,106,3,100,9, + 116,4,100,7,100,8,141,3,1,0,124,0,100,10,25,0, + 125,1,100,11,124,0,107,7,114,142,124,1,160,5,100,12, + 161,1,100,13,25,0,125,1,124,1,83,0,41,14,122,167, + 67,97,108,99,117,108,97,116,101,32,119,104,97,116,32,95, + 95,112,97,99,107,97,103,101,95,95,32,115,104,111,117,108, + 100,32,98,101,46,10,10,32,32,32,32,95,95,112,97,99, + 107,97,103,101,95,95,32,105,115,32,110,111,116,32,103,117, + 97,114,97,110,116,101,101,100,32,116,111,32,98,101,32,100, + 101,102,105,110,101,100,32,111,114,32,99,111,117,108,100,32, + 98,101,32,115,101,116,32,116,111,32,78,111,110,101,10,32, + 32,32,32,116,111,32,114,101,112,114,101,115,101,110,116,32, + 116,104,97,116,32,105,116,115,32,112,114,111,112,101,114,32, + 118,97,108,117,101,32,105,115,32,117,110,107,110,111,119,110, + 46,10,10,32,32,32,32,114,130,0,0,0,114,89,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,127,0,0,0,114,117,0,0,0,114,19,0,0,0,41, + 6,114,30,0,0,0,114,119,0,0,0,114,166,0,0,0, + 114,167,0,0,0,114,168,0,0,0,114,118,0,0,0,41, + 3,218,7,103,108,111,98,97,108,115,114,160,0,0,0,114, + 82,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,23,4,0,0,115,30,0,0,0,0, + 7,10,1,10,1,8,1,18,1,22,2,10,1,4,1,8, + 1,6,2,6,2,10,1,8,1,8,1,14,1,114,191,0, + 0,0,114,10,0,0,0,99,5,0,0,0,0,0,0,0, + 9,0,0,0,5,0,0,0,67,0,0,0,115,166,0,0, + 0,124,4,100,1,107,2,114,18,116,0,124,0,131,1,125, + 5,110,36,124,1,100,2,107,9,114,30,124,1,110,2,105, + 0,125,6,116,1,124,6,131,1,125,7,116,0,124,0,124, + 7,124,4,131,3,125,5,124,3,115,150,124,4,100,1,107, + 2,114,84,116,0,124,0,160,2,100,3,161,1,100,1,25, + 0,131,1,83,0,124,0,115,92,124,5,83,0,116,3,124, + 0,131,1,116,3,124,0,160,2,100,3,161,1,100,1,25, + 0,131,1,24,0,125,8,116,4,106,5,124,5,106,6,100, + 2,116,3,124,5,106,6,131,1,124,8,24,0,133,2,25, + 0,25,0,83,0,110,12,116,7,124,5,124,3,116,0,131, + 3,83,0,100,2,83,0,41,4,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,19,0,0,0,78,114,117,0,0,0, + 41,8,114,181,0,0,0,114,191,0,0,0,218,9,112,97, + 114,116,105,116,105,111,110,114,158,0,0,0,114,14,0,0, + 0,114,79,0,0,0,114,1,0,0,0,114,185,0,0,0, + 41,9,114,15,0,0,0,114,190,0,0,0,218,6,108,111, + 99,97,108,115,114,186,0,0,0,114,161,0,0,0,114,83, + 0,0,0,90,8,103,108,111,98,97,108,115,95,114,160,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,50,4,0,0,115,26,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,2,114,194,0,0,0,99,1, + 0,0,0,0,0,0,0,2,0,0,0,3,0,0,0,67, + 0,0,0,115,38,0,0,0,116,0,160,1,124,0,161,1, + 125,1,124,1,100,0,107,8,114,30,116,2,100,1,124,0, + 23,0,131,1,130,1,116,3,124,1,131,1,83,0,41,2, + 78,122,25,110,111,32,98,117,105,108,116,45,105,110,32,109, + 111,100,117,108,101,32,110,97,109,101,100,32,41,4,114,141, + 0,0,0,114,145,0,0,0,114,70,0,0,0,114,140,0, + 0,0,41,2,114,15,0,0,0,114,82,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,85,4,0,0,115,8,0,0,0,0,1,10,1,8,1, + 12,1,114,195,0,0,0,99,2,0,0,0,0,0,0,0, + 10,0,0,0,5,0,0,0,67,0,0,0,115,174,0,0, + 0,124,1,97,0,124,0,97,1,116,2,116,1,131,1,125, + 2,120,86,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,28,124, + 3,116,1,106,6,107,6,114,62,116,7,125,5,110,18,116, + 0,160,8,124,3,161,1,114,28,116,9,125,5,110,2,113, + 28,116,10,124,4,124,5,131,2,125,6,116,11,124,6,124, + 4,131,2,1,0,113,28,87,0,116,1,106,3,116,12,25, + 0,125,7,120,54,100,1,68,0,93,46,125,8,124,8,116, + 1,106,3,107,7,114,144,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,120,87,0,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, + 20,0,0,0,114,166,0,0,0,114,56,0,0,0,78,41, + 15,114,49,0,0,0,114,14,0,0,0,114,13,0,0,0, + 114,79,0,0,0,218,5,105,116,101,109,115,114,170,0,0, + 0,114,69,0,0,0,114,141,0,0,0,114,75,0,0,0, + 114,151,0,0,0,114,128,0,0,0,114,133,0,0,0,114, + 1,0,0,0,114,195,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,15,0,0,0,114,83,0,0,0, + 114,93,0,0,0,114,82,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,92,4,0,0, + 115,36,0,0,0,0,9,4,1,4,3,8,1,20,1,10, + 1,10,1,6,1,10,1,6,2,2,1,10,1,14,3,10, + 1,10,1,10,1,10,2,10,1,114,199,0,0,0,99,2, + 0,0,0,0,0,0,0,2,0,0,0,3,0,0,0,67, + 0,0,0,115,38,0,0,0,116,0,124,0,124,1,131,2, + 1,0,116,1,106,2,160,3,116,4,161,1,1,0,116,1, + 106,2,160,3,116,5,161,1,1,0,100,1,83,0,41,2, + 122,48,73,110,115,116,97,108,108,32,105,109,112,111,114,116, + 101,114,115,32,102,111,114,32,98,117,105,108,116,105,110,32, + 97,110,100,32,102,114,111,122,101,110,32,109,111,100,117,108, + 101,115,78,41,6,114,199,0,0,0,114,14,0,0,0,114, + 165,0,0,0,114,109,0,0,0,114,141,0,0,0,114,151, + 0,0,0,41,2,114,197,0,0,0,114,198,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,127,4,0,0,115,6,0,0, + 0,0,2,10,2,12,1,114,200,0,0,0,99,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,19,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,115,0,0,0,114,200,0,0, + 0,114,14,0,0,0,114,79,0,0,0,114,1,0,0,0, + 41,1,114,201,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,135,4,0,0,115,6,0,0,0,0,3,8,1, + 4,1,114,202,0,0,0,41,2,78,78,41,1,78,41,2, + 78,114,19,0,0,0,41,4,78,78,114,10,0,0,0,114, + 19,0,0,0,41,51,114,3,0,0,0,114,115,0,0,0, + 114,12,0,0,0,114,16,0,0,0,114,51,0,0,0,114, + 29,0,0,0,114,36,0,0,0,114,17,0,0,0,114,18, + 0,0,0,114,41,0,0,0,114,42,0,0,0,114,45,0, + 0,0,114,57,0,0,0,114,59,0,0,0,114,68,0,0, + 0,114,74,0,0,0,114,77,0,0,0,114,84,0,0,0, + 114,95,0,0,0,114,96,0,0,0,114,102,0,0,0,114, + 78,0,0,0,114,128,0,0,0,114,133,0,0,0,114,136, + 0,0,0,114,91,0,0,0,114,80,0,0,0,114,139,0, + 0,0,114,140,0,0,0,114,81,0,0,0,114,141,0,0, + 0,114,151,0,0,0,114,156,0,0,0,114,162,0,0,0, + 114,164,0,0,0,114,169,0,0,0,114,173,0,0,0,90, + 15,95,69,82,82,95,77,83,71,95,80,82,69,70,73,88, + 114,175,0,0,0,114,178,0,0,0,218,6,111,98,106,101, + 99,116,114,179,0,0,0,114,180,0,0,0,114,181,0,0, + 0,114,185,0,0,0,114,191,0,0,0,114,194,0,0,0, + 114,195,0,0,0,114,199,0,0,0,114,200,0,0,0,114, + 202,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,8,0,0,0,115,96,0,0,0,4,17,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, + 27,14,101,16,26,10,45,14,72,8,17,8,17,8,24,8, + 29,8,23,8,15,14,73,14,77,14,13,8,9,8,9,10, + 47,8,16,4,1,8,2,8,27,6,3,8,16,10,15,14, + 38,8,27,10,35,8,7,8,35,8,8, }; diff --git a/Python/importlib_external.h b/Python/importlib_external.h index 273188bfb8e7..73775cd37b16 100644 --- a/Python/importlib_external.h +++ b/Python/importlib_external.h @@ -243,7 +243,7 @@ const unsigned char _Py_M__importlib_external[] = { 114,4,0,0,0,218,13,95,119,114,105,116,101,95,97,116, 111,109,105,99,105,0,0,0,115,26,0,0,0,0,5,16, 1,6,1,26,1,2,3,14,1,20,1,16,1,14,1,2, - 1,14,1,14,1,6,1,114,56,0,0,0,105,65,13,0, + 1,14,1,14,1,6,1,114,56,0,0,0,105,66,13,0, 0,233,2,0,0,0,114,13,0,0,0,115,2,0,0,0, 13,10,90,11,95,95,112,121,99,97,99,104,101,95,95,122, 4,111,112,116,45,122,3,46,112,121,122,4,46,112,121,99, @@ -348,7 +348,7 @@ const unsigned char _Py_M__importlib_external[] = { 108,109,111,115,116,95,102,105,108,101,110,97,109,101,114,2, 0,0,0,114,2,0,0,0,114,4,0,0,0,218,17,99, 97,99,104,101,95,102,114,111,109,95,115,111,117,114,99,101, - 13,1,0,0,115,48,0,0,0,0,18,8,1,6,1,6, + 15,1,0,0,115,48,0,0,0,0,18,8,1,6,1,6, 1,8,1,4,1,8,1,12,1,10,1,12,1,16,1,8, 1,8,1,8,1,24,1,8,1,12,1,6,2,8,1,8, 1,8,1,8,1,14,1,14,1,114,81,0,0,0,99,1, @@ -422,7 +422,7 @@ const unsigned char _Py_M__importlib_external[] = { 101,118,101,108,90,13,98,97,115,101,95,102,105,108,101,110, 97,109,101,114,2,0,0,0,114,2,0,0,0,114,4,0, 0,0,218,17,115,111,117,114,99,101,95,102,114,111,109,95, - 99,97,99,104,101,58,1,0,0,115,46,0,0,0,0,9, + 99,97,99,104,101,60,1,0,0,115,46,0,0,0,0,9, 12,1,8,1,10,1,12,1,12,1,8,1,6,1,10,1, 10,1,8,1,6,1,10,1,8,1,16,1,10,1,6,1, 8,1,16,1,8,1,6,1,8,1,14,1,114,87,0,0, @@ -456,7 +456,7 @@ const unsigned char _Py_M__importlib_external[] = { 36,0,0,0,90,9,101,120,116,101,110,115,105,111,110,218, 11,115,111,117,114,99,101,95,112,97,116,104,114,2,0,0, 0,114,2,0,0,0,114,4,0,0,0,218,15,95,103,101, - 116,95,115,111,117,114,99,101,102,105,108,101,92,1,0,0, + 116,95,115,111,117,114,99,101,102,105,108,101,94,1,0,0, 115,20,0,0,0,0,7,12,1,4,1,16,1,24,1,4, 1,2,1,12,1,18,1,18,1,114,93,0,0,0,99,1, 0,0,0,0,0,0,0,1,0,0,0,8,0,0,0,67, @@ -470,7 +470,7 @@ const unsigned char _Py_M__importlib_external[] = { 114,68,0,0,0,114,76,0,0,0,41,1,218,8,102,105, 108,101,110,97,109,101,114,2,0,0,0,114,2,0,0,0, 114,4,0,0,0,218,11,95,103,101,116,95,99,97,99,104, - 101,100,111,1,0,0,115,16,0,0,0,0,1,14,1,2, + 101,100,113,1,0,0,115,16,0,0,0,0,1,14,1,2, 1,8,1,14,1,8,1,14,1,4,2,114,97,0,0,0, 99,1,0,0,0,0,0,0,0,2,0,0,0,8,0,0, 0,67,0,0,0,115,52,0,0,0,121,14,116,0,124,0, @@ -484,7 +484,7 @@ const unsigned char _Py_M__importlib_external[] = { 3,114,39,0,0,0,114,41,0,0,0,114,40,0,0,0, 41,2,114,35,0,0,0,114,42,0,0,0,114,2,0,0, 0,114,2,0,0,0,114,4,0,0,0,218,10,95,99,97, - 108,99,95,109,111,100,101,123,1,0,0,115,12,0,0,0, + 108,99,95,109,111,100,101,125,1,0,0,115,12,0,0,0, 0,2,2,1,14,1,14,1,10,3,8,1,114,99,0,0, 0,99,1,0,0,0,0,0,0,0,3,0,0,0,8,0, 0,0,3,0,0,0,115,68,0,0,0,100,6,135,0,102, @@ -521,7 +521,7 @@ const unsigned char _Py_M__importlib_external[] = { 101,108,102,114,100,0,0,0,218,4,97,114,103,115,90,6, 107,119,97,114,103,115,41,1,218,6,109,101,116,104,111,100, 114,2,0,0,0,114,4,0,0,0,218,19,95,99,104,101, - 99,107,95,110,97,109,101,95,119,114,97,112,112,101,114,143, + 99,107,95,110,97,109,101,95,119,114,97,112,112,101,114,145, 1,0,0,115,12,0,0,0,0,1,8,1,8,1,10,1, 4,1,18,1,122,40,95,99,104,101,99,107,95,110,97,109, 101,46,60,108,111,99,97,108,115,62,46,95,99,104,101,99, @@ -539,7 +539,7 @@ const unsigned char _Py_M__importlib_external[] = { 116,116,114,218,8,95,95,100,105,99,116,95,95,218,6,117, 112,100,97,116,101,41,3,90,3,110,101,119,90,3,111,108, 100,114,53,0,0,0,114,2,0,0,0,114,2,0,0,0, - 114,4,0,0,0,218,5,95,119,114,97,112,154,1,0,0, + 114,4,0,0,0,218,5,95,119,114,97,112,156,1,0,0, 115,8,0,0,0,0,1,10,1,10,1,22,1,122,26,95, 99,104,101,99,107,95,110,97,109,101,46,60,108,111,99,97, 108,115,62,46,95,119,114,97,112,41,1,78,41,3,218,10, @@ -547,7 +547,7 @@ const unsigned char _Py_M__importlib_external[] = { 9,78,97,109,101,69,114,114,111,114,41,3,114,104,0,0, 0,114,105,0,0,0,114,115,0,0,0,114,2,0,0,0, 41,1,114,104,0,0,0,114,4,0,0,0,218,11,95,99, - 104,101,99,107,95,110,97,109,101,135,1,0,0,115,14,0, + 104,101,99,107,95,110,97,109,101,137,1,0,0,115,14,0, 0,0,0,8,14,7,2,1,10,1,14,2,14,5,10,1, 114,118,0,0,0,99,2,0,0,0,0,0,0,0,5,0, 0,0,6,0,0,0,67,0,0,0,115,60,0,0,0,124, @@ -575,7 +575,7 @@ const unsigned char _Py_M__importlib_external[] = { 101,218,6,108,111,97,100,101,114,218,8,112,111,114,116,105, 111,110,115,218,3,109,115,103,114,2,0,0,0,114,2,0, 0,0,114,4,0,0,0,218,17,95,102,105,110,100,95,109, - 111,100,117,108,101,95,115,104,105,109,163,1,0,0,115,10, + 111,100,117,108,101,95,115,104,105,109,165,1,0,0,115,10, 0,0,0,0,10,14,1,16,1,4,1,22,1,114,125,0, 0,0,99,3,0,0,0,0,0,0,0,6,0,0,0,4, 0,0,0,67,0,0,0,115,158,0,0,0,124,0,100,1, @@ -642,7 +642,7 @@ const unsigned char _Py_M__importlib_external[] = { 115,90,5,109,97,103,105,99,114,77,0,0,0,114,69,0, 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, 0,218,13,95,99,108,97,115,115,105,102,121,95,112,121,99, - 180,1,0,0,115,28,0,0,0,0,16,12,1,8,1,16, + 182,1,0,0,115,28,0,0,0,0,16,12,1,8,1,16, 1,12,1,12,1,12,1,10,1,12,1,8,1,16,2,8, 1,16,1,12,1,114,133,0,0,0,99,5,0,0,0,0, 0,0,0,6,0,0,0,4,0,0,0,67,0,0,0,115, @@ -696,7 +696,7 @@ const unsigned char _Py_M__importlib_external[] = { 101,114,100,0,0,0,114,132,0,0,0,114,77,0,0,0, 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,218, 23,95,118,97,108,105,100,97,116,101,95,116,105,109,101,115, - 116,97,109,112,95,112,121,99,213,1,0,0,115,14,0,0, + 116,97,109,112,95,112,121,99,215,1,0,0,115,14,0,0, 0,0,19,24,1,10,1,12,1,12,1,8,1,24,1,114, 137,0,0,0,99,4,0,0,0,0,0,0,0,4,0,0, 0,3,0,0,0,67,0,0,0,115,38,0,0,0,124,0, @@ -742,7 +742,7 @@ const unsigned char _Py_M__importlib_external[] = { 104,97,115,104,114,100,0,0,0,114,132,0,0,0,114,2, 0,0,0,114,2,0,0,0,114,4,0,0,0,218,18,95, 118,97,108,105,100,97,116,101,95,104,97,115,104,95,112,121, - 99,241,1,0,0,115,8,0,0,0,0,17,16,1,2,1, + 99,243,1,0,0,115,8,0,0,0,0,17,16,1,2,1, 10,1,114,139,0,0,0,99,4,0,0,0,0,0,0,0, 5,0,0,0,5,0,0,0,67,0,0,0,115,80,0,0, 0,116,0,160,1,124,0,161,1,125,4,116,2,124,4,116, @@ -765,7 +765,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,114,100,0,0,0,114,91,0,0,0,114,92,0,0, 0,218,4,99,111,100,101,114,2,0,0,0,114,2,0,0, 0,114,4,0,0,0,218,17,95,99,111,109,112,105,108,101, - 95,98,121,116,101,99,111,100,101,9,2,0,0,115,16,0, + 95,98,121,116,101,99,111,100,101,11,2,0,0,115,16,0, 0,0,0,2,10,1,10,1,12,1,8,1,12,1,4,2, 10,1,114,145,0,0,0,114,60,0,0,0,99,3,0,0, 0,0,0,0,0,4,0,0,0,5,0,0,0,67,0,0, @@ -783,7 +783,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,218,5,109,116,105,109,101,114,136,0,0,0,114,54, 0,0,0,114,2,0,0,0,114,2,0,0,0,114,4,0, 0,0,218,22,95,99,111,100,101,95,116,111,95,116,105,109, - 101,115,116,97,109,112,95,112,121,99,22,2,0,0,115,12, + 101,115,116,97,109,112,95,112,121,99,24,2,0,0,115,12, 0,0,0,0,2,8,1,14,1,14,1,14,1,16,1,114, 150,0,0,0,84,99,3,0,0,0,0,0,0,0,5,0, 0,0,5,0,0,0,67,0,0,0,115,80,0,0,0,116, @@ -802,7 +802,7 @@ const unsigned char _Py_M__importlib_external[] = { 138,0,0,0,90,7,99,104,101,99,107,101,100,114,54,0, 0,0,114,69,0,0,0,114,2,0,0,0,114,2,0,0, 0,114,4,0,0,0,218,17,95,99,111,100,101,95,116,111, - 95,104,97,115,104,95,112,121,99,32,2,0,0,115,14,0, + 95,104,97,115,104,95,112,121,99,34,2,0,0,115,14,0, 0,0,0,2,8,1,12,1,14,1,16,1,10,1,16,1, 114,152,0,0,0,99,1,0,0,0,0,0,0,0,5,0, 0,0,6,0,0,0,67,0,0,0,115,62,0,0,0,100, @@ -829,7 +829,7 @@ const unsigned char _Py_M__importlib_external[] = { 100,108,105,110,101,218,8,101,110,99,111,100,105,110,103,90, 15,110,101,119,108,105,110,101,95,100,101,99,111,100,101,114, 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,218, - 13,100,101,99,111,100,101,95,115,111,117,114,99,101,43,2, + 13,100,101,99,111,100,101,95,115,111,117,114,99,101,45,2, 0,0,115,10,0,0,0,0,5,8,1,12,1,10,1,12, 1,114,157,0,0,0,41,2,114,122,0,0,0,218,26,115, 117,98,109,111,100,117,108,101,95,115,101,97,114,99,104,95, @@ -891,7 +891,7 @@ const unsigned char _Py_M__importlib_external[] = { 115,114,161,0,0,0,90,7,100,105,114,110,97,109,101,114, 2,0,0,0,114,2,0,0,0,114,4,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,60,2,0,0,115,62,0,0,0, + 111,99,97,116,105,111,110,62,2,0,0,115,62,0,0,0, 0,12,8,4,4,1,10,2,2,1,14,1,14,1,8,2, 10,8,16,1,6,3,8,1,16,1,14,1,10,1,6,1, 6,2,4,3,8,2,10,1,2,1,14,1,14,1,6,2, @@ -928,7 +928,7 @@ const unsigned char _Py_M__importlib_external[] = { 65,67,72,73,78,69,41,2,218,3,99,108,115,114,3,0, 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, 0,218,14,95,111,112,101,110,95,114,101,103,105,115,116,114, - 121,140,2,0,0,115,8,0,0,0,0,2,2,1,14,1, + 121,142,2,0,0,115,8,0,0,0,0,2,2,1,14,1, 14,1,122,36,87,105,110,100,111,119,115,82,101,103,105,115, 116,114,121,70,105,110,100,101,114,46,95,111,112,101,110,95, 114,101,103,105,115,116,114,121,99,2,0,0,0,0,0,0, @@ -953,7 +953,7 @@ const unsigned char _Py_M__importlib_external[] = { 115,116,114,121,95,107,101,121,114,3,0,0,0,90,4,104, 107,101,121,218,8,102,105,108,101,112,97,116,104,114,2,0, 0,0,114,2,0,0,0,114,4,0,0,0,218,16,95,115, - 101,97,114,99,104,95,114,101,103,105,115,116,114,121,147,2, + 101,97,114,99,104,95,114,101,103,105,115,116,114,121,149,2, 0,0,115,22,0,0,0,0,2,6,1,8,2,6,1,6, 1,22,1,2,1,12,1,26,1,14,1,6,1,122,38,87, 105,110,100,111,119,115,82,101,103,105,115,116,114,121,70,105, @@ -976,7 +976,7 @@ const unsigned char _Py_M__importlib_external[] = { 101,116,114,178,0,0,0,114,122,0,0,0,114,168,0,0, 0,114,166,0,0,0,114,2,0,0,0,114,2,0,0,0, 114,4,0,0,0,218,9,102,105,110,100,95,115,112,101,99, - 162,2,0,0,115,26,0,0,0,0,2,10,1,8,1,4, + 164,2,0,0,115,26,0,0,0,0,2,10,1,8,1,4, 1,2,1,12,1,14,1,6,1,16,1,14,1,6,1,8, 1,8,1,122,31,87,105,110,100,111,119,115,82,101,103,105, 115,116,114,121,70,105,110,100,101,114,46,102,105,110,100,95, @@ -994,7 +994,7 @@ const unsigned char _Py_M__importlib_external[] = { 78,41,2,114,182,0,0,0,114,122,0,0,0,41,4,114, 172,0,0,0,114,121,0,0,0,114,35,0,0,0,114,166, 0,0,0,114,2,0,0,0,114,2,0,0,0,114,4,0, - 0,0,218,11,102,105,110,100,95,109,111,100,117,108,101,178, + 0,0,218,11,102,105,110,100,95,109,111,100,117,108,101,180, 2,0,0,115,8,0,0,0,0,7,12,1,8,1,6,2, 122,33,87,105,110,100,111,119,115,82,101,103,105,115,116,114, 121,70,105,110,100,101,114,46,102,105,110,100,95,109,111,100, @@ -1004,731 +1004,732 @@ const unsigned char _Py_M__importlib_external[] = { 11,99,108,97,115,115,109,101,116,104,111,100,114,173,0,0, 0,114,179,0,0,0,114,182,0,0,0,114,183,0,0,0, 114,2,0,0,0,114,2,0,0,0,114,2,0,0,0,114, - 4,0,0,0,114,170,0,0,0,128,2,0,0,115,18,0, - 0,0,12,5,4,3,4,2,4,2,12,7,12,15,2,1, - 12,15,2,1,114,170,0,0,0,99,0,0,0,0,0,0, - 0,0,0,0,0,0,2,0,0,0,64,0,0,0,115,48, - 0,0,0,101,0,90,1,100,0,90,2,100,1,90,3,100, - 2,100,3,132,0,90,4,100,4,100,5,132,0,90,5,100, - 6,100,7,132,0,90,6,100,8,100,9,132,0,90,7,100, - 10,83,0,41,11,218,13,95,76,111,97,100,101,114,66,97, - 115,105,99,115,122,83,66,97,115,101,32,99,108,97,115,115, - 32,111,102,32,99,111,109,109,111,110,32,99,111,100,101,32, - 110,101,101,100,101,100,32,98,121,32,98,111,116,104,32,83, - 111,117,114,99,101,76,111,97,100,101,114,32,97,110,100,10, - 32,32,32,32,83,111,117,114,99,101,108,101,115,115,70,105, - 108,101,76,111,97,100,101,114,46,99,2,0,0,0,0,0, - 0,0,5,0,0,0,4,0,0,0,67,0,0,0,115,64, - 0,0,0,116,0,124,0,160,1,124,1,161,1,131,1,100, - 1,25,0,125,2,124,2,160,2,100,2,100,1,161,2,100, - 3,25,0,125,3,124,1,160,3,100,2,161,1,100,4,25, - 0,125,4,124,3,100,5,107,2,111,62,124,4,100,5,107, - 3,83,0,41,6,122,141,67,111,110,99,114,101,116,101,32, - 105,109,112,108,101,109,101,110,116,97,116,105,111,110,32,111, - 102,32,73,110,115,112,101,99,116,76,111,97,100,101,114,46, - 105,115,95,112,97,99,107,97,103,101,32,98,121,32,99,104, - 101,99,107,105,110,103,32,105,102,10,32,32,32,32,32,32, - 32,32,116,104,101,32,112,97,116,104,32,114,101,116,117,114, - 110,101,100,32,98,121,32,103,101,116,95,102,105,108,101,110, - 97,109,101,32,104,97,115,32,97,32,102,105,108,101,110,97, - 109,101,32,111,102,32,39,95,95,105,110,105,116,95,95,46, - 112,121,39,46,114,29,0,0,0,114,59,0,0,0,114,60, - 0,0,0,114,57,0,0,0,218,8,95,95,105,110,105,116, - 95,95,41,4,114,38,0,0,0,114,159,0,0,0,114,34, - 0,0,0,114,32,0,0,0,41,5,114,102,0,0,0,114, - 121,0,0,0,114,96,0,0,0,90,13,102,105,108,101,110, - 97,109,101,95,98,97,115,101,90,9,116,97,105,108,95,110, - 97,109,101,114,2,0,0,0,114,2,0,0,0,114,4,0, - 0,0,114,161,0,0,0,197,2,0,0,115,8,0,0,0, - 0,3,18,1,16,1,14,1,122,24,95,76,111,97,100,101, - 114,66,97,115,105,99,115,46,105,115,95,112,97,99,107,97, - 103,101,99,2,0,0,0,0,0,0,0,2,0,0,0,1, - 0,0,0,67,0,0,0,115,4,0,0,0,100,1,83,0, - 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, - 2,0,0,0,41,2,114,102,0,0,0,114,166,0,0,0, - 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,218, - 13,99,114,101,97,116,101,95,109,111,100,117,108,101,205,2, - 0,0,115,0,0,0,0,122,27,95,76,111,97,100,101,114, - 66,97,115,105,99,115,46,99,114,101,97,116,101,95,109,111, - 100,117,108,101,99,2,0,0,0,0,0,0,0,3,0,0, - 0,5,0,0,0,67,0,0,0,115,56,0,0,0,124,0, - 160,0,124,1,106,1,161,1,125,2,124,2,100,1,107,8, - 114,36,116,2,100,2,160,3,124,1,106,1,161,1,131,1, - 130,1,116,4,160,5,116,6,124,2,124,1,106,7,161,3, - 1,0,100,1,83,0,41,3,122,19,69,120,101,99,117,116, - 101,32,116,104,101,32,109,111,100,117,108,101,46,78,122,52, - 99,97,110,110,111,116,32,108,111,97,100,32,109,111,100,117, - 108,101,32,123,33,114,125,32,119,104,101,110,32,103,101,116, - 95,99,111,100,101,40,41,32,114,101,116,117,114,110,115,32, - 78,111,110,101,41,8,218,8,103,101,116,95,99,111,100,101, - 114,107,0,0,0,114,101,0,0,0,114,48,0,0,0,114, - 116,0,0,0,218,25,95,99,97,108,108,95,119,105,116,104, - 95,102,114,97,109,101,115,95,114,101,109,111,118,101,100,218, - 4,101,120,101,99,114,113,0,0,0,41,3,114,102,0,0, - 0,218,6,109,111,100,117,108,101,114,144,0,0,0,114,2, - 0,0,0,114,2,0,0,0,114,4,0,0,0,218,11,101, - 120,101,99,95,109,111,100,117,108,101,208,2,0,0,115,10, - 0,0,0,0,2,12,1,8,1,6,1,10,1,122,25,95, - 76,111,97,100,101,114,66,97,115,105,99,115,46,101,120,101, - 99,95,109,111,100,117,108,101,99,2,0,0,0,0,0,0, - 0,2,0,0,0,4,0,0,0,67,0,0,0,115,12,0, - 0,0,116,0,160,1,124,0,124,1,161,2,83,0,41,1, - 122,26,84,104,105,115,32,109,111,100,117,108,101,32,105,115, - 32,100,101,112,114,101,99,97,116,101,100,46,41,2,114,116, - 0,0,0,218,17,95,108,111,97,100,95,109,111,100,117,108, - 101,95,115,104,105,109,41,2,114,102,0,0,0,114,121,0, + 4,0,0,0,114,170,0,0,0,130,2,0,0,115,20,0, + 0,0,8,2,4,3,4,3,4,2,4,2,12,7,12,15, + 2,1,12,15,2,1,114,170,0,0,0,99,0,0,0,0, + 0,0,0,0,0,0,0,0,2,0,0,0,64,0,0,0, + 115,48,0,0,0,101,0,90,1,100,0,90,2,100,1,90, + 3,100,2,100,3,132,0,90,4,100,4,100,5,132,0,90, + 5,100,6,100,7,132,0,90,6,100,8,100,9,132,0,90, + 7,100,10,83,0,41,11,218,13,95,76,111,97,100,101,114, + 66,97,115,105,99,115,122,83,66,97,115,101,32,99,108,97, + 115,115,32,111,102,32,99,111,109,109,111,110,32,99,111,100, + 101,32,110,101,101,100,101,100,32,98,121,32,98,111,116,104, + 32,83,111,117,114,99,101,76,111,97,100,101,114,32,97,110, + 100,10,32,32,32,32,83,111,117,114,99,101,108,101,115,115, + 70,105,108,101,76,111,97,100,101,114,46,99,2,0,0,0, + 0,0,0,0,5,0,0,0,4,0,0,0,67,0,0,0, + 115,64,0,0,0,116,0,124,0,160,1,124,1,161,1,131, + 1,100,1,25,0,125,2,124,2,160,2,100,2,100,1,161, + 2,100,3,25,0,125,3,124,1,160,3,100,2,161,1,100, + 4,25,0,125,4,124,3,100,5,107,2,111,62,124,4,100, + 5,107,3,83,0,41,6,122,141,67,111,110,99,114,101,116, + 101,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110, + 32,111,102,32,73,110,115,112,101,99,116,76,111,97,100,101, + 114,46,105,115,95,112,97,99,107,97,103,101,32,98,121,32, + 99,104,101,99,107,105,110,103,32,105,102,10,32,32,32,32, + 32,32,32,32,116,104,101,32,112,97,116,104,32,114,101,116, + 117,114,110,101,100,32,98,121,32,103,101,116,95,102,105,108, + 101,110,97,109,101,32,104,97,115,32,97,32,102,105,108,101, + 110,97,109,101,32,111,102,32,39,95,95,105,110,105,116,95, + 95,46,112,121,39,46,114,29,0,0,0,114,59,0,0,0, + 114,60,0,0,0,114,57,0,0,0,218,8,95,95,105,110, + 105,116,95,95,41,4,114,38,0,0,0,114,159,0,0,0, + 114,34,0,0,0,114,32,0,0,0,41,5,114,102,0,0, + 0,114,121,0,0,0,114,96,0,0,0,90,13,102,105,108, + 101,110,97,109,101,95,98,97,115,101,90,9,116,97,105,108, + 95,110,97,109,101,114,2,0,0,0,114,2,0,0,0,114, + 4,0,0,0,114,161,0,0,0,199,2,0,0,115,8,0, + 0,0,0,3,18,1,16,1,14,1,122,24,95,76,111,97, + 100,101,114,66,97,115,105,99,115,46,105,115,95,112,97,99, + 107,97,103,101,99,2,0,0,0,0,0,0,0,2,0,0, + 0,1,0,0,0,67,0,0,0,115,4,0,0,0,100,1, + 83,0,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,2,0,0,0,41,2,114,102,0,0,0,114,166,0, 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, - 0,218,11,108,111,97,100,95,109,111,100,117,108,101,216,2, - 0,0,115,2,0,0,0,0,2,122,25,95,76,111,97,100, - 101,114,66,97,115,105,99,115,46,108,111,97,100,95,109,111, - 100,117,108,101,78,41,8,114,107,0,0,0,114,106,0,0, - 0,114,108,0,0,0,114,109,0,0,0,114,161,0,0,0, - 114,187,0,0,0,114,192,0,0,0,114,194,0,0,0,114, - 2,0,0,0,114,2,0,0,0,114,2,0,0,0,114,4, - 0,0,0,114,185,0,0,0,192,2,0,0,115,8,0,0, - 0,12,5,8,8,8,3,8,8,114,185,0,0,0,99,0, - 0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,64, - 0,0,0,115,74,0,0,0,101,0,90,1,100,0,90,2, - 100,1,100,2,132,0,90,3,100,3,100,4,132,0,90,4, - 100,5,100,6,132,0,90,5,100,7,100,8,132,0,90,6, - 100,9,100,10,132,0,90,7,100,11,100,12,156,1,100,13, - 100,14,132,2,90,8,100,15,100,16,132,0,90,9,100,17, - 83,0,41,18,218,12,83,111,117,114,99,101,76,111,97,100, - 101,114,99,2,0,0,0,0,0,0,0,2,0,0,0,1, - 0,0,0,67,0,0,0,115,8,0,0,0,116,0,130,1, - 100,1,83,0,41,2,122,178,79,112,116,105,111,110,97,108, - 32,109,101,116,104,111,100,32,116,104,97,116,32,114,101,116, - 117,114,110,115,32,116,104,101,32,109,111,100,105,102,105,99, - 97,116,105,111,110,32,116,105,109,101,32,40,97,110,32,105, - 110,116,41,32,102,111,114,32,116,104,101,10,32,32,32,32, - 32,32,32,32,115,112,101,99,105,102,105,101,100,32,112,97, - 116,104,44,32,119,104,101,114,101,32,112,97,116,104,32,105, - 115,32,97,32,115,116,114,46,10,10,32,32,32,32,32,32, - 32,32,82,97,105,115,101,115,32,79,83,69,114,114,111,114, - 32,119,104,101,110,32,116,104,101,32,112,97,116,104,32,99, - 97,110,110,111,116,32,98,101,32,104,97,110,100,108,101,100, - 46,10,32,32,32,32,32,32,32,32,78,41,1,114,40,0, - 0,0,41,2,114,102,0,0,0,114,35,0,0,0,114,2, - 0,0,0,114,2,0,0,0,114,4,0,0,0,218,10,112, - 97,116,104,95,109,116,105,109,101,223,2,0,0,115,2,0, - 0,0,0,6,122,23,83,111,117,114,99,101,76,111,97,100, - 101,114,46,112,97,116,104,95,109,116,105,109,101,99,2,0, - 0,0,0,0,0,0,2,0,0,0,4,0,0,0,67,0, - 0,0,115,14,0,0,0,100,1,124,0,160,0,124,1,161, - 1,105,1,83,0,41,2,97,170,1,0,0,79,112,116,105, - 111,110,97,108,32,109,101,116,104,111,100,32,114,101,116,117, - 114,110,105,110,103,32,97,32,109,101,116,97,100,97,116,97, - 32,100,105,99,116,32,102,111,114,32,116,104,101,32,115,112, - 101,99,105,102,105,101,100,32,112,97,116,104,10,32,32,32, - 32,32,32,32,32,116,111,32,98,121,32,116,104,101,32,112, - 97,116,104,32,40,115,116,114,41,46,10,32,32,32,32,32, - 32,32,32,80,111,115,115,105,98,108,101,32,107,101,121,115, - 58,10,32,32,32,32,32,32,32,32,45,32,39,109,116,105, - 109,101,39,32,40,109,97,110,100,97,116,111,114,121,41,32, - 105,115,32,116,104,101,32,110,117,109,101,114,105,99,32,116, - 105,109,101,115,116,97,109,112,32,111,102,32,108,97,115,116, - 32,115,111,117,114,99,101,10,32,32,32,32,32,32,32,32, - 32,32,99,111,100,101,32,109,111,100,105,102,105,99,97,116, - 105,111,110,59,10,32,32,32,32,32,32,32,32,45,32,39, - 115,105,122,101,39,32,40,111,112,116,105,111,110,97,108,41, - 32,105,115,32,116,104,101,32,115,105,122,101,32,105,110,32, - 98,121,116,101,115,32,111,102,32,116,104,101,32,115,111,117, - 114,99,101,32,99,111,100,101,46,10,10,32,32,32,32,32, - 32,32,32,73,109,112,108,101,109,101,110,116,105,110,103,32, - 116,104,105,115,32,109,101,116,104,111,100,32,97,108,108,111, - 119,115,32,116,104,101,32,108,111,97,100,101,114,32,116,111, - 32,114,101,97,100,32,98,121,116,101,99,111,100,101,32,102, - 105,108,101,115,46,10,32,32,32,32,32,32,32,32,82,97, - 105,115,101,115,32,79,83,69,114,114,111,114,32,119,104,101, - 110,32,116,104,101,32,112,97,116,104,32,99,97,110,110,111, - 116,32,98,101,32,104,97,110,100,108,101,100,46,10,32,32, - 32,32,32,32,32,32,114,149,0,0,0,41,1,114,196,0, - 0,0,41,2,114,102,0,0,0,114,35,0,0,0,114,2, - 0,0,0,114,2,0,0,0,114,4,0,0,0,218,10,112, - 97,116,104,95,115,116,97,116,115,231,2,0,0,115,2,0, - 0,0,0,11,122,23,83,111,117,114,99,101,76,111,97,100, - 101,114,46,112,97,116,104,95,115,116,97,116,115,99,4,0, - 0,0,0,0,0,0,4,0,0,0,4,0,0,0,67,0, - 0,0,115,12,0,0,0,124,0,160,0,124,2,124,3,161, - 2,83,0,41,1,122,228,79,112,116,105,111,110,97,108,32, - 109,101,116,104,111,100,32,119,104,105,99,104,32,119,114,105, - 116,101,115,32,100,97,116,97,32,40,98,121,116,101,115,41, - 32,116,111,32,97,32,102,105,108,101,32,112,97,116,104,32, - 40,97,32,115,116,114,41,46,10,10,32,32,32,32,32,32, - 32,32,73,109,112,108,101,109,101,110,116,105,110,103,32,116, - 104,105,115,32,109,101,116,104,111,100,32,97,108,108,111,119, - 115,32,102,111,114,32,116,104,101,32,119,114,105,116,105,110, - 103,32,111,102,32,98,121,116,101,99,111,100,101,32,102,105, - 108,101,115,46,10,10,32,32,32,32,32,32,32,32,84,104, - 101,32,115,111,117,114,99,101,32,112,97,116,104,32,105,115, - 32,110,101,101,100,101,100,32,105,110,32,111,114,100,101,114, - 32,116,111,32,99,111,114,114,101,99,116,108,121,32,116,114, - 97,110,115,102,101,114,32,112,101,114,109,105,115,115,105,111, - 110,115,10,32,32,32,32,32,32,32,32,41,1,218,8,115, - 101,116,95,100,97,116,97,41,4,114,102,0,0,0,114,92, - 0,0,0,90,10,99,97,99,104,101,95,112,97,116,104,114, - 54,0,0,0,114,2,0,0,0,114,2,0,0,0,114,4, - 0,0,0,218,15,95,99,97,99,104,101,95,98,121,116,101, - 99,111,100,101,244,2,0,0,115,2,0,0,0,0,8,122, - 28,83,111,117,114,99,101,76,111,97,100,101,114,46,95,99, - 97,99,104,101,95,98,121,116,101,99,111,100,101,99,3,0, - 0,0,0,0,0,0,3,0,0,0,1,0,0,0,67,0, - 0,0,115,4,0,0,0,100,1,83,0,41,2,122,150,79, - 112,116,105,111,110,97,108,32,109,101,116,104,111,100,32,119, - 104,105,99,104,32,119,114,105,116,101,115,32,100,97,116,97, - 32,40,98,121,116,101,115,41,32,116,111,32,97,32,102,105, - 108,101,32,112,97,116,104,32,40,97,32,115,116,114,41,46, - 10,10,32,32,32,32,32,32,32,32,73,109,112,108,101,109, - 101,110,116,105,110,103,32,116,104,105,115,32,109,101,116,104, - 111,100,32,97,108,108,111,119,115,32,102,111,114,32,116,104, - 101,32,119,114,105,116,105,110,103,32,111,102,32,98,121,116, - 101,99,111,100,101,32,102,105,108,101,115,46,10,32,32,32, - 32,32,32,32,32,78,114,2,0,0,0,41,3,114,102,0, - 0,0,114,35,0,0,0,114,54,0,0,0,114,2,0,0, - 0,114,2,0,0,0,114,4,0,0,0,114,198,0,0,0, - 254,2,0,0,115,0,0,0,0,122,21,83,111,117,114,99, - 101,76,111,97,100,101,114,46,115,101,116,95,100,97,116,97, - 99,2,0,0,0,0,0,0,0,5,0,0,0,10,0,0, - 0,67,0,0,0,115,82,0,0,0,124,0,160,0,124,1, - 161,1,125,2,121,14,124,0,160,1,124,2,161,1,125,3, - 87,0,110,48,4,0,116,2,107,10,114,72,1,0,125,4, - 1,0,122,18,116,3,100,1,124,1,100,2,141,2,124,4, - 130,2,87,0,100,3,100,3,125,4,126,4,88,0,89,0, - 110,2,88,0,116,4,124,3,131,1,83,0,41,4,122,52, - 67,111,110,99,114,101,116,101,32,105,109,112,108,101,109,101, - 110,116,97,116,105,111,110,32,111,102,32,73,110,115,112,101, - 99,116,76,111,97,100,101,114,46,103,101,116,95,115,111,117, - 114,99,101,46,122,39,115,111,117,114,99,101,32,110,111,116, - 32,97,118,97,105,108,97,98,108,101,32,116,104,114,111,117, - 103,104,32,103,101,116,95,100,97,116,97,40,41,41,1,114, - 100,0,0,0,78,41,5,114,159,0,0,0,218,8,103,101, - 116,95,100,97,116,97,114,40,0,0,0,114,101,0,0,0, - 114,157,0,0,0,41,5,114,102,0,0,0,114,121,0,0, - 0,114,35,0,0,0,114,155,0,0,0,218,3,101,120,99, - 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,218, - 10,103,101,116,95,115,111,117,114,99,101,5,3,0,0,115, - 14,0,0,0,0,2,10,1,2,1,14,1,16,1,4,1, - 28,1,122,23,83,111,117,114,99,101,76,111,97,100,101,114, - 46,103,101,116,95,115,111,117,114,99,101,114,89,0,0,0, - 41,1,218,9,95,111,112,116,105,109,105,122,101,99,3,0, - 0,0,1,0,0,0,4,0,0,0,8,0,0,0,67,0, - 0,0,115,22,0,0,0,116,0,106,1,116,2,124,1,124, - 2,100,1,100,2,124,3,100,3,141,6,83,0,41,4,122, - 130,82,101,116,117,114,110,32,116,104,101,32,99,111,100,101, - 32,111,98,106,101,99,116,32,99,111,109,112,105,108,101,100, - 32,102,114,111,109,32,115,111,117,114,99,101,46,10,10,32, - 32,32,32,32,32,32,32,84,104,101,32,39,100,97,116,97, - 39,32,97,114,103,117,109,101,110,116,32,99,97,110,32,98, - 101,32,97,110,121,32,111,98,106,101,99,116,32,116,121,112, - 101,32,116,104,97,116,32,99,111,109,112,105,108,101,40,41, - 32,115,117,112,112,111,114,116,115,46,10,32,32,32,32,32, - 32,32,32,114,190,0,0,0,84,41,2,218,12,100,111,110, - 116,95,105,110,104,101,114,105,116,114,70,0,0,0,41,3, - 114,116,0,0,0,114,189,0,0,0,218,7,99,111,109,112, - 105,108,101,41,4,114,102,0,0,0,114,54,0,0,0,114, - 35,0,0,0,114,203,0,0,0,114,2,0,0,0,114,2, - 0,0,0,114,4,0,0,0,218,14,115,111,117,114,99,101, - 95,116,111,95,99,111,100,101,15,3,0,0,115,4,0,0, - 0,0,5,12,1,122,27,83,111,117,114,99,101,76,111,97, - 100,101,114,46,115,111,117,114,99,101,95,116,111,95,99,111, - 100,101,99,2,0,0,0,0,0,0,0,15,0,0,0,9, - 0,0,0,67,0,0,0,115,46,2,0,0,124,0,160,0, - 124,1,161,1,125,2,100,1,125,3,100,1,125,4,100,1, - 125,5,100,2,125,6,100,3,125,7,121,12,116,1,124,2, - 131,1,125,8,87,0,110,26,4,0,116,2,107,10,114,68, - 1,0,1,0,1,0,100,1,125,8,89,0,144,1,110,48, - 88,0,121,14,124,0,160,3,124,2,161,1,125,9,87,0, - 110,22,4,0,116,4,107,10,114,106,1,0,1,0,1,0, - 89,0,144,1,110,10,88,0,116,5,124,9,100,4,25,0, - 131,1,125,3,121,14,124,0,160,6,124,8,161,1,125,10, - 87,0,110,20,4,0,116,4,107,10,114,154,1,0,1,0, - 1,0,89,0,110,218,88,0,124,1,124,8,100,5,156,2, - 125,11,121,148,116,7,124,10,124,1,124,11,131,3,125,12, - 116,8,124,10,131,1,100,6,100,1,133,2,25,0,125,13, - 124,12,100,7,64,0,100,8,107,3,125,6,124,6,144,1, - 114,36,124,12,100,9,64,0,100,8,107,3,125,7,116,9, - 106,10,100,10,107,3,144,1,114,56,124,7,115,254,116,9, - 106,10,100,11,107,2,144,1,114,56,124,0,160,6,124,2, - 161,1,125,4,116,9,160,11,116,12,124,4,161,2,125,5, - 116,13,124,10,124,5,124,1,124,11,131,4,1,0,110,20, - 116,14,124,10,124,3,124,9,100,12,25,0,124,1,124,11, - 131,5,1,0,87,0,110,26,4,0,116,15,116,16,102,2, - 107,10,144,1,114,84,1,0,1,0,1,0,89,0,110,32, - 88,0,116,17,160,18,100,13,124,8,124,2,161,3,1,0, - 116,19,124,13,124,1,124,8,124,2,100,14,141,4,83,0, - 124,4,100,1,107,8,144,1,114,136,124,0,160,6,124,2, - 161,1,125,4,124,0,160,20,124,4,124,2,161,2,125,14, - 116,17,160,18,100,15,124,2,161,2,1,0,116,21,106,22, - 144,2,115,42,124,8,100,1,107,9,144,2,114,42,124,3, - 100,1,107,9,144,2,114,42,124,6,144,1,114,228,124,5, - 100,1,107,8,144,1,114,214,116,9,160,11,124,4,161,1, - 125,5,116,23,124,14,124,5,124,7,131,3,125,10,110,16, - 116,24,124,14,124,3,116,25,124,4,131,1,131,3,125,10, - 121,30,124,0,160,26,124,2,124,8,124,10,161,3,1,0, - 116,17,160,18,100,16,124,8,161,2,1,0,87,0,110,22, - 4,0,116,2,107,10,144,2,114,40,1,0,1,0,1,0, - 89,0,110,2,88,0,124,14,83,0,41,17,122,190,67,111, - 110,99,114,101,116,101,32,105,109,112,108,101,109,101,110,116, - 97,116,105,111,110,32,111,102,32,73,110,115,112,101,99,116, - 76,111,97,100,101,114,46,103,101,116,95,99,111,100,101,46, - 10,10,32,32,32,32,32,32,32,32,82,101,97,100,105,110, - 103,32,111,102,32,98,121,116,101,99,111,100,101,32,114,101, - 113,117,105,114,101,115,32,112,97,116,104,95,115,116,97,116, - 115,32,116,111,32,98,101,32,105,109,112,108,101,109,101,110, - 116,101,100,46,32,84,111,32,119,114,105,116,101,10,32,32, - 32,32,32,32,32,32,98,121,116,101,99,111,100,101,44,32, - 115,101,116,95,100,97,116,97,32,109,117,115,116,32,97,108, - 115,111,32,98,101,32,105,109,112,108,101,109,101,110,116,101, - 100,46,10,10,32,32,32,32,32,32,32,32,78,70,84,114, - 149,0,0,0,41,2,114,100,0,0,0,114,35,0,0,0, - 114,126,0,0,0,114,29,0,0,0,114,60,0,0,0,114, - 57,0,0,0,90,5,110,101,118,101,114,90,6,97,108,119, - 97,121,115,218,4,115,105,122,101,122,13,123,125,32,109,97, - 116,99,104,101,115,32,123,125,41,3,114,100,0,0,0,114, - 91,0,0,0,114,92,0,0,0,122,19,99,111,100,101,32, - 111,98,106,101,99,116,32,102,114,111,109,32,123,125,122,10, - 119,114,111,116,101,32,123,33,114,125,41,27,114,159,0,0, - 0,114,81,0,0,0,114,68,0,0,0,114,197,0,0,0, - 114,40,0,0,0,114,14,0,0,0,114,200,0,0,0,114, - 133,0,0,0,218,10,109,101,109,111,114,121,118,105,101,119, - 114,143,0,0,0,90,21,99,104,101,99,107,95,104,97,115, - 104,95,98,97,115,101,100,95,112,121,99,115,114,138,0,0, - 0,218,17,95,82,65,87,95,77,65,71,73,67,95,78,85, - 77,66,69,82,114,139,0,0,0,114,137,0,0,0,114,101, - 0,0,0,114,131,0,0,0,114,116,0,0,0,114,130,0, - 0,0,114,145,0,0,0,114,206,0,0,0,114,6,0,0, - 0,218,19,100,111,110,116,95,119,114,105,116,101,95,98,121, - 116,101,99,111,100,101,114,152,0,0,0,114,150,0,0,0, - 114,31,0,0,0,114,199,0,0,0,41,15,114,102,0,0, - 0,114,121,0,0,0,114,92,0,0,0,114,135,0,0,0, - 114,155,0,0,0,114,138,0,0,0,90,10,104,97,115,104, - 95,98,97,115,101,100,90,12,99,104,101,99,107,95,115,111, - 117,114,99,101,114,91,0,0,0,218,2,115,116,114,54,0, - 0,0,114,132,0,0,0,114,69,0,0,0,90,10,98,121, - 116,101,115,95,100,97,116,97,90,11,99,111,100,101,95,111, - 98,106,101,99,116,114,2,0,0,0,114,2,0,0,0,114, - 4,0,0,0,114,188,0,0,0,23,3,0,0,115,134,0, - 0,0,0,7,10,1,4,1,4,1,4,1,4,1,4,1, - 2,1,12,1,14,1,12,2,2,1,14,1,14,1,8,2, - 12,1,2,1,14,1,14,1,6,3,2,1,8,2,2,1, - 12,1,16,1,12,1,6,1,12,1,12,1,4,1,12,1, - 10,1,4,1,2,1,6,2,8,1,8,2,2,1,2,1, - 2,1,6,1,2,1,10,2,20,1,6,2,8,1,6,1, - 6,1,2,1,8,1,10,1,10,1,12,1,12,1,18,1, - 10,1,6,1,10,1,10,1,14,2,6,1,10,1,2,1, - 14,1,16,1,16,1,6,1,122,21,83,111,117,114,99,101, - 76,111,97,100,101,114,46,103,101,116,95,99,111,100,101,78, - 41,10,114,107,0,0,0,114,106,0,0,0,114,108,0,0, - 0,114,196,0,0,0,114,197,0,0,0,114,199,0,0,0, - 114,198,0,0,0,114,202,0,0,0,114,206,0,0,0,114, - 188,0,0,0,114,2,0,0,0,114,2,0,0,0,114,2, - 0,0,0,114,4,0,0,0,114,195,0,0,0,221,2,0, - 0,115,14,0,0,0,8,2,8,8,8,13,8,10,8,7, - 8,10,14,8,114,195,0,0,0,99,0,0,0,0,0,0, - 0,0,0,0,0,0,4,0,0,0,0,0,0,0,115,124, - 0,0,0,101,0,90,1,100,0,90,2,100,1,90,3,100, - 2,100,3,132,0,90,4,100,4,100,5,132,0,90,5,100, - 6,100,7,132,0,90,6,101,7,135,0,102,1,100,8,100, - 9,132,8,131,1,90,8,101,7,100,10,100,11,132,0,131, - 1,90,9,100,12,100,13,132,0,90,10,101,7,100,14,100, - 15,132,0,131,1,90,11,100,16,100,17,132,0,90,12,100, - 18,100,19,132,0,90,13,100,20,100,21,132,0,90,14,100, - 22,100,23,132,0,90,15,135,0,4,0,90,16,83,0,41, - 24,218,10,70,105,108,101,76,111,97,100,101,114,122,103,66, - 97,115,101,32,102,105,108,101,32,108,111,97,100,101,114,32, - 99,108,97,115,115,32,119,104,105,99,104,32,105,109,112,108, - 101,109,101,110,116,115,32,116,104,101,32,108,111,97,100,101, - 114,32,112,114,111,116,111,99,111,108,32,109,101,116,104,111, - 100,115,32,116,104,97,116,10,32,32,32,32,114,101,113,117, - 105,114,101,32,102,105,108,101,32,115,121,115,116,101,109,32, - 117,115,97,103,101,46,99,3,0,0,0,0,0,0,0,3, - 0,0,0,2,0,0,0,67,0,0,0,115,16,0,0,0, - 124,1,124,0,95,0,124,2,124,0,95,1,100,1,83,0, - 41,2,122,75,67,97,99,104,101,32,116,104,101,32,109,111, - 100,117,108,101,32,110,97,109,101,32,97,110,100,32,116,104, - 101,32,112,97,116,104,32,116,111,32,116,104,101,32,102,105, - 108,101,32,102,111,117,110,100,32,98,121,32,116,104,101,10, - 32,32,32,32,32,32,32,32,102,105,110,100,101,114,46,78, - 41,2,114,100,0,0,0,114,35,0,0,0,41,3,114,102, - 0,0,0,114,121,0,0,0,114,35,0,0,0,114,2,0, - 0,0,114,2,0,0,0,114,4,0,0,0,114,186,0,0, - 0,114,3,0,0,115,4,0,0,0,0,3,6,1,122,19, - 70,105,108,101,76,111,97,100,101,114,46,95,95,105,110,105, - 116,95,95,99,2,0,0,0,0,0,0,0,2,0,0,0, - 2,0,0,0,67,0,0,0,115,24,0,0,0,124,0,106, - 0,124,1,106,0,107,2,111,22,124,0,106,1,124,1,106, - 1,107,2,83,0,41,1,78,41,2,218,9,95,95,99,108, - 97,115,115,95,95,114,113,0,0,0,41,2,114,102,0,0, - 0,218,5,111,116,104,101,114,114,2,0,0,0,114,2,0, - 0,0,114,4,0,0,0,218,6,95,95,101,113,95,95,120, - 3,0,0,115,4,0,0,0,0,1,12,1,122,17,70,105, - 108,101,76,111,97,100,101,114,46,95,95,101,113,95,95,99, - 1,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0, - 67,0,0,0,115,20,0,0,0,116,0,124,0,106,1,131, - 1,116,0,124,0,106,2,131,1,65,0,83,0,41,1,78, - 41,3,218,4,104,97,115,104,114,100,0,0,0,114,35,0, - 0,0,41,1,114,102,0,0,0,114,2,0,0,0,114,2, - 0,0,0,114,4,0,0,0,218,8,95,95,104,97,115,104, - 95,95,124,3,0,0,115,2,0,0,0,0,1,122,19,70, - 105,108,101,76,111,97,100,101,114,46,95,95,104,97,115,104, - 95,95,99,2,0,0,0,0,0,0,0,2,0,0,0,3, - 0,0,0,3,0,0,0,115,16,0,0,0,116,0,116,1, - 124,0,131,2,160,2,124,1,161,1,83,0,41,1,122,100, - 76,111,97,100,32,97,32,109,111,100,117,108,101,32,102,114, - 111,109,32,97,32,102,105,108,101,46,10,10,32,32,32,32, - 32,32,32,32,84,104,105,115,32,109,101,116,104,111,100,32, - 105,115,32,100,101,112,114,101,99,97,116,101,100,46,32,32, - 85,115,101,32,101,120,101,99,95,109,111,100,117,108,101,40, - 41,32,105,110,115,116,101,97,100,46,10,10,32,32,32,32, - 32,32,32,32,41,3,218,5,115,117,112,101,114,114,212,0, - 0,0,114,194,0,0,0,41,2,114,102,0,0,0,114,121, - 0,0,0,41,1,114,213,0,0,0,114,2,0,0,0,114, - 4,0,0,0,114,194,0,0,0,127,3,0,0,115,2,0, - 0,0,0,10,122,22,70,105,108,101,76,111,97,100,101,114, - 46,108,111,97,100,95,109,111,100,117,108,101,99,2,0,0, - 0,0,0,0,0,2,0,0,0,1,0,0,0,67,0,0, - 0,115,6,0,0,0,124,0,106,0,83,0,41,1,122,58, - 82,101,116,117,114,110,32,116,104,101,32,112,97,116,104,32, - 116,111,32,116,104,101,32,115,111,117,114,99,101,32,102,105, - 108,101,32,97,115,32,102,111,117,110,100,32,98,121,32,116, - 104,101,32,102,105,110,100,101,114,46,41,1,114,35,0,0, - 0,41,2,114,102,0,0,0,114,121,0,0,0,114,2,0, - 0,0,114,2,0,0,0,114,4,0,0,0,114,159,0,0, - 0,139,3,0,0,115,2,0,0,0,0,3,122,23,70,105, - 108,101,76,111,97,100,101,114,46,103,101,116,95,102,105,108, - 101,110,97,109,101,99,2,0,0,0,0,0,0,0,3,0, - 0,0,9,0,0,0,67,0,0,0,115,32,0,0,0,116, - 0,160,1,124,1,100,1,161,2,143,10,125,2,124,2,160, - 2,161,0,83,0,81,0,82,0,88,0,100,2,83,0,41, - 3,122,39,82,101,116,117,114,110,32,116,104,101,32,100,97, - 116,97,32,102,114,111,109,32,112,97,116,104,32,97,115,32, - 114,97,119,32,98,121,116,101,115,46,218,1,114,78,41,3, - 114,50,0,0,0,114,51,0,0,0,90,4,114,101,97,100, - 41,3,114,102,0,0,0,114,35,0,0,0,114,55,0,0, - 0,114,2,0,0,0,114,2,0,0,0,114,4,0,0,0, - 114,200,0,0,0,144,3,0,0,115,4,0,0,0,0,2, - 14,1,122,19,70,105,108,101,76,111,97,100,101,114,46,103, - 101,116,95,100,97,116,97,99,2,0,0,0,0,0,0,0, - 2,0,0,0,3,0,0,0,67,0,0,0,115,18,0,0, - 0,124,0,160,0,124,1,161,1,114,14,124,0,83,0,100, - 0,83,0,41,1,78,41,1,114,161,0,0,0,41,2,114, - 102,0,0,0,114,191,0,0,0,114,2,0,0,0,114,2, - 0,0,0,114,4,0,0,0,218,19,103,101,116,95,114,101, - 115,111,117,114,99,101,95,114,101,97,100,101,114,151,3,0, - 0,115,6,0,0,0,0,2,10,1,4,1,122,30,70,105, - 108,101,76,111,97,100,101,114,46,103,101,116,95,114,101,115, - 111,117,114,99,101,95,114,101,97,100,101,114,99,2,0,0, - 0,0,0,0,0,3,0,0,0,4,0,0,0,67,0,0, - 0,115,32,0,0,0,116,0,116,1,124,0,106,2,131,1, - 100,1,25,0,124,1,131,2,125,2,116,3,160,4,124,2, - 100,2,161,2,83,0,41,3,78,114,60,0,0,0,114,219, - 0,0,0,41,5,114,28,0,0,0,114,38,0,0,0,114, - 35,0,0,0,114,50,0,0,0,114,51,0,0,0,41,3, - 114,102,0,0,0,218,8,114,101,115,111,117,114,99,101,114, + 0,218,13,99,114,101,97,116,101,95,109,111,100,117,108,101, + 207,2,0,0,115,2,0,0,0,0,1,122,27,95,76,111, + 97,100,101,114,66,97,115,105,99,115,46,99,114,101,97,116, + 101,95,109,111,100,117,108,101,99,2,0,0,0,0,0,0, + 0,3,0,0,0,5,0,0,0,67,0,0,0,115,56,0, + 0,0,124,0,160,0,124,1,106,1,161,1,125,2,124,2, + 100,1,107,8,114,36,116,2,100,2,160,3,124,1,106,1, + 161,1,131,1,130,1,116,4,160,5,116,6,124,2,124,1, + 106,7,161,3,1,0,100,1,83,0,41,3,122,19,69,120, + 101,99,117,116,101,32,116,104,101,32,109,111,100,117,108,101, + 46,78,122,52,99,97,110,110,111,116,32,108,111,97,100,32, + 109,111,100,117,108,101,32,123,33,114,125,32,119,104,101,110, + 32,103,101,116,95,99,111,100,101,40,41,32,114,101,116,117, + 114,110,115,32,78,111,110,101,41,8,218,8,103,101,116,95, + 99,111,100,101,114,107,0,0,0,114,101,0,0,0,114,48, + 0,0,0,114,116,0,0,0,218,25,95,99,97,108,108,95, + 119,105,116,104,95,102,114,97,109,101,115,95,114,101,109,111, + 118,101,100,218,4,101,120,101,99,114,113,0,0,0,41,3, + 114,102,0,0,0,218,6,109,111,100,117,108,101,114,144,0, + 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, + 0,218,11,101,120,101,99,95,109,111,100,117,108,101,210,2, + 0,0,115,10,0,0,0,0,2,12,1,8,1,6,1,10, + 1,122,25,95,76,111,97,100,101,114,66,97,115,105,99,115, + 46,101,120,101,99,95,109,111,100,117,108,101,99,2,0,0, + 0,0,0,0,0,2,0,0,0,4,0,0,0,67,0,0, + 0,115,12,0,0,0,116,0,160,1,124,0,124,1,161,2, + 83,0,41,1,122,26,84,104,105,115,32,109,111,100,117,108, + 101,32,105,115,32,100,101,112,114,101,99,97,116,101,100,46, + 41,2,114,116,0,0,0,218,17,95,108,111,97,100,95,109, + 111,100,117,108,101,95,115,104,105,109,41,2,114,102,0,0, + 0,114,121,0,0,0,114,2,0,0,0,114,2,0,0,0, + 114,4,0,0,0,218,11,108,111,97,100,95,109,111,100,117, + 108,101,218,2,0,0,115,2,0,0,0,0,2,122,25,95, + 76,111,97,100,101,114,66,97,115,105,99,115,46,108,111,97, + 100,95,109,111,100,117,108,101,78,41,8,114,107,0,0,0, + 114,106,0,0,0,114,108,0,0,0,114,109,0,0,0,114, + 161,0,0,0,114,187,0,0,0,114,192,0,0,0,114,194, + 0,0,0,114,2,0,0,0,114,2,0,0,0,114,2,0, + 0,0,114,4,0,0,0,114,185,0,0,0,194,2,0,0, + 115,10,0,0,0,8,3,4,2,8,8,8,3,8,8,114, + 185,0,0,0,99,0,0,0,0,0,0,0,0,0,0,0, + 0,3,0,0,0,64,0,0,0,115,74,0,0,0,101,0, + 90,1,100,0,90,2,100,1,100,2,132,0,90,3,100,3, + 100,4,132,0,90,4,100,5,100,6,132,0,90,5,100,7, + 100,8,132,0,90,6,100,9,100,10,132,0,90,7,100,11, + 100,12,156,1,100,13,100,14,132,2,90,8,100,15,100,16, + 132,0,90,9,100,17,83,0,41,18,218,12,83,111,117,114, + 99,101,76,111,97,100,101,114,99,2,0,0,0,0,0,0, + 0,2,0,0,0,1,0,0,0,67,0,0,0,115,8,0, + 0,0,116,0,130,1,100,1,83,0,41,2,122,178,79,112, + 116,105,111,110,97,108,32,109,101,116,104,111,100,32,116,104, + 97,116,32,114,101,116,117,114,110,115,32,116,104,101,32,109, + 111,100,105,102,105,99,97,116,105,111,110,32,116,105,109,101, + 32,40,97,110,32,105,110,116,41,32,102,111,114,32,116,104, + 101,10,32,32,32,32,32,32,32,32,115,112,101,99,105,102, + 105,101,100,32,112,97,116,104,44,32,119,104,101,114,101,32, + 112,97,116,104,32,105,115,32,97,32,115,116,114,46,10,10, + 32,32,32,32,32,32,32,32,82,97,105,115,101,115,32,79, + 83,69,114,114,111,114,32,119,104,101,110,32,116,104,101,32, + 112,97,116,104,32,99,97,110,110,111,116,32,98,101,32,104, + 97,110,100,108,101,100,46,10,32,32,32,32,32,32,32,32, + 78,41,1,114,40,0,0,0,41,2,114,102,0,0,0,114, 35,0,0,0,114,2,0,0,0,114,2,0,0,0,114,4, - 0,0,0,218,13,111,112,101,110,95,114,101,115,111,117,114, - 99,101,157,3,0,0,115,4,0,0,0,0,1,20,1,122, - 24,70,105,108,101,76,111,97,100,101,114,46,111,112,101,110, - 95,114,101,115,111,117,114,99,101,99,2,0,0,0,0,0, - 0,0,3,0,0,0,3,0,0,0,67,0,0,0,115,38, - 0,0,0,124,0,160,0,124,1,161,1,115,14,116,1,130, - 1,116,2,116,3,124,0,106,4,131,1,100,1,25,0,124, - 1,131,2,125,2,124,2,83,0,41,2,78,114,60,0,0, - 0,41,5,218,11,105,115,95,114,101,115,111,117,114,99,101, - 218,17,70,105,108,101,78,111,116,70,111,117,110,100,69,114, - 114,111,114,114,28,0,0,0,114,38,0,0,0,114,35,0, - 0,0,41,3,114,102,0,0,0,114,221,0,0,0,114,35, - 0,0,0,114,2,0,0,0,114,2,0,0,0,114,4,0, - 0,0,218,13,114,101,115,111,117,114,99,101,95,112,97,116, - 104,161,3,0,0,115,8,0,0,0,0,1,10,1,4,1, - 20,1,122,24,70,105,108,101,76,111,97,100,101,114,46,114, - 101,115,111,117,114,99,101,95,112,97,116,104,99,2,0,0, - 0,0,0,0,0,3,0,0,0,3,0,0,0,67,0,0, - 0,115,40,0,0,0,116,0,124,1,107,6,114,12,100,1, - 83,0,116,1,116,2,124,0,106,3,131,1,100,2,25,0, - 124,1,131,2,125,2,116,4,124,2,131,1,83,0,41,3, - 78,70,114,60,0,0,0,41,5,114,25,0,0,0,114,28, - 0,0,0,114,38,0,0,0,114,35,0,0,0,114,44,0, - 0,0,41,3,114,102,0,0,0,114,100,0,0,0,114,35, - 0,0,0,114,2,0,0,0,114,2,0,0,0,114,4,0, - 0,0,114,223,0,0,0,167,3,0,0,115,8,0,0,0, - 0,1,8,1,4,1,20,1,122,22,70,105,108,101,76,111, - 97,100,101,114,46,105,115,95,114,101,115,111,117,114,99,101, - 99,1,0,0,0,0,0,0,0,1,0,0,0,5,0,0, - 0,67,0,0,0,115,24,0,0,0,116,0,116,1,160,2, - 116,3,124,0,106,4,131,1,100,1,25,0,161,1,131,1, - 83,0,41,2,78,114,60,0,0,0,41,5,218,4,105,116, - 101,114,114,1,0,0,0,218,7,108,105,115,116,100,105,114, - 114,38,0,0,0,114,35,0,0,0,41,1,114,102,0,0, + 0,0,0,218,10,112,97,116,104,95,109,116,105,109,101,225, + 2,0,0,115,2,0,0,0,0,6,122,23,83,111,117,114, + 99,101,76,111,97,100,101,114,46,112,97,116,104,95,109,116, + 105,109,101,99,2,0,0,0,0,0,0,0,2,0,0,0, + 4,0,0,0,67,0,0,0,115,14,0,0,0,100,1,124, + 0,160,0,124,1,161,1,105,1,83,0,41,2,97,170,1, + 0,0,79,112,116,105,111,110,97,108,32,109,101,116,104,111, + 100,32,114,101,116,117,114,110,105,110,103,32,97,32,109,101, + 116,97,100,97,116,97,32,100,105,99,116,32,102,111,114,32, + 116,104,101,32,115,112,101,99,105,102,105,101,100,32,112,97, + 116,104,10,32,32,32,32,32,32,32,32,116,111,32,98,121, + 32,116,104,101,32,112,97,116,104,32,40,115,116,114,41,46, + 10,32,32,32,32,32,32,32,32,80,111,115,115,105,98,108, + 101,32,107,101,121,115,58,10,32,32,32,32,32,32,32,32, + 45,32,39,109,116,105,109,101,39,32,40,109,97,110,100,97, + 116,111,114,121,41,32,105,115,32,116,104,101,32,110,117,109, + 101,114,105,99,32,116,105,109,101,115,116,97,109,112,32,111, + 102,32,108,97,115,116,32,115,111,117,114,99,101,10,32,32, + 32,32,32,32,32,32,32,32,99,111,100,101,32,109,111,100, + 105,102,105,99,97,116,105,111,110,59,10,32,32,32,32,32, + 32,32,32,45,32,39,115,105,122,101,39,32,40,111,112,116, + 105,111,110,97,108,41,32,105,115,32,116,104,101,32,115,105, + 122,101,32,105,110,32,98,121,116,101,115,32,111,102,32,116, + 104,101,32,115,111,117,114,99,101,32,99,111,100,101,46,10, + 10,32,32,32,32,32,32,32,32,73,109,112,108,101,109,101, + 110,116,105,110,103,32,116,104,105,115,32,109,101,116,104,111, + 100,32,97,108,108,111,119,115,32,116,104,101,32,108,111,97, + 100,101,114,32,116,111,32,114,101,97,100,32,98,121,116,101, + 99,111,100,101,32,102,105,108,101,115,46,10,32,32,32,32, + 32,32,32,32,82,97,105,115,101,115,32,79,83,69,114,114, + 111,114,32,119,104,101,110,32,116,104,101,32,112,97,116,104, + 32,99,97,110,110,111,116,32,98,101,32,104,97,110,100,108, + 101,100,46,10,32,32,32,32,32,32,32,32,114,149,0,0, + 0,41,1,114,196,0,0,0,41,2,114,102,0,0,0,114, + 35,0,0,0,114,2,0,0,0,114,2,0,0,0,114,4, + 0,0,0,218,10,112,97,116,104,95,115,116,97,116,115,233, + 2,0,0,115,2,0,0,0,0,11,122,23,83,111,117,114, + 99,101,76,111,97,100,101,114,46,112,97,116,104,95,115,116, + 97,116,115,99,4,0,0,0,0,0,0,0,4,0,0,0, + 4,0,0,0,67,0,0,0,115,12,0,0,0,124,0,160, + 0,124,2,124,3,161,2,83,0,41,1,122,228,79,112,116, + 105,111,110,97,108,32,109,101,116,104,111,100,32,119,104,105, + 99,104,32,119,114,105,116,101,115,32,100,97,116,97,32,40, + 98,121,116,101,115,41,32,116,111,32,97,32,102,105,108,101, + 32,112,97,116,104,32,40,97,32,115,116,114,41,46,10,10, + 32,32,32,32,32,32,32,32,73,109,112,108,101,109,101,110, + 116,105,110,103,32,116,104,105,115,32,109,101,116,104,111,100, + 32,97,108,108,111,119,115,32,102,111,114,32,116,104,101,32, + 119,114,105,116,105,110,103,32,111,102,32,98,121,116,101,99, + 111,100,101,32,102,105,108,101,115,46,10,10,32,32,32,32, + 32,32,32,32,84,104,101,32,115,111,117,114,99,101,32,112, + 97,116,104,32,105,115,32,110,101,101,100,101,100,32,105,110, + 32,111,114,100,101,114,32,116,111,32,99,111,114,114,101,99, + 116,108,121,32,116,114,97,110,115,102,101,114,32,112,101,114, + 109,105,115,115,105,111,110,115,10,32,32,32,32,32,32,32, + 32,41,1,218,8,115,101,116,95,100,97,116,97,41,4,114, + 102,0,0,0,114,92,0,0,0,90,10,99,97,99,104,101, + 95,112,97,116,104,114,54,0,0,0,114,2,0,0,0,114, + 2,0,0,0,114,4,0,0,0,218,15,95,99,97,99,104, + 101,95,98,121,116,101,99,111,100,101,246,2,0,0,115,2, + 0,0,0,0,8,122,28,83,111,117,114,99,101,76,111,97, + 100,101,114,46,95,99,97,99,104,101,95,98,121,116,101,99, + 111,100,101,99,3,0,0,0,0,0,0,0,3,0,0,0, + 1,0,0,0,67,0,0,0,115,4,0,0,0,100,1,83, + 0,41,2,122,150,79,112,116,105,111,110,97,108,32,109,101, + 116,104,111,100,32,119,104,105,99,104,32,119,114,105,116,101, + 115,32,100,97,116,97,32,40,98,121,116,101,115,41,32,116, + 111,32,97,32,102,105,108,101,32,112,97,116,104,32,40,97, + 32,115,116,114,41,46,10,10,32,32,32,32,32,32,32,32, + 73,109,112,108,101,109,101,110,116,105,110,103,32,116,104,105, + 115,32,109,101,116,104,111,100,32,97,108,108,111,119,115,32, + 102,111,114,32,116,104,101,32,119,114,105,116,105,110,103,32, + 111,102,32,98,121,116,101,99,111,100,101,32,102,105,108,101, + 115,46,10,32,32,32,32,32,32,32,32,78,114,2,0,0, + 0,41,3,114,102,0,0,0,114,35,0,0,0,114,54,0, + 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, + 0,114,198,0,0,0,0,3,0,0,115,2,0,0,0,0, + 4,122,21,83,111,117,114,99,101,76,111,97,100,101,114,46, + 115,101,116,95,100,97,116,97,99,2,0,0,0,0,0,0, + 0,5,0,0,0,10,0,0,0,67,0,0,0,115,82,0, + 0,0,124,0,160,0,124,1,161,1,125,2,121,14,124,0, + 160,1,124,2,161,1,125,3,87,0,110,48,4,0,116,2, + 107,10,114,72,1,0,125,4,1,0,122,18,116,3,100,1, + 124,1,100,2,141,2,124,4,130,2,87,0,100,3,100,3, + 125,4,126,4,88,0,89,0,110,2,88,0,116,4,124,3, + 131,1,83,0,41,4,122,52,67,111,110,99,114,101,116,101, + 32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32, + 111,102,32,73,110,115,112,101,99,116,76,111,97,100,101,114, + 46,103,101,116,95,115,111,117,114,99,101,46,122,39,115,111, + 117,114,99,101,32,110,111,116,32,97,118,97,105,108,97,98, + 108,101,32,116,104,114,111,117,103,104,32,103,101,116,95,100, + 97,116,97,40,41,41,1,114,100,0,0,0,78,41,5,114, + 159,0,0,0,218,8,103,101,116,95,100,97,116,97,114,40, + 0,0,0,114,101,0,0,0,114,157,0,0,0,41,5,114, + 102,0,0,0,114,121,0,0,0,114,35,0,0,0,114,155, + 0,0,0,218,3,101,120,99,114,2,0,0,0,114,2,0, + 0,0,114,4,0,0,0,218,10,103,101,116,95,115,111,117, + 114,99,101,7,3,0,0,115,14,0,0,0,0,2,10,1, + 2,1,14,1,16,1,4,1,28,1,122,23,83,111,117,114, + 99,101,76,111,97,100,101,114,46,103,101,116,95,115,111,117, + 114,99,101,114,89,0,0,0,41,1,218,9,95,111,112,116, + 105,109,105,122,101,99,3,0,0,0,1,0,0,0,4,0, + 0,0,8,0,0,0,67,0,0,0,115,22,0,0,0,116, + 0,106,1,116,2,124,1,124,2,100,1,100,2,124,3,100, + 3,141,6,83,0,41,4,122,130,82,101,116,117,114,110,32, + 116,104,101,32,99,111,100,101,32,111,98,106,101,99,116,32, + 99,111,109,112,105,108,101,100,32,102,114,111,109,32,115,111, + 117,114,99,101,46,10,10,32,32,32,32,32,32,32,32,84, + 104,101,32,39,100,97,116,97,39,32,97,114,103,117,109,101, + 110,116,32,99,97,110,32,98,101,32,97,110,121,32,111,98, + 106,101,99,116,32,116,121,112,101,32,116,104,97,116,32,99, + 111,109,112,105,108,101,40,41,32,115,117,112,112,111,114,116, + 115,46,10,32,32,32,32,32,32,32,32,114,190,0,0,0, + 84,41,2,218,12,100,111,110,116,95,105,110,104,101,114,105, + 116,114,70,0,0,0,41,3,114,116,0,0,0,114,189,0, + 0,0,218,7,99,111,109,112,105,108,101,41,4,114,102,0, + 0,0,114,54,0,0,0,114,35,0,0,0,114,203,0,0, + 0,114,2,0,0,0,114,2,0,0,0,114,4,0,0,0, + 218,14,115,111,117,114,99,101,95,116,111,95,99,111,100,101, + 17,3,0,0,115,4,0,0,0,0,5,12,1,122,27,83, + 111,117,114,99,101,76,111,97,100,101,114,46,115,111,117,114, + 99,101,95,116,111,95,99,111,100,101,99,2,0,0,0,0, + 0,0,0,15,0,0,0,9,0,0,0,67,0,0,0,115, + 46,2,0,0,124,0,160,0,124,1,161,1,125,2,100,1, + 125,3,100,1,125,4,100,1,125,5,100,2,125,6,100,3, + 125,7,121,12,116,1,124,2,131,1,125,8,87,0,110,26, + 4,0,116,2,107,10,114,68,1,0,1,0,1,0,100,1, + 125,8,89,0,144,1,110,48,88,0,121,14,124,0,160,3, + 124,2,161,1,125,9,87,0,110,22,4,0,116,4,107,10, + 114,106,1,0,1,0,1,0,89,0,144,1,110,10,88,0, + 116,5,124,9,100,4,25,0,131,1,125,3,121,14,124,0, + 160,6,124,8,161,1,125,10,87,0,110,20,4,0,116,4, + 107,10,114,154,1,0,1,0,1,0,89,0,110,218,88,0, + 124,1,124,8,100,5,156,2,125,11,121,148,116,7,124,10, + 124,1,124,11,131,3,125,12,116,8,124,10,131,1,100,6, + 100,1,133,2,25,0,125,13,124,12,100,7,64,0,100,8, + 107,3,125,6,124,6,144,1,114,36,124,12,100,9,64,0, + 100,8,107,3,125,7,116,9,106,10,100,10,107,3,144,1, + 114,56,124,7,115,254,116,9,106,10,100,11,107,2,144,1, + 114,56,124,0,160,6,124,2,161,1,125,4,116,9,160,11, + 116,12,124,4,161,2,125,5,116,13,124,10,124,5,124,1, + 124,11,131,4,1,0,110,20,116,14,124,10,124,3,124,9, + 100,12,25,0,124,1,124,11,131,5,1,0,87,0,110,26, + 4,0,116,15,116,16,102,2,107,10,144,1,114,84,1,0, + 1,0,1,0,89,0,110,32,88,0,116,17,160,18,100,13, + 124,8,124,2,161,3,1,0,116,19,124,13,124,1,124,8, + 124,2,100,14,141,4,83,0,124,4,100,1,107,8,144,1, + 114,136,124,0,160,6,124,2,161,1,125,4,124,0,160,20, + 124,4,124,2,161,2,125,14,116,17,160,18,100,15,124,2, + 161,2,1,0,116,21,106,22,144,2,115,42,124,8,100,1, + 107,9,144,2,114,42,124,3,100,1,107,9,144,2,114,42, + 124,6,144,1,114,228,124,5,100,1,107,8,144,1,114,214, + 116,9,160,11,124,4,161,1,125,5,116,23,124,14,124,5, + 124,7,131,3,125,10,110,16,116,24,124,14,124,3,116,25, + 124,4,131,1,131,3,125,10,121,30,124,0,160,26,124,2, + 124,8,124,10,161,3,1,0,116,17,160,18,100,16,124,8, + 161,2,1,0,87,0,110,22,4,0,116,2,107,10,144,2, + 114,40,1,0,1,0,1,0,89,0,110,2,88,0,124,14, + 83,0,41,17,122,190,67,111,110,99,114,101,116,101,32,105, + 109,112,108,101,109,101,110,116,97,116,105,111,110,32,111,102, + 32,73,110,115,112,101,99,116,76,111,97,100,101,114,46,103, + 101,116,95,99,111,100,101,46,10,10,32,32,32,32,32,32, + 32,32,82,101,97,100,105,110,103,32,111,102,32,98,121,116, + 101,99,111,100,101,32,114,101,113,117,105,114,101,115,32,112, + 97,116,104,95,115,116,97,116,115,32,116,111,32,98,101,32, + 105,109,112,108,101,109,101,110,116,101,100,46,32,84,111,32, + 119,114,105,116,101,10,32,32,32,32,32,32,32,32,98,121, + 116,101,99,111,100,101,44,32,115,101,116,95,100,97,116,97, + 32,109,117,115,116,32,97,108,115,111,32,98,101,32,105,109, + 112,108,101,109,101,110,116,101,100,46,10,10,32,32,32,32, + 32,32,32,32,78,70,84,114,149,0,0,0,41,2,114,100, + 0,0,0,114,35,0,0,0,114,126,0,0,0,114,29,0, + 0,0,114,60,0,0,0,114,57,0,0,0,90,5,110,101, + 118,101,114,90,6,97,108,119,97,121,115,218,4,115,105,122, + 101,122,13,123,125,32,109,97,116,99,104,101,115,32,123,125, + 41,3,114,100,0,0,0,114,91,0,0,0,114,92,0,0, + 0,122,19,99,111,100,101,32,111,98,106,101,99,116,32,102, + 114,111,109,32,123,125,122,10,119,114,111,116,101,32,123,33, + 114,125,41,27,114,159,0,0,0,114,81,0,0,0,114,68, + 0,0,0,114,197,0,0,0,114,40,0,0,0,114,14,0, + 0,0,114,200,0,0,0,114,133,0,0,0,218,10,109,101, + 109,111,114,121,118,105,101,119,114,143,0,0,0,90,21,99, + 104,101,99,107,95,104,97,115,104,95,98,97,115,101,100,95, + 112,121,99,115,114,138,0,0,0,218,17,95,82,65,87,95, + 77,65,71,73,67,95,78,85,77,66,69,82,114,139,0,0, + 0,114,137,0,0,0,114,101,0,0,0,114,131,0,0,0, + 114,116,0,0,0,114,130,0,0,0,114,145,0,0,0,114, + 206,0,0,0,114,6,0,0,0,218,19,100,111,110,116,95, + 119,114,105,116,101,95,98,121,116,101,99,111,100,101,114,152, + 0,0,0,114,150,0,0,0,114,31,0,0,0,114,199,0, + 0,0,41,15,114,102,0,0,0,114,121,0,0,0,114,92, + 0,0,0,114,135,0,0,0,114,155,0,0,0,114,138,0, + 0,0,90,10,104,97,115,104,95,98,97,115,101,100,90,12, + 99,104,101,99,107,95,115,111,117,114,99,101,114,91,0,0, + 0,218,2,115,116,114,54,0,0,0,114,132,0,0,0,114, + 69,0,0,0,90,10,98,121,116,101,115,95,100,97,116,97, + 90,11,99,111,100,101,95,111,98,106,101,99,116,114,2,0, + 0,0,114,2,0,0,0,114,4,0,0,0,114,188,0,0, + 0,25,3,0,0,115,134,0,0,0,0,7,10,1,4,1, + 4,1,4,1,4,1,4,1,2,1,12,1,14,1,12,2, + 2,1,14,1,14,1,8,2,12,1,2,1,14,1,14,1, + 6,3,2,1,8,2,2,1,12,1,16,1,12,1,6,1, + 12,1,12,1,4,1,12,1,10,1,4,1,2,1,6,2, + 8,1,8,2,2,1,2,1,2,1,6,1,2,1,10,2, + 20,1,6,2,8,1,6,1,6,1,2,1,8,1,10,1, + 10,1,12,1,12,1,18,1,10,1,6,1,10,1,10,1, + 14,2,6,1,10,1,2,1,14,1,16,1,16,1,6,1, + 122,21,83,111,117,114,99,101,76,111,97,100,101,114,46,103, + 101,116,95,99,111,100,101,78,41,10,114,107,0,0,0,114, + 106,0,0,0,114,108,0,0,0,114,196,0,0,0,114,197, + 0,0,0,114,199,0,0,0,114,198,0,0,0,114,202,0, + 0,0,114,206,0,0,0,114,188,0,0,0,114,2,0,0, + 0,114,2,0,0,0,114,2,0,0,0,114,4,0,0,0, + 114,195,0,0,0,223,2,0,0,115,14,0,0,0,8,2, + 8,8,8,13,8,10,8,7,8,10,14,8,114,195,0,0, + 0,99,0,0,0,0,0,0,0,0,0,0,0,0,4,0, + 0,0,0,0,0,0,115,124,0,0,0,101,0,90,1,100, + 0,90,2,100,1,90,3,100,2,100,3,132,0,90,4,100, + 4,100,5,132,0,90,5,100,6,100,7,132,0,90,6,101, + 7,135,0,102,1,100,8,100,9,132,8,131,1,90,8,101, + 7,100,10,100,11,132,0,131,1,90,9,100,12,100,13,132, + 0,90,10,101,7,100,14,100,15,132,0,131,1,90,11,100, + 16,100,17,132,0,90,12,100,18,100,19,132,0,90,13,100, + 20,100,21,132,0,90,14,100,22,100,23,132,0,90,15,135, + 0,4,0,90,16,83,0,41,24,218,10,70,105,108,101,76, + 111,97,100,101,114,122,103,66,97,115,101,32,102,105,108,101, + 32,108,111,97,100,101,114,32,99,108,97,115,115,32,119,104, + 105,99,104,32,105,109,112,108,101,109,101,110,116,115,32,116, + 104,101,32,108,111,97,100,101,114,32,112,114,111,116,111,99, + 111,108,32,109,101,116,104,111,100,115,32,116,104,97,116,10, + 32,32,32,32,114,101,113,117,105,114,101,32,102,105,108,101, + 32,115,121,115,116,101,109,32,117,115,97,103,101,46,99,3, + 0,0,0,0,0,0,0,3,0,0,0,2,0,0,0,67, + 0,0,0,115,16,0,0,0,124,1,124,0,95,0,124,2, + 124,0,95,1,100,1,83,0,41,2,122,75,67,97,99,104, + 101,32,116,104,101,32,109,111,100,117,108,101,32,110,97,109, + 101,32,97,110,100,32,116,104,101,32,112,97,116,104,32,116, + 111,32,116,104,101,32,102,105,108,101,32,102,111,117,110,100, + 32,98,121,32,116,104,101,10,32,32,32,32,32,32,32,32, + 102,105,110,100,101,114,46,78,41,2,114,100,0,0,0,114, + 35,0,0,0,41,3,114,102,0,0,0,114,121,0,0,0, + 114,35,0,0,0,114,2,0,0,0,114,2,0,0,0,114, + 4,0,0,0,114,186,0,0,0,116,3,0,0,115,4,0, + 0,0,0,3,6,1,122,19,70,105,108,101,76,111,97,100, + 101,114,46,95,95,105,110,105,116,95,95,99,2,0,0,0, + 0,0,0,0,2,0,0,0,2,0,0,0,67,0,0,0, + 115,24,0,0,0,124,0,106,0,124,1,106,0,107,2,111, + 22,124,0,106,1,124,1,106,1,107,2,83,0,41,1,78, + 41,2,218,9,95,95,99,108,97,115,115,95,95,114,113,0, + 0,0,41,2,114,102,0,0,0,218,5,111,116,104,101,114, + 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,218, + 6,95,95,101,113,95,95,122,3,0,0,115,4,0,0,0, + 0,1,12,1,122,17,70,105,108,101,76,111,97,100,101,114, + 46,95,95,101,113,95,95,99,1,0,0,0,0,0,0,0, + 1,0,0,0,3,0,0,0,67,0,0,0,115,20,0,0, + 0,116,0,124,0,106,1,131,1,116,0,124,0,106,2,131, + 1,65,0,83,0,41,1,78,41,3,218,4,104,97,115,104, + 114,100,0,0,0,114,35,0,0,0,41,1,114,102,0,0, 0,114,2,0,0,0,114,2,0,0,0,114,4,0,0,0, - 218,8,99,111,110,116,101,110,116,115,173,3,0,0,115,2, + 218,8,95,95,104,97,115,104,95,95,126,3,0,0,115,2, 0,0,0,0,1,122,19,70,105,108,101,76,111,97,100,101, - 114,46,99,111,110,116,101,110,116,115,41,17,114,107,0,0, - 0,114,106,0,0,0,114,108,0,0,0,114,109,0,0,0, - 114,186,0,0,0,114,215,0,0,0,114,217,0,0,0,114, - 118,0,0,0,114,194,0,0,0,114,159,0,0,0,114,200, - 0,0,0,114,220,0,0,0,114,222,0,0,0,114,225,0, - 0,0,114,223,0,0,0,114,228,0,0,0,90,13,95,95, - 99,108,97,115,115,99,101,108,108,95,95,114,2,0,0,0, - 114,2,0,0,0,41,1,114,213,0,0,0,114,4,0,0, - 0,114,212,0,0,0,109,3,0,0,115,22,0,0,0,12, - 5,8,6,8,4,8,3,16,12,12,5,8,7,12,6,8, - 4,8,6,8,6,114,212,0,0,0,99,0,0,0,0,0, - 0,0,0,0,0,0,0,3,0,0,0,64,0,0,0,115, - 46,0,0,0,101,0,90,1,100,0,90,2,100,1,90,3, - 100,2,100,3,132,0,90,4,100,4,100,5,132,0,90,5, - 100,6,100,7,156,1,100,8,100,9,132,2,90,6,100,10, - 83,0,41,11,218,16,83,111,117,114,99,101,70,105,108,101, - 76,111,97,100,101,114,122,62,67,111,110,99,114,101,116,101, - 32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32, - 111,102,32,83,111,117,114,99,101,76,111,97,100,101,114,32, - 117,115,105,110,103,32,116,104,101,32,102,105,108,101,32,115, - 121,115,116,101,109,46,99,2,0,0,0,0,0,0,0,3, - 0,0,0,3,0,0,0,67,0,0,0,115,22,0,0,0, - 116,0,124,1,131,1,125,2,124,2,106,1,124,2,106,2, - 100,1,156,2,83,0,41,2,122,33,82,101,116,117,114,110, - 32,116,104,101,32,109,101,116,97,100,97,116,97,32,102,111, - 114,32,116,104,101,32,112,97,116,104,46,41,2,114,149,0, - 0,0,114,207,0,0,0,41,3,114,39,0,0,0,218,8, - 115,116,95,109,116,105,109,101,90,7,115,116,95,115,105,122, - 101,41,3,114,102,0,0,0,114,35,0,0,0,114,211,0, - 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, - 0,114,197,0,0,0,181,3,0,0,115,4,0,0,0,0, - 2,8,1,122,27,83,111,117,114,99,101,70,105,108,101,76, - 111,97,100,101,114,46,112,97,116,104,95,115,116,97,116,115, - 99,4,0,0,0,0,0,0,0,5,0,0,0,5,0,0, - 0,67,0,0,0,115,24,0,0,0,116,0,124,1,131,1, - 125,4,124,0,106,1,124,2,124,3,124,4,100,1,141,3, - 83,0,41,2,78,41,1,218,5,95,109,111,100,101,41,2, - 114,99,0,0,0,114,198,0,0,0,41,5,114,102,0,0, - 0,114,92,0,0,0,114,91,0,0,0,114,54,0,0,0, - 114,42,0,0,0,114,2,0,0,0,114,2,0,0,0,114, - 4,0,0,0,114,199,0,0,0,186,3,0,0,115,4,0, - 0,0,0,2,8,1,122,32,83,111,117,114,99,101,70,105, - 108,101,76,111,97,100,101,114,46,95,99,97,99,104,101,95, - 98,121,116,101,99,111,100,101,105,182,1,0,0,41,1,114, - 231,0,0,0,99,3,0,0,0,1,0,0,0,9,0,0, - 0,11,0,0,0,67,0,0,0,115,250,0,0,0,116,0, - 124,1,131,1,92,2,125,4,125,5,103,0,125,6,120,38, - 124,4,114,54,116,1,124,4,131,1,115,54,116,0,124,4, - 131,1,92,2,125,4,125,7,124,6,160,2,124,7,161,1, - 1,0,113,18,87,0,120,110,116,3,124,6,131,1,68,0, - 93,98,125,7,116,4,124,4,124,7,131,2,125,4,121,14, - 116,5,160,6,124,4,161,1,1,0,87,0,113,66,4,0, - 116,7,107,10,114,116,1,0,1,0,1,0,119,66,89,0, - 113,66,4,0,116,8,107,10,114,162,1,0,125,8,1,0, - 122,18,116,9,160,10,100,1,124,4,124,8,161,3,1,0, - 100,2,83,0,100,2,125,8,126,8,88,0,89,0,113,66, - 88,0,113,66,87,0,121,28,116,11,124,1,124,2,124,3, - 131,3,1,0,116,9,160,10,100,3,124,1,161,2,1,0, - 87,0,110,48,4,0,116,8,107,10,114,244,1,0,125,8, - 1,0,122,18,116,9,160,10,100,1,124,1,124,8,161,3, - 1,0,87,0,100,2,100,2,125,8,126,8,88,0,89,0, - 110,2,88,0,100,2,83,0,41,4,122,27,87,114,105,116, - 101,32,98,121,116,101,115,32,100,97,116,97,32,116,111,32, - 97,32,102,105,108,101,46,122,27,99,111,117,108,100,32,110, - 111,116,32,99,114,101,97,116,101,32,123,33,114,125,58,32, - 123,33,114,125,78,122,12,99,114,101,97,116,101,100,32,123, - 33,114,125,41,12,114,38,0,0,0,114,46,0,0,0,114, - 165,0,0,0,114,33,0,0,0,114,28,0,0,0,114,1, - 0,0,0,90,5,109,107,100,105,114,218,15,70,105,108,101, - 69,120,105,115,116,115,69,114,114,111,114,114,40,0,0,0, - 114,116,0,0,0,114,130,0,0,0,114,56,0,0,0,41, - 9,114,102,0,0,0,114,35,0,0,0,114,54,0,0,0, - 114,231,0,0,0,218,6,112,97,114,101,110,116,114,96,0, - 0,0,114,27,0,0,0,114,23,0,0,0,114,201,0,0, + 114,46,95,95,104,97,115,104,95,95,99,2,0,0,0,0, + 0,0,0,2,0,0,0,3,0,0,0,3,0,0,0,115, + 16,0,0,0,116,0,116,1,124,0,131,2,160,2,124,1, + 161,1,83,0,41,1,122,100,76,111,97,100,32,97,32,109, + 111,100,117,108,101,32,102,114,111,109,32,97,32,102,105,108, + 101,46,10,10,32,32,32,32,32,32,32,32,84,104,105,115, + 32,109,101,116,104,111,100,32,105,115,32,100,101,112,114,101, + 99,97,116,101,100,46,32,32,85,115,101,32,101,120,101,99, + 95,109,111,100,117,108,101,40,41,32,105,110,115,116,101,97, + 100,46,10,10,32,32,32,32,32,32,32,32,41,3,218,5, + 115,117,112,101,114,114,212,0,0,0,114,194,0,0,0,41, + 2,114,102,0,0,0,114,121,0,0,0,41,1,114,213,0, + 0,0,114,2,0,0,0,114,4,0,0,0,114,194,0,0, + 0,129,3,0,0,115,2,0,0,0,0,10,122,22,70,105, + 108,101,76,111,97,100,101,114,46,108,111,97,100,95,109,111, + 100,117,108,101,99,2,0,0,0,0,0,0,0,2,0,0, + 0,1,0,0,0,67,0,0,0,115,6,0,0,0,124,0, + 106,0,83,0,41,1,122,58,82,101,116,117,114,110,32,116, + 104,101,32,112,97,116,104,32,116,111,32,116,104,101,32,115, + 111,117,114,99,101,32,102,105,108,101,32,97,115,32,102,111, + 117,110,100,32,98,121,32,116,104,101,32,102,105,110,100,101, + 114,46,41,1,114,35,0,0,0,41,2,114,102,0,0,0, + 114,121,0,0,0,114,2,0,0,0,114,2,0,0,0,114, + 4,0,0,0,114,159,0,0,0,141,3,0,0,115,2,0, + 0,0,0,3,122,23,70,105,108,101,76,111,97,100,101,114, + 46,103,101,116,95,102,105,108,101,110,97,109,101,99,2,0, + 0,0,0,0,0,0,3,0,0,0,9,0,0,0,67,0, + 0,0,115,32,0,0,0,116,0,160,1,124,1,100,1,161, + 2,143,10,125,2,124,2,160,2,161,0,83,0,81,0,82, + 0,88,0,100,2,83,0,41,3,122,39,82,101,116,117,114, + 110,32,116,104,101,32,100,97,116,97,32,102,114,111,109,32, + 112,97,116,104,32,97,115,32,114,97,119,32,98,121,116,101, + 115,46,218,1,114,78,41,3,114,50,0,0,0,114,51,0, + 0,0,90,4,114,101,97,100,41,3,114,102,0,0,0,114, + 35,0,0,0,114,55,0,0,0,114,2,0,0,0,114,2, + 0,0,0,114,4,0,0,0,114,200,0,0,0,146,3,0, + 0,115,4,0,0,0,0,2,14,1,122,19,70,105,108,101, + 76,111,97,100,101,114,46,103,101,116,95,100,97,116,97,99, + 2,0,0,0,0,0,0,0,2,0,0,0,3,0,0,0, + 67,0,0,0,115,18,0,0,0,124,0,160,0,124,1,161, + 1,114,14,124,0,83,0,100,0,83,0,41,1,78,41,1, + 114,161,0,0,0,41,2,114,102,0,0,0,114,191,0,0, 0,114,2,0,0,0,114,2,0,0,0,114,4,0,0,0, - 114,198,0,0,0,191,3,0,0,115,42,0,0,0,0,2, - 12,1,4,2,14,1,12,1,14,2,14,1,10,1,2,1, - 14,1,14,2,6,1,16,3,6,1,8,1,22,1,2,1, - 12,1,16,1,16,2,8,1,122,25,83,111,117,114,99,101, - 70,105,108,101,76,111,97,100,101,114,46,115,101,116,95,100, - 97,116,97,78,41,7,114,107,0,0,0,114,106,0,0,0, - 114,108,0,0,0,114,109,0,0,0,114,197,0,0,0,114, - 199,0,0,0,114,198,0,0,0,114,2,0,0,0,114,2, - 0,0,0,114,2,0,0,0,114,4,0,0,0,114,229,0, - 0,0,177,3,0,0,115,6,0,0,0,12,4,8,5,8, - 5,114,229,0,0,0,99,0,0,0,0,0,0,0,0,0, - 0,0,0,2,0,0,0,64,0,0,0,115,32,0,0,0, - 101,0,90,1,100,0,90,2,100,1,90,3,100,2,100,3, - 132,0,90,4,100,4,100,5,132,0,90,5,100,6,83,0, - 41,7,218,20,83,111,117,114,99,101,108,101,115,115,70,105, - 108,101,76,111,97,100,101,114,122,45,76,111,97,100,101,114, - 32,119,104,105,99,104,32,104,97,110,100,108,101,115,32,115, - 111,117,114,99,101,108,101,115,115,32,102,105,108,101,32,105, - 109,112,111,114,116,115,46,99,2,0,0,0,0,0,0,0, - 5,0,0,0,5,0,0,0,67,0,0,0,115,68,0,0, - 0,124,0,160,0,124,1,161,1,125,2,124,0,160,1,124, - 2,161,1,125,3,124,1,124,2,100,1,156,2,125,4,116, - 2,124,3,124,1,124,4,131,3,1,0,116,3,116,4,124, - 3,131,1,100,2,100,0,133,2,25,0,124,1,124,2,100, - 3,141,3,83,0,41,4,78,41,2,114,100,0,0,0,114, - 35,0,0,0,114,126,0,0,0,41,2,114,100,0,0,0, - 114,91,0,0,0,41,5,114,159,0,0,0,114,200,0,0, - 0,114,133,0,0,0,114,145,0,0,0,114,208,0,0,0, - 41,5,114,102,0,0,0,114,121,0,0,0,114,35,0,0, - 0,114,54,0,0,0,114,132,0,0,0,114,2,0,0,0, - 114,2,0,0,0,114,4,0,0,0,114,188,0,0,0,226, - 3,0,0,115,18,0,0,0,0,1,10,1,10,4,2,1, - 8,2,12,1,2,1,14,1,2,1,122,29,83,111,117,114, - 99,101,108,101,115,115,70,105,108,101,76,111,97,100,101,114, - 46,103,101,116,95,99,111,100,101,99,2,0,0,0,0,0, - 0,0,2,0,0,0,1,0,0,0,67,0,0,0,115,4, - 0,0,0,100,1,83,0,41,2,122,39,82,101,116,117,114, - 110,32,78,111,110,101,32,97,115,32,116,104,101,114,101,32, - 105,115,32,110,111,32,115,111,117,114,99,101,32,99,111,100, - 101,46,78,114,2,0,0,0,41,2,114,102,0,0,0,114, - 121,0,0,0,114,2,0,0,0,114,2,0,0,0,114,4, - 0,0,0,114,202,0,0,0,242,3,0,0,115,2,0,0, - 0,0,2,122,31,83,111,117,114,99,101,108,101,115,115,70, - 105,108,101,76,111,97,100,101,114,46,103,101,116,95,115,111, - 117,114,99,101,78,41,6,114,107,0,0,0,114,106,0,0, - 0,114,108,0,0,0,114,109,0,0,0,114,188,0,0,0, - 114,202,0,0,0,114,2,0,0,0,114,2,0,0,0,114, - 2,0,0,0,114,4,0,0,0,114,234,0,0,0,222,3, - 0,0,115,4,0,0,0,12,4,8,16,114,234,0,0,0, - 99,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0, - 0,64,0,0,0,115,92,0,0,0,101,0,90,1,100,0, - 90,2,100,1,90,3,100,2,100,3,132,0,90,4,100,4, - 100,5,132,0,90,5,100,6,100,7,132,0,90,6,100,8, - 100,9,132,0,90,7,100,10,100,11,132,0,90,8,100,12, - 100,13,132,0,90,9,100,14,100,15,132,0,90,10,100,16, - 100,17,132,0,90,11,101,12,100,18,100,19,132,0,131,1, - 90,13,100,20,83,0,41,21,218,19,69,120,116,101,110,115, - 105,111,110,70,105,108,101,76,111,97,100,101,114,122,93,76, - 111,97,100,101,114,32,102,111,114,32,101,120,116,101,110,115, - 105,111,110,32,109,111,100,117,108,101,115,46,10,10,32,32, - 32,32,84,104,101,32,99,111,110,115,116,114,117,99,116,111, - 114,32,105,115,32,100,101,115,105,103,110,101,100,32,116,111, - 32,119,111,114,107,32,119,105,116,104,32,70,105,108,101,70, - 105,110,100,101,114,46,10,10,32,32,32,32,99,3,0,0, - 0,0,0,0,0,3,0,0,0,2,0,0,0,67,0,0, - 0,115,16,0,0,0,124,1,124,0,95,0,124,2,124,0, - 95,1,100,0,83,0,41,1,78,41,2,114,100,0,0,0, - 114,35,0,0,0,41,3,114,102,0,0,0,114,100,0,0, - 0,114,35,0,0,0,114,2,0,0,0,114,2,0,0,0, - 114,4,0,0,0,114,186,0,0,0,3,4,0,0,115,4, - 0,0,0,0,1,6,1,122,28,69,120,116,101,110,115,105, - 111,110,70,105,108,101,76,111,97,100,101,114,46,95,95,105, - 110,105,116,95,95,99,2,0,0,0,0,0,0,0,2,0, - 0,0,2,0,0,0,67,0,0,0,115,24,0,0,0,124, - 0,106,0,124,1,106,0,107,2,111,22,124,0,106,1,124, - 1,106,1,107,2,83,0,41,1,78,41,2,114,213,0,0, - 0,114,113,0,0,0,41,2,114,102,0,0,0,114,214,0, - 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, - 0,114,215,0,0,0,7,4,0,0,115,4,0,0,0,0, - 1,12,1,122,26,69,120,116,101,110,115,105,111,110,70,105, - 108,101,76,111,97,100,101,114,46,95,95,101,113,95,95,99, - 1,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0, - 67,0,0,0,115,20,0,0,0,116,0,124,0,106,1,131, - 1,116,0,124,0,106,2,131,1,65,0,83,0,41,1,78, - 41,3,114,216,0,0,0,114,100,0,0,0,114,35,0,0, - 0,41,1,114,102,0,0,0,114,2,0,0,0,114,2,0, - 0,0,114,4,0,0,0,114,217,0,0,0,11,4,0,0, - 115,2,0,0,0,0,1,122,28,69,120,116,101,110,115,105, - 111,110,70,105,108,101,76,111,97,100,101,114,46,95,95,104, - 97,115,104,95,95,99,2,0,0,0,0,0,0,0,3,0, - 0,0,5,0,0,0,67,0,0,0,115,36,0,0,0,116, - 0,160,1,116,2,106,3,124,1,161,2,125,2,116,0,160, - 4,100,1,124,1,106,5,124,0,106,6,161,3,1,0,124, - 2,83,0,41,2,122,38,67,114,101,97,116,101,32,97,110, - 32,117,110,105,116,105,97,108,105,122,101,100,32,101,120,116, - 101,110,115,105,111,110,32,109,111,100,117,108,101,122,38,101, - 120,116,101,110,115,105,111,110,32,109,111,100,117,108,101,32, - 123,33,114,125,32,108,111,97,100,101,100,32,102,114,111,109, - 32,123,33,114,125,41,7,114,116,0,0,0,114,189,0,0, - 0,114,143,0,0,0,90,14,99,114,101,97,116,101,95,100, - 121,110,97,109,105,99,114,130,0,0,0,114,100,0,0,0, - 114,35,0,0,0,41,3,114,102,0,0,0,114,166,0,0, - 0,114,191,0,0,0,114,2,0,0,0,114,2,0,0,0, - 114,4,0,0,0,114,187,0,0,0,14,4,0,0,115,10, - 0,0,0,0,2,4,1,10,1,6,1,12,1,122,33,69, - 120,116,101,110,115,105,111,110,70,105,108,101,76,111,97,100, - 101,114,46,99,114,101,97,116,101,95,109,111,100,117,108,101, - 99,2,0,0,0,0,0,0,0,2,0,0,0,5,0,0, - 0,67,0,0,0,115,36,0,0,0,116,0,160,1,116,2, - 106,3,124,1,161,2,1,0,116,0,160,4,100,1,124,0, - 106,5,124,0,106,6,161,3,1,0,100,2,83,0,41,3, - 122,30,73,110,105,116,105,97,108,105,122,101,32,97,110,32, - 101,120,116,101,110,115,105,111,110,32,109,111,100,117,108,101, - 122,40,101,120,116,101,110,115,105,111,110,32,109,111,100,117, - 108,101,32,123,33,114,125,32,101,120,101,99,117,116,101,100, - 32,102,114,111,109,32,123,33,114,125,78,41,7,114,116,0, - 0,0,114,189,0,0,0,114,143,0,0,0,90,12,101,120, - 101,99,95,100,121,110,97,109,105,99,114,130,0,0,0,114, - 100,0,0,0,114,35,0,0,0,41,2,114,102,0,0,0, - 114,191,0,0,0,114,2,0,0,0,114,2,0,0,0,114, - 4,0,0,0,114,192,0,0,0,22,4,0,0,115,6,0, - 0,0,0,2,14,1,6,1,122,31,69,120,116,101,110,115, - 105,111,110,70,105,108,101,76,111,97,100,101,114,46,101,120, - 101,99,95,109,111,100,117,108,101,99,2,0,0,0,0,0, - 0,0,2,0,0,0,4,0,0,0,3,0,0,0,115,36, - 0,0,0,116,0,124,0,106,1,131,1,100,1,25,0,137, - 0,116,2,135,0,102,1,100,2,100,3,132,8,116,3,68, - 0,131,1,131,1,83,0,41,4,122,49,82,101,116,117,114, - 110,32,84,114,117,101,32,105,102,32,116,104,101,32,101,120, - 116,101,110,115,105,111,110,32,109,111,100,117,108,101,32,105, - 115,32,97,32,112,97,99,107,97,103,101,46,114,29,0,0, - 0,99,1,0,0,0,0,0,0,0,2,0,0,0,4,0, - 0,0,51,0,0,0,115,26,0,0,0,124,0,93,18,125, - 1,136,0,100,0,124,1,23,0,107,2,86,0,1,0,113, - 2,100,1,83,0,41,2,114,186,0,0,0,78,114,2,0, - 0,0,41,2,114,22,0,0,0,218,6,115,117,102,102,105, - 120,41,1,218,9,102,105,108,101,95,110,97,109,101,114,2, - 0,0,0,114,4,0,0,0,250,9,60,103,101,110,101,120, - 112,114,62,31,4,0,0,115,2,0,0,0,4,1,122,49, - 69,120,116,101,110,115,105,111,110,70,105,108,101,76,111,97, - 100,101,114,46,105,115,95,112,97,99,107,97,103,101,46,60, - 108,111,99,97,108,115,62,46,60,103,101,110,101,120,112,114, - 62,41,4,114,38,0,0,0,114,35,0,0,0,218,3,97, - 110,121,218,18,69,88,84,69,78,83,73,79,78,95,83,85, - 70,70,73,88,69,83,41,2,114,102,0,0,0,114,121,0, - 0,0,114,2,0,0,0,41,1,114,237,0,0,0,114,4, - 0,0,0,114,161,0,0,0,28,4,0,0,115,6,0,0, - 0,0,2,14,1,12,1,122,30,69,120,116,101,110,115,105, - 111,110,70,105,108,101,76,111,97,100,101,114,46,105,115,95, - 112,97,99,107,97,103,101,99,2,0,0,0,0,0,0,0, - 2,0,0,0,1,0,0,0,67,0,0,0,115,4,0,0, - 0,100,1,83,0,41,2,122,63,82,101,116,117,114,110,32, - 78,111,110,101,32,97,115,32,97,110,32,101,120,116,101,110, - 115,105,111,110,32,109,111,100,117,108,101,32,99,97,110,110, - 111,116,32,99,114,101,97,116,101,32,97,32,99,111,100,101, - 32,111,98,106,101,99,116,46,78,114,2,0,0,0,41,2, - 114,102,0,0,0,114,121,0,0,0,114,2,0,0,0,114, - 2,0,0,0,114,4,0,0,0,114,188,0,0,0,34,4, - 0,0,115,2,0,0,0,0,2,122,28,69,120,116,101,110, - 115,105,111,110,70,105,108,101,76,111,97,100,101,114,46,103, - 101,116,95,99,111,100,101,99,2,0,0,0,0,0,0,0, - 2,0,0,0,1,0,0,0,67,0,0,0,115,4,0,0, - 0,100,1,83,0,41,2,122,53,82,101,116,117,114,110,32, - 78,111,110,101,32,97,115,32,101,120,116,101,110,115,105,111, - 110,32,109,111,100,117,108,101,115,32,104,97,118,101,32,110, + 218,19,103,101,116,95,114,101,115,111,117,114,99,101,95,114, + 101,97,100,101,114,153,3,0,0,115,6,0,0,0,0,2, + 10,1,4,1,122,30,70,105,108,101,76,111,97,100,101,114, + 46,103,101,116,95,114,101,115,111,117,114,99,101,95,114,101, + 97,100,101,114,99,2,0,0,0,0,0,0,0,3,0,0, + 0,4,0,0,0,67,0,0,0,115,32,0,0,0,116,0, + 116,1,124,0,106,2,131,1,100,1,25,0,124,1,131,2, + 125,2,116,3,160,4,124,2,100,2,161,2,83,0,41,3, + 78,114,60,0,0,0,114,219,0,0,0,41,5,114,28,0, + 0,0,114,38,0,0,0,114,35,0,0,0,114,50,0,0, + 0,114,51,0,0,0,41,3,114,102,0,0,0,218,8,114, + 101,115,111,117,114,99,101,114,35,0,0,0,114,2,0,0, + 0,114,2,0,0,0,114,4,0,0,0,218,13,111,112,101, + 110,95,114,101,115,111,117,114,99,101,159,3,0,0,115,4, + 0,0,0,0,1,20,1,122,24,70,105,108,101,76,111,97, + 100,101,114,46,111,112,101,110,95,114,101,115,111,117,114,99, + 101,99,2,0,0,0,0,0,0,0,3,0,0,0,3,0, + 0,0,67,0,0,0,115,38,0,0,0,124,0,160,0,124, + 1,161,1,115,14,116,1,130,1,116,2,116,3,124,0,106, + 4,131,1,100,1,25,0,124,1,131,2,125,2,124,2,83, + 0,41,2,78,114,60,0,0,0,41,5,218,11,105,115,95, + 114,101,115,111,117,114,99,101,218,17,70,105,108,101,78,111, + 116,70,111,117,110,100,69,114,114,111,114,114,28,0,0,0, + 114,38,0,0,0,114,35,0,0,0,41,3,114,102,0,0, + 0,114,221,0,0,0,114,35,0,0,0,114,2,0,0,0, + 114,2,0,0,0,114,4,0,0,0,218,13,114,101,115,111, + 117,114,99,101,95,112,97,116,104,163,3,0,0,115,8,0, + 0,0,0,1,10,1,4,1,20,1,122,24,70,105,108,101, + 76,111,97,100,101,114,46,114,101,115,111,117,114,99,101,95, + 112,97,116,104,99,2,0,0,0,0,0,0,0,3,0,0, + 0,3,0,0,0,67,0,0,0,115,40,0,0,0,116,0, + 124,1,107,6,114,12,100,1,83,0,116,1,116,2,124,0, + 106,3,131,1,100,2,25,0,124,1,131,2,125,2,116,4, + 124,2,131,1,83,0,41,3,78,70,114,60,0,0,0,41, + 5,114,25,0,0,0,114,28,0,0,0,114,38,0,0,0, + 114,35,0,0,0,114,44,0,0,0,41,3,114,102,0,0, + 0,114,100,0,0,0,114,35,0,0,0,114,2,0,0,0, + 114,2,0,0,0,114,4,0,0,0,114,223,0,0,0,169, + 3,0,0,115,8,0,0,0,0,1,8,1,4,1,20,1, + 122,22,70,105,108,101,76,111,97,100,101,114,46,105,115,95, + 114,101,115,111,117,114,99,101,99,1,0,0,0,0,0,0, + 0,1,0,0,0,5,0,0,0,67,0,0,0,115,24,0, + 0,0,116,0,116,1,160,2,116,3,124,0,106,4,131,1, + 100,1,25,0,161,1,131,1,83,0,41,2,78,114,60,0, + 0,0,41,5,218,4,105,116,101,114,114,1,0,0,0,218, + 7,108,105,115,116,100,105,114,114,38,0,0,0,114,35,0, + 0,0,41,1,114,102,0,0,0,114,2,0,0,0,114,2, + 0,0,0,114,4,0,0,0,218,8,99,111,110,116,101,110, + 116,115,175,3,0,0,115,2,0,0,0,0,1,122,19,70, + 105,108,101,76,111,97,100,101,114,46,99,111,110,116,101,110, + 116,115,41,17,114,107,0,0,0,114,106,0,0,0,114,108, + 0,0,0,114,109,0,0,0,114,186,0,0,0,114,215,0, + 0,0,114,217,0,0,0,114,118,0,0,0,114,194,0,0, + 0,114,159,0,0,0,114,200,0,0,0,114,220,0,0,0, + 114,222,0,0,0,114,225,0,0,0,114,223,0,0,0,114, + 228,0,0,0,90,13,95,95,99,108,97,115,115,99,101,108, + 108,95,95,114,2,0,0,0,114,2,0,0,0,41,1,114, + 213,0,0,0,114,4,0,0,0,114,212,0,0,0,111,3, + 0,0,115,24,0,0,0,8,3,4,2,8,6,8,4,8, + 3,16,12,12,5,8,7,12,6,8,4,8,6,8,6,114, + 212,0,0,0,99,0,0,0,0,0,0,0,0,0,0,0, + 0,3,0,0,0,64,0,0,0,115,46,0,0,0,101,0, + 90,1,100,0,90,2,100,1,90,3,100,2,100,3,132,0, + 90,4,100,4,100,5,132,0,90,5,100,6,100,7,156,1, + 100,8,100,9,132,2,90,6,100,10,83,0,41,11,218,16, + 83,111,117,114,99,101,70,105,108,101,76,111,97,100,101,114, + 122,62,67,111,110,99,114,101,116,101,32,105,109,112,108,101, + 109,101,110,116,97,116,105,111,110,32,111,102,32,83,111,117, + 114,99,101,76,111,97,100,101,114,32,117,115,105,110,103,32, + 116,104,101,32,102,105,108,101,32,115,121,115,116,101,109,46, + 99,2,0,0,0,0,0,0,0,3,0,0,0,3,0,0, + 0,67,0,0,0,115,22,0,0,0,116,0,124,1,131,1, + 125,2,124,2,106,1,124,2,106,2,100,1,156,2,83,0, + 41,2,122,33,82,101,116,117,114,110,32,116,104,101,32,109, + 101,116,97,100,97,116,97,32,102,111,114,32,116,104,101,32, + 112,97,116,104,46,41,2,114,149,0,0,0,114,207,0,0, + 0,41,3,114,39,0,0,0,218,8,115,116,95,109,116,105, + 109,101,90,7,115,116,95,115,105,122,101,41,3,114,102,0, + 0,0,114,35,0,0,0,114,211,0,0,0,114,2,0,0, + 0,114,2,0,0,0,114,4,0,0,0,114,197,0,0,0, + 183,3,0,0,115,4,0,0,0,0,2,8,1,122,27,83, + 111,117,114,99,101,70,105,108,101,76,111,97,100,101,114,46, + 112,97,116,104,95,115,116,97,116,115,99,4,0,0,0,0, + 0,0,0,5,0,0,0,5,0,0,0,67,0,0,0,115, + 24,0,0,0,116,0,124,1,131,1,125,4,124,0,106,1, + 124,2,124,3,124,4,100,1,141,3,83,0,41,2,78,41, + 1,218,5,95,109,111,100,101,41,2,114,99,0,0,0,114, + 198,0,0,0,41,5,114,102,0,0,0,114,92,0,0,0, + 114,91,0,0,0,114,54,0,0,0,114,42,0,0,0,114, + 2,0,0,0,114,2,0,0,0,114,4,0,0,0,114,199, + 0,0,0,188,3,0,0,115,4,0,0,0,0,2,8,1, + 122,32,83,111,117,114,99,101,70,105,108,101,76,111,97,100, + 101,114,46,95,99,97,99,104,101,95,98,121,116,101,99,111, + 100,101,105,182,1,0,0,41,1,114,231,0,0,0,99,3, + 0,0,0,1,0,0,0,9,0,0,0,11,0,0,0,67, + 0,0,0,115,250,0,0,0,116,0,124,1,131,1,92,2, + 125,4,125,5,103,0,125,6,120,38,124,4,114,54,116,1, + 124,4,131,1,115,54,116,0,124,4,131,1,92,2,125,4, + 125,7,124,6,160,2,124,7,161,1,1,0,113,18,87,0, + 120,110,116,3,124,6,131,1,68,0,93,98,125,7,116,4, + 124,4,124,7,131,2,125,4,121,14,116,5,160,6,124,4, + 161,1,1,0,87,0,113,66,4,0,116,7,107,10,114,116, + 1,0,1,0,1,0,119,66,89,0,113,66,4,0,116,8, + 107,10,114,162,1,0,125,8,1,0,122,18,116,9,160,10, + 100,1,124,4,124,8,161,3,1,0,100,2,83,0,100,2, + 125,8,126,8,88,0,89,0,113,66,88,0,113,66,87,0, + 121,28,116,11,124,1,124,2,124,3,131,3,1,0,116,9, + 160,10,100,3,124,1,161,2,1,0,87,0,110,48,4,0, + 116,8,107,10,114,244,1,0,125,8,1,0,122,18,116,9, + 160,10,100,1,124,1,124,8,161,3,1,0,87,0,100,2, + 100,2,125,8,126,8,88,0,89,0,110,2,88,0,100,2, + 83,0,41,4,122,27,87,114,105,116,101,32,98,121,116,101, + 115,32,100,97,116,97,32,116,111,32,97,32,102,105,108,101, + 46,122,27,99,111,117,108,100,32,110,111,116,32,99,114,101, + 97,116,101,32,123,33,114,125,58,32,123,33,114,125,78,122, + 12,99,114,101,97,116,101,100,32,123,33,114,125,41,12,114, + 38,0,0,0,114,46,0,0,0,114,165,0,0,0,114,33, + 0,0,0,114,28,0,0,0,114,1,0,0,0,90,5,109, + 107,100,105,114,218,15,70,105,108,101,69,120,105,115,116,115, + 69,114,114,111,114,114,40,0,0,0,114,116,0,0,0,114, + 130,0,0,0,114,56,0,0,0,41,9,114,102,0,0,0, + 114,35,0,0,0,114,54,0,0,0,114,231,0,0,0,218, + 6,112,97,114,101,110,116,114,96,0,0,0,114,27,0,0, + 0,114,23,0,0,0,114,201,0,0,0,114,2,0,0,0, + 114,2,0,0,0,114,4,0,0,0,114,198,0,0,0,193, + 3,0,0,115,42,0,0,0,0,2,12,1,4,2,14,1, + 12,1,14,2,14,1,10,1,2,1,14,1,14,2,6,1, + 16,3,6,1,8,1,22,1,2,1,12,1,16,1,16,2, + 8,1,122,25,83,111,117,114,99,101,70,105,108,101,76,111, + 97,100,101,114,46,115,101,116,95,100,97,116,97,78,41,7, + 114,107,0,0,0,114,106,0,0,0,114,108,0,0,0,114, + 109,0,0,0,114,197,0,0,0,114,199,0,0,0,114,198, + 0,0,0,114,2,0,0,0,114,2,0,0,0,114,2,0, + 0,0,114,4,0,0,0,114,229,0,0,0,179,3,0,0, + 115,8,0,0,0,8,2,4,2,8,5,8,5,114,229,0, + 0,0,99,0,0,0,0,0,0,0,0,0,0,0,0,2, + 0,0,0,64,0,0,0,115,32,0,0,0,101,0,90,1, + 100,0,90,2,100,1,90,3,100,2,100,3,132,0,90,4, + 100,4,100,5,132,0,90,5,100,6,83,0,41,7,218,20, + 83,111,117,114,99,101,108,101,115,115,70,105,108,101,76,111, + 97,100,101,114,122,45,76,111,97,100,101,114,32,119,104,105, + 99,104,32,104,97,110,100,108,101,115,32,115,111,117,114,99, + 101,108,101,115,115,32,102,105,108,101,32,105,109,112,111,114, + 116,115,46,99,2,0,0,0,0,0,0,0,5,0,0,0, + 5,0,0,0,67,0,0,0,115,68,0,0,0,124,0,160, + 0,124,1,161,1,125,2,124,0,160,1,124,2,161,1,125, + 3,124,1,124,2,100,1,156,2,125,4,116,2,124,3,124, + 1,124,4,131,3,1,0,116,3,116,4,124,3,131,1,100, + 2,100,0,133,2,25,0,124,1,124,2,100,3,141,3,83, + 0,41,4,78,41,2,114,100,0,0,0,114,35,0,0,0, + 114,126,0,0,0,41,2,114,100,0,0,0,114,91,0,0, + 0,41,5,114,159,0,0,0,114,200,0,0,0,114,133,0, + 0,0,114,145,0,0,0,114,208,0,0,0,41,5,114,102, + 0,0,0,114,121,0,0,0,114,35,0,0,0,114,54,0, + 0,0,114,132,0,0,0,114,2,0,0,0,114,2,0,0, + 0,114,4,0,0,0,114,188,0,0,0,228,3,0,0,115, + 18,0,0,0,0,1,10,1,10,4,2,1,8,2,12,1, + 2,1,14,1,2,1,122,29,83,111,117,114,99,101,108,101, + 115,115,70,105,108,101,76,111,97,100,101,114,46,103,101,116, + 95,99,111,100,101,99,2,0,0,0,0,0,0,0,2,0, + 0,0,1,0,0,0,67,0,0,0,115,4,0,0,0,100, + 1,83,0,41,2,122,39,82,101,116,117,114,110,32,78,111, + 110,101,32,97,115,32,116,104,101,114,101,32,105,115,32,110, 111,32,115,111,117,114,99,101,32,99,111,100,101,46,78,114, 2,0,0,0,41,2,114,102,0,0,0,114,121,0,0,0, 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,114, - 202,0,0,0,38,4,0,0,115,2,0,0,0,0,2,122, - 30,69,120,116,101,110,115,105,111,110,70,105,108,101,76,111, - 97,100,101,114,46,103,101,116,95,115,111,117,114,99,101,99, - 2,0,0,0,0,0,0,0,2,0,0,0,1,0,0,0, - 67,0,0,0,115,6,0,0,0,124,0,106,0,83,0,41, - 1,122,58,82,101,116,117,114,110,32,116,104,101,32,112,97, - 116,104,32,116,111,32,116,104,101,32,115,111,117,114,99,101, - 32,102,105,108,101,32,97,115,32,102,111,117,110,100,32,98, - 121,32,116,104,101,32,102,105,110,100,101,114,46,41,1,114, - 35,0,0,0,41,2,114,102,0,0,0,114,121,0,0,0, + 202,0,0,0,244,3,0,0,115,2,0,0,0,0,2,122, + 31,83,111,117,114,99,101,108,101,115,115,70,105,108,101,76, + 111,97,100,101,114,46,103,101,116,95,115,111,117,114,99,101, + 78,41,6,114,107,0,0,0,114,106,0,0,0,114,108,0, + 0,0,114,109,0,0,0,114,188,0,0,0,114,202,0,0, + 0,114,2,0,0,0,114,2,0,0,0,114,2,0,0,0, + 114,4,0,0,0,114,234,0,0,0,224,3,0,0,115,6, + 0,0,0,8,2,4,2,8,16,114,234,0,0,0,99,0, + 0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,64, + 0,0,0,115,92,0,0,0,101,0,90,1,100,0,90,2, + 100,1,90,3,100,2,100,3,132,0,90,4,100,4,100,5, + 132,0,90,5,100,6,100,7,132,0,90,6,100,8,100,9, + 132,0,90,7,100,10,100,11,132,0,90,8,100,12,100,13, + 132,0,90,9,100,14,100,15,132,0,90,10,100,16,100,17, + 132,0,90,11,101,12,100,18,100,19,132,0,131,1,90,13, + 100,20,83,0,41,21,218,19,69,120,116,101,110,115,105,111, + 110,70,105,108,101,76,111,97,100,101,114,122,93,76,111,97, + 100,101,114,32,102,111,114,32,101,120,116,101,110,115,105,111, + 110,32,109,111,100,117,108,101,115,46,10,10,32,32,32,32, + 84,104,101,32,99,111,110,115,116,114,117,99,116,111,114,32, + 105,115,32,100,101,115,105,103,110,101,100,32,116,111,32,119, + 111,114,107,32,119,105,116,104,32,70,105,108,101,70,105,110, + 100,101,114,46,10,10,32,32,32,32,99,3,0,0,0,0, + 0,0,0,3,0,0,0,2,0,0,0,67,0,0,0,115, + 16,0,0,0,124,1,124,0,95,0,124,2,124,0,95,1, + 100,0,83,0,41,1,78,41,2,114,100,0,0,0,114,35, + 0,0,0,41,3,114,102,0,0,0,114,100,0,0,0,114, + 35,0,0,0,114,2,0,0,0,114,2,0,0,0,114,4, + 0,0,0,114,186,0,0,0,5,4,0,0,115,4,0,0, + 0,0,1,6,1,122,28,69,120,116,101,110,115,105,111,110, + 70,105,108,101,76,111,97,100,101,114,46,95,95,105,110,105, + 116,95,95,99,2,0,0,0,0,0,0,0,2,0,0,0, + 2,0,0,0,67,0,0,0,115,24,0,0,0,124,0,106, + 0,124,1,106,0,107,2,111,22,124,0,106,1,124,1,106, + 1,107,2,83,0,41,1,78,41,2,114,213,0,0,0,114, + 113,0,0,0,41,2,114,102,0,0,0,114,214,0,0,0, 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,114, - 159,0,0,0,42,4,0,0,115,2,0,0,0,0,3,122, - 32,69,120,116,101,110,115,105,111,110,70,105,108,101,76,111, - 97,100,101,114,46,103,101,116,95,102,105,108,101,110,97,109, - 101,78,41,14,114,107,0,0,0,114,106,0,0,0,114,108, - 0,0,0,114,109,0,0,0,114,186,0,0,0,114,215,0, - 0,0,114,217,0,0,0,114,187,0,0,0,114,192,0,0, - 0,114,161,0,0,0,114,188,0,0,0,114,202,0,0,0, - 114,118,0,0,0,114,159,0,0,0,114,2,0,0,0,114, - 2,0,0,0,114,2,0,0,0,114,4,0,0,0,114,235, - 0,0,0,251,3,0,0,115,18,0,0,0,12,8,8,4, + 215,0,0,0,9,4,0,0,115,4,0,0,0,0,1,12, + 1,122,26,69,120,116,101,110,115,105,111,110,70,105,108,101, + 76,111,97,100,101,114,46,95,95,101,113,95,95,99,1,0, + 0,0,0,0,0,0,1,0,0,0,3,0,0,0,67,0, + 0,0,115,20,0,0,0,116,0,124,0,106,1,131,1,116, + 0,124,0,106,2,131,1,65,0,83,0,41,1,78,41,3, + 114,216,0,0,0,114,100,0,0,0,114,35,0,0,0,41, + 1,114,102,0,0,0,114,2,0,0,0,114,2,0,0,0, + 114,4,0,0,0,114,217,0,0,0,13,4,0,0,115,2, + 0,0,0,0,1,122,28,69,120,116,101,110,115,105,111,110, + 70,105,108,101,76,111,97,100,101,114,46,95,95,104,97,115, + 104,95,95,99,2,0,0,0,0,0,0,0,3,0,0,0, + 5,0,0,0,67,0,0,0,115,36,0,0,0,116,0,160, + 1,116,2,106,3,124,1,161,2,125,2,116,0,160,4,100, + 1,124,1,106,5,124,0,106,6,161,3,1,0,124,2,83, + 0,41,2,122,38,67,114,101,97,116,101,32,97,110,32,117, + 110,105,116,105,97,108,105,122,101,100,32,101,120,116,101,110, + 115,105,111,110,32,109,111,100,117,108,101,122,38,101,120,116, + 101,110,115,105,111,110,32,109,111,100,117,108,101,32,123,33, + 114,125,32,108,111,97,100,101,100,32,102,114,111,109,32,123, + 33,114,125,41,7,114,116,0,0,0,114,189,0,0,0,114, + 143,0,0,0,90,14,99,114,101,97,116,101,95,100,121,110, + 97,109,105,99,114,130,0,0,0,114,100,0,0,0,114,35, + 0,0,0,41,3,114,102,0,0,0,114,166,0,0,0,114, + 191,0,0,0,114,2,0,0,0,114,2,0,0,0,114,4, + 0,0,0,114,187,0,0,0,16,4,0,0,115,10,0,0, + 0,0,2,4,1,10,1,6,1,12,1,122,33,69,120,116, + 101,110,115,105,111,110,70,105,108,101,76,111,97,100,101,114, + 46,99,114,101,97,116,101,95,109,111,100,117,108,101,99,2, + 0,0,0,0,0,0,0,2,0,0,0,5,0,0,0,67, + 0,0,0,115,36,0,0,0,116,0,160,1,116,2,106,3, + 124,1,161,2,1,0,116,0,160,4,100,1,124,0,106,5, + 124,0,106,6,161,3,1,0,100,2,83,0,41,3,122,30, + 73,110,105,116,105,97,108,105,122,101,32,97,110,32,101,120, + 116,101,110,115,105,111,110,32,109,111,100,117,108,101,122,40, + 101,120,116,101,110,115,105,111,110,32,109,111,100,117,108,101, + 32,123,33,114,125,32,101,120,101,99,117,116,101,100,32,102, + 114,111,109,32,123,33,114,125,78,41,7,114,116,0,0,0, + 114,189,0,0,0,114,143,0,0,0,90,12,101,120,101,99, + 95,100,121,110,97,109,105,99,114,130,0,0,0,114,100,0, + 0,0,114,35,0,0,0,41,2,114,102,0,0,0,114,191, + 0,0,0,114,2,0,0,0,114,2,0,0,0,114,4,0, + 0,0,114,192,0,0,0,24,4,0,0,115,6,0,0,0, + 0,2,14,1,6,1,122,31,69,120,116,101,110,115,105,111, + 110,70,105,108,101,76,111,97,100,101,114,46,101,120,101,99, + 95,109,111,100,117,108,101,99,2,0,0,0,0,0,0,0, + 2,0,0,0,4,0,0,0,3,0,0,0,115,36,0,0, + 0,116,0,124,0,106,1,131,1,100,1,25,0,137,0,116, + 2,135,0,102,1,100,2,100,3,132,8,116,3,68,0,131, + 1,131,1,83,0,41,4,122,49,82,101,116,117,114,110,32, + 84,114,117,101,32,105,102,32,116,104,101,32,101,120,116,101, + 110,115,105,111,110,32,109,111,100,117,108,101,32,105,115,32, + 97,32,112,97,99,107,97,103,101,46,114,29,0,0,0,99, + 1,0,0,0,0,0,0,0,2,0,0,0,4,0,0,0, + 51,0,0,0,115,26,0,0,0,124,0,93,18,125,1,136, + 0,100,0,124,1,23,0,107,2,86,0,1,0,113,2,100, + 1,83,0,41,2,114,186,0,0,0,78,114,2,0,0,0, + 41,2,114,22,0,0,0,218,6,115,117,102,102,105,120,41, + 1,218,9,102,105,108,101,95,110,97,109,101,114,2,0,0, + 0,114,4,0,0,0,250,9,60,103,101,110,101,120,112,114, + 62,33,4,0,0,115,2,0,0,0,4,1,122,49,69,120, + 116,101,110,115,105,111,110,70,105,108,101,76,111,97,100,101, + 114,46,105,115,95,112,97,99,107,97,103,101,46,60,108,111, + 99,97,108,115,62,46,60,103,101,110,101,120,112,114,62,41, + 4,114,38,0,0,0,114,35,0,0,0,218,3,97,110,121, + 218,18,69,88,84,69,78,83,73,79,78,95,83,85,70,70, + 73,88,69,83,41,2,114,102,0,0,0,114,121,0,0,0, + 114,2,0,0,0,41,1,114,237,0,0,0,114,4,0,0, + 0,114,161,0,0,0,30,4,0,0,115,6,0,0,0,0, + 2,14,1,12,1,122,30,69,120,116,101,110,115,105,111,110, + 70,105,108,101,76,111,97,100,101,114,46,105,115,95,112,97, + 99,107,97,103,101,99,2,0,0,0,0,0,0,0,2,0, + 0,0,1,0,0,0,67,0,0,0,115,4,0,0,0,100, + 1,83,0,41,2,122,63,82,101,116,117,114,110,32,78,111, + 110,101,32,97,115,32,97,110,32,101,120,116,101,110,115,105, + 111,110,32,109,111,100,117,108,101,32,99,97,110,110,111,116, + 32,99,114,101,97,116,101,32,97,32,99,111,100,101,32,111, + 98,106,101,99,116,46,78,114,2,0,0,0,41,2,114,102, + 0,0,0,114,121,0,0,0,114,2,0,0,0,114,2,0, + 0,0,114,4,0,0,0,114,188,0,0,0,36,4,0,0, + 115,2,0,0,0,0,2,122,28,69,120,116,101,110,115,105, + 111,110,70,105,108,101,76,111,97,100,101,114,46,103,101,116, + 95,99,111,100,101,99,2,0,0,0,0,0,0,0,2,0, + 0,0,1,0,0,0,67,0,0,0,115,4,0,0,0,100, + 1,83,0,41,2,122,53,82,101,116,117,114,110,32,78,111, + 110,101,32,97,115,32,101,120,116,101,110,115,105,111,110,32, + 109,111,100,117,108,101,115,32,104,97,118,101,32,110,111,32, + 115,111,117,114,99,101,32,99,111,100,101,46,78,114,2,0, + 0,0,41,2,114,102,0,0,0,114,121,0,0,0,114,2, + 0,0,0,114,2,0,0,0,114,4,0,0,0,114,202,0, + 0,0,40,4,0,0,115,2,0,0,0,0,2,122,30,69, + 120,116,101,110,115,105,111,110,70,105,108,101,76,111,97,100, + 101,114,46,103,101,116,95,115,111,117,114,99,101,99,2,0, + 0,0,0,0,0,0,2,0,0,0,1,0,0,0,67,0, + 0,0,115,6,0,0,0,124,0,106,0,83,0,41,1,122, + 58,82,101,116,117,114,110,32,116,104,101,32,112,97,116,104, + 32,116,111,32,116,104,101,32,115,111,117,114,99,101,32,102, + 105,108,101,32,97,115,32,102,111,117,110,100,32,98,121,32, + 116,104,101,32,102,105,110,100,101,114,46,41,1,114,35,0, + 0,0,41,2,114,102,0,0,0,114,121,0,0,0,114,2, + 0,0,0,114,2,0,0,0,114,4,0,0,0,114,159,0, + 0,0,44,4,0,0,115,2,0,0,0,0,3,122,32,69, + 120,116,101,110,115,105,111,110,70,105,108,101,76,111,97,100, + 101,114,46,103,101,116,95,102,105,108,101,110,97,109,101,78, + 41,14,114,107,0,0,0,114,106,0,0,0,114,108,0,0, + 0,114,109,0,0,0,114,186,0,0,0,114,215,0,0,0, + 114,217,0,0,0,114,187,0,0,0,114,192,0,0,0,114, + 161,0,0,0,114,188,0,0,0,114,202,0,0,0,114,118, + 0,0,0,114,159,0,0,0,114,2,0,0,0,114,2,0, + 0,0,114,2,0,0,0,114,4,0,0,0,114,235,0,0, + 0,253,3,0,0,115,20,0,0,0,8,6,4,2,8,4, 8,4,8,3,8,8,8,6,8,6,8,4,8,4,114,235, 0,0,0,99,0,0,0,0,0,0,0,0,0,0,0,0, 2,0,0,0,64,0,0,0,115,96,0,0,0,101,0,90, @@ -1769,7 +1770,7 @@ const unsigned char _Py_M__importlib_external[] = { 100,101,114,41,4,114,102,0,0,0,114,100,0,0,0,114, 35,0,0,0,218,11,112,97,116,104,95,102,105,110,100,101, 114,114,2,0,0,0,114,2,0,0,0,114,4,0,0,0, - 114,186,0,0,0,55,4,0,0,115,8,0,0,0,0,1, + 114,186,0,0,0,57,4,0,0,115,8,0,0,0,0,1, 6,1,6,1,14,1,122,23,95,78,97,109,101,115,112,97, 99,101,80,97,116,104,46,95,95,105,110,105,116,95,95,99, 1,0,0,0,0,0,0,0,4,0,0,0,3,0,0,0, @@ -1786,7 +1787,7 @@ const unsigned char _Py_M__importlib_external[] = { 102,0,0,0,114,233,0,0,0,218,3,100,111,116,90,2, 109,101,114,2,0,0,0,114,2,0,0,0,114,4,0,0, 0,218,23,95,102,105,110,100,95,112,97,114,101,110,116,95, - 112,97,116,104,95,110,97,109,101,115,61,4,0,0,115,8, + 112,97,116,104,95,110,97,109,101,115,63,4,0,0,115,8, 0,0,0,0,2,18,1,8,2,4,3,122,38,95,78,97, 109,101,115,112,97,99,101,80,97,116,104,46,95,102,105,110, 100,95,112,97,114,101,110,116,95,112,97,116,104,95,110,97, @@ -1799,7 +1800,7 @@ const unsigned char _Py_M__importlib_external[] = { 97,114,101,110,116,95,109,111,100,117,108,101,95,110,97,109, 101,90,14,112,97,116,104,95,97,116,116,114,95,110,97,109, 101,114,2,0,0,0,114,2,0,0,0,114,4,0,0,0, - 114,244,0,0,0,71,4,0,0,115,4,0,0,0,0,1, + 114,244,0,0,0,73,4,0,0,115,4,0,0,0,0,1, 12,1,122,31,95,78,97,109,101,115,112,97,99,101,80,97, 116,104,46,95,103,101,116,95,112,97,114,101,110,116,95,112, 97,116,104,99,1,0,0,0,0,0,0,0,3,0,0,0, @@ -1815,7 +1816,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,90,11,112,97,114,101,110,116,95,112,97,116,104,114,166, 0,0,0,114,2,0,0,0,114,2,0,0,0,114,4,0, 0,0,218,12,95,114,101,99,97,108,99,117,108,97,116,101, - 75,4,0,0,115,16,0,0,0,0,2,12,1,10,1,14, + 77,4,0,0,115,16,0,0,0,0,2,12,1,10,1,14, 3,18,1,6,1,8,1,6,1,122,27,95,78,97,109,101, 115,112,97,99,101,80,97,116,104,46,95,114,101,99,97,108, 99,117,108,97,116,101,99,1,0,0,0,0,0,0,0,1, @@ -1823,7 +1824,7 @@ const unsigned char _Py_M__importlib_external[] = { 116,0,124,0,160,1,161,0,131,1,83,0,41,1,78,41, 2,114,226,0,0,0,114,251,0,0,0,41,1,114,102,0, 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, - 0,218,8,95,95,105,116,101,114,95,95,88,4,0,0,115, + 0,218,8,95,95,105,116,101,114,95,95,90,4,0,0,115, 2,0,0,0,0,1,122,23,95,78,97,109,101,115,112,97, 99,101,80,97,116,104,46,95,95,105,116,101,114,95,95,99, 3,0,0,0,0,0,0,0,3,0,0,0,3,0,0,0, @@ -1832,14 +1833,14 @@ const unsigned char _Py_M__importlib_external[] = { 0,41,3,114,102,0,0,0,218,5,105,110,100,101,120,114, 35,0,0,0,114,2,0,0,0,114,2,0,0,0,114,4, 0,0,0,218,11,95,95,115,101,116,105,116,101,109,95,95, - 91,4,0,0,115,2,0,0,0,0,1,122,26,95,78,97, + 93,4,0,0,115,2,0,0,0,0,1,122,26,95,78,97, 109,101,115,112,97,99,101,80,97,116,104,46,95,95,115,101, 116,105,116,101,109,95,95,99,1,0,0,0,0,0,0,0, 1,0,0,0,3,0,0,0,67,0,0,0,115,12,0,0, 0,116,0,124,0,160,1,161,0,131,1,83,0,41,1,78, 41,2,114,31,0,0,0,114,251,0,0,0,41,1,114,102, 0,0,0,114,2,0,0,0,114,2,0,0,0,114,4,0, - 0,0,218,7,95,95,108,101,110,95,95,94,4,0,0,115, + 0,0,218,7,95,95,108,101,110,95,95,96,4,0,0,115, 2,0,0,0,0,1,122,22,95,78,97,109,101,115,112,97, 99,101,80,97,116,104,46,95,95,108,101,110,95,95,99,1, 0,0,0,0,0,0,0,1,0,0,0,3,0,0,0,67, @@ -1848,7 +1849,7 @@ const unsigned char _Py_M__importlib_external[] = { 97,99,101,80,97,116,104,40,123,33,114,125,41,41,2,114, 48,0,0,0,114,243,0,0,0,41,1,114,102,0,0,0, 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,218, - 8,95,95,114,101,112,114,95,95,97,4,0,0,115,2,0, + 8,95,95,114,101,112,114,95,95,99,4,0,0,115,2,0, 0,0,0,1,122,23,95,78,97,109,101,115,112,97,99,101, 80,97,116,104,46,95,95,114,101,112,114,95,95,99,2,0, 0,0,0,0,0,0,2,0,0,0,3,0,0,0,67,0, @@ -1856,7 +1857,7 @@ const unsigned char _Py_M__importlib_external[] = { 6,83,0,41,1,78,41,1,114,251,0,0,0,41,2,114, 102,0,0,0,218,4,105,116,101,109,114,2,0,0,0,114, 2,0,0,0,114,4,0,0,0,218,12,95,95,99,111,110, - 116,97,105,110,115,95,95,100,4,0,0,115,2,0,0,0, + 116,97,105,110,115,95,95,102,4,0,0,115,2,0,0,0, 0,1,122,27,95,78,97,109,101,115,112,97,99,101,80,97, 116,104,46,95,95,99,111,110,116,97,105,110,115,95,95,99, 2,0,0,0,0,0,0,0,2,0,0,0,3,0,0,0, @@ -1864,7 +1865,7 @@ const unsigned char _Py_M__importlib_external[] = { 1,161,1,1,0,100,0,83,0,41,1,78,41,2,114,243, 0,0,0,114,165,0,0,0,41,2,114,102,0,0,0,114, 1,1,0,0,114,2,0,0,0,114,2,0,0,0,114,4, - 0,0,0,114,165,0,0,0,103,4,0,0,115,2,0,0, + 0,0,0,114,165,0,0,0,105,4,0,0,115,2,0,0, 0,0,1,122,21,95,78,97,109,101,115,112,97,99,101,80, 97,116,104,46,97,112,112,101,110,100,78,41,14,114,107,0, 0,0,114,106,0,0,0,114,108,0,0,0,114,109,0,0, @@ -1872,742 +1873,742 @@ const unsigned char _Py_M__importlib_external[] = { 114,251,0,0,0,114,252,0,0,0,114,254,0,0,0,114, 255,0,0,0,114,0,1,0,0,114,2,1,0,0,114,165, 0,0,0,114,2,0,0,0,114,2,0,0,0,114,2,0, - 0,0,114,4,0,0,0,114,241,0,0,0,48,4,0,0, - 115,20,0,0,0,12,7,8,6,8,10,8,4,8,13,8, - 3,8,3,8,3,8,3,8,3,114,241,0,0,0,99,0, - 0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,64, - 0,0,0,115,80,0,0,0,101,0,90,1,100,0,90,2, - 100,1,100,2,132,0,90,3,101,4,100,3,100,4,132,0, - 131,1,90,5,100,5,100,6,132,0,90,6,100,7,100,8, - 132,0,90,7,100,9,100,10,132,0,90,8,100,11,100,12, - 132,0,90,9,100,13,100,14,132,0,90,10,100,15,100,16, - 132,0,90,11,100,17,83,0,41,18,218,16,95,78,97,109, - 101,115,112,97,99,101,76,111,97,100,101,114,99,4,0,0, - 0,0,0,0,0,4,0,0,0,4,0,0,0,67,0,0, - 0,115,18,0,0,0,116,0,124,1,124,2,124,3,131,3, - 124,0,95,1,100,0,83,0,41,1,78,41,2,114,241,0, - 0,0,114,243,0,0,0,41,4,114,102,0,0,0,114,100, - 0,0,0,114,35,0,0,0,114,247,0,0,0,114,2,0, - 0,0,114,2,0,0,0,114,4,0,0,0,114,186,0,0, - 0,109,4,0,0,115,2,0,0,0,0,1,122,25,95,78, - 97,109,101,115,112,97,99,101,76,111,97,100,101,114,46,95, - 95,105,110,105,116,95,95,99,2,0,0,0,0,0,0,0, - 2,0,0,0,3,0,0,0,67,0,0,0,115,12,0,0, - 0,100,1,160,0,124,1,106,1,161,1,83,0,41,2,122, - 115,82,101,116,117,114,110,32,114,101,112,114,32,102,111,114, - 32,116,104,101,32,109,111,100,117,108,101,46,10,10,32,32, - 32,32,32,32,32,32,84,104,101,32,109,101,116,104,111,100, - 32,105,115,32,100,101,112,114,101,99,97,116,101,100,46,32, - 32,84,104,101,32,105,109,112,111,114,116,32,109,97,99,104, - 105,110,101,114,121,32,100,111,101,115,32,116,104,101,32,106, - 111,98,32,105,116,115,101,108,102,46,10,10,32,32,32,32, - 32,32,32,32,122,25,60,109,111,100,117,108,101,32,123,33, - 114,125,32,40,110,97,109,101,115,112,97,99,101,41,62,41, - 2,114,48,0,0,0,114,107,0,0,0,41,2,114,172,0, - 0,0,114,191,0,0,0,114,2,0,0,0,114,2,0,0, - 0,114,4,0,0,0,218,11,109,111,100,117,108,101,95,114, - 101,112,114,112,4,0,0,115,2,0,0,0,0,7,122,28, - 95,78,97,109,101,115,112,97,99,101,76,111,97,100,101,114, - 46,109,111,100,117,108,101,95,114,101,112,114,99,2,0,0, - 0,0,0,0,0,2,0,0,0,1,0,0,0,67,0,0, - 0,115,4,0,0,0,100,1,83,0,41,2,78,84,114,2, - 0,0,0,41,2,114,102,0,0,0,114,121,0,0,0,114, - 2,0,0,0,114,2,0,0,0,114,4,0,0,0,114,161, - 0,0,0,121,4,0,0,115,2,0,0,0,0,1,122,27, + 0,0,114,4,0,0,0,114,241,0,0,0,50,4,0,0, + 115,22,0,0,0,8,5,4,2,8,6,8,10,8,4,8, + 13,8,3,8,3,8,3,8,3,8,3,114,241,0,0,0, + 99,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0, + 0,64,0,0,0,115,80,0,0,0,101,0,90,1,100,0, + 90,2,100,1,100,2,132,0,90,3,101,4,100,3,100,4, + 132,0,131,1,90,5,100,5,100,6,132,0,90,6,100,7, + 100,8,132,0,90,7,100,9,100,10,132,0,90,8,100,11, + 100,12,132,0,90,9,100,13,100,14,132,0,90,10,100,15, + 100,16,132,0,90,11,100,17,83,0,41,18,218,16,95,78, + 97,109,101,115,112,97,99,101,76,111,97,100,101,114,99,4, + 0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,67, + 0,0,0,115,18,0,0,0,116,0,124,1,124,2,124,3, + 131,3,124,0,95,1,100,0,83,0,41,1,78,41,2,114, + 241,0,0,0,114,243,0,0,0,41,4,114,102,0,0,0, + 114,100,0,0,0,114,35,0,0,0,114,247,0,0,0,114, + 2,0,0,0,114,2,0,0,0,114,4,0,0,0,114,186, + 0,0,0,111,4,0,0,115,2,0,0,0,0,1,122,25, 95,78,97,109,101,115,112,97,99,101,76,111,97,100,101,114, - 46,105,115,95,112,97,99,107,97,103,101,99,2,0,0,0, - 0,0,0,0,2,0,0,0,1,0,0,0,67,0,0,0, - 115,4,0,0,0,100,1,83,0,41,2,78,114,30,0,0, - 0,114,2,0,0,0,41,2,114,102,0,0,0,114,121,0, - 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, - 0,114,202,0,0,0,124,4,0,0,115,2,0,0,0,0, - 1,122,27,95,78,97,109,101,115,112,97,99,101,76,111,97, - 100,101,114,46,103,101,116,95,115,111,117,114,99,101,99,2, - 0,0,0,0,0,0,0,2,0,0,0,6,0,0,0,67, - 0,0,0,115,16,0,0,0,116,0,100,1,100,2,100,3, - 100,4,100,5,141,4,83,0,41,6,78,114,30,0,0,0, - 122,8,60,115,116,114,105,110,103,62,114,190,0,0,0,84, - 41,1,114,204,0,0,0,41,1,114,205,0,0,0,41,2, - 114,102,0,0,0,114,121,0,0,0,114,2,0,0,0,114, - 2,0,0,0,114,4,0,0,0,114,188,0,0,0,127,4, - 0,0,115,2,0,0,0,0,1,122,25,95,78,97,109,101, - 115,112,97,99,101,76,111,97,100,101,114,46,103,101,116,95, - 99,111,100,101,99,2,0,0,0,0,0,0,0,2,0,0, - 0,1,0,0,0,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,2,0,0,0,41,2,114,102,0,0,0,114,166,0, - 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, - 0,114,187,0,0,0,130,4,0,0,115,0,0,0,0,122, - 30,95,78,97,109,101,115,112,97,99,101,76,111,97,100,101, - 114,46,99,114,101,97,116,101,95,109,111,100,117,108,101,99, - 2,0,0,0,0,0,0,0,2,0,0,0,1,0,0,0, - 67,0,0,0,115,4,0,0,0,100,0,83,0,41,1,78, - 114,2,0,0,0,41,2,114,102,0,0,0,114,191,0,0, - 0,114,2,0,0,0,114,2,0,0,0,114,4,0,0,0, - 114,192,0,0,0,133,4,0,0,115,2,0,0,0,0,1, + 46,95,95,105,110,105,116,95,95,99,2,0,0,0,0,0, + 0,0,2,0,0,0,3,0,0,0,67,0,0,0,115,12, + 0,0,0,100,1,160,0,124,1,106,1,161,1,83,0,41, + 2,122,115,82,101,116,117,114,110,32,114,101,112,114,32,102, + 111,114,32,116,104,101,32,109,111,100,117,108,101,46,10,10, + 32,32,32,32,32,32,32,32,84,104,101,32,109,101,116,104, + 111,100,32,105,115,32,100,101,112,114,101,99,97,116,101,100, + 46,32,32,84,104,101,32,105,109,112,111,114,116,32,109,97, + 99,104,105,110,101,114,121,32,100,111,101,115,32,116,104,101, + 32,106,111,98,32,105,116,115,101,108,102,46,10,10,32,32, + 32,32,32,32,32,32,122,25,60,109,111,100,117,108,101,32, + 123,33,114,125,32,40,110,97,109,101,115,112,97,99,101,41, + 62,41,2,114,48,0,0,0,114,107,0,0,0,41,2,114, + 172,0,0,0,114,191,0,0,0,114,2,0,0,0,114,2, + 0,0,0,114,4,0,0,0,218,11,109,111,100,117,108,101, + 95,114,101,112,114,114,4,0,0,115,2,0,0,0,0,7, 122,28,95,78,97,109,101,115,112,97,99,101,76,111,97,100, - 101,114,46,101,120,101,99,95,109,111,100,117,108,101,99,2, - 0,0,0,0,0,0,0,2,0,0,0,4,0,0,0,67, - 0,0,0,115,26,0,0,0,116,0,160,1,100,1,124,0, - 106,2,161,2,1,0,116,0,160,3,124,0,124,1,161,2, - 83,0,41,2,122,98,76,111,97,100,32,97,32,110,97,109, - 101,115,112,97,99,101,32,109,111,100,117,108,101,46,10,10, - 32,32,32,32,32,32,32,32,84,104,105,115,32,109,101,116, - 104,111,100,32,105,115,32,100,101,112,114,101,99,97,116,101, - 100,46,32,32,85,115,101,32,101,120,101,99,95,109,111,100, - 117,108,101,40,41,32,105,110,115,116,101,97,100,46,10,10, - 32,32,32,32,32,32,32,32,122,38,110,97,109,101,115,112, - 97,99,101,32,109,111,100,117,108,101,32,108,111,97,100,101, - 100,32,119,105,116,104,32,112,97,116,104,32,123,33,114,125, - 41,4,114,116,0,0,0,114,130,0,0,0,114,243,0,0, - 0,114,193,0,0,0,41,2,114,102,0,0,0,114,121,0, - 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, - 0,114,194,0,0,0,136,4,0,0,115,6,0,0,0,0, - 7,6,1,8,1,122,28,95,78,97,109,101,115,112,97,99, - 101,76,111,97,100,101,114,46,108,111,97,100,95,109,111,100, - 117,108,101,78,41,12,114,107,0,0,0,114,106,0,0,0, - 114,108,0,0,0,114,186,0,0,0,114,184,0,0,0,114, - 4,1,0,0,114,161,0,0,0,114,202,0,0,0,114,188, - 0,0,0,114,187,0,0,0,114,192,0,0,0,114,194,0, - 0,0,114,2,0,0,0,114,2,0,0,0,114,2,0,0, - 0,114,4,0,0,0,114,3,1,0,0,108,4,0,0,115, - 16,0,0,0,8,1,8,3,12,9,8,3,8,3,8,3, - 8,3,8,3,114,3,1,0,0,99,0,0,0,0,0,0, - 0,0,0,0,0,0,4,0,0,0,64,0,0,0,115,106, - 0,0,0,101,0,90,1,100,0,90,2,100,1,90,3,101, - 4,100,2,100,3,132,0,131,1,90,5,101,4,100,4,100, - 5,132,0,131,1,90,6,101,4,100,6,100,7,132,0,131, - 1,90,7,101,4,100,8,100,9,132,0,131,1,90,8,101, - 4,100,17,100,11,100,12,132,1,131,1,90,9,101,4,100, - 18,100,13,100,14,132,1,131,1,90,10,101,4,100,19,100, - 15,100,16,132,1,131,1,90,11,100,10,83,0,41,20,218, - 10,80,97,116,104,70,105,110,100,101,114,122,62,77,101,116, - 97,32,112,97,116,104,32,102,105,110,100,101,114,32,102,111, - 114,32,115,121,115,46,112,97,116,104,32,97,110,100,32,112, - 97,99,107,97,103,101,32,95,95,112,97,116,104,95,95,32, - 97,116,116,114,105,98,117,116,101,115,46,99,1,0,0,0, - 0,0,0,0,3,0,0,0,4,0,0,0,67,0,0,0, - 115,68,0,0,0,120,62,116,0,116,1,106,2,160,3,161, - 0,131,1,68,0,93,44,92,2,125,1,125,2,124,2,100, - 1,107,8,114,42,116,1,106,2,124,1,61,0,113,16,116, - 4,124,2,100,2,131,2,114,16,124,2,160,5,161,0,1, - 0,113,16,87,0,100,1,83,0,41,3,122,125,67,97,108, - 108,32,116,104,101,32,105,110,118,97,108,105,100,97,116,101, - 95,99,97,99,104,101,115,40,41,32,109,101,116,104,111,100, - 32,111,110,32,97,108,108,32,112,97,116,104,32,101,110,116, - 114,121,32,102,105,110,100,101,114,115,10,32,32,32,32,32, - 32,32,32,115,116,111,114,101,100,32,105,110,32,115,121,115, - 46,112,97,116,104,95,105,109,112,111,114,116,101,114,95,99, - 97,99,104,101,115,32,40,119,104,101,114,101,32,105,109,112, - 108,101,109,101,110,116,101,100,41,46,78,218,17,105,110,118, - 97,108,105,100,97,116,101,95,99,97,99,104,101,115,41,6, - 218,4,108,105,115,116,114,6,0,0,0,218,19,112,97,116, - 104,95,105,109,112,111,114,116,101,114,95,99,97,99,104,101, - 218,5,105,116,101,109,115,114,110,0,0,0,114,6,1,0, - 0,41,3,114,172,0,0,0,114,100,0,0,0,218,6,102, - 105,110,100,101,114,114,2,0,0,0,114,2,0,0,0,114, - 4,0,0,0,114,6,1,0,0,154,4,0,0,115,10,0, - 0,0,0,4,24,1,8,1,10,1,10,1,122,28,80,97, - 116,104,70,105,110,100,101,114,46,105,110,118,97,108,105,100, - 97,116,101,95,99,97,99,104,101,115,99,2,0,0,0,0, - 0,0,0,3,0,0,0,9,0,0,0,67,0,0,0,115, - 84,0,0,0,116,0,106,1,100,1,107,9,114,28,116,0, - 106,1,115,28,116,2,160,3,100,2,116,4,161,2,1,0, - 120,50,116,0,106,1,68,0,93,36,125,2,121,8,124,2, - 124,1,131,1,83,0,4,0,116,5,107,10,114,70,1,0, - 1,0,1,0,119,36,89,0,113,36,88,0,113,36,87,0, - 100,1,83,0,100,1,83,0,41,3,122,46,83,101,97,114, - 99,104,32,115,121,115,46,112,97,116,104,95,104,111,111,107, - 115,32,102,111,114,32,97,32,102,105,110,100,101,114,32,102, - 111,114,32,39,112,97,116,104,39,46,78,122,23,115,121,115, - 46,112,97,116,104,95,104,111,111,107,115,32,105,115,32,101, - 109,112,116,121,41,6,114,6,0,0,0,218,10,112,97,116, - 104,95,104,111,111,107,115,114,61,0,0,0,114,62,0,0, - 0,114,120,0,0,0,114,101,0,0,0,41,3,114,172,0, - 0,0,114,35,0,0,0,90,4,104,111,111,107,114,2,0, - 0,0,114,2,0,0,0,114,4,0,0,0,218,11,95,112, - 97,116,104,95,104,111,111,107,115,164,4,0,0,115,16,0, - 0,0,0,3,16,1,12,1,12,1,2,1,8,1,14,1, - 12,2,122,22,80,97,116,104,70,105,110,100,101,114,46,95, - 112,97,116,104,95,104,111,111,107,115,99,2,0,0,0,0, - 0,0,0,3,0,0,0,8,0,0,0,67,0,0,0,115, - 102,0,0,0,124,1,100,1,107,2,114,42,121,12,116,0, - 160,1,161,0,125,1,87,0,110,20,4,0,116,2,107,10, - 114,40,1,0,1,0,1,0,100,2,83,0,88,0,121,14, - 116,3,106,4,124,1,25,0,125,2,87,0,110,40,4,0, - 116,5,107,10,114,96,1,0,1,0,1,0,124,0,160,6, - 124,1,161,1,125,2,124,2,116,3,106,4,124,1,60,0, - 89,0,110,2,88,0,124,2,83,0,41,3,122,210,71,101, - 116,32,116,104,101,32,102,105,110,100,101,114,32,102,111,114, - 32,116,104,101,32,112,97,116,104,32,101,110,116,114,121,32, - 102,114,111,109,32,115,121,115,46,112,97,116,104,95,105,109, - 112,111,114,116,101,114,95,99,97,99,104,101,46,10,10,32, - 32,32,32,32,32,32,32,73,102,32,116,104,101,32,112,97, - 116,104,32,101,110,116,114,121,32,105,115,32,110,111,116,32, - 105,110,32,116,104,101,32,99,97,99,104,101,44,32,102,105, - 110,100,32,116,104,101,32,97,112,112,114,111,112,114,105,97, - 116,101,32,102,105,110,100,101,114,10,32,32,32,32,32,32, - 32,32,97,110,100,32,99,97,99,104,101,32,105,116,46,32, - 73,102,32,110,111,32,102,105,110,100,101,114,32,105,115,32, - 97,118,97,105,108,97,98,108,101,44,32,115,116,111,114,101, - 32,78,111,110,101,46,10,10,32,32,32,32,32,32,32,32, - 114,30,0,0,0,78,41,7,114,1,0,0,0,114,45,0, - 0,0,114,224,0,0,0,114,6,0,0,0,114,8,1,0, - 0,218,8,75,101,121,69,114,114,111,114,114,12,1,0,0, - 41,3,114,172,0,0,0,114,35,0,0,0,114,10,1,0, + 101,114,46,109,111,100,117,108,101,95,114,101,112,114,99,2, + 0,0,0,0,0,0,0,2,0,0,0,1,0,0,0,67, + 0,0,0,115,4,0,0,0,100,1,83,0,41,2,78,84, + 114,2,0,0,0,41,2,114,102,0,0,0,114,121,0,0, 0,114,2,0,0,0,114,2,0,0,0,114,4,0,0,0, - 218,20,95,112,97,116,104,95,105,109,112,111,114,116,101,114, - 95,99,97,99,104,101,177,4,0,0,115,22,0,0,0,0, - 8,8,1,2,1,12,1,14,3,6,1,2,1,14,1,14, - 1,10,1,16,1,122,31,80,97,116,104,70,105,110,100,101, - 114,46,95,112,97,116,104,95,105,109,112,111,114,116,101,114, - 95,99,97,99,104,101,99,3,0,0,0,0,0,0,0,6, - 0,0,0,4,0,0,0,67,0,0,0,115,82,0,0,0, - 116,0,124,2,100,1,131,2,114,26,124,2,160,1,124,1, - 161,1,92,2,125,3,125,4,110,14,124,2,160,2,124,1, - 161,1,125,3,103,0,125,4,124,3,100,0,107,9,114,60, - 116,3,160,4,124,1,124,3,161,2,83,0,116,3,160,5, - 124,1,100,0,161,2,125,5,124,4,124,5,95,6,124,5, - 83,0,41,2,78,114,119,0,0,0,41,7,114,110,0,0, - 0,114,119,0,0,0,114,183,0,0,0,114,116,0,0,0, - 114,180,0,0,0,114,162,0,0,0,114,158,0,0,0,41, - 6,114,172,0,0,0,114,121,0,0,0,114,10,1,0,0, - 114,122,0,0,0,114,123,0,0,0,114,166,0,0,0,114, - 2,0,0,0,114,2,0,0,0,114,4,0,0,0,218,16, - 95,108,101,103,97,99,121,95,103,101,116,95,115,112,101,99, - 199,4,0,0,115,18,0,0,0,0,4,10,1,16,2,10, - 1,4,1,8,1,12,1,12,1,6,1,122,27,80,97,116, - 104,70,105,110,100,101,114,46,95,108,101,103,97,99,121,95, - 103,101,116,95,115,112,101,99,78,99,4,0,0,0,0,0, - 0,0,9,0,0,0,5,0,0,0,67,0,0,0,115,170, - 0,0,0,103,0,125,4,120,160,124,2,68,0,93,130,125, - 5,116,0,124,5,116,1,116,2,102,2,131,2,115,30,113, - 10,124,0,160,3,124,5,161,1,125,6,124,6,100,1,107, - 9,114,10,116,4,124,6,100,2,131,2,114,72,124,6,160, - 5,124,1,124,3,161,2,125,7,110,12,124,0,160,6,124, - 1,124,6,161,2,125,7,124,7,100,1,107,8,114,94,113, - 10,124,7,106,7,100,1,107,9,114,108,124,7,83,0,124, - 7,106,8,125,8,124,8,100,1,107,8,114,130,116,9,100, - 3,131,1,130,1,124,4,160,10,124,8,161,1,1,0,113, - 10,87,0,116,11,160,12,124,1,100,1,161,2,125,7,124, - 4,124,7,95,8,124,7,83,0,100,1,83,0,41,4,122, - 63,70,105,110,100,32,116,104,101,32,108,111,97,100,101,114, - 32,111,114,32,110,97,109,101,115,112,97,99,101,95,112,97, - 116,104,32,102,111,114,32,116,104,105,115,32,109,111,100,117, - 108,101,47,112,97,99,107,97,103,101,32,110,97,109,101,46, - 78,114,182,0,0,0,122,19,115,112,101,99,32,109,105,115, - 115,105,110,103,32,108,111,97,100,101,114,41,13,114,141,0, - 0,0,114,71,0,0,0,218,5,98,121,116,101,115,114,14, - 1,0,0,114,110,0,0,0,114,182,0,0,0,114,15,1, - 0,0,114,122,0,0,0,114,158,0,0,0,114,101,0,0, - 0,114,147,0,0,0,114,116,0,0,0,114,162,0,0,0, - 41,9,114,172,0,0,0,114,121,0,0,0,114,35,0,0, - 0,114,181,0,0,0,218,14,110,97,109,101,115,112,97,99, - 101,95,112,97,116,104,90,5,101,110,116,114,121,114,10,1, - 0,0,114,166,0,0,0,114,123,0,0,0,114,2,0,0, - 0,114,2,0,0,0,114,4,0,0,0,218,9,95,103,101, - 116,95,115,112,101,99,214,4,0,0,115,40,0,0,0,0, - 5,4,1,10,1,14,1,2,1,10,1,8,1,10,1,14, - 2,12,1,8,1,2,1,10,1,4,1,6,1,8,1,8, - 5,14,2,12,1,6,1,122,20,80,97,116,104,70,105,110, - 100,101,114,46,95,103,101,116,95,115,112,101,99,99,4,0, - 0,0,0,0,0,0,6,0,0,0,5,0,0,0,67,0, - 0,0,115,100,0,0,0,124,2,100,1,107,8,114,14,116, - 0,106,1,125,2,124,0,160,2,124,1,124,2,124,3,161, - 3,125,4,124,4,100,1,107,8,114,40,100,1,83,0,124, - 4,106,3,100,1,107,8,114,92,124,4,106,4,125,5,124, - 5,114,86,100,1,124,4,95,5,116,6,124,1,124,5,124, - 0,106,2,131,3,124,4,95,4,124,4,83,0,100,1,83, - 0,110,4,124,4,83,0,100,1,83,0,41,2,122,141,84, - 114,121,32,116,111,32,102,105,110,100,32,97,32,115,112,101, - 99,32,102,111,114,32,39,102,117,108,108,110,97,109,101,39, - 32,111,110,32,115,121,115,46,112,97,116,104,32,111,114,32, - 39,112,97,116,104,39,46,10,10,32,32,32,32,32,32,32, - 32,84,104,101,32,115,101,97,114,99,104,32,105,115,32,98, - 97,115,101,100,32,111,110,32,115,121,115,46,112,97,116,104, - 95,104,111,111,107,115,32,97,110,100,32,115,121,115,46,112, - 97,116,104,95,105,109,112,111,114,116,101,114,95,99,97,99, - 104,101,46,10,32,32,32,32,32,32,32,32,78,41,7,114, - 6,0,0,0,114,35,0,0,0,114,18,1,0,0,114,122, - 0,0,0,114,158,0,0,0,114,160,0,0,0,114,241,0, - 0,0,41,6,114,172,0,0,0,114,121,0,0,0,114,35, - 0,0,0,114,181,0,0,0,114,166,0,0,0,114,17,1, - 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, - 0,114,182,0,0,0,246,4,0,0,115,26,0,0,0,0, - 6,8,1,6,1,14,1,8,1,4,1,10,1,6,1,4, - 3,6,1,16,1,4,2,6,2,122,20,80,97,116,104,70, - 105,110,100,101,114,46,102,105,110,100,95,115,112,101,99,99, - 3,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0, - 67,0,0,0,115,30,0,0,0,124,0,160,0,124,1,124, - 2,161,2,125,3,124,3,100,1,107,8,114,24,100,1,83, - 0,124,3,106,1,83,0,41,2,122,170,102,105,110,100,32, - 116,104,101,32,109,111,100,117,108,101,32,111,110,32,115,121, - 115,46,112,97,116,104,32,111,114,32,39,112,97,116,104,39, - 32,98,97,115,101,100,32,111,110,32,115,121,115,46,112,97, - 116,104,95,104,111,111,107,115,32,97,110,100,10,32,32,32, - 32,32,32,32,32,115,121,115,46,112,97,116,104,95,105,109, - 112,111,114,116,101,114,95,99,97,99,104,101,46,10,10,32, - 32,32,32,32,32,32,32,84,104,105,115,32,109,101,116,104, - 111,100,32,105,115,32,100,101,112,114,101,99,97,116,101,100, - 46,32,32,85,115,101,32,102,105,110,100,95,115,112,101,99, - 40,41,32,105,110,115,116,101,97,100,46,10,10,32,32,32, - 32,32,32,32,32,78,41,2,114,182,0,0,0,114,122,0, - 0,0,41,4,114,172,0,0,0,114,121,0,0,0,114,35, - 0,0,0,114,166,0,0,0,114,2,0,0,0,114,2,0, - 0,0,114,4,0,0,0,114,183,0,0,0,14,5,0,0, - 115,8,0,0,0,0,8,12,1,8,1,4,1,122,22,80, - 97,116,104,70,105,110,100,101,114,46,102,105,110,100,95,109, - 111,100,117,108,101,41,1,78,41,2,78,78,41,1,78,41, - 12,114,107,0,0,0,114,106,0,0,0,114,108,0,0,0, - 114,109,0,0,0,114,184,0,0,0,114,6,1,0,0,114, - 12,1,0,0,114,14,1,0,0,114,15,1,0,0,114,18, - 1,0,0,114,182,0,0,0,114,183,0,0,0,114,2,0, - 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, - 0,114,5,1,0,0,150,4,0,0,115,20,0,0,0,12, - 4,12,10,12,13,12,22,12,15,2,1,12,31,2,1,12, - 23,2,1,114,5,1,0,0,99,0,0,0,0,0,0,0, - 0,0,0,0,0,3,0,0,0,64,0,0,0,115,90,0, - 0,0,101,0,90,1,100,0,90,2,100,1,90,3,100,2, - 100,3,132,0,90,4,100,4,100,5,132,0,90,5,101,6, - 90,7,100,6,100,7,132,0,90,8,100,8,100,9,132,0, - 90,9,100,19,100,11,100,12,132,1,90,10,100,13,100,14, - 132,0,90,11,101,12,100,15,100,16,132,0,131,1,90,13, - 100,17,100,18,132,0,90,14,100,10,83,0,41,20,218,10, - 70,105,108,101,70,105,110,100,101,114,122,172,70,105,108,101, - 45,98,97,115,101,100,32,102,105,110,100,101,114,46,10,10, - 32,32,32,32,73,110,116,101,114,97,99,116,105,111,110,115, - 32,119,105,116,104,32,116,104,101,32,102,105,108,101,32,115, - 121,115,116,101,109,32,97,114,101,32,99,97,99,104,101,100, - 32,102,111,114,32,112,101,114,102,111,114,109,97,110,99,101, - 44,32,98,101,105,110,103,10,32,32,32,32,114,101,102,114, - 101,115,104,101,100,32,119,104,101,110,32,116,104,101,32,100, - 105,114,101,99,116,111,114,121,32,116,104,101,32,102,105,110, - 100,101,114,32,105,115,32,104,97,110,100,108,105,110,103,32, - 104,97,115,32,98,101,101,110,32,109,111,100,105,102,105,101, - 100,46,10,10,32,32,32,32,99,2,0,0,0,0,0,0, - 0,5,0,0,0,6,0,0,0,7,0,0,0,115,88,0, - 0,0,103,0,125,3,120,40,124,2,68,0,93,32,92,2, - 137,0,125,4,124,3,160,0,135,0,102,1,100,1,100,2, - 132,8,124,4,68,0,131,1,161,1,1,0,113,10,87,0, - 124,3,124,0,95,1,124,1,112,58,100,3,124,0,95,2, - 100,4,124,0,95,3,116,4,131,0,124,0,95,5,116,4, - 131,0,124,0,95,6,100,5,83,0,41,6,122,154,73,110, - 105,116,105,97,108,105,122,101,32,119,105,116,104,32,116,104, - 101,32,112,97,116,104,32,116,111,32,115,101,97,114,99,104, - 32,111,110,32,97,110,100,32,97,32,118,97,114,105,97,98, - 108,101,32,110,117,109,98,101,114,32,111,102,10,32,32,32, - 32,32,32,32,32,50,45,116,117,112,108,101,115,32,99,111, - 110,116,97,105,110,105,110,103,32,116,104,101,32,108,111,97, - 100,101,114,32,97,110,100,32,116,104,101,32,102,105,108,101, - 32,115,117,102,102,105,120,101,115,32,116,104,101,32,108,111, - 97,100,101,114,10,32,32,32,32,32,32,32,32,114,101,99, - 111,103,110,105,122,101,115,46,99,1,0,0,0,0,0,0, - 0,2,0,0,0,3,0,0,0,51,0,0,0,115,22,0, - 0,0,124,0,93,14,125,1,124,1,136,0,102,2,86,0, - 1,0,113,2,100,0,83,0,41,1,78,114,2,0,0,0, - 41,2,114,22,0,0,0,114,236,0,0,0,41,1,114,122, - 0,0,0,114,2,0,0,0,114,4,0,0,0,114,238,0, - 0,0,43,5,0,0,115,2,0,0,0,4,0,122,38,70, - 105,108,101,70,105,110,100,101,114,46,95,95,105,110,105,116, - 95,95,46,60,108,111,99,97,108,115,62,46,60,103,101,110, - 101,120,112,114,62,114,59,0,0,0,114,89,0,0,0,78, - 41,7,114,147,0,0,0,218,8,95,108,111,97,100,101,114, - 115,114,35,0,0,0,218,11,95,112,97,116,104,95,109,116, - 105,109,101,218,3,115,101,116,218,11,95,112,97,116,104,95, - 99,97,99,104,101,218,19,95,114,101,108,97,120,101,100,95, - 112,97,116,104,95,99,97,99,104,101,41,5,114,102,0,0, - 0,114,35,0,0,0,218,14,108,111,97,100,101,114,95,100, - 101,116,97,105,108,115,90,7,108,111,97,100,101,114,115,114, - 168,0,0,0,114,2,0,0,0,41,1,114,122,0,0,0, - 114,4,0,0,0,114,186,0,0,0,37,5,0,0,115,16, - 0,0,0,0,4,4,1,14,1,28,1,6,2,10,1,6, - 1,8,1,122,19,70,105,108,101,70,105,110,100,101,114,46, - 95,95,105,110,105,116,95,95,99,1,0,0,0,0,0,0, - 0,1,0,0,0,2,0,0,0,67,0,0,0,115,10,0, - 0,0,100,1,124,0,95,0,100,2,83,0,41,3,122,31, - 73,110,118,97,108,105,100,97,116,101,32,116,104,101,32,100, - 105,114,101,99,116,111,114,121,32,109,116,105,109,101,46,114, - 89,0,0,0,78,41,1,114,21,1,0,0,41,1,114,102, + 114,161,0,0,0,123,4,0,0,115,2,0,0,0,0,1, + 122,27,95,78,97,109,101,115,112,97,99,101,76,111,97,100, + 101,114,46,105,115,95,112,97,99,107,97,103,101,99,2,0, + 0,0,0,0,0,0,2,0,0,0,1,0,0,0,67,0, + 0,0,115,4,0,0,0,100,1,83,0,41,2,78,114,30, + 0,0,0,114,2,0,0,0,41,2,114,102,0,0,0,114, + 121,0,0,0,114,2,0,0,0,114,2,0,0,0,114,4, + 0,0,0,114,202,0,0,0,126,4,0,0,115,2,0,0, + 0,0,1,122,27,95,78,97,109,101,115,112,97,99,101,76, + 111,97,100,101,114,46,103,101,116,95,115,111,117,114,99,101, + 99,2,0,0,0,0,0,0,0,2,0,0,0,6,0,0, + 0,67,0,0,0,115,16,0,0,0,116,0,100,1,100,2, + 100,3,100,4,100,5,141,4,83,0,41,6,78,114,30,0, + 0,0,122,8,60,115,116,114,105,110,103,62,114,190,0,0, + 0,84,41,1,114,204,0,0,0,41,1,114,205,0,0,0, + 41,2,114,102,0,0,0,114,121,0,0,0,114,2,0,0, + 0,114,2,0,0,0,114,4,0,0,0,114,188,0,0,0, + 129,4,0,0,115,2,0,0,0,0,1,122,25,95,78,97, + 109,101,115,112,97,99,101,76,111,97,100,101,114,46,103,101, + 116,95,99,111,100,101,99,2,0,0,0,0,0,0,0,2, + 0,0,0,1,0,0,0,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,2,0,0,0,41,2,114,102,0,0,0,114, + 166,0,0,0,114,2,0,0,0,114,2,0,0,0,114,4, + 0,0,0,114,187,0,0,0,132,4,0,0,115,2,0,0, + 0,0,1,122,30,95,78,97,109,101,115,112,97,99,101,76, + 111,97,100,101,114,46,99,114,101,97,116,101,95,109,111,100, + 117,108,101,99,2,0,0,0,0,0,0,0,2,0,0,0, + 1,0,0,0,67,0,0,0,115,4,0,0,0,100,0,83, + 0,41,1,78,114,2,0,0,0,41,2,114,102,0,0,0, + 114,191,0,0,0,114,2,0,0,0,114,2,0,0,0,114, + 4,0,0,0,114,192,0,0,0,135,4,0,0,115,2,0, + 0,0,0,1,122,28,95,78,97,109,101,115,112,97,99,101, + 76,111,97,100,101,114,46,101,120,101,99,95,109,111,100,117, + 108,101,99,2,0,0,0,0,0,0,0,2,0,0,0,4, + 0,0,0,67,0,0,0,115,26,0,0,0,116,0,160,1, + 100,1,124,0,106,2,161,2,1,0,116,0,160,3,124,0, + 124,1,161,2,83,0,41,2,122,98,76,111,97,100,32,97, + 32,110,97,109,101,115,112,97,99,101,32,109,111,100,117,108, + 101,46,10,10,32,32,32,32,32,32,32,32,84,104,105,115, + 32,109,101,116,104,111,100,32,105,115,32,100,101,112,114,101, + 99,97,116,101,100,46,32,32,85,115,101,32,101,120,101,99, + 95,109,111,100,117,108,101,40,41,32,105,110,115,116,101,97, + 100,46,10,10,32,32,32,32,32,32,32,32,122,38,110,97, + 109,101,115,112,97,99,101,32,109,111,100,117,108,101,32,108, + 111,97,100,101,100,32,119,105,116,104,32,112,97,116,104,32, + 123,33,114,125,41,4,114,116,0,0,0,114,130,0,0,0, + 114,243,0,0,0,114,193,0,0,0,41,2,114,102,0,0, + 0,114,121,0,0,0,114,2,0,0,0,114,2,0,0,0, + 114,4,0,0,0,114,194,0,0,0,138,4,0,0,115,6, + 0,0,0,0,7,6,1,8,1,122,28,95,78,97,109,101, + 115,112,97,99,101,76,111,97,100,101,114,46,108,111,97,100, + 95,109,111,100,117,108,101,78,41,12,114,107,0,0,0,114, + 106,0,0,0,114,108,0,0,0,114,186,0,0,0,114,184, + 0,0,0,114,4,1,0,0,114,161,0,0,0,114,202,0, + 0,0,114,188,0,0,0,114,187,0,0,0,114,192,0,0, + 0,114,194,0,0,0,114,2,0,0,0,114,2,0,0,0, + 114,2,0,0,0,114,4,0,0,0,114,3,1,0,0,110, + 4,0,0,115,16,0,0,0,8,1,8,3,12,9,8,3, + 8,3,8,3,8,3,8,3,114,3,1,0,0,99,0,0, + 0,0,0,0,0,0,0,0,0,0,4,0,0,0,64,0, + 0,0,115,106,0,0,0,101,0,90,1,100,0,90,2,100, + 1,90,3,101,4,100,2,100,3,132,0,131,1,90,5,101, + 4,100,4,100,5,132,0,131,1,90,6,101,4,100,6,100, + 7,132,0,131,1,90,7,101,4,100,8,100,9,132,0,131, + 1,90,8,101,4,100,17,100,11,100,12,132,1,131,1,90, + 9,101,4,100,18,100,13,100,14,132,1,131,1,90,10,101, + 4,100,19,100,15,100,16,132,1,131,1,90,11,100,10,83, + 0,41,20,218,10,80,97,116,104,70,105,110,100,101,114,122, + 62,77,101,116,97,32,112,97,116,104,32,102,105,110,100,101, + 114,32,102,111,114,32,115,121,115,46,112,97,116,104,32,97, + 110,100,32,112,97,99,107,97,103,101,32,95,95,112,97,116, + 104,95,95,32,97,116,116,114,105,98,117,116,101,115,46,99, + 1,0,0,0,0,0,0,0,3,0,0,0,4,0,0,0, + 67,0,0,0,115,68,0,0,0,120,62,116,0,116,1,106, + 2,160,3,161,0,131,1,68,0,93,44,92,2,125,1,125, + 2,124,2,100,1,107,8,114,42,116,1,106,2,124,1,61, + 0,113,16,116,4,124,2,100,2,131,2,114,16,124,2,160, + 5,161,0,1,0,113,16,87,0,100,1,83,0,41,3,122, + 125,67,97,108,108,32,116,104,101,32,105,110,118,97,108,105, + 100,97,116,101,95,99,97,99,104,101,115,40,41,32,109,101, + 116,104,111,100,32,111,110,32,97,108,108,32,112,97,116,104, + 32,101,110,116,114,121,32,102,105,110,100,101,114,115,10,32, + 32,32,32,32,32,32,32,115,116,111,114,101,100,32,105,110, + 32,115,121,115,46,112,97,116,104,95,105,109,112,111,114,116, + 101,114,95,99,97,99,104,101,115,32,40,119,104,101,114,101, + 32,105,109,112,108,101,109,101,110,116,101,100,41,46,78,218, + 17,105,110,118,97,108,105,100,97,116,101,95,99,97,99,104, + 101,115,41,6,218,4,108,105,115,116,114,6,0,0,0,218, + 19,112,97,116,104,95,105,109,112,111,114,116,101,114,95,99, + 97,99,104,101,218,5,105,116,101,109,115,114,110,0,0,0, + 114,6,1,0,0,41,3,114,172,0,0,0,114,100,0,0, + 0,218,6,102,105,110,100,101,114,114,2,0,0,0,114,2, + 0,0,0,114,4,0,0,0,114,6,1,0,0,156,4,0, + 0,115,10,0,0,0,0,4,24,1,8,1,10,1,10,1, + 122,28,80,97,116,104,70,105,110,100,101,114,46,105,110,118, + 97,108,105,100,97,116,101,95,99,97,99,104,101,115,99,2, + 0,0,0,0,0,0,0,3,0,0,0,9,0,0,0,67, + 0,0,0,115,84,0,0,0,116,0,106,1,100,1,107,9, + 114,28,116,0,106,1,115,28,116,2,160,3,100,2,116,4, + 161,2,1,0,120,50,116,0,106,1,68,0,93,36,125,2, + 121,8,124,2,124,1,131,1,83,0,4,0,116,5,107,10, + 114,70,1,0,1,0,1,0,119,36,89,0,113,36,88,0, + 113,36,87,0,100,1,83,0,100,1,83,0,41,3,122,46, + 83,101,97,114,99,104,32,115,121,115,46,112,97,116,104,95, + 104,111,111,107,115,32,102,111,114,32,97,32,102,105,110,100, + 101,114,32,102,111,114,32,39,112,97,116,104,39,46,78,122, + 23,115,121,115,46,112,97,116,104,95,104,111,111,107,115,32, + 105,115,32,101,109,112,116,121,41,6,114,6,0,0,0,218, + 10,112,97,116,104,95,104,111,111,107,115,114,61,0,0,0, + 114,62,0,0,0,114,120,0,0,0,114,101,0,0,0,41, + 3,114,172,0,0,0,114,35,0,0,0,90,4,104,111,111, + 107,114,2,0,0,0,114,2,0,0,0,114,4,0,0,0, + 218,11,95,112,97,116,104,95,104,111,111,107,115,166,4,0, + 0,115,16,0,0,0,0,3,16,1,12,1,12,1,2,1, + 8,1,14,1,12,2,122,22,80,97,116,104,70,105,110,100, + 101,114,46,95,112,97,116,104,95,104,111,111,107,115,99,2, + 0,0,0,0,0,0,0,3,0,0,0,8,0,0,0,67, + 0,0,0,115,102,0,0,0,124,1,100,1,107,2,114,42, + 121,12,116,0,160,1,161,0,125,1,87,0,110,20,4,0, + 116,2,107,10,114,40,1,0,1,0,1,0,100,2,83,0, + 88,0,121,14,116,3,106,4,124,1,25,0,125,2,87,0, + 110,40,4,0,116,5,107,10,114,96,1,0,1,0,1,0, + 124,0,160,6,124,1,161,1,125,2,124,2,116,3,106,4, + 124,1,60,0,89,0,110,2,88,0,124,2,83,0,41,3, + 122,210,71,101,116,32,116,104,101,32,102,105,110,100,101,114, + 32,102,111,114,32,116,104,101,32,112,97,116,104,32,101,110, + 116,114,121,32,102,114,111,109,32,115,121,115,46,112,97,116, + 104,95,105,109,112,111,114,116,101,114,95,99,97,99,104,101, + 46,10,10,32,32,32,32,32,32,32,32,73,102,32,116,104, + 101,32,112,97,116,104,32,101,110,116,114,121,32,105,115,32, + 110,111,116,32,105,110,32,116,104,101,32,99,97,99,104,101, + 44,32,102,105,110,100,32,116,104,101,32,97,112,112,114,111, + 112,114,105,97,116,101,32,102,105,110,100,101,114,10,32,32, + 32,32,32,32,32,32,97,110,100,32,99,97,99,104,101,32, + 105,116,46,32,73,102,32,110,111,32,102,105,110,100,101,114, + 32,105,115,32,97,118,97,105,108,97,98,108,101,44,32,115, + 116,111,114,101,32,78,111,110,101,46,10,10,32,32,32,32, + 32,32,32,32,114,30,0,0,0,78,41,7,114,1,0,0, + 0,114,45,0,0,0,114,224,0,0,0,114,6,0,0,0, + 114,8,1,0,0,218,8,75,101,121,69,114,114,111,114,114, + 12,1,0,0,41,3,114,172,0,0,0,114,35,0,0,0, + 114,10,1,0,0,114,2,0,0,0,114,2,0,0,0,114, + 4,0,0,0,218,20,95,112,97,116,104,95,105,109,112,111, + 114,116,101,114,95,99,97,99,104,101,179,4,0,0,115,22, + 0,0,0,0,8,8,1,2,1,12,1,14,3,6,1,2, + 1,14,1,14,1,10,1,16,1,122,31,80,97,116,104,70, + 105,110,100,101,114,46,95,112,97,116,104,95,105,109,112,111, + 114,116,101,114,95,99,97,99,104,101,99,3,0,0,0,0, + 0,0,0,6,0,0,0,4,0,0,0,67,0,0,0,115, + 82,0,0,0,116,0,124,2,100,1,131,2,114,26,124,2, + 160,1,124,1,161,1,92,2,125,3,125,4,110,14,124,2, + 160,2,124,1,161,1,125,3,103,0,125,4,124,3,100,0, + 107,9,114,60,116,3,160,4,124,1,124,3,161,2,83,0, + 116,3,160,5,124,1,100,0,161,2,125,5,124,4,124,5, + 95,6,124,5,83,0,41,2,78,114,119,0,0,0,41,7, + 114,110,0,0,0,114,119,0,0,0,114,183,0,0,0,114, + 116,0,0,0,114,180,0,0,0,114,162,0,0,0,114,158, + 0,0,0,41,6,114,172,0,0,0,114,121,0,0,0,114, + 10,1,0,0,114,122,0,0,0,114,123,0,0,0,114,166, 0,0,0,114,2,0,0,0,114,2,0,0,0,114,4,0, - 0,0,114,6,1,0,0,51,5,0,0,115,2,0,0,0, - 0,2,122,28,70,105,108,101,70,105,110,100,101,114,46,105, - 110,118,97,108,105,100,97,116,101,95,99,97,99,104,101,115, - 99,2,0,0,0,0,0,0,0,3,0,0,0,3,0,0, - 0,67,0,0,0,115,42,0,0,0,124,0,160,0,124,1, - 161,1,125,2,124,2,100,1,107,8,114,26,100,1,103,0, - 102,2,83,0,124,2,106,1,124,2,106,2,112,38,103,0, - 102,2,83,0,41,2,122,197,84,114,121,32,116,111,32,102, - 105,110,100,32,97,32,108,111,97,100,101,114,32,102,111,114, - 32,116,104,101,32,115,112,101,99,105,102,105,101,100,32,109, - 111,100,117,108,101,44,32,111,114,32,116,104,101,32,110,97, - 109,101,115,112,97,99,101,10,32,32,32,32,32,32,32,32, - 112,97,99,107,97,103,101,32,112,111,114,116,105,111,110,115, - 46,32,82,101,116,117,114,110,115,32,40,108,111,97,100,101, - 114,44,32,108,105,115,116,45,111,102,45,112,111,114,116,105, - 111,110,115,41,46,10,10,32,32,32,32,32,32,32,32,84, - 104,105,115,32,109,101,116,104,111,100,32,105,115,32,100,101, - 112,114,101,99,97,116,101,100,46,32,32,85,115,101,32,102, - 105,110,100,95,115,112,101,99,40,41,32,105,110,115,116,101, - 97,100,46,10,10,32,32,32,32,32,32,32,32,78,41,3, - 114,182,0,0,0,114,122,0,0,0,114,158,0,0,0,41, - 3,114,102,0,0,0,114,121,0,0,0,114,166,0,0,0, - 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,114, - 119,0,0,0,57,5,0,0,115,8,0,0,0,0,7,10, - 1,8,1,8,1,122,22,70,105,108,101,70,105,110,100,101, - 114,46,102,105,110,100,95,108,111,97,100,101,114,99,6,0, - 0,0,0,0,0,0,7,0,0,0,6,0,0,0,67,0, - 0,0,115,26,0,0,0,124,1,124,2,124,3,131,2,125, - 6,116,0,124,2,124,3,124,6,124,4,100,1,141,4,83, - 0,41,2,78,41,2,114,122,0,0,0,114,158,0,0,0, - 41,1,114,169,0,0,0,41,7,114,102,0,0,0,114,167, - 0,0,0,114,121,0,0,0,114,35,0,0,0,90,4,115, - 109,115,108,114,181,0,0,0,114,122,0,0,0,114,2,0, - 0,0,114,2,0,0,0,114,4,0,0,0,114,18,1,0, - 0,69,5,0,0,115,6,0,0,0,0,1,10,1,8,1, - 122,20,70,105,108,101,70,105,110,100,101,114,46,95,103,101, - 116,95,115,112,101,99,78,99,3,0,0,0,0,0,0,0, - 14,0,0,0,8,0,0,0,67,0,0,0,115,98,1,0, - 0,100,1,125,3,124,1,160,0,100,2,161,1,100,3,25, - 0,125,4,121,24,116,1,124,0,106,2,112,34,116,3,160, - 4,161,0,131,1,106,5,125,5,87,0,110,24,4,0,116, - 6,107,10,114,66,1,0,1,0,1,0,100,4,125,5,89, - 0,110,2,88,0,124,5,124,0,106,7,107,3,114,92,124, - 0,160,8,161,0,1,0,124,5,124,0,95,7,116,9,131, - 0,114,114,124,0,106,10,125,6,124,4,160,11,161,0,125, - 7,110,10,124,0,106,12,125,6,124,4,125,7,124,7,124, - 6,107,6,114,218,116,13,124,0,106,2,124,4,131,2,125, - 8,120,72,124,0,106,14,68,0,93,54,92,2,125,9,125, - 10,100,5,124,9,23,0,125,11,116,13,124,8,124,11,131, - 2,125,12,116,15,124,12,131,1,114,152,124,0,160,16,124, - 10,124,1,124,12,124,8,103,1,124,2,161,5,83,0,113, - 152,87,0,116,17,124,8,131,1,125,3,120,88,124,0,106, - 14,68,0,93,78,92,2,125,9,125,10,116,13,124,0,106, - 2,124,4,124,9,23,0,131,2,125,12,116,18,106,19,100, - 6,124,12,100,3,100,7,141,3,1,0,124,7,124,9,23, - 0,124,6,107,6,114,226,116,15,124,12,131,1,114,226,124, - 0,160,16,124,10,124,1,124,12,100,8,124,2,161,5,83, - 0,113,226,87,0,124,3,144,1,114,94,116,18,160,19,100, - 9,124,8,161,2,1,0,116,18,160,20,124,1,100,8,161, - 2,125,13,124,8,103,1,124,13,95,21,124,13,83,0,100, - 8,83,0,41,10,122,111,84,114,121,32,116,111,32,102,105, - 110,100,32,97,32,115,112,101,99,32,102,111,114,32,116,104, - 101,32,115,112,101,99,105,102,105,101,100,32,109,111,100,117, - 108,101,46,10,10,32,32,32,32,32,32,32,32,82,101,116, - 117,114,110,115,32,116,104,101,32,109,97,116,99,104,105,110, - 103,32,115,112,101,99,44,32,111,114,32,78,111,110,101,32, - 105,102,32,110,111,116,32,102,111,117,110,100,46,10,32,32, - 32,32,32,32,32,32,70,114,59,0,0,0,114,57,0,0, - 0,114,89,0,0,0,114,186,0,0,0,122,9,116,114,121, - 105,110,103,32,123,125,41,1,90,9,118,101,114,98,111,115, - 105,116,121,78,122,25,112,111,115,115,105,98,108,101,32,110, - 97,109,101,115,112,97,99,101,32,102,111,114,32,123,125,41, - 22,114,32,0,0,0,114,39,0,0,0,114,35,0,0,0, - 114,1,0,0,0,114,45,0,0,0,114,230,0,0,0,114, - 40,0,0,0,114,21,1,0,0,218,11,95,102,105,108,108, - 95,99,97,99,104,101,114,5,0,0,0,114,24,1,0,0, - 114,90,0,0,0,114,23,1,0,0,114,28,0,0,0,114, - 20,1,0,0,114,44,0,0,0,114,18,1,0,0,114,46, - 0,0,0,114,116,0,0,0,114,130,0,0,0,114,162,0, - 0,0,114,158,0,0,0,41,14,114,102,0,0,0,114,121, - 0,0,0,114,181,0,0,0,90,12,105,115,95,110,97,109, - 101,115,112,97,99,101,90,11,116,97,105,108,95,109,111,100, - 117,108,101,114,149,0,0,0,90,5,99,97,99,104,101,90, - 12,99,97,99,104,101,95,109,111,100,117,108,101,90,9,98, - 97,115,101,95,112,97,116,104,114,236,0,0,0,114,167,0, - 0,0,90,13,105,110,105,116,95,102,105,108,101,110,97,109, - 101,90,9,102,117,108,108,95,112,97,116,104,114,166,0,0, - 0,114,2,0,0,0,114,2,0,0,0,114,4,0,0,0, - 114,182,0,0,0,74,5,0,0,115,70,0,0,0,0,5, - 4,1,14,1,2,1,24,1,14,1,10,1,10,1,8,1, - 6,2,6,1,6,1,10,2,6,1,4,2,8,1,12,1, - 16,1,8,1,10,1,8,1,24,4,8,2,16,1,16,1, - 16,1,12,1,8,1,10,1,12,1,6,1,12,1,12,1, - 8,1,4,1,122,20,70,105,108,101,70,105,110,100,101,114, - 46,102,105,110,100,95,115,112,101,99,99,1,0,0,0,0, - 0,0,0,9,0,0,0,10,0,0,0,67,0,0,0,115, - 194,0,0,0,124,0,106,0,125,1,121,22,116,1,160,2, - 124,1,112,22,116,1,160,3,161,0,161,1,125,2,87,0, - 110,30,4,0,116,4,116,5,116,6,102,3,107,10,114,58, - 1,0,1,0,1,0,103,0,125,2,89,0,110,2,88,0, - 116,7,106,8,160,9,100,1,161,1,115,84,116,10,124,2, - 131,1,124,0,95,11,110,78,116,10,131,0,125,3,120,64, - 124,2,68,0,93,56,125,4,124,4,160,12,100,2,161,1, - 92,3,125,5,125,6,125,7,124,6,114,138,100,3,160,13, - 124,5,124,7,160,14,161,0,161,2,125,8,110,4,124,5, - 125,8,124,3,160,15,124,8,161,1,1,0,113,96,87,0, - 124,3,124,0,95,11,116,7,106,8,160,9,116,16,161,1, - 114,190,100,4,100,5,132,0,124,2,68,0,131,1,124,0, - 95,17,100,6,83,0,41,7,122,68,70,105,108,108,32,116, - 104,101,32,99,97,99,104,101,32,111,102,32,112,111,116,101, - 110,116,105,97,108,32,109,111,100,117,108,101,115,32,97,110, - 100,32,112,97,99,107,97,103,101,115,32,102,111,114,32,116, - 104,105,115,32,100,105,114,101,99,116,111,114,121,46,114,0, - 0,0,0,114,59,0,0,0,122,5,123,125,46,123,125,99, - 1,0,0,0,0,0,0,0,2,0,0,0,4,0,0,0, - 83,0,0,0,115,20,0,0,0,104,0,124,0,93,12,125, - 1,124,1,160,0,161,0,146,2,113,4,83,0,114,2,0, - 0,0,41,1,114,90,0,0,0,41,2,114,22,0,0,0, - 90,2,102,110,114,2,0,0,0,114,2,0,0,0,114,4, - 0,0,0,250,9,60,115,101,116,99,111,109,112,62,151,5, - 0,0,115,2,0,0,0,6,0,122,41,70,105,108,101,70, - 105,110,100,101,114,46,95,102,105,108,108,95,99,97,99,104, - 101,46,60,108,111,99,97,108,115,62,46,60,115,101,116,99, - 111,109,112,62,78,41,18,114,35,0,0,0,114,1,0,0, - 0,114,227,0,0,0,114,45,0,0,0,114,224,0,0,0, - 218,15,80,101,114,109,105,115,115,105,111,110,69,114,114,111, - 114,218,18,78,111,116,65,68,105,114,101,99,116,111,114,121, - 69,114,114,111,114,114,6,0,0,0,114,7,0,0,0,114, - 8,0,0,0,114,22,1,0,0,114,23,1,0,0,114,85, - 0,0,0,114,48,0,0,0,114,90,0,0,0,218,3,97, - 100,100,114,9,0,0,0,114,24,1,0,0,41,9,114,102, - 0,0,0,114,35,0,0,0,114,228,0,0,0,90,21,108, - 111,119,101,114,95,115,117,102,102,105,120,95,99,111,110,116, - 101,110,116,115,114,1,1,0,0,114,100,0,0,0,114,248, - 0,0,0,114,236,0,0,0,90,8,110,101,119,95,110,97, - 109,101,114,2,0,0,0,114,2,0,0,0,114,4,0,0, - 0,114,26,1,0,0,122,5,0,0,115,34,0,0,0,0, - 2,6,1,2,1,22,1,20,3,10,3,12,1,12,7,6, - 1,10,1,16,1,4,1,18,2,4,1,14,1,6,1,12, - 1,122,22,70,105,108,101,70,105,110,100,101,114,46,95,102, - 105,108,108,95,99,97,99,104,101,99,1,0,0,0,0,0, - 0,0,3,0,0,0,3,0,0,0,7,0,0,0,115,18, - 0,0,0,135,0,135,1,102,2,100,1,100,2,132,8,125, - 2,124,2,83,0,41,3,97,20,1,0,0,65,32,99,108, - 97,115,115,32,109,101,116,104,111,100,32,119,104,105,99,104, - 32,114,101,116,117,114,110,115,32,97,32,99,108,111,115,117, - 114,101,32,116,111,32,117,115,101,32,111,110,32,115,121,115, - 46,112,97,116,104,95,104,111,111,107,10,32,32,32,32,32, - 32,32,32,119,104,105,99,104,32,119,105,108,108,32,114,101, - 116,117,114,110,32,97,110,32,105,110,115,116,97,110,99,101, - 32,117,115,105,110,103,32,116,104,101,32,115,112,101,99,105, - 102,105,101,100,32,108,111,97,100,101,114,115,32,97,110,100, - 32,116,104,101,32,112,97,116,104,10,32,32,32,32,32,32, - 32,32,99,97,108,108,101,100,32,111,110,32,116,104,101,32, - 99,108,111,115,117,114,101,46,10,10,32,32,32,32,32,32, - 32,32,73,102,32,116,104,101,32,112,97,116,104,32,99,97, - 108,108,101,100,32,111,110,32,116,104,101,32,99,108,111,115, - 117,114,101,32,105,115,32,110,111,116,32,97,32,100,105,114, - 101,99,116,111,114,121,44,32,73,109,112,111,114,116,69,114, - 114,111,114,32,105,115,10,32,32,32,32,32,32,32,32,114, - 97,105,115,101,100,46,10,10,32,32,32,32,32,32,32,32, - 99,1,0,0,0,0,0,0,0,1,0,0,0,4,0,0, - 0,19,0,0,0,115,34,0,0,0,116,0,124,0,131,1, - 115,20,116,1,100,1,124,0,100,2,141,2,130,1,136,0, - 124,0,102,1,136,1,158,2,142,0,83,0,41,3,122,45, - 80,97,116,104,32,104,111,111,107,32,102,111,114,32,105,109, - 112,111,114,116,108,105,98,46,109,97,99,104,105,110,101,114, - 121,46,70,105,108,101,70,105,110,100,101,114,46,122,30,111, - 110,108,121,32,100,105,114,101,99,116,111,114,105,101,115,32, - 97,114,101,32,115,117,112,112,111,114,116,101,100,41,1,114, - 35,0,0,0,41,2,114,46,0,0,0,114,101,0,0,0, - 41,1,114,35,0,0,0,41,2,114,172,0,0,0,114,25, - 1,0,0,114,2,0,0,0,114,4,0,0,0,218,24,112, - 97,116,104,95,104,111,111,107,95,102,111,114,95,70,105,108, - 101,70,105,110,100,101,114,163,5,0,0,115,6,0,0,0, - 0,2,8,1,12,1,122,54,70,105,108,101,70,105,110,100, - 101,114,46,112,97,116,104,95,104,111,111,107,46,60,108,111, - 99,97,108,115,62,46,112,97,116,104,95,104,111,111,107,95, - 102,111,114,95,70,105,108,101,70,105,110,100,101,114,114,2, - 0,0,0,41,3,114,172,0,0,0,114,25,1,0,0,114, - 31,1,0,0,114,2,0,0,0,41,2,114,172,0,0,0, - 114,25,1,0,0,114,4,0,0,0,218,9,112,97,116,104, - 95,104,111,111,107,153,5,0,0,115,4,0,0,0,0,10, - 14,6,122,20,70,105,108,101,70,105,110,100,101,114,46,112, - 97,116,104,95,104,111,111,107,99,1,0,0,0,0,0,0, - 0,1,0,0,0,3,0,0,0,67,0,0,0,115,12,0, - 0,0,100,1,160,0,124,0,106,1,161,1,83,0,41,2, - 78,122,16,70,105,108,101,70,105,110,100,101,114,40,123,33, - 114,125,41,41,2,114,48,0,0,0,114,35,0,0,0,41, - 1,114,102,0,0,0,114,2,0,0,0,114,2,0,0,0, - 114,4,0,0,0,114,0,1,0,0,171,5,0,0,115,2, - 0,0,0,0,1,122,19,70,105,108,101,70,105,110,100,101, - 114,46,95,95,114,101,112,114,95,95,41,1,78,41,15,114, - 107,0,0,0,114,106,0,0,0,114,108,0,0,0,114,109, - 0,0,0,114,186,0,0,0,114,6,1,0,0,114,125,0, - 0,0,114,183,0,0,0,114,119,0,0,0,114,18,1,0, - 0,114,182,0,0,0,114,26,1,0,0,114,184,0,0,0, - 114,32,1,0,0,114,0,1,0,0,114,2,0,0,0,114, - 2,0,0,0,114,2,0,0,0,114,4,0,0,0,114,19, - 1,0,0,28,5,0,0,115,18,0,0,0,12,9,8,14, - 8,4,4,2,8,12,8,5,10,48,8,31,12,18,114,19, - 1,0,0,99,4,0,0,0,0,0,0,0,6,0,0,0, - 8,0,0,0,67,0,0,0,115,146,0,0,0,124,0,160, - 0,100,1,161,1,125,4,124,0,160,0,100,2,161,1,125, - 5,124,4,115,66,124,5,114,36,124,5,106,1,125,4,110, - 30,124,2,124,3,107,2,114,56,116,2,124,1,124,2,131, - 2,125,4,110,10,116,3,124,1,124,2,131,2,125,4,124, - 5,115,84,116,4,124,1,124,2,124,4,100,3,141,3,125, - 5,121,36,124,5,124,0,100,2,60,0,124,4,124,0,100, - 1,60,0,124,2,124,0,100,4,60,0,124,3,124,0,100, - 5,60,0,87,0,110,20,4,0,116,5,107,10,114,140,1, - 0,1,0,1,0,89,0,110,2,88,0,100,0,83,0,41, - 6,78,218,10,95,95,108,111,97,100,101,114,95,95,218,8, - 95,95,115,112,101,99,95,95,41,1,114,122,0,0,0,90, - 8,95,95,102,105,108,101,95,95,90,10,95,95,99,97,99, - 104,101,100,95,95,41,6,218,3,103,101,116,114,122,0,0, - 0,114,234,0,0,0,114,229,0,0,0,114,169,0,0,0, - 218,9,69,120,99,101,112,116,105,111,110,41,6,90,2,110, - 115,114,100,0,0,0,90,8,112,97,116,104,110,97,109,101, - 90,9,99,112,97,116,104,110,97,109,101,114,122,0,0,0, - 114,166,0,0,0,114,2,0,0,0,114,2,0,0,0,114, - 4,0,0,0,218,14,95,102,105,120,95,117,112,95,109,111, - 100,117,108,101,177,5,0,0,115,34,0,0,0,0,2,10, - 1,10,1,4,1,4,1,8,1,8,1,12,2,10,1,4, - 1,14,1,2,1,8,1,8,1,8,1,12,1,14,2,114, - 37,1,0,0,99,0,0,0,0,0,0,0,0,3,0,0, - 0,3,0,0,0,67,0,0,0,115,38,0,0,0,116,0, - 116,1,160,2,161,0,102,2,125,0,116,3,116,4,102,2, - 125,1,116,5,116,6,102,2,125,2,124,0,124,1,124,2, - 103,3,83,0,41,1,122,95,82,101,116,117,114,110,115,32, - 97,32,108,105,115,116,32,111,102,32,102,105,108,101,45,98, - 97,115,101,100,32,109,111,100,117,108,101,32,108,111,97,100, - 101,114,115,46,10,10,32,32,32,32,69,97,99,104,32,105, - 116,101,109,32,105,115,32,97,32,116,117,112,108,101,32,40, - 108,111,97,100,101,114,44,32,115,117,102,102,105,120,101,115, - 41,46,10,32,32,32,32,41,7,114,235,0,0,0,114,143, - 0,0,0,218,18,101,120,116,101,110,115,105,111,110,95,115, - 117,102,102,105,120,101,115,114,229,0,0,0,114,86,0,0, - 0,114,234,0,0,0,114,76,0,0,0,41,3,90,10,101, - 120,116,101,110,115,105,111,110,115,90,6,115,111,117,114,99, - 101,90,8,98,121,116,101,99,111,100,101,114,2,0,0,0, - 114,2,0,0,0,114,4,0,0,0,114,163,0,0,0,200, - 5,0,0,115,8,0,0,0,0,5,12,1,8,1,8,1, - 114,163,0,0,0,99,1,0,0,0,0,0,0,0,12,0, - 0,0,9,0,0,0,67,0,0,0,115,156,1,0,0,124, - 0,97,0,116,0,106,1,97,1,116,0,106,2,97,2,116, - 1,106,3,116,4,25,0,125,1,120,56,100,1,68,0,93, - 48,125,2,124,2,116,1,106,3,107,7,114,58,116,0,160, - 5,124,2,161,1,125,3,110,10,116,1,106,3,124,2,25, - 0,125,3,116,6,124,1,124,2,124,3,131,3,1,0,113, - 32,87,0,100,2,100,3,103,1,102,2,100,4,100,5,100, - 3,103,2,102,2,102,2,125,4,120,118,124,4,68,0,93, - 102,92,2,125,5,125,6,116,7,100,6,100,7,132,0,124, - 6,68,0,131,1,131,1,115,142,116,8,130,1,124,6,100, - 8,25,0,125,7,124,5,116,1,106,3,107,6,114,174,116, - 1,106,3,124,5,25,0,125,8,80,0,113,112,121,16,116, - 0,160,5,124,5,161,1,125,8,80,0,87,0,113,112,4, - 0,116,9,107,10,114,212,1,0,1,0,1,0,119,112,89, - 0,113,112,88,0,113,112,87,0,116,9,100,9,131,1,130, - 1,116,6,124,1,100,10,124,8,131,3,1,0,116,6,124, - 1,100,11,124,7,131,3,1,0,116,6,124,1,100,12,100, - 13,160,10,124,6,161,1,131,3,1,0,116,0,160,5,100, - 14,161,1,125,9,116,6,124,1,100,14,124,9,131,3,1, - 0,116,0,160,5,100,15,161,1,125,10,116,6,124,1,100, - 15,124,10,131,3,1,0,124,5,100,4,107,2,144,1,114, - 88,116,0,160,5,100,16,161,1,125,11,116,6,124,1,100, - 17,124,11,131,3,1,0,116,6,124,1,100,18,116,11,131, - 0,131,3,1,0,116,12,160,13,116,2,160,14,161,0,161, - 1,1,0,124,5,100,4,107,2,144,1,114,152,116,15,160, - 16,100,19,161,1,1,0,100,20,116,12,107,6,144,1,114, - 152,100,21,116,17,95,18,100,22,83,0,41,23,122,205,83, - 101,116,117,112,32,116,104,101,32,112,97,116,104,45,98,97, - 115,101,100,32,105,109,112,111,114,116,101,114,115,32,102,111, - 114,32,105,109,112,111,114,116,108,105,98,32,98,121,32,105, - 109,112,111,114,116,105,110,103,32,110,101,101,100,101,100,10, - 32,32,32,32,98,117,105,108,116,45,105,110,32,109,111,100, - 117,108,101,115,32,97,110,100,32,105,110,106,101,99,116,105, - 110,103,32,116,104,101,109,32,105,110,116,111,32,116,104,101, - 32,103,108,111,98,97,108,32,110,97,109,101,115,112,97,99, - 101,46,10,10,32,32,32,32,79,116,104,101,114,32,99,111, - 109,112,111,110,101,110,116,115,32,97,114,101,32,101,120,116, - 114,97,99,116,101,100,32,102,114,111,109,32,116,104,101,32, - 99,111,114,101,32,98,111,111,116,115,116,114,97,112,32,109, - 111,100,117,108,101,46,10,10,32,32,32,32,41,4,114,50, - 0,0,0,114,61,0,0,0,218,8,98,117,105,108,116,105, - 110,115,114,140,0,0,0,90,5,112,111,115,105,120,250,1, - 47,90,2,110,116,250,1,92,99,1,0,0,0,0,0,0, - 0,2,0,0,0,3,0,0,0,115,0,0,0,115,26,0, - 0,0,124,0,93,18,125,1,116,0,124,1,131,1,100,0, - 107,2,86,0,1,0,113,2,100,1,83,0,41,2,114,29, - 0,0,0,78,41,1,114,31,0,0,0,41,2,114,22,0, - 0,0,114,79,0,0,0,114,2,0,0,0,114,2,0,0, - 0,114,4,0,0,0,114,238,0,0,0,236,5,0,0,115, - 2,0,0,0,4,0,122,25,95,115,101,116,117,112,46,60, - 108,111,99,97,108,115,62,46,60,103,101,110,101,120,112,114, - 62,114,60,0,0,0,122,30,105,109,112,111,114,116,108,105, - 98,32,114,101,113,117,105,114,101,115,32,112,111,115,105,120, - 32,111,114,32,110,116,114,1,0,0,0,114,25,0,0,0, - 114,21,0,0,0,114,30,0,0,0,90,7,95,116,104,114, - 101,97,100,90,8,95,119,101,97,107,114,101,102,90,6,119, - 105,110,114,101,103,114,171,0,0,0,114,5,0,0,0,122, - 4,46,112,121,119,122,6,95,100,46,112,121,100,84,78,41, - 19,114,116,0,0,0,114,6,0,0,0,114,143,0,0,0, - 114,250,0,0,0,114,107,0,0,0,90,18,95,98,117,105, - 108,116,105,110,95,102,114,111,109,95,110,97,109,101,114,111, - 0,0,0,218,3,97,108,108,114,151,0,0,0,114,101,0, - 0,0,114,26,0,0,0,114,11,0,0,0,114,240,0,0, - 0,114,147,0,0,0,114,38,1,0,0,114,86,0,0,0, - 114,165,0,0,0,114,170,0,0,0,114,174,0,0,0,41, - 12,218,17,95,98,111,111,116,115,116,114,97,112,95,109,111, - 100,117,108,101,90,11,115,101,108,102,95,109,111,100,117,108, - 101,90,12,98,117,105,108,116,105,110,95,110,97,109,101,90, - 14,98,117,105,108,116,105,110,95,109,111,100,117,108,101,90, - 10,111,115,95,100,101,116,97,105,108,115,90,10,98,117,105, - 108,116,105,110,95,111,115,114,21,0,0,0,114,25,0,0, - 0,90,9,111,115,95,109,111,100,117,108,101,90,13,116,104, - 114,101,97,100,95,109,111,100,117,108,101,90,14,119,101,97, - 107,114,101,102,95,109,111,100,117,108,101,90,13,119,105,110, - 114,101,103,95,109,111,100,117,108,101,114,2,0,0,0,114, - 2,0,0,0,114,4,0,0,0,218,6,95,115,101,116,117, - 112,211,5,0,0,115,76,0,0,0,0,8,4,1,6,1, - 6,3,10,1,10,1,10,1,12,2,10,1,16,3,22,1, - 14,2,22,1,8,1,10,1,10,1,4,2,2,1,10,1, - 6,1,14,1,12,2,8,1,12,1,12,1,18,3,10,1, - 12,3,10,1,12,3,10,1,10,1,12,3,14,1,14,1, - 10,1,10,1,10,1,114,44,1,0,0,99,1,0,0,0, - 0,0,0,0,2,0,0,0,4,0,0,0,67,0,0,0, - 115,50,0,0,0,116,0,124,0,131,1,1,0,116,1,131, - 0,125,1,116,2,106,3,160,4,116,5,106,6,124,1,142, - 0,103,1,161,1,1,0,116,2,106,7,160,8,116,9,161, - 1,1,0,100,1,83,0,41,2,122,41,73,110,115,116,97, - 108,108,32,116,104,101,32,112,97,116,104,45,98,97,115,101, - 100,32,105,109,112,111,114,116,32,99,111,109,112,111,110,101, - 110,116,115,46,78,41,10,114,44,1,0,0,114,163,0,0, - 0,114,6,0,0,0,114,11,1,0,0,114,147,0,0,0, - 114,19,1,0,0,114,32,1,0,0,218,9,109,101,116,97, - 95,112,97,116,104,114,165,0,0,0,114,5,1,0,0,41, - 2,114,43,1,0,0,90,17,115,117,112,112,111,114,116,101, - 100,95,108,111,97,100,101,114,115,114,2,0,0,0,114,2, - 0,0,0,114,4,0,0,0,218,8,95,105,110,115,116,97, - 108,108,19,6,0,0,115,8,0,0,0,0,2,8,1,6, - 1,20,1,114,46,1,0,0,41,1,114,47,0,0,0,41, - 1,78,41,3,78,78,78,41,2,114,60,0,0,0,114,60, - 0,0,0,41,1,84,41,1,78,41,1,78,41,61,114,109, - 0,0,0,114,10,0,0,0,90,37,95,67,65,83,69,95, - 73,78,83,69,78,83,73,84,73,86,69,95,80,76,65,84, - 70,79,82,77,83,95,66,89,84,69,83,95,75,69,89,114, - 9,0,0,0,114,11,0,0,0,114,17,0,0,0,114,19, - 0,0,0,114,28,0,0,0,114,38,0,0,0,114,39,0, - 0,0,114,43,0,0,0,114,44,0,0,0,114,46,0,0, - 0,114,56,0,0,0,218,4,116,121,112,101,218,8,95,95, - 99,111,100,101,95,95,114,142,0,0,0,114,15,0,0,0, - 114,129,0,0,0,114,14,0,0,0,114,18,0,0,0,114, - 209,0,0,0,114,75,0,0,0,114,74,0,0,0,114,86, - 0,0,0,114,76,0,0,0,90,23,68,69,66,85,71,95, - 66,89,84,69,67,79,68,69,95,83,85,70,70,73,88,69, - 83,90,27,79,80,84,73,77,73,90,69,68,95,66,89,84, - 69,67,79,68,69,95,83,85,70,70,73,88,69,83,114,81, - 0,0,0,114,87,0,0,0,114,93,0,0,0,114,97,0, - 0,0,114,99,0,0,0,114,118,0,0,0,114,125,0,0, - 0,114,133,0,0,0,114,137,0,0,0,114,139,0,0,0, - 114,145,0,0,0,114,150,0,0,0,114,152,0,0,0,114, - 157,0,0,0,218,6,111,98,106,101,99,116,114,164,0,0, - 0,114,169,0,0,0,114,170,0,0,0,114,185,0,0,0, - 114,195,0,0,0,114,212,0,0,0,114,229,0,0,0,114, - 234,0,0,0,114,240,0,0,0,114,235,0,0,0,114,241, - 0,0,0,114,3,1,0,0,114,5,1,0,0,114,19,1, - 0,0,114,37,1,0,0,114,163,0,0,0,114,44,1,0, - 0,114,46,1,0,0,114,2,0,0,0,114,2,0,0,0, - 114,2,0,0,0,114,4,0,0,0,218,8,60,109,111,100, - 117,108,101,62,23,0,0,0,115,118,0,0,0,4,0,4, - 1,4,1,2,1,6,3,8,17,8,5,8,5,8,6,8, - 12,8,10,8,9,8,5,8,7,10,22,10,127,0,3,16, - 1,12,2,4,1,4,2,6,2,6,2,8,2,16,45,8, - 34,8,19,8,12,8,12,8,28,8,17,8,33,8,28,8, - 24,10,13,10,10,10,11,8,14,6,3,4,1,14,67,14, - 64,14,29,16,127,0,17,14,68,18,45,18,26,4,3,18, - 53,14,60,14,42,14,127,0,7,14,127,0,22,10,23,8, - 11,8,64, + 0,0,218,16,95,108,101,103,97,99,121,95,103,101,116,95, + 115,112,101,99,201,4,0,0,115,18,0,0,0,0,4,10, + 1,16,2,10,1,4,1,8,1,12,1,12,1,6,1,122, + 27,80,97,116,104,70,105,110,100,101,114,46,95,108,101,103, + 97,99,121,95,103,101,116,95,115,112,101,99,78,99,4,0, + 0,0,0,0,0,0,9,0,0,0,5,0,0,0,67,0, + 0,0,115,170,0,0,0,103,0,125,4,120,160,124,2,68, + 0,93,130,125,5,116,0,124,5,116,1,116,2,102,2,131, + 2,115,30,113,10,124,0,160,3,124,5,161,1,125,6,124, + 6,100,1,107,9,114,10,116,4,124,6,100,2,131,2,114, + 72,124,6,160,5,124,1,124,3,161,2,125,7,110,12,124, + 0,160,6,124,1,124,6,161,2,125,7,124,7,100,1,107, + 8,114,94,113,10,124,7,106,7,100,1,107,9,114,108,124, + 7,83,0,124,7,106,8,125,8,124,8,100,1,107,8,114, + 130,116,9,100,3,131,1,130,1,124,4,160,10,124,8,161, + 1,1,0,113,10,87,0,116,11,160,12,124,1,100,1,161, + 2,125,7,124,4,124,7,95,8,124,7,83,0,100,1,83, + 0,41,4,122,63,70,105,110,100,32,116,104,101,32,108,111, + 97,100,101,114,32,111,114,32,110,97,109,101,115,112,97,99, + 101,95,112,97,116,104,32,102,111,114,32,116,104,105,115,32, + 109,111,100,117,108,101,47,112,97,99,107,97,103,101,32,110, + 97,109,101,46,78,114,182,0,0,0,122,19,115,112,101,99, + 32,109,105,115,115,105,110,103,32,108,111,97,100,101,114,41, + 13,114,141,0,0,0,114,71,0,0,0,218,5,98,121,116, + 101,115,114,14,1,0,0,114,110,0,0,0,114,182,0,0, + 0,114,15,1,0,0,114,122,0,0,0,114,158,0,0,0, + 114,101,0,0,0,114,147,0,0,0,114,116,0,0,0,114, + 162,0,0,0,41,9,114,172,0,0,0,114,121,0,0,0, + 114,35,0,0,0,114,181,0,0,0,218,14,110,97,109,101, + 115,112,97,99,101,95,112,97,116,104,90,5,101,110,116,114, + 121,114,10,1,0,0,114,166,0,0,0,114,123,0,0,0, + 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,218, + 9,95,103,101,116,95,115,112,101,99,216,4,0,0,115,40, + 0,0,0,0,5,4,1,10,1,14,1,2,1,10,1,8, + 1,10,1,14,2,12,1,8,1,2,1,10,1,4,1,6, + 1,8,1,8,5,14,2,12,1,6,1,122,20,80,97,116, + 104,70,105,110,100,101,114,46,95,103,101,116,95,115,112,101, + 99,99,4,0,0,0,0,0,0,0,6,0,0,0,5,0, + 0,0,67,0,0,0,115,100,0,0,0,124,2,100,1,107, + 8,114,14,116,0,106,1,125,2,124,0,160,2,124,1,124, + 2,124,3,161,3,125,4,124,4,100,1,107,8,114,40,100, + 1,83,0,124,4,106,3,100,1,107,8,114,92,124,4,106, + 4,125,5,124,5,114,86,100,1,124,4,95,5,116,6,124, + 1,124,5,124,0,106,2,131,3,124,4,95,4,124,4,83, + 0,100,1,83,0,110,4,124,4,83,0,100,1,83,0,41, + 2,122,141,84,114,121,32,116,111,32,102,105,110,100,32,97, + 32,115,112,101,99,32,102,111,114,32,39,102,117,108,108,110, + 97,109,101,39,32,111,110,32,115,121,115,46,112,97,116,104, + 32,111,114,32,39,112,97,116,104,39,46,10,10,32,32,32, + 32,32,32,32,32,84,104,101,32,115,101,97,114,99,104,32, + 105,115,32,98,97,115,101,100,32,111,110,32,115,121,115,46, + 112,97,116,104,95,104,111,111,107,115,32,97,110,100,32,115, + 121,115,46,112,97,116,104,95,105,109,112,111,114,116,101,114, + 95,99,97,99,104,101,46,10,32,32,32,32,32,32,32,32, + 78,41,7,114,6,0,0,0,114,35,0,0,0,114,18,1, + 0,0,114,122,0,0,0,114,158,0,0,0,114,160,0,0, + 0,114,241,0,0,0,41,6,114,172,0,0,0,114,121,0, + 0,0,114,35,0,0,0,114,181,0,0,0,114,166,0,0, + 0,114,17,1,0,0,114,2,0,0,0,114,2,0,0,0, + 114,4,0,0,0,114,182,0,0,0,248,4,0,0,115,26, + 0,0,0,0,6,8,1,6,1,14,1,8,1,4,1,10, + 1,6,1,4,3,6,1,16,1,4,2,6,2,122,20,80, + 97,116,104,70,105,110,100,101,114,46,102,105,110,100,95,115, + 112,101,99,99,3,0,0,0,0,0,0,0,4,0,0,0, + 4,0,0,0,67,0,0,0,115,30,0,0,0,124,0,160, + 0,124,1,124,2,161,2,125,3,124,3,100,1,107,8,114, + 24,100,1,83,0,124,3,106,1,83,0,41,2,122,170,102, + 105,110,100,32,116,104,101,32,109,111,100,117,108,101,32,111, + 110,32,115,121,115,46,112,97,116,104,32,111,114,32,39,112, + 97,116,104,39,32,98,97,115,101,100,32,111,110,32,115,121, + 115,46,112,97,116,104,95,104,111,111,107,115,32,97,110,100, + 10,32,32,32,32,32,32,32,32,115,121,115,46,112,97,116, + 104,95,105,109,112,111,114,116,101,114,95,99,97,99,104,101, + 46,10,10,32,32,32,32,32,32,32,32,84,104,105,115,32, + 109,101,116,104,111,100,32,105,115,32,100,101,112,114,101,99, + 97,116,101,100,46,32,32,85,115,101,32,102,105,110,100,95, + 115,112,101,99,40,41,32,105,110,115,116,101,97,100,46,10, + 10,32,32,32,32,32,32,32,32,78,41,2,114,182,0,0, + 0,114,122,0,0,0,41,4,114,172,0,0,0,114,121,0, + 0,0,114,35,0,0,0,114,166,0,0,0,114,2,0,0, + 0,114,2,0,0,0,114,4,0,0,0,114,183,0,0,0, + 16,5,0,0,115,8,0,0,0,0,8,12,1,8,1,4, + 1,122,22,80,97,116,104,70,105,110,100,101,114,46,102,105, + 110,100,95,109,111,100,117,108,101,41,1,78,41,2,78,78, + 41,1,78,41,12,114,107,0,0,0,114,106,0,0,0,114, + 108,0,0,0,114,109,0,0,0,114,184,0,0,0,114,6, + 1,0,0,114,12,1,0,0,114,14,1,0,0,114,15,1, + 0,0,114,18,1,0,0,114,182,0,0,0,114,183,0,0, + 0,114,2,0,0,0,114,2,0,0,0,114,2,0,0,0, + 114,4,0,0,0,114,5,1,0,0,152,4,0,0,115,22, + 0,0,0,8,2,4,2,12,10,12,13,12,22,12,15,2, + 1,12,31,2,1,12,23,2,1,114,5,1,0,0,99,0, + 0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,64, + 0,0,0,115,90,0,0,0,101,0,90,1,100,0,90,2, + 100,1,90,3,100,2,100,3,132,0,90,4,100,4,100,5, + 132,0,90,5,101,6,90,7,100,6,100,7,132,0,90,8, + 100,8,100,9,132,0,90,9,100,19,100,11,100,12,132,1, + 90,10,100,13,100,14,132,0,90,11,101,12,100,15,100,16, + 132,0,131,1,90,13,100,17,100,18,132,0,90,14,100,10, + 83,0,41,20,218,10,70,105,108,101,70,105,110,100,101,114, + 122,172,70,105,108,101,45,98,97,115,101,100,32,102,105,110, + 100,101,114,46,10,10,32,32,32,32,73,110,116,101,114,97, + 99,116,105,111,110,115,32,119,105,116,104,32,116,104,101,32, + 102,105,108,101,32,115,121,115,116,101,109,32,97,114,101,32, + 99,97,99,104,101,100,32,102,111,114,32,112,101,114,102,111, + 114,109,97,110,99,101,44,32,98,101,105,110,103,10,32,32, + 32,32,114,101,102,114,101,115,104,101,100,32,119,104,101,110, + 32,116,104,101,32,100,105,114,101,99,116,111,114,121,32,116, + 104,101,32,102,105,110,100,101,114,32,105,115,32,104,97,110, + 100,108,105,110,103,32,104,97,115,32,98,101,101,110,32,109, + 111,100,105,102,105,101,100,46,10,10,32,32,32,32,99,2, + 0,0,0,0,0,0,0,5,0,0,0,6,0,0,0,7, + 0,0,0,115,88,0,0,0,103,0,125,3,120,40,124,2, + 68,0,93,32,92,2,137,0,125,4,124,3,160,0,135,0, + 102,1,100,1,100,2,132,8,124,4,68,0,131,1,161,1, + 1,0,113,10,87,0,124,3,124,0,95,1,124,1,112,58, + 100,3,124,0,95,2,100,4,124,0,95,3,116,4,131,0, + 124,0,95,5,116,4,131,0,124,0,95,6,100,5,83,0, + 41,6,122,154,73,110,105,116,105,97,108,105,122,101,32,119, + 105,116,104,32,116,104,101,32,112,97,116,104,32,116,111,32, + 115,101,97,114,99,104,32,111,110,32,97,110,100,32,97,32, + 118,97,114,105,97,98,108,101,32,110,117,109,98,101,114,32, + 111,102,10,32,32,32,32,32,32,32,32,50,45,116,117,112, + 108,101,115,32,99,111,110,116,97,105,110,105,110,103,32,116, + 104,101,32,108,111,97,100,101,114,32,97,110,100,32,116,104, + 101,32,102,105,108,101,32,115,117,102,102,105,120,101,115,32, + 116,104,101,32,108,111,97,100,101,114,10,32,32,32,32,32, + 32,32,32,114,101,99,111,103,110,105,122,101,115,46,99,1, + 0,0,0,0,0,0,0,2,0,0,0,3,0,0,0,51, + 0,0,0,115,22,0,0,0,124,0,93,14,125,1,124,1, + 136,0,102,2,86,0,1,0,113,2,100,0,83,0,41,1, + 78,114,2,0,0,0,41,2,114,22,0,0,0,114,236,0, + 0,0,41,1,114,122,0,0,0,114,2,0,0,0,114,4, + 0,0,0,114,238,0,0,0,45,5,0,0,115,2,0,0, + 0,4,0,122,38,70,105,108,101,70,105,110,100,101,114,46, + 95,95,105,110,105,116,95,95,46,60,108,111,99,97,108,115, + 62,46,60,103,101,110,101,120,112,114,62,114,59,0,0,0, + 114,89,0,0,0,78,41,7,114,147,0,0,0,218,8,95, + 108,111,97,100,101,114,115,114,35,0,0,0,218,11,95,112, + 97,116,104,95,109,116,105,109,101,218,3,115,101,116,218,11, + 95,112,97,116,104,95,99,97,99,104,101,218,19,95,114,101, + 108,97,120,101,100,95,112,97,116,104,95,99,97,99,104,101, + 41,5,114,102,0,0,0,114,35,0,0,0,218,14,108,111, + 97,100,101,114,95,100,101,116,97,105,108,115,90,7,108,111, + 97,100,101,114,115,114,168,0,0,0,114,2,0,0,0,41, + 1,114,122,0,0,0,114,4,0,0,0,114,186,0,0,0, + 39,5,0,0,115,16,0,0,0,0,4,4,1,14,1,28, + 1,6,2,10,1,6,1,8,1,122,19,70,105,108,101,70, + 105,110,100,101,114,46,95,95,105,110,105,116,95,95,99,1, + 0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,67, + 0,0,0,115,10,0,0,0,100,1,124,0,95,0,100,2, + 83,0,41,3,122,31,73,110,118,97,108,105,100,97,116,101, + 32,116,104,101,32,100,105,114,101,99,116,111,114,121,32,109, + 116,105,109,101,46,114,89,0,0,0,78,41,1,114,21,1, + 0,0,41,1,114,102,0,0,0,114,2,0,0,0,114,2, + 0,0,0,114,4,0,0,0,114,6,1,0,0,53,5,0, + 0,115,2,0,0,0,0,2,122,28,70,105,108,101,70,105, + 110,100,101,114,46,105,110,118,97,108,105,100,97,116,101,95, + 99,97,99,104,101,115,99,2,0,0,0,0,0,0,0,3, + 0,0,0,3,0,0,0,67,0,0,0,115,42,0,0,0, + 124,0,160,0,124,1,161,1,125,2,124,2,100,1,107,8, + 114,26,100,1,103,0,102,2,83,0,124,2,106,1,124,2, + 106,2,112,38,103,0,102,2,83,0,41,2,122,197,84,114, + 121,32,116,111,32,102,105,110,100,32,97,32,108,111,97,100, + 101,114,32,102,111,114,32,116,104,101,32,115,112,101,99,105, + 102,105,101,100,32,109,111,100,117,108,101,44,32,111,114,32, + 116,104,101,32,110,97,109,101,115,112,97,99,101,10,32,32, + 32,32,32,32,32,32,112,97,99,107,97,103,101,32,112,111, + 114,116,105,111,110,115,46,32,82,101,116,117,114,110,115,32, + 40,108,111,97,100,101,114,44,32,108,105,115,116,45,111,102, + 45,112,111,114,116,105,111,110,115,41,46,10,10,32,32,32, + 32,32,32,32,32,84,104,105,115,32,109,101,116,104,111,100, + 32,105,115,32,100,101,112,114,101,99,97,116,101,100,46,32, + 32,85,115,101,32,102,105,110,100,95,115,112,101,99,40,41, + 32,105,110,115,116,101,97,100,46,10,10,32,32,32,32,32, + 32,32,32,78,41,3,114,182,0,0,0,114,122,0,0,0, + 114,158,0,0,0,41,3,114,102,0,0,0,114,121,0,0, + 0,114,166,0,0,0,114,2,0,0,0,114,2,0,0,0, + 114,4,0,0,0,114,119,0,0,0,59,5,0,0,115,8, + 0,0,0,0,7,10,1,8,1,8,1,122,22,70,105,108, + 101,70,105,110,100,101,114,46,102,105,110,100,95,108,111,97, + 100,101,114,99,6,0,0,0,0,0,0,0,7,0,0,0, + 6,0,0,0,67,0,0,0,115,26,0,0,0,124,1,124, + 2,124,3,131,2,125,6,116,0,124,2,124,3,124,6,124, + 4,100,1,141,4,83,0,41,2,78,41,2,114,122,0,0, + 0,114,158,0,0,0,41,1,114,169,0,0,0,41,7,114, + 102,0,0,0,114,167,0,0,0,114,121,0,0,0,114,35, + 0,0,0,90,4,115,109,115,108,114,181,0,0,0,114,122, + 0,0,0,114,2,0,0,0,114,2,0,0,0,114,4,0, + 0,0,114,18,1,0,0,71,5,0,0,115,6,0,0,0, + 0,1,10,1,8,1,122,20,70,105,108,101,70,105,110,100, + 101,114,46,95,103,101,116,95,115,112,101,99,78,99,3,0, + 0,0,0,0,0,0,14,0,0,0,8,0,0,0,67,0, + 0,0,115,98,1,0,0,100,1,125,3,124,1,160,0,100, + 2,161,1,100,3,25,0,125,4,121,24,116,1,124,0,106, + 2,112,34,116,3,160,4,161,0,131,1,106,5,125,5,87, + 0,110,24,4,0,116,6,107,10,114,66,1,0,1,0,1, + 0,100,4,125,5,89,0,110,2,88,0,124,5,124,0,106, + 7,107,3,114,92,124,0,160,8,161,0,1,0,124,5,124, + 0,95,7,116,9,131,0,114,114,124,0,106,10,125,6,124, + 4,160,11,161,0,125,7,110,10,124,0,106,12,125,6,124, + 4,125,7,124,7,124,6,107,6,114,218,116,13,124,0,106, + 2,124,4,131,2,125,8,120,72,124,0,106,14,68,0,93, + 54,92,2,125,9,125,10,100,5,124,9,23,0,125,11,116, + 13,124,8,124,11,131,2,125,12,116,15,124,12,131,1,114, + 152,124,0,160,16,124,10,124,1,124,12,124,8,103,1,124, + 2,161,5,83,0,113,152,87,0,116,17,124,8,131,1,125, + 3,120,88,124,0,106,14,68,0,93,78,92,2,125,9,125, + 10,116,13,124,0,106,2,124,4,124,9,23,0,131,2,125, + 12,116,18,106,19,100,6,124,12,100,3,100,7,141,3,1, + 0,124,7,124,9,23,0,124,6,107,6,114,226,116,15,124, + 12,131,1,114,226,124,0,160,16,124,10,124,1,124,12,100, + 8,124,2,161,5,83,0,113,226,87,0,124,3,144,1,114, + 94,116,18,160,19,100,9,124,8,161,2,1,0,116,18,160, + 20,124,1,100,8,161,2,125,13,124,8,103,1,124,13,95, + 21,124,13,83,0,100,8,83,0,41,10,122,111,84,114,121, + 32,116,111,32,102,105,110,100,32,97,32,115,112,101,99,32, + 102,111,114,32,116,104,101,32,115,112,101,99,105,102,105,101, + 100,32,109,111,100,117,108,101,46,10,10,32,32,32,32,32, + 32,32,32,82,101,116,117,114,110,115,32,116,104,101,32,109, + 97,116,99,104,105,110,103,32,115,112,101,99,44,32,111,114, + 32,78,111,110,101,32,105,102,32,110,111,116,32,102,111,117, + 110,100,46,10,32,32,32,32,32,32,32,32,70,114,59,0, + 0,0,114,57,0,0,0,114,89,0,0,0,114,186,0,0, + 0,122,9,116,114,121,105,110,103,32,123,125,41,1,90,9, + 118,101,114,98,111,115,105,116,121,78,122,25,112,111,115,115, + 105,98,108,101,32,110,97,109,101,115,112,97,99,101,32,102, + 111,114,32,123,125,41,22,114,32,0,0,0,114,39,0,0, + 0,114,35,0,0,0,114,1,0,0,0,114,45,0,0,0, + 114,230,0,0,0,114,40,0,0,0,114,21,1,0,0,218, + 11,95,102,105,108,108,95,99,97,99,104,101,114,5,0,0, + 0,114,24,1,0,0,114,90,0,0,0,114,23,1,0,0, + 114,28,0,0,0,114,20,1,0,0,114,44,0,0,0,114, + 18,1,0,0,114,46,0,0,0,114,116,0,0,0,114,130, + 0,0,0,114,162,0,0,0,114,158,0,0,0,41,14,114, + 102,0,0,0,114,121,0,0,0,114,181,0,0,0,90,12, + 105,115,95,110,97,109,101,115,112,97,99,101,90,11,116,97, + 105,108,95,109,111,100,117,108,101,114,149,0,0,0,90,5, + 99,97,99,104,101,90,12,99,97,99,104,101,95,109,111,100, + 117,108,101,90,9,98,97,115,101,95,112,97,116,104,114,236, + 0,0,0,114,167,0,0,0,90,13,105,110,105,116,95,102, + 105,108,101,110,97,109,101,90,9,102,117,108,108,95,112,97, + 116,104,114,166,0,0,0,114,2,0,0,0,114,2,0,0, + 0,114,4,0,0,0,114,182,0,0,0,76,5,0,0,115, + 70,0,0,0,0,5,4,1,14,1,2,1,24,1,14,1, + 10,1,10,1,8,1,6,2,6,1,6,1,10,2,6,1, + 4,2,8,1,12,1,16,1,8,1,10,1,8,1,24,4, + 8,2,16,1,16,1,16,1,12,1,8,1,10,1,12,1, + 6,1,12,1,12,1,8,1,4,1,122,20,70,105,108,101, + 70,105,110,100,101,114,46,102,105,110,100,95,115,112,101,99, + 99,1,0,0,0,0,0,0,0,9,0,0,0,10,0,0, + 0,67,0,0,0,115,194,0,0,0,124,0,106,0,125,1, + 121,22,116,1,160,2,124,1,112,22,116,1,160,3,161,0, + 161,1,125,2,87,0,110,30,4,0,116,4,116,5,116,6, + 102,3,107,10,114,58,1,0,1,0,1,0,103,0,125,2, + 89,0,110,2,88,0,116,7,106,8,160,9,100,1,161,1, + 115,84,116,10,124,2,131,1,124,0,95,11,110,78,116,10, + 131,0,125,3,120,64,124,2,68,0,93,56,125,4,124,4, + 160,12,100,2,161,1,92,3,125,5,125,6,125,7,124,6, + 114,138,100,3,160,13,124,5,124,7,160,14,161,0,161,2, + 125,8,110,4,124,5,125,8,124,3,160,15,124,8,161,1, + 1,0,113,96,87,0,124,3,124,0,95,11,116,7,106,8, + 160,9,116,16,161,1,114,190,100,4,100,5,132,0,124,2, + 68,0,131,1,124,0,95,17,100,6,83,0,41,7,122,68, + 70,105,108,108,32,116,104,101,32,99,97,99,104,101,32,111, + 102,32,112,111,116,101,110,116,105,97,108,32,109,111,100,117, + 108,101,115,32,97,110,100,32,112,97,99,107,97,103,101,115, + 32,102,111,114,32,116,104,105,115,32,100,105,114,101,99,116, + 111,114,121,46,114,0,0,0,0,114,59,0,0,0,122,5, + 123,125,46,123,125,99,1,0,0,0,0,0,0,0,2,0, + 0,0,4,0,0,0,83,0,0,0,115,20,0,0,0,104, + 0,124,0,93,12,125,1,124,1,160,0,161,0,146,2,113, + 4,83,0,114,2,0,0,0,41,1,114,90,0,0,0,41, + 2,114,22,0,0,0,90,2,102,110,114,2,0,0,0,114, + 2,0,0,0,114,4,0,0,0,250,9,60,115,101,116,99, + 111,109,112,62,153,5,0,0,115,2,0,0,0,6,0,122, + 41,70,105,108,101,70,105,110,100,101,114,46,95,102,105,108, + 108,95,99,97,99,104,101,46,60,108,111,99,97,108,115,62, + 46,60,115,101,116,99,111,109,112,62,78,41,18,114,35,0, + 0,0,114,1,0,0,0,114,227,0,0,0,114,45,0,0, + 0,114,224,0,0,0,218,15,80,101,114,109,105,115,115,105, + 111,110,69,114,114,111,114,218,18,78,111,116,65,68,105,114, + 101,99,116,111,114,121,69,114,114,111,114,114,6,0,0,0, + 114,7,0,0,0,114,8,0,0,0,114,22,1,0,0,114, + 23,1,0,0,114,85,0,0,0,114,48,0,0,0,114,90, + 0,0,0,218,3,97,100,100,114,9,0,0,0,114,24,1, + 0,0,41,9,114,102,0,0,0,114,35,0,0,0,114,228, + 0,0,0,90,21,108,111,119,101,114,95,115,117,102,102,105, + 120,95,99,111,110,116,101,110,116,115,114,1,1,0,0,114, + 100,0,0,0,114,248,0,0,0,114,236,0,0,0,90,8, + 110,101,119,95,110,97,109,101,114,2,0,0,0,114,2,0, + 0,0,114,4,0,0,0,114,26,1,0,0,124,5,0,0, + 115,34,0,0,0,0,2,6,1,2,1,22,1,20,3,10, + 3,12,1,12,7,6,1,10,1,16,1,4,1,18,2,4, + 1,14,1,6,1,12,1,122,22,70,105,108,101,70,105,110, + 100,101,114,46,95,102,105,108,108,95,99,97,99,104,101,99, + 1,0,0,0,0,0,0,0,3,0,0,0,3,0,0,0, + 7,0,0,0,115,18,0,0,0,135,0,135,1,102,2,100, + 1,100,2,132,8,125,2,124,2,83,0,41,3,97,20,1, + 0,0,65,32,99,108,97,115,115,32,109,101,116,104,111,100, + 32,119,104,105,99,104,32,114,101,116,117,114,110,115,32,97, + 32,99,108,111,115,117,114,101,32,116,111,32,117,115,101,32, + 111,110,32,115,121,115,46,112,97,116,104,95,104,111,111,107, + 10,32,32,32,32,32,32,32,32,119,104,105,99,104,32,119, + 105,108,108,32,114,101,116,117,114,110,32,97,110,32,105,110, + 115,116,97,110,99,101,32,117,115,105,110,103,32,116,104,101, + 32,115,112,101,99,105,102,105,101,100,32,108,111,97,100,101, + 114,115,32,97,110,100,32,116,104,101,32,112,97,116,104,10, + 32,32,32,32,32,32,32,32,99,97,108,108,101,100,32,111, + 110,32,116,104,101,32,99,108,111,115,117,114,101,46,10,10, + 32,32,32,32,32,32,32,32,73,102,32,116,104,101,32,112, + 97,116,104,32,99,97,108,108,101,100,32,111,110,32,116,104, + 101,32,99,108,111,115,117,114,101,32,105,115,32,110,111,116, + 32,97,32,100,105,114,101,99,116,111,114,121,44,32,73,109, + 112,111,114,116,69,114,114,111,114,32,105,115,10,32,32,32, + 32,32,32,32,32,114,97,105,115,101,100,46,10,10,32,32, + 32,32,32,32,32,32,99,1,0,0,0,0,0,0,0,1, + 0,0,0,4,0,0,0,19,0,0,0,115,34,0,0,0, + 116,0,124,0,131,1,115,20,116,1,100,1,124,0,100,2, + 141,2,130,1,136,0,124,0,102,1,136,1,158,2,142,0, + 83,0,41,3,122,45,80,97,116,104,32,104,111,111,107,32, + 102,111,114,32,105,109,112,111,114,116,108,105,98,46,109,97, + 99,104,105,110,101,114,121,46,70,105,108,101,70,105,110,100, + 101,114,46,122,30,111,110,108,121,32,100,105,114,101,99,116, + 111,114,105,101,115,32,97,114,101,32,115,117,112,112,111,114, + 116,101,100,41,1,114,35,0,0,0,41,2,114,46,0,0, + 0,114,101,0,0,0,41,1,114,35,0,0,0,41,2,114, + 172,0,0,0,114,25,1,0,0,114,2,0,0,0,114,4, + 0,0,0,218,24,112,97,116,104,95,104,111,111,107,95,102, + 111,114,95,70,105,108,101,70,105,110,100,101,114,165,5,0, + 0,115,6,0,0,0,0,2,8,1,12,1,122,54,70,105, + 108,101,70,105,110,100,101,114,46,112,97,116,104,95,104,111, + 111,107,46,60,108,111,99,97,108,115,62,46,112,97,116,104, + 95,104,111,111,107,95,102,111,114,95,70,105,108,101,70,105, + 110,100,101,114,114,2,0,0,0,41,3,114,172,0,0,0, + 114,25,1,0,0,114,31,1,0,0,114,2,0,0,0,41, + 2,114,172,0,0,0,114,25,1,0,0,114,4,0,0,0, + 218,9,112,97,116,104,95,104,111,111,107,155,5,0,0,115, + 4,0,0,0,0,10,14,6,122,20,70,105,108,101,70,105, + 110,100,101,114,46,112,97,116,104,95,104,111,111,107,99,1, + 0,0,0,0,0,0,0,1,0,0,0,3,0,0,0,67, + 0,0,0,115,12,0,0,0,100,1,160,0,124,0,106,1, + 161,1,83,0,41,2,78,122,16,70,105,108,101,70,105,110, + 100,101,114,40,123,33,114,125,41,41,2,114,48,0,0,0, + 114,35,0,0,0,41,1,114,102,0,0,0,114,2,0,0, + 0,114,2,0,0,0,114,4,0,0,0,114,0,1,0,0, + 173,5,0,0,115,2,0,0,0,0,1,122,19,70,105,108, + 101,70,105,110,100,101,114,46,95,95,114,101,112,114,95,95, + 41,1,78,41,15,114,107,0,0,0,114,106,0,0,0,114, + 108,0,0,0,114,109,0,0,0,114,186,0,0,0,114,6, + 1,0,0,114,125,0,0,0,114,183,0,0,0,114,119,0, + 0,0,114,18,1,0,0,114,182,0,0,0,114,26,1,0, + 0,114,184,0,0,0,114,32,1,0,0,114,0,1,0,0, + 114,2,0,0,0,114,2,0,0,0,114,2,0,0,0,114, + 4,0,0,0,114,19,1,0,0,30,5,0,0,115,20,0, + 0,0,8,7,4,2,8,14,8,4,4,2,8,12,8,5, + 10,48,8,31,12,18,114,19,1,0,0,99,4,0,0,0, + 0,0,0,0,6,0,0,0,8,0,0,0,67,0,0,0, + 115,146,0,0,0,124,0,160,0,100,1,161,1,125,4,124, + 0,160,0,100,2,161,1,125,5,124,4,115,66,124,5,114, + 36,124,5,106,1,125,4,110,30,124,2,124,3,107,2,114, + 56,116,2,124,1,124,2,131,2,125,4,110,10,116,3,124, + 1,124,2,131,2,125,4,124,5,115,84,116,4,124,1,124, + 2,124,4,100,3,141,3,125,5,121,36,124,5,124,0,100, + 2,60,0,124,4,124,0,100,1,60,0,124,2,124,0,100, + 4,60,0,124,3,124,0,100,5,60,0,87,0,110,20,4, + 0,116,5,107,10,114,140,1,0,1,0,1,0,89,0,110, + 2,88,0,100,0,83,0,41,6,78,218,10,95,95,108,111, + 97,100,101,114,95,95,218,8,95,95,115,112,101,99,95,95, + 41,1,114,122,0,0,0,90,8,95,95,102,105,108,101,95, + 95,90,10,95,95,99,97,99,104,101,100,95,95,41,6,218, + 3,103,101,116,114,122,0,0,0,114,234,0,0,0,114,229, + 0,0,0,114,169,0,0,0,218,9,69,120,99,101,112,116, + 105,111,110,41,6,90,2,110,115,114,100,0,0,0,90,8, + 112,97,116,104,110,97,109,101,90,9,99,112,97,116,104,110, + 97,109,101,114,122,0,0,0,114,166,0,0,0,114,2,0, + 0,0,114,2,0,0,0,114,4,0,0,0,218,14,95,102, + 105,120,95,117,112,95,109,111,100,117,108,101,179,5,0,0, + 115,34,0,0,0,0,2,10,1,10,1,4,1,4,1,8, + 1,8,1,12,2,10,1,4,1,14,1,2,1,8,1,8, + 1,8,1,12,1,14,2,114,37,1,0,0,99,0,0,0, + 0,0,0,0,0,3,0,0,0,3,0,0,0,67,0,0, + 0,115,38,0,0,0,116,0,116,1,160,2,161,0,102,2, + 125,0,116,3,116,4,102,2,125,1,116,5,116,6,102,2, + 125,2,124,0,124,1,124,2,103,3,83,0,41,1,122,95, + 82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111, + 102,32,102,105,108,101,45,98,97,115,101,100,32,109,111,100, + 117,108,101,32,108,111,97,100,101,114,115,46,10,10,32,32, + 32,32,69,97,99,104,32,105,116,101,109,32,105,115,32,97, + 32,116,117,112,108,101,32,40,108,111,97,100,101,114,44,32, + 115,117,102,102,105,120,101,115,41,46,10,32,32,32,32,41, + 7,114,235,0,0,0,114,143,0,0,0,218,18,101,120,116, + 101,110,115,105,111,110,95,115,117,102,102,105,120,101,115,114, + 229,0,0,0,114,86,0,0,0,114,234,0,0,0,114,76, + 0,0,0,41,3,90,10,101,120,116,101,110,115,105,111,110, + 115,90,6,115,111,117,114,99,101,90,8,98,121,116,101,99, + 111,100,101,114,2,0,0,0,114,2,0,0,0,114,4,0, + 0,0,114,163,0,0,0,202,5,0,0,115,8,0,0,0, + 0,5,12,1,8,1,8,1,114,163,0,0,0,99,1,0, + 0,0,0,0,0,0,12,0,0,0,9,0,0,0,67,0, + 0,0,115,156,1,0,0,124,0,97,0,116,0,106,1,97, + 1,116,0,106,2,97,2,116,1,106,3,116,4,25,0,125, + 1,120,56,100,1,68,0,93,48,125,2,124,2,116,1,106, + 3,107,7,114,58,116,0,160,5,124,2,161,1,125,3,110, + 10,116,1,106,3,124,2,25,0,125,3,116,6,124,1,124, + 2,124,3,131,3,1,0,113,32,87,0,100,2,100,3,103, + 1,102,2,100,4,100,5,100,3,103,2,102,2,102,2,125, + 4,120,118,124,4,68,0,93,102,92,2,125,5,125,6,116, + 7,100,6,100,7,132,0,124,6,68,0,131,1,131,1,115, + 142,116,8,130,1,124,6,100,8,25,0,125,7,124,5,116, + 1,106,3,107,6,114,174,116,1,106,3,124,5,25,0,125, + 8,80,0,113,112,121,16,116,0,160,5,124,5,161,1,125, + 8,80,0,87,0,113,112,4,0,116,9,107,10,114,212,1, + 0,1,0,1,0,119,112,89,0,113,112,88,0,113,112,87, + 0,116,9,100,9,131,1,130,1,116,6,124,1,100,10,124, + 8,131,3,1,0,116,6,124,1,100,11,124,7,131,3,1, + 0,116,6,124,1,100,12,100,13,160,10,124,6,161,1,131, + 3,1,0,116,0,160,5,100,14,161,1,125,9,116,6,124, + 1,100,14,124,9,131,3,1,0,116,0,160,5,100,15,161, + 1,125,10,116,6,124,1,100,15,124,10,131,3,1,0,124, + 5,100,4,107,2,144,1,114,88,116,0,160,5,100,16,161, + 1,125,11,116,6,124,1,100,17,124,11,131,3,1,0,116, + 6,124,1,100,18,116,11,131,0,131,3,1,0,116,12,160, + 13,116,2,160,14,161,0,161,1,1,0,124,5,100,4,107, + 2,144,1,114,152,116,15,160,16,100,19,161,1,1,0,100, + 20,116,12,107,6,144,1,114,152,100,21,116,17,95,18,100, + 22,83,0,41,23,122,205,83,101,116,117,112,32,116,104,101, + 32,112,97,116,104,45,98,97,115,101,100,32,105,109,112,111, + 114,116,101,114,115,32,102,111,114,32,105,109,112,111,114,116, + 108,105,98,32,98,121,32,105,109,112,111,114,116,105,110,103, + 32,110,101,101,100,101,100,10,32,32,32,32,98,117,105,108, + 116,45,105,110,32,109,111,100,117,108,101,115,32,97,110,100, + 32,105,110,106,101,99,116,105,110,103,32,116,104,101,109,32, + 105,110,116,111,32,116,104,101,32,103,108,111,98,97,108,32, + 110,97,109,101,115,112,97,99,101,46,10,10,32,32,32,32, + 79,116,104,101,114,32,99,111,109,112,111,110,101,110,116,115, + 32,97,114,101,32,101,120,116,114,97,99,116,101,100,32,102, + 114,111,109,32,116,104,101,32,99,111,114,101,32,98,111,111, + 116,115,116,114,97,112,32,109,111,100,117,108,101,46,10,10, + 32,32,32,32,41,4,114,50,0,0,0,114,61,0,0,0, + 218,8,98,117,105,108,116,105,110,115,114,140,0,0,0,90, + 5,112,111,115,105,120,250,1,47,90,2,110,116,250,1,92, + 99,1,0,0,0,0,0,0,0,2,0,0,0,3,0,0, + 0,115,0,0,0,115,26,0,0,0,124,0,93,18,125,1, + 116,0,124,1,131,1,100,0,107,2,86,0,1,0,113,2, + 100,1,83,0,41,2,114,29,0,0,0,78,41,1,114,31, + 0,0,0,41,2,114,22,0,0,0,114,79,0,0,0,114, + 2,0,0,0,114,2,0,0,0,114,4,0,0,0,114,238, + 0,0,0,238,5,0,0,115,2,0,0,0,4,0,122,25, + 95,115,101,116,117,112,46,60,108,111,99,97,108,115,62,46, + 60,103,101,110,101,120,112,114,62,114,60,0,0,0,122,30, + 105,109,112,111,114,116,108,105,98,32,114,101,113,117,105,114, + 101,115,32,112,111,115,105,120,32,111,114,32,110,116,114,1, + 0,0,0,114,25,0,0,0,114,21,0,0,0,114,30,0, + 0,0,90,7,95,116,104,114,101,97,100,90,8,95,119,101, + 97,107,114,101,102,90,6,119,105,110,114,101,103,114,171,0, + 0,0,114,5,0,0,0,122,4,46,112,121,119,122,6,95, + 100,46,112,121,100,84,78,41,19,114,116,0,0,0,114,6, + 0,0,0,114,143,0,0,0,114,250,0,0,0,114,107,0, + 0,0,90,18,95,98,117,105,108,116,105,110,95,102,114,111, + 109,95,110,97,109,101,114,111,0,0,0,218,3,97,108,108, + 114,151,0,0,0,114,101,0,0,0,114,26,0,0,0,114, + 11,0,0,0,114,240,0,0,0,114,147,0,0,0,114,38, + 1,0,0,114,86,0,0,0,114,165,0,0,0,114,170,0, + 0,0,114,174,0,0,0,41,12,218,17,95,98,111,111,116, + 115,116,114,97,112,95,109,111,100,117,108,101,90,11,115,101, + 108,102,95,109,111,100,117,108,101,90,12,98,117,105,108,116, + 105,110,95,110,97,109,101,90,14,98,117,105,108,116,105,110, + 95,109,111,100,117,108,101,90,10,111,115,95,100,101,116,97, + 105,108,115,90,10,98,117,105,108,116,105,110,95,111,115,114, + 21,0,0,0,114,25,0,0,0,90,9,111,115,95,109,111, + 100,117,108,101,90,13,116,104,114,101,97,100,95,109,111,100, + 117,108,101,90,14,119,101,97,107,114,101,102,95,109,111,100, + 117,108,101,90,13,119,105,110,114,101,103,95,109,111,100,117, + 108,101,114,2,0,0,0,114,2,0,0,0,114,4,0,0, + 0,218,6,95,115,101,116,117,112,213,5,0,0,115,76,0, + 0,0,0,8,4,1,6,1,6,3,10,1,10,1,10,1, + 12,2,10,1,16,3,22,1,14,2,22,1,8,1,10,1, + 10,1,4,2,2,1,10,1,6,1,14,1,12,2,8,1, + 12,1,12,1,18,3,10,1,12,3,10,1,12,3,10,1, + 10,1,12,3,14,1,14,1,10,1,10,1,10,1,114,44, + 1,0,0,99,1,0,0,0,0,0,0,0,2,0,0,0, + 4,0,0,0,67,0,0,0,115,50,0,0,0,116,0,124, + 0,131,1,1,0,116,1,131,0,125,1,116,2,106,3,160, + 4,116,5,106,6,124,1,142,0,103,1,161,1,1,0,116, + 2,106,7,160,8,116,9,161,1,1,0,100,1,83,0,41, + 2,122,41,73,110,115,116,97,108,108,32,116,104,101,32,112, + 97,116,104,45,98,97,115,101,100,32,105,109,112,111,114,116, + 32,99,111,109,112,111,110,101,110,116,115,46,78,41,10,114, + 44,1,0,0,114,163,0,0,0,114,6,0,0,0,114,11, + 1,0,0,114,147,0,0,0,114,19,1,0,0,114,32,1, + 0,0,218,9,109,101,116,97,95,112,97,116,104,114,165,0, + 0,0,114,5,1,0,0,41,2,114,43,1,0,0,90,17, + 115,117,112,112,111,114,116,101,100,95,108,111,97,100,101,114, + 115,114,2,0,0,0,114,2,0,0,0,114,4,0,0,0, + 218,8,95,105,110,115,116,97,108,108,21,6,0,0,115,8, + 0,0,0,0,2,8,1,6,1,20,1,114,46,1,0,0, + 41,1,114,47,0,0,0,41,1,78,41,3,78,78,78,41, + 2,114,60,0,0,0,114,60,0,0,0,41,1,84,41,1, + 78,41,1,78,41,61,114,109,0,0,0,114,10,0,0,0, + 90,37,95,67,65,83,69,95,73,78,83,69,78,83,73,84, + 73,86,69,95,80,76,65,84,70,79,82,77,83,95,66,89, + 84,69,83,95,75,69,89,114,9,0,0,0,114,11,0,0, + 0,114,17,0,0,0,114,19,0,0,0,114,28,0,0,0, + 114,38,0,0,0,114,39,0,0,0,114,43,0,0,0,114, + 44,0,0,0,114,46,0,0,0,114,56,0,0,0,218,4, + 116,121,112,101,218,8,95,95,99,111,100,101,95,95,114,142, + 0,0,0,114,15,0,0,0,114,129,0,0,0,114,14,0, + 0,0,114,18,0,0,0,114,209,0,0,0,114,75,0,0, + 0,114,74,0,0,0,114,86,0,0,0,114,76,0,0,0, + 90,23,68,69,66,85,71,95,66,89,84,69,67,79,68,69, + 95,83,85,70,70,73,88,69,83,90,27,79,80,84,73,77, + 73,90,69,68,95,66,89,84,69,67,79,68,69,95,83,85, + 70,70,73,88,69,83,114,81,0,0,0,114,87,0,0,0, + 114,93,0,0,0,114,97,0,0,0,114,99,0,0,0,114, + 118,0,0,0,114,125,0,0,0,114,133,0,0,0,114,137, + 0,0,0,114,139,0,0,0,114,145,0,0,0,114,150,0, + 0,0,114,152,0,0,0,114,157,0,0,0,218,6,111,98, + 106,101,99,116,114,164,0,0,0,114,169,0,0,0,114,170, + 0,0,0,114,185,0,0,0,114,195,0,0,0,114,212,0, + 0,0,114,229,0,0,0,114,234,0,0,0,114,240,0,0, + 0,114,235,0,0,0,114,241,0,0,0,114,3,1,0,0, + 114,5,1,0,0,114,19,1,0,0,114,37,1,0,0,114, + 163,0,0,0,114,44,1,0,0,114,46,1,0,0,114,2, + 0,0,0,114,2,0,0,0,114,2,0,0,0,114,4,0, + 0,0,218,8,60,109,111,100,117,108,101,62,8,0,0,0, + 115,118,0,0,0,4,15,4,1,4,1,2,1,6,3,8, + 17,8,5,8,5,8,6,8,12,8,10,8,9,8,5,8, + 7,10,22,10,127,0,5,16,1,12,2,4,1,4,2,6, + 2,6,2,8,2,16,45,8,34,8,19,8,12,8,12,8, + 28,8,17,8,33,8,28,8,24,10,13,10,10,10,11,8, + 14,6,3,4,1,14,67,14,64,14,29,16,127,0,17,14, + 68,18,45,18,26,4,3,18,53,14,60,14,42,14,127,0, + 7,14,127,0,22,10,23,8,11,8,64, }; diff --git a/Tools/parser/unparse.py b/Tools/parser/unparse.py index 3eb63108c590..7e1cc4ea5db9 100644 --- a/Tools/parser/unparse.py +++ b/Tools/parser/unparse.py @@ -71,8 +71,6 @@ def dispatch(self, tree): ######################################################## def _Module(self, tree): - if tree.docstring is not None: - self.fill(repr(tree.docstring)) for stmt in tree.body: self.dispatch(stmt) @@ -237,8 +235,6 @@ def _ClassDef(self, t): self.write(")") self.enter() - if t.docstring is not None: - self.fill(repr(t.docstring)) self.dispatch(t.body) self.leave() @@ -261,8 +257,6 @@ def __FunctionDef_helper(self, t, fill_suffix): self.write(" -> ") self.dispatch(t.returns) self.enter() - if t.docstring is not None: - self.fill(repr(t.docstring)) self.dispatch(t.body) self.leave() From webhook-mailer at python.org Tue May 29 05:02:52 2018 From: webhook-mailer at python.org (Andrew Svetlov) Date: Tue, 29 May 2018 09:02:52 -0000 Subject: [Python-checkins] bpo-33654: Support protocol type switching in SSLTransport.set_protocol() (#7194) Message-ID: <mailman.52.1527584573.2800.python-checkins@python.org> https://github.com/python/cpython/commit/2179022d94937d7b0600b0dc192ca6fa5f53d830 commit: 2179022d94937d7b0600b0dc192ca6fa5f53d830 branch: master author: Yury Selivanov <yury at magic.io> committer: Andrew Svetlov <andrew.svetlov at gmail.com> date: 2018-05-29T12:02:40+03:00 summary: bpo-33654: Support protocol type switching in SSLTransport.set_protocol() (#7194) files: A Misc/NEWS.d/next/Library/2018-05-29-01-13-39.bpo-33654.sa81Si.rst M Lib/asyncio/sslproto.py M Lib/test/test_asyncio/test_sslproto.py diff --git a/Lib/asyncio/sslproto.py b/Lib/asyncio/sslproto.py index ab43e93b28bc..a6d382ecd3de 100644 --- a/Lib/asyncio/sslproto.py +++ b/Lib/asyncio/sslproto.py @@ -295,7 +295,7 @@ def get_extra_info(self, name, default=None): return self._ssl_protocol._get_extra_info(name, default) def set_protocol(self, protocol): - self._ssl_protocol._app_protocol = protocol + self._ssl_protocol._set_app_protocol(protocol) def get_protocol(self): return self._ssl_protocol._app_protocol @@ -440,9 +440,7 @@ def __init__(self, loop, app_protocol, sslcontext, waiter, self._waiter = waiter self._loop = loop - self._app_protocol = app_protocol - self._app_protocol_is_buffer = \ - isinstance(app_protocol, protocols.BufferedProtocol) + self._set_app_protocol(app_protocol) self._app_transport = _SSLProtocolTransport(self._loop, self) # _SSLPipe instance (None until the connection is made) self._sslpipe = None @@ -454,6 +452,11 @@ def __init__(self, loop, app_protocol, sslcontext, waiter, self._call_connection_made = call_connection_made self._ssl_handshake_timeout = ssl_handshake_timeout + def _set_app_protocol(self, app_protocol): + self._app_protocol = app_protocol + self._app_protocol_is_buffer = \ + isinstance(app_protocol, protocols.BufferedProtocol) + def _wakeup_waiter(self, exc=None): if self._waiter is None: return diff --git a/Lib/test/test_asyncio/test_sslproto.py b/Lib/test/test_asyncio/test_sslproto.py index 1b2f9d2a3a2a..fa9cbd56ed42 100644 --- a/Lib/test/test_asyncio/test_sslproto.py +++ b/Lib/test/test_asyncio/test_sslproto.py @@ -302,6 +302,7 @@ def test_start_tls_client_buf_proto_1(self): server_context = test_utils.simple_server_sslcontext() client_context = test_utils.simple_client_sslcontext() + client_con_made_calls = 0 def serve(sock): sock.settimeout(self.TIMEOUT) @@ -315,20 +316,21 @@ def serve(sock): data = sock.recv_all(len(HELLO_MSG)) self.assertEqual(len(data), len(HELLO_MSG)) + sock.sendall(b'2') + data = sock.recv_all(len(HELLO_MSG)) + self.assertEqual(len(data), len(HELLO_MSG)) + sock.shutdown(socket.SHUT_RDWR) sock.close() - class ClientProto(asyncio.BufferedProtocol): - def __init__(self, on_data, on_eof): + class ClientProtoFirst(asyncio.BufferedProtocol): + def __init__(self, on_data): self.on_data = on_data - self.on_eof = on_eof - self.con_made_cnt = 0 self.buf = bytearray(1) - def connection_made(proto, tr): - proto.con_made_cnt += 1 - # Ensure connection_made gets called only once. - self.assertEqual(proto.con_made_cnt, 1) + def connection_made(self, tr): + nonlocal client_con_made_calls + client_con_made_calls += 1 def get_buffer(self, sizehint): return self.buf @@ -337,27 +339,50 @@ def buffer_updated(self, nsize): assert nsize == 1 self.on_data.set_result(bytes(self.buf[:nsize])) + class ClientProtoSecond(asyncio.Protocol): + def __init__(self, on_data, on_eof): + self.on_data = on_data + self.on_eof = on_eof + self.con_made_cnt = 0 + + def connection_made(self, tr): + nonlocal client_con_made_calls + client_con_made_calls += 1 + + def data_received(self, data): + self.on_data.set_result(data) + def eof_received(self): self.on_eof.set_result(True) async def client(addr): await asyncio.sleep(0.5, loop=self.loop) - on_data = self.loop.create_future() + on_data1 = self.loop.create_future() + on_data2 = self.loop.create_future() on_eof = self.loop.create_future() tr, proto = await self.loop.create_connection( - lambda: ClientProto(on_data, on_eof), *addr) + lambda: ClientProtoFirst(on_data1), *addr) tr.write(HELLO_MSG) new_tr = await self.loop.start_tls(tr, proto, client_context) - self.assertEqual(await on_data, b'O') + self.assertEqual(await on_data1, b'O') + new_tr.write(HELLO_MSG) + + new_tr.set_protocol(ClientProtoSecond(on_data2, on_eof)) + self.assertEqual(await on_data2, b'2') new_tr.write(HELLO_MSG) await on_eof new_tr.close() + # connection_made() should be called only once -- when + # we establish connection for the first time. Start TLS + # doesn't call connection_made() on application protocols. + self.assertEqual(client_con_made_calls, 1) + with self.tcp_server(serve, timeout=self.TIMEOUT) as srv: self.loop.run_until_complete( asyncio.wait_for(client(srv.addr), diff --git a/Misc/NEWS.d/next/Library/2018-05-29-01-13-39.bpo-33654.sa81Si.rst b/Misc/NEWS.d/next/Library/2018-05-29-01-13-39.bpo-33654.sa81Si.rst new file mode 100644 index 000000000000..39e8e615d8c4 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-29-01-13-39.bpo-33654.sa81Si.rst @@ -0,0 +1 @@ +Support protocol type switching in SSLTransport.set_protocol(). From webhook-mailer at python.org Tue May 29 05:05:00 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Tue, 29 May 2018 09:05:00 -0000 Subject: [Python-checkins] bpo-32911: Revert bpo-29463. (GH-7121) (GH-7197) Message-ID: <mailman.53.1527584706.2800.python-checkins@python.org> https://github.com/python/cpython/commit/73cbe7a01a22d02dbe1ec841e8779c775cad3d08 commit: 73cbe7a01a22d02dbe1ec841e8779c775cad3d08 branch: master author: Serhiy Storchaka <storchaka at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-29T12:04:55+03:00 summary: bpo-32911: Revert bpo-29463. (GH-7121) (GH-7197) Remove the docstring attribute of AST types and restore docstring expression as a first stmt in their body. Co-authored-by: INADA Naoki <methane at users.noreply.github.com> files: A Misc/NEWS.d/next/Core and Builtins/2018-02-27-20-57-00.bpo-32911.cmKfco.rst M Doc/library/ast.rst M Doc/whatsnew/3.7.rst M Include/Python-ast.h M Lib/ast.py M Lib/test/test_ast.py M Lib/test/test_opcodes.py M Misc/NEWS.d/3.7.0a1.rst M Parser/Python.asdl M Python/Python-ast.c M Python/ast.c M Python/ast_opt.c M Python/compile.c M Python/future.c M Python/importlib.h M Python/importlib_external.h M Tools/parser/unparse.py diff --git a/Doc/library/ast.rst b/Doc/library/ast.rst index a75a6afbf2d7..9ff422cdf503 100644 --- a/Doc/library/ast.rst +++ b/Doc/library/ast.rst @@ -151,10 +151,6 @@ and classes for traversing abstract syntax trees: .. versionchanged:: 3.5 :class:`AsyncFunctionDef` is now supported. - .. versionchanged:: 3.7 - The docstring is now exported from the node docstring field, instead of - the first body statement. - .. function:: fix_missing_locations(node) diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index b466e74cffb4..8b94cdcc9e6a 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -2161,13 +2161,6 @@ Changes in Python Behavior Changes in the Python API ------------------------- -* ``Module``, ``FunctionDef``, ``AsyncFunctionDef``, and - ``ClassDef`` AST nodes now have the new ``docstring`` attribute. - The first statement in their body is not considered as a docstring - anymore. ``co_firstlineno`` and ``co_lnotab`` of code object for class - and module are affected by this change. (Contributed by INADA Naoki and - Eugene Toder in :issue:`29463`.) - * :meth:`socketserver.ThreadingMixIn.server_close` now waits until all non-daemon threads complete. Set the new :attr:`socketserver.ThreadingMixIn.block_on_close` class attribute to diff --git a/Include/Python-ast.h b/Include/Python-ast.h index 26dfef8fe153..8e0f750a8250 100644 --- a/Include/Python-ast.h +++ b/Include/Python-ast.h @@ -46,7 +46,6 @@ struct _mod { union { struct { asdl_seq *body; - string docstring; } Module; struct { @@ -81,7 +80,6 @@ struct _stmt { asdl_seq *body; asdl_seq *decorator_list; expr_ty returns; - string docstring; } FunctionDef; struct { @@ -90,7 +88,6 @@ struct _stmt { asdl_seq *body; asdl_seq *decorator_list; expr_ty returns; - string docstring; } AsyncFunctionDef; struct { @@ -99,7 +96,6 @@ struct _stmt { asdl_seq *keywords; asdl_seq *body; asdl_seq *decorator_list; - string docstring; } ClassDef; struct { @@ -443,27 +439,26 @@ struct _withitem { }; -#define Module(a0, a1, a2) _Py_Module(a0, a1, a2) -mod_ty _Py_Module(asdl_seq * body, string docstring, PyArena *arena); +#define Module(a0, a1) _Py_Module(a0, a1) +mod_ty _Py_Module(asdl_seq * body, PyArena *arena); #define Interactive(a0, a1) _Py_Interactive(a0, a1) mod_ty _Py_Interactive(asdl_seq * body, PyArena *arena); #define Expression(a0, a1) _Py_Expression(a0, a1) mod_ty _Py_Expression(expr_ty body, PyArena *arena); #define Suite(a0, a1) _Py_Suite(a0, a1) mod_ty _Py_Suite(asdl_seq * body, PyArena *arena); -#define FunctionDef(a0, a1, a2, a3, a4, a5, a6, a7, a8) _Py_FunctionDef(a0, a1, a2, a3, a4, a5, a6, a7, a8) +#define FunctionDef(a0, a1, a2, a3, a4, a5, a6, a7) _Py_FunctionDef(a0, a1, a2, a3, a4, a5, a6, a7) stmt_ty _Py_FunctionDef(identifier name, arguments_ty args, asdl_seq * body, - asdl_seq * decorator_list, expr_ty returns, string - docstring, int lineno, int col_offset, PyArena *arena); -#define AsyncFunctionDef(a0, a1, a2, a3, a4, a5, a6, a7, a8) _Py_AsyncFunctionDef(a0, a1, a2, a3, a4, a5, a6, a7, a8) + asdl_seq * decorator_list, expr_ty returns, int lineno, + int col_offset, PyArena *arena); +#define AsyncFunctionDef(a0, a1, a2, a3, a4, a5, a6, a7) _Py_AsyncFunctionDef(a0, a1, a2, a3, a4, a5, a6, a7) stmt_ty _Py_AsyncFunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq * decorator_list, expr_ty returns, - string docstring, int lineno, int col_offset, - PyArena *arena); -#define ClassDef(a0, a1, a2, a3, a4, a5, a6, a7, a8) _Py_ClassDef(a0, a1, a2, a3, a4, a5, a6, a7, a8) + int lineno, int col_offset, PyArena *arena); +#define ClassDef(a0, a1, a2, a3, a4, a5, a6, a7) _Py_ClassDef(a0, a1, a2, a3, a4, a5, a6, a7) stmt_ty _Py_ClassDef(identifier name, asdl_seq * bases, asdl_seq * keywords, - asdl_seq * body, asdl_seq * decorator_list, string - docstring, int lineno, int col_offset, PyArena *arena); + asdl_seq * body, asdl_seq * decorator_list, int lineno, + int col_offset, PyArena *arena); #define Return(a0, a1, a2, a3) _Py_Return(a0, a1, a2, a3) stmt_ty _Py_Return(expr_ty value, int lineno, int col_offset, PyArena *arena); #define Delete(a0, a1, a2, a3) _Py_Delete(a0, a1, a2, a3) diff --git a/Lib/ast.py b/Lib/ast.py index 2ecb03f38bc0..134d9d27582e 100644 --- a/Lib/ast.py +++ b/Lib/ast.py @@ -206,7 +206,15 @@ def get_docstring(node, clean=True): """ if not isinstance(node, (AsyncFunctionDef, FunctionDef, ClassDef, Module)): raise TypeError("%r can't have docstrings" % node.__class__.__name__) - text = node.docstring + if not node.body: + return None + node = node.body[0].value + if isinstance(node, Str): + text = node.s + elif isinstance(node, Constant) and isinstance(node.value, str): + text = node.value + else: + return None if clean and text: import inspect text = inspect.cleandoc(text) diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py index 67f363ad31f3..ab32d9d389e6 100644 --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -327,24 +327,9 @@ def test_classattrs(self): def test_module(self): body = [ast.Num(42)] - x = ast.Module(body, None) + x = ast.Module(body) self.assertEqual(x.body, body) - def test_docstring(self): - body = [] # AST nodes having docstring must accept empty body - x = ast.Module(body, "module docstring") - self.assertEqual(x.docstring, "module docstring") - - a = ast.arguments() - x = ast.FunctionDef("x", a, body, [], None, "func docstring") - self.assertEqual(x.docstring, "func docstring") - - x = ast.AsyncFunctionDef("x", a, body, [], None, "async func docstring") - self.assertEqual(x.docstring, "async func docstring") - - x = ast.ClassDef("x", [], [], body, [], "class docstring") - self.assertEqual(x.docstring, "class docstring") - def test_nodeclasses(self): # Zero arguments constructor explicitly allowed x = ast.BinOp() @@ -411,13 +396,13 @@ def test_pickling(self): def test_invalid_sum(self): pos = dict(lineno=2, col_offset=3) - m = ast.Module([ast.Expr(ast.expr(**pos), **pos)], "doc") + m = ast.Module([ast.Expr(ast.expr(**pos), **pos)]) with self.assertRaises(TypeError) as cm: compile(m, "<test>", "exec") self.assertIn("but got <_ast.expr", str(cm.exception)) def test_invalid_identitifer(self): - m = ast.Module([ast.Expr(ast.Name(42, ast.Load()))], None) + m = ast.Module([ast.Expr(ast.Name(42, ast.Load()))]) ast.fix_missing_locations(m) with self.assertRaises(TypeError) as cm: compile(m, "<test>", "exec") @@ -462,18 +447,18 @@ def test_dump(self): self.assertEqual(ast.dump(node), "Module(body=[Expr(value=Call(func=Name(id='spam', ctx=Load()), " "args=[Name(id='eggs', ctx=Load()), Str(s='and cheese')], " - "keywords=[]))], docstring=None)" + "keywords=[]))])" ) self.assertEqual(ast.dump(node, annotate_fields=False), "Module([Expr(Call(Name('spam', Load()), [Name('eggs', Load()), " - "Str('and cheese')], []))], None)" + "Str('and cheese')], []))])" ) self.assertEqual(ast.dump(node, include_attributes=True), "Module(body=[Expr(value=Call(func=Name(id='spam', ctx=Load(), " "lineno=1, col_offset=0), args=[Name(id='eggs', ctx=Load(), " "lineno=1, col_offset=5), Str(s='and cheese', lineno=1, " "col_offset=11)], keywords=[], " - "lineno=1, col_offset=0), lineno=1, col_offset=0)], docstring=None)" + "lineno=1, col_offset=0), lineno=1, col_offset=0)])" ) def test_copy_location(self): @@ -498,7 +483,7 @@ def test_fix_missing_locations(self): "Expr(value=Call(func=Name(id='spam', ctx=Load(), lineno=1, " "col_offset=0), args=[Str(s='eggs', lineno=1, col_offset=0)], " "keywords=[], lineno=1, " - "col_offset=0), lineno=1, col_offset=0)], docstring=None)" + "col_offset=0), lineno=1, col_offset=0)])" ) def test_increment_lineno(self): @@ -589,7 +574,7 @@ def test_bad_integer(self): names=[ast.alias(name='sleep')], level=None, lineno=None, col_offset=None)] - mod = ast.Module(body, None) + mod = ast.Module(body) with self.assertRaises(ValueError) as cm: compile(mod, 'test', 'exec') self.assertIn("invalid integer value: None", str(cm.exception)) @@ -599,7 +584,7 @@ def test_level_as_none(self): names=[ast.alias(name='sleep')], level=None, lineno=0, col_offset=0)] - mod = ast.Module(body, None) + mod = ast.Module(body) code = compile(mod, 'test', 'exec') ns = {} exec(code, ns) @@ -617,11 +602,11 @@ def mod(self, mod, msg=None, mode="exec", *, exc=ValueError): self.assertIn(msg, str(cm.exception)) def expr(self, node, msg=None, *, exc=ValueError): - mod = ast.Module([ast.Expr(node)], None) + mod = ast.Module([ast.Expr(node)]) self.mod(mod, msg, exc=exc) def stmt(self, stmt, msg=None): - mod = ast.Module([stmt], None) + mod = ast.Module([stmt]) self.mod(mod, msg) def test_module(self): @@ -663,16 +648,16 @@ def arguments(args=None, vararg=None, def test_funcdef(self): a = ast.arguments([], None, [], [], None, []) - f = ast.FunctionDef("x", a, [], [], None, None) + f = ast.FunctionDef("x", a, [], [], None) self.stmt(f, "empty body on FunctionDef") f = ast.FunctionDef("x", a, [ast.Pass()], [ast.Name("x", ast.Store())], - None, None) + None) self.stmt(f, "must have Load context") f = ast.FunctionDef("x", a, [ast.Pass()], [], - ast.Name("x", ast.Store()), None) + ast.Name("x", ast.Store())) self.stmt(f, "must have Load context") def fac(args): - return ast.FunctionDef("x", args, [ast.Pass()], [], None, None) + return ast.FunctionDef("x", args, [ast.Pass()], [], None) self._check_arguments(fac, self.stmt) def test_classdef(self): @@ -686,7 +671,7 @@ def cls(bases=None, keywords=None, body=None, decorator_list=None): if decorator_list is None: decorator_list = [] return ast.ClassDef("myclass", bases, keywords, - body, decorator_list, None) + body, decorator_list) self.stmt(cls(bases=[ast.Name("x", ast.Store())]), "must have Load context") self.stmt(cls(keywords=[ast.keyword("x", ast.Name("x", ast.Store()))]), @@ -1124,53 +1109,53 @@ def main(): #### EVERYTHING BELOW IS GENERATED ##### exec_results = [ -('Module', [('Expr', (1, 0), ('NameConstant', (1, 0), None))], None), -('Module', [], 'module docstring'), -('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('Pass', (1, 9))], [], None, None)], None), -('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [], [], None, 'function docstring')], None), -('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None)], None, [], [], None, []), [('Pass', (1, 10))], [], None, None)], None), -('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None)], None, [], [], None, [('Num', (1, 8), 0)]), [('Pass', (1, 12))], [], None, None)], None), -('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], ('arg', (1, 7), 'args', None), [], [], None, []), [('Pass', (1, 14))], [], None, None)], None), -('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], ('arg', (1, 8), 'kwargs', None), []), [('Pass', (1, 17))], [], None, None)], None), -('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None), ('arg', (1, 9), 'b', None), ('arg', (1, 14), 'c', None), ('arg', (1, 22), 'd', None), ('arg', (1, 28), 'e', None)], ('arg', (1, 35), 'args', None), [('arg', (1, 41), 'f', None)], [('Num', (1, 43), 42)], ('arg', (1, 49), 'kwargs', None), [('Num', (1, 11), 1), ('NameConstant', (1, 16), None), ('List', (1, 24), [], ('Load',)), ('Dict', (1, 30), [], [])]), [], [], None, 'doc for f()')], None), -('Module', [('ClassDef', (1, 0), 'C', [], [], [('Pass', (1, 8))], [], None)], None), -('Module', [('ClassDef', (1, 0), 'C', [], [], [], [], 'docstring for class C')], None), -('Module', [('ClassDef', (1, 0), 'C', [('Name', (1, 8), 'object', ('Load',))], [], [('Pass', (1, 17))], [], None)], None), -('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('Return', (1, 8), ('Num', (1, 15), 1))], [], None, None)], None), -('Module', [('Delete', (1, 0), [('Name', (1, 4), 'v', ('Del',))])], None), -('Module', [('Assign', (1, 0), [('Name', (1, 0), 'v', ('Store',))], ('Num', (1, 4), 1))], None), -('Module', [('AugAssign', (1, 0), ('Name', (1, 0), 'v', ('Store',)), ('Add',), ('Num', (1, 5), 1))], None), -('Module', [('For', (1, 0), ('Name', (1, 4), 'v', ('Store',)), ('Name', (1, 9), 'v', ('Load',)), [('Pass', (1, 11))], [])], None), -('Module', [('While', (1, 0), ('Name', (1, 6), 'v', ('Load',)), [('Pass', (1, 8))], [])], None), -('Module', [('If', (1, 0), ('Name', (1, 3), 'v', ('Load',)), [('Pass', (1, 5))], [])], None), -('Module', [('With', (1, 0), [('withitem', ('Name', (1, 5), 'x', ('Load',)), ('Name', (1, 10), 'y', ('Store',)))], [('Pass', (1, 13))])], None), -('Module', [('With', (1, 0), [('withitem', ('Name', (1, 5), 'x', ('Load',)), ('Name', (1, 10), 'y', ('Store',))), ('withitem', ('Name', (1, 13), 'z', ('Load',)), ('Name', (1, 18), 'q', ('Store',)))], [('Pass', (1, 21))])], None), -('Module', [('Raise', (1, 0), ('Call', (1, 6), ('Name', (1, 6), 'Exception', ('Load',)), [('Str', (1, 16), 'string')], []), None)], None), -('Module', [('Try', (1, 0), [('Pass', (2, 2))], [('ExceptHandler', (3, 0), ('Name', (3, 7), 'Exception', ('Load',)), None, [('Pass', (4, 2))])], [], [])], None), -('Module', [('Try', (1, 0), [('Pass', (2, 2))], [], [], [('Pass', (4, 2))])], None), -('Module', [('Assert', (1, 0), ('Name', (1, 7), 'v', ('Load',)), None)], None), -('Module', [('Import', (1, 0), [('alias', 'sys', None)])], None), -('Module', [('ImportFrom', (1, 0), 'sys', [('alias', 'v', None)], 0)], None), -('Module', [('Global', (1, 0), ['v'])], None), -('Module', [('Expr', (1, 0), ('Num', (1, 0), 1))], None), -('Module', [('Pass', (1, 0))], None), -('Module', [('For', (1, 0), ('Name', (1, 4), 'v', ('Store',)), ('Name', (1, 9), 'v', ('Load',)), [('Break', (1, 11))], [])], None), -('Module', [('For', (1, 0), ('Name', (1, 4), 'v', ('Store',)), ('Name', (1, 9), 'v', ('Load',)), [('Continue', (1, 11))], [])], None), -('Module', [('For', (1, 0), ('Tuple', (1, 4), [('Name', (1, 4), 'a', ('Store',)), ('Name', (1, 6), 'b', ('Store',))], ('Store',)), ('Name', (1, 11), 'c', ('Load',)), [('Pass', (1, 14))], [])], None), -('Module', [('Expr', (1, 0), ('ListComp', (1, 1), ('Tuple', (1, 2), [('Name', (1, 2), 'a', ('Load',)), ('Name', (1, 4), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 11), [('Name', (1, 11), 'a', ('Store',)), ('Name', (1, 13), 'b', ('Store',))], ('Store',)), ('Name', (1, 18), 'c', ('Load',)), [], 0)]))], None), -('Module', [('Expr', (1, 0), ('GeneratorExp', (1, 1), ('Tuple', (1, 2), [('Name', (1, 2), 'a', ('Load',)), ('Name', (1, 4), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 11), [('Name', (1, 11), 'a', ('Store',)), ('Name', (1, 13), 'b', ('Store',))], ('Store',)), ('Name', (1, 18), 'c', ('Load',)), [], 0)]))], None), -('Module', [('Expr', (1, 0), ('GeneratorExp', (1, 1), ('Tuple', (1, 2), [('Name', (1, 2), 'a', ('Load',)), ('Name', (1, 4), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 12), [('Name', (1, 12), 'a', ('Store',)), ('Name', (1, 14), 'b', ('Store',))], ('Store',)), ('Name', (1, 20), 'c', ('Load',)), [], 0)]))], None), -('Module', [('Expr', (1, 0), ('GeneratorExp', (2, 4), ('Tuple', (3, 4), [('Name', (3, 4), 'Aa', ('Load',)), ('Name', (5, 7), 'Bb', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (8, 4), [('Name', (8, 4), 'Aa', ('Store',)), ('Name', (10, 4), 'Bb', ('Store',))], ('Store',)), ('Name', (10, 10), 'Cc', ('Load',)), [], 0)]))], None), -('Module', [('Expr', (1, 0), ('DictComp', (1, 0), ('Name', (1, 1), 'a', ('Load',)), ('Name', (1, 5), 'b', ('Load',)), [('comprehension', ('Name', (1, 11), 'w', ('Store',)), ('Name', (1, 16), 'x', ('Load',)), [], 0), ('comprehension', ('Name', (1, 22), 'm', ('Store',)), ('Name', (1, 27), 'p', ('Load',)), [('Name', (1, 32), 'g', ('Load',))], 0)]))], None), -('Module', [('Expr', (1, 0), ('DictComp', (1, 0), ('Name', (1, 1), 'a', ('Load',)), ('Name', (1, 5), 'b', ('Load',)), [('comprehension', ('Tuple', (1, 11), [('Name', (1, 11), 'v', ('Store',)), ('Name', (1, 13), 'w', ('Store',))], ('Store',)), ('Name', (1, 18), 'x', ('Load',)), [], 0)]))], None), -('Module', [('Expr', (1, 0), ('SetComp', (1, 0), ('Name', (1, 1), 'r', ('Load',)), [('comprehension', ('Name', (1, 7), 'l', ('Store',)), ('Name', (1, 12), 'x', ('Load',)), [('Name', (1, 17), 'g', ('Load',))], 0)]))], None), -('Module', [('Expr', (1, 0), ('SetComp', (1, 0), ('Name', (1, 1), 'r', ('Load',)), [('comprehension', ('Tuple', (1, 7), [('Name', (1, 7), 'l', ('Store',)), ('Name', (1, 9), 'm', ('Store',))], ('Store',)), ('Name', (1, 14), 'x', ('Load',)), [], 0)]))], None), -('Module', [('AsyncFunctionDef', (1, 6), 'f', ('arguments', [], None, [], [], None, []), [('Expr', (3, 1), ('Await', (3, 1), ('Call', (3, 7), ('Name', (3, 7), 'something', ('Load',)), [], [])))], [], None, 'async function')], None), -('Module', [('AsyncFunctionDef', (1, 6), 'f', ('arguments', [], None, [], [], None, []), [('AsyncFor', (2, 7), ('Name', (2, 11), 'e', ('Store',)), ('Name', (2, 16), 'i', ('Load',)), [('Expr', (2, 19), ('Num', (2, 19), 1))], [('Expr', (3, 7), ('Num', (3, 7), 2))])], [], None, None)], None), -('Module', [('AsyncFunctionDef', (1, 6), 'f', ('arguments', [], None, [], [], None, []), [('AsyncWith', (2, 7), [('withitem', ('Name', (2, 12), 'a', ('Load',)), ('Name', (2, 17), 'b', ('Store',)))], [('Expr', (2, 20), ('Num', (2, 20), 1))])], [], None, None)], None), -('Module', [('Expr', (1, 0), ('Dict', (1, 0), [None, ('Num', (1, 10), 2)], [('Dict', (1, 3), [('Num', (1, 4), 1)], [('Num', (1, 6), 2)]), ('Num', (1, 12), 3)]))], None), -('Module', [('Expr', (1, 0), ('Set', (1, 0), [('Starred', (1, 1), ('Set', (1, 2), [('Num', (1, 3), 1), ('Num', (1, 6), 2)]), ('Load',)), ('Num', (1, 10), 3)]))], None), -('Module', [('AsyncFunctionDef', (1, 6), 'f', ('arguments', [], None, [], [], None, []), [('Expr', (2, 1), ('ListComp', (2, 2), ('Name', (2, 2), 'i', ('Load',)), [('comprehension', ('Name', (2, 14), 'b', ('Store',)), ('Name', (2, 19), 'c', ('Load',)), [], 1)]))], [], None, None)], None), +('Module', [('Expr', (1, 0), ('NameConstant', (1, 0), None))]), +('Module', [('Expr', (1, 0), ('Str', (1, 0), 'module docstring'))]), +('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('Pass', (1, 9))], [], None)]), +('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('Expr', (1, 9), ('Str', (1, 9), 'function docstring'))], [], None)]), +('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None)], None, [], [], None, []), [('Pass', (1, 10))], [], None)]), +('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None)], None, [], [], None, [('Num', (1, 8), 0)]), [('Pass', (1, 12))], [], None)]), +('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], ('arg', (1, 7), 'args', None), [], [], None, []), [('Pass', (1, 14))], [], None)]), +('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], ('arg', (1, 8), 'kwargs', None), []), [('Pass', (1, 17))], [], None)]), +('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [('arg', (1, 6), 'a', None), ('arg', (1, 9), 'b', None), ('arg', (1, 14), 'c', None), ('arg', (1, 22), 'd', None), ('arg', (1, 28), 'e', None)], ('arg', (1, 35), 'args', None), [('arg', (1, 41), 'f', None)], [('Num', (1, 43), 42)], ('arg', (1, 49), 'kwargs', None), [('Num', (1, 11), 1), ('NameConstant', (1, 16), None), ('List', (1, 24), [], ('Load',)), ('Dict', (1, 30), [], [])]), [('Expr', (1, 58), ('Str', (1, 58), 'doc for f()'))], [], None)]), +('Module', [('ClassDef', (1, 0), 'C', [], [], [('Pass', (1, 8))], [])]), +('Module', [('ClassDef', (1, 0), 'C', [], [], [('Expr', (1, 9), ('Str', (1, 9), 'docstring for class C'))], [])]), +('Module', [('ClassDef', (1, 0), 'C', [('Name', (1, 8), 'object', ('Load',))], [], [('Pass', (1, 17))], [])]), +('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], [], None, []), [('Return', (1, 8), ('Num', (1, 15), 1))], [], None)]), +('Module', [('Delete', (1, 0), [('Name', (1, 4), 'v', ('Del',))])]), +('Module', [('Assign', (1, 0), [('Name', (1, 0), 'v', ('Store',))], ('Num', (1, 4), 1))]), +('Module', [('AugAssign', (1, 0), ('Name', (1, 0), 'v', ('Store',)), ('Add',), ('Num', (1, 5), 1))]), +('Module', [('For', (1, 0), ('Name', (1, 4), 'v', ('Store',)), ('Name', (1, 9), 'v', ('Load',)), [('Pass', (1, 11))], [])]), +('Module', [('While', (1, 0), ('Name', (1, 6), 'v', ('Load',)), [('Pass', (1, 8))], [])]), +('Module', [('If', (1, 0), ('Name', (1, 3), 'v', ('Load',)), [('Pass', (1, 5))], [])]), +('Module', [('With', (1, 0), [('withitem', ('Name', (1, 5), 'x', ('Load',)), ('Name', (1, 10), 'y', ('Store',)))], [('Pass', (1, 13))])]), +('Module', [('With', (1, 0), [('withitem', ('Name', (1, 5), 'x', ('Load',)), ('Name', (1, 10), 'y', ('Store',))), ('withitem', ('Name', (1, 13), 'z', ('Load',)), ('Name', (1, 18), 'q', ('Store',)))], [('Pass', (1, 21))])]), +('Module', [('Raise', (1, 0), ('Call', (1, 6), ('Name', (1, 6), 'Exception', ('Load',)), [('Str', (1, 16), 'string')], []), None)]), +('Module', [('Try', (1, 0), [('Pass', (2, 2))], [('ExceptHandler', (3, 0), ('Name', (3, 7), 'Exception', ('Load',)), None, [('Pass', (4, 2))])], [], [])]), +('Module', [('Try', (1, 0), [('Pass', (2, 2))], [], [], [('Pass', (4, 2))])]), +('Module', [('Assert', (1, 0), ('Name', (1, 7), 'v', ('Load',)), None)]), +('Module', [('Import', (1, 0), [('alias', 'sys', None)])]), +('Module', [('ImportFrom', (1, 0), 'sys', [('alias', 'v', None)], 0)]), +('Module', [('Global', (1, 0), ['v'])]), +('Module', [('Expr', (1, 0), ('Num', (1, 0), 1))]), +('Module', [('Pass', (1, 0))]), +('Module', [('For', (1, 0), ('Name', (1, 4), 'v', ('Store',)), ('Name', (1, 9), 'v', ('Load',)), [('Break', (1, 11))], [])]), +('Module', [('For', (1, 0), ('Name', (1, 4), 'v', ('Store',)), ('Name', (1, 9), 'v', ('Load',)), [('Continue', (1, 11))], [])]), +('Module', [('For', (1, 0), ('Tuple', (1, 4), [('Name', (1, 4), 'a', ('Store',)), ('Name', (1, 6), 'b', ('Store',))], ('Store',)), ('Name', (1, 11), 'c', ('Load',)), [('Pass', (1, 14))], [])]), +('Module', [('Expr', (1, 0), ('ListComp', (1, 1), ('Tuple', (1, 2), [('Name', (1, 2), 'a', ('Load',)), ('Name', (1, 4), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 11), [('Name', (1, 11), 'a', ('Store',)), ('Name', (1, 13), 'b', ('Store',))], ('Store',)), ('Name', (1, 18), 'c', ('Load',)), [], 0)]))]), +('Module', [('Expr', (1, 0), ('GeneratorExp', (1, 1), ('Tuple', (1, 2), [('Name', (1, 2), 'a', ('Load',)), ('Name', (1, 4), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 11), [('Name', (1, 11), 'a', ('Store',)), ('Name', (1, 13), 'b', ('Store',))], ('Store',)), ('Name', (1, 18), 'c', ('Load',)), [], 0)]))]), +('Module', [('Expr', (1, 0), ('GeneratorExp', (1, 1), ('Tuple', (1, 2), [('Name', (1, 2), 'a', ('Load',)), ('Name', (1, 4), 'b', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (1, 12), [('Name', (1, 12), 'a', ('Store',)), ('Name', (1, 14), 'b', ('Store',))], ('Store',)), ('Name', (1, 20), 'c', ('Load',)), [], 0)]))]), +('Module', [('Expr', (1, 0), ('GeneratorExp', (2, 4), ('Tuple', (3, 4), [('Name', (3, 4), 'Aa', ('Load',)), ('Name', (5, 7), 'Bb', ('Load',))], ('Load',)), [('comprehension', ('Tuple', (8, 4), [('Name', (8, 4), 'Aa', ('Store',)), ('Name', (10, 4), 'Bb', ('Store',))], ('Store',)), ('Name', (10, 10), 'Cc', ('Load',)), [], 0)]))]), +('Module', [('Expr', (1, 0), ('DictComp', (1, 0), ('Name', (1, 1), 'a', ('Load',)), ('Name', (1, 5), 'b', ('Load',)), [('comprehension', ('Name', (1, 11), 'w', ('Store',)), ('Name', (1, 16), 'x', ('Load',)), [], 0), ('comprehension', ('Name', (1, 22), 'm', ('Store',)), ('Name', (1, 27), 'p', ('Load',)), [('Name', (1, 32), 'g', ('Load',))], 0)]))]), +('Module', [('Expr', (1, 0), ('DictComp', (1, 0), ('Name', (1, 1), 'a', ('Load',)), ('Name', (1, 5), 'b', ('Load',)), [('comprehension', ('Tuple', (1, 11), [('Name', (1, 11), 'v', ('Store',)), ('Name', (1, 13), 'w', ('Store',))], ('Store',)), ('Name', (1, 18), 'x', ('Load',)), [], 0)]))]), +('Module', [('Expr', (1, 0), ('SetComp', (1, 0), ('Name', (1, 1), 'r', ('Load',)), [('comprehension', ('Name', (1, 7), 'l', ('Store',)), ('Name', (1, 12), 'x', ('Load',)), [('Name', (1, 17), 'g', ('Load',))], 0)]))]), +('Module', [('Expr', (1, 0), ('SetComp', (1, 0), ('Name', (1, 1), 'r', ('Load',)), [('comprehension', ('Tuple', (1, 7), [('Name', (1, 7), 'l', ('Store',)), ('Name', (1, 9), 'm', ('Store',))], ('Store',)), ('Name', (1, 14), 'x', ('Load',)), [], 0)]))]), +('Module', [('AsyncFunctionDef', (1, 6), 'f', ('arguments', [], None, [], [], None, []), [('Expr', (2, 1), ('Str', (2, 1), 'async function')), ('Expr', (3, 1), ('Await', (3, 1), ('Call', (3, 7), ('Name', (3, 7), 'something', ('Load',)), [], [])))], [], None)]), +('Module', [('AsyncFunctionDef', (1, 6), 'f', ('arguments', [], None, [], [], None, []), [('AsyncFor', (2, 7), ('Name', (2, 11), 'e', ('Store',)), ('Name', (2, 16), 'i', ('Load',)), [('Expr', (2, 19), ('Num', (2, 19), 1))], [('Expr', (3, 7), ('Num', (3, 7), 2))])], [], None)]), +('Module', [('AsyncFunctionDef', (1, 6), 'f', ('arguments', [], None, [], [], None, []), [('AsyncWith', (2, 7), [('withitem', ('Name', (2, 12), 'a', ('Load',)), ('Name', (2, 17), 'b', ('Store',)))], [('Expr', (2, 20), ('Num', (2, 20), 1))])], [], None)]), +('Module', [('Expr', (1, 0), ('Dict', (1, 0), [None, ('Num', (1, 10), 2)], [('Dict', (1, 3), [('Num', (1, 4), 1)], [('Num', (1, 6), 2)]), ('Num', (1, 12), 3)]))]), +('Module', [('Expr', (1, 0), ('Set', (1, 0), [('Starred', (1, 1), ('Set', (1, 2), [('Num', (1, 3), 1), ('Num', (1, 6), 2)]), ('Load',)), ('Num', (1, 10), 3)]))]), +('Module', [('AsyncFunctionDef', (1, 6), 'f', ('arguments', [], None, [], [], None, []), [('Expr', (2, 1), ('ListComp', (2, 2), ('Name', (2, 2), 'i', ('Load',)), [('comprehension', ('Name', (2, 14), 'b', ('Store',)), ('Name', (2, 19), 'c', ('Load',)), [], 1)]))], [], None)]), ] single_results = [ ('Interactive', [('Expr', (1, 0), ('BinOp', (1, 0), ('Num', (1, 0), 1), ('Add',), ('Num', (1, 2), 2)))]), diff --git a/Lib/test/test_opcodes.py b/Lib/test/test_opcodes.py index 8af098fb206b..6806c616cbef 100644 --- a/Lib/test/test_opcodes.py +++ b/Lib/test/test_opcodes.py @@ -27,7 +27,7 @@ def test_setup_annotations_line(self): with open(ann_module.__file__) as f: txt = f.read() co = compile(txt, ann_module.__file__, 'exec') - self.assertEqual(co.co_firstlineno, 8) + self.assertEqual(co.co_firstlineno, 6) except OSError: pass diff --git a/Misc/NEWS.d/3.7.0a1.rst b/Misc/NEWS.d/3.7.0a1.rst index 3962923a2d24..acecfcf55720 100644 --- a/Misc/NEWS.d/3.7.0a1.rst +++ b/Misc/NEWS.d/3.7.0a1.rst @@ -788,7 +788,7 @@ objects. Add ``docstring`` field to Module, ClassDef, FunctionDef, and AsyncFunctionDef ast nodes. docstring is not first stmt in their body anymore. It affects ``co_firstlineno`` and ``co_lnotab`` of code object for -module and class. +module and class. (Reverted in :issue:`32911`.) .. diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-02-27-20-57-00.bpo-32911.cmKfco.rst b/Misc/NEWS.d/next/Core and Builtins/2018-02-27-20-57-00.bpo-32911.cmKfco.rst new file mode 100644 index 000000000000..0c2ae756b65c --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-02-27-20-57-00.bpo-32911.cmKfco.rst @@ -0,0 +1,5 @@ +Due to unexpected compatibility issues discovered during downstream beta +testing, reverted :issue:`29463`. ``docstring`` field is removed from Module, +ClassDef, FunctionDef, and AsyncFunctionDef ast nodes which was added in +3.7a1. Docstring expression is restored as a first statement in their body. +Based on patch by Inada Naoki. diff --git a/Parser/Python.asdl b/Parser/Python.asdl index 526cffbce028..f470ad13b655 100644 --- a/Parser/Python.asdl +++ b/Parser/Python.asdl @@ -6,7 +6,7 @@ module Python { - mod = Module(stmt* body, string? docstring) + mod = Module(stmt* body) | Interactive(stmt* body) | Expression(expr body) @@ -14,18 +14,15 @@ module Python | Suite(stmt* body) stmt = FunctionDef(identifier name, arguments args, - stmt* body, expr* decorator_list, expr? returns, - string? docstring) + stmt* body, expr* decorator_list, expr? returns) | AsyncFunctionDef(identifier name, arguments args, - stmt* body, expr* decorator_list, expr? returns, - string? docstring) + stmt* body, expr* decorator_list, expr? returns) | ClassDef(identifier name, expr* bases, keyword* keywords, stmt* body, - expr* decorator_list, - string? docstring) + expr* decorator_list) | Return(expr? value) | Delete(expr* targets) diff --git a/Python/Python-ast.c b/Python/Python-ast.c index f7a056845e95..38b9292577f2 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -10,10 +10,8 @@ static PyTypeObject *mod_type; static PyObject* ast2obj_mod(void*); static PyTypeObject *Module_type; _Py_IDENTIFIER(body); -_Py_IDENTIFIER(docstring); static char *Module_fields[]={ "body", - "docstring", }; static PyTypeObject *Interactive_type; static char *Interactive_fields[]={ @@ -46,7 +44,6 @@ static char *FunctionDef_fields[]={ "body", "decorator_list", "returns", - "docstring", }; static PyTypeObject *AsyncFunctionDef_type; static char *AsyncFunctionDef_fields[]={ @@ -55,7 +52,6 @@ static char *AsyncFunctionDef_fields[]={ "body", "decorator_list", "returns", - "docstring", }; static PyTypeObject *ClassDef_type; _Py_IDENTIFIER(bases); @@ -66,7 +62,6 @@ static char *ClassDef_fields[]={ "keywords", "body", "decorator_list", - "docstring", }; static PyTypeObject *Return_type; _Py_IDENTIFIER(value); @@ -847,7 +842,7 @@ static int init_types(void) mod_type = make_type("mod", &AST_type, NULL, 0); if (!mod_type) return 0; if (!add_attributes(mod_type, NULL, 0)) return 0; - Module_type = make_type("Module", mod_type, Module_fields, 2); + Module_type = make_type("Module", mod_type, Module_fields, 1); if (!Module_type) return 0; Interactive_type = make_type("Interactive", mod_type, Interactive_fields, 1); @@ -860,12 +855,12 @@ static int init_types(void) if (!stmt_type) return 0; if (!add_attributes(stmt_type, stmt_attributes, 2)) return 0; FunctionDef_type = make_type("FunctionDef", stmt_type, FunctionDef_fields, - 6); + 5); if (!FunctionDef_type) return 0; AsyncFunctionDef_type = make_type("AsyncFunctionDef", stmt_type, - AsyncFunctionDef_fields, 6); + AsyncFunctionDef_fields, 5); if (!AsyncFunctionDef_type) return 0; - ClassDef_type = make_type("ClassDef", stmt_type, ClassDef_fields, 6); + ClassDef_type = make_type("ClassDef", stmt_type, ClassDef_fields, 5); if (!ClassDef_type) return 0; Return_type = make_type("Return", stmt_type, Return_fields, 1); if (!Return_type) return 0; @@ -1192,7 +1187,7 @@ static int obj2ast_alias(PyObject* obj, alias_ty* out, PyArena* arena); static int obj2ast_withitem(PyObject* obj, withitem_ty* out, PyArena* arena); mod_ty -Module(asdl_seq * body, string docstring, PyArena *arena) +Module(asdl_seq * body, PyArena *arena) { mod_ty p; p = (mod_ty)PyArena_Malloc(arena, sizeof(*p)); @@ -1200,7 +1195,6 @@ Module(asdl_seq * body, string docstring, PyArena *arena) return NULL; p->kind = Module_kind; p->v.Module.body = body; - p->v.Module.docstring = docstring; return p; } @@ -1247,8 +1241,8 @@ Suite(asdl_seq * body, PyArena *arena) stmt_ty FunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq * - decorator_list, expr_ty returns, string docstring, int lineno, int - col_offset, PyArena *arena) + decorator_list, expr_ty returns, int lineno, int col_offset, + PyArena *arena) { stmt_ty p; if (!name) { @@ -1270,7 +1264,6 @@ FunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq * p->v.FunctionDef.body = body; p->v.FunctionDef.decorator_list = decorator_list; p->v.FunctionDef.returns = returns; - p->v.FunctionDef.docstring = docstring; p->lineno = lineno; p->col_offset = col_offset; return p; @@ -1278,8 +1271,8 @@ FunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq * stmt_ty AsyncFunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq - * decorator_list, expr_ty returns, string docstring, int - lineno, int col_offset, PyArena *arena) + * decorator_list, expr_ty returns, int lineno, int col_offset, + PyArena *arena) { stmt_ty p; if (!name) { @@ -1301,7 +1294,6 @@ AsyncFunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq p->v.AsyncFunctionDef.body = body; p->v.AsyncFunctionDef.decorator_list = decorator_list; p->v.AsyncFunctionDef.returns = returns; - p->v.AsyncFunctionDef.docstring = docstring; p->lineno = lineno; p->col_offset = col_offset; return p; @@ -1309,8 +1301,8 @@ AsyncFunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq stmt_ty ClassDef(identifier name, asdl_seq * bases, asdl_seq * keywords, asdl_seq * - body, asdl_seq * decorator_list, string docstring, int lineno, int - col_offset, PyArena *arena) + body, asdl_seq * decorator_list, int lineno, int col_offset, PyArena + *arena) { stmt_ty p; if (!name) { @@ -1327,7 +1319,6 @@ ClassDef(identifier name, asdl_seq * bases, asdl_seq * keywords, asdl_seq * p->v.ClassDef.keywords = keywords; p->v.ClassDef.body = body; p->v.ClassDef.decorator_list = decorator_list; - p->v.ClassDef.docstring = docstring; p->lineno = lineno; p->col_offset = col_offset; return p; @@ -2591,11 +2582,6 @@ ast2obj_mod(void* _o) if (_PyObject_SetAttrId(result, &PyId_body, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_string(o->v.Module.docstring); - if (!value) goto failed; - if (_PyObject_SetAttrId(result, &PyId_docstring, value) == -1) - goto failed; - Py_DECREF(value); break; case Interactive_kind: result = PyType_GenericNew(Interactive_type, NULL, NULL); @@ -2670,11 +2656,6 @@ ast2obj_stmt(void* _o) if (_PyObject_SetAttrId(result, &PyId_returns, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_string(o->v.FunctionDef.docstring); - if (!value) goto failed; - if (_PyObject_SetAttrId(result, &PyId_docstring, value) == -1) - goto failed; - Py_DECREF(value); break; case AsyncFunctionDef_kind: result = PyType_GenericNew(AsyncFunctionDef_type, NULL, NULL); @@ -2705,11 +2686,6 @@ ast2obj_stmt(void* _o) if (_PyObject_SetAttrId(result, &PyId_returns, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_string(o->v.AsyncFunctionDef.docstring); - if (!value) goto failed; - if (_PyObject_SetAttrId(result, &PyId_docstring, value) == -1) - goto failed; - Py_DECREF(value); break; case ClassDef_kind: result = PyType_GenericNew(ClassDef_type, NULL, NULL); @@ -2739,11 +2715,6 @@ ast2obj_stmt(void* _o) if (_PyObject_SetAttrId(result, &PyId_decorator_list, value) == -1) goto failed; Py_DECREF(value); - value = ast2obj_string(o->v.ClassDef.docstring); - if (!value) goto failed; - if (_PyObject_SetAttrId(result, &PyId_docstring, value) == -1) - goto failed; - Py_DECREF(value); break; case Return_kind: result = PyType_GenericNew(Return_type, NULL, NULL); @@ -3984,7 +3955,6 @@ obj2ast_mod(PyObject* obj, mod_ty* out, PyArena* arena) } if (isinstance) { asdl_seq* body; - string docstring; if (_PyObject_LookupAttrId(obj, &PyId_body, &tmp) < 0) { return 1; @@ -4016,20 +3986,7 @@ obj2ast_mod(PyObject* obj, mod_ty* out, PyArena* arena) } Py_CLEAR(tmp); } - if (_PyObject_LookupAttrId(obj, &PyId_docstring, &tmp) < 0) { - return 1; - } - if (tmp == NULL || tmp == Py_None) { - Py_CLEAR(tmp); - docstring = NULL; - } - else { - int res; - res = obj2ast_string(tmp, &docstring, arena); - if (res != 0) goto failed; - Py_CLEAR(tmp); - } - *out = Module(body, docstring, arena); + *out = Module(body, arena); if (*out == NULL) goto failed; return 0; } @@ -4195,7 +4152,6 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) asdl_seq* body; asdl_seq* decorator_list; expr_ty returns; - string docstring; if (_PyObject_LookupAttrId(obj, &PyId_name, &tmp) < 0) { return 1; @@ -4296,21 +4252,8 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) if (res != 0) goto failed; Py_CLEAR(tmp); } - if (_PyObject_LookupAttrId(obj, &PyId_docstring, &tmp) < 0) { - return 1; - } - if (tmp == NULL || tmp == Py_None) { - Py_CLEAR(tmp); - docstring = NULL; - } - else { - int res; - res = obj2ast_string(tmp, &docstring, arena); - if (res != 0) goto failed; - Py_CLEAR(tmp); - } - *out = FunctionDef(name, args, body, decorator_list, returns, - docstring, lineno, col_offset, arena); + *out = FunctionDef(name, args, body, decorator_list, returns, lineno, + col_offset, arena); if (*out == NULL) goto failed; return 0; } @@ -4324,7 +4267,6 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) asdl_seq* body; asdl_seq* decorator_list; expr_ty returns; - string docstring; if (_PyObject_LookupAttrId(obj, &PyId_name, &tmp) < 0) { return 1; @@ -4425,21 +4367,8 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) if (res != 0) goto failed; Py_CLEAR(tmp); } - if (_PyObject_LookupAttrId(obj, &PyId_docstring, &tmp) < 0) { - return 1; - } - if (tmp == NULL || tmp == Py_None) { - Py_CLEAR(tmp); - docstring = NULL; - } - else { - int res; - res = obj2ast_string(tmp, &docstring, arena); - if (res != 0) goto failed; - Py_CLEAR(tmp); - } *out = AsyncFunctionDef(name, args, body, decorator_list, returns, - docstring, lineno, col_offset, arena); + lineno, col_offset, arena); if (*out == NULL) goto failed; return 0; } @@ -4453,7 +4382,6 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) asdl_seq* keywords; asdl_seq* body; asdl_seq* decorator_list; - string docstring; if (_PyObject_LookupAttrId(obj, &PyId_name, &tmp) < 0) { return 1; @@ -4588,21 +4516,8 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena) } Py_CLEAR(tmp); } - if (_PyObject_LookupAttrId(obj, &PyId_docstring, &tmp) < 0) { - return 1; - } - if (tmp == NULL || tmp == Py_None) { - Py_CLEAR(tmp); - docstring = NULL; - } - else { - int res; - res = obj2ast_string(tmp, &docstring, arena); - if (res != 0) goto failed; - Py_CLEAR(tmp); - } - *out = ClassDef(name, bases, keywords, body, decorator_list, docstring, - lineno, col_offset, arena); + *out = ClassDef(name, bases, keywords, body, decorator_list, lineno, + col_offset, arena); if (*out == NULL) goto failed; return 0; } diff --git a/Python/ast.c b/Python/ast.c index 03a489a74ef0..43bd786015a7 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -367,12 +367,9 @@ validate_assignlist(asdl_seq *targets, expr_context_ty ctx) } static int -validate_body(asdl_seq *body, const char *owner, int allowempty) +validate_body(asdl_seq *body, const char *owner) { - if (!allowempty && !validate_nonempty_seq(body, "body", owner)) { - return 0; - } - return validate_stmts(body); + return validate_nonempty_seq(body, "body", owner) && validate_stmts(body); } static int @@ -381,15 +378,13 @@ validate_stmt(stmt_ty stmt) int i; switch (stmt->kind) { case FunctionDef_kind: - return validate_body(stmt->v.FunctionDef.body, "FunctionDef", - stmt->v.FunctionDef.docstring != NULL) && + return validate_body(stmt->v.FunctionDef.body, "FunctionDef") && validate_arguments(stmt->v.FunctionDef.args) && validate_exprs(stmt->v.FunctionDef.decorator_list, Load, 0) && (!stmt->v.FunctionDef.returns || validate_expr(stmt->v.FunctionDef.returns, Load)); case ClassDef_kind: - return validate_body(stmt->v.ClassDef.body, "ClassDef", - stmt->v.ClassDef.docstring != NULL) && + return validate_body(stmt->v.ClassDef.body, "ClassDef") && validate_exprs(stmt->v.ClassDef.bases, Load, 0) && validate_keywords(stmt->v.ClassDef.keywords) && validate_exprs(stmt->v.ClassDef.decorator_list, Load, 0); @@ -417,20 +412,20 @@ validate_stmt(stmt_ty stmt) case For_kind: return validate_expr(stmt->v.For.target, Store) && validate_expr(stmt->v.For.iter, Load) && - validate_body(stmt->v.For.body, "For", 0) && + validate_body(stmt->v.For.body, "For") && validate_stmts(stmt->v.For.orelse); case AsyncFor_kind: return validate_expr(stmt->v.AsyncFor.target, Store) && validate_expr(stmt->v.AsyncFor.iter, Load) && - validate_body(stmt->v.AsyncFor.body, "AsyncFor", 0) && + validate_body(stmt->v.AsyncFor.body, "AsyncFor") && validate_stmts(stmt->v.AsyncFor.orelse); case While_kind: return validate_expr(stmt->v.While.test, Load) && - validate_body(stmt->v.While.body, "While", 0) && + validate_body(stmt->v.While.body, "While") && validate_stmts(stmt->v.While.orelse); case If_kind: return validate_expr(stmt->v.If.test, Load) && - validate_body(stmt->v.If.body, "If", 0) && + validate_body(stmt->v.If.body, "If") && validate_stmts(stmt->v.If.orelse); case With_kind: if (!validate_nonempty_seq(stmt->v.With.items, "items", "With")) @@ -441,7 +436,7 @@ validate_stmt(stmt_ty stmt) (item->optional_vars && !validate_expr(item->optional_vars, Store))) return 0; } - return validate_body(stmt->v.With.body, "With", 0); + return validate_body(stmt->v.With.body, "With"); case AsyncWith_kind: if (!validate_nonempty_seq(stmt->v.AsyncWith.items, "items", "AsyncWith")) return 0; @@ -451,7 +446,7 @@ validate_stmt(stmt_ty stmt) (item->optional_vars && !validate_expr(item->optional_vars, Store))) return 0; } - return validate_body(stmt->v.AsyncWith.body, "AsyncWith", 0); + return validate_body(stmt->v.AsyncWith.body, "AsyncWith"); case Raise_kind: if (stmt->v.Raise.exc) { return validate_expr(stmt->v.Raise.exc, Load) && @@ -463,7 +458,7 @@ validate_stmt(stmt_ty stmt) } return 1; case Try_kind: - if (!validate_body(stmt->v.Try.body, "Try", 0)) + if (!validate_body(stmt->v.Try.body, "Try")) return 0; if (!asdl_seq_LEN(stmt->v.Try.handlers) && !asdl_seq_LEN(stmt->v.Try.finalbody)) { @@ -479,7 +474,7 @@ validate_stmt(stmt_ty stmt) excepthandler_ty handler = asdl_seq_GET(stmt->v.Try.handlers, i); if ((handler->v.ExceptHandler.type && !validate_expr(handler->v.ExceptHandler.type, Load)) || - !validate_body(handler->v.ExceptHandler.body, "ExceptHandler", 0)) + !validate_body(handler->v.ExceptHandler.body, "ExceptHandler")) return 0; } return (!asdl_seq_LEN(stmt->v.Try.finalbody) || @@ -504,8 +499,7 @@ validate_stmt(stmt_ty stmt) case Expr_kind: return validate_expr(stmt->v.Expr.value, Load); case AsyncFunctionDef_kind: - return validate_body(stmt->v.AsyncFunctionDef.body, "AsyncFunctionDef", - stmt->v.AsyncFunctionDef.docstring != NULL) && + return validate_body(stmt->v.AsyncFunctionDef.body, "AsyncFunctionDef") && validate_arguments(stmt->v.AsyncFunctionDef.args) && validate_exprs(stmt->v.AsyncFunctionDef.decorator_list, Load, 0) && (!stmt->v.AsyncFunctionDef.returns || @@ -600,9 +594,7 @@ struct compiling { static asdl_seq *seq_for_testlist(struct compiling *, const node *); static expr_ty ast_for_expr(struct compiling *, const node *); static stmt_ty ast_for_stmt(struct compiling *, const node *); -static asdl_seq *ast_for_body(struct compiling *c, const node *n, - string *docstring); -static string docstring_from_stmts(asdl_seq *stmts); +static asdl_seq *ast_for_suite(struct compiling *c, const node *n); static asdl_seq *ast_for_exprlist(struct compiling *, const node *, expr_context_ty); static expr_ty ast_for_testlist(struct compiling *, const node *); @@ -820,7 +812,7 @@ PyAST_FromNodeObject(const node *n, PyCompilerFlags *flags, } } } - res = Module(stmts, docstring_from_stmts(stmts), arena); + res = Module(stmts, arena); break; case eval_input: { expr_ty testlist_ast; @@ -1585,7 +1577,6 @@ ast_for_funcdef_impl(struct compiling *c, const node *n, arguments_ty args; asdl_seq *body; expr_ty returns = NULL; - string docstring; int name_i = 1; REQ(n, funcdef); @@ -1604,18 +1595,16 @@ ast_for_funcdef_impl(struct compiling *c, const node *n, return NULL; name_i += 2; } - body = ast_for_body(c, CHILD(n, name_i + 3), &docstring); + body = ast_for_suite(c, CHILD(n, name_i + 3)); if (!body) return NULL; if (is_async) return AsyncFunctionDef(name, args, body, decorator_seq, returns, - docstring, LINENO(n), - n->n_col_offset, c->c_arena); + LINENO(n), n->n_col_offset, c->c_arena); else return FunctionDef(name, args, body, decorator_seq, returns, - docstring, LINENO(n), - n->n_col_offset, c->c_arena); + LINENO(n), n->n_col_offset, c->c_arena); } static stmt_ty @@ -3528,32 +3517,6 @@ ast_for_suite(struct compiling *c, const node *n) return seq; } -static string -docstring_from_stmts(asdl_seq *stmts) -{ - if (stmts && stmts->size) { - stmt_ty s = (stmt_ty)asdl_seq_GET(stmts, 0); - /* If first statement is a literal string, it's the doc string. */ - if (s->kind == Expr_kind && s->v.Expr.value->kind == Str_kind) { - string doc = s->v.Expr.value->v.Str.s; - /* not very efficient, but simple */ - memmove(&asdl_seq_GET(stmts, 0), &asdl_seq_GET(stmts, 1), - (stmts->size - 1) * sizeof(void*)); - stmts->size--; - return doc; - } - } - return NULL; -} - -static asdl_seq * -ast_for_body(struct compiling *c, const node *n, string *docstring) -{ - asdl_seq *stmts = ast_for_suite(c, n); - *docstring = docstring_from_stmts(stmts); - return stmts; -} - static stmt_ty ast_for_if_stmt(struct compiling *c, const node *n) { @@ -3938,13 +3901,12 @@ ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq) /* classdef: 'class' NAME ['(' arglist ')'] ':' suite */ PyObject *classname; asdl_seq *s; - string docstring; expr_ty call; REQ(n, classdef); if (NCH(n) == 4) { /* class NAME ':' suite */ - s = ast_for_body(c, CHILD(n, 3), &docstring); + s = ast_for_suite(c, CHILD(n, 3)); if (!s) return NULL; classname = NEW_IDENTIFIER(CHILD(n, 1)); @@ -3952,12 +3914,12 @@ ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq) return NULL; if (forbidden_name(c, classname, CHILD(n, 3), 0)) return NULL; - return ClassDef(classname, NULL, NULL, s, decorator_seq, docstring, + return ClassDef(classname, NULL, NULL, s, decorator_seq, LINENO(n), n->n_col_offset, c->c_arena); } if (TYPE(CHILD(n, 3)) == RPAR) { /* class NAME '(' ')' ':' suite */ - s = ast_for_body(c, CHILD(n, 5), &docstring); + s = ast_for_suite(c, CHILD(n, 5)); if (!s) return NULL; classname = NEW_IDENTIFIER(CHILD(n, 1)); @@ -3965,7 +3927,7 @@ ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq) return NULL; if (forbidden_name(c, classname, CHILD(n, 3), 0)) return NULL; - return ClassDef(classname, NULL, NULL, s, decorator_seq, docstring, + return ClassDef(classname, NULL, NULL, s, decorator_seq, LINENO(n), n->n_col_offset, c->c_arena); } @@ -3982,7 +3944,7 @@ ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq) if (!call) return NULL; } - s = ast_for_body(c, CHILD(n, 6), &docstring); + s = ast_for_suite(c, CHILD(n, 6)); if (!s) return NULL; classname = NEW_IDENTIFIER(CHILD(n, 1)); @@ -3992,8 +3954,7 @@ ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq) return NULL; return ClassDef(classname, call->v.Call.args, call->v.Call.keywords, s, - decorator_seq, docstring, LINENO(n), n->n_col_offset, - c->c_arena); + decorator_seq, LINENO(n), n->n_col_offset, c->c_arena); } static stmt_ty diff --git a/Python/ast_opt.c b/Python/ast_opt.c index a54f98c8c721..a998d1fb6014 100644 --- a/Python/ast_opt.c +++ b/Python/ast_opt.c @@ -467,12 +467,51 @@ static int astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, int opti } \ } +static int +isdocstring(stmt_ty s) +{ + if (s->kind != Expr_kind) + return 0; + if (s->v.Expr.value->kind == Str_kind) + return 1; + if (s->v.Expr.value->kind == Constant_kind) + return PyUnicode_CheckExact(s->v.Expr.value->v.Constant.value); + return 0; +} + +static int +astfold_body(asdl_seq *stmts, PyArena *ctx_, int optimize_) +{ + if (!asdl_seq_LEN(stmts)) { + return 1; + } + int docstring = isdocstring((stmt_ty)asdl_seq_GET(stmts, 0)); + CALL_SEQ(astfold_stmt, stmt_ty, stmts); + if (docstring) { + return 1; + } + stmt_ty st = (stmt_ty)asdl_seq_GET(stmts, 0); + if (isdocstring(st)) { + asdl_seq *values = _Py_asdl_seq_new(1, ctx_); + if (!values) { + return 0; + } + asdl_seq_SET(values, 0, st->v.Expr.value); + expr_ty expr = _Py_JoinedStr(values, st->lineno, st->col_offset, ctx_); + if (!expr) { + return 0; + } + st->v.Expr.value = expr; + } + return 1; +} + static int astfold_mod(mod_ty node_, PyArena *ctx_, int optimize_) { switch (node_->kind) { case Module_kind: - CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Module.body); + CALL(astfold_body, asdl_seq, node_->v.Module.body); break; case Interactive_kind: CALL_SEQ(astfold_stmt, stmt_ty, node_->v.Interactive.body); @@ -657,20 +696,20 @@ astfold_stmt(stmt_ty node_, PyArena *ctx_, int optimize_) switch (node_->kind) { case FunctionDef_kind: CALL(astfold_arguments, arguments_ty, node_->v.FunctionDef.args); - CALL_SEQ(astfold_stmt, stmt_ty, node_->v.FunctionDef.body); + CALL(astfold_body, asdl_seq, node_->v.FunctionDef.body); CALL_SEQ(astfold_expr, expr_ty, node_->v.FunctionDef.decorator_list); CALL_OPT(astfold_expr, expr_ty, node_->v.FunctionDef.returns); break; case AsyncFunctionDef_kind: CALL(astfold_arguments, arguments_ty, node_->v.AsyncFunctionDef.args); - CALL_SEQ(astfold_stmt, stmt_ty, node_->v.AsyncFunctionDef.body); + CALL(astfold_body, asdl_seq, node_->v.AsyncFunctionDef.body); CALL_SEQ(astfold_expr, expr_ty, node_->v.AsyncFunctionDef.decorator_list); CALL_OPT(astfold_expr, expr_ty, node_->v.AsyncFunctionDef.returns); break; case ClassDef_kind: CALL_SEQ(astfold_expr, expr_ty, node_->v.ClassDef.bases); CALL_SEQ(astfold_keyword, keyword_ty, node_->v.ClassDef.keywords); - CALL_SEQ(astfold_stmt, stmt_ty, node_->v.ClassDef.body); + CALL(astfold_body, asdl_seq, node_->v.ClassDef.body); CALL_SEQ(astfold_expr, expr_ty, node_->v.ClassDef.decorator_list); break; case Return_kind: diff --git a/Python/compile.c b/Python/compile.c index c3397f0c455d..42ae5082593c 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1392,6 +1392,18 @@ compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute) } \ } +static int +compiler_isdocstring(stmt_ty s) +{ + if (s->kind != Expr_kind) + return 0; + if (s->v.Expr.value->kind == Str_kind) + return 1; + if (s->v.Expr.value->kind == Constant_kind) + return PyUnicode_CheckExact(s->v.Expr.value->v.Constant.value); + return 0; +} + static int is_const(expr_ty e) { @@ -1587,27 +1599,37 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info, and for annotations. */ static int -compiler_body(struct compiler *c, asdl_seq *stmts, string docstring) +compiler_body(struct compiler *c, asdl_seq *stmts) { + int i = 0; + stmt_ty st; + /* Set current line number to the line number of first statement. This way line number for SETUP_ANNOTATIONS will always coincide with the line number of first "real" statement in module. If body is empy, then lineno will be set later in assemble. */ if (c->u->u_scope_type == COMPILER_SCOPE_MODULE && !c->u->u_lineno && asdl_seq_LEN(stmts)) { - stmt_ty st = (stmt_ty)asdl_seq_GET(stmts, 0); + st = (stmt_ty)asdl_seq_GET(stmts, 0); c->u->u_lineno = st->lineno; } /* Every annotated class and module should have __annotations__. */ if (find_ann(stmts)) { ADDOP(c, SETUP_ANNOTATIONS); } + if (!asdl_seq_LEN(stmts)) + return 1; + st = (stmt_ty)asdl_seq_GET(stmts, 0); /* if not -OO mode, set docstring */ - if (c->c_optimize < 2 && docstring) { - ADDOP_LOAD_CONST(c, docstring); - ADDOP_NAME(c, STORE_NAME, __doc__, names); + if (compiler_isdocstring(st) && c->c_optimize < 2) { + /* don't generate docstrings if -OO */ + i = 1; + VISIT(c, expr, st->v.Expr.value); + if (!compiler_nameop(c, __doc__, Store)) + return 0; } - VISIT_SEQ(c, stmt, stmts); + for (; i < asdl_seq_LEN(stmts); i++) + VISIT(c, stmt, (stmt_ty)asdl_seq_GET(stmts, i)); return 1; } @@ -1627,7 +1649,7 @@ compiler_mod(struct compiler *c, mod_ty mod) return NULL; switch (mod->kind) { case Module_kind: - if (!compiler_body(c, mod->v.Module.body, mod->v.Module.docstring)) { + if (!compiler_body(c, mod->v.Module.body)) { compiler_exit_scope(c); return 0; } @@ -1957,13 +1979,15 @@ static int compiler_function(struct compiler *c, stmt_ty s, int is_async) { PyCodeObject *co; - PyObject *qualname, *docstring = Py_None; + PyObject *qualname, *first_const = Py_None; arguments_ty args; expr_ty returns; identifier name; asdl_seq* decos; asdl_seq *body; + stmt_ty st; Py_ssize_t i, funcflags; + int docstring; int annotations; int scope_type; @@ -2010,16 +2034,21 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async) } /* if not -OO mode, add docstring */ - if (c->c_optimize < 2 && s->v.FunctionDef.docstring) - docstring = s->v.FunctionDef.docstring; - if (compiler_add_const(c, docstring) < 0) { + st = (stmt_ty)asdl_seq_GET(body, 0); + docstring = compiler_isdocstring(st); + if (docstring && c->c_optimize < 2) { + if (st->v.Expr.value->kind == Constant_kind) + first_const = st->v.Expr.value->v.Constant.value; + else + first_const = st->v.Expr.value->v.Str.s; + } + if (compiler_add_const(c, first_const) < 0) { compiler_exit_scope(c); return 0; } c->u->u_argcount = asdl_seq_LEN(args->args); c->u->u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs); - /* if there was a docstring, we need to skip the first statement */ VISIT_SEQ_IN_SCOPE(c, stmt, body); co = assemble(c, 1); qualname = c->u->u_qualname; @@ -2101,7 +2130,7 @@ compiler_class(struct compiler *c, stmt_ty s) } Py_DECREF(str); /* compile the body proper */ - if (!compiler_body(c, s->v.ClassDef.body, s->v.ClassDef.docstring)) { + if (!compiler_body(c, s->v.ClassDef.body)) { compiler_exit_scope(c); return 0; } diff --git a/Python/future.c b/Python/future.c index ade647f25baf..03a97c865a82 100644 --- a/Python/future.c +++ b/Python/future.c @@ -63,6 +63,7 @@ static int future_parse(PyFutureFeatures *ff, mod_ty mod, PyObject *filename) { int i, done = 0, prev_line = 0; + stmt_ty first; if (!(mod->kind == Module_kind || mod->kind == Interactive_kind)) return 1; @@ -78,7 +79,15 @@ future_parse(PyFutureFeatures *ff, mod_ty mod, PyObject *filename) but is preceded by a regular import. */ - for (i = 0; i < asdl_seq_LEN(mod->v.Module.body); i++) { + i = 0; + first = (stmt_ty)asdl_seq_GET(mod->v.Module.body, i); + if (first->kind == Expr_kind + && (first->v.Expr.value->kind == Str_kind + || (first->v.Expr.value->kind == Constant_kind + && PyUnicode_CheckExact(first->v.Expr.value->v.Constant.value)))) + i++; + + for (; i < asdl_seq_LEN(mod->v.Module.body); i++) { stmt_ty s = (stmt_ty)asdl_seq_GET(mod->v.Module.body, i); if (done && s->lineno > prev_line) diff --git a/Python/importlib.h b/Python/importlib.h index 3120faf5b78d..f006b87606f2 100644 --- a/Python/importlib.h +++ b/Python/importlib.h @@ -205,1624 +205,1625 @@ const unsigned char _Py_M__importlib[] = { 0,0,114,32,0,0,0,114,34,0,0,0,114,35,0,0, 0,114,40,0,0,0,114,10,0,0,0,114,10,0,0,0, 114,10,0,0,0,114,11,0,0,0,114,18,0,0,0,52, - 0,0,0,115,10,0,0,0,12,6,8,8,8,12,8,25, - 8,13,114,18,0,0,0,99,0,0,0,0,0,0,0,0, - 0,0,0,0,2,0,0,0,64,0,0,0,115,48,0,0, - 0,101,0,90,1,100,0,90,2,100,1,90,3,100,2,100, - 3,132,0,90,4,100,4,100,5,132,0,90,5,100,6,100, - 7,132,0,90,6,100,8,100,9,132,0,90,7,100,10,83, - 0,41,11,218,16,95,68,117,109,109,121,77,111,100,117,108, - 101,76,111,99,107,122,86,65,32,115,105,109,112,108,101,32, - 95,77,111,100,117,108,101,76,111,99,107,32,101,113,117,105, - 118,97,108,101,110,116,32,102,111,114,32,80,121,116,104,111, - 110,32,98,117,105,108,100,115,32,119,105,116,104,111,117,116, - 10,32,32,32,32,109,117,108,116,105,45,116,104,114,101,97, - 100,105,110,103,32,115,117,112,112,111,114,116,46,99,2,0, - 0,0,0,0,0,0,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,41,2,78,114,19,0,0,0,41, - 2,114,15,0,0,0,114,24,0,0,0,41,2,114,26,0, + 0,0,0,115,12,0,0,0,8,4,4,2,8,8,8,12, + 8,25,8,13,114,18,0,0,0,99,0,0,0,0,0,0, + 0,0,0,0,0,0,2,0,0,0,64,0,0,0,115,48, + 0,0,0,101,0,90,1,100,0,90,2,100,1,90,3,100, + 2,100,3,132,0,90,4,100,4,100,5,132,0,90,5,100, + 6,100,7,132,0,90,6,100,8,100,9,132,0,90,7,100, + 10,83,0,41,11,218,16,95,68,117,109,109,121,77,111,100, + 117,108,101,76,111,99,107,122,86,65,32,115,105,109,112,108, + 101,32,95,77,111,100,117,108,101,76,111,99,107,32,101,113, + 117,105,118,97,108,101,110,116,32,102,111,114,32,80,121,116, + 104,111,110,32,98,117,105,108,100,115,32,119,105,116,104,111, + 117,116,10,32,32,32,32,109,117,108,116,105,45,116,104,114, + 101,97,100,105,110,103,32,115,117,112,112,111,114,116,46,99, + 2,0,0,0,0,0,0,0,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,41,2,78,114,19,0,0, + 0,41,2,114,15,0,0,0,114,24,0,0,0,41,2,114, + 26,0,0,0,114,15,0,0,0,114,10,0,0,0,114,10, + 0,0,0,114,11,0,0,0,114,27,0,0,0,124,0,0, + 0,115,4,0,0,0,0,1,6,1,122,25,95,68,117,109, + 109,121,77,111,100,117,108,101,76,111,99,107,46,95,95,105, + 110,105,116,95,95,99,1,0,0,0,0,0,0,0,1,0, + 0,0,3,0,0,0,67,0,0,0,115,18,0,0,0,124, + 0,4,0,106,0,100,1,55,0,2,0,95,0,100,2,83, + 0,41,3,78,114,33,0,0,0,84,41,1,114,24,0,0, + 0,41,1,114,26,0,0,0,114,10,0,0,0,114,10,0, + 0,0,114,11,0,0,0,114,34,0,0,0,128,0,0,0, + 115,4,0,0,0,0,1,14,1,122,24,95,68,117,109,109, + 121,77,111,100,117,108,101,76,111,99,107,46,97,99,113,117, + 105,114,101,99,1,0,0,0,0,0,0,0,1,0,0,0, + 3,0,0,0,67,0,0,0,115,36,0,0,0,124,0,106, + 0,100,1,107,2,114,18,116,1,100,2,131,1,130,1,124, + 0,4,0,106,0,100,3,56,0,2,0,95,0,100,0,83, + 0,41,4,78,114,19,0,0,0,122,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,33,0,0,0,41, + 2,114,24,0,0,0,114,36,0,0,0,41,1,114,26,0, + 0,0,114,10,0,0,0,114,10,0,0,0,114,11,0,0, + 0,114,35,0,0,0,132,0,0,0,115,6,0,0,0,0, + 1,10,1,8,1,122,24,95,68,117,109,109,121,77,111,100, + 117,108,101,76,111,99,107,46,114,101,108,101,97,115,101,99, + 1,0,0,0,0,0,0,0,1,0,0,0,5,0,0,0, + 67,0,0,0,115,18,0,0,0,100,1,160,0,124,0,106, + 1,116,2,124,0,131,1,161,2,83,0,41,2,78,122,28, + 95,68,117,109,109,121,77,111,100,117,108,101,76,111,99,107, + 40,123,33,114,125,41,32,97,116,32,123,125,41,3,114,38, + 0,0,0,114,15,0,0,0,114,39,0,0,0,41,1,114, + 26,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,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,27,0,0,0,114,34,0,0,0,114, + 35,0,0,0,114,40,0,0,0,114,10,0,0,0,114,10, + 0,0,0,114,10,0,0,0,114,11,0,0,0,114,41,0, + 0,0,120,0,0,0,115,10,0,0,0,8,2,4,2,8, + 4,8,4,8,5,114,41,0,0,0,99,0,0,0,0,0, + 0,0,0,0,0,0,0,2,0,0,0,64,0,0,0,115, + 36,0,0,0,101,0,90,1,100,0,90,2,100,1,100,2, + 132,0,90,3,100,3,100,4,132,0,90,4,100,5,100,6, + 132,0,90,5,100,7,83,0,41,8,218,18,95,77,111,100, + 117,108,101,76,111,99,107,77,97,110,97,103,101,114,99,2, + 0,0,0,0,0,0,0,2,0,0,0,2,0,0,0,67, + 0,0,0,115,16,0,0,0,124,1,124,0,95,0,100,0, + 124,0,95,1,100,0,83,0,41,1,78,41,2,218,5,95, + 110,97,109,101,218,5,95,108,111,99,107,41,2,114,26,0, 0,0,114,15,0,0,0,114,10,0,0,0,114,10,0,0, - 0,114,11,0,0,0,114,27,0,0,0,124,0,0,0,115, - 4,0,0,0,0,1,6,1,122,25,95,68,117,109,109,121, - 77,111,100,117,108,101,76,111,99,107,46,95,95,105,110,105, - 116,95,95,99,1,0,0,0,0,0,0,0,1,0,0,0, - 3,0,0,0,67,0,0,0,115,18,0,0,0,124,0,4, - 0,106,0,100,1,55,0,2,0,95,0,100,2,83,0,41, - 3,78,114,33,0,0,0,84,41,1,114,24,0,0,0,41, + 0,114,11,0,0,0,114,27,0,0,0,143,0,0,0,115, + 4,0,0,0,0,1,6,1,122,27,95,77,111,100,117,108, + 101,76,111,99,107,77,97,110,97,103,101,114,46,95,95,105, + 110,105,116,95,95,99,1,0,0,0,0,0,0,0,1,0, + 0,0,2,0,0,0,67,0,0,0,115,26,0,0,0,116, + 0,124,0,106,1,131,1,124,0,95,2,124,0,106,2,160, + 3,161,0,1,0,100,0,83,0,41,1,78,41,4,218,16, + 95,103,101,116,95,109,111,100,117,108,101,95,108,111,99,107, + 114,43,0,0,0,114,44,0,0,0,114,34,0,0,0,41, + 1,114,26,0,0,0,114,10,0,0,0,114,10,0,0,0, + 114,11,0,0,0,218,9,95,95,101,110,116,101,114,95,95, + 147,0,0,0,115,4,0,0,0,0,1,12,1,122,28,95, + 77,111,100,117,108,101,76,111,99,107,77,97,110,97,103,101, + 114,46,95,95,101,110,116,101,114,95,95,99,1,0,0,0, + 0,0,0,0,3,0,0,0,2,0,0,0,79,0,0,0, + 115,14,0,0,0,124,0,106,0,160,1,161,0,1,0,100, + 0,83,0,41,1,78,41,2,114,44,0,0,0,114,35,0, + 0,0,41,3,114,26,0,0,0,218,4,97,114,103,115,90, + 6,107,119,97,114,103,115,114,10,0,0,0,114,10,0,0, + 0,114,11,0,0,0,218,8,95,95,101,120,105,116,95,95, + 151,0,0,0,115,2,0,0,0,0,1,122,27,95,77,111, + 100,117,108,101,76,111,99,107,77,97,110,97,103,101,114,46, + 95,95,101,120,105,116,95,95,78,41,6,114,1,0,0,0, + 114,0,0,0,0,114,2,0,0,0,114,27,0,0,0,114, + 46,0,0,0,114,48,0,0,0,114,10,0,0,0,114,10, + 0,0,0,114,10,0,0,0,114,11,0,0,0,114,42,0, + 0,0,141,0,0,0,115,6,0,0,0,8,2,8,4,8, + 4,114,42,0,0,0,99,1,0,0,0,0,0,0,0,3, + 0,0,0,8,0,0,0,67,0,0,0,115,130,0,0,0, + 116,0,160,1,161,0,1,0,122,106,122,14,116,2,124,0, + 25,0,131,0,125,1,87,0,110,24,4,0,116,3,107,10, + 114,48,1,0,1,0,1,0,100,1,125,1,89,0,110,2, + 88,0,124,1,100,1,107,8,114,112,116,4,100,1,107,8, + 114,76,116,5,124,0,131,1,125,1,110,8,116,6,124,0, + 131,1,125,1,124,0,102,1,100,2,100,3,132,1,125,2, + 116,7,160,8,124,1,124,2,161,2,116,2,124,0,60,0, + 87,0,53,0,116,0,160,9,161,0,1,0,88,0,124,1, + 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,2,0,0,0,8, + 0,0,0,83,0,0,0,115,48,0,0,0,116,0,160,1, + 161,0,1,0,122,24,116,2,160,3,124,1,161,1,124,0, + 107,8,114,30,116,2,124,1,61,0,87,0,53,0,116,0, + 160,4,161,0,1,0,88,0,100,0,83,0,41,1,78,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,30,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,15, + 0,0,0,114,10,0,0,0,114,10,0,0,0,114,11,0, + 0,0,218,2,99,98,176,0,0,0,115,10,0,0,0,0, + 1,8,1,2,4,14,1,10,2,122,28,95,103,101,116,95, + 109,111,100,117,108,101,95,108,111,99,107,46,60,108,111,99, + 97,108,115,62,46,99,98,41,10,114,49,0,0,0,114,50, + 0,0,0,114,51,0,0,0,218,8,75,101,121,69,114,114, + 111,114,114,20,0,0,0,114,41,0,0,0,114,18,0,0, + 0,218,8,95,119,101,97,107,114,101,102,114,53,0,0,0, + 114,52,0,0,0,41,3,114,15,0,0,0,114,21,0,0, + 0,114,54,0,0,0,114,10,0,0,0,114,10,0,0,0, + 114,11,0,0,0,114,45,0,0,0,157,0,0,0,115,28, + 0,0,0,0,6,8,1,2,1,2,1,14,1,14,1,10, + 2,8,1,8,1,10,2,8,2,12,11,20,2,10,2,114, + 45,0,0,0,99,1,0,0,0,0,0,0,0,2,0,0, + 0,8,0,0,0,67,0,0,0,115,54,0,0,0,116,0, + 124,0,131,1,125,1,122,12,124,1,160,1,161,0,1,0, + 87,0,110,20,4,0,116,2,107,10,114,40,1,0,1,0, + 1,0,89,0,110,10,88,0,124,1,160,3,161,0,1,0, + 100,1,83,0,41,2,122,189,65,99,113,117,105,114,101,115, + 32,116,104,101,110,32,114,101,108,101,97,115,101,115,32,116, + 104,101,32,109,111,100,117,108,101,32,108,111,99,107,32,102, + 111,114,32,97,32,103,105,118,101,110,32,109,111,100,117,108, + 101,32,110,97,109,101,46,10,10,32,32,32,32,84,104,105, + 115,32,105,115,32,117,115,101,100,32,116,111,32,101,110,115, + 117,114,101,32,97,32,109,111,100,117,108,101,32,105,115,32, + 99,111,109,112,108,101,116,101,108,121,32,105,110,105,116,105, + 97,108,105,122,101,100,44,32,105,110,32,116,104,101,10,32, + 32,32,32,101,118,101,110,116,32,105,116,32,105,115,32,98, + 101,105,110,103,32,105,109,112,111,114,116,101,100,32,98,121, + 32,97,110,111,116,104,101,114,32,116,104,114,101,97,100,46, + 10,32,32,32,32,78,41,4,114,45,0,0,0,114,34,0, + 0,0,114,17,0,0,0,114,35,0,0,0,41,2,114,15, + 0,0,0,114,21,0,0,0,114,10,0,0,0,114,10,0, + 0,0,114,11,0,0,0,218,19,95,108,111,99,107,95,117, + 110,108,111,99,107,95,109,111,100,117,108,101,194,0,0,0, + 115,12,0,0,0,0,6,8,1,2,1,12,1,14,3,6, + 2,114,57,0,0,0,99,1,0,0,0,0,0,0,0,3, + 0,0,0,3,0,0,0,79,0,0,0,115,10,0,0,0, + 124,0,124,1,124,2,142,1,83,0,41,1,97,46,1,0, + 0,114,101,109,111,118,101,95,105,109,112,111,114,116,108,105, + 98,95,102,114,97,109,101,115,32,105,110,32,105,109,112,111, + 114,116,46,99,32,119,105,108,108,32,97,108,119,97,121,115, + 32,114,101,109,111,118,101,32,115,101,113,117,101,110,99,101, + 115,10,32,32,32,32,111,102,32,105,109,112,111,114,116,108, + 105,98,32,102,114,97,109,101,115,32,116,104,97,116,32,101, + 110,100,32,119,105,116,104,32,97,32,99,97,108,108,32,116, + 111,32,116,104,105,115,32,102,117,110,99,116,105,111,110,10, + 10,32,32,32,32,85,115,101,32,105,116,32,105,110,115,116, + 101,97,100,32,111,102,32,97,32,110,111,114,109,97,108,32, + 99,97,108,108,32,105,110,32,112,108,97,99,101,115,32,119, + 104,101,114,101,32,105,110,99,108,117,100,105,110,103,32,116, + 104,101,32,105,109,112,111,114,116,108,105,98,10,32,32,32, + 32,102,114,97,109,101,115,32,105,110,116,114,111,100,117,99, + 101,115,32,117,110,119,97,110,116,101,100,32,110,111,105,115, + 101,32,105,110,116,111,32,116,104,101,32,116,114,97,99,101, + 98,97,99,107,32,40,101,46,103,46,32,119,104,101,110,32, + 101,120,101,99,117,116,105,110,103,10,32,32,32,32,109,111, + 100,117,108,101,32,99,111,100,101,41,10,32,32,32,32,114, + 10,0,0,0,41,3,218,1,102,114,47,0,0,0,90,4, + 107,119,100,115,114,10,0,0,0,114,10,0,0,0,114,11, + 0,0,0,218,25,95,99,97,108,108,95,119,105,116,104,95, + 102,114,97,109,101,115,95,114,101,109,111,118,101,100,211,0, + 0,0,115,2,0,0,0,0,8,114,59,0,0,0,114,33, + 0,0,0,41,1,218,9,118,101,114,98,111,115,105,116,121, + 99,1,0,0,0,1,0,0,0,3,0,0,0,4,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,14, + 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,38,0,0,0,218,6,115,116,100, + 101,114,114,41,3,218,7,109,101,115,115,97,103,101,114,60, + 0,0,0,114,47,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,68,0,0,0,99, + 1,0,0,0,0,0,0,0,2,0,0,0,3,0,0,0, + 3,0,0,0,115,26,0,0,0,135,0,102,1,100,1,100, + 2,132,8,125,1,116,0,124,1,136,0,131,2,1,0,124, + 1,83,0,41,3,122,49,68,101,99,111,114,97,116,111,114, + 32,116,111,32,118,101,114,105,102,121,32,116,104,101,32,110, + 97,109,101,100,32,109,111,100,117,108,101,32,105,115,32,98, + 117,105,108,116,45,105,110,46,99,2,0,0,0,0,0,0, + 0,2,0,0,0,4,0,0,0,19,0,0,0,115,38,0, + 0,0,124,1,116,0,106,1,107,7,114,28,116,2,100,1, + 160,3,124,1,161,1,124,1,100,2,141,2,130,1,136,0, + 124,0,124,1,131,2,83,0,41,3,78,122,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,41,1,114,15,0,0, + 0,41,4,114,14,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,38,0,0,0, + 41,2,114,26,0,0,0,218,8,102,117,108,108,110,97,109, + 101,41,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,8,0,0,0,0,1,10,1,10,1,8,1,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,41,1,114,12,0,0,0,41,2,114,72,0, + 0,0,114,73,0,0,0,114,10,0,0,0,41,1,114,72, + 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,74,0,0,0,99, + 1,0,0,0,0,0,0,0,2,0,0,0,3,0,0,0, + 3,0,0,0,115,26,0,0,0,135,0,102,1,100,1,100, + 2,132,8,125,1,116,0,124,1,136,0,131,2,1,0,124, + 1,83,0,41,3,122,47,68,101,99,111,114,97,116,111,114, + 32,116,111,32,118,101,114,105,102,121,32,116,104,101,32,110, + 97,109,101,100,32,109,111,100,117,108,101,32,105,115,32,102, + 114,111,122,101,110,46,99,2,0,0,0,0,0,0,0,2, + 0,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,41,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,41,1,114,15,0,0,0,41,4,114, + 49,0,0,0,218,9,105,115,95,102,114,111,122,101,110,114, + 70,0,0,0,114,38,0,0,0,41,2,114,26,0,0,0, + 114,71,0,0,0,41,1,114,72,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,8,0,0,0,0,1,10,1,10,1,8, + 1,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,41,1,114,12,0,0,0,41,2,114,72, + 0,0,0,114,76,0,0,0,114,10,0,0,0,41,1,114, + 72,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,77,0,0,0,99, + 2,0,0,0,0,0,0,0,4,0,0,0,3,0,0,0, + 67,0,0,0,115,62,0,0,0,116,0,124,1,124,0,131, + 2,125,2,124,1,116,1,106,2,107,6,114,50,116,1,106, + 2,124,1,25,0,125,3,116,3,124,2,124,3,131,2,1, + 0,116,1,106,2,124,1,25,0,83,0,116,4,124,2,131, + 1,83,0,100,1,83,0,41,2,122,128,76,111,97,100,32, + 116,104,101,32,115,112,101,99,105,102,105,101,100,32,109,111, + 100,117,108,101,32,105,110,116,111,32,115,121,115,46,109,111, + 100,117,108,101,115,32,97,110,100,32,114,101,116,117,114,110, + 32,105,116,46,10,10,32,32,32,32,84,104,105,115,32,109, + 101,116,104,111,100,32,105,115,32,100,101,112,114,101,99,97, + 116,101,100,46,32,32,85,115,101,32,108,111,97,100,101,114, + 46,101,120,101,99,95,109,111,100,117,108,101,32,105,110,115, + 116,101,97,100,46,10,10,32,32,32,32,78,41,5,218,16, + 115,112,101,99,95,102,114,111,109,95,108,111,97,100,101,114, + 114,14,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,26, + 0,0,0,114,71,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,84,0, + 0,0,99,1,0,0,0,0,0,0,0,5,0,0,0,8, + 0,0,0,67,0,0,0,115,226,0,0,0,116,0,124,0, + 100,1,100,0,131,3,125,1,116,1,124,1,100,2,131,2, + 114,56,122,12,124,1,160,2,124,0,161,1,87,0,83,0, + 4,0,116,3,107,10,114,54,1,0,1,0,1,0,89,0, + 110,2,88,0,122,10,124,0,106,4,125,2,87,0,110,20, + 4,0,116,5,107,10,114,86,1,0,1,0,1,0,89,0, + 110,18,88,0,124,2,100,0,107,9,114,104,116,6,124,2, + 131,1,83,0,122,10,124,0,106,7,125,3,87,0,110,24, + 4,0,116,5,107,10,114,138,1,0,1,0,1,0,100,3, + 125,3,89,0,110,2,88,0,122,10,124,0,106,8,125,4, + 87,0,110,58,4,0,116,5,107,10,114,208,1,0,1,0, + 1,0,124,1,100,0,107,8,114,188,100,4,160,9,124,3, + 161,1,6,0,89,0,83,0,100,5,160,9,124,3,124,1, + 161,2,6,0,89,0,83,0,89,0,110,14,88,0,100,6, + 160,9,124,3,124,4,161,2,83,0,100,0,83,0,41,7, + 78,218,10,95,95,108,111,97,100,101,114,95,95,218,11,109, + 111,100,117,108,101,95,114,101,112,114,250,1,63,122,13,60, + 109,111,100,117,108,101,32,123,33,114,125,62,122,20,60,109, + 111,100,117,108,101,32,123,33,114,125,32,40,123,33,114,125, + 41,62,122,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,86,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,38,0,0,0,41,5,114, + 83,0,0,0,218,6,108,111,97,100,101,114,114,82,0,0, + 0,114,15,0,0,0,218,8,102,105,108,101,110,97,109,101, + 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,218, + 12,95,109,111,100,117,108,101,95,114,101,112,114,13,1,0, + 0,115,46,0,0,0,0,2,12,1,10,4,2,1,12,1, + 14,1,6,1,2,1,10,1,14,1,6,2,8,1,8,4, + 2,1,10,1,14,1,10,1,2,1,10,1,14,1,8,1, + 14,2,22,2,114,95,0,0,0,99,0,0,0,0,0,0, + 0,0,0,0,0,0,2,0,0,0,64,0,0,0,115,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,17,95,105,110,115,116, + 97,108,108,101,100,95,115,97,102,101,108,121,99,2,0,0, + 0,0,0,0,0,2,0,0,0,2,0,0,0,67,0,0, + 0,115,18,0,0,0,124,1,124,0,95,0,124,1,106,1, + 124,0,95,2,100,0,83,0,41,1,78,41,3,218,7,95, + 109,111,100,117,108,101,114,89,0,0,0,218,5,95,115,112, + 101,99,41,2,114,26,0,0,0,114,83,0,0,0,114,10, + 0,0,0,114,10,0,0,0,114,11,0,0,0,114,27,0, + 0,0,51,1,0,0,115,4,0,0,0,0,1,6,1,122, + 26,95,105,110,115,116,97,108,108,101,100,95,115,97,102,101, + 108,121,46,95,95,105,110,105,116,95,95,99,1,0,0,0, + 0,0,0,0,1,0,0,0,3,0,0,0,67,0,0,0, + 115,28,0,0,0,100,1,124,0,106,0,95,1,124,0,106, + 2,116,3,106,4,124,0,106,0,106,5,60,0,100,0,83, + 0,41,2,78,84,41,6,114,98,0,0,0,218,13,95,105, + 110,105,116,105,97,108,105,122,105,110,103,114,97,0,0,0, + 114,14,0,0,0,114,79,0,0,0,114,15,0,0,0,41, 1,114,26,0,0,0,114,10,0,0,0,114,10,0,0,0, - 114,11,0,0,0,114,34,0,0,0,128,0,0,0,115,4, - 0,0,0,0,1,14,1,122,24,95,68,117,109,109,121,77, - 111,100,117,108,101,76,111,99,107,46,97,99,113,117,105,114, - 101,99,1,0,0,0,0,0,0,0,1,0,0,0,3,0, - 0,0,67,0,0,0,115,36,0,0,0,124,0,106,0,100, - 1,107,2,114,18,116,1,100,2,131,1,130,1,124,0,4, - 0,106,0,100,3,56,0,2,0,95,0,100,0,83,0,41, - 4,78,114,19,0,0,0,122,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,33,0,0,0,41,2,114, - 24,0,0,0,114,36,0,0,0,41,1,114,26,0,0,0, + 114,11,0,0,0,114,46,0,0,0,55,1,0,0,115,4, + 0,0,0,0,4,8,1,122,27,95,105,110,115,116,97,108, + 108,101,100,95,115,97,102,101,108,121,46,95,95,101,110,116, + 101,114,95,95,99,1,0,0,0,0,0,0,0,3,0,0, + 0,8,0,0,0,71,0,0,0,115,98,0,0,0,122,82, + 124,0,106,0,125,2,116,1,100,1,100,2,132,0,124,1, + 68,0,131,1,131,1,114,64,122,14,116,2,106,3,124,2, + 106,4,61,0,87,0,113,80,4,0,116,5,107,10,114,60, + 1,0,1,0,1,0,89,0,113,80,88,0,110,16,116,6, + 100,3,124,2,106,4,124,2,106,7,131,3,1,0,87,0, + 53,0,100,4,124,0,106,0,95,8,88,0,100,0,83,0, + 41,5,78,99,1,0,0,0,0,0,0,0,2,0,0,0, + 3,0,0,0,115,0,0,0,115,22,0,0,0,124,0,93, + 14,125,1,124,1,100,0,107,9,86,0,1,0,113,2,100, + 0,83,0,41,1,78,114,10,0,0,0,41,2,90,2,46, + 48,90,3,97,114,103,114,10,0,0,0,114,10,0,0,0, + 114,11,0,0,0,218,9,60,103,101,110,101,120,112,114,62, + 65,1,0,0,115,2,0,0,0,4,0,122,45,95,105,110, + 115,116,97,108,108,101,100,95,115,97,102,101,108,121,46,95, + 95,101,120,105,116,95,95,46,60,108,111,99,97,108,115,62, + 46,60,103,101,110,101,120,112,114,62,122,18,105,109,112,111, + 114,116,32,123,33,114,125,32,35,32,123,33,114,125,70,41, + 9,114,98,0,0,0,218,3,97,110,121,114,14,0,0,0, + 114,79,0,0,0,114,15,0,0,0,114,55,0,0,0,114, + 68,0,0,0,114,93,0,0,0,114,99,0,0,0,41,3, + 114,26,0,0,0,114,47,0,0,0,114,82,0,0,0,114, + 10,0,0,0,114,10,0,0,0,114,11,0,0,0,114,48, + 0,0,0,62,1,0,0,115,18,0,0,0,0,1,2,1, + 6,1,18,1,2,1,14,1,14,1,8,2,20,2,122,26, + 95,105,110,115,116,97,108,108,101,100,95,115,97,102,101,108, + 121,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,27,0,0, + 0,114,46,0,0,0,114,48,0,0,0,114,10,0,0,0, 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,114, - 35,0,0,0,132,0,0,0,115,6,0,0,0,0,1,10, - 1,8,1,122,24,95,68,117,109,109,121,77,111,100,117,108, - 101,76,111,99,107,46,114,101,108,101,97,115,101,99,1,0, - 0,0,0,0,0,0,1,0,0,0,5,0,0,0,67,0, - 0,0,115,18,0,0,0,100,1,160,0,124,0,106,1,116, - 2,124,0,131,1,161,2,83,0,41,2,78,122,28,95,68, - 117,109,109,121,77,111,100,117,108,101,76,111,99,107,40,123, - 33,114,125,41,32,97,116,32,123,125,41,3,114,38,0,0, - 0,114,15,0,0,0,114,39,0,0,0,41,1,114,26,0, + 96,0,0,0,49,1,0,0,115,6,0,0,0,8,2,8, + 4,8,7,114,96,0,0,0,99,0,0,0,0,0,0,0, + 0,0,0,0,0,4,0,0,0,64,0,0,0,115,114,0, + 0,0,101,0,90,1,100,0,90,2,100,1,90,3,100,2, + 100,2,100,2,100,3,156,3,100,4,100,5,132,2,90,4, + 100,6,100,7,132,0,90,5,100,8,100,9,132,0,90,6, + 101,7,100,10,100,11,132,0,131,1,90,8,101,8,106,9, + 100,12,100,11,132,0,131,1,90,8,101,7,100,13,100,14, + 132,0,131,1,90,10,101,7,100,15,100,16,132,0,131,1, + 90,11,101,11,106,9,100,17,100,16,132,0,131,1,90,11, + 100,2,83,0,41,18,218,10,77,111,100,117,108,101,83,112, + 101,99,97,208,5,0,0,84,104,101,32,115,112,101,99,105, + 102,105,99,97,116,105,111,110,32,102,111,114,32,97,32,109, + 111,100,117,108,101,44,32,117,115,101,100,32,102,111,114,32, + 108,111,97,100,105,110,103,46,10,10,32,32,32,32,65,32, + 109,111,100,117,108,101,39,115,32,115,112,101,99,32,105,115, + 32,116,104,101,32,115,111,117,114,99,101,32,102,111,114,32, + 105,110,102,111,114,109,97,116,105,111,110,32,97,98,111,117, + 116,32,116,104,101,32,109,111,100,117,108,101,46,32,32,70, + 111,114,10,32,32,32,32,100,97,116,97,32,97,115,115,111, + 99,105,97,116,101,100,32,119,105,116,104,32,116,104,101,32, + 109,111,100,117,108,101,44,32,105,110,99,108,117,100,105,110, + 103,32,115,111,117,114,99,101,44,32,117,115,101,32,116,104, + 101,32,115,112,101,99,39,115,10,32,32,32,32,108,111,97, + 100,101,114,46,10,10,32,32,32,32,96,110,97,109,101,96, + 32,105,115,32,116,104,101,32,97,98,115,111,108,117,116,101, + 32,110,97,109,101,32,111,102,32,116,104,101,32,109,111,100, + 117,108,101,46,32,32,96,108,111,97,100,101,114,96,32,105, + 115,32,116,104,101,32,108,111,97,100,101,114,10,32,32,32, + 32,116,111,32,117,115,101,32,119,104,101,110,32,108,111,97, + 100,105,110,103,32,116,104,101,32,109,111,100,117,108,101,46, + 32,32,96,112,97,114,101,110,116,96,32,105,115,32,116,104, + 101,32,110,97,109,101,32,111,102,32,116,104,101,10,32,32, + 32,32,112,97,99,107,97,103,101,32,116,104,101,32,109,111, + 100,117,108,101,32,105,115,32,105,110,46,32,32,84,104,101, + 32,112,97,114,101,110,116,32,105,115,32,100,101,114,105,118, + 101,100,32,102,114,111,109,32,116,104,101,32,110,97,109,101, + 46,10,10,32,32,32,32,96,105,115,95,112,97,99,107,97, + 103,101,96,32,100,101,116,101,114,109,105,110,101,115,32,105, + 102,32,116,104,101,32,109,111,100,117,108,101,32,105,115,32, + 99,111,110,115,105,100,101,114,101,100,32,97,32,112,97,99, + 107,97,103,101,32,111,114,10,32,32,32,32,110,111,116,46, + 32,32,79,110,32,109,111,100,117,108,101,115,32,116,104,105, + 115,32,105,115,32,114,101,102,108,101,99,116,101,100,32,98, + 121,32,116,104,101,32,96,95,95,112,97,116,104,95,95,96, + 32,97,116,116,114,105,98,117,116,101,46,10,10,32,32,32, + 32,96,111,114,105,103,105,110,96,32,105,115,32,116,104,101, + 32,115,112,101,99,105,102,105,99,32,108,111,99,97,116,105, + 111,110,32,117,115,101,100,32,98,121,32,116,104,101,32,108, + 111,97,100,101,114,32,102,114,111,109,32,119,104,105,99,104, + 32,116,111,10,32,32,32,32,108,111,97,100,32,116,104,101, + 32,109,111,100,117,108,101,44,32,105,102,32,116,104,97,116, + 32,105,110,102,111,114,109,97,116,105,111,110,32,105,115,32, + 97,118,97,105,108,97,98,108,101,46,32,32,87,104,101,110, + 32,102,105,108,101,110,97,109,101,32,105,115,10,32,32,32, + 32,115,101,116,44,32,111,114,105,103,105,110,32,119,105,108, + 108,32,109,97,116,99,104,46,10,10,32,32,32,32,96,104, + 97,115,95,108,111,99,97,116,105,111,110,96,32,105,110,100, + 105,99,97,116,101,115,32,116,104,97,116,32,97,32,115,112, + 101,99,39,115,32,34,111,114,105,103,105,110,34,32,114,101, + 102,108,101,99,116,115,32,97,32,108,111,99,97,116,105,111, + 110,46,10,32,32,32,32,87,104,101,110,32,116,104,105,115, + 32,105,115,32,84,114,117,101,44,32,96,95,95,102,105,108, + 101,95,95,96,32,97,116,116,114,105,98,117,116,101,32,111, + 102,32,116,104,101,32,109,111,100,117,108,101,32,105,115,32, + 115,101,116,46,10,10,32,32,32,32,96,99,97,99,104,101, + 100,96,32,105,115,32,116,104,101,32,108,111,99,97,116,105, + 111,110,32,111,102,32,116,104,101,32,99,97,99,104,101,100, + 32,98,121,116,101,99,111,100,101,32,102,105,108,101,44,32, + 105,102,32,97,110,121,46,32,32,73,116,10,32,32,32,32, + 99,111,114,114,101,115,112,111,110,100,115,32,116,111,32,116, + 104,101,32,96,95,95,99,97,99,104,101,100,95,95,96,32, + 97,116,116,114,105,98,117,116,101,46,10,10,32,32,32,32, + 96,115,117,98,109,111,100,117,108,101,95,115,101,97,114,99, + 104,95,108,111,99,97,116,105,111,110,115,96,32,105,115,32, + 116,104,101,32,115,101,113,117,101,110,99,101,32,111,102,32, + 112,97,116,104,32,101,110,116,114,105,101,115,32,116,111,10, + 32,32,32,32,115,101,97,114,99,104,32,119,104,101,110,32, + 105,109,112,111,114,116,105,110,103,32,115,117,98,109,111,100, + 117,108,101,115,46,32,32,73,102,32,115,101,116,44,32,105, + 115,95,112,97,99,107,97,103,101,32,115,104,111,117,108,100, + 32,98,101,10,32,32,32,32,84,114,117,101,45,45,97,110, + 100,32,70,97,108,115,101,32,111,116,104,101,114,119,105,115, + 101,46,10,10,32,32,32,32,80,97,99,107,97,103,101,115, + 32,97,114,101,32,115,105,109,112,108,121,32,109,111,100,117, + 108,101,115,32,116,104,97,116,32,40,109,97,121,41,32,104, + 97,118,101,32,115,117,98,109,111,100,117,108,101,115,46,32, + 32,73,102,32,97,32,115,112,101,99,10,32,32,32,32,104, + 97,115,32,97,32,110,111,110,45,78,111,110,101,32,118,97, + 108,117,101,32,105,110,32,96,115,117,98,109,111,100,117,108, + 101,95,115,101,97,114,99,104,95,108,111,99,97,116,105,111, + 110,115,96,44,32,116,104,101,32,105,109,112,111,114,116,10, + 32,32,32,32,115,121,115,116,101,109,32,119,105,108,108,32, + 99,111,110,115,105,100,101,114,32,109,111,100,117,108,101,115, + 32,108,111,97,100,101,100,32,102,114,111,109,32,116,104,101, + 32,115,112,101,99,32,97,115,32,112,97,99,107,97,103,101, + 115,46,10,10,32,32,32,32,79,110,108,121,32,102,105,110, + 100,101,114,115,32,40,115,101,101,32,105,109,112,111,114,116, + 108,105,98,46,97,98,99,46,77,101,116,97,80,97,116,104, + 70,105,110,100,101,114,32,97,110,100,10,32,32,32,32,105, + 109,112,111,114,116,108,105,98,46,97,98,99,46,80,97,116, + 104,69,110,116,114,121,70,105,110,100,101,114,41,32,115,104, + 111,117,108,100,32,109,111,100,105,102,121,32,77,111,100,117, + 108,101,83,112,101,99,32,105,110,115,116,97,110,99,101,115, + 46,10,10,32,32,32,32,78,41,3,218,6,111,114,105,103, + 105,110,218,12,108,111,97,100,101,114,95,115,116,97,116,101, + 218,10,105,115,95,112,97,99,107,97,103,101,99,3,0,0, + 0,3,0,0,0,6,0,0,0,2,0,0,0,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,15,0,0,0,114,93,0,0,0,114,103,0,0, + 0,114,104,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,26,0,0, + 0,114,15,0,0,0,114,93,0,0,0,114,103,0,0,0, + 114,104,0,0,0,114,105,0,0,0,114,10,0,0,0,114, + 10,0,0,0,114,11,0,0,0,114,27,0,0,0,113,1, + 0,0,115,14,0,0,0,0,2,6,1,6,1,6,1,6, + 1,14,3,6,1,122,19,77,111,100,117,108,101,83,112,101, + 99,46,95,95,105,110,105,116,95,95,99,1,0,0,0,0, + 0,0,0,2,0,0,0,6,0,0,0,67,0,0,0,115, + 102,0,0,0,100,1,160,0,124,0,106,1,161,1,100,2, + 160,0,124,0,106,2,161,1,103,2,125,1,124,0,106,3, + 100,0,107,9,114,52,124,1,160,4,100,3,160,0,124,0, + 106,3,161,1,161,1,1,0,124,0,106,5,100,0,107,9, + 114,80,124,1,160,4,100,4,160,0,124,0,106,5,161,1, + 161,1,1,0,100,5,160,0,124,0,106,6,106,7,100,6, + 160,8,124,1,161,1,161,2,83,0,41,7,78,122,9,110, + 97,109,101,61,123,33,114,125,122,11,108,111,97,100,101,114, + 61,123,33,114,125,122,11,111,114,105,103,105,110,61,123,33, + 114,125,122,29,115,117,98,109,111,100,117,108,101,95,115,101, + 97,114,99,104,95,108,111,99,97,116,105,111,110,115,61,123, + 125,122,6,123,125,40,123,125,41,122,2,44,32,41,9,114, + 38,0,0,0,114,15,0,0,0,114,93,0,0,0,114,103, + 0,0,0,218,6,97,112,112,101,110,100,114,106,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,26,0,0,0,114,47,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,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,27,0,0,0,114,34,0,0,0,114,35,0, - 0,0,114,40,0,0,0,114,10,0,0,0,114,10,0,0, - 0,114,10,0,0,0,114,11,0,0,0,114,41,0,0,0, - 120,0,0,0,115,8,0,0,0,12,4,8,4,8,4,8, - 5,114,41,0,0,0,99,0,0,0,0,0,0,0,0,0, - 0,0,0,2,0,0,0,64,0,0,0,115,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,114,40,0,0,0,125,1,0,0,115,16,0,0,0,0, + 1,10,1,14,1,10,1,18,1,10,1,8,1,10,1,122, + 19,77,111,100,117,108,101,83,112,101,99,46,95,95,114,101, + 112,114,95,95,99,2,0,0,0,0,0,0,0,3,0,0, + 0,8,0,0,0,67,0,0,0,115,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,107,10,114,100,1,0,1,0,1,0,89,0,100,1, + 83,0,88,0,100,0,83,0,41,2,78,70,41,7,114,106, + 0,0,0,114,15,0,0,0,114,93,0,0,0,114,103,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,90,0,0,0,41,3,114, + 26,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,135,1,0,0,115,20,0,0, + 0,0,1,6,1,2,1,12,1,12,1,12,1,10,1,12, + 1,14,1,14,1,122,17,77,111,100,117,108,101,83,112,101, + 99,46,95,95,101,113,95,95,99,1,0,0,0,0,0,0, + 0,1,0,0,0,3,0,0,0,67,0,0,0,115,58,0, + 0,0,124,0,106,0,100,0,107,8,114,52,124,0,106,1, + 100,0,107,9,114,52,124,0,106,2,114,52,116,3,100,0, + 107,8,114,38,116,4,130,1,116,3,160,5,124,0,106,1, + 161,1,124,0,95,0,124,0,106,0,83,0,41,1,78,41, + 6,114,108,0,0,0,114,103,0,0,0,114,107,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,41,1,114,26,0,0,0,114,10, + 0,0,0,114,10,0,0,0,114,11,0,0,0,114,112,0, + 0,0,147,1,0,0,115,12,0,0,0,0,2,10,1,16, + 1,8,1,4,1,14,1,122,17,77,111,100,117,108,101,83, + 112,101,99,46,99,97,99,104,101,100,99,2,0,0,0,0, 0,0,0,2,0,0,0,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,41,1,78,41,2,218,5,95,110,97,109,101, - 218,5,95,108,111,99,107,41,2,114,26,0,0,0,114,15, + 10,0,0,0,124,1,124,0,95,0,100,0,83,0,41,1, + 78,41,1,114,108,0,0,0,41,2,114,26,0,0,0,114, + 112,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, + 0,0,0,114,112,0,0,0,156,1,0,0,115,2,0,0, + 0,0,2,99,1,0,0,0,0,0,0,0,1,0,0,0, + 3,0,0,0,67,0,0,0,115,36,0,0,0,124,0,106, + 0,100,1,107,8,114,26,124,0,106,1,160,2,100,2,161, + 1,100,3,25,0,83,0,124,0,106,1,83,0,100,1,83, + 0,41,4,122,32,84,104,101,32,110,97,109,101,32,111,102, + 32,116,104,101,32,109,111,100,117,108,101,39,115,32,112,97, + 114,101,110,116,46,78,218,1,46,114,19,0,0,0,41,3, + 114,106,0,0,0,114,15,0,0,0,218,10,114,112,97,114, + 116,105,116,105,111,110,41,1,114,26,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,160,1,0,0,115,6,0,0,0,0,3,10, + 1,16,2,122,17,77,111,100,117,108,101,83,112,101,99,46, + 112,97,114,101,110,116,99,1,0,0,0,0,0,0,0,1, + 0,0,0,1,0,0,0,67,0,0,0,115,6,0,0,0, + 124,0,106,0,83,0,41,1,78,41,1,114,107,0,0,0, + 41,1,114,26,0,0,0,114,10,0,0,0,114,10,0,0, + 0,114,11,0,0,0,114,113,0,0,0,168,1,0,0,115, + 2,0,0,0,0,2,122,23,77,111,100,117,108,101,83,112, + 101,99,46,104,97,115,95,108,111,99,97,116,105,111,110,99, + 2,0,0,0,0,0,0,0,2,0,0,0,2,0,0,0, + 67,0,0,0,115,14,0,0,0,116,0,124,1,131,1,124, + 0,95,1,100,0,83,0,41,1,78,41,2,218,4,98,111, + 111,108,114,107,0,0,0,41,2,114,26,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,113,0,0,0,172,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,27,0,0,0,114, + 40,0,0,0,114,114,0,0,0,218,8,112,114,111,112,101, + 114,116,121,114,112,0,0,0,218,6,115,101,116,116,101,114, + 114,119,0,0,0,114,113,0,0,0,114,10,0,0,0,114, + 10,0,0,0,114,10,0,0,0,114,11,0,0,0,114,102, + 0,0,0,76,1,0,0,115,20,0,0,0,8,35,4,2, + 4,1,14,11,8,10,8,12,12,9,14,4,12,8,12,4, + 114,102,0,0,0,41,2,114,103,0,0,0,114,105,0,0, + 0,99,2,0,0,0,2,0,0,0,6,0,0,0,8,0, + 0,0,67,0,0,0,115,154,0,0,0,116,0,124,1,100, + 1,131,2,114,74,116,1,100,2,107,8,114,22,116,2,130, + 1,116,1,106,3,125,4,124,3,100,2,107,8,114,48,124, + 4,124,0,124,1,100,3,141,2,83,0,124,3,114,56,103, + 0,110,2,100,2,125,5,124,4,124,0,124,1,124,5,100, + 4,141,3,83,0,124,3,100,2,107,8,114,138,116,0,124, + 1,100,5,131,2,114,134,122,14,124,1,160,4,124,0,161, + 1,125,3,87,0,113,138,4,0,116,5,107,10,114,130,1, + 0,1,0,1,0,100,2,125,3,89,0,113,138,88,0,110, + 4,100,6,125,3,116,6,124,0,124,1,124,2,124,3,100, + 7,141,4,83,0,41,8,122,53,82,101,116,117,114,110,32, + 97,32,109,111,100,117,108,101,32,115,112,101,99,32,98,97, + 115,101,100,32,111,110,32,118,97,114,105,111,117,115,32,108, + 111,97,100,101,114,32,109,101,116,104,111,100,115,46,90,12, + 103,101,116,95,102,105,108,101,110,97,109,101,78,41,1,114, + 93,0,0,0,41,2,114,93,0,0,0,114,106,0,0,0, + 114,105,0,0,0,70,41,2,114,103,0,0,0,114,105,0, + 0,0,41,7,114,4,0,0,0,114,115,0,0,0,114,116, + 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,105,0,0, + 0,114,70,0,0,0,114,102,0,0,0,41,6,114,15,0, + 0,0,114,93,0,0,0,114,103,0,0,0,114,105,0,0, + 0,114,124,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,78,0, + 0,0,177,1,0,0,115,34,0,0,0,0,2,10,1,8, + 1,4,1,6,2,8,1,12,1,12,1,6,1,8,2,8, + 1,10,1,2,1,14,1,14,1,12,3,4,2,114,78,0, + 0,0,99,3,0,0,0,0,0,0,0,8,0,0,0,8, + 0,0,0,67,0,0,0,115,56,1,0,0,122,10,124,0, + 106,0,125,3,87,0,110,20,4,0,116,1,107,10,114,30, + 1,0,1,0,1,0,89,0,110,14,88,0,124,3,100,0, + 107,9,114,44,124,3,83,0,124,0,106,2,125,4,124,1, + 100,0,107,8,114,90,122,10,124,0,106,3,125,1,87,0, + 110,20,4,0,116,1,107,10,114,88,1,0,1,0,1,0, + 89,0,110,2,88,0,122,10,124,0,106,4,125,5,87,0, + 110,24,4,0,116,1,107,10,114,124,1,0,1,0,1,0, + 100,0,125,5,89,0,110,2,88,0,124,2,100,0,107,8, + 114,184,124,5,100,0,107,8,114,180,122,10,124,1,106,5, + 125,2,87,0,113,184,4,0,116,1,107,10,114,176,1,0, + 1,0,1,0,100,0,125,2,89,0,113,184,88,0,110,4, + 124,5,125,2,122,10,124,0,106,6,125,6,87,0,110,24, + 4,0,116,1,107,10,114,218,1,0,1,0,1,0,100,0, + 125,6,89,0,110,2,88,0,122,14,116,7,124,0,106,8, + 131,1,125,7,87,0,110,26,4,0,116,1,107,10,144,1, + 114,4,1,0,1,0,1,0,100,0,125,7,89,0,110,2, + 88,0,116,9,124,4,124,1,124,2,100,1,141,3,125,3, + 124,5,100,0,107,8,144,1,114,34,100,2,110,2,100,3, + 124,3,95,10,124,6,124,3,95,11,124,7,124,3,95,12, + 124,3,83,0,41,4,78,41,1,114,103,0,0,0,70,84, + 41,13,114,89,0,0,0,114,90,0,0,0,114,1,0,0, + 0,114,85,0,0,0,114,92,0,0,0,90,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,102,0,0,0,114,107,0,0,0,114,112,0,0,0,114, + 106,0,0,0,41,8,114,83,0,0,0,114,93,0,0,0, + 114,103,0,0,0,114,82,0,0,0,114,15,0,0,0,90, + 8,108,111,99,97,116,105,111,110,114,112,0,0,0,114,106, 0,0,0,114,10,0,0,0,114,10,0,0,0,114,11,0, - 0,0,114,27,0,0,0,143,0,0,0,115,4,0,0,0, - 0,1,6,1,122,27,95,77,111,100,117,108,101,76,111,99, - 107,77,97,110,97,103,101,114,46,95,95,105,110,105,116,95, - 95,99,1,0,0,0,0,0,0,0,1,0,0,0,2,0, - 0,0,67,0,0,0,115,26,0,0,0,116,0,124,0,106, - 1,131,1,124,0,95,2,124,0,106,2,160,3,161,0,1, - 0,100,0,83,0,41,1,78,41,4,218,16,95,103,101,116, - 95,109,111,100,117,108,101,95,108,111,99,107,114,43,0,0, - 0,114,44,0,0,0,114,34,0,0,0,41,1,114,26,0, - 0,0,114,10,0,0,0,114,10,0,0,0,114,11,0,0, - 0,218,9,95,95,101,110,116,101,114,95,95,147,0,0,0, - 115,4,0,0,0,0,1,12,1,122,28,95,77,111,100,117, - 108,101,76,111,99,107,77,97,110,97,103,101,114,46,95,95, - 101,110,116,101,114,95,95,99,1,0,0,0,0,0,0,0, - 3,0,0,0,2,0,0,0,79,0,0,0,115,14,0,0, - 0,124,0,106,0,160,1,161,0,1,0,100,0,83,0,41, - 1,78,41,2,114,44,0,0,0,114,35,0,0,0,41,3, - 114,26,0,0,0,218,4,97,114,103,115,90,6,107,119,97, - 114,103,115,114,10,0,0,0,114,10,0,0,0,114,11,0, - 0,0,218,8,95,95,101,120,105,116,95,95,151,0,0,0, - 115,2,0,0,0,0,1,122,27,95,77,111,100,117,108,101, - 76,111,99,107,77,97,110,97,103,101,114,46,95,95,101,120, - 105,116,95,95,78,41,6,114,1,0,0,0,114,0,0,0, - 0,114,2,0,0,0,114,27,0,0,0,114,46,0,0,0, - 114,48,0,0,0,114,10,0,0,0,114,10,0,0,0,114, - 10,0,0,0,114,11,0,0,0,114,42,0,0,0,141,0, - 0,0,115,6,0,0,0,8,2,8,4,8,4,114,42,0, - 0,0,99,1,0,0,0,0,0,0,0,3,0,0,0,8, - 0,0,0,67,0,0,0,115,130,0,0,0,116,0,160,1, - 161,0,1,0,122,106,122,14,116,2,124,0,25,0,131,0, - 125,1,87,0,110,24,4,0,116,3,107,10,114,48,1,0, - 1,0,1,0,100,1,125,1,89,0,110,2,88,0,124,1, - 100,1,107,8,114,112,116,4,100,1,107,8,114,76,116,5, - 124,0,131,1,125,1,110,8,116,6,124,0,131,1,125,1, - 124,0,102,1,100,2,100,3,132,1,125,2,116,7,160,8, - 124,1,124,2,161,2,116,2,124,0,60,0,87,0,53,0, - 116,0,160,9,161,0,1,0,88,0,124,1,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,2,0,0,0,8,0,0,0,83, - 0,0,0,115,48,0,0,0,116,0,160,1,161,0,1,0, - 122,24,116,2,160,3,124,1,161,1,124,0,107,8,114,30, - 116,2,124,1,61,0,87,0,53,0,116,0,160,4,161,0, - 1,0,88,0,100,0,83,0,41,1,78,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,30,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,15,0,0,0,114, - 10,0,0,0,114,10,0,0,0,114,11,0,0,0,218,2, - 99,98,176,0,0,0,115,10,0,0,0,0,1,8,1,2, - 4,14,1,10,2,122,28,95,103,101,116,95,109,111,100,117, - 108,101,95,108,111,99,107,46,60,108,111,99,97,108,115,62, - 46,99,98,41,10,114,49,0,0,0,114,50,0,0,0,114, - 51,0,0,0,218,8,75,101,121,69,114,114,111,114,114,20, - 0,0,0,114,41,0,0,0,114,18,0,0,0,218,8,95, - 119,101,97,107,114,101,102,114,53,0,0,0,114,52,0,0, - 0,41,3,114,15,0,0,0,114,21,0,0,0,114,54,0, - 0,0,114,10,0,0,0,114,10,0,0,0,114,11,0,0, - 0,114,45,0,0,0,157,0,0,0,115,28,0,0,0,0, - 6,8,1,2,1,2,1,14,1,14,1,10,2,8,1,8, - 1,10,2,8,2,12,11,20,2,10,2,114,45,0,0,0, - 99,1,0,0,0,0,0,0,0,2,0,0,0,8,0,0, - 0,67,0,0,0,115,54,0,0,0,116,0,124,0,131,1, - 125,1,122,12,124,1,160,1,161,0,1,0,87,0,110,20, - 4,0,116,2,107,10,114,40,1,0,1,0,1,0,89,0, - 110,10,88,0,124,1,160,3,161,0,1,0,100,1,83,0, - 41,2,122,189,65,99,113,117,105,114,101,115,32,116,104,101, - 110,32,114,101,108,101,97,115,101,115,32,116,104,101,32,109, - 111,100,117,108,101,32,108,111,99,107,32,102,111,114,32,97, - 32,103,105,118,101,110,32,109,111,100,117,108,101,32,110,97, - 109,101,46,10,10,32,32,32,32,84,104,105,115,32,105,115, - 32,117,115,101,100,32,116,111,32,101,110,115,117,114,101,32, - 97,32,109,111,100,117,108,101,32,105,115,32,99,111,109,112, - 108,101,116,101,108,121,32,105,110,105,116,105,97,108,105,122, - 101,100,44,32,105,110,32,116,104,101,10,32,32,32,32,101, - 118,101,110,116,32,105,116,32,105,115,32,98,101,105,110,103, - 32,105,109,112,111,114,116,101,100,32,98,121,32,97,110,111, - 116,104,101,114,32,116,104,114,101,97,100,46,10,32,32,32, - 32,78,41,4,114,45,0,0,0,114,34,0,0,0,114,17, - 0,0,0,114,35,0,0,0,41,2,114,15,0,0,0,114, - 21,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, - 0,0,0,218,19,95,108,111,99,107,95,117,110,108,111,99, - 107,95,109,111,100,117,108,101,194,0,0,0,115,12,0,0, - 0,0,6,8,1,2,1,12,1,14,3,6,2,114,57,0, - 0,0,99,1,0,0,0,0,0,0,0,3,0,0,0,3, - 0,0,0,79,0,0,0,115,10,0,0,0,124,0,124,1, - 124,2,142,1,83,0,41,1,97,46,1,0,0,114,101,109, - 111,118,101,95,105,109,112,111,114,116,108,105,98,95,102,114, - 97,109,101,115,32,105,110,32,105,109,112,111,114,116,46,99, - 32,119,105,108,108,32,97,108,119,97,121,115,32,114,101,109, - 111,118,101,32,115,101,113,117,101,110,99,101,115,10,32,32, - 32,32,111,102,32,105,109,112,111,114,116,108,105,98,32,102, - 114,97,109,101,115,32,116,104,97,116,32,101,110,100,32,119, - 105,116,104,32,97,32,99,97,108,108,32,116,111,32,116,104, - 105,115,32,102,117,110,99,116,105,111,110,10,10,32,32,32, - 32,85,115,101,32,105,116,32,105,110,115,116,101,97,100,32, - 111,102,32,97,32,110,111,114,109,97,108,32,99,97,108,108, - 32,105,110,32,112,108,97,99,101,115,32,119,104,101,114,101, - 32,105,110,99,108,117,100,105,110,103,32,116,104,101,32,105, - 109,112,111,114,116,108,105,98,10,32,32,32,32,102,114,97, - 109,101,115,32,105,110,116,114,111,100,117,99,101,115,32,117, - 110,119,97,110,116,101,100,32,110,111,105,115,101,32,105,110, - 116,111,32,116,104,101,32,116,114,97,99,101,98,97,99,107, - 32,40,101,46,103,46,32,119,104,101,110,32,101,120,101,99, - 117,116,105,110,103,10,32,32,32,32,109,111,100,117,108,101, - 32,99,111,100,101,41,10,32,32,32,32,114,10,0,0,0, - 41,3,218,1,102,114,47,0,0,0,90,4,107,119,100,115, - 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,218, - 25,95,99,97,108,108,95,119,105,116,104,95,102,114,97,109, - 101,115,95,114,101,109,111,118,101,100,211,0,0,0,115,2, - 0,0,0,0,8,114,59,0,0,0,114,33,0,0,0,41, - 1,218,9,118,101,114,98,111,115,105,116,121,99,1,0,0, - 0,1,0,0,0,3,0,0,0,4,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,14,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,38,0,0,0,218,6,115,116,100,101,114,114,41, - 3,218,7,109,101,115,115,97,103,101,114,60,0,0,0,114, - 47,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,68,0,0,0,99,1,0,0,0, - 0,0,0,0,2,0,0,0,3,0,0,0,3,0,0,0, - 115,26,0,0,0,135,0,102,1,100,1,100,2,132,8,125, - 1,116,0,124,1,136,0,131,2,1,0,124,1,83,0,41, - 3,122,49,68,101,99,111,114,97,116,111,114,32,116,111,32, - 118,101,114,105,102,121,32,116,104,101,32,110,97,109,101,100, - 32,109,111,100,117,108,101,32,105,115,32,98,117,105,108,116, - 45,105,110,46,99,2,0,0,0,0,0,0,0,2,0,0, - 0,4,0,0,0,19,0,0,0,115,38,0,0,0,124,1, - 116,0,106,1,107,7,114,28,116,2,100,1,160,3,124,1, - 161,1,124,1,100,2,141,2,130,1,136,0,124,0,124,1, - 131,2,83,0,41,3,78,122,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,41,1,114,15,0,0,0,41,4,114, - 14,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,38,0,0,0,41,2,114,26, - 0,0,0,218,8,102,117,108,108,110,97,109,101,41,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,8,0, - 0,0,0,1,10,1,10,1,8,1,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, - 41,1,114,12,0,0,0,41,2,114,72,0,0,0,114,73, - 0,0,0,114,10,0,0,0,41,1,114,72,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,74,0,0,0,99,1,0,0,0, - 0,0,0,0,2,0,0,0,3,0,0,0,3,0,0,0, - 115,26,0,0,0,135,0,102,1,100,1,100,2,132,8,125, - 1,116,0,124,1,136,0,131,2,1,0,124,1,83,0,41, - 3,122,47,68,101,99,111,114,97,116,111,114,32,116,111,32, - 118,101,114,105,102,121,32,116,104,101,32,110,97,109,101,100, - 32,109,111,100,117,108,101,32,105,115,32,102,114,111,122,101, - 110,46,99,2,0,0,0,0,0,0,0,2,0,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,41,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,41,1,114,15,0,0,0,41,4,114,49,0,0,0, - 218,9,105,115,95,102,114,111,122,101,110,114,70,0,0,0, - 114,38,0,0,0,41,2,114,26,0,0,0,114,71,0,0, - 0,41,1,114,72,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,8,0,0,0,0,1,10,1,10,1,8,1,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,41,1,114,12,0,0,0,41,2,114,72,0,0,0,114, - 76,0,0,0,114,10,0,0,0,41,1,114,72,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,77,0,0,0,99,2,0,0,0, - 0,0,0,0,4,0,0,0,3,0,0,0,67,0,0,0, - 115,62,0,0,0,116,0,124,1,124,0,131,2,125,2,124, - 1,116,1,106,2,107,6,114,50,116,1,106,2,124,1,25, - 0,125,3,116,3,124,2,124,3,131,2,1,0,116,1,106, - 2,124,1,25,0,83,0,116,4,124,2,131,1,83,0,100, - 1,83,0,41,2,122,128,76,111,97,100,32,116,104,101,32, - 115,112,101,99,105,102,105,101,100,32,109,111,100,117,108,101, - 32,105,110,116,111,32,115,121,115,46,109,111,100,117,108,101, - 115,32,97,110,100,32,114,101,116,117,114,110,32,105,116,46, - 10,10,32,32,32,32,84,104,105,115,32,109,101,116,104,111, - 100,32,105,115,32,100,101,112,114,101,99,97,116,101,100,46, - 32,32,85,115,101,32,108,111,97,100,101,114,46,101,120,101, - 99,95,109,111,100,117,108,101,32,105,110,115,116,101,97,100, - 46,10,10,32,32,32,32,78,41,5,218,16,115,112,101,99, - 95,102,114,111,109,95,108,111,97,100,101,114,114,14,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,26,0,0,0,114, - 71,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,84,0,0,0,99,1, - 0,0,0,0,0,0,0,5,0,0,0,8,0,0,0,67, - 0,0,0,115,226,0,0,0,116,0,124,0,100,1,100,0, - 131,3,125,1,116,1,124,1,100,2,131,2,114,56,122,12, - 124,1,160,2,124,0,161,1,87,0,83,0,4,0,116,3, - 107,10,114,54,1,0,1,0,1,0,89,0,110,2,88,0, - 122,10,124,0,106,4,125,2,87,0,110,20,4,0,116,5, - 107,10,114,86,1,0,1,0,1,0,89,0,110,18,88,0, - 124,2,100,0,107,9,114,104,116,6,124,2,131,1,83,0, - 122,10,124,0,106,7,125,3,87,0,110,24,4,0,116,5, - 107,10,114,138,1,0,1,0,1,0,100,3,125,3,89,0, - 110,2,88,0,122,10,124,0,106,8,125,4,87,0,110,58, - 4,0,116,5,107,10,114,208,1,0,1,0,1,0,124,1, - 100,0,107,8,114,188,100,4,160,9,124,3,161,1,6,0, - 89,0,83,0,100,5,160,9,124,3,124,1,161,2,6,0, - 89,0,83,0,89,0,110,14,88,0,100,6,160,9,124,3, - 124,4,161,2,83,0,100,0,83,0,41,7,78,218,10,95, - 95,108,111,97,100,101,114,95,95,218,11,109,111,100,117,108, - 101,95,114,101,112,114,250,1,63,122,13,60,109,111,100,117, + 0,0,218,17,95,115,112,101,99,95,102,114,111,109,95,109, + 111,100,117,108,101,203,1,0,0,115,72,0,0,0,0,2, + 2,1,10,1,14,1,6,2,8,1,4,2,6,1,8,1, + 2,1,10,1,14,2,6,1,2,1,10,1,14,1,10,1, + 8,1,8,1,2,1,10,1,14,1,12,2,4,1,2,1, + 10,1,14,1,10,1,2,1,14,1,16,1,10,2,14,1, + 20,1,6,1,6,1,114,128,0,0,0,70,41,1,218,8, + 111,118,101,114,114,105,100,101,99,2,0,0,0,1,0,0, + 0,5,0,0,0,8,0,0,0,67,0,0,0,115,226,1, + 0,0,124,2,115,20,116,0,124,1,100,1,100,0,131,3, + 100,0,107,8,114,54,122,12,124,0,106,1,124,1,95,2, + 87,0,110,20,4,0,116,3,107,10,114,52,1,0,1,0, + 1,0,89,0,110,2,88,0,124,2,115,74,116,0,124,1, + 100,2,100,0,131,3,100,0,107,8,114,178,124,0,106,4, + 125,3,124,3,100,0,107,8,114,146,124,0,106,5,100,0, + 107,9,114,146,116,6,100,0,107,8,114,110,116,7,130,1, + 116,6,106,8,125,4,124,4,160,9,124,4,161,1,125,3, + 124,0,106,5,124,3,95,10,124,3,124,0,95,4,100,0, + 124,1,95,11,122,10,124,3,124,1,95,12,87,0,110,20, + 4,0,116,3,107,10,114,176,1,0,1,0,1,0,89,0, + 110,2,88,0,124,2,115,198,116,0,124,1,100,3,100,0, + 131,3,100,0,107,8,114,232,122,12,124,0,106,13,124,1, + 95,14,87,0,110,20,4,0,116,3,107,10,114,230,1,0, + 1,0,1,0,89,0,110,2,88,0,122,10,124,0,124,1, + 95,15,87,0,110,22,4,0,116,3,107,10,144,1,114,8, + 1,0,1,0,1,0,89,0,110,2,88,0,124,2,144,1, + 115,34,116,0,124,1,100,4,100,0,131,3,100,0,107,8, + 144,1,114,82,124,0,106,5,100,0,107,9,144,1,114,82, + 122,12,124,0,106,5,124,1,95,16,87,0,110,22,4,0, + 116,3,107,10,144,1,114,80,1,0,1,0,1,0,89,0, + 110,2,88,0,124,0,106,17,144,1,114,222,124,2,144,1, + 115,114,116,0,124,1,100,5,100,0,131,3,100,0,107,8, + 144,1,114,150,122,12,124,0,106,18,124,1,95,11,87,0, + 110,22,4,0,116,3,107,10,144,1,114,148,1,0,1,0, + 1,0,89,0,110,2,88,0,124,2,144,1,115,174,116,0, + 124,1,100,6,100,0,131,3,100,0,107,8,144,1,114,222, + 124,0,106,19,100,0,107,9,144,1,114,222,122,12,124,0, + 106,19,124,1,95,20,87,0,110,22,4,0,116,3,107,10, + 144,1,114,220,1,0,1,0,1,0,89,0,110,2,88,0, + 124,1,83,0,41,7,78,114,1,0,0,0,114,85,0,0, + 0,218,11,95,95,112,97,99,107,97,103,101,95,95,114,127, + 0,0,0,114,92,0,0,0,114,125,0,0,0,41,21,114, + 6,0,0,0,114,15,0,0,0,114,1,0,0,0,114,90, + 0,0,0,114,93,0,0,0,114,106,0,0,0,114,115,0, + 0,0,114,116,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,92,0,0,0,114,85, + 0,0,0,114,119,0,0,0,114,130,0,0,0,114,89,0, + 0,0,114,127,0,0,0,114,113,0,0,0,114,103,0,0, + 0,114,112,0,0,0,114,125,0,0,0,41,5,114,82,0, + 0,0,114,83,0,0,0,114,129,0,0,0,114,93,0,0, + 0,114,131,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,248,1,0,0,115,96,0, + 0,0,0,4,20,1,2,1,12,1,14,1,6,2,20,1, + 6,1,8,2,10,1,8,1,4,1,6,2,10,1,8,1, + 6,11,6,1,2,1,10,1,14,1,6,2,20,1,2,1, + 12,1,14,1,6,2,2,1,10,1,16,1,6,2,24,1, + 12,1,2,1,12,1,16,1,6,2,8,1,24,1,2,1, + 12,1,16,1,6,2,24,1,12,1,2,1,12,1,16,1, + 6,1,114,133,0,0,0,99,1,0,0,0,0,0,0,0, + 2,0,0,0,3,0,0,0,67,0,0,0,115,82,0,0, + 0,100,1,125,1,116,0,124,0,106,1,100,2,131,2,114, + 30,124,0,106,1,160,2,124,0,161,1,125,1,110,20,116, + 0,124,0,106,1,100,3,131,2,114,50,116,3,100,4,131, + 1,130,1,124,1,100,1,107,8,114,68,116,4,124,0,106, + 5,131,1,125,1,116,6,124,0,124,1,131,2,1,0,124, + 1,83,0,41,5,122,43,67,114,101,97,116,101,32,97,32, + 109,111,100,117,108,101,32,98,97,115,101,100,32,111,110,32, + 116,104,101,32,112,114,111,118,105,100,101,100,32,115,112,101, + 99,46,78,218,13,99,114,101,97,116,101,95,109,111,100,117, + 108,101,218,11,101,120,101,99,95,109,111,100,117,108,101,122, + 66,108,111,97,100,101,114,115,32,116,104,97,116,32,100,101, + 102,105,110,101,32,101,120,101,99,95,109,111,100,117,108,101, + 40,41,32,109,117,115,116,32,97,108,115,111,32,100,101,102, + 105,110,101,32,99,114,101,97,116,101,95,109,111,100,117,108, + 101,40,41,41,7,114,4,0,0,0,114,93,0,0,0,114, + 134,0,0,0,114,70,0,0,0,114,16,0,0,0,114,15, + 0,0,0,114,133,0,0,0,41,2,114,82,0,0,0,114, + 83,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,64,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,136,0,0,0,99,1,0,0,0,0,0,0,0,2,0, + 0,0,4,0,0,0,67,0,0,0,115,106,0,0,0,124, + 0,106,0,100,1,107,8,114,14,100,2,110,4,124,0,106, + 0,125,1,124,0,106,1,100,1,107,8,114,66,124,0,106, + 2,100,1,107,8,114,50,100,3,160,3,124,1,161,1,83, + 0,100,4,160,3,124,1,124,0,106,2,161,2,83,0,110, + 36,124,0,106,4,114,86,100,5,160,3,124,1,124,0,106, + 1,161,2,83,0,100,6,160,3,124,0,106,0,124,0,106, + 1,161,2,83,0,100,1,83,0,41,7,122,38,82,101,116, + 117,114,110,32,116,104,101,32,114,101,112,114,32,116,111,32, + 117,115,101,32,102,111,114,32,116,104,101,32,109,111,100,117, + 108,101,46,78,114,87,0,0,0,122,13,60,109,111,100,117, 108,101,32,123,33,114,125,62,122,20,60,109,111,100,117,108, 101,32,123,33,114,125,32,40,123,33,114,125,41,62,122,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,86,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,38,0,0,0,41,5,114,83,0,0,0, - 218,6,108,111,97,100,101,114,114,82,0,0,0,114,15,0, - 0,0,218,8,102,105,108,101,110,97,109,101,114,10,0,0, - 0,114,10,0,0,0,114,11,0,0,0,218,12,95,109,111, - 100,117,108,101,95,114,101,112,114,13,1,0,0,115,46,0, - 0,0,0,2,12,1,10,4,2,1,12,1,14,1,6,1, - 2,1,10,1,14,1,6,2,8,1,8,4,2,1,10,1, - 14,1,10,1,2,1,10,1,14,1,8,1,14,2,22,2, - 114,95,0,0,0,99,0,0,0,0,0,0,0,0,0,0, - 0,0,2,0,0,0,64,0,0,0,115,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,17,95,105,110,115,116,97,108,108,101, - 100,95,115,97,102,101,108,121,99,2,0,0,0,0,0,0, - 0,2,0,0,0,2,0,0,0,67,0,0,0,115,18,0, - 0,0,124,1,124,0,95,0,124,1,106,1,124,0,95,2, - 100,0,83,0,41,1,78,41,3,218,7,95,109,111,100,117, - 108,101,114,89,0,0,0,218,5,95,115,112,101,99,41,2, - 114,26,0,0,0,114,83,0,0,0,114,10,0,0,0,114, - 10,0,0,0,114,11,0,0,0,114,27,0,0,0,51,1, - 0,0,115,4,0,0,0,0,1,6,1,122,26,95,105,110, - 115,116,97,108,108,101,100,95,115,97,102,101,108,121,46,95, - 95,105,110,105,116,95,95,99,1,0,0,0,0,0,0,0, - 1,0,0,0,3,0,0,0,67,0,0,0,115,28,0,0, - 0,100,1,124,0,106,0,95,1,124,0,106,2,116,3,106, - 4,124,0,106,0,106,5,60,0,100,0,83,0,41,2,78, - 84,41,6,114,98,0,0,0,218,13,95,105,110,105,116,105, - 97,108,105,122,105,110,103,114,97,0,0,0,114,14,0,0, - 0,114,79,0,0,0,114,15,0,0,0,41,1,114,26,0, + 109,32,123,33,114,125,62,122,18,60,109,111,100,117,108,101, + 32,123,33,114,125,32,40,123,125,41,62,41,5,114,15,0, + 0,0,114,103,0,0,0,114,93,0,0,0,114,38,0,0, + 0,114,113,0,0,0,41,2,114,82,0,0,0,114,15,0, 0,0,114,10,0,0,0,114,10,0,0,0,114,11,0,0, - 0,114,46,0,0,0,55,1,0,0,115,4,0,0,0,0, - 4,8,1,122,27,95,105,110,115,116,97,108,108,101,100,95, - 115,97,102,101,108,121,46,95,95,101,110,116,101,114,95,95, - 99,1,0,0,0,0,0,0,0,3,0,0,0,8,0,0, - 0,71,0,0,0,115,98,0,0,0,122,82,124,0,106,0, - 125,2,116,1,100,1,100,2,132,0,124,1,68,0,131,1, - 131,1,114,64,122,14,116,2,106,3,124,2,106,4,61,0, - 87,0,113,80,4,0,116,5,107,10,114,60,1,0,1,0, - 1,0,89,0,113,80,88,0,110,16,116,6,100,3,124,2, - 106,4,124,2,106,7,131,3,1,0,87,0,53,0,100,4, - 124,0,106,0,95,8,88,0,100,0,83,0,41,5,78,99, - 1,0,0,0,0,0,0,0,2,0,0,0,3,0,0,0, - 115,0,0,0,115,22,0,0,0,124,0,93,14,125,1,124, - 1,100,0,107,9,86,0,1,0,113,2,100,0,83,0,41, - 1,78,114,10,0,0,0,41,2,90,2,46,48,90,3,97, - 114,103,114,10,0,0,0,114,10,0,0,0,114,11,0,0, - 0,218,9,60,103,101,110,101,120,112,114,62,65,1,0,0, - 115,2,0,0,0,4,0,122,45,95,105,110,115,116,97,108, - 108,101,100,95,115,97,102,101,108,121,46,95,95,101,120,105, - 116,95,95,46,60,108,111,99,97,108,115,62,46,60,103,101, - 110,101,120,112,114,62,122,18,105,109,112,111,114,116,32,123, - 33,114,125,32,35,32,123,33,114,125,70,41,9,114,98,0, - 0,0,218,3,97,110,121,114,14,0,0,0,114,79,0,0, - 0,114,15,0,0,0,114,55,0,0,0,114,68,0,0,0, - 114,93,0,0,0,114,99,0,0,0,41,3,114,26,0,0, - 0,114,47,0,0,0,114,82,0,0,0,114,10,0,0,0, - 114,10,0,0,0,114,11,0,0,0,114,48,0,0,0,62, - 1,0,0,115,18,0,0,0,0,1,2,1,6,1,18,1, - 2,1,14,1,14,1,8,2,20,2,122,26,95,105,110,115, - 116,97,108,108,101,100,95,115,97,102,101,108,121,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,27,0,0,0,114,46,0, - 0,0,114,48,0,0,0,114,10,0,0,0,114,10,0,0, - 0,114,10,0,0,0,114,11,0,0,0,114,96,0,0,0, - 49,1,0,0,115,6,0,0,0,8,2,8,4,8,7,114, - 96,0,0,0,99,0,0,0,0,0,0,0,0,0,0,0, - 0,4,0,0,0,64,0,0,0,115,114,0,0,0,101,0, - 90,1,100,0,90,2,100,1,90,3,100,2,100,2,100,2, - 100,3,156,3,100,4,100,5,132,2,90,4,100,6,100,7, - 132,0,90,5,100,8,100,9,132,0,90,6,101,7,100,10, - 100,11,132,0,131,1,90,8,101,8,106,9,100,12,100,11, - 132,0,131,1,90,8,101,7,100,13,100,14,132,0,131,1, - 90,10,101,7,100,15,100,16,132,0,131,1,90,11,101,11, - 106,9,100,17,100,16,132,0,131,1,90,11,100,2,83,0, - 41,18,218,10,77,111,100,117,108,101,83,112,101,99,97,208, - 5,0,0,84,104,101,32,115,112,101,99,105,102,105,99,97, - 116,105,111,110,32,102,111,114,32,97,32,109,111,100,117,108, - 101,44,32,117,115,101,100,32,102,111,114,32,108,111,97,100, - 105,110,103,46,10,10,32,32,32,32,65,32,109,111,100,117, - 108,101,39,115,32,115,112,101,99,32,105,115,32,116,104,101, - 32,115,111,117,114,99,101,32,102,111,114,32,105,110,102,111, - 114,109,97,116,105,111,110,32,97,98,111,117,116,32,116,104, - 101,32,109,111,100,117,108,101,46,32,32,70,111,114,10,32, - 32,32,32,100,97,116,97,32,97,115,115,111,99,105,97,116, - 101,100,32,119,105,116,104,32,116,104,101,32,109,111,100,117, - 108,101,44,32,105,110,99,108,117,100,105,110,103,32,115,111, - 117,114,99,101,44,32,117,115,101,32,116,104,101,32,115,112, - 101,99,39,115,10,32,32,32,32,108,111,97,100,101,114,46, - 10,10,32,32,32,32,96,110,97,109,101,96,32,105,115,32, - 116,104,101,32,97,98,115,111,108,117,116,101,32,110,97,109, - 101,32,111,102,32,116,104,101,32,109,111,100,117,108,101,46, - 32,32,96,108,111,97,100,101,114,96,32,105,115,32,116,104, - 101,32,108,111,97,100,101,114,10,32,32,32,32,116,111,32, - 117,115,101,32,119,104,101,110,32,108,111,97,100,105,110,103, - 32,116,104,101,32,109,111,100,117,108,101,46,32,32,96,112, - 97,114,101,110,116,96,32,105,115,32,116,104,101,32,110,97, - 109,101,32,111,102,32,116,104,101,10,32,32,32,32,112,97, - 99,107,97,103,101,32,116,104,101,32,109,111,100,117,108,101, - 32,105,115,32,105,110,46,32,32,84,104,101,32,112,97,114, - 101,110,116,32,105,115,32,100,101,114,105,118,101,100,32,102, - 114,111,109,32,116,104,101,32,110,97,109,101,46,10,10,32, - 32,32,32,96,105,115,95,112,97,99,107,97,103,101,96,32, - 100,101,116,101,114,109,105,110,101,115,32,105,102,32,116,104, - 101,32,109,111,100,117,108,101,32,105,115,32,99,111,110,115, - 105,100,101,114,101,100,32,97,32,112,97,99,107,97,103,101, - 32,111,114,10,32,32,32,32,110,111,116,46,32,32,79,110, - 32,109,111,100,117,108,101,115,32,116,104,105,115,32,105,115, - 32,114,101,102,108,101,99,116,101,100,32,98,121,32,116,104, - 101,32,96,95,95,112,97,116,104,95,95,96,32,97,116,116, - 114,105,98,117,116,101,46,10,10,32,32,32,32,96,111,114, - 105,103,105,110,96,32,105,115,32,116,104,101,32,115,112,101, - 99,105,102,105,99,32,108,111,99,97,116,105,111,110,32,117, - 115,101,100,32,98,121,32,116,104,101,32,108,111,97,100,101, - 114,32,102,114,111,109,32,119,104,105,99,104,32,116,111,10, - 32,32,32,32,108,111,97,100,32,116,104,101,32,109,111,100, - 117,108,101,44,32,105,102,32,116,104,97,116,32,105,110,102, - 111,114,109,97,116,105,111,110,32,105,115,32,97,118,97,105, - 108,97,98,108,101,46,32,32,87,104,101,110,32,102,105,108, - 101,110,97,109,101,32,105,115,10,32,32,32,32,115,101,116, - 44,32,111,114,105,103,105,110,32,119,105,108,108,32,109,97, - 116,99,104,46,10,10,32,32,32,32,96,104,97,115,95,108, - 111,99,97,116,105,111,110,96,32,105,110,100,105,99,97,116, - 101,115,32,116,104,97,116,32,97,32,115,112,101,99,39,115, - 32,34,111,114,105,103,105,110,34,32,114,101,102,108,101,99, - 116,115,32,97,32,108,111,99,97,116,105,111,110,46,10,32, - 32,32,32,87,104,101,110,32,116,104,105,115,32,105,115,32, - 84,114,117,101,44,32,96,95,95,102,105,108,101,95,95,96, - 32,97,116,116,114,105,98,117,116,101,32,111,102,32,116,104, - 101,32,109,111,100,117,108,101,32,105,115,32,115,101,116,46, - 10,10,32,32,32,32,96,99,97,99,104,101,100,96,32,105, - 115,32,116,104,101,32,108,111,99,97,116,105,111,110,32,111, - 102,32,116,104,101,32,99,97,99,104,101,100,32,98,121,116, - 101,99,111,100,101,32,102,105,108,101,44,32,105,102,32,97, - 110,121,46,32,32,73,116,10,32,32,32,32,99,111,114,114, - 101,115,112,111,110,100,115,32,116,111,32,116,104,101,32,96, - 95,95,99,97,99,104,101,100,95,95,96,32,97,116,116,114, - 105,98,117,116,101,46,10,10,32,32,32,32,96,115,117,98, - 109,111,100,117,108,101,95,115,101,97,114,99,104,95,108,111, - 99,97,116,105,111,110,115,96,32,105,115,32,116,104,101,32, - 115,101,113,117,101,110,99,101,32,111,102,32,112,97,116,104, - 32,101,110,116,114,105,101,115,32,116,111,10,32,32,32,32, - 115,101,97,114,99,104,32,119,104,101,110,32,105,109,112,111, - 114,116,105,110,103,32,115,117,98,109,111,100,117,108,101,115, - 46,32,32,73,102,32,115,101,116,44,32,105,115,95,112,97, - 99,107,97,103,101,32,115,104,111,117,108,100,32,98,101,10, - 32,32,32,32,84,114,117,101,45,45,97,110,100,32,70,97, - 108,115,101,32,111,116,104,101,114,119,105,115,101,46,10,10, - 32,32,32,32,80,97,99,107,97,103,101,115,32,97,114,101, - 32,115,105,109,112,108,121,32,109,111,100,117,108,101,115,32, - 116,104,97,116,32,40,109,97,121,41,32,104,97,118,101,32, - 115,117,98,109,111,100,117,108,101,115,46,32,32,73,102,32, - 97,32,115,112,101,99,10,32,32,32,32,104,97,115,32,97, - 32,110,111,110,45,78,111,110,101,32,118,97,108,117,101,32, - 105,110,32,96,115,117,98,109,111,100,117,108,101,95,115,101, - 97,114,99,104,95,108,111,99,97,116,105,111,110,115,96,44, - 32,116,104,101,32,105,109,112,111,114,116,10,32,32,32,32, - 115,121,115,116,101,109,32,119,105,108,108,32,99,111,110,115, - 105,100,101,114,32,109,111,100,117,108,101,115,32,108,111,97, - 100,101,100,32,102,114,111,109,32,116,104,101,32,115,112,101, - 99,32,97,115,32,112,97,99,107,97,103,101,115,46,10,10, - 32,32,32,32,79,110,108,121,32,102,105,110,100,101,114,115, - 32,40,115,101,101,32,105,109,112,111,114,116,108,105,98,46, - 97,98,99,46,77,101,116,97,80,97,116,104,70,105,110,100, - 101,114,32,97,110,100,10,32,32,32,32,105,109,112,111,114, - 116,108,105,98,46,97,98,99,46,80,97,116,104,69,110,116, - 114,121,70,105,110,100,101,114,41,32,115,104,111,117,108,100, - 32,109,111,100,105,102,121,32,77,111,100,117,108,101,83,112, - 101,99,32,105,110,115,116,97,110,99,101,115,46,10,10,32, - 32,32,32,78,41,3,218,6,111,114,105,103,105,110,218,12, - 108,111,97,100,101,114,95,115,116,97,116,101,218,10,105,115, - 95,112,97,99,107,97,103,101,99,3,0,0,0,3,0,0, - 0,6,0,0,0,2,0,0,0,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,15, - 0,0,0,114,93,0,0,0,114,103,0,0,0,114,104,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,26,0,0,0,114,15,0, - 0,0,114,93,0,0,0,114,103,0,0,0,114,104,0,0, - 0,114,105,0,0,0,114,10,0,0,0,114,10,0,0,0, - 114,11,0,0,0,114,27,0,0,0,113,1,0,0,115,14, - 0,0,0,0,2,6,1,6,1,6,1,6,1,14,3,6, - 1,122,19,77,111,100,117,108,101,83,112,101,99,46,95,95, - 105,110,105,116,95,95,99,1,0,0,0,0,0,0,0,2, - 0,0,0,6,0,0,0,67,0,0,0,115,102,0,0,0, - 100,1,160,0,124,0,106,1,161,1,100,2,160,0,124,0, - 106,2,161,1,103,2,125,1,124,0,106,3,100,0,107,9, - 114,52,124,1,160,4,100,3,160,0,124,0,106,3,161,1, - 161,1,1,0,124,0,106,5,100,0,107,9,114,80,124,1, - 160,4,100,4,160,0,124,0,106,5,161,1,161,1,1,0, - 100,5,160,0,124,0,106,6,106,7,100,6,160,8,124,1, - 161,1,161,2,83,0,41,7,78,122,9,110,97,109,101,61, - 123,33,114,125,122,11,108,111,97,100,101,114,61,123,33,114, - 125,122,11,111,114,105,103,105,110,61,123,33,114,125,122,29, - 115,117,98,109,111,100,117,108,101,95,115,101,97,114,99,104, - 95,108,111,99,97,116,105,111,110,115,61,123,125,122,6,123, - 125,40,123,125,41,122,2,44,32,41,9,114,38,0,0,0, - 114,15,0,0,0,114,93,0,0,0,114,103,0,0,0,218, - 6,97,112,112,101,110,100,114,106,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,26,0,0,0,114,47,0,0,0,114,10, - 0,0,0,114,10,0,0,0,114,11,0,0,0,114,40,0, - 0,0,125,1,0,0,115,16,0,0,0,0,1,10,1,14, - 1,10,1,18,1,10,1,8,1,10,1,122,19,77,111,100, - 117,108,101,83,112,101,99,46,95,95,114,101,112,114,95,95, - 99,2,0,0,0,0,0,0,0,3,0,0,0,8,0,0, - 0,67,0,0,0,115,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,107,10, - 114,100,1,0,1,0,1,0,89,0,100,1,83,0,88,0, - 100,0,83,0,41,2,78,70,41,7,114,106,0,0,0,114, - 15,0,0,0,114,93,0,0,0,114,103,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,90,0,0,0,41,3,114,26,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,135,1,0,0,115,20,0,0,0,0,1,6, - 1,2,1,12,1,12,1,12,1,10,1,12,1,14,1,14, - 1,122,17,77,111,100,117,108,101,83,112,101,99,46,95,95, - 101,113,95,95,99,1,0,0,0,0,0,0,0,1,0,0, - 0,3,0,0,0,67,0,0,0,115,58,0,0,0,124,0, - 106,0,100,0,107,8,114,52,124,0,106,1,100,0,107,9, - 114,52,124,0,106,2,114,52,116,3,100,0,107,8,114,38, - 116,4,130,1,116,3,160,5,124,0,106,1,161,1,124,0, - 95,0,124,0,106,0,83,0,41,1,78,41,6,114,108,0, - 0,0,114,103,0,0,0,114,107,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,41,1,114,26,0,0,0,114,10,0,0,0,114, - 10,0,0,0,114,11,0,0,0,114,112,0,0,0,147,1, - 0,0,115,12,0,0,0,0,2,10,1,16,1,8,1,4, - 1,14,1,122,17,77,111,100,117,108,101,83,112,101,99,46, - 99,97,99,104,101,100,99,2,0,0,0,0,0,0,0,2, - 0,0,0,2,0,0,0,67,0,0,0,115,10,0,0,0, - 124,1,124,0,95,0,100,0,83,0,41,1,78,41,1,114, - 108,0,0,0,41,2,114,26,0,0,0,114,112,0,0,0, + 0,114,91,0,0,0,81,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, + 91,0,0,0,99,2,0,0,0,0,0,0,0,4,0,0, + 0,10,0,0,0,67,0,0,0,115,190,0,0,0,124,0, + 106,0,125,2,116,1,124,2,131,1,143,160,1,0,116,2, + 106,3,160,4,124,2,161,1,124,1,107,9,114,54,100,1, + 160,5,124,2,161,1,125,3,116,6,124,3,124,2,100,2, + 141,2,130,1,124,0,106,7,100,3,107,8,114,118,124,0, + 106,8,100,3,107,8,114,88,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,124,1,87,0,2,0,53,0,81,0,82,0, + 163,0,83,0,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,158,124,0, + 106,7,160,11,124,2,161,1,1,0,110,12,124,0,106,7, + 160,12,124,1,161,1,1,0,87,0,53,0,81,0,82,0, + 88,0,116,2,106,3,124,2,25,0,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,41,1,114,15,0,0,0,78,122,14, + 109,105,115,115,105,110,103,32,108,111,97,100,101,114,84,41, + 1,114,129,0,0,0,114,135,0,0,0,41,13,114,15,0, + 0,0,114,42,0,0,0,114,14,0,0,0,114,79,0,0, + 0,114,30,0,0,0,114,38,0,0,0,114,70,0,0,0, + 114,93,0,0,0,114,106,0,0,0,114,133,0,0,0,114, + 4,0,0,0,218,11,108,111,97,100,95,109,111,100,117,108, + 101,114,135,0,0,0,41,4,114,82,0,0,0,114,83,0, + 0,0,114,15,0,0,0,218,3,109,115,103,114,10,0,0, + 0,114,10,0,0,0,114,11,0,0,0,114,80,0,0,0, + 98,2,0,0,115,30,0,0,0,0,2,6,1,10,1,16, + 1,10,1,12,1,10,1,10,1,14,2,14,1,16,1,14, + 1,12,4,14,2,22,1,114,80,0,0,0,99,1,0,0, + 0,0,0,0,0,2,0,0,0,8,0,0,0,67,0,0, + 0,115,206,0,0,0,124,0,106,0,160,1,124,0,106,2, + 161,1,1,0,116,3,106,4,124,0,106,2,25,0,125,1, + 116,5,124,1,100,1,100,0,131,3,100,0,107,8,114,76, + 122,12,124,0,106,0,124,1,95,6,87,0,110,20,4,0, + 116,7,107,10,114,74,1,0,1,0,1,0,89,0,110,2, + 88,0,116,5,124,1,100,2,100,0,131,3,100,0,107,8, + 114,154,122,40,124,1,106,8,124,1,95,9,116,10,124,1, + 100,3,131,2,115,130,124,0,106,2,160,11,100,4,161,1, + 100,5,25,0,124,1,95,9,87,0,110,20,4,0,116,7, + 107,10,114,152,1,0,1,0,1,0,89,0,110,2,88,0, + 116,5,124,1,100,6,100,0,131,3,100,0,107,8,114,202, + 122,10,124,0,124,1,95,12,87,0,110,20,4,0,116,7, + 107,10,114,200,1,0,1,0,1,0,89,0,110,2,88,0, + 124,1,83,0,41,7,78,114,85,0,0,0,114,130,0,0, + 0,114,127,0,0,0,114,117,0,0,0,114,19,0,0,0, + 114,89,0,0,0,41,13,114,93,0,0,0,114,137,0,0, + 0,114,15,0,0,0,114,14,0,0,0,114,79,0,0,0, + 114,6,0,0,0,114,85,0,0,0,114,90,0,0,0,114, + 1,0,0,0,114,130,0,0,0,114,4,0,0,0,114,118, + 0,0,0,114,89,0,0,0,41,2,114,82,0,0,0,114, + 83,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,122,2, + 0,0,115,40,0,0,0,0,4,14,2,12,1,16,1,2, + 1,12,1,14,1,6,1,16,1,2,4,8,1,10,1,22, + 1,14,1,6,1,16,1,2,1,10,1,14,1,6,1,114, + 139,0,0,0,99,1,0,0,0,0,0,0,0,2,0,0, + 0,9,0,0,0,67,0,0,0,115,118,0,0,0,124,0, + 106,0,100,0,107,9,114,30,116,1,124,0,106,0,100,1, + 131,2,115,30,116,2,124,0,131,1,83,0,116,3,124,0, + 131,1,125,1,116,4,124,1,131,1,143,54,1,0,124,0, + 106,0,100,0,107,8,114,84,124,0,106,5,100,0,107,8, + 114,96,116,6,100,2,124,0,106,7,100,3,141,2,130,1, + 110,12,124,0,106,0,160,8,124,1,161,1,1,0,87,0, + 53,0,81,0,82,0,88,0,116,9,106,10,124,0,106,7, + 25,0,83,0,41,4,78,114,135,0,0,0,122,14,109,105, + 115,115,105,110,103,32,108,111,97,100,101,114,41,1,114,15, + 0,0,0,41,11,114,93,0,0,0,114,4,0,0,0,114, + 139,0,0,0,114,136,0,0,0,114,96,0,0,0,114,106, + 0,0,0,114,70,0,0,0,114,15,0,0,0,114,135,0, + 0,0,114,14,0,0,0,114,79,0,0,0,41,2,114,82, + 0,0,0,114,83,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,151,2,0,0,115,20,0,0,0, + 0,2,10,2,12,1,8,2,8,1,10,1,10,1,10,1, + 16,3,22,5,114,140,0,0,0,99,1,0,0,0,0,0, + 0,0,1,0,0,0,10,0,0,0,67,0,0,0,115,42, + 0,0,0,116,0,124,0,106,1,131,1,143,22,1,0,116, + 2,124,0,131,1,87,0,2,0,53,0,81,0,82,0,163, + 0,83,0,81,0,82,0,88,0,100,1,83,0,41,2,122, + 191,82,101,116,117,114,110,32,97,32,110,101,119,32,109,111, + 100,117,108,101,32,111,98,106,101,99,116,44,32,108,111,97, + 100,101,100,32,98,121,32,116,104,101,32,115,112,101,99,39, + 115,32,108,111,97,100,101,114,46,10,10,32,32,32,32,84, + 104,101,32,109,111,100,117,108,101,32,105,115,32,110,111,116, + 32,97,100,100,101,100,32,116,111,32,105,116,115,32,112,97, + 114,101,110,116,46,10,10,32,32,32,32,73,102,32,97,32, + 109,111,100,117,108,101,32,105,115,32,97,108,114,101,97,100, + 121,32,105,110,32,115,121,115,46,109,111,100,117,108,101,115, + 44,32,116,104,97,116,32,101,120,105,115,116,105,110,103,32, + 109,111,100,117,108,101,32,103,101,116,115,10,32,32,32,32, + 99,108,111,98,98,101,114,101,100,46,10,10,32,32,32,32, + 78,41,3,114,42,0,0,0,114,15,0,0,0,114,140,0, + 0,0,41,1,114,82,0,0,0,114,10,0,0,0,114,10, + 0,0,0,114,11,0,0,0,114,81,0,0,0,174,2,0, + 0,115,4,0,0,0,0,9,12,1,114,81,0,0,0,99, + 0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0, + 64,0,0,0,115,136,0,0,0,101,0,90,1,100,0,90, + 2,100,1,90,3,101,4,100,2,100,3,132,0,131,1,90, + 5,101,6,100,19,100,5,100,6,132,1,131,1,90,7,101, + 6,100,20,100,7,100,8,132,1,131,1,90,8,101,6,100, + 9,100,10,132,0,131,1,90,9,101,6,100,11,100,12,132, + 0,131,1,90,10,101,6,101,11,100,13,100,14,132,0,131, + 1,131,1,90,12,101,6,101,11,100,15,100,16,132,0,131, + 1,131,1,90,13,101,6,101,11,100,17,100,18,132,0,131, + 1,131,1,90,14,101,6,101,15,131,1,90,16,100,4,83, + 0,41,21,218,15,66,117,105,108,116,105,110,73,109,112,111, + 114,116,101,114,122,144,77,101,116,97,32,112,97,116,104,32, + 105,109,112,111,114,116,32,102,111,114,32,98,117,105,108,116, + 45,105,110,32,109,111,100,117,108,101,115,46,10,10,32,32, + 32,32,65,108,108,32,109,101,116,104,111,100,115,32,97,114, + 101,32,101,105,116,104,101,114,32,99,108,97,115,115,32,111, + 114,32,115,116,97,116,105,99,32,109,101,116,104,111,100,115, + 32,116,111,32,97,118,111,105,100,32,116,104,101,32,110,101, + 101,100,32,116,111,10,32,32,32,32,105,110,115,116,97,110, + 116,105,97,116,101,32,116,104,101,32,99,108,97,115,115,46, + 10,10,32,32,32,32,99,1,0,0,0,0,0,0,0,1, + 0,0,0,3,0,0,0,67,0,0,0,115,12,0,0,0, + 100,1,160,0,124,0,106,1,161,1,83,0,41,2,122,115, + 82,101,116,117,114,110,32,114,101,112,114,32,102,111,114,32, + 116,104,101,32,109,111,100,117,108,101,46,10,10,32,32,32, + 32,32,32,32,32,84,104,101,32,109,101,116,104,111,100,32, + 105,115,32,100,101,112,114,101,99,97,116,101,100,46,32,32, + 84,104,101,32,105,109,112,111,114,116,32,109,97,99,104,105, + 110,101,114,121,32,100,111,101,115,32,116,104,101,32,106,111, + 98,32,105,116,115,101,108,102,46,10,10,32,32,32,32,32, + 32,32,32,122,24,60,109,111,100,117,108,101,32,123,33,114, + 125,32,40,98,117,105,108,116,45,105,110,41,62,41,2,114, + 38,0,0,0,114,1,0,0,0,41,1,114,83,0,0,0, 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,114, - 112,0,0,0,156,1,0,0,115,2,0,0,0,0,2,99, - 1,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0, - 67,0,0,0,115,36,0,0,0,124,0,106,0,100,1,107, - 8,114,26,124,0,106,1,160,2,100,2,161,1,100,3,25, - 0,83,0,124,0,106,1,83,0,100,1,83,0,41,4,122, - 32,84,104,101,32,110,97,109,101,32,111,102,32,116,104,101, - 32,109,111,100,117,108,101,39,115,32,112,97,114,101,110,116, - 46,78,218,1,46,114,19,0,0,0,41,3,114,106,0,0, - 0,114,15,0,0,0,218,10,114,112,97,114,116,105,116,105, - 111,110,41,1,114,26,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, - 160,1,0,0,115,6,0,0,0,0,3,10,1,16,2,122, - 17,77,111,100,117,108,101,83,112,101,99,46,112,97,114,101, - 110,116,99,1,0,0,0,0,0,0,0,1,0,0,0,1, - 0,0,0,67,0,0,0,115,6,0,0,0,124,0,106,0, - 83,0,41,1,78,41,1,114,107,0,0,0,41,1,114,26, - 0,0,0,114,10,0,0,0,114,10,0,0,0,114,11,0, - 0,0,114,113,0,0,0,168,1,0,0,115,2,0,0,0, - 0,2,122,23,77,111,100,117,108,101,83,112,101,99,46,104, - 97,115,95,108,111,99,97,116,105,111,110,99,2,0,0,0, - 0,0,0,0,2,0,0,0,2,0,0,0,67,0,0,0, - 115,14,0,0,0,116,0,124,1,131,1,124,0,95,1,100, - 0,83,0,41,1,78,41,2,218,4,98,111,111,108,114,107, - 0,0,0,41,2,114,26,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,113,0,0,0,172,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,27,0,0,0,114,40,0,0,0, - 114,114,0,0,0,218,8,112,114,111,112,101,114,116,121,114, - 112,0,0,0,218,6,115,101,116,116,101,114,114,119,0,0, - 0,114,113,0,0,0,114,10,0,0,0,114,10,0,0,0, - 114,10,0,0,0,114,11,0,0,0,114,102,0,0,0,76, - 1,0,0,115,18,0,0,0,12,37,4,1,14,11,8,10, - 8,12,12,9,14,4,12,8,12,4,114,102,0,0,0,41, - 2,114,103,0,0,0,114,105,0,0,0,99,2,0,0,0, - 2,0,0,0,6,0,0,0,8,0,0,0,67,0,0,0, - 115,154,0,0,0,116,0,124,1,100,1,131,2,114,74,116, - 1,100,2,107,8,114,22,116,2,130,1,116,1,106,3,125, - 4,124,3,100,2,107,8,114,48,124,4,124,0,124,1,100, - 3,141,2,83,0,124,3,114,56,103,0,110,2,100,2,125, - 5,124,4,124,0,124,1,124,5,100,4,141,3,83,0,124, - 3,100,2,107,8,114,138,116,0,124,1,100,5,131,2,114, - 134,122,14,124,1,160,4,124,0,161,1,125,3,87,0,113, - 138,4,0,116,5,107,10,114,130,1,0,1,0,1,0,100, - 2,125,3,89,0,113,138,88,0,110,4,100,6,125,3,116, - 6,124,0,124,1,124,2,124,3,100,7,141,4,83,0,41, - 8,122,53,82,101,116,117,114,110,32,97,32,109,111,100,117, - 108,101,32,115,112,101,99,32,98,97,115,101,100,32,111,110, - 32,118,97,114,105,111,117,115,32,108,111,97,100,101,114,32, - 109,101,116,104,111,100,115,46,90,12,103,101,116,95,102,105, - 108,101,110,97,109,101,78,41,1,114,93,0,0,0,41,2, - 114,93,0,0,0,114,106,0,0,0,114,105,0,0,0,70, - 41,2,114,103,0,0,0,114,105,0,0,0,41,7,114,4, - 0,0,0,114,115,0,0,0,114,116,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,105,0,0,0,114,70,0,0,0, - 114,102,0,0,0,41,6,114,15,0,0,0,114,93,0,0, - 0,114,103,0,0,0,114,105,0,0,0,114,124,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,78,0,0,0,177,1,0,0, - 115,34,0,0,0,0,2,10,1,8,1,4,1,6,2,8, - 1,12,1,12,1,6,1,8,2,8,1,10,1,2,1,14, - 1,14,1,12,3,4,2,114,78,0,0,0,99,3,0,0, - 0,0,0,0,0,8,0,0,0,8,0,0,0,67,0,0, - 0,115,56,1,0,0,122,10,124,0,106,0,125,3,87,0, - 110,20,4,0,116,1,107,10,114,30,1,0,1,0,1,0, - 89,0,110,14,88,0,124,3,100,0,107,9,114,44,124,3, - 83,0,124,0,106,2,125,4,124,1,100,0,107,8,114,90, - 122,10,124,0,106,3,125,1,87,0,110,20,4,0,116,1, - 107,10,114,88,1,0,1,0,1,0,89,0,110,2,88,0, - 122,10,124,0,106,4,125,5,87,0,110,24,4,0,116,1, - 107,10,114,124,1,0,1,0,1,0,100,0,125,5,89,0, - 110,2,88,0,124,2,100,0,107,8,114,184,124,5,100,0, - 107,8,114,180,122,10,124,1,106,5,125,2,87,0,113,184, - 4,0,116,1,107,10,114,176,1,0,1,0,1,0,100,0, - 125,2,89,0,113,184,88,0,110,4,124,5,125,2,122,10, - 124,0,106,6,125,6,87,0,110,24,4,0,116,1,107,10, - 114,218,1,0,1,0,1,0,100,0,125,6,89,0,110,2, - 88,0,122,14,116,7,124,0,106,8,131,1,125,7,87,0, - 110,26,4,0,116,1,107,10,144,1,114,4,1,0,1,0, - 1,0,100,0,125,7,89,0,110,2,88,0,116,9,124,4, - 124,1,124,2,100,1,141,3,125,3,124,5,100,0,107,8, - 144,1,114,34,100,2,110,2,100,3,124,3,95,10,124,6, - 124,3,95,11,124,7,124,3,95,12,124,3,83,0,41,4, - 78,41,1,114,103,0,0,0,70,84,41,13,114,89,0,0, - 0,114,90,0,0,0,114,1,0,0,0,114,85,0,0,0, - 114,92,0,0,0,90,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,102,0,0,0,114, - 107,0,0,0,114,112,0,0,0,114,106,0,0,0,41,8, - 114,83,0,0,0,114,93,0,0,0,114,103,0,0,0,114, - 82,0,0,0,114,15,0,0,0,90,8,108,111,99,97,116, - 105,111,110,114,112,0,0,0,114,106,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,203, - 1,0,0,115,72,0,0,0,0,2,2,1,10,1,14,1, - 6,2,8,1,4,2,6,1,8,1,2,1,10,1,14,2, - 6,1,2,1,10,1,14,1,10,1,8,1,8,1,2,1, - 10,1,14,1,12,2,4,1,2,1,10,1,14,1,10,1, - 2,1,14,1,16,1,10,2,14,1,20,1,6,1,6,1, - 114,128,0,0,0,70,41,1,218,8,111,118,101,114,114,105, - 100,101,99,2,0,0,0,1,0,0,0,5,0,0,0,8, - 0,0,0,67,0,0,0,115,226,1,0,0,124,2,115,20, - 116,0,124,1,100,1,100,0,131,3,100,0,107,8,114,54, - 122,12,124,0,106,1,124,1,95,2,87,0,110,20,4,0, - 116,3,107,10,114,52,1,0,1,0,1,0,89,0,110,2, - 88,0,124,2,115,74,116,0,124,1,100,2,100,0,131,3, - 100,0,107,8,114,178,124,0,106,4,125,3,124,3,100,0, - 107,8,114,146,124,0,106,5,100,0,107,9,114,146,116,6, - 100,0,107,8,114,110,116,7,130,1,116,6,106,8,125,4, - 124,4,160,9,124,4,161,1,125,3,124,0,106,5,124,3, - 95,10,124,3,124,0,95,4,100,0,124,1,95,11,122,10, - 124,3,124,1,95,12,87,0,110,20,4,0,116,3,107,10, - 114,176,1,0,1,0,1,0,89,0,110,2,88,0,124,2, - 115,198,116,0,124,1,100,3,100,0,131,3,100,0,107,8, - 114,232,122,12,124,0,106,13,124,1,95,14,87,0,110,20, - 4,0,116,3,107,10,114,230,1,0,1,0,1,0,89,0, - 110,2,88,0,122,10,124,0,124,1,95,15,87,0,110,22, - 4,0,116,3,107,10,144,1,114,8,1,0,1,0,1,0, - 89,0,110,2,88,0,124,2,144,1,115,34,116,0,124,1, - 100,4,100,0,131,3,100,0,107,8,144,1,114,82,124,0, - 106,5,100,0,107,9,144,1,114,82,122,12,124,0,106,5, - 124,1,95,16,87,0,110,22,4,0,116,3,107,10,144,1, - 114,80,1,0,1,0,1,0,89,0,110,2,88,0,124,0, - 106,17,144,1,114,222,124,2,144,1,115,114,116,0,124,1, - 100,5,100,0,131,3,100,0,107,8,144,1,114,150,122,12, - 124,0,106,18,124,1,95,11,87,0,110,22,4,0,116,3, - 107,10,144,1,114,148,1,0,1,0,1,0,89,0,110,2, - 88,0,124,2,144,1,115,174,116,0,124,1,100,6,100,0, - 131,3,100,0,107,8,144,1,114,222,124,0,106,19,100,0, - 107,9,144,1,114,222,122,12,124,0,106,19,124,1,95,20, - 87,0,110,22,4,0,116,3,107,10,144,1,114,220,1,0, - 1,0,1,0,89,0,110,2,88,0,124,1,83,0,41,7, - 78,114,1,0,0,0,114,85,0,0,0,218,11,95,95,112, - 97,99,107,97,103,101,95,95,114,127,0,0,0,114,92,0, - 0,0,114,125,0,0,0,41,21,114,6,0,0,0,114,15, - 0,0,0,114,1,0,0,0,114,90,0,0,0,114,93,0, - 0,0,114,106,0,0,0,114,115,0,0,0,114,116,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,92,0,0,0,114,85,0,0,0,114,119,0, - 0,0,114,130,0,0,0,114,89,0,0,0,114,127,0,0, - 0,114,113,0,0,0,114,103,0,0,0,114,112,0,0,0, - 114,125,0,0,0,41,5,114,82,0,0,0,114,83,0,0, - 0,114,129,0,0,0,114,93,0,0,0,114,131,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,248,1,0,0,115,96,0,0,0,0,4,20,1, - 2,1,12,1,14,1,6,2,20,1,6,1,8,2,10,1, - 8,1,4,1,6,2,10,1,8,1,6,11,6,1,2,1, - 10,1,14,1,6,2,20,1,2,1,12,1,14,1,6,2, - 2,1,10,1,16,1,6,2,24,1,12,1,2,1,12,1, - 16,1,6,2,8,1,24,1,2,1,12,1,16,1,6,2, - 24,1,12,1,2,1,12,1,16,1,6,1,114,133,0,0, - 0,99,1,0,0,0,0,0,0,0,2,0,0,0,3,0, - 0,0,67,0,0,0,115,82,0,0,0,100,1,125,1,116, - 0,124,0,106,1,100,2,131,2,114,30,124,0,106,1,160, - 2,124,0,161,1,125,1,110,20,116,0,124,0,106,1,100, - 3,131,2,114,50,116,3,100,4,131,1,130,1,124,1,100, - 1,107,8,114,68,116,4,124,0,106,5,131,1,125,1,116, - 6,124,0,124,1,131,2,1,0,124,1,83,0,41,5,122, - 43,67,114,101,97,116,101,32,97,32,109,111,100,117,108,101, - 32,98,97,115,101,100,32,111,110,32,116,104,101,32,112,114, - 111,118,105,100,101,100,32,115,112,101,99,46,78,218,13,99, - 114,101,97,116,101,95,109,111,100,117,108,101,218,11,101,120, - 101,99,95,109,111,100,117,108,101,122,66,108,111,97,100,101, - 114,115,32,116,104,97,116,32,100,101,102,105,110,101,32,101, - 120,101,99,95,109,111,100,117,108,101,40,41,32,109,117,115, - 116,32,97,108,115,111,32,100,101,102,105,110,101,32,99,114, - 101,97,116,101,95,109,111,100,117,108,101,40,41,41,7,114, - 4,0,0,0,114,93,0,0,0,114,134,0,0,0,114,70, - 0,0,0,114,16,0,0,0,114,15,0,0,0,114,133,0, - 0,0,41,2,114,82,0,0,0,114,83,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,64, - 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,136,0,0,0,99, - 1,0,0,0,0,0,0,0,2,0,0,0,4,0,0,0, - 67,0,0,0,115,106,0,0,0,124,0,106,0,100,1,107, - 8,114,14,100,2,110,4,124,0,106,0,125,1,124,0,106, - 1,100,1,107,8,114,66,124,0,106,2,100,1,107,8,114, - 50,100,3,160,3,124,1,161,1,83,0,100,4,160,3,124, - 1,124,0,106,2,161,2,83,0,110,36,124,0,106,4,114, - 86,100,5,160,3,124,1,124,0,106,1,161,2,83,0,100, - 6,160,3,124,0,106,0,124,0,106,1,161,2,83,0,100, - 1,83,0,41,7,122,38,82,101,116,117,114,110,32,116,104, - 101,32,114,101,112,114,32,116,111,32,117,115,101,32,102,111, - 114,32,116,104,101,32,109,111,100,117,108,101,46,78,114,87, - 0,0,0,122,13,60,109,111,100,117,108,101,32,123,33,114, - 125,62,122,20,60,109,111,100,117,108,101,32,123,33,114,125, - 32,40,123,33,114,125,41,62,122,23,60,109,111,100,117,108, - 101,32,123,33,114,125,32,102,114,111,109,32,123,33,114,125, - 62,122,18,60,109,111,100,117,108,101,32,123,33,114,125,32, - 40,123,125,41,62,41,5,114,15,0,0,0,114,103,0,0, - 0,114,93,0,0,0,114,38,0,0,0,114,113,0,0,0, - 41,2,114,82,0,0,0,114,15,0,0,0,114,10,0,0, - 0,114,10,0,0,0,114,11,0,0,0,114,91,0,0,0, - 81,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,91,0,0,0,99,2, - 0,0,0,0,0,0,0,4,0,0,0,10,0,0,0,67, - 0,0,0,115,190,0,0,0,124,0,106,0,125,2,116,1, - 124,2,131,1,143,160,1,0,116,2,106,3,160,4,124,2, - 161,1,124,1,107,9,114,54,100,1,160,5,124,2,161,1, - 125,3,116,6,124,3,124,2,100,2,141,2,130,1,124,0, - 106,7,100,3,107,8,114,118,124,0,106,8,100,3,107,8, - 114,88,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,124,1, - 87,0,2,0,53,0,81,0,82,0,163,0,83,0,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,158,124,0,106,7,160,11,124,2, - 161,1,1,0,110,12,124,0,106,7,160,12,124,1,161,1, - 1,0,87,0,53,0,81,0,82,0,88,0,116,2,106,3, - 124,2,25,0,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, - 41,1,114,15,0,0,0,78,122,14,109,105,115,115,105,110, - 103,32,108,111,97,100,101,114,84,41,1,114,129,0,0,0, - 114,135,0,0,0,41,13,114,15,0,0,0,114,42,0,0, - 0,114,14,0,0,0,114,79,0,0,0,114,30,0,0,0, - 114,38,0,0,0,114,70,0,0,0,114,93,0,0,0,114, - 106,0,0,0,114,133,0,0,0,114,4,0,0,0,218,11, - 108,111,97,100,95,109,111,100,117,108,101,114,135,0,0,0, - 41,4,114,82,0,0,0,114,83,0,0,0,114,15,0,0, - 0,218,3,109,115,103,114,10,0,0,0,114,10,0,0,0, - 114,11,0,0,0,114,80,0,0,0,98,2,0,0,115,30, - 0,0,0,0,2,6,1,10,1,16,1,10,1,12,1,10, - 1,10,1,14,2,14,1,16,1,14,1,12,4,14,2,22, - 1,114,80,0,0,0,99,1,0,0,0,0,0,0,0,2, - 0,0,0,8,0,0,0,67,0,0,0,115,206,0,0,0, - 124,0,106,0,160,1,124,0,106,2,161,1,1,0,116,3, - 106,4,124,0,106,2,25,0,125,1,116,5,124,1,100,1, - 100,0,131,3,100,0,107,8,114,76,122,12,124,0,106,0, - 124,1,95,6,87,0,110,20,4,0,116,7,107,10,114,74, - 1,0,1,0,1,0,89,0,110,2,88,0,116,5,124,1, - 100,2,100,0,131,3,100,0,107,8,114,154,122,40,124,1, - 106,8,124,1,95,9,116,10,124,1,100,3,131,2,115,130, - 124,0,106,2,160,11,100,4,161,1,100,5,25,0,124,1, - 95,9,87,0,110,20,4,0,116,7,107,10,114,152,1,0, - 1,0,1,0,89,0,110,2,88,0,116,5,124,1,100,6, - 100,0,131,3,100,0,107,8,114,202,122,10,124,0,124,1, - 95,12,87,0,110,20,4,0,116,7,107,10,114,200,1,0, - 1,0,1,0,89,0,110,2,88,0,124,1,83,0,41,7, - 78,114,85,0,0,0,114,130,0,0,0,114,127,0,0,0, - 114,117,0,0,0,114,19,0,0,0,114,89,0,0,0,41, - 13,114,93,0,0,0,114,137,0,0,0,114,15,0,0,0, - 114,14,0,0,0,114,79,0,0,0,114,6,0,0,0,114, - 85,0,0,0,114,90,0,0,0,114,1,0,0,0,114,130, - 0,0,0,114,4,0,0,0,114,118,0,0,0,114,89,0, - 0,0,41,2,114,82,0,0,0,114,83,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,122,2,0,0,115,40,0,0, - 0,0,4,14,2,12,1,16,1,2,1,12,1,14,1,6, - 1,16,1,2,4,8,1,10,1,22,1,14,1,6,1,16, - 1,2,1,10,1,14,1,6,1,114,139,0,0,0,99,1, - 0,0,0,0,0,0,0,2,0,0,0,9,0,0,0,67, - 0,0,0,115,118,0,0,0,124,0,106,0,100,0,107,9, - 114,30,116,1,124,0,106,0,100,1,131,2,115,30,116,2, - 124,0,131,1,83,0,116,3,124,0,131,1,125,1,116,4, - 124,1,131,1,143,54,1,0,124,0,106,0,100,0,107,8, - 114,84,124,0,106,5,100,0,107,8,114,96,116,6,100,2, - 124,0,106,7,100,3,141,2,130,1,110,12,124,0,106,0, - 160,8,124,1,161,1,1,0,87,0,53,0,81,0,82,0, - 88,0,116,9,106,10,124,0,106,7,25,0,83,0,41,4, - 78,114,135,0,0,0,122,14,109,105,115,115,105,110,103,32, - 108,111,97,100,101,114,41,1,114,15,0,0,0,41,11,114, - 93,0,0,0,114,4,0,0,0,114,139,0,0,0,114,136, - 0,0,0,114,96,0,0,0,114,106,0,0,0,114,70,0, - 0,0,114,15,0,0,0,114,135,0,0,0,114,14,0,0, - 0,114,79,0,0,0,41,2,114,82,0,0,0,114,83,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,151,2,0,0,115,20,0,0,0,0,2,10,2,12,1, - 8,2,8,1,10,1,10,1,10,1,16,3,22,5,114,140, - 0,0,0,99,1,0,0,0,0,0,0,0,1,0,0,0, - 10,0,0,0,67,0,0,0,115,42,0,0,0,116,0,124, - 0,106,1,131,1,143,22,1,0,116,2,124,0,131,1,87, - 0,2,0,53,0,81,0,82,0,163,0,83,0,81,0,82, - 0,88,0,100,1,83,0,41,2,122,191,82,101,116,117,114, - 110,32,97,32,110,101,119,32,109,111,100,117,108,101,32,111, - 98,106,101,99,116,44,32,108,111,97,100,101,100,32,98,121, - 32,116,104,101,32,115,112,101,99,39,115,32,108,111,97,100, - 101,114,46,10,10,32,32,32,32,84,104,101,32,109,111,100, - 117,108,101,32,105,115,32,110,111,116,32,97,100,100,101,100, - 32,116,111,32,105,116,115,32,112,97,114,101,110,116,46,10, - 10,32,32,32,32,73,102,32,97,32,109,111,100,117,108,101, - 32,105,115,32,97,108,114,101,97,100,121,32,105,110,32,115, - 121,115,46,109,111,100,117,108,101,115,44,32,116,104,97,116, - 32,101,120,105,115,116,105,110,103,32,109,111,100,117,108,101, - 32,103,101,116,115,10,32,32,32,32,99,108,111,98,98,101, - 114,101,100,46,10,10,32,32,32,32,78,41,3,114,42,0, - 0,0,114,15,0,0,0,114,140,0,0,0,41,1,114,82, - 0,0,0,114,10,0,0,0,114,10,0,0,0,114,11,0, - 0,0,114,81,0,0,0,174,2,0,0,115,4,0,0,0, - 0,9,12,1,114,81,0,0,0,99,0,0,0,0,0,0, - 0,0,0,0,0,0,4,0,0,0,64,0,0,0,115,136, - 0,0,0,101,0,90,1,100,0,90,2,100,1,90,3,101, - 4,100,2,100,3,132,0,131,1,90,5,101,6,100,19,100, - 5,100,6,132,1,131,1,90,7,101,6,100,20,100,7,100, - 8,132,1,131,1,90,8,101,6,100,9,100,10,132,0,131, - 1,90,9,101,6,100,11,100,12,132,0,131,1,90,10,101, - 6,101,11,100,13,100,14,132,0,131,1,131,1,90,12,101, - 6,101,11,100,15,100,16,132,0,131,1,131,1,90,13,101, - 6,101,11,100,17,100,18,132,0,131,1,131,1,90,14,101, - 6,101,15,131,1,90,16,100,4,83,0,41,21,218,15,66, - 117,105,108,116,105,110,73,109,112,111,114,116,101,114,122,144, - 77,101,116,97,32,112,97,116,104,32,105,109,112,111,114,116, - 32,102,111,114,32,98,117,105,108,116,45,105,110,32,109,111, - 100,117,108,101,115,46,10,10,32,32,32,32,65,108,108,32, - 109,101,116,104,111,100,115,32,97,114,101,32,101,105,116,104, - 101,114,32,99,108,97,115,115,32,111,114,32,115,116,97,116, - 105,99,32,109,101,116,104,111,100,115,32,116,111,32,97,118, - 111,105,100,32,116,104,101,32,110,101,101,100,32,116,111,10, - 32,32,32,32,105,110,115,116,97,110,116,105,97,116,101,32, - 116,104,101,32,99,108,97,115,115,46,10,10,32,32,32,32, - 99,1,0,0,0,0,0,0,0,1,0,0,0,3,0,0, - 0,67,0,0,0,115,12,0,0,0,100,1,160,0,124,0, - 106,1,161,1,83,0,41,2,122,115,82,101,116,117,114,110, - 32,114,101,112,114,32,102,111,114,32,116,104,101,32,109,111, - 100,117,108,101,46,10,10,32,32,32,32,32,32,32,32,84, - 104,101,32,109,101,116,104,111,100,32,105,115,32,100,101,112, - 114,101,99,97,116,101,100,46,32,32,84,104,101,32,105,109, - 112,111,114,116,32,109,97,99,104,105,110,101,114,121,32,100, - 111,101,115,32,116,104,101,32,106,111,98,32,105,116,115,101, - 108,102,46,10,10,32,32,32,32,32,32,32,32,122,24,60, - 109,111,100,117,108,101,32,123,33,114,125,32,40,98,117,105, - 108,116,45,105,110,41,62,41,2,114,38,0,0,0,114,1, - 0,0,0,41,1,114,83,0,0,0,114,10,0,0,0,114, - 10,0,0,0,114,11,0,0,0,114,86,0,0,0,198,2, - 0,0,115,2,0,0,0,0,7,122,27,66,117,105,108,116, - 105,110,73,109,112,111,114,116,101,114,46,109,111,100,117,108, - 101,95,114,101,112,114,78,99,4,0,0,0,0,0,0,0, - 4,0,0,0,5,0,0,0,67,0,0,0,115,44,0,0, - 0,124,2,100,0,107,9,114,12,100,0,83,0,116,0,160, - 1,124,1,161,1,114,36,116,2,124,1,124,0,100,1,100, - 2,141,3,83,0,100,0,83,0,100,0,83,0,41,3,78, - 122,8,98,117,105,108,116,45,105,110,41,1,114,103,0,0, - 0,41,3,114,49,0,0,0,90,10,105,115,95,98,117,105, - 108,116,105,110,114,78,0,0,0,41,4,218,3,99,108,115, - 114,71,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,207,2,0, - 0,115,10,0,0,0,0,2,8,1,4,1,10,1,14,2, - 122,25,66,117,105,108,116,105,110,73,109,112,111,114,116,101, - 114,46,102,105,110,100,95,115,112,101,99,99,3,0,0,0, - 0,0,0,0,4,0,0,0,4,0,0,0,67,0,0,0, - 115,30,0,0,0,124,0,160,0,124,1,124,2,161,2,125, - 3,124,3,100,1,107,9,114,26,124,3,106,1,83,0,100, - 1,83,0,41,2,122,175,70,105,110,100,32,116,104,101,32, - 98,117,105,108,116,45,105,110,32,109,111,100,117,108,101,46, - 10,10,32,32,32,32,32,32,32,32,73,102,32,39,112,97, - 116,104,39,32,105,115,32,101,118,101,114,32,115,112,101,99, - 105,102,105,101,100,32,116,104,101,110,32,116,104,101,32,115, - 101,97,114,99,104,32,105,115,32,99,111,110,115,105,100,101, - 114,101,100,32,97,32,102,97,105,108,117,114,101,46,10,10, - 32,32,32,32,32,32,32,32,84,104,105,115,32,109,101,116, - 104,111,100,32,105,115,32,100,101,112,114,101,99,97,116,101, - 100,46,32,32,85,115,101,32,102,105,110,100,95,115,112,101, - 99,40,41,32,105,110,115,116,101,97,100,46,10,10,32,32, - 32,32,32,32,32,32,78,41,2,114,145,0,0,0,114,93, - 0,0,0,41,4,114,142,0,0,0,114,71,0,0,0,114, - 143,0,0,0,114,82,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,216,2,0,0,115,4,0,0,0,0,9, - 12,1,122,27,66,117,105,108,116,105,110,73,109,112,111,114, - 116,101,114,46,102,105,110,100,95,109,111,100,117,108,101,99, - 2,0,0,0,0,0,0,0,2,0,0,0,4,0,0,0, - 67,0,0,0,115,46,0,0,0,124,1,106,0,116,1,106, - 2,107,7,114,34,116,3,100,1,160,4,124,1,106,0,161, - 1,124,1,106,0,100,2,141,2,130,1,116,5,116,6,106, - 7,124,1,131,2,83,0,41,3,122,24,67,114,101,97,116, - 101,32,97,32,98,117,105,108,116,45,105,110,32,109,111,100, - 117,108,101,122,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,41,1,114,15,0,0,0,41,8,114,15,0,0,0, - 114,14,0,0,0,114,69,0,0,0,114,70,0,0,0,114, - 38,0,0,0,114,59,0,0,0,114,49,0,0,0,90,14, - 99,114,101,97,116,101,95,98,117,105,108,116,105,110,41,2, - 114,26,0,0,0,114,82,0,0,0,114,10,0,0,0,114, - 10,0,0,0,114,11,0,0,0,114,134,0,0,0,228,2, - 0,0,115,8,0,0,0,0,3,12,1,12,1,10,1,122, - 29,66,117,105,108,116,105,110,73,109,112,111,114,116,101,114, - 46,99,114,101,97,116,101,95,109,111,100,117,108,101,99,2, - 0,0,0,0,0,0,0,2,0,0,0,3,0,0,0,67, - 0,0,0,115,16,0,0,0,116,0,116,1,106,2,124,1, - 131,2,1,0,100,1,83,0,41,2,122,22,69,120,101,99, - 32,97,32,98,117,105,108,116,45,105,110,32,109,111,100,117, - 108,101,78,41,3,114,59,0,0,0,114,49,0,0,0,90, - 12,101,120,101,99,95,98,117,105,108,116,105,110,41,2,114, - 26,0,0,0,114,83,0,0,0,114,10,0,0,0,114,10, - 0,0,0,114,11,0,0,0,114,135,0,0,0,236,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, + 86,0,0,0,198,2,0,0,115,2,0,0,0,0,7,122, + 27,66,117,105,108,116,105,110,73,109,112,111,114,116,101,114, + 46,109,111,100,117,108,101,95,114,101,112,114,78,99,4,0, + 0,0,0,0,0,0,4,0,0,0,5,0,0,0,67,0, + 0,0,115,44,0,0,0,124,2,100,0,107,9,114,12,100, + 0,83,0,116,0,160,1,124,1,161,1,114,36,116,2,124, + 1,124,0,100,1,100,2,141,3,83,0,100,0,83,0,100, + 0,83,0,41,3,78,122,8,98,117,105,108,116,45,105,110, + 41,1,114,103,0,0,0,41,3,114,49,0,0,0,90,10, + 105,115,95,98,117,105,108,116,105,110,114,78,0,0,0,41, + 4,218,3,99,108,115,114,71,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,207,2,0,0,115,10,0,0,0,0,2,8,1, + 4,1,10,1,14,2,122,25,66,117,105,108,116,105,110,73, + 109,112,111,114,116,101,114,46,102,105,110,100,95,115,112,101, + 99,99,3,0,0,0,0,0,0,0,4,0,0,0,4,0, + 0,0,67,0,0,0,115,30,0,0,0,124,0,160,0,124, + 1,124,2,161,2,125,3,124,3,100,1,107,9,114,26,124, + 3,106,1,83,0,100,1,83,0,41,2,122,175,70,105,110, + 100,32,116,104,101,32,98,117,105,108,116,45,105,110,32,109, + 111,100,117,108,101,46,10,10,32,32,32,32,32,32,32,32, + 73,102,32,39,112,97,116,104,39,32,105,115,32,101,118,101, + 114,32,115,112,101,99,105,102,105,101,100,32,116,104,101,110, + 32,116,104,101,32,115,101,97,114,99,104,32,105,115,32,99, + 111,110,115,105,100,101,114,101,100,32,97,32,102,97,105,108, + 117,114,101,46,10,10,32,32,32,32,32,32,32,32,84,104, + 105,115,32,109,101,116,104,111,100,32,105,115,32,100,101,112, + 114,101,99,97,116,101,100,46,32,32,85,115,101,32,102,105, + 110,100,95,115,112,101,99,40,41,32,105,110,115,116,101,97, + 100,46,10,10,32,32,32,32,32,32,32,32,78,41,2,114, + 145,0,0,0,114,93,0,0,0,41,4,114,142,0,0,0, + 114,71,0,0,0,114,143,0,0,0,114,82,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,216,2,0,0,115, + 4,0,0,0,0,9,12,1,122,27,66,117,105,108,116,105, + 110,73,109,112,111,114,116,101,114,46,102,105,110,100,95,109, 111,100,117,108,101,99,2,0,0,0,0,0,0,0,2,0, - 0,0,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, + 0,0,4,0,0,0,67,0,0,0,115,46,0,0,0,124, + 1,106,0,116,1,106,2,107,7,114,34,116,3,100,1,160, + 4,124,1,106,0,161,1,124,1,106,0,100,2,141,2,130, + 1,116,5,116,6,106,7,124,1,131,2,83,0,41,3,122, + 24,67,114,101,97,116,101,32,97,32,98,117,105,108,116,45, + 105,110,32,109,111,100,117,108,101,122,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,41,1,114,15,0,0,0,41, + 8,114,15,0,0,0,114,14,0,0,0,114,69,0,0,0, + 114,70,0,0,0,114,38,0,0,0,114,59,0,0,0,114, + 49,0,0,0,90,14,99,114,101,97,116,101,95,98,117,105, + 108,116,105,110,41,2,114,26,0,0,0,114,82,0,0,0, + 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,114, + 134,0,0,0,228,2,0,0,115,8,0,0,0,0,3,12, + 1,12,1,10,1,122,29,66,117,105,108,116,105,110,73,109, + 112,111,114,116,101,114,46,99,114,101,97,116,101,95,109,111, + 100,117,108,101,99,2,0,0,0,0,0,0,0,2,0,0, + 0,3,0,0,0,67,0,0,0,115,16,0,0,0,116,0, + 116,1,106,2,124,1,131,2,1,0,100,1,83,0,41,2, + 122,22,69,120,101,99,32,97,32,98,117,105,108,116,45,105, + 110,32,109,111,100,117,108,101,78,41,3,114,59,0,0,0, + 114,49,0,0,0,90,12,101,120,101,99,95,98,117,105,108, + 116,105,110,41,2,114,26,0,0,0,114,83,0,0,0,114, + 10,0,0,0,114,10,0,0,0,114,11,0,0,0,114,135, + 0,0,0,236,2,0,0,115,2,0,0,0,0,3,122,27, + 66,117,105,108,116,105,110,73,109,112,111,114,116,101,114,46, + 101,120,101,99,95,109,111,100,117,108,101,99,2,0,0,0, + 0,0,0,0,2,0,0,0,1,0,0,0,67,0,0,0, + 115,4,0,0,0,100,1,83,0,41,2,122,57,82,101,116, + 117,114,110,32,78,111,110,101,32,97,115,32,98,117,105,108, + 116,45,105,110,32,109,111,100,117,108,101,115,32,100,111,32, + 110,111,116,32,104,97,118,101,32,99,111,100,101,32,111,98, + 106,101,99,116,115,46,78,114,10,0,0,0,41,2,114,142, + 0,0,0,114,71,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,241,2,0,0,115,2,0,0,0,0,4,122,24,66,117, + 105,108,116,105,110,73,109,112,111,114,116,101,114,46,103,101, + 116,95,99,111,100,101,99,2,0,0,0,0,0,0,0,2, + 0,0,0,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,41,2,114,142,0,0,0,114,71,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,241,2,0,0,115, - 2,0,0,0,0,4,122,24,66,117,105,108,116,105,110,73, - 109,112,111,114,116,101,114,46,103,101,116,95,99,111,100,101, - 99,2,0,0,0,0,0,0,0,2,0,0,0,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, + 0,218,10,103,101,116,95,115,111,117,114,99,101,247,2,0, + 0,115,2,0,0,0,0,4,122,26,66,117,105,108,116,105, + 110,73,109,112,111,114,116,101,114,46,103,101,116,95,115,111, + 117,114,99,101,99,2,0,0,0,0,0,0,0,2,0,0, + 0,1,0,0,0,67,0,0,0,115,4,0,0,0,100,1, + 83,0,41,2,122,52,82,101,116,117,114,110,32,70,97,108, + 115,101,32,97,115,32,98,117,105,108,116,45,105,110,32,109, + 111,100,117,108,101,115,32,97,114,101,32,110,101,118,101,114, + 32,112,97,99,107,97,103,101,115,46,70,114,10,0,0,0, 41,2,114,142,0,0,0,114,71,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,247,2,0,0,115,2,0,0,0, - 0,4,122,26,66,117,105,108,116,105,110,73,109,112,111,114, - 116,101,114,46,103,101,116,95,115,111,117,114,99,101,99,2, - 0,0,0,0,0,0,0,2,0,0,0,1,0,0,0,67, - 0,0,0,115,4,0,0,0,100,1,83,0,41,2,122,52, - 82,101,116,117,114,110,32,70,97,108,115,101,32,97,115,32, - 98,117,105,108,116,45,105,110,32,109,111,100,117,108,101,115, - 32,97,114,101,32,110,101,118,101,114,32,112,97,99,107,97, - 103,101,115,46,70,114,10,0,0,0,41,2,114,142,0,0, - 0,114,71,0,0,0,114,10,0,0,0,114,10,0,0,0, - 114,11,0,0,0,114,105,0,0,0,253,2,0,0,115,2, - 0,0,0,0,4,122,26,66,117,105,108,116,105,110,73,109, - 112,111,114,116,101,114,46,105,115,95,112,97,99,107,97,103, - 101,41,2,78,78,41,1,78,41,17,114,1,0,0,0,114, - 0,0,0,0,114,2,0,0,0,114,3,0,0,0,218,12, - 115,116,97,116,105,99,109,101,116,104,111,100,114,86,0,0, - 0,218,11,99,108,97,115,115,109,101,116,104,111,100,114,145, - 0,0,0,114,146,0,0,0,114,134,0,0,0,114,135,0, - 0,0,114,74,0,0,0,114,147,0,0,0,114,148,0,0, - 0,114,105,0,0,0,114,84,0,0,0,114,137,0,0,0, - 114,10,0,0,0,114,10,0,0,0,114,10,0,0,0,114, - 11,0,0,0,114,141,0,0,0,189,2,0,0,115,28,0, - 0,0,12,9,12,9,2,1,12,8,2,1,12,11,12,8, - 12,5,2,1,14,5,2,1,14,5,2,1,14,5,114,141, - 0,0,0,99,0,0,0,0,0,0,0,0,0,0,0,0, - 4,0,0,0,64,0,0,0,115,140,0,0,0,101,0,90, - 1,100,0,90,2,100,1,90,3,101,4,100,2,100,3,132, - 0,131,1,90,5,101,6,100,21,100,5,100,6,132,1,131, - 1,90,7,101,6,100,22,100,7,100,8,132,1,131,1,90, - 8,101,6,100,9,100,10,132,0,131,1,90,9,101,4,100, - 11,100,12,132,0,131,1,90,10,101,6,100,13,100,14,132, - 0,131,1,90,11,101,6,101,12,100,15,100,16,132,0,131, - 1,131,1,90,13,101,6,101,12,100,17,100,18,132,0,131, - 1,131,1,90,14,101,6,101,12,100,19,100,20,132,0,131, - 1,131,1,90,15,100,4,83,0,41,23,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,99,1,0,0,0, - 0,0,0,0,1,0,0,0,3,0,0,0,67,0,0,0, - 115,12,0,0,0,100,1,160,0,124,0,106,1,161,1,83, - 0,41,2,122,115,82,101,116,117,114,110,32,114,101,112,114, - 32,102,111,114,32,116,104,101,32,109,111,100,117,108,101,46, - 10,10,32,32,32,32,32,32,32,32,84,104,101,32,109,101, - 116,104,111,100,32,105,115,32,100,101,112,114,101,99,97,116, - 101,100,46,32,32,84,104,101,32,105,109,112,111,114,116,32, - 109,97,99,104,105,110,101,114,121,32,100,111,101,115,32,116, - 104,101,32,106,111,98,32,105,116,115,101,108,102,46,10,10, - 32,32,32,32,32,32,32,32,122,22,60,109,111,100,117,108, - 101,32,123,33,114,125,32,40,102,114,111,122,101,110,41,62, - 41,2,114,38,0,0,0,114,1,0,0,0,41,1,218,1, - 109,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, - 114,86,0,0,0,15,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,4,0,0,0,5,0,0,0,67,0, - 0,0,115,32,0,0,0,116,0,160,1,124,1,161,1,114, - 24,116,2,124,1,124,0,100,1,100,2,141,3,83,0,100, - 0,83,0,100,0,83,0,41,3,78,90,6,102,114,111,122, - 101,110,41,1,114,103,0,0,0,41,3,114,49,0,0,0, - 114,75,0,0,0,114,78,0,0,0,41,4,114,142,0,0, - 0,114,71,0,0,0,114,143,0,0,0,114,144,0,0,0, + 0,114,10,0,0,0,114,11,0,0,0,114,105,0,0,0, + 253,2,0,0,115,2,0,0,0,0,4,122,26,66,117,105, + 108,116,105,110,73,109,112,111,114,116,101,114,46,105,115,95, + 112,97,99,107,97,103,101,41,2,78,78,41,1,78,41,17, + 114,1,0,0,0,114,0,0,0,0,114,2,0,0,0,114, + 3,0,0,0,218,12,115,116,97,116,105,99,109,101,116,104, + 111,100,114,86,0,0,0,218,11,99,108,97,115,115,109,101, + 116,104,111,100,114,145,0,0,0,114,146,0,0,0,114,134, + 0,0,0,114,135,0,0,0,114,74,0,0,0,114,147,0, + 0,0,114,148,0,0,0,114,105,0,0,0,114,84,0,0, + 0,114,137,0,0,0,114,10,0,0,0,114,10,0,0,0, + 114,10,0,0,0,114,11,0,0,0,114,141,0,0,0,189, + 2,0,0,115,30,0,0,0,8,7,4,2,12,9,2,1, + 12,8,2,1,12,11,12,8,12,5,2,1,14,5,2,1, + 14,5,2,1,14,5,114,141,0,0,0,99,0,0,0,0, + 0,0,0,0,0,0,0,0,4,0,0,0,64,0,0,0, + 115,140,0,0,0,101,0,90,1,100,0,90,2,100,1,90, + 3,101,4,100,2,100,3,132,0,131,1,90,5,101,6,100, + 21,100,5,100,6,132,1,131,1,90,7,101,6,100,22,100, + 7,100,8,132,1,131,1,90,8,101,6,100,9,100,10,132, + 0,131,1,90,9,101,4,100,11,100,12,132,0,131,1,90, + 10,101,6,100,13,100,14,132,0,131,1,90,11,101,6,101, + 12,100,15,100,16,132,0,131,1,131,1,90,13,101,6,101, + 12,100,17,100,18,132,0,131,1,131,1,90,14,101,6,101, + 12,100,19,100,20,132,0,131,1,131,1,90,15,100,4,83, + 0,41,23,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,99,1,0,0,0,0,0,0,0,1,0,0,0, + 3,0,0,0,67,0,0,0,115,12,0,0,0,100,1,160, + 0,124,0,106,1,161,1,83,0,41,2,122,115,82,101,116, + 117,114,110,32,114,101,112,114,32,102,111,114,32,116,104,101, + 32,109,111,100,117,108,101,46,10,10,32,32,32,32,32,32, + 32,32,84,104,101,32,109,101,116,104,111,100,32,105,115,32, + 100,101,112,114,101,99,97,116,101,100,46,32,32,84,104,101, + 32,105,109,112,111,114,116,32,109,97,99,104,105,110,101,114, + 121,32,100,111,101,115,32,116,104,101,32,106,111,98,32,105, + 116,115,101,108,102,46,10,10,32,32,32,32,32,32,32,32, + 122,22,60,109,111,100,117,108,101,32,123,33,114,125,32,40, + 102,114,111,122,101,110,41,62,41,2,114,38,0,0,0,114, + 1,0,0,0,41,1,218,1,109,114,10,0,0,0,114,10, + 0,0,0,114,11,0,0,0,114,86,0,0,0,15,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,4,0, + 0,0,5,0,0,0,67,0,0,0,115,32,0,0,0,116, + 0,160,1,124,1,161,1,114,24,116,2,124,1,124,0,100, + 1,100,2,141,3,83,0,100,0,83,0,100,0,83,0,41, + 3,78,90,6,102,114,111,122,101,110,41,1,114,103,0,0, + 0,41,3,114,49,0,0,0,114,75,0,0,0,114,78,0, + 0,0,41,4,114,142,0,0,0,114,71,0,0,0,114,143, + 0,0,0,114,144,0,0,0,114,10,0,0,0,114,10,0, + 0,0,114,11,0,0,0,114,145,0,0,0,24,3,0,0, + 115,6,0,0,0,0,2,10,1,14,2,122,24,70,114,111, + 122,101,110,73,109,112,111,114,116,101,114,46,102,105,110,100, + 95,115,112,101,99,99,3,0,0,0,0,0,0,0,3,0, + 0,0,3,0,0,0,67,0,0,0,115,18,0,0,0,116, + 0,160,1,124,1,161,1,114,14,124,0,83,0,100,1,83, + 0,41,2,122,93,70,105,110,100,32,97,32,102,114,111,122, + 101,110,32,109,111,100,117,108,101,46,10,10,32,32,32,32, + 32,32,32,32,84,104,105,115,32,109,101,116,104,111,100,32, + 105,115,32,100,101,112,114,101,99,97,116,101,100,46,32,32, + 85,115,101,32,102,105,110,100,95,115,112,101,99,40,41,32, + 105,110,115,116,101,97,100,46,10,10,32,32,32,32,32,32, + 32,32,78,41,2,114,49,0,0,0,114,75,0,0,0,41, + 3,114,142,0,0,0,114,71,0,0,0,114,143,0,0,0, 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,114, - 145,0,0,0,24,3,0,0,115,6,0,0,0,0,2,10, - 1,14,2,122,24,70,114,111,122,101,110,73,109,112,111,114, - 116,101,114,46,102,105,110,100,95,115,112,101,99,99,3,0, - 0,0,0,0,0,0,3,0,0,0,3,0,0,0,67,0, - 0,0,115,18,0,0,0,116,0,160,1,124,1,161,1,114, - 14,124,0,83,0,100,1,83,0,41,2,122,93,70,105,110, - 100,32,97,32,102,114,111,122,101,110,32,109,111,100,117,108, - 101,46,10,10,32,32,32,32,32,32,32,32,84,104,105,115, - 32,109,101,116,104,111,100,32,105,115,32,100,101,112,114,101, - 99,97,116,101,100,46,32,32,85,115,101,32,102,105,110,100, - 95,115,112,101,99,40,41,32,105,110,115,116,101,97,100,46, - 10,10,32,32,32,32,32,32,32,32,78,41,2,114,49,0, - 0,0,114,75,0,0,0,41,3,114,142,0,0,0,114,71, - 0,0,0,114,143,0,0,0,114,10,0,0,0,114,10,0, - 0,0,114,11,0,0,0,114,146,0,0,0,31,3,0,0, - 115,2,0,0,0,0,7,122,26,70,114,111,122,101,110,73, - 109,112,111,114,116,101,114,46,102,105,110,100,95,109,111,100, - 117,108,101,99,2,0,0,0,0,0,0,0,2,0,0,0, - 1,0,0,0,67,0,0,0,115,4,0,0,0,100,1,83, - 0,41,2,122,42,85,115,101,32,100,101,102,97,117,108,116, - 32,115,101,109,97,110,116,105,99,115,32,102,111,114,32,109, - 111,100,117,108,101,32,99,114,101,97,116,105,111,110,46,78, - 114,10,0,0,0,41,2,114,142,0,0,0,114,82,0,0, - 0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, - 114,134,0,0,0,40,3,0,0,115,0,0,0,0,122,28, - 70,114,111,122,101,110,73,109,112,111,114,116,101,114,46,99, - 114,101,97,116,101,95,109,111,100,117,108,101,99,1,0,0, - 0,0,0,0,0,3,0,0,0,4,0,0,0,67,0,0, - 0,115,64,0,0,0,124,0,106,0,106,1,125,1,116,2, - 160,3,124,1,161,1,115,36,116,4,100,1,160,5,124,1, - 161,1,124,1,100,2,141,2,130,1,116,6,116,2,106,7, - 124,1,131,2,125,2,116,8,124,2,124,0,106,9,131,2, - 1,0,100,0,83,0,41,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,41,1,114,15,0,0,0,41,10,114, - 89,0,0,0,114,15,0,0,0,114,49,0,0,0,114,75, - 0,0,0,114,70,0,0,0,114,38,0,0,0,114,59,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,83,0,0,0,114,15,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,135,0,0,0,44,3,0,0,115,12,0,0,0,0, - 2,8,1,10,1,10,1,8,1,12,1,122,26,70,114,111, - 122,101,110,73,109,112,111,114,116,101,114,46,101,120,101,99, - 95,109,111,100,117,108,101,99,2,0,0,0,0,0,0,0, - 2,0,0,0,3,0,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,84,0,0,0,41,2,114,142,0,0,0,114,71,0,0, - 0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, - 114,137,0,0,0,53,3,0,0,115,2,0,0,0,0,7, - 122,26,70,114,111,122,101,110,73,109,112,111,114,116,101,114, - 46,108,111,97,100,95,109,111,100,117,108,101,99,2,0,0, - 0,0,0,0,0,2,0,0,0,3,0,0,0,67,0,0, - 0,115,10,0,0,0,116,0,160,1,124,1,161,1,83,0, - 41,1,122,45,82,101,116,117,114,110,32,116,104,101,32,99, - 111,100,101,32,111,98,106,101,99,116,32,102,111,114,32,116, - 104,101,32,102,114,111,122,101,110,32,109,111,100,117,108,101, - 46,41,2,114,49,0,0,0,114,153,0,0,0,41,2,114, - 142,0,0,0,114,71,0,0,0,114,10,0,0,0,114,10, - 0,0,0,114,11,0,0,0,114,147,0,0,0,62,3,0, - 0,115,2,0,0,0,0,4,122,23,70,114,111,122,101,110, - 73,109,112,111,114,116,101,114,46,103,101,116,95,99,111,100, - 101,99,2,0,0,0,0,0,0,0,2,0,0,0,1,0, - 0,0,67,0,0,0,115,4,0,0,0,100,1,83,0,41, - 2,122,54,82,101,116,117,114,110,32,78,111,110,101,32,97, - 115,32,102,114,111,122,101,110,32,109,111,100,117,108,101,115, - 32,100,111,32,110,111,116,32,104,97,118,101,32,115,111,117, - 114,99,101,32,99,111,100,101,46,78,114,10,0,0,0,41, + 146,0,0,0,31,3,0,0,115,2,0,0,0,0,7,122, + 26,70,114,111,122,101,110,73,109,112,111,114,116,101,114,46, + 102,105,110,100,95,109,111,100,117,108,101,99,2,0,0,0, + 0,0,0,0,2,0,0,0,1,0,0,0,67,0,0,0, + 115,4,0,0,0,100,1,83,0,41,2,122,42,85,115,101, + 32,100,101,102,97,117,108,116,32,115,101,109,97,110,116,105, + 99,115,32,102,111,114,32,109,111,100,117,108,101,32,99,114, + 101,97,116,105,111,110,46,78,114,10,0,0,0,41,2,114, + 142,0,0,0,114,82,0,0,0,114,10,0,0,0,114,10, + 0,0,0,114,11,0,0,0,114,134,0,0,0,40,3,0, + 0,115,2,0,0,0,0,2,122,28,70,114,111,122,101,110, + 73,109,112,111,114,116,101,114,46,99,114,101,97,116,101,95, + 109,111,100,117,108,101,99,1,0,0,0,0,0,0,0,3, + 0,0,0,4,0,0,0,67,0,0,0,115,64,0,0,0, + 124,0,106,0,106,1,125,1,116,2,160,3,124,1,161,1, + 115,36,116,4,100,1,160,5,124,1,161,1,124,1,100,2, + 141,2,130,1,116,6,116,2,106,7,124,1,131,2,125,2, + 116,8,124,2,124,0,106,9,131,2,1,0,100,0,83,0, + 41,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, + 41,1,114,15,0,0,0,41,10,114,89,0,0,0,114,15, + 0,0,0,114,49,0,0,0,114,75,0,0,0,114,70,0, + 0,0,114,38,0,0,0,114,59,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,83,0,0, + 0,114,15,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,135,0,0,0, + 44,3,0,0,115,12,0,0,0,0,2,8,1,10,1,10, + 1,8,1,12,1,122,26,70,114,111,122,101,110,73,109,112, + 111,114,116,101,114,46,101,120,101,99,95,109,111,100,117,108, + 101,99,2,0,0,0,0,0,0,0,2,0,0,0,3,0, + 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,84,0,0,0,41, 2,114,142,0,0,0,114,71,0,0,0,114,10,0,0,0, - 114,10,0,0,0,114,11,0,0,0,114,148,0,0,0,68, - 3,0,0,115,2,0,0,0,0,4,122,25,70,114,111,122, - 101,110,73,109,112,111,114,116,101,114,46,103,101,116,95,115, - 111,117,114,99,101,99,2,0,0,0,0,0,0,0,2,0, - 0,0,3,0,0,0,67,0,0,0,115,10,0,0,0,116, - 0,160,1,124,1,161,1,83,0,41,1,122,46,82,101,116, - 117,114,110,32,84,114,117,101,32,105,102,32,116,104,101,32, - 102,114,111,122,101,110,32,109,111,100,117,108,101,32,105,115, - 32,97,32,112,97,99,107,97,103,101,46,41,2,114,49,0, - 0,0,90,17,105,115,95,102,114,111,122,101,110,95,112,97, - 99,107,97,103,101,41,2,114,142,0,0,0,114,71,0,0, - 0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, - 114,105,0,0,0,74,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,16,114,1,0,0,0,114,0,0,0,0,114,2, - 0,0,0,114,3,0,0,0,114,149,0,0,0,114,86,0, - 0,0,114,150,0,0,0,114,145,0,0,0,114,146,0,0, - 0,114,134,0,0,0,114,135,0,0,0,114,137,0,0,0, - 114,77,0,0,0,114,147,0,0,0,114,148,0,0,0,114, - 105,0,0,0,114,10,0,0,0,114,10,0,0,0,114,10, - 0,0,0,114,11,0,0,0,114,151,0,0,0,6,3,0, - 0,115,28,0,0,0,12,9,12,9,2,1,12,6,2,1, - 12,8,12,4,12,9,12,9,2,1,14,5,2,1,14,5, - 2,1,114,151,0,0,0,99,0,0,0,0,0,0,0,0, - 0,0,0,0,2,0,0,0,64,0,0,0,115,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,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,49,0,0,0,114,50,0,0,0,41,1,114,26, - 0,0,0,114,10,0,0,0,114,10,0,0,0,114,11,0, - 0,0,114,46,0,0,0,87,3,0,0,115,2,0,0,0, - 0,2,122,28,95,73,109,112,111,114,116,76,111,99,107,67, - 111,110,116,101,120,116,46,95,95,101,110,116,101,114,95,95, - 99,4,0,0,0,0,0,0,0,4,0,0,0,2,0,0, - 0,67,0,0,0,115,12,0,0,0,116,0,160,1,161,0, - 1,0,100,1,83,0,41,2,122,60,82,101,108,101,97,115, - 101,32,116,104,101,32,105,109,112,111,114,116,32,108,111,99, - 107,32,114,101,103,97,114,100,108,101,115,115,32,111,102,32, - 97,110,121,32,114,97,105,115,101,100,32,101,120,99,101,112, - 116,105,111,110,115,46,78,41,2,114,49,0,0,0,114,52, - 0,0,0,41,4,114,26,0,0,0,90,8,101,120,99,95, - 116,121,112,101,90,9,101,120,99,95,118,97,108,117,101,90, - 13,101,120,99,95,116,114,97,99,101,98,97,99,107,114,10, - 0,0,0,114,10,0,0,0,114,11,0,0,0,114,48,0, - 0,0,91,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,46,0,0,0,114,48,0,0,0,114,10,0,0,0, - 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,114, - 156,0,0,0,83,3,0,0,115,4,0,0,0,12,4,8, - 4,114,156,0,0,0,99,3,0,0,0,0,0,0,0,5, - 0,0,0,5,0,0,0,67,0,0,0,115,64,0,0,0, - 124,1,160,0,100,1,124,2,100,2,24,0,161,2,125,3, - 116,1,124,3,131,1,124,2,107,0,114,36,116,2,100,3, - 131,1,130,1,124,3,100,4,25,0,125,4,124,0,114,60, - 100,5,160,3,124,4,124,0,161,2,83,0,124,4,83,0, - 41,6,122,50,82,101,115,111,108,118,101,32,97,32,114,101, - 108,97,116,105,118,101,32,109,111,100,117,108,101,32,110,97, - 109,101,32,116,111,32,97,110,32,97,98,115,111,108,117,116, - 101,32,111,110,101,46,114,117,0,0,0,114,33,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,19,0,0,0,122,5,123,125,46,123,125, - 41,4,218,6,114,115,112,108,105,116,218,3,108,101,110,218, - 10,86,97,108,117,101,69,114,114,111,114,114,38,0,0,0, - 41,5,114,15,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,96,3,0,0,115,10,0,0,0,0,2,16,1,12,1, - 8,1,8,1,114,162,0,0,0,99,3,0,0,0,0,0, - 0,0,4,0,0,0,4,0,0,0,67,0,0,0,115,34, - 0,0,0,124,0,160,0,124,1,124,2,161,2,125,3,124, - 3,100,0,107,8,114,24,100,0,83,0,116,1,124,1,124, - 3,131,2,83,0,41,1,78,41,2,114,146,0,0,0,114, - 78,0,0,0,41,4,218,6,102,105,110,100,101,114,114,15, - 0,0,0,114,143,0,0,0,114,93,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,105, - 3,0,0,115,8,0,0,0,0,3,12,1,8,1,4,1, - 114,164,0,0,0,99,3,0,0,0,0,0,0,0,10,0, - 0,0,10,0,0,0,67,0,0,0,115,12,1,0,0,116, - 0,106,1,125,3,124,3,100,1,107,8,114,22,116,2,100, - 2,131,1,130,1,124,3,115,38,116,3,160,4,100,3,116, - 5,161,2,1,0,124,0,116,0,106,6,107,6,125,4,124, - 3,68,0,93,210,125,5,116,7,131,0,143,84,1,0,122, - 10,124,5,106,8,125,6,87,0,110,54,4,0,116,9,107, - 10,114,128,1,0,1,0,1,0,116,10,124,5,124,0,124, - 1,131,3,125,7,124,7,100,1,107,8,114,124,89,0,87, - 0,53,0,81,0,82,0,163,0,113,52,89,0,110,14,88, - 0,124,6,124,0,124,1,124,2,131,3,125,7,87,0,53, - 0,81,0,82,0,88,0,124,7,100,1,107,9,114,52,124, - 4,144,0,115,254,124,0,116,0,106,6,107,6,144,0,114, - 254,116,0,106,6,124,0,25,0,125,8,122,10,124,8,106, - 11,125,9,87,0,110,28,4,0,116,9,107,10,114,226,1, - 0,1,0,1,0,124,7,6,0,89,0,2,0,1,0,83, - 0,88,0,124,9,100,1,107,8,114,244,124,7,2,0,1, - 0,83,0,124,9,2,0,1,0,83,0,113,52,124,7,2, - 0,1,0,83,0,113,52,100,1,83,0,41,4,122,21,70, - 105,110,100,32,97,32,109,111,100,117,108,101,39,115,32,115, - 112,101,99,46,78,122,53,115,121,115,46,109,101,116,97,95, - 112,97,116,104,32,105,115,32,78,111,110,101,44,32,80,121, - 116,104,111,110,32,105,115,32,108,105,107,101,108,121,32,115, - 104,117,116,116,105,110,103,32,100,111,119,110,122,22,115,121, - 115,46,109,101,116,97,95,112,97,116,104,32,105,115,32,101, - 109,112,116,121,41,12,114,14,0,0,0,218,9,109,101,116, - 97,95,112,97,116,104,114,70,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,79,0,0,0, - 114,156,0,0,0,114,145,0,0,0,114,90,0,0,0,114, - 164,0,0,0,114,89,0,0,0,41,10,114,15,0,0,0, - 114,143,0,0,0,114,144,0,0,0,114,165,0,0,0,90, - 9,105,115,95,114,101,108,111,97,100,114,163,0,0,0,114, - 145,0,0,0,114,82,0,0,0,114,83,0,0,0,114,89, + 114,10,0,0,0,114,11,0,0,0,114,137,0,0,0,53, + 3,0,0,115,2,0,0,0,0,7,122,26,70,114,111,122, + 101,110,73,109,112,111,114,116,101,114,46,108,111,97,100,95, + 109,111,100,117,108,101,99,2,0,0,0,0,0,0,0,2, + 0,0,0,3,0,0,0,67,0,0,0,115,10,0,0,0, + 116,0,160,1,124,1,161,1,83,0,41,1,122,45,82,101, + 116,117,114,110,32,116,104,101,32,99,111,100,101,32,111,98, + 106,101,99,116,32,102,111,114,32,116,104,101,32,102,114,111, + 122,101,110,32,109,111,100,117,108,101,46,41,2,114,49,0, + 0,0,114,153,0,0,0,41,2,114,142,0,0,0,114,71, 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,114,3, - 0,0,115,54,0,0,0,0,2,6,1,8,2,8,3,4, - 1,12,5,10,1,8,1,8,1,2,1,10,1,14,1,12, - 1,8,1,20,2,22,1,8,2,18,1,10,1,2,1,10, - 1,14,4,14,2,8,1,8,2,10,2,10,2,114,169,0, - 0,0,99,3,0,0,0,0,0,0,0,3,0,0,0,5, - 0,0,0,67,0,0,0,115,108,0,0,0,116,0,124,0, - 116,1,131,2,115,28,116,2,100,1,160,3,116,4,124,0, - 131,1,161,1,131,1,130,1,124,2,100,2,107,0,114,44, - 116,5,100,3,131,1,130,1,124,2,100,2,107,4,114,84, - 116,0,124,1,116,1,131,2,115,72,116,2,100,4,131,1, - 130,1,110,12,124,1,115,84,116,6,100,5,131,1,130,1, - 124,0,115,104,124,2,100,2,107,2,114,104,116,5,100,6, - 131,1,130,1,100,7,83,0,41,8,122,28,86,101,114,105, - 102,121,32,97,114,103,117,109,101,110,116,115,32,97,114,101, - 32,34,115,97,110,101,34,46,122,31,109,111,100,117,108,101, - 32,110,97,109,101,32,109,117,115,116,32,98,101,32,115,116, - 114,44,32,110,111,116,32,123,125,114,19,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,38,0, - 0,0,114,13,0,0,0,114,159,0,0,0,114,70,0,0, - 0,41,3,114,15,0,0,0,114,160,0,0,0,114,161,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, - 161,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, - 173,0,0,0,122,16,78,111,32,109,111,100,117,108,101,32, - 110,97,109,101,100,32,122,4,123,33,114,125,99,2,0,0, - 0,0,0,0,0,8,0,0,0,8,0,0,0,67,0,0, - 0,115,220,0,0,0,100,0,125,2,124,0,160,0,100,1, - 161,1,100,2,25,0,125,3,124,3,114,134,124,3,116,1, - 106,2,107,7,114,42,116,3,124,1,124,3,131,2,1,0, - 124,0,116,1,106,2,107,6,114,62,116,1,106,2,124,0, - 25,0,83,0,116,1,106,2,124,3,25,0,125,4,122,10, - 124,4,106,4,125,2,87,0,110,50,4,0,116,5,107,10, - 114,132,1,0,1,0,1,0,116,6,100,3,23,0,160,7, - 124,0,124,3,161,2,125,5,116,8,124,5,124,0,100,4, - 141,2,100,0,130,2,89,0,110,2,88,0,116,9,124,0, - 124,2,131,2,125,6,124,6,100,0,107,8,114,172,116,8, - 116,6,160,7,124,0,161,1,124,0,100,4,141,2,130,1, - 110,8,116,10,124,6,131,1,125,7,124,3,114,216,116,1, - 106,2,124,3,25,0,125,4,116,11,124,4,124,0,160,0, - 100,1,161,1,100,5,25,0,124,7,131,3,1,0,124,7, - 83,0,41,6,78,114,117,0,0,0,114,19,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,41,1,114,15,0,0,0,233, - 2,0,0,0,41,12,114,118,0,0,0,114,14,0,0,0, - 114,79,0,0,0,114,59,0,0,0,114,127,0,0,0,114, - 90,0,0,0,218,8,95,69,82,82,95,77,83,71,114,38, - 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,169,0,0,0,114,140,0, - 0,0,114,5,0,0,0,41,8,114,15,0,0,0,218,7, - 105,109,112,111,114,116,95,114,143,0,0,0,114,119,0,0, - 0,90,13,112,97,114,101,110,116,95,109,111,100,117,108,101, - 114,138,0,0,0,114,82,0,0,0,114,83,0,0,0,114, - 10,0,0,0,114,10,0,0,0,114,11,0,0,0,218,23, - 95,102,105,110,100,95,97,110,100,95,108,111,97,100,95,117, - 110,108,111,99,107,101,100,180,3,0,0,115,42,0,0,0, - 0,1,4,1,14,1,4,1,10,1,10,2,10,1,10,1, - 10,1,2,1,10,1,14,1,16,1,20,1,10,1,8,1, - 20,2,8,1,4,2,10,1,22,1,114,178,0,0,0,99, - 2,0,0,0,0,0,0,0,4,0,0,0,10,0,0,0, - 67,0,0,0,115,106,0,0,0,116,0,124,0,131,1,143, - 50,1,0,116,1,106,2,160,3,124,0,116,4,161,2,125, - 2,124,2,116,4,107,8,114,54,116,5,124,0,124,1,131, - 2,87,0,2,0,53,0,81,0,82,0,163,0,83,0,87, - 0,53,0,81,0,82,0,88,0,124,2,100,1,107,8,114, - 94,100,2,160,6,124,0,161,1,125,3,116,7,124,3,124, - 0,100,3,141,2,130,1,116,8,124,0,131,1,1,0,124, - 2,83,0,41,4,122,25,70,105,110,100,32,97,110,100,32, - 108,111,97,100,32,116,104,101,32,109,111,100,117,108,101,46, - 78,122,40,105,109,112,111,114,116,32,111,102,32,123,125,32, - 104,97,108,116,101,100,59,32,78,111,110,101,32,105,110,32, - 115,121,115,46,109,111,100,117,108,101,115,41,1,114,15,0, - 0,0,41,9,114,42,0,0,0,114,14,0,0,0,114,79, - 0,0,0,114,30,0,0,0,218,14,95,78,69,69,68,83, - 95,76,79,65,68,73,78,71,114,178,0,0,0,114,38,0, - 0,0,114,176,0,0,0,114,57,0,0,0,41,4,114,15, - 0,0,0,114,177,0,0,0,114,83,0,0,0,114,67,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,210,3,0,0,115,20,0,0,0,0,2,10,1,14,1, - 8,1,32,2,8,1,4,1,6,1,12,2,8,1,114,180, - 0,0,0,114,19,0,0,0,99,3,0,0,0,0,0,0, - 0,3,0,0,0,4,0,0,0,67,0,0,0,115,42,0, - 0,0,116,0,124,0,124,1,124,2,131,3,1,0,124,2, - 100,1,107,4,114,32,116,1,124,0,124,1,124,2,131,3, - 125,0,116,2,124,0,116,3,131,2,83,0,41,2,97,50, - 1,0,0,73,109,112,111,114,116,32,97,110,100,32,114,101, - 116,117,114,110,32,116,104,101,32,109,111,100,117,108,101,32, - 98,97,115,101,100,32,111,110,32,105,116,115,32,110,97,109, - 101,44,32,116,104,101,32,112,97,99,107,97,103,101,32,116, - 104,101,32,99,97,108,108,32,105,115,10,32,32,32,32,98, - 101,105,110,103,32,109,97,100,101,32,102,114,111,109,44,32, - 97,110,100,32,116,104,101,32,108,101,118,101,108,32,97,100, - 106,117,115,116,109,101,110,116,46,10,10,32,32,32,32,84, - 104,105,115,32,102,117,110,99,116,105,111,110,32,114,101,112, - 114,101,115,101,110,116,115,32,116,104,101,32,103,114,101,97, - 116,101,115,116,32,99,111,109,109,111,110,32,100,101,110,111, - 109,105,110,97,116,111,114,32,111,102,32,102,117,110,99,116, - 105,111,110,97,108,105,116,121,10,32,32,32,32,98,101,116, - 119,101,101,110,32,105,109,112,111,114,116,95,109,111,100,117, - 108,101,32,97,110,100,32,95,95,105,109,112,111,114,116,95, - 95,46,32,84,104,105,115,32,105,110,99,108,117,100,101,115, - 32,115,101,116,116,105,110,103,32,95,95,112,97,99,107,97, - 103,101,95,95,32,105,102,10,32,32,32,32,116,104,101,32, - 108,111,97,100,101,114,32,100,105,100,32,110,111,116,46,10, - 10,32,32,32,32,114,19,0,0,0,41,4,114,173,0,0, - 0,114,162,0,0,0,114,180,0,0,0,218,11,95,103,99, - 100,95,105,109,112,111,114,116,41,3,114,15,0,0,0,114, - 160,0,0,0,114,161,0,0,0,114,10,0,0,0,114,10, - 0,0,0,114,11,0,0,0,114,181,0,0,0,226,3,0, - 0,115,8,0,0,0,0,9,12,1,8,1,12,1,114,181, - 0,0,0,41,1,218,9,114,101,99,117,114,115,105,118,101, - 99,3,0,0,0,1,0,0,0,8,0,0,0,11,0,0, - 0,67,0,0,0,115,226,0,0,0,124,1,68,0,93,216, - 125,4,116,0,124,4,116,1,131,2,115,66,124,3,114,34, - 124,0,106,2,100,1,23,0,125,5,110,4,100,2,125,5, - 116,3,100,3,124,5,155,0,100,4,116,4,124,4,131,1, - 106,2,155,0,157,4,131,1,130,1,113,4,124,4,100,5, - 107,2,114,108,124,3,115,220,116,5,124,0,100,6,131,2, - 114,220,116,6,124,0,124,0,106,7,124,2,100,7,100,8, - 141,4,1,0,113,4,116,5,124,0,124,4,131,2,115,4, - 100,9,160,8,124,0,106,2,124,4,161,2,125,6,122,14, - 116,9,124,2,124,6,131,2,1,0,87,0,113,4,4,0, - 116,10,107,10,114,218,1,0,125,7,1,0,122,42,124,7, - 106,11,124,6,107,2,114,200,116,12,106,13,160,14,124,6, - 116,15,161,2,100,10,107,9,114,200,87,0,89,0,162,8, - 113,4,130,0,87,0,53,0,100,10,125,7,126,7,88,0, - 89,0,113,4,88,0,113,4,124,0,83,0,41,11,122,238, - 70,105,103,117,114,101,32,111,117,116,32,119,104,97,116,32, - 95,95,105,109,112,111,114,116,95,95,32,115,104,111,117,108, - 100,32,114,101,116,117,114,110,46,10,10,32,32,32,32,84, - 104,101,32,105,109,112,111,114,116,95,32,112,97,114,97,109, - 101,116,101,114,32,105,115,32,97,32,99,97,108,108,97,98, - 108,101,32,119,104,105,99,104,32,116,97,107,101,115,32,116, - 104,101,32,110,97,109,101,32,111,102,32,109,111,100,117,108, - 101,32,116,111,10,32,32,32,32,105,109,112,111,114,116,46, - 32,73,116,32,105,115,32,114,101,113,117,105,114,101,100,32, - 116,111,32,100,101,99,111,117,112,108,101,32,116,104,101,32, - 102,117,110,99,116,105,111,110,32,102,114,111,109,32,97,115, - 115,117,109,105,110,103,32,105,109,112,111,114,116,108,105,98, - 39,115,10,32,32,32,32,105,109,112,111,114,116,32,105,109, - 112,108,101,109,101,110,116,97,116,105,111,110,32,105,115,32, - 100,101,115,105,114,101,100,46,10,10,32,32,32,32,122,8, - 46,95,95,97,108,108,95,95,122,13,96,96,102,114,111,109, - 32,108,105,115,116,39,39,122,8,73,116,101,109,32,105,110, - 32,122,18,32,109,117,115,116,32,98,101,32,115,116,114,44, - 32,110,111,116,32,250,1,42,218,7,95,95,97,108,108,95, - 95,84,41,1,114,182,0,0,0,122,5,123,125,46,123,125, - 78,41,16,114,170,0,0,0,114,171,0,0,0,114,1,0, - 0,0,114,172,0,0,0,114,13,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,184,0,0,0,114,38,0,0,0,114,59,0, - 0,0,114,176,0,0,0,114,15,0,0,0,114,14,0,0, - 0,114,79,0,0,0,114,30,0,0,0,114,179,0,0,0, - 41,8,114,83,0,0,0,218,8,102,114,111,109,108,105,115, - 116,114,177,0,0,0,114,182,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,185,0,0,0,241,3,0,0,115,40,0, - 0,0,0,10,8,1,10,1,4,1,12,2,4,1,28,2, - 8,1,14,1,10,1,10,1,10,1,14,1,2,1,14,1, - 16,4,10,1,18,1,8,1,22,1,114,185,0,0,0,99, - 1,0,0,0,0,0,0,0,3,0,0,0,6,0,0,0, - 67,0,0,0,115,146,0,0,0,124,0,160,0,100,1,161, - 1,125,1,124,0,160,0,100,2,161,1,125,2,124,1,100, - 3,107,9,114,82,124,2,100,3,107,9,114,78,124,1,124, - 2,106,1,107,3,114,78,116,2,106,3,100,4,124,1,155, - 2,100,5,124,2,106,1,155,2,100,6,157,5,116,4,100, - 7,100,8,141,3,1,0,124,1,83,0,124,2,100,3,107, - 9,114,96,124,2,106,1,83,0,116,2,106,3,100,9,116, - 4,100,7,100,8,141,3,1,0,124,0,100,10,25,0,125, - 1,100,11,124,0,107,7,114,142,124,1,160,5,100,12,161, - 1,100,13,25,0,125,1,124,1,83,0,41,14,122,167,67, - 97,108,99,117,108,97,116,101,32,119,104,97,116,32,95,95, - 112,97,99,107,97,103,101,95,95,32,115,104,111,117,108,100, - 32,98,101,46,10,10,32,32,32,32,95,95,112,97,99,107, - 97,103,101,95,95,32,105,115,32,110,111,116,32,103,117,97, - 114,97,110,116,101,101,100,32,116,111,32,98,101,32,100,101, - 102,105,110,101,100,32,111,114,32,99,111,117,108,100,32,98, - 101,32,115,101,116,32,116,111,32,78,111,110,101,10,32,32, - 32,32,116,111,32,114,101,112,114,101,115,101,110,116,32,116, - 104,97,116,32,105,116,115,32,112,114,111,112,101,114,32,118, - 97,108,117,101,32,105,115,32,117,110,107,110,111,119,110,46, - 10,10,32,32,32,32,114,130,0,0,0,114,89,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, - 127,0,0,0,114,117,0,0,0,114,19,0,0,0,41,6, - 114,30,0,0,0,114,119,0,0,0,114,166,0,0,0,114, - 167,0,0,0,114,168,0,0,0,114,118,0,0,0,41,3, - 218,7,103,108,111,98,97,108,115,114,160,0,0,0,114,82, + 0,0,114,147,0,0,0,62,3,0,0,115,2,0,0,0, + 0,4,122,23,70,114,111,122,101,110,73,109,112,111,114,116, + 101,114,46,103,101,116,95,99,111,100,101,99,2,0,0,0, + 0,0,0,0,2,0,0,0,1,0,0,0,67,0,0,0, + 115,4,0,0,0,100,1,83,0,41,2,122,54,82,101,116, + 117,114,110,32,78,111,110,101,32,97,115,32,102,114,111,122, + 101,110,32,109,111,100,117,108,101,115,32,100,111,32,110,111, + 116,32,104,97,118,101,32,115,111,117,114,99,101,32,99,111, + 100,101,46,78,114,10,0,0,0,41,2,114,142,0,0,0, + 114,71,0,0,0,114,10,0,0,0,114,10,0,0,0,114, + 11,0,0,0,114,148,0,0,0,68,3,0,0,115,2,0, + 0,0,0,4,122,25,70,114,111,122,101,110,73,109,112,111, + 114,116,101,114,46,103,101,116,95,115,111,117,114,99,101,99, + 2,0,0,0,0,0,0,0,2,0,0,0,3,0,0,0, + 67,0,0,0,115,10,0,0,0,116,0,160,1,124,1,161, + 1,83,0,41,1,122,46,82,101,116,117,114,110,32,84,114, + 117,101,32,105,102,32,116,104,101,32,102,114,111,122,101,110, + 32,109,111,100,117,108,101,32,105,115,32,97,32,112,97,99, + 107,97,103,101,46,41,2,114,49,0,0,0,90,17,105,115, + 95,102,114,111,122,101,110,95,112,97,99,107,97,103,101,41, + 2,114,142,0,0,0,114,71,0,0,0,114,10,0,0,0, + 114,10,0,0,0,114,11,0,0,0,114,105,0,0,0,74, + 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,16,114,1, + 0,0,0,114,0,0,0,0,114,2,0,0,0,114,3,0, + 0,0,114,149,0,0,0,114,86,0,0,0,114,150,0,0, + 0,114,145,0,0,0,114,146,0,0,0,114,134,0,0,0, + 114,135,0,0,0,114,137,0,0,0,114,77,0,0,0,114, + 147,0,0,0,114,148,0,0,0,114,105,0,0,0,114,10, 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,22,4,0,0,115,30,0,0,0,0,7, - 10,1,10,1,8,1,18,1,22,2,10,1,4,1,8,1, - 6,2,6,2,10,1,8,1,8,1,14,1,114,191,0,0, - 0,114,10,0,0,0,99,5,0,0,0,0,0,0,0,9, - 0,0,0,5,0,0,0,67,0,0,0,115,180,0,0,0, - 124,4,100,1,107,2,114,18,116,0,124,0,131,1,125,5, - 110,36,124,1,100,2,107,9,114,30,124,1,110,2,105,0, - 125,6,116,1,124,6,131,1,125,7,116,0,124,0,124,7, - 124,4,131,3,125,5,124,3,115,150,124,4,100,1,107,2, - 114,84,116,0,124,0,160,2,100,3,161,1,100,1,25,0, - 131,1,83,0,124,0,115,92,124,5,83,0,116,3,124,0, - 131,1,116,3,124,0,160,2,100,3,161,1,100,1,25,0, - 131,1,24,0,125,8,116,4,106,5,124,5,106,6,100,2, - 116,3,124,5,106,6,131,1,124,8,24,0,133,2,25,0, - 25,0,83,0,110,26,116,7,124,5,100,4,131,2,114,172, - 116,8,124,5,124,3,116,0,131,3,83,0,124,5,83,0, - 100,2,83,0,41,5,97,215,1,0,0,73,109,112,111,114, - 116,32,97,32,109,111,100,117,108,101,46,10,10,32,32,32, - 32,84,104,101,32,39,103,108,111,98,97,108,115,39,32,97, - 114,103,117,109,101,110,116,32,105,115,32,117,115,101,100,32, - 116,111,32,105,110,102,101,114,32,119,104,101,114,101,32,116, - 104,101,32,105,109,112,111,114,116,32,105,115,32,111,99,99, - 117,114,114,105,110,103,32,102,114,111,109,10,32,32,32,32, - 116,111,32,104,97,110,100,108,101,32,114,101,108,97,116,105, - 118,101,32,105,109,112,111,114,116,115,46,32,84,104,101,32, - 39,108,111,99,97,108,115,39,32,97,114,103,117,109,101,110, - 116,32,105,115,32,105,103,110,111,114,101,100,46,32,84,104, - 101,10,32,32,32,32,39,102,114,111,109,108,105,115,116,39, - 32,97,114,103,117,109,101,110,116,32,115,112,101,99,105,102, - 105,101,115,32,119,104,97,116,32,115,104,111,117,108,100,32, - 101,120,105,115,116,32,97,115,32,97,116,116,114,105,98,117, - 116,101,115,32,111,110,32,116,104,101,32,109,111,100,117,108, - 101,10,32,32,32,32,98,101,105,110,103,32,105,109,112,111, - 114,116,101,100,32,40,101,46,103,46,32,96,96,102,114,111, - 109,32,109,111,100,117,108,101,32,105,109,112,111,114,116,32, - 60,102,114,111,109,108,105,115,116,62,96,96,41,46,32,32, - 84,104,101,32,39,108,101,118,101,108,39,10,32,32,32,32, - 97,114,103,117,109,101,110,116,32,114,101,112,114,101,115,101, - 110,116,115,32,116,104,101,32,112,97,99,107,97,103,101,32, - 108,111,99,97,116,105,111,110,32,116,111,32,105,109,112,111, - 114,116,32,102,114,111,109,32,105,110,32,97,32,114,101,108, - 97,116,105,118,101,10,32,32,32,32,105,109,112,111,114,116, - 32,40,101,46,103,46,32,96,96,102,114,111,109,32,46,46, - 112,107,103,32,105,109,112,111,114,116,32,109,111,100,96,96, - 32,119,111,117,108,100,32,104,97,118,101,32,97,32,39,108, - 101,118,101,108,39,32,111,102,32,50,41,46,10,10,32,32, - 32,32,114,19,0,0,0,78,114,117,0,0,0,114,127,0, - 0,0,41,9,114,181,0,0,0,114,191,0,0,0,218,9, - 112,97,114,116,105,116,105,111,110,114,158,0,0,0,114,14, - 0,0,0,114,79,0,0,0,114,1,0,0,0,114,4,0, - 0,0,114,185,0,0,0,41,9,114,15,0,0,0,114,190, - 0,0,0,218,6,108,111,99,97,108,115,114,186,0,0,0, - 114,161,0,0,0,114,83,0,0,0,90,8,103,108,111,98, - 97,108,115,95,114,160,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,49,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,194,0,0,0,99,1,0,0,0,0,0, - 0,0,2,0,0,0,3,0,0,0,67,0,0,0,115,38, - 0,0,0,116,0,160,1,124,0,161,1,125,1,124,1,100, - 0,107,8,114,30,116,2,100,1,124,0,23,0,131,1,130, - 1,116,3,124,1,131,1,83,0,41,2,78,122,25,110,111, - 32,98,117,105,108,116,45,105,110,32,109,111,100,117,108,101, - 32,110,97,109,101,100,32,41,4,114,141,0,0,0,114,145, - 0,0,0,114,70,0,0,0,114,140,0,0,0,41,2,114, - 15,0,0,0,114,82,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,86,4,0,0, - 115,8,0,0,0,0,1,10,1,8,1,12,1,114,195,0, - 0,0,99,2,0,0,0,0,0,0,0,10,0,0,0,5, - 0,0,0,67,0,0,0,115,166,0,0,0,124,1,97,0, - 124,0,97,1,116,2,116,1,131,1,125,2,116,1,106,3, - 160,4,161,0,68,0,93,72,92,2,125,3,125,4,116,5, - 124,4,124,2,131,2,114,26,124,3,116,1,106,6,107,6, - 114,60,116,7,125,5,110,18,116,0,160,8,124,3,161,1, - 114,26,116,9,125,5,110,2,113,26,116,10,124,4,124,5, - 131,2,125,6,116,11,124,6,124,4,131,2,1,0,113,26, - 116,1,106,3,116,12,25,0,125,7,100,1,68,0,93,46, - 125,8,124,8,116,1,106,3,107,7,114,138,116,13,124,8, - 131,1,125,9,110,10,116,1,106,3,124,8,25,0,125,9, - 116,14,124,7,124,8,124,9,131,3,1,0,113,114,100,2, - 83,0,41,3,122,250,83,101,116,117,112,32,105,109,112,111, - 114,116,108,105,98,32,98,121,32,105,109,112,111,114,116,105, - 110,103,32,110,101,101,100,101,100,32,98,117,105,108,116,45, - 105,110,32,109,111,100,117,108,101,115,32,97,110,100,32,105, - 110,106,101,99,116,105,110,103,32,116,104,101,109,10,32,32, - 32,32,105,110,116,111,32,116,104,101,32,103,108,111,98,97, - 108,32,110,97,109,101,115,112,97,99,101,46,10,10,32,32, - 32,32,65,115,32,115,121,115,32,105,115,32,110,101,101,100, - 101,100,32,102,111,114,32,115,121,115,46,109,111,100,117,108, - 101,115,32,97,99,99,101,115,115,32,97,110,100,32,95,105, - 109,112,32,105,115,32,110,101,101,100,101,100,32,116,111,32, - 108,111,97,100,32,98,117,105,108,116,45,105,110,10,32,32, - 32,32,109,111,100,117,108,101,115,44,32,116,104,111,115,101, - 32,116,119,111,32,109,111,100,117,108,101,115,32,109,117,115, - 116,32,98,101,32,101,120,112,108,105,99,105,116,108,121,32, - 112,97,115,115,101,100,32,105,110,46,10,10,32,32,32,32, - 41,3,114,20,0,0,0,114,166,0,0,0,114,56,0,0, - 0,78,41,15,114,49,0,0,0,114,14,0,0,0,114,13, - 0,0,0,114,79,0,0,0,218,5,105,116,101,109,115,114, - 170,0,0,0,114,69,0,0,0,114,141,0,0,0,114,75, - 0,0,0,114,151,0,0,0,114,128,0,0,0,114,133,0, - 0,0,114,1,0,0,0,114,195,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,15,0,0,0,114,83, - 0,0,0,114,93,0,0,0,114,82,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,93, - 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,199,0,0, - 0,99,2,0,0,0,0,0,0,0,2,0,0,0,3,0, - 0,0,67,0,0,0,115,38,0,0,0,116,0,124,0,124, - 1,131,2,1,0,116,1,106,2,160,3,116,4,161,1,1, - 0,116,1,106,2,160,3,116,5,161,1,1,0,100,1,83, - 0,41,2,122,48,73,110,115,116,97,108,108,32,105,109,112, - 111,114,116,101,114,115,32,102,111,114,32,98,117,105,108,116, - 105,110,32,97,110,100,32,102,114,111,122,101,110,32,109,111, - 100,117,108,101,115,78,41,6,114,199,0,0,0,114,14,0, - 0,0,114,165,0,0,0,114,109,0,0,0,114,141,0,0, - 0,114,151,0,0,0,41,2,114,197,0,0,0,114,198,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,128,4,0,0,115, - 6,0,0,0,0,2,10,2,12,1,114,200,0,0,0,99, - 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,19,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,115,0,0,0,114, - 200,0,0,0,114,14,0,0,0,114,79,0,0,0,114,1, - 0,0,0,41,1,114,201,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,136,4,0,0,115,6,0,0,0,0, - 3,8,1,4,1,114,202,0,0,0,41,2,78,78,41,1, - 78,41,2,78,114,19,0,0,0,41,4,78,78,114,10,0, - 0,0,114,19,0,0,0,41,51,114,3,0,0,0,114,115, - 0,0,0,114,12,0,0,0,114,16,0,0,0,114,51,0, - 0,0,114,29,0,0,0,114,36,0,0,0,114,17,0,0, - 0,114,18,0,0,0,114,41,0,0,0,114,42,0,0,0, - 114,45,0,0,0,114,57,0,0,0,114,59,0,0,0,114, - 68,0,0,0,114,74,0,0,0,114,77,0,0,0,114,84, - 0,0,0,114,95,0,0,0,114,96,0,0,0,114,102,0, - 0,0,114,78,0,0,0,114,128,0,0,0,114,133,0,0, - 0,114,136,0,0,0,114,91,0,0,0,114,80,0,0,0, - 114,139,0,0,0,114,140,0,0,0,114,81,0,0,0,114, - 141,0,0,0,114,151,0,0,0,114,156,0,0,0,114,162, - 0,0,0,114,164,0,0,0,114,169,0,0,0,114,173,0, - 0,0,90,15,95,69,82,82,95,77,83,71,95,80,82,69, - 70,73,88,114,175,0,0,0,114,178,0,0,0,218,6,111, - 98,106,101,99,116,114,179,0,0,0,114,180,0,0,0,114, - 181,0,0,0,114,185,0,0,0,114,191,0,0,0,114,194, - 0,0,0,114,195,0,0,0,114,199,0,0,0,114,200,0, - 0,0,114,202,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,25,0,0,0,115,96,0,0,0,4,0, - 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,27,14,101,16,26,10,45,14,72,8,17,8,17, - 8,24,8,29,8,23,8,15,14,73,14,77,14,13,8,9, - 8,9,10,47,8,16,4,1,8,2,8,27,6,3,8,16, - 10,15,14,37,8,27,10,37,8,7,8,35,8,8, + 0,0,114,151,0,0,0,6,3,0,0,115,30,0,0,0, + 8,7,4,2,12,9,2,1,12,6,2,1,12,8,12,4, + 12,9,12,9,2,1,14,5,2,1,14,5,2,1,114,151, + 0,0,0,99,0,0,0,0,0,0,0,0,0,0,0,0, + 2,0,0,0,64,0,0,0,115,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,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,49, + 0,0,0,114,50,0,0,0,41,1,114,26,0,0,0,114, + 10,0,0,0,114,10,0,0,0,114,11,0,0,0,114,46, + 0,0,0,87,3,0,0,115,2,0,0,0,0,2,122,28, + 95,73,109,112,111,114,116,76,111,99,107,67,111,110,116,101, + 120,116,46,95,95,101,110,116,101,114,95,95,99,4,0,0, + 0,0,0,0,0,4,0,0,0,2,0,0,0,67,0,0, + 0,115,12,0,0,0,116,0,160,1,161,0,1,0,100,1, + 83,0,41,2,122,60,82,101,108,101,97,115,101,32,116,104, + 101,32,105,109,112,111,114,116,32,108,111,99,107,32,114,101, + 103,97,114,100,108,101,115,115,32,111,102,32,97,110,121,32, + 114,97,105,115,101,100,32,101,120,99,101,112,116,105,111,110, + 115,46,78,41,2,114,49,0,0,0,114,52,0,0,0,41, + 4,114,26,0,0,0,90,8,101,120,99,95,116,121,112,101, + 90,9,101,120,99,95,118,97,108,117,101,90,13,101,120,99, + 95,116,114,97,99,101,98,97,99,107,114,10,0,0,0,114, + 10,0,0,0,114,11,0,0,0,114,48,0,0,0,91,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,46,0, + 0,0,114,48,0,0,0,114,10,0,0,0,114,10,0,0, + 0,114,10,0,0,0,114,11,0,0,0,114,156,0,0,0, + 83,3,0,0,115,6,0,0,0,8,2,4,2,8,4,114, + 156,0,0,0,99,3,0,0,0,0,0,0,0,5,0,0, + 0,5,0,0,0,67,0,0,0,115,64,0,0,0,124,1, + 160,0,100,1,124,2,100,2,24,0,161,2,125,3,116,1, + 124,3,131,1,124,2,107,0,114,36,116,2,100,3,131,1, + 130,1,124,3,100,4,25,0,125,4,124,0,114,60,100,5, + 160,3,124,4,124,0,161,2,83,0,124,4,83,0,41,6, + 122,50,82,101,115,111,108,118,101,32,97,32,114,101,108,97, + 116,105,118,101,32,109,111,100,117,108,101,32,110,97,109,101, + 32,116,111,32,97,110,32,97,98,115,111,108,117,116,101,32, + 111,110,101,46,114,117,0,0,0,114,33,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,19,0,0,0,122,5,123,125,46,123,125,41,4, + 218,6,114,115,112,108,105,116,218,3,108,101,110,218,10,86, + 97,108,117,101,69,114,114,111,114,114,38,0,0,0,41,5, + 114,15,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,96, + 3,0,0,115,10,0,0,0,0,2,16,1,12,1,8,1, + 8,1,114,162,0,0,0,99,3,0,0,0,0,0,0,0, + 4,0,0,0,4,0,0,0,67,0,0,0,115,34,0,0, + 0,124,0,160,0,124,1,124,2,161,2,125,3,124,3,100, + 0,107,8,114,24,100,0,83,0,116,1,124,1,124,3,131, + 2,83,0,41,1,78,41,2,114,146,0,0,0,114,78,0, + 0,0,41,4,218,6,102,105,110,100,101,114,114,15,0,0, + 0,114,143,0,0,0,114,93,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,105,3,0, + 0,115,8,0,0,0,0,3,12,1,8,1,4,1,114,164, + 0,0,0,99,3,0,0,0,0,0,0,0,10,0,0,0, + 10,0,0,0,67,0,0,0,115,12,1,0,0,116,0,106, + 1,125,3,124,3,100,1,107,8,114,22,116,2,100,2,131, + 1,130,1,124,3,115,38,116,3,160,4,100,3,116,5,161, + 2,1,0,124,0,116,0,106,6,107,6,125,4,124,3,68, + 0,93,210,125,5,116,7,131,0,143,84,1,0,122,10,124, + 5,106,8,125,6,87,0,110,54,4,0,116,9,107,10,114, + 128,1,0,1,0,1,0,116,10,124,5,124,0,124,1,131, + 3,125,7,124,7,100,1,107,8,114,124,89,0,87,0,53, + 0,81,0,82,0,163,0,113,52,89,0,110,14,88,0,124, + 6,124,0,124,1,124,2,131,3,125,7,87,0,53,0,81, + 0,82,0,88,0,124,7,100,1,107,9,114,52,124,4,144, + 0,115,254,124,0,116,0,106,6,107,6,144,0,114,254,116, + 0,106,6,124,0,25,0,125,8,122,10,124,8,106,11,125, + 9,87,0,110,28,4,0,116,9,107,10,114,226,1,0,1, + 0,1,0,124,7,6,0,89,0,2,0,1,0,83,0,88, + 0,124,9,100,1,107,8,114,244,124,7,2,0,1,0,83, + 0,124,9,2,0,1,0,83,0,113,52,124,7,2,0,1, + 0,83,0,113,52,100,1,83,0,41,4,122,21,70,105,110, + 100,32,97,32,109,111,100,117,108,101,39,115,32,115,112,101, + 99,46,78,122,53,115,121,115,46,109,101,116,97,95,112,97, + 116,104,32,105,115,32,78,111,110,101,44,32,80,121,116,104, + 111,110,32,105,115,32,108,105,107,101,108,121,32,115,104,117, + 116,116,105,110,103,32,100,111,119,110,122,22,115,121,115,46, + 109,101,116,97,95,112,97,116,104,32,105,115,32,101,109,112, + 116,121,41,12,114,14,0,0,0,218,9,109,101,116,97,95, + 112,97,116,104,114,70,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,79,0,0,0,114,156, + 0,0,0,114,145,0,0,0,114,90,0,0,0,114,164,0, + 0,0,114,89,0,0,0,41,10,114,15,0,0,0,114,143, + 0,0,0,114,144,0,0,0,114,165,0,0,0,90,9,105, + 115,95,114,101,108,111,97,100,114,163,0,0,0,114,145,0, + 0,0,114,82,0,0,0,114,83,0,0,0,114,89,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,114,3,0,0, + 115,54,0,0,0,0,2,6,1,8,2,8,3,4,1,12, + 5,10,1,8,1,8,1,2,1,10,1,14,1,12,1,8, + 1,20,2,22,1,8,2,18,1,10,1,2,1,10,1,14, + 4,14,2,8,1,8,2,10,2,10,2,114,169,0,0,0, + 99,3,0,0,0,0,0,0,0,3,0,0,0,5,0,0, + 0,67,0,0,0,115,108,0,0,0,116,0,124,0,116,1, + 131,2,115,28,116,2,100,1,160,3,116,4,124,0,131,1, + 161,1,131,1,130,1,124,2,100,2,107,0,114,44,116,5, + 100,3,131,1,130,1,124,2,100,2,107,4,114,84,116,0, + 124,1,116,1,131,2,115,72,116,2,100,4,131,1,130,1, + 110,12,124,1,115,84,116,6,100,5,131,1,130,1,124,0, + 115,104,124,2,100,2,107,2,114,104,116,5,100,6,131,1, + 130,1,100,7,83,0,41,8,122,28,86,101,114,105,102,121, + 32,97,114,103,117,109,101,110,116,115,32,97,114,101,32,34, + 115,97,110,101,34,46,122,31,109,111,100,117,108,101,32,110, + 97,109,101,32,109,117,115,116,32,98,101,32,115,116,114,44, + 32,110,111,116,32,123,125,114,19,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,38,0,0,0, + 114,13,0,0,0,114,159,0,0,0,114,70,0,0,0,41, + 3,114,15,0,0,0,114,160,0,0,0,114,161,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,161,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,173,0, + 0,0,122,16,78,111,32,109,111,100,117,108,101,32,110,97, + 109,101,100,32,122,4,123,33,114,125,99,2,0,0,0,0, + 0,0,0,8,0,0,0,8,0,0,0,67,0,0,0,115, + 220,0,0,0,100,0,125,2,124,0,160,0,100,1,161,1, + 100,2,25,0,125,3,124,3,114,134,124,3,116,1,106,2, + 107,7,114,42,116,3,124,1,124,3,131,2,1,0,124,0, + 116,1,106,2,107,6,114,62,116,1,106,2,124,0,25,0, + 83,0,116,1,106,2,124,3,25,0,125,4,122,10,124,4, + 106,4,125,2,87,0,110,50,4,0,116,5,107,10,114,132, + 1,0,1,0,1,0,116,6,100,3,23,0,160,7,124,0, + 124,3,161,2,125,5,116,8,124,5,124,0,100,4,141,2, + 100,0,130,2,89,0,110,2,88,0,116,9,124,0,124,2, + 131,2,125,6,124,6,100,0,107,8,114,172,116,8,116,6, + 160,7,124,0,161,1,124,0,100,4,141,2,130,1,110,8, + 116,10,124,6,131,1,125,7,124,3,114,216,116,1,106,2, + 124,3,25,0,125,4,116,11,124,4,124,0,160,0,100,1, + 161,1,100,5,25,0,124,7,131,3,1,0,124,7,83,0, + 41,6,78,114,117,0,0,0,114,19,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,41,1,114,15,0,0,0,233,2,0, + 0,0,41,12,114,118,0,0,0,114,14,0,0,0,114,79, + 0,0,0,114,59,0,0,0,114,127,0,0,0,114,90,0, + 0,0,218,8,95,69,82,82,95,77,83,71,114,38,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,169,0,0,0,114,140,0,0,0, + 114,5,0,0,0,41,8,114,15,0,0,0,218,7,105,109, + 112,111,114,116,95,114,143,0,0,0,114,119,0,0,0,90, + 13,112,97,114,101,110,116,95,109,111,100,117,108,101,114,138, + 0,0,0,114,82,0,0,0,114,83,0,0,0,114,10,0, + 0,0,114,10,0,0,0,114,11,0,0,0,218,23,95,102, + 105,110,100,95,97,110,100,95,108,111,97,100,95,117,110,108, + 111,99,107,101,100,180,3,0,0,115,42,0,0,0,0,1, + 4,1,14,1,4,1,10,1,10,2,10,1,10,1,10,1, + 2,1,10,1,14,1,16,1,20,1,10,1,8,1,20,2, + 8,1,4,2,10,1,22,1,114,178,0,0,0,99,2,0, + 0,0,0,0,0,0,4,0,0,0,10,0,0,0,67,0, + 0,0,115,106,0,0,0,116,0,124,0,131,1,143,50,1, + 0,116,1,106,2,160,3,124,0,116,4,161,2,125,2,124, + 2,116,4,107,8,114,54,116,5,124,0,124,1,131,2,87, + 0,2,0,53,0,81,0,82,0,163,0,83,0,87,0,53, + 0,81,0,82,0,88,0,124,2,100,1,107,8,114,94,100, + 2,160,6,124,0,161,1,125,3,116,7,124,3,124,0,100, + 3,141,2,130,1,116,8,124,0,131,1,1,0,124,2,83, + 0,41,4,122,25,70,105,110,100,32,97,110,100,32,108,111, + 97,100,32,116,104,101,32,109,111,100,117,108,101,46,78,122, + 40,105,109,112,111,114,116,32,111,102,32,123,125,32,104,97, + 108,116,101,100,59,32,78,111,110,101,32,105,110,32,115,121, + 115,46,109,111,100,117,108,101,115,41,1,114,15,0,0,0, + 41,9,114,42,0,0,0,114,14,0,0,0,114,79,0,0, + 0,114,30,0,0,0,218,14,95,78,69,69,68,83,95,76, + 79,65,68,73,78,71,114,178,0,0,0,114,38,0,0,0, + 114,176,0,0,0,114,57,0,0,0,41,4,114,15,0,0, + 0,114,177,0,0,0,114,83,0,0,0,114,67,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,210, + 3,0,0,115,20,0,0,0,0,2,10,1,14,1,8,1, + 32,2,8,1,4,1,6,1,12,2,8,1,114,180,0,0, + 0,114,19,0,0,0,99,3,0,0,0,0,0,0,0,3, + 0,0,0,4,0,0,0,67,0,0,0,115,42,0,0,0, + 116,0,124,0,124,1,124,2,131,3,1,0,124,2,100,1, + 107,4,114,32,116,1,124,0,124,1,124,2,131,3,125,0, + 116,2,124,0,116,3,131,2,83,0,41,2,97,50,1,0, + 0,73,109,112,111,114,116,32,97,110,100,32,114,101,116,117, + 114,110,32,116,104,101,32,109,111,100,117,108,101,32,98,97, + 115,101,100,32,111,110,32,105,116,115,32,110,97,109,101,44, + 32,116,104,101,32,112,97,99,107,97,103,101,32,116,104,101, + 32,99,97,108,108,32,105,115,10,32,32,32,32,98,101,105, + 110,103,32,109,97,100,101,32,102,114,111,109,44,32,97,110, + 100,32,116,104,101,32,108,101,118,101,108,32,97,100,106,117, + 115,116,109,101,110,116,46,10,10,32,32,32,32,84,104,105, + 115,32,102,117,110,99,116,105,111,110,32,114,101,112,114,101, + 115,101,110,116,115,32,116,104,101,32,103,114,101,97,116,101, + 115,116,32,99,111,109,109,111,110,32,100,101,110,111,109,105, + 110,97,116,111,114,32,111,102,32,102,117,110,99,116,105,111, + 110,97,108,105,116,121,10,32,32,32,32,98,101,116,119,101, + 101,110,32,105,109,112,111,114,116,95,109,111,100,117,108,101, + 32,97,110,100,32,95,95,105,109,112,111,114,116,95,95,46, + 32,84,104,105,115,32,105,110,99,108,117,100,101,115,32,115, + 101,116,116,105,110,103,32,95,95,112,97,99,107,97,103,101, + 95,95,32,105,102,10,32,32,32,32,116,104,101,32,108,111, + 97,100,101,114,32,100,105,100,32,110,111,116,46,10,10,32, + 32,32,32,114,19,0,0,0,41,4,114,173,0,0,0,114, + 162,0,0,0,114,180,0,0,0,218,11,95,103,99,100,95, + 105,109,112,111,114,116,41,3,114,15,0,0,0,114,160,0, + 0,0,114,161,0,0,0,114,10,0,0,0,114,10,0,0, + 0,114,11,0,0,0,114,181,0,0,0,226,3,0,0,115, + 8,0,0,0,0,9,12,1,8,1,12,1,114,181,0,0, + 0,41,1,218,9,114,101,99,117,114,115,105,118,101,99,3, + 0,0,0,1,0,0,0,8,0,0,0,11,0,0,0,67, + 0,0,0,115,226,0,0,0,124,1,68,0,93,216,125,4, + 116,0,124,4,116,1,131,2,115,66,124,3,114,34,124,0, + 106,2,100,1,23,0,125,5,110,4,100,2,125,5,116,3, + 100,3,124,5,155,0,100,4,116,4,124,4,131,1,106,2, + 155,0,157,4,131,1,130,1,113,4,124,4,100,5,107,2, + 114,108,124,3,115,220,116,5,124,0,100,6,131,2,114,220, + 116,6,124,0,124,0,106,7,124,2,100,7,100,8,141,4, + 1,0,113,4,116,5,124,0,124,4,131,2,115,4,100,9, + 160,8,124,0,106,2,124,4,161,2,125,6,122,14,116,9, + 124,2,124,6,131,2,1,0,87,0,113,4,4,0,116,10, + 107,10,114,218,1,0,125,7,1,0,122,42,124,7,106,11, + 124,6,107,2,114,200,116,12,106,13,160,14,124,6,116,15, + 161,2,100,10,107,9,114,200,87,0,89,0,162,8,113,4, + 130,0,87,0,53,0,100,10,125,7,126,7,88,0,89,0, + 113,4,88,0,113,4,124,0,83,0,41,11,122,238,70,105, + 103,117,114,101,32,111,117,116,32,119,104,97,116,32,95,95, + 105,109,112,111,114,116,95,95,32,115,104,111,117,108,100,32, + 114,101,116,117,114,110,46,10,10,32,32,32,32,84,104,101, + 32,105,109,112,111,114,116,95,32,112,97,114,97,109,101,116, + 101,114,32,105,115,32,97,32,99,97,108,108,97,98,108,101, + 32,119,104,105,99,104,32,116,97,107,101,115,32,116,104,101, + 32,110,97,109,101,32,111,102,32,109,111,100,117,108,101,32, + 116,111,10,32,32,32,32,105,109,112,111,114,116,46,32,73, + 116,32,105,115,32,114,101,113,117,105,114,101,100,32,116,111, + 32,100,101,99,111,117,112,108,101,32,116,104,101,32,102,117, + 110,99,116,105,111,110,32,102,114,111,109,32,97,115,115,117, + 109,105,110,103,32,105,109,112,111,114,116,108,105,98,39,115, + 10,32,32,32,32,105,109,112,111,114,116,32,105,109,112,108, + 101,109,101,110,116,97,116,105,111,110,32,105,115,32,100,101, + 115,105,114,101,100,46,10,10,32,32,32,32,122,8,46,95, + 95,97,108,108,95,95,122,13,96,96,102,114,111,109,32,108, + 105,115,116,39,39,122,8,73,116,101,109,32,105,110,32,122, + 18,32,109,117,115,116,32,98,101,32,115,116,114,44,32,110, + 111,116,32,250,1,42,218,7,95,95,97,108,108,95,95,84, + 41,1,114,182,0,0,0,122,5,123,125,46,123,125,78,41, + 16,114,170,0,0,0,114,171,0,0,0,114,1,0,0,0, + 114,172,0,0,0,114,13,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,184,0,0,0,114,38,0,0,0,114,59,0,0,0, + 114,176,0,0,0,114,15,0,0,0,114,14,0,0,0,114, + 79,0,0,0,114,30,0,0,0,114,179,0,0,0,41,8, + 114,83,0,0,0,218,8,102,114,111,109,108,105,115,116,114, + 177,0,0,0,114,182,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,185,0,0,0,241,3,0,0,115,40,0,0,0, + 0,10,8,1,10,1,4,1,12,2,4,1,28,2,8,1, + 14,1,10,1,10,1,10,1,14,1,2,1,14,1,16,4, + 10,1,18,1,8,1,22,1,114,185,0,0,0,99,1,0, + 0,0,0,0,0,0,3,0,0,0,6,0,0,0,67,0, + 0,0,115,146,0,0,0,124,0,160,0,100,1,161,1,125, + 1,124,0,160,0,100,2,161,1,125,2,124,1,100,3,107, + 9,114,82,124,2,100,3,107,9,114,78,124,1,124,2,106, + 1,107,3,114,78,116,2,106,3,100,4,124,1,155,2,100, + 5,124,2,106,1,155,2,100,6,157,5,116,4,100,7,100, + 8,141,3,1,0,124,1,83,0,124,2,100,3,107,9,114, + 96,124,2,106,1,83,0,116,2,106,3,100,9,116,4,100, + 7,100,8,141,3,1,0,124,0,100,10,25,0,125,1,100, + 11,124,0,107,7,114,142,124,1,160,5,100,12,161,1,100, + 13,25,0,125,1,124,1,83,0,41,14,122,167,67,97,108, + 99,117,108,97,116,101,32,119,104,97,116,32,95,95,112,97, + 99,107,97,103,101,95,95,32,115,104,111,117,108,100,32,98, + 101,46,10,10,32,32,32,32,95,95,112,97,99,107,97,103, + 101,95,95,32,105,115,32,110,111,116,32,103,117,97,114,97, + 110,116,101,101,100,32,116,111,32,98,101,32,100,101,102,105, + 110,101,100,32,111,114,32,99,111,117,108,100,32,98,101,32, + 115,101,116,32,116,111,32,78,111,110,101,10,32,32,32,32, + 116,111,32,114,101,112,114,101,115,101,110,116,32,116,104,97, + 116,32,105,116,115,32,112,114,111,112,101,114,32,118,97,108, + 117,101,32,105,115,32,117,110,107,110,111,119,110,46,10,10, + 32,32,32,32,114,130,0,0,0,114,89,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,127,0, + 0,0,114,117,0,0,0,114,19,0,0,0,41,6,114,30, + 0,0,0,114,119,0,0,0,114,166,0,0,0,114,167,0, + 0,0,114,168,0,0,0,114,118,0,0,0,41,3,218,7, + 103,108,111,98,97,108,115,114,160,0,0,0,114,82,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,22,4,0,0,115,30,0,0,0,0,7,10,1, + 10,1,8,1,18,1,22,2,10,1,4,1,8,1,6,2, + 6,2,10,1,8,1,8,1,14,1,114,191,0,0,0,114, + 10,0,0,0,99,5,0,0,0,0,0,0,0,9,0,0, + 0,5,0,0,0,67,0,0,0,115,180,0,0,0,124,4, + 100,1,107,2,114,18,116,0,124,0,131,1,125,5,110,36, + 124,1,100,2,107,9,114,30,124,1,110,2,105,0,125,6, + 116,1,124,6,131,1,125,7,116,0,124,0,124,7,124,4, + 131,3,125,5,124,3,115,150,124,4,100,1,107,2,114,84, + 116,0,124,0,160,2,100,3,161,1,100,1,25,0,131,1, + 83,0,124,0,115,92,124,5,83,0,116,3,124,0,131,1, + 116,3,124,0,160,2,100,3,161,1,100,1,25,0,131,1, + 24,0,125,8,116,4,106,5,124,5,106,6,100,2,116,3, + 124,5,106,6,131,1,124,8,24,0,133,2,25,0,25,0, + 83,0,110,26,116,7,124,5,100,4,131,2,114,172,116,8, + 124,5,124,3,116,0,131,3,83,0,124,5,83,0,100,2, + 83,0,41,5,97,215,1,0,0,73,109,112,111,114,116,32, + 97,32,109,111,100,117,108,101,46,10,10,32,32,32,32,84, + 104,101,32,39,103,108,111,98,97,108,115,39,32,97,114,103, + 117,109,101,110,116,32,105,115,32,117,115,101,100,32,116,111, + 32,105,110,102,101,114,32,119,104,101,114,101,32,116,104,101, + 32,105,109,112,111,114,116,32,105,115,32,111,99,99,117,114, + 114,105,110,103,32,102,114,111,109,10,32,32,32,32,116,111, + 32,104,97,110,100,108,101,32,114,101,108,97,116,105,118,101, + 32,105,109,112,111,114,116,115,46,32,84,104,101,32,39,108, + 111,99,97,108,115,39,32,97,114,103,117,109,101,110,116,32, + 105,115,32,105,103,110,111,114,101,100,46,32,84,104,101,10, + 32,32,32,32,39,102,114,111,109,108,105,115,116,39,32,97, + 114,103,117,109,101,110,116,32,115,112,101,99,105,102,105,101, + 115,32,119,104,97,116,32,115,104,111,117,108,100,32,101,120, + 105,115,116,32,97,115,32,97,116,116,114,105,98,117,116,101, + 115,32,111,110,32,116,104,101,32,109,111,100,117,108,101,10, + 32,32,32,32,98,101,105,110,103,32,105,109,112,111,114,116, + 101,100,32,40,101,46,103,46,32,96,96,102,114,111,109,32, + 109,111,100,117,108,101,32,105,109,112,111,114,116,32,60,102, + 114,111,109,108,105,115,116,62,96,96,41,46,32,32,84,104, + 101,32,39,108,101,118,101,108,39,10,32,32,32,32,97,114, + 103,117,109,101,110,116,32,114,101,112,114,101,115,101,110,116, + 115,32,116,104,101,32,112,97,99,107,97,103,101,32,108,111, + 99,97,116,105,111,110,32,116,111,32,105,109,112,111,114,116, + 32,102,114,111,109,32,105,110,32,97,32,114,101,108,97,116, + 105,118,101,10,32,32,32,32,105,109,112,111,114,116,32,40, + 101,46,103,46,32,96,96,102,114,111,109,32,46,46,112,107, + 103,32,105,109,112,111,114,116,32,109,111,100,96,96,32,119, + 111,117,108,100,32,104,97,118,101,32,97,32,39,108,101,118, + 101,108,39,32,111,102,32,50,41,46,10,10,32,32,32,32, + 114,19,0,0,0,78,114,117,0,0,0,114,127,0,0,0, + 41,9,114,181,0,0,0,114,191,0,0,0,218,9,112,97, + 114,116,105,116,105,111,110,114,158,0,0,0,114,14,0,0, + 0,114,79,0,0,0,114,1,0,0,0,114,4,0,0,0, + 114,185,0,0,0,41,9,114,15,0,0,0,114,190,0,0, + 0,218,6,108,111,99,97,108,115,114,186,0,0,0,114,161, + 0,0,0,114,83,0,0,0,90,8,103,108,111,98,97,108, + 115,95,114,160,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,49,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,194,0,0,0,99,1,0,0,0,0,0,0,0, + 2,0,0,0,3,0,0,0,67,0,0,0,115,38,0,0, + 0,116,0,160,1,124,0,161,1,125,1,124,1,100,0,107, + 8,114,30,116,2,100,1,124,0,23,0,131,1,130,1,116, + 3,124,1,131,1,83,0,41,2,78,122,25,110,111,32,98, + 117,105,108,116,45,105,110,32,109,111,100,117,108,101,32,110, + 97,109,101,100,32,41,4,114,141,0,0,0,114,145,0,0, + 0,114,70,0,0,0,114,140,0,0,0,41,2,114,15,0, + 0,0,114,82,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,86,4,0,0,115,8, + 0,0,0,0,1,10,1,8,1,12,1,114,195,0,0,0, + 99,2,0,0,0,0,0,0,0,10,0,0,0,5,0,0, + 0,67,0,0,0,115,166,0,0,0,124,1,97,0,124,0, + 97,1,116,2,116,1,131,1,125,2,116,1,106,3,160,4, + 161,0,68,0,93,72,92,2,125,3,125,4,116,5,124,4, + 124,2,131,2,114,26,124,3,116,1,106,6,107,6,114,60, + 116,7,125,5,110,18,116,0,160,8,124,3,161,1,114,26, + 116,9,125,5,110,2,113,26,116,10,124,4,124,5,131,2, + 125,6,116,11,124,6,124,4,131,2,1,0,113,26,116,1, + 106,3,116,12,25,0,125,7,100,1,68,0,93,46,125,8, + 124,8,116,1,106,3,107,7,114,138,116,13,124,8,131,1, + 125,9,110,10,116,1,106,3,124,8,25,0,125,9,116,14, + 124,7,124,8,124,9,131,3,1,0,113,114,100,2,83,0, + 41,3,122,250,83,101,116,117,112,32,105,109,112,111,114,116, + 108,105,98,32,98,121,32,105,109,112,111,114,116,105,110,103, + 32,110,101,101,100,101,100,32,98,117,105,108,116,45,105,110, + 32,109,111,100,117,108,101,115,32,97,110,100,32,105,110,106, + 101,99,116,105,110,103,32,116,104,101,109,10,32,32,32,32, + 105,110,116,111,32,116,104,101,32,103,108,111,98,97,108,32, + 110,97,109,101,115,112,97,99,101,46,10,10,32,32,32,32, + 65,115,32,115,121,115,32,105,115,32,110,101,101,100,101,100, + 32,102,111,114,32,115,121,115,46,109,111,100,117,108,101,115, + 32,97,99,99,101,115,115,32,97,110,100,32,95,105,109,112, + 32,105,115,32,110,101,101,100,101,100,32,116,111,32,108,111, + 97,100,32,98,117,105,108,116,45,105,110,10,32,32,32,32, + 109,111,100,117,108,101,115,44,32,116,104,111,115,101,32,116, + 119,111,32,109,111,100,117,108,101,115,32,109,117,115,116,32, + 98,101,32,101,120,112,108,105,99,105,116,108,121,32,112,97, + 115,115,101,100,32,105,110,46,10,10,32,32,32,32,41,3, + 114,20,0,0,0,114,166,0,0,0,114,56,0,0,0,78, + 41,15,114,49,0,0,0,114,14,0,0,0,114,13,0,0, + 0,114,79,0,0,0,218,5,105,116,101,109,115,114,170,0, + 0,0,114,69,0,0,0,114,141,0,0,0,114,75,0,0, + 0,114,151,0,0,0,114,128,0,0,0,114,133,0,0,0, + 114,1,0,0,0,114,195,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,15,0,0,0,114,83,0,0, + 0,114,93,0,0,0,114,82,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,93,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,199,0,0,0,99, + 2,0,0,0,0,0,0,0,2,0,0,0,3,0,0,0, + 67,0,0,0,115,38,0,0,0,116,0,124,0,124,1,131, + 2,1,0,116,1,106,2,160,3,116,4,161,1,1,0,116, + 1,106,2,160,3,116,5,161,1,1,0,100,1,83,0,41, + 2,122,48,73,110,115,116,97,108,108,32,105,109,112,111,114, + 116,101,114,115,32,102,111,114,32,98,117,105,108,116,105,110, + 32,97,110,100,32,102,114,111,122,101,110,32,109,111,100,117, + 108,101,115,78,41,6,114,199,0,0,0,114,14,0,0,0, + 114,165,0,0,0,114,109,0,0,0,114,141,0,0,0,114, + 151,0,0,0,41,2,114,197,0,0,0,114,198,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,128,4,0,0,115,6,0, + 0,0,0,2,10,2,12,1,114,200,0,0,0,99,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,19,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,115,0,0,0,114,200,0, + 0,0,114,14,0,0,0,114,79,0,0,0,114,1,0,0, + 0,41,1,114,201,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,136,4,0,0,115,6,0,0,0,0,3,8, + 1,4,1,114,202,0,0,0,41,2,78,78,41,1,78,41, + 2,78,114,19,0,0,0,41,4,78,78,114,10,0,0,0, + 114,19,0,0,0,41,51,114,3,0,0,0,114,115,0,0, + 0,114,12,0,0,0,114,16,0,0,0,114,51,0,0,0, + 114,29,0,0,0,114,36,0,0,0,114,17,0,0,0,114, + 18,0,0,0,114,41,0,0,0,114,42,0,0,0,114,45, + 0,0,0,114,57,0,0,0,114,59,0,0,0,114,68,0, + 0,0,114,74,0,0,0,114,77,0,0,0,114,84,0,0, + 0,114,95,0,0,0,114,96,0,0,0,114,102,0,0,0, + 114,78,0,0,0,114,128,0,0,0,114,133,0,0,0,114, + 136,0,0,0,114,91,0,0,0,114,80,0,0,0,114,139, + 0,0,0,114,140,0,0,0,114,81,0,0,0,114,141,0, + 0,0,114,151,0,0,0,114,156,0,0,0,114,162,0,0, + 0,114,164,0,0,0,114,169,0,0,0,114,173,0,0,0, + 90,15,95,69,82,82,95,77,83,71,95,80,82,69,70,73, + 88,114,175,0,0,0,114,178,0,0,0,218,6,111,98,106, + 101,99,116,114,179,0,0,0,114,180,0,0,0,114,181,0, + 0,0,114,185,0,0,0,114,191,0,0,0,114,194,0,0, + 0,114,195,0,0,0,114,199,0,0,0,114,200,0,0,0, + 114,202,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,8,0,0,0,115,96,0,0,0,4,17,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,27,14,101,16,26,10,45,14,72,8,17,8,17,8,24, + 8,29,8,23,8,15,14,73,14,77,14,13,8,9,8,9, + 10,47,8,16,4,1,8,2,8,27,6,3,8,16,10,15, + 14,37,8,27,10,37,8,7,8,35,8,8, }; diff --git a/Python/importlib_external.h b/Python/importlib_external.h index 70dfe545e66f..26a0383588a4 100644 --- a/Python/importlib_external.h +++ b/Python/importlib_external.h @@ -1005,732 +1005,733 @@ const unsigned char _Py_M__importlib_external[] = { 116,104,111,100,114,173,0,0,0,114,179,0,0,0,114,182, 0,0,0,114,183,0,0,0,114,2,0,0,0,114,2,0, 0,0,114,2,0,0,0,114,4,0,0,0,114,170,0,0, - 0,130,2,0,0,115,18,0,0,0,12,5,4,3,4,2, - 4,2,12,7,12,15,2,1,12,15,2,1,114,170,0,0, - 0,99,0,0,0,0,0,0,0,0,0,0,0,0,2,0, - 0,0,64,0,0,0,115,48,0,0,0,101,0,90,1,100, - 0,90,2,100,1,90,3,100,2,100,3,132,0,90,4,100, - 4,100,5,132,0,90,5,100,6,100,7,132,0,90,6,100, - 8,100,9,132,0,90,7,100,10,83,0,41,11,218,13,95, - 76,111,97,100,101,114,66,97,115,105,99,115,122,83,66,97, - 115,101,32,99,108,97,115,115,32,111,102,32,99,111,109,109, - 111,110,32,99,111,100,101,32,110,101,101,100,101,100,32,98, - 121,32,98,111,116,104,32,83,111,117,114,99,101,76,111,97, - 100,101,114,32,97,110,100,10,32,32,32,32,83,111,117,114, - 99,101,108,101,115,115,70,105,108,101,76,111,97,100,101,114, - 46,99,2,0,0,0,0,0,0,0,5,0,0,0,4,0, - 0,0,67,0,0,0,115,64,0,0,0,116,0,124,0,160, - 1,124,1,161,1,131,1,100,1,25,0,125,2,124,2,160, - 2,100,2,100,1,161,2,100,3,25,0,125,3,124,1,160, - 3,100,2,161,1,100,4,25,0,125,4,124,3,100,5,107, - 2,111,62,124,4,100,5,107,3,83,0,41,6,122,141,67, - 111,110,99,114,101,116,101,32,105,109,112,108,101,109,101,110, - 116,97,116,105,111,110,32,111,102,32,73,110,115,112,101,99, - 116,76,111,97,100,101,114,46,105,115,95,112,97,99,107,97, - 103,101,32,98,121,32,99,104,101,99,107,105,110,103,32,105, - 102,10,32,32,32,32,32,32,32,32,116,104,101,32,112,97, - 116,104,32,114,101,116,117,114,110,101,100,32,98,121,32,103, - 101,116,95,102,105,108,101,110,97,109,101,32,104,97,115,32, - 97,32,102,105,108,101,110,97,109,101,32,111,102,32,39,95, - 95,105,110,105,116,95,95,46,112,121,39,46,114,29,0,0, - 0,114,59,0,0,0,114,60,0,0,0,114,57,0,0,0, - 218,8,95,95,105,110,105,116,95,95,41,4,114,38,0,0, - 0,114,159,0,0,0,114,34,0,0,0,114,32,0,0,0, - 41,5,114,102,0,0,0,114,121,0,0,0,114,96,0,0, - 0,90,13,102,105,108,101,110,97,109,101,95,98,97,115,101, - 90,9,116,97,105,108,95,110,97,109,101,114,2,0,0,0, - 114,2,0,0,0,114,4,0,0,0,114,161,0,0,0,199, - 2,0,0,115,8,0,0,0,0,3,18,1,16,1,14,1, - 122,24,95,76,111,97,100,101,114,66,97,115,105,99,115,46, - 105,115,95,112,97,99,107,97,103,101,99,2,0,0,0,0, - 0,0,0,2,0,0,0,1,0,0,0,67,0,0,0,115, - 4,0,0,0,100,1,83,0,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,2,0,0,0,41,2,114,102, - 0,0,0,114,166,0,0,0,114,2,0,0,0,114,2,0, - 0,0,114,4,0,0,0,218,13,99,114,101,97,116,101,95, - 109,111,100,117,108,101,207,2,0,0,115,0,0,0,0,122, - 27,95,76,111,97,100,101,114,66,97,115,105,99,115,46,99, - 114,101,97,116,101,95,109,111,100,117,108,101,99,2,0,0, - 0,0,0,0,0,3,0,0,0,5,0,0,0,67,0,0, - 0,115,56,0,0,0,124,0,160,0,124,1,106,1,161,1, - 125,2,124,2,100,1,107,8,114,36,116,2,100,2,160,3, - 124,1,106,1,161,1,131,1,130,1,116,4,160,5,116,6, - 124,2,124,1,106,7,161,3,1,0,100,1,83,0,41,3, - 122,19,69,120,101,99,117,116,101,32,116,104,101,32,109,111, - 100,117,108,101,46,78,122,52,99,97,110,110,111,116,32,108, - 111,97,100,32,109,111,100,117,108,101,32,123,33,114,125,32, - 119,104,101,110,32,103,101,116,95,99,111,100,101,40,41,32, - 114,101,116,117,114,110,115,32,78,111,110,101,41,8,218,8, - 103,101,116,95,99,111,100,101,114,107,0,0,0,114,101,0, - 0,0,114,48,0,0,0,114,116,0,0,0,218,25,95,99, - 97,108,108,95,119,105,116,104,95,102,114,97,109,101,115,95, - 114,101,109,111,118,101,100,218,4,101,120,101,99,114,113,0, - 0,0,41,3,114,102,0,0,0,218,6,109,111,100,117,108, - 101,114,144,0,0,0,114,2,0,0,0,114,2,0,0,0, - 114,4,0,0,0,218,11,101,120,101,99,95,109,111,100,117, - 108,101,210,2,0,0,115,10,0,0,0,0,2,12,1,8, - 1,6,1,10,1,122,25,95,76,111,97,100,101,114,66,97, - 115,105,99,115,46,101,120,101,99,95,109,111,100,117,108,101, - 99,2,0,0,0,0,0,0,0,2,0,0,0,4,0,0, - 0,67,0,0,0,115,12,0,0,0,116,0,160,1,124,0, - 124,1,161,2,83,0,41,1,122,26,84,104,105,115,32,109, - 111,100,117,108,101,32,105,115,32,100,101,112,114,101,99,97, - 116,101,100,46,41,2,114,116,0,0,0,218,17,95,108,111, - 97,100,95,109,111,100,117,108,101,95,115,104,105,109,41,2, - 114,102,0,0,0,114,121,0,0,0,114,2,0,0,0,114, - 2,0,0,0,114,4,0,0,0,218,11,108,111,97,100,95, - 109,111,100,117,108,101,218,2,0,0,115,2,0,0,0,0, - 2,122,25,95,76,111,97,100,101,114,66,97,115,105,99,115, - 46,108,111,97,100,95,109,111,100,117,108,101,78,41,8,114, - 107,0,0,0,114,106,0,0,0,114,108,0,0,0,114,109, - 0,0,0,114,161,0,0,0,114,187,0,0,0,114,192,0, - 0,0,114,194,0,0,0,114,2,0,0,0,114,2,0,0, - 0,114,2,0,0,0,114,4,0,0,0,114,185,0,0,0, - 194,2,0,0,115,8,0,0,0,12,5,8,8,8,3,8, - 8,114,185,0,0,0,99,0,0,0,0,0,0,0,0,0, - 0,0,0,3,0,0,0,64,0,0,0,115,74,0,0,0, - 101,0,90,1,100,0,90,2,100,1,100,2,132,0,90,3, - 100,3,100,4,132,0,90,4,100,5,100,6,132,0,90,5, - 100,7,100,8,132,0,90,6,100,9,100,10,132,0,90,7, - 100,11,100,12,156,1,100,13,100,14,132,2,90,8,100,15, - 100,16,132,0,90,9,100,17,83,0,41,18,218,12,83,111, - 117,114,99,101,76,111,97,100,101,114,99,2,0,0,0,0, - 0,0,0,2,0,0,0,1,0,0,0,67,0,0,0,115, - 8,0,0,0,116,0,130,1,100,1,83,0,41,2,122,178, - 79,112,116,105,111,110,97,108,32,109,101,116,104,111,100,32, - 116,104,97,116,32,114,101,116,117,114,110,115,32,116,104,101, - 32,109,111,100,105,102,105,99,97,116,105,111,110,32,116,105, - 109,101,32,40,97,110,32,105,110,116,41,32,102,111,114,32, - 116,104,101,10,32,32,32,32,32,32,32,32,115,112,101,99, - 105,102,105,101,100,32,112,97,116,104,44,32,119,104,101,114, - 101,32,112,97,116,104,32,105,115,32,97,32,115,116,114,46, - 10,10,32,32,32,32,32,32,32,32,82,97,105,115,101,115, - 32,79,83,69,114,114,111,114,32,119,104,101,110,32,116,104, - 101,32,112,97,116,104,32,99,97,110,110,111,116,32,98,101, - 32,104,97,110,100,108,101,100,46,10,32,32,32,32,32,32, - 32,32,78,41,1,114,40,0,0,0,41,2,114,102,0,0, - 0,114,35,0,0,0,114,2,0,0,0,114,2,0,0,0, - 114,4,0,0,0,218,10,112,97,116,104,95,109,116,105,109, - 101,225,2,0,0,115,2,0,0,0,0,6,122,23,83,111, - 117,114,99,101,76,111,97,100,101,114,46,112,97,116,104,95, - 109,116,105,109,101,99,2,0,0,0,0,0,0,0,2,0, - 0,0,4,0,0,0,67,0,0,0,115,14,0,0,0,100, - 1,124,0,160,0,124,1,161,1,105,1,83,0,41,2,97, - 170,1,0,0,79,112,116,105,111,110,97,108,32,109,101,116, - 104,111,100,32,114,101,116,117,114,110,105,110,103,32,97,32, - 109,101,116,97,100,97,116,97,32,100,105,99,116,32,102,111, - 114,32,116,104,101,32,115,112,101,99,105,102,105,101,100,32, - 112,97,116,104,10,32,32,32,32,32,32,32,32,116,111,32, - 98,121,32,116,104,101,32,112,97,116,104,32,40,115,116,114, - 41,46,10,32,32,32,32,32,32,32,32,80,111,115,115,105, - 98,108,101,32,107,101,121,115,58,10,32,32,32,32,32,32, - 32,32,45,32,39,109,116,105,109,101,39,32,40,109,97,110, - 100,97,116,111,114,121,41,32,105,115,32,116,104,101,32,110, - 117,109,101,114,105,99,32,116,105,109,101,115,116,97,109,112, - 32,111,102,32,108,97,115,116,32,115,111,117,114,99,101,10, - 32,32,32,32,32,32,32,32,32,32,99,111,100,101,32,109, - 111,100,105,102,105,99,97,116,105,111,110,59,10,32,32,32, - 32,32,32,32,32,45,32,39,115,105,122,101,39,32,40,111, - 112,116,105,111,110,97,108,41,32,105,115,32,116,104,101,32, - 115,105,122,101,32,105,110,32,98,121,116,101,115,32,111,102, - 32,116,104,101,32,115,111,117,114,99,101,32,99,111,100,101, - 46,10,10,32,32,32,32,32,32,32,32,73,109,112,108,101, - 109,101,110,116,105,110,103,32,116,104,105,115,32,109,101,116, - 104,111,100,32,97,108,108,111,119,115,32,116,104,101,32,108, - 111,97,100,101,114,32,116,111,32,114,101,97,100,32,98,121, - 116,101,99,111,100,101,32,102,105,108,101,115,46,10,32,32, - 32,32,32,32,32,32,82,97,105,115,101,115,32,79,83,69, - 114,114,111,114,32,119,104,101,110,32,116,104,101,32,112,97, - 116,104,32,99,97,110,110,111,116,32,98,101,32,104,97,110, - 100,108,101,100,46,10,32,32,32,32,32,32,32,32,114,149, - 0,0,0,41,1,114,196,0,0,0,41,2,114,102,0,0, - 0,114,35,0,0,0,114,2,0,0,0,114,2,0,0,0, - 114,4,0,0,0,218,10,112,97,116,104,95,115,116,97,116, - 115,233,2,0,0,115,2,0,0,0,0,11,122,23,83,111, - 117,114,99,101,76,111,97,100,101,114,46,112,97,116,104,95, - 115,116,97,116,115,99,4,0,0,0,0,0,0,0,4,0, - 0,0,4,0,0,0,67,0,0,0,115,12,0,0,0,124, - 0,160,0,124,2,124,3,161,2,83,0,41,1,122,228,79, - 112,116,105,111,110,97,108,32,109,101,116,104,111,100,32,119, - 104,105,99,104,32,119,114,105,116,101,115,32,100,97,116,97, - 32,40,98,121,116,101,115,41,32,116,111,32,97,32,102,105, - 108,101,32,112,97,116,104,32,40,97,32,115,116,114,41,46, - 10,10,32,32,32,32,32,32,32,32,73,109,112,108,101,109, - 101,110,116,105,110,103,32,116,104,105,115,32,109,101,116,104, - 111,100,32,97,108,108,111,119,115,32,102,111,114,32,116,104, - 101,32,119,114,105,116,105,110,103,32,111,102,32,98,121,116, - 101,99,111,100,101,32,102,105,108,101,115,46,10,10,32,32, - 32,32,32,32,32,32,84,104,101,32,115,111,117,114,99,101, - 32,112,97,116,104,32,105,115,32,110,101,101,100,101,100,32, - 105,110,32,111,114,100,101,114,32,116,111,32,99,111,114,114, - 101,99,116,108,121,32,116,114,97,110,115,102,101,114,32,112, - 101,114,109,105,115,115,105,111,110,115,10,32,32,32,32,32, - 32,32,32,41,1,218,8,115,101,116,95,100,97,116,97,41, - 4,114,102,0,0,0,114,92,0,0,0,90,10,99,97,99, - 104,101,95,112,97,116,104,114,54,0,0,0,114,2,0,0, - 0,114,2,0,0,0,114,4,0,0,0,218,15,95,99,97, - 99,104,101,95,98,121,116,101,99,111,100,101,246,2,0,0, - 115,2,0,0,0,0,8,122,28,83,111,117,114,99,101,76, - 111,97,100,101,114,46,95,99,97,99,104,101,95,98,121,116, - 101,99,111,100,101,99,3,0,0,0,0,0,0,0,3,0, - 0,0,1,0,0,0,67,0,0,0,115,4,0,0,0,100, - 1,83,0,41,2,122,150,79,112,116,105,111,110,97,108,32, - 109,101,116,104,111,100,32,119,104,105,99,104,32,119,114,105, - 116,101,115,32,100,97,116,97,32,40,98,121,116,101,115,41, - 32,116,111,32,97,32,102,105,108,101,32,112,97,116,104,32, - 40,97,32,115,116,114,41,46,10,10,32,32,32,32,32,32, - 32,32,73,109,112,108,101,109,101,110,116,105,110,103,32,116, - 104,105,115,32,109,101,116,104,111,100,32,97,108,108,111,119, - 115,32,102,111,114,32,116,104,101,32,119,114,105,116,105,110, - 103,32,111,102,32,98,121,116,101,99,111,100,101,32,102,105, - 108,101,115,46,10,32,32,32,32,32,32,32,32,78,114,2, - 0,0,0,41,3,114,102,0,0,0,114,35,0,0,0,114, - 54,0,0,0,114,2,0,0,0,114,2,0,0,0,114,4, - 0,0,0,114,198,0,0,0,0,3,0,0,115,0,0,0, - 0,122,21,83,111,117,114,99,101,76,111,97,100,101,114,46, - 115,101,116,95,100,97,116,97,99,2,0,0,0,0,0,0, - 0,5,0,0,0,10,0,0,0,67,0,0,0,115,82,0, - 0,0,124,0,160,0,124,1,161,1,125,2,122,14,124,0, - 160,1,124,2,161,1,125,3,87,0,110,48,4,0,116,2, - 107,10,114,72,1,0,125,4,1,0,122,18,116,3,100,1, - 124,1,100,2,141,2,124,4,130,2,87,0,53,0,100,3, - 125,4,126,4,88,0,89,0,110,2,88,0,116,4,124,3, - 131,1,83,0,41,4,122,52,67,111,110,99,114,101,116,101, - 32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32, - 111,102,32,73,110,115,112,101,99,116,76,111,97,100,101,114, - 46,103,101,116,95,115,111,117,114,99,101,46,122,39,115,111, - 117,114,99,101,32,110,111,116,32,97,118,97,105,108,97,98, - 108,101,32,116,104,114,111,117,103,104,32,103,101,116,95,100, - 97,116,97,40,41,41,1,114,100,0,0,0,78,41,5,114, - 159,0,0,0,218,8,103,101,116,95,100,97,116,97,114,40, - 0,0,0,114,101,0,0,0,114,157,0,0,0,41,5,114, - 102,0,0,0,114,121,0,0,0,114,35,0,0,0,114,155, - 0,0,0,218,3,101,120,99,114,2,0,0,0,114,2,0, - 0,0,114,4,0,0,0,218,10,103,101,116,95,115,111,117, - 114,99,101,7,3,0,0,115,14,0,0,0,0,2,10,1, - 2,1,14,1,16,1,4,1,28,1,122,23,83,111,117,114, - 99,101,76,111,97,100,101,114,46,103,101,116,95,115,111,117, - 114,99,101,114,89,0,0,0,41,1,218,9,95,111,112,116, - 105,109,105,122,101,99,3,0,0,0,1,0,0,0,4,0, - 0,0,8,0,0,0,67,0,0,0,115,22,0,0,0,116, - 0,106,1,116,2,124,1,124,2,100,1,100,2,124,3,100, - 3,141,6,83,0,41,4,122,130,82,101,116,117,114,110,32, - 116,104,101,32,99,111,100,101,32,111,98,106,101,99,116,32, - 99,111,109,112,105,108,101,100,32,102,114,111,109,32,115,111, - 117,114,99,101,46,10,10,32,32,32,32,32,32,32,32,84, - 104,101,32,39,100,97,116,97,39,32,97,114,103,117,109,101, - 110,116,32,99,97,110,32,98,101,32,97,110,121,32,111,98, - 106,101,99,116,32,116,121,112,101,32,116,104,97,116,32,99, - 111,109,112,105,108,101,40,41,32,115,117,112,112,111,114,116, - 115,46,10,32,32,32,32,32,32,32,32,114,190,0,0,0, - 84,41,2,218,12,100,111,110,116,95,105,110,104,101,114,105, - 116,114,70,0,0,0,41,3,114,116,0,0,0,114,189,0, - 0,0,218,7,99,111,109,112,105,108,101,41,4,114,102,0, - 0,0,114,54,0,0,0,114,35,0,0,0,114,203,0,0, - 0,114,2,0,0,0,114,2,0,0,0,114,4,0,0,0, - 218,14,115,111,117,114,99,101,95,116,111,95,99,111,100,101, - 17,3,0,0,115,4,0,0,0,0,5,12,1,122,27,83, - 111,117,114,99,101,76,111,97,100,101,114,46,115,111,117,114, - 99,101,95,116,111,95,99,111,100,101,99,2,0,0,0,0, - 0,0,0,15,0,0,0,9,0,0,0,67,0,0,0,115, - 46,2,0,0,124,0,160,0,124,1,161,1,125,2,100,1, - 125,3,100,1,125,4,100,1,125,5,100,2,125,6,100,3, - 125,7,122,12,116,1,124,2,131,1,125,8,87,0,110,26, - 4,0,116,2,107,10,114,68,1,0,1,0,1,0,100,1, - 125,8,89,0,144,1,110,48,88,0,122,14,124,0,160,3, - 124,2,161,1,125,9,87,0,110,22,4,0,116,4,107,10, - 114,106,1,0,1,0,1,0,89,0,144,1,110,10,88,0, - 116,5,124,9,100,4,25,0,131,1,125,3,122,14,124,0, - 160,6,124,8,161,1,125,10,87,0,110,20,4,0,116,4, - 107,10,114,154,1,0,1,0,1,0,89,0,110,218,88,0, - 124,1,124,8,100,5,156,2,125,11,122,148,116,7,124,10, - 124,1,124,11,131,3,125,12,116,8,124,10,131,1,100,6, - 100,1,133,2,25,0,125,13,124,12,100,7,64,0,100,8, - 107,3,125,6,124,6,144,1,114,36,124,12,100,9,64,0, - 100,8,107,3,125,7,116,9,106,10,100,10,107,3,144,1, - 114,56,124,7,115,254,116,9,106,10,100,11,107,2,144,1, - 114,56,124,0,160,6,124,2,161,1,125,4,116,9,160,11, - 116,12,124,4,161,2,125,5,116,13,124,10,124,5,124,1, - 124,11,131,4,1,0,110,20,116,14,124,10,124,3,124,9, - 100,12,25,0,124,1,124,11,131,5,1,0,87,0,110,26, - 4,0,116,15,116,16,102,2,107,10,144,1,114,84,1,0, - 1,0,1,0,89,0,110,32,88,0,116,17,160,18,100,13, - 124,8,124,2,161,3,1,0,116,19,124,13,124,1,124,8, - 124,2,100,14,141,4,83,0,124,4,100,1,107,8,144,1, - 114,136,124,0,160,6,124,2,161,1,125,4,124,0,160,20, - 124,4,124,2,161,2,125,14,116,17,160,18,100,15,124,2, - 161,2,1,0,116,21,106,22,144,2,115,42,124,8,100,1, - 107,9,144,2,114,42,124,3,100,1,107,9,144,2,114,42, - 124,6,144,1,114,228,124,5,100,1,107,8,144,1,114,214, - 116,9,160,11,124,4,161,1,125,5,116,23,124,14,124,5, - 124,7,131,3,125,10,110,16,116,24,124,14,124,3,116,25, - 124,4,131,1,131,3,125,10,122,30,124,0,160,26,124,2, - 124,8,124,10,161,3,1,0,116,17,160,18,100,16,124,8, - 161,2,1,0,87,0,110,22,4,0,116,2,107,10,144,2, - 114,40,1,0,1,0,1,0,89,0,110,2,88,0,124,14, - 83,0,41,17,122,190,67,111,110,99,114,101,116,101,32,105, - 109,112,108,101,109,101,110,116,97,116,105,111,110,32,111,102, - 32,73,110,115,112,101,99,116,76,111,97,100,101,114,46,103, - 101,116,95,99,111,100,101,46,10,10,32,32,32,32,32,32, - 32,32,82,101,97,100,105,110,103,32,111,102,32,98,121,116, - 101,99,111,100,101,32,114,101,113,117,105,114,101,115,32,112, - 97,116,104,95,115,116,97,116,115,32,116,111,32,98,101,32, - 105,109,112,108,101,109,101,110,116,101,100,46,32,84,111,32, - 119,114,105,116,101,10,32,32,32,32,32,32,32,32,98,121, - 116,101,99,111,100,101,44,32,115,101,116,95,100,97,116,97, - 32,109,117,115,116,32,97,108,115,111,32,98,101,32,105,109, - 112,108,101,109,101,110,116,101,100,46,10,10,32,32,32,32, - 32,32,32,32,78,70,84,114,149,0,0,0,41,2,114,100, - 0,0,0,114,35,0,0,0,114,126,0,0,0,114,29,0, - 0,0,114,60,0,0,0,114,57,0,0,0,90,5,110,101, - 118,101,114,90,6,97,108,119,97,121,115,218,4,115,105,122, - 101,122,13,123,125,32,109,97,116,99,104,101,115,32,123,125, - 41,3,114,100,0,0,0,114,91,0,0,0,114,92,0,0, - 0,122,19,99,111,100,101,32,111,98,106,101,99,116,32,102, - 114,111,109,32,123,125,122,10,119,114,111,116,101,32,123,33, - 114,125,41,27,114,159,0,0,0,114,81,0,0,0,114,68, - 0,0,0,114,197,0,0,0,114,40,0,0,0,114,14,0, - 0,0,114,200,0,0,0,114,133,0,0,0,218,10,109,101, - 109,111,114,121,118,105,101,119,114,143,0,0,0,90,21,99, - 104,101,99,107,95,104,97,115,104,95,98,97,115,101,100,95, - 112,121,99,115,114,138,0,0,0,218,17,95,82,65,87,95, - 77,65,71,73,67,95,78,85,77,66,69,82,114,139,0,0, - 0,114,137,0,0,0,114,101,0,0,0,114,131,0,0,0, - 114,116,0,0,0,114,130,0,0,0,114,145,0,0,0,114, - 206,0,0,0,114,6,0,0,0,218,19,100,111,110,116,95, - 119,114,105,116,101,95,98,121,116,101,99,111,100,101,114,152, - 0,0,0,114,150,0,0,0,114,31,0,0,0,114,199,0, - 0,0,41,15,114,102,0,0,0,114,121,0,0,0,114,92, - 0,0,0,114,135,0,0,0,114,155,0,0,0,114,138,0, - 0,0,90,10,104,97,115,104,95,98,97,115,101,100,90,12, - 99,104,101,99,107,95,115,111,117,114,99,101,114,91,0,0, - 0,218,2,115,116,114,54,0,0,0,114,132,0,0,0,114, - 69,0,0,0,90,10,98,121,116,101,115,95,100,97,116,97, - 90,11,99,111,100,101,95,111,98,106,101,99,116,114,2,0, - 0,0,114,2,0,0,0,114,4,0,0,0,114,188,0,0, - 0,25,3,0,0,115,134,0,0,0,0,7,10,1,4,1, - 4,1,4,1,4,1,4,1,2,1,12,1,14,1,12,2, - 2,1,14,1,14,1,8,2,12,1,2,1,14,1,14,1, - 6,3,2,1,8,2,2,1,12,1,16,1,12,1,6,1, - 12,1,12,1,4,1,12,1,10,1,4,1,2,1,6,2, - 8,1,8,2,2,1,2,1,2,1,6,1,2,1,10,2, - 20,1,6,2,8,1,6,1,6,1,2,1,8,1,10,1, - 10,1,12,1,12,1,18,1,10,1,6,1,10,1,10,1, - 14,2,6,1,10,1,2,1,14,1,16,1,16,1,6,1, - 122,21,83,111,117,114,99,101,76,111,97,100,101,114,46,103, - 101,116,95,99,111,100,101,78,41,10,114,107,0,0,0,114, - 106,0,0,0,114,108,0,0,0,114,196,0,0,0,114,197, - 0,0,0,114,199,0,0,0,114,198,0,0,0,114,202,0, - 0,0,114,206,0,0,0,114,188,0,0,0,114,2,0,0, - 0,114,2,0,0,0,114,2,0,0,0,114,4,0,0,0, - 114,195,0,0,0,223,2,0,0,115,14,0,0,0,8,2, - 8,8,8,13,8,10,8,7,8,10,14,8,114,195,0,0, - 0,99,0,0,0,0,0,0,0,0,0,0,0,0,4,0, - 0,0,0,0,0,0,115,124,0,0,0,101,0,90,1,100, - 0,90,2,100,1,90,3,100,2,100,3,132,0,90,4,100, - 4,100,5,132,0,90,5,100,6,100,7,132,0,90,6,101, - 7,135,0,102,1,100,8,100,9,132,8,131,1,90,8,101, - 7,100,10,100,11,132,0,131,1,90,9,100,12,100,13,132, - 0,90,10,101,7,100,14,100,15,132,0,131,1,90,11,100, - 16,100,17,132,0,90,12,100,18,100,19,132,0,90,13,100, - 20,100,21,132,0,90,14,100,22,100,23,132,0,90,15,135, - 0,4,0,90,16,83,0,41,24,218,10,70,105,108,101,76, - 111,97,100,101,114,122,103,66,97,115,101,32,102,105,108,101, - 32,108,111,97,100,101,114,32,99,108,97,115,115,32,119,104, - 105,99,104,32,105,109,112,108,101,109,101,110,116,115,32,116, - 104,101,32,108,111,97,100,101,114,32,112,114,111,116,111,99, - 111,108,32,109,101,116,104,111,100,115,32,116,104,97,116,10, - 32,32,32,32,114,101,113,117,105,114,101,32,102,105,108,101, - 32,115,121,115,116,101,109,32,117,115,97,103,101,46,99,3, - 0,0,0,0,0,0,0,3,0,0,0,2,0,0,0,67, - 0,0,0,115,16,0,0,0,124,1,124,0,95,0,124,2, - 124,0,95,1,100,1,83,0,41,2,122,75,67,97,99,104, - 101,32,116,104,101,32,109,111,100,117,108,101,32,110,97,109, - 101,32,97,110,100,32,116,104,101,32,112,97,116,104,32,116, - 111,32,116,104,101,32,102,105,108,101,32,102,111,117,110,100, - 32,98,121,32,116,104,101,10,32,32,32,32,32,32,32,32, - 102,105,110,100,101,114,46,78,41,2,114,100,0,0,0,114, - 35,0,0,0,41,3,114,102,0,0,0,114,121,0,0,0, - 114,35,0,0,0,114,2,0,0,0,114,2,0,0,0,114, - 4,0,0,0,114,186,0,0,0,116,3,0,0,115,4,0, - 0,0,0,3,6,1,122,19,70,105,108,101,76,111,97,100, - 101,114,46,95,95,105,110,105,116,95,95,99,2,0,0,0, - 0,0,0,0,2,0,0,0,2,0,0,0,67,0,0,0, - 115,24,0,0,0,124,0,106,0,124,1,106,0,107,2,111, - 22,124,0,106,1,124,1,106,1,107,2,83,0,41,1,78, - 41,2,218,9,95,95,99,108,97,115,115,95,95,114,113,0, - 0,0,41,2,114,102,0,0,0,218,5,111,116,104,101,114, - 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,218, - 6,95,95,101,113,95,95,122,3,0,0,115,4,0,0,0, - 0,1,12,1,122,17,70,105,108,101,76,111,97,100,101,114, - 46,95,95,101,113,95,95,99,1,0,0,0,0,0,0,0, - 1,0,0,0,3,0,0,0,67,0,0,0,115,20,0,0, - 0,116,0,124,0,106,1,131,1,116,0,124,0,106,2,131, - 1,65,0,83,0,41,1,78,41,3,218,4,104,97,115,104, - 114,100,0,0,0,114,35,0,0,0,41,1,114,102,0,0, - 0,114,2,0,0,0,114,2,0,0,0,114,4,0,0,0, - 218,8,95,95,104,97,115,104,95,95,126,3,0,0,115,2, - 0,0,0,0,1,122,19,70,105,108,101,76,111,97,100,101, - 114,46,95,95,104,97,115,104,95,95,99,2,0,0,0,0, - 0,0,0,2,0,0,0,3,0,0,0,3,0,0,0,115, - 16,0,0,0,116,0,116,1,124,0,131,2,160,2,124,1, - 161,1,83,0,41,1,122,100,76,111,97,100,32,97,32,109, - 111,100,117,108,101,32,102,114,111,109,32,97,32,102,105,108, - 101,46,10,10,32,32,32,32,32,32,32,32,84,104,105,115, - 32,109,101,116,104,111,100,32,105,115,32,100,101,112,114,101, - 99,97,116,101,100,46,32,32,85,115,101,32,101,120,101,99, - 95,109,111,100,117,108,101,40,41,32,105,110,115,116,101,97, - 100,46,10,10,32,32,32,32,32,32,32,32,41,3,218,5, - 115,117,112,101,114,114,212,0,0,0,114,194,0,0,0,41, - 2,114,102,0,0,0,114,121,0,0,0,41,1,114,213,0, - 0,0,114,2,0,0,0,114,4,0,0,0,114,194,0,0, - 0,129,3,0,0,115,2,0,0,0,0,10,122,22,70,105, - 108,101,76,111,97,100,101,114,46,108,111,97,100,95,109,111, + 0,130,2,0,0,115,20,0,0,0,8,2,4,3,4,3, + 4,2,4,2,12,7,12,15,2,1,12,15,2,1,114,170, + 0,0,0,99,0,0,0,0,0,0,0,0,0,0,0,0, + 2,0,0,0,64,0,0,0,115,48,0,0,0,101,0,90, + 1,100,0,90,2,100,1,90,3,100,2,100,3,132,0,90, + 4,100,4,100,5,132,0,90,5,100,6,100,7,132,0,90, + 6,100,8,100,9,132,0,90,7,100,10,83,0,41,11,218, + 13,95,76,111,97,100,101,114,66,97,115,105,99,115,122,83, + 66,97,115,101,32,99,108,97,115,115,32,111,102,32,99,111, + 109,109,111,110,32,99,111,100,101,32,110,101,101,100,101,100, + 32,98,121,32,98,111,116,104,32,83,111,117,114,99,101,76, + 111,97,100,101,114,32,97,110,100,10,32,32,32,32,83,111, + 117,114,99,101,108,101,115,115,70,105,108,101,76,111,97,100, + 101,114,46,99,2,0,0,0,0,0,0,0,5,0,0,0, + 4,0,0,0,67,0,0,0,115,64,0,0,0,116,0,124, + 0,160,1,124,1,161,1,131,1,100,1,25,0,125,2,124, + 2,160,2,100,2,100,1,161,2,100,3,25,0,125,3,124, + 1,160,3,100,2,161,1,100,4,25,0,125,4,124,3,100, + 5,107,2,111,62,124,4,100,5,107,3,83,0,41,6,122, + 141,67,111,110,99,114,101,116,101,32,105,109,112,108,101,109, + 101,110,116,97,116,105,111,110,32,111,102,32,73,110,115,112, + 101,99,116,76,111,97,100,101,114,46,105,115,95,112,97,99, + 107,97,103,101,32,98,121,32,99,104,101,99,107,105,110,103, + 32,105,102,10,32,32,32,32,32,32,32,32,116,104,101,32, + 112,97,116,104,32,114,101,116,117,114,110,101,100,32,98,121, + 32,103,101,116,95,102,105,108,101,110,97,109,101,32,104,97, + 115,32,97,32,102,105,108,101,110,97,109,101,32,111,102,32, + 39,95,95,105,110,105,116,95,95,46,112,121,39,46,114,29, + 0,0,0,114,59,0,0,0,114,60,0,0,0,114,57,0, + 0,0,218,8,95,95,105,110,105,116,95,95,41,4,114,38, + 0,0,0,114,159,0,0,0,114,34,0,0,0,114,32,0, + 0,0,41,5,114,102,0,0,0,114,121,0,0,0,114,96, + 0,0,0,90,13,102,105,108,101,110,97,109,101,95,98,97, + 115,101,90,9,116,97,105,108,95,110,97,109,101,114,2,0, + 0,0,114,2,0,0,0,114,4,0,0,0,114,161,0,0, + 0,199,2,0,0,115,8,0,0,0,0,3,18,1,16,1, + 14,1,122,24,95,76,111,97,100,101,114,66,97,115,105,99, + 115,46,105,115,95,112,97,99,107,97,103,101,99,2,0,0, + 0,0,0,0,0,2,0,0,0,1,0,0,0,67,0,0, + 0,115,4,0,0,0,100,1,83,0,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,2,0,0,0,41,2, + 114,102,0,0,0,114,166,0,0,0,114,2,0,0,0,114, + 2,0,0,0,114,4,0,0,0,218,13,99,114,101,97,116, + 101,95,109,111,100,117,108,101,207,2,0,0,115,2,0,0, + 0,0,1,122,27,95,76,111,97,100,101,114,66,97,115,105, + 99,115,46,99,114,101,97,116,101,95,109,111,100,117,108,101, + 99,2,0,0,0,0,0,0,0,3,0,0,0,5,0,0, + 0,67,0,0,0,115,56,0,0,0,124,0,160,0,124,1, + 106,1,161,1,125,2,124,2,100,1,107,8,114,36,116,2, + 100,2,160,3,124,1,106,1,161,1,131,1,130,1,116,4, + 160,5,116,6,124,2,124,1,106,7,161,3,1,0,100,1, + 83,0,41,3,122,19,69,120,101,99,117,116,101,32,116,104, + 101,32,109,111,100,117,108,101,46,78,122,52,99,97,110,110, + 111,116,32,108,111,97,100,32,109,111,100,117,108,101,32,123, + 33,114,125,32,119,104,101,110,32,103,101,116,95,99,111,100, + 101,40,41,32,114,101,116,117,114,110,115,32,78,111,110,101, + 41,8,218,8,103,101,116,95,99,111,100,101,114,107,0,0, + 0,114,101,0,0,0,114,48,0,0,0,114,116,0,0,0, + 218,25,95,99,97,108,108,95,119,105,116,104,95,102,114,97, + 109,101,115,95,114,101,109,111,118,101,100,218,4,101,120,101, + 99,114,113,0,0,0,41,3,114,102,0,0,0,218,6,109, + 111,100,117,108,101,114,144,0,0,0,114,2,0,0,0,114, + 2,0,0,0,114,4,0,0,0,218,11,101,120,101,99,95, + 109,111,100,117,108,101,210,2,0,0,115,10,0,0,0,0, + 2,12,1,8,1,6,1,10,1,122,25,95,76,111,97,100, + 101,114,66,97,115,105,99,115,46,101,120,101,99,95,109,111, 100,117,108,101,99,2,0,0,0,0,0,0,0,2,0,0, - 0,1,0,0,0,67,0,0,0,115,6,0,0,0,124,0, - 106,0,83,0,41,1,122,58,82,101,116,117,114,110,32,116, - 104,101,32,112,97,116,104,32,116,111,32,116,104,101,32,115, - 111,117,114,99,101,32,102,105,108,101,32,97,115,32,102,111, - 117,110,100,32,98,121,32,116,104,101,32,102,105,110,100,101, - 114,46,41,1,114,35,0,0,0,41,2,114,102,0,0,0, - 114,121,0,0,0,114,2,0,0,0,114,2,0,0,0,114, - 4,0,0,0,114,159,0,0,0,141,3,0,0,115,2,0, - 0,0,0,3,122,23,70,105,108,101,76,111,97,100,101,114, - 46,103,101,116,95,102,105,108,101,110,97,109,101,99,2,0, - 0,0,0,0,0,0,3,0,0,0,10,0,0,0,67,0, - 0,0,115,44,0,0,0,116,0,160,1,124,1,100,1,161, - 2,143,22,125,2,124,2,160,2,161,0,87,0,2,0,53, - 0,81,0,82,0,163,0,83,0,81,0,82,0,88,0,100, - 2,83,0,41,3,122,39,82,101,116,117,114,110,32,116,104, - 101,32,100,97,116,97,32,102,114,111,109,32,112,97,116,104, - 32,97,115,32,114,97,119,32,98,121,116,101,115,46,218,1, - 114,78,41,3,114,50,0,0,0,114,51,0,0,0,90,4, - 114,101,97,100,41,3,114,102,0,0,0,114,35,0,0,0, - 114,55,0,0,0,114,2,0,0,0,114,2,0,0,0,114, - 4,0,0,0,114,200,0,0,0,146,3,0,0,115,4,0, - 0,0,0,2,14,1,122,19,70,105,108,101,76,111,97,100, - 101,114,46,103,101,116,95,100,97,116,97,99,2,0,0,0, - 0,0,0,0,2,0,0,0,3,0,0,0,67,0,0,0, - 115,18,0,0,0,124,0,160,0,124,1,161,1,114,14,124, - 0,83,0,100,0,83,0,41,1,78,41,1,114,161,0,0, - 0,41,2,114,102,0,0,0,114,191,0,0,0,114,2,0, - 0,0,114,2,0,0,0,114,4,0,0,0,218,19,103,101, - 116,95,114,101,115,111,117,114,99,101,95,114,101,97,100,101, - 114,153,3,0,0,115,6,0,0,0,0,2,10,1,4,1, - 122,30,70,105,108,101,76,111,97,100,101,114,46,103,101,116, - 95,114,101,115,111,117,114,99,101,95,114,101,97,100,101,114, - 99,2,0,0,0,0,0,0,0,3,0,0,0,4,0,0, - 0,67,0,0,0,115,32,0,0,0,116,0,116,1,124,0, - 106,2,131,1,100,1,25,0,124,1,131,2,125,2,116,3, - 160,4,124,2,100,2,161,2,83,0,41,3,78,114,60,0, - 0,0,114,219,0,0,0,41,5,114,28,0,0,0,114,38, - 0,0,0,114,35,0,0,0,114,50,0,0,0,114,51,0, - 0,0,41,3,114,102,0,0,0,218,8,114,101,115,111,117, - 114,99,101,114,35,0,0,0,114,2,0,0,0,114,2,0, - 0,0,114,4,0,0,0,218,13,111,112,101,110,95,114,101, - 115,111,117,114,99,101,159,3,0,0,115,4,0,0,0,0, - 1,20,1,122,24,70,105,108,101,76,111,97,100,101,114,46, - 111,112,101,110,95,114,101,115,111,117,114,99,101,99,2,0, - 0,0,0,0,0,0,3,0,0,0,3,0,0,0,67,0, - 0,0,115,38,0,0,0,124,0,160,0,124,1,161,1,115, - 14,116,1,130,1,116,2,116,3,124,0,106,4,131,1,100, - 1,25,0,124,1,131,2,125,2,124,2,83,0,41,2,78, - 114,60,0,0,0,41,5,218,11,105,115,95,114,101,115,111, - 117,114,99,101,218,17,70,105,108,101,78,111,116,70,111,117, - 110,100,69,114,114,111,114,114,28,0,0,0,114,38,0,0, - 0,114,35,0,0,0,41,3,114,102,0,0,0,114,221,0, - 0,0,114,35,0,0,0,114,2,0,0,0,114,2,0,0, - 0,114,4,0,0,0,218,13,114,101,115,111,117,114,99,101, - 95,112,97,116,104,163,3,0,0,115,8,0,0,0,0,1, - 10,1,4,1,20,1,122,24,70,105,108,101,76,111,97,100, - 101,114,46,114,101,115,111,117,114,99,101,95,112,97,116,104, - 99,2,0,0,0,0,0,0,0,3,0,0,0,3,0,0, - 0,67,0,0,0,115,40,0,0,0,116,0,124,1,107,6, - 114,12,100,1,83,0,116,1,116,2,124,0,106,3,131,1, - 100,2,25,0,124,1,131,2,125,2,116,4,124,2,131,1, - 83,0,41,3,78,70,114,60,0,0,0,41,5,114,25,0, - 0,0,114,28,0,0,0,114,38,0,0,0,114,35,0,0, - 0,114,44,0,0,0,41,3,114,102,0,0,0,114,100,0, - 0,0,114,35,0,0,0,114,2,0,0,0,114,2,0,0, - 0,114,4,0,0,0,114,223,0,0,0,169,3,0,0,115, - 8,0,0,0,0,1,8,1,4,1,20,1,122,22,70,105, - 108,101,76,111,97,100,101,114,46,105,115,95,114,101,115,111, - 117,114,99,101,99,1,0,0,0,0,0,0,0,1,0,0, - 0,5,0,0,0,67,0,0,0,115,24,0,0,0,116,0, - 116,1,160,2,116,3,124,0,106,4,131,1,100,1,25,0, - 161,1,131,1,83,0,41,2,78,114,60,0,0,0,41,5, - 218,4,105,116,101,114,114,1,0,0,0,218,7,108,105,115, - 116,100,105,114,114,38,0,0,0,114,35,0,0,0,41,1, - 114,102,0,0,0,114,2,0,0,0,114,2,0,0,0,114, - 4,0,0,0,218,8,99,111,110,116,101,110,116,115,175,3, - 0,0,115,2,0,0,0,0,1,122,19,70,105,108,101,76, - 111,97,100,101,114,46,99,111,110,116,101,110,116,115,41,17, - 114,107,0,0,0,114,106,0,0,0,114,108,0,0,0,114, - 109,0,0,0,114,186,0,0,0,114,215,0,0,0,114,217, - 0,0,0,114,118,0,0,0,114,194,0,0,0,114,159,0, - 0,0,114,200,0,0,0,114,220,0,0,0,114,222,0,0, - 0,114,225,0,0,0,114,223,0,0,0,114,228,0,0,0, - 90,13,95,95,99,108,97,115,115,99,101,108,108,95,95,114, - 2,0,0,0,114,2,0,0,0,41,1,114,213,0,0,0, - 114,4,0,0,0,114,212,0,0,0,111,3,0,0,115,22, - 0,0,0,12,5,8,6,8,4,8,3,16,12,12,5,8, - 7,12,6,8,4,8,6,8,6,114,212,0,0,0,99,0, - 0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,64, - 0,0,0,115,46,0,0,0,101,0,90,1,100,0,90,2, - 100,1,90,3,100,2,100,3,132,0,90,4,100,4,100,5, - 132,0,90,5,100,6,100,7,156,1,100,8,100,9,132,2, - 90,6,100,10,83,0,41,11,218,16,83,111,117,114,99,101, - 70,105,108,101,76,111,97,100,101,114,122,62,67,111,110,99, - 114,101,116,101,32,105,109,112,108,101,109,101,110,116,97,116, - 105,111,110,32,111,102,32,83,111,117,114,99,101,76,111,97, - 100,101,114,32,117,115,105,110,103,32,116,104,101,32,102,105, - 108,101,32,115,121,115,116,101,109,46,99,2,0,0,0,0, - 0,0,0,3,0,0,0,3,0,0,0,67,0,0,0,115, - 22,0,0,0,116,0,124,1,131,1,125,2,124,2,106,1, - 124,2,106,2,100,1,156,2,83,0,41,2,122,33,82,101, - 116,117,114,110,32,116,104,101,32,109,101,116,97,100,97,116, - 97,32,102,111,114,32,116,104,101,32,112,97,116,104,46,41, - 2,114,149,0,0,0,114,207,0,0,0,41,3,114,39,0, - 0,0,218,8,115,116,95,109,116,105,109,101,90,7,115,116, - 95,115,105,122,101,41,3,114,102,0,0,0,114,35,0,0, - 0,114,211,0,0,0,114,2,0,0,0,114,2,0,0,0, - 114,4,0,0,0,114,197,0,0,0,183,3,0,0,115,4, - 0,0,0,0,2,8,1,122,27,83,111,117,114,99,101,70, - 105,108,101,76,111,97,100,101,114,46,112,97,116,104,95,115, - 116,97,116,115,99,4,0,0,0,0,0,0,0,5,0,0, - 0,5,0,0,0,67,0,0,0,115,24,0,0,0,116,0, - 124,1,131,1,125,4,124,0,106,1,124,2,124,3,124,4, - 100,1,141,3,83,0,41,2,78,41,1,218,5,95,109,111, - 100,101,41,2,114,99,0,0,0,114,198,0,0,0,41,5, - 114,102,0,0,0,114,92,0,0,0,114,91,0,0,0,114, - 54,0,0,0,114,42,0,0,0,114,2,0,0,0,114,2, - 0,0,0,114,4,0,0,0,114,199,0,0,0,188,3,0, - 0,115,4,0,0,0,0,2,8,1,122,32,83,111,117,114, - 99,101,70,105,108,101,76,111,97,100,101,114,46,95,99,97, - 99,104,101,95,98,121,116,101,99,111,100,101,105,182,1,0, - 0,41,1,114,231,0,0,0,99,3,0,0,0,1,0,0, - 0,9,0,0,0,11,0,0,0,67,0,0,0,115,252,0, - 0,0,116,0,124,1,131,1,92,2,125,4,125,5,103,0, - 125,6,124,4,114,52,116,1,124,4,131,1,115,52,116,0, - 124,4,131,1,92,2,125,4,125,7,124,6,160,2,124,7, - 161,1,1,0,113,16,116,3,124,6,131,1,68,0,93,108, - 125,7,116,4,124,4,124,7,131,2,125,4,122,14,116,5, - 160,6,124,4,161,1,1,0,87,0,113,60,4,0,116,7, - 107,10,114,112,1,0,1,0,1,0,89,0,113,60,89,0, - 113,60,4,0,116,8,107,10,114,166,1,0,125,8,1,0, - 122,26,116,9,160,10,100,1,124,4,124,8,161,3,1,0, - 87,0,89,0,162,6,1,0,100,2,83,0,100,2,125,8, - 126,8,88,0,89,0,113,60,88,0,113,60,122,28,116,11, - 124,1,124,2,124,3,131,3,1,0,116,9,160,10,100,3, - 124,1,161,2,1,0,87,0,110,48,4,0,116,8,107,10, - 114,246,1,0,125,8,1,0,122,18,116,9,160,10,100,1, - 124,1,124,8,161,3,1,0,87,0,53,0,100,2,125,8, - 126,8,88,0,89,0,110,2,88,0,100,2,83,0,41,4, - 122,27,87,114,105,116,101,32,98,121,116,101,115,32,100,97, - 116,97,32,116,111,32,97,32,102,105,108,101,46,122,27,99, - 111,117,108,100,32,110,111,116,32,99,114,101,97,116,101,32, - 123,33,114,125,58,32,123,33,114,125,78,122,12,99,114,101, - 97,116,101,100,32,123,33,114,125,41,12,114,38,0,0,0, - 114,46,0,0,0,114,165,0,0,0,114,33,0,0,0,114, - 28,0,0,0,114,1,0,0,0,90,5,109,107,100,105,114, - 218,15,70,105,108,101,69,120,105,115,116,115,69,114,114,111, - 114,114,40,0,0,0,114,116,0,0,0,114,130,0,0,0, - 114,56,0,0,0,41,9,114,102,0,0,0,114,35,0,0, - 0,114,54,0,0,0,114,231,0,0,0,218,6,112,97,114, - 101,110,116,114,96,0,0,0,114,27,0,0,0,114,23,0, - 0,0,114,201,0,0,0,114,2,0,0,0,114,2,0,0, - 0,114,4,0,0,0,114,198,0,0,0,193,3,0,0,115, - 42,0,0,0,0,2,12,1,4,2,12,1,12,1,12,2, - 12,1,10,1,2,1,14,1,14,2,8,1,16,3,6,1, - 8,1,28,1,2,1,12,1,16,1,16,2,8,1,122,25, - 83,111,117,114,99,101,70,105,108,101,76,111,97,100,101,114, - 46,115,101,116,95,100,97,116,97,78,41,7,114,107,0,0, - 0,114,106,0,0,0,114,108,0,0,0,114,109,0,0,0, - 114,197,0,0,0,114,199,0,0,0,114,198,0,0,0,114, - 2,0,0,0,114,2,0,0,0,114,2,0,0,0,114,4, - 0,0,0,114,229,0,0,0,179,3,0,0,115,6,0,0, - 0,12,4,8,5,8,5,114,229,0,0,0,99,0,0,0, - 0,0,0,0,0,0,0,0,0,2,0,0,0,64,0,0, - 0,115,32,0,0,0,101,0,90,1,100,0,90,2,100,1, - 90,3,100,2,100,3,132,0,90,4,100,4,100,5,132,0, - 90,5,100,6,83,0,41,7,218,20,83,111,117,114,99,101, - 108,101,115,115,70,105,108,101,76,111,97,100,101,114,122,45, - 76,111,97,100,101,114,32,119,104,105,99,104,32,104,97,110, - 100,108,101,115,32,115,111,117,114,99,101,108,101,115,115,32, - 102,105,108,101,32,105,109,112,111,114,116,115,46,99,2,0, - 0,0,0,0,0,0,5,0,0,0,5,0,0,0,67,0, - 0,0,115,68,0,0,0,124,0,160,0,124,1,161,1,125, - 2,124,0,160,1,124,2,161,1,125,3,124,1,124,2,100, - 1,156,2,125,4,116,2,124,3,124,1,124,4,131,3,1, - 0,116,3,116,4,124,3,131,1,100,2,100,0,133,2,25, - 0,124,1,124,2,100,3,141,3,83,0,41,4,78,41,2, - 114,100,0,0,0,114,35,0,0,0,114,126,0,0,0,41, - 2,114,100,0,0,0,114,91,0,0,0,41,5,114,159,0, - 0,0,114,200,0,0,0,114,133,0,0,0,114,145,0,0, - 0,114,208,0,0,0,41,5,114,102,0,0,0,114,121,0, - 0,0,114,35,0,0,0,114,54,0,0,0,114,132,0,0, - 0,114,2,0,0,0,114,2,0,0,0,114,4,0,0,0, - 114,188,0,0,0,228,3,0,0,115,18,0,0,0,0,1, - 10,1,10,4,2,1,8,2,12,1,2,1,14,1,2,1, - 122,29,83,111,117,114,99,101,108,101,115,115,70,105,108,101, - 76,111,97,100,101,114,46,103,101,116,95,99,111,100,101,99, - 2,0,0,0,0,0,0,0,2,0,0,0,1,0,0,0, - 67,0,0,0,115,4,0,0,0,100,1,83,0,41,2,122, - 39,82,101,116,117,114,110,32,78,111,110,101,32,97,115,32, - 116,104,101,114,101,32,105,115,32,110,111,32,115,111,117,114, - 99,101,32,99,111,100,101,46,78,114,2,0,0,0,41,2, - 114,102,0,0,0,114,121,0,0,0,114,2,0,0,0,114, - 2,0,0,0,114,4,0,0,0,114,202,0,0,0,244,3, - 0,0,115,2,0,0,0,0,2,122,31,83,111,117,114,99, - 101,108,101,115,115,70,105,108,101,76,111,97,100,101,114,46, - 103,101,116,95,115,111,117,114,99,101,78,41,6,114,107,0, - 0,0,114,106,0,0,0,114,108,0,0,0,114,109,0,0, - 0,114,188,0,0,0,114,202,0,0,0,114,2,0,0,0, + 0,4,0,0,0,67,0,0,0,115,12,0,0,0,116,0, + 160,1,124,0,124,1,161,2,83,0,41,1,122,26,84,104, + 105,115,32,109,111,100,117,108,101,32,105,115,32,100,101,112, + 114,101,99,97,116,101,100,46,41,2,114,116,0,0,0,218, + 17,95,108,111,97,100,95,109,111,100,117,108,101,95,115,104, + 105,109,41,2,114,102,0,0,0,114,121,0,0,0,114,2, + 0,0,0,114,2,0,0,0,114,4,0,0,0,218,11,108, + 111,97,100,95,109,111,100,117,108,101,218,2,0,0,115,2, + 0,0,0,0,2,122,25,95,76,111,97,100,101,114,66,97, + 115,105,99,115,46,108,111,97,100,95,109,111,100,117,108,101, + 78,41,8,114,107,0,0,0,114,106,0,0,0,114,108,0, + 0,0,114,109,0,0,0,114,161,0,0,0,114,187,0,0, + 0,114,192,0,0,0,114,194,0,0,0,114,2,0,0,0, 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,114, - 234,0,0,0,224,3,0,0,115,4,0,0,0,12,4,8, - 16,114,234,0,0,0,99,0,0,0,0,0,0,0,0,0, - 0,0,0,3,0,0,0,64,0,0,0,115,92,0,0,0, - 101,0,90,1,100,0,90,2,100,1,90,3,100,2,100,3, - 132,0,90,4,100,4,100,5,132,0,90,5,100,6,100,7, - 132,0,90,6,100,8,100,9,132,0,90,7,100,10,100,11, - 132,0,90,8,100,12,100,13,132,0,90,9,100,14,100,15, - 132,0,90,10,100,16,100,17,132,0,90,11,101,12,100,18, - 100,19,132,0,131,1,90,13,100,20,83,0,41,21,218,19, - 69,120,116,101,110,115,105,111,110,70,105,108,101,76,111,97, - 100,101,114,122,93,76,111,97,100,101,114,32,102,111,114,32, - 101,120,116,101,110,115,105,111,110,32,109,111,100,117,108,101, - 115,46,10,10,32,32,32,32,84,104,101,32,99,111,110,115, - 116,114,117,99,116,111,114,32,105,115,32,100,101,115,105,103, - 110,101,100,32,116,111,32,119,111,114,107,32,119,105,116,104, - 32,70,105,108,101,70,105,110,100,101,114,46,10,10,32,32, - 32,32,99,3,0,0,0,0,0,0,0,3,0,0,0,2, - 0,0,0,67,0,0,0,115,16,0,0,0,124,1,124,0, - 95,0,124,2,124,0,95,1,100,0,83,0,41,1,78,41, - 2,114,100,0,0,0,114,35,0,0,0,41,3,114,102,0, - 0,0,114,100,0,0,0,114,35,0,0,0,114,2,0,0, - 0,114,2,0,0,0,114,4,0,0,0,114,186,0,0,0, - 5,4,0,0,115,4,0,0,0,0,1,6,1,122,28,69, - 120,116,101,110,115,105,111,110,70,105,108,101,76,111,97,100, - 101,114,46,95,95,105,110,105,116,95,95,99,2,0,0,0, - 0,0,0,0,2,0,0,0,2,0,0,0,67,0,0,0, - 115,24,0,0,0,124,0,106,0,124,1,106,0,107,2,111, - 22,124,0,106,1,124,1,106,1,107,2,83,0,41,1,78, - 41,2,114,213,0,0,0,114,113,0,0,0,41,2,114,102, - 0,0,0,114,214,0,0,0,114,2,0,0,0,114,2,0, - 0,0,114,4,0,0,0,114,215,0,0,0,9,4,0,0, - 115,4,0,0,0,0,1,12,1,122,26,69,120,116,101,110, - 115,105,111,110,70,105,108,101,76,111,97,100,101,114,46,95, - 95,101,113,95,95,99,1,0,0,0,0,0,0,0,1,0, - 0,0,3,0,0,0,67,0,0,0,115,20,0,0,0,116, - 0,124,0,106,1,131,1,116,0,124,0,106,2,131,1,65, - 0,83,0,41,1,78,41,3,114,216,0,0,0,114,100,0, - 0,0,114,35,0,0,0,41,1,114,102,0,0,0,114,2, - 0,0,0,114,2,0,0,0,114,4,0,0,0,114,217,0, - 0,0,13,4,0,0,115,2,0,0,0,0,1,122,28,69, - 120,116,101,110,115,105,111,110,70,105,108,101,76,111,97,100, - 101,114,46,95,95,104,97,115,104,95,95,99,2,0,0,0, - 0,0,0,0,3,0,0,0,5,0,0,0,67,0,0,0, - 115,36,0,0,0,116,0,160,1,116,2,106,3,124,1,161, - 2,125,2,116,0,160,4,100,1,124,1,106,5,124,0,106, - 6,161,3,1,0,124,2,83,0,41,2,122,38,67,114,101, - 97,116,101,32,97,110,32,117,110,105,116,105,97,108,105,122, - 101,100,32,101,120,116,101,110,115,105,111,110,32,109,111,100, - 117,108,101,122,38,101,120,116,101,110,115,105,111,110,32,109, - 111,100,117,108,101,32,123,33,114,125,32,108,111,97,100,101, - 100,32,102,114,111,109,32,123,33,114,125,41,7,114,116,0, - 0,0,114,189,0,0,0,114,143,0,0,0,90,14,99,114, - 101,97,116,101,95,100,121,110,97,109,105,99,114,130,0,0, - 0,114,100,0,0,0,114,35,0,0,0,41,3,114,102,0, - 0,0,114,166,0,0,0,114,191,0,0,0,114,2,0,0, - 0,114,2,0,0,0,114,4,0,0,0,114,187,0,0,0, - 16,4,0,0,115,10,0,0,0,0,2,4,1,10,1,6, - 1,12,1,122,33,69,120,116,101,110,115,105,111,110,70,105, - 108,101,76,111,97,100,101,114,46,99,114,101,97,116,101,95, - 109,111,100,117,108,101,99,2,0,0,0,0,0,0,0,2, - 0,0,0,5,0,0,0,67,0,0,0,115,36,0,0,0, - 116,0,160,1,116,2,106,3,124,1,161,2,1,0,116,0, - 160,4,100,1,124,0,106,5,124,0,106,6,161,3,1,0, - 100,2,83,0,41,3,122,30,73,110,105,116,105,97,108,105, - 122,101,32,97,110,32,101,120,116,101,110,115,105,111,110,32, - 109,111,100,117,108,101,122,40,101,120,116,101,110,115,105,111, - 110,32,109,111,100,117,108,101,32,123,33,114,125,32,101,120, - 101,99,117,116,101,100,32,102,114,111,109,32,123,33,114,125, - 78,41,7,114,116,0,0,0,114,189,0,0,0,114,143,0, - 0,0,90,12,101,120,101,99,95,100,121,110,97,109,105,99, - 114,130,0,0,0,114,100,0,0,0,114,35,0,0,0,41, - 2,114,102,0,0,0,114,191,0,0,0,114,2,0,0,0, - 114,2,0,0,0,114,4,0,0,0,114,192,0,0,0,24, - 4,0,0,115,6,0,0,0,0,2,14,1,6,1,122,31, - 69,120,116,101,110,115,105,111,110,70,105,108,101,76,111,97, - 100,101,114,46,101,120,101,99,95,109,111,100,117,108,101,99, - 2,0,0,0,0,0,0,0,2,0,0,0,4,0,0,0, - 3,0,0,0,115,36,0,0,0,116,0,124,0,106,1,131, - 1,100,1,25,0,137,0,116,2,135,0,102,1,100,2,100, - 3,132,8,116,3,68,0,131,1,131,1,83,0,41,4,122, - 49,82,101,116,117,114,110,32,84,114,117,101,32,105,102,32, - 116,104,101,32,101,120,116,101,110,115,105,111,110,32,109,111, - 100,117,108,101,32,105,115,32,97,32,112,97,99,107,97,103, - 101,46,114,29,0,0,0,99,1,0,0,0,0,0,0,0, - 2,0,0,0,4,0,0,0,51,0,0,0,115,26,0,0, - 0,124,0,93,18,125,1,136,0,100,0,124,1,23,0,107, - 2,86,0,1,0,113,2,100,1,83,0,41,2,114,186,0, - 0,0,78,114,2,0,0,0,41,2,114,22,0,0,0,218, - 6,115,117,102,102,105,120,41,1,218,9,102,105,108,101,95, - 110,97,109,101,114,2,0,0,0,114,4,0,0,0,218,9, - 60,103,101,110,101,120,112,114,62,33,4,0,0,115,2,0, - 0,0,4,1,122,49,69,120,116,101,110,115,105,111,110,70, - 105,108,101,76,111,97,100,101,114,46,105,115,95,112,97,99, - 107,97,103,101,46,60,108,111,99,97,108,115,62,46,60,103, - 101,110,101,120,112,114,62,41,4,114,38,0,0,0,114,35, - 0,0,0,218,3,97,110,121,218,18,69,88,84,69,78,83, - 73,79,78,95,83,85,70,70,73,88,69,83,41,2,114,102, - 0,0,0,114,121,0,0,0,114,2,0,0,0,41,1,114, - 237,0,0,0,114,4,0,0,0,114,161,0,0,0,30,4, - 0,0,115,6,0,0,0,0,2,14,1,12,1,122,30,69, - 120,116,101,110,115,105,111,110,70,105,108,101,76,111,97,100, - 101,114,46,105,115,95,112,97,99,107,97,103,101,99,2,0, - 0,0,0,0,0,0,2,0,0,0,1,0,0,0,67,0, - 0,0,115,4,0,0,0,100,1,83,0,41,2,122,63,82, - 101,116,117,114,110,32,78,111,110,101,32,97,115,32,97,110, - 32,101,120,116,101,110,115,105,111,110,32,109,111,100,117,108, - 101,32,99,97,110,110,111,116,32,99,114,101,97,116,101,32, - 97,32,99,111,100,101,32,111,98,106,101,99,116,46,78,114, - 2,0,0,0,41,2,114,102,0,0,0,114,121,0,0,0, + 185,0,0,0,194,2,0,0,115,10,0,0,0,8,3,4, + 2,8,8,8,3,8,8,114,185,0,0,0,99,0,0,0, + 0,0,0,0,0,0,0,0,0,3,0,0,0,64,0,0, + 0,115,74,0,0,0,101,0,90,1,100,0,90,2,100,1, + 100,2,132,0,90,3,100,3,100,4,132,0,90,4,100,5, + 100,6,132,0,90,5,100,7,100,8,132,0,90,6,100,9, + 100,10,132,0,90,7,100,11,100,12,156,1,100,13,100,14, + 132,2,90,8,100,15,100,16,132,0,90,9,100,17,83,0, + 41,18,218,12,83,111,117,114,99,101,76,111,97,100,101,114, + 99,2,0,0,0,0,0,0,0,2,0,0,0,1,0,0, + 0,67,0,0,0,115,8,0,0,0,116,0,130,1,100,1, + 83,0,41,2,122,178,79,112,116,105,111,110,97,108,32,109, + 101,116,104,111,100,32,116,104,97,116,32,114,101,116,117,114, + 110,115,32,116,104,101,32,109,111,100,105,102,105,99,97,116, + 105,111,110,32,116,105,109,101,32,40,97,110,32,105,110,116, + 41,32,102,111,114,32,116,104,101,10,32,32,32,32,32,32, + 32,32,115,112,101,99,105,102,105,101,100,32,112,97,116,104, + 44,32,119,104,101,114,101,32,112,97,116,104,32,105,115,32, + 97,32,115,116,114,46,10,10,32,32,32,32,32,32,32,32, + 82,97,105,115,101,115,32,79,83,69,114,114,111,114,32,119, + 104,101,110,32,116,104,101,32,112,97,116,104,32,99,97,110, + 110,111,116,32,98,101,32,104,97,110,100,108,101,100,46,10, + 32,32,32,32,32,32,32,32,78,41,1,114,40,0,0,0, + 41,2,114,102,0,0,0,114,35,0,0,0,114,2,0,0, + 0,114,2,0,0,0,114,4,0,0,0,218,10,112,97,116, + 104,95,109,116,105,109,101,225,2,0,0,115,2,0,0,0, + 0,6,122,23,83,111,117,114,99,101,76,111,97,100,101,114, + 46,112,97,116,104,95,109,116,105,109,101,99,2,0,0,0, + 0,0,0,0,2,0,0,0,4,0,0,0,67,0,0,0, + 115,14,0,0,0,100,1,124,0,160,0,124,1,161,1,105, + 1,83,0,41,2,97,170,1,0,0,79,112,116,105,111,110, + 97,108,32,109,101,116,104,111,100,32,114,101,116,117,114,110, + 105,110,103,32,97,32,109,101,116,97,100,97,116,97,32,100, + 105,99,116,32,102,111,114,32,116,104,101,32,115,112,101,99, + 105,102,105,101,100,32,112,97,116,104,10,32,32,32,32,32, + 32,32,32,116,111,32,98,121,32,116,104,101,32,112,97,116, + 104,32,40,115,116,114,41,46,10,32,32,32,32,32,32,32, + 32,80,111,115,115,105,98,108,101,32,107,101,121,115,58,10, + 32,32,32,32,32,32,32,32,45,32,39,109,116,105,109,101, + 39,32,40,109,97,110,100,97,116,111,114,121,41,32,105,115, + 32,116,104,101,32,110,117,109,101,114,105,99,32,116,105,109, + 101,115,116,97,109,112,32,111,102,32,108,97,115,116,32,115, + 111,117,114,99,101,10,32,32,32,32,32,32,32,32,32,32, + 99,111,100,101,32,109,111,100,105,102,105,99,97,116,105,111, + 110,59,10,32,32,32,32,32,32,32,32,45,32,39,115,105, + 122,101,39,32,40,111,112,116,105,111,110,97,108,41,32,105, + 115,32,116,104,101,32,115,105,122,101,32,105,110,32,98,121, + 116,101,115,32,111,102,32,116,104,101,32,115,111,117,114,99, + 101,32,99,111,100,101,46,10,10,32,32,32,32,32,32,32, + 32,73,109,112,108,101,109,101,110,116,105,110,103,32,116,104, + 105,115,32,109,101,116,104,111,100,32,97,108,108,111,119,115, + 32,116,104,101,32,108,111,97,100,101,114,32,116,111,32,114, + 101,97,100,32,98,121,116,101,99,111,100,101,32,102,105,108, + 101,115,46,10,32,32,32,32,32,32,32,32,82,97,105,115, + 101,115,32,79,83,69,114,114,111,114,32,119,104,101,110,32, + 116,104,101,32,112,97,116,104,32,99,97,110,110,111,116,32, + 98,101,32,104,97,110,100,108,101,100,46,10,32,32,32,32, + 32,32,32,32,114,149,0,0,0,41,1,114,196,0,0,0, + 41,2,114,102,0,0,0,114,35,0,0,0,114,2,0,0, + 0,114,2,0,0,0,114,4,0,0,0,218,10,112,97,116, + 104,95,115,116,97,116,115,233,2,0,0,115,2,0,0,0, + 0,11,122,23,83,111,117,114,99,101,76,111,97,100,101,114, + 46,112,97,116,104,95,115,116,97,116,115,99,4,0,0,0, + 0,0,0,0,4,0,0,0,4,0,0,0,67,0,0,0, + 115,12,0,0,0,124,0,160,0,124,2,124,3,161,2,83, + 0,41,1,122,228,79,112,116,105,111,110,97,108,32,109,101, + 116,104,111,100,32,119,104,105,99,104,32,119,114,105,116,101, + 115,32,100,97,116,97,32,40,98,121,116,101,115,41,32,116, + 111,32,97,32,102,105,108,101,32,112,97,116,104,32,40,97, + 32,115,116,114,41,46,10,10,32,32,32,32,32,32,32,32, + 73,109,112,108,101,109,101,110,116,105,110,103,32,116,104,105, + 115,32,109,101,116,104,111,100,32,97,108,108,111,119,115,32, + 102,111,114,32,116,104,101,32,119,114,105,116,105,110,103,32, + 111,102,32,98,121,116,101,99,111,100,101,32,102,105,108,101, + 115,46,10,10,32,32,32,32,32,32,32,32,84,104,101,32, + 115,111,117,114,99,101,32,112,97,116,104,32,105,115,32,110, + 101,101,100,101,100,32,105,110,32,111,114,100,101,114,32,116, + 111,32,99,111,114,114,101,99,116,108,121,32,116,114,97,110, + 115,102,101,114,32,112,101,114,109,105,115,115,105,111,110,115, + 10,32,32,32,32,32,32,32,32,41,1,218,8,115,101,116, + 95,100,97,116,97,41,4,114,102,0,0,0,114,92,0,0, + 0,90,10,99,97,99,104,101,95,112,97,116,104,114,54,0, + 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, + 0,218,15,95,99,97,99,104,101,95,98,121,116,101,99,111, + 100,101,246,2,0,0,115,2,0,0,0,0,8,122,28,83, + 111,117,114,99,101,76,111,97,100,101,114,46,95,99,97,99, + 104,101,95,98,121,116,101,99,111,100,101,99,3,0,0,0, + 0,0,0,0,3,0,0,0,1,0,0,0,67,0,0,0, + 115,4,0,0,0,100,1,83,0,41,2,122,150,79,112,116, + 105,111,110,97,108,32,109,101,116,104,111,100,32,119,104,105, + 99,104,32,119,114,105,116,101,115,32,100,97,116,97,32,40, + 98,121,116,101,115,41,32,116,111,32,97,32,102,105,108,101, + 32,112,97,116,104,32,40,97,32,115,116,114,41,46,10,10, + 32,32,32,32,32,32,32,32,73,109,112,108,101,109,101,110, + 116,105,110,103,32,116,104,105,115,32,109,101,116,104,111,100, + 32,97,108,108,111,119,115,32,102,111,114,32,116,104,101,32, + 119,114,105,116,105,110,103,32,111,102,32,98,121,116,101,99, + 111,100,101,32,102,105,108,101,115,46,10,32,32,32,32,32, + 32,32,32,78,114,2,0,0,0,41,3,114,102,0,0,0, + 114,35,0,0,0,114,54,0,0,0,114,2,0,0,0,114, + 2,0,0,0,114,4,0,0,0,114,198,0,0,0,0,3, + 0,0,115,2,0,0,0,0,4,122,21,83,111,117,114,99, + 101,76,111,97,100,101,114,46,115,101,116,95,100,97,116,97, + 99,2,0,0,0,0,0,0,0,5,0,0,0,10,0,0, + 0,67,0,0,0,115,82,0,0,0,124,0,160,0,124,1, + 161,1,125,2,122,14,124,0,160,1,124,2,161,1,125,3, + 87,0,110,48,4,0,116,2,107,10,114,72,1,0,125,4, + 1,0,122,18,116,3,100,1,124,1,100,2,141,2,124,4, + 130,2,87,0,53,0,100,3,125,4,126,4,88,0,89,0, + 110,2,88,0,116,4,124,3,131,1,83,0,41,4,122,52, + 67,111,110,99,114,101,116,101,32,105,109,112,108,101,109,101, + 110,116,97,116,105,111,110,32,111,102,32,73,110,115,112,101, + 99,116,76,111,97,100,101,114,46,103,101,116,95,115,111,117, + 114,99,101,46,122,39,115,111,117,114,99,101,32,110,111,116, + 32,97,118,97,105,108,97,98,108,101,32,116,104,114,111,117, + 103,104,32,103,101,116,95,100,97,116,97,40,41,41,1,114, + 100,0,0,0,78,41,5,114,159,0,0,0,218,8,103,101, + 116,95,100,97,116,97,114,40,0,0,0,114,101,0,0,0, + 114,157,0,0,0,41,5,114,102,0,0,0,114,121,0,0, + 0,114,35,0,0,0,114,155,0,0,0,218,3,101,120,99, + 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,218, + 10,103,101,116,95,115,111,117,114,99,101,7,3,0,0,115, + 14,0,0,0,0,2,10,1,2,1,14,1,16,1,4,1, + 28,1,122,23,83,111,117,114,99,101,76,111,97,100,101,114, + 46,103,101,116,95,115,111,117,114,99,101,114,89,0,0,0, + 41,1,218,9,95,111,112,116,105,109,105,122,101,99,3,0, + 0,0,1,0,0,0,4,0,0,0,8,0,0,0,67,0, + 0,0,115,22,0,0,0,116,0,106,1,116,2,124,1,124, + 2,100,1,100,2,124,3,100,3,141,6,83,0,41,4,122, + 130,82,101,116,117,114,110,32,116,104,101,32,99,111,100,101, + 32,111,98,106,101,99,116,32,99,111,109,112,105,108,101,100, + 32,102,114,111,109,32,115,111,117,114,99,101,46,10,10,32, + 32,32,32,32,32,32,32,84,104,101,32,39,100,97,116,97, + 39,32,97,114,103,117,109,101,110,116,32,99,97,110,32,98, + 101,32,97,110,121,32,111,98,106,101,99,116,32,116,121,112, + 101,32,116,104,97,116,32,99,111,109,112,105,108,101,40,41, + 32,115,117,112,112,111,114,116,115,46,10,32,32,32,32,32, + 32,32,32,114,190,0,0,0,84,41,2,218,12,100,111,110, + 116,95,105,110,104,101,114,105,116,114,70,0,0,0,41,3, + 114,116,0,0,0,114,189,0,0,0,218,7,99,111,109,112, + 105,108,101,41,4,114,102,0,0,0,114,54,0,0,0,114, + 35,0,0,0,114,203,0,0,0,114,2,0,0,0,114,2, + 0,0,0,114,4,0,0,0,218,14,115,111,117,114,99,101, + 95,116,111,95,99,111,100,101,17,3,0,0,115,4,0,0, + 0,0,5,12,1,122,27,83,111,117,114,99,101,76,111,97, + 100,101,114,46,115,111,117,114,99,101,95,116,111,95,99,111, + 100,101,99,2,0,0,0,0,0,0,0,15,0,0,0,9, + 0,0,0,67,0,0,0,115,46,2,0,0,124,0,160,0, + 124,1,161,1,125,2,100,1,125,3,100,1,125,4,100,1, + 125,5,100,2,125,6,100,3,125,7,122,12,116,1,124,2, + 131,1,125,8,87,0,110,26,4,0,116,2,107,10,114,68, + 1,0,1,0,1,0,100,1,125,8,89,0,144,1,110,48, + 88,0,122,14,124,0,160,3,124,2,161,1,125,9,87,0, + 110,22,4,0,116,4,107,10,114,106,1,0,1,0,1,0, + 89,0,144,1,110,10,88,0,116,5,124,9,100,4,25,0, + 131,1,125,3,122,14,124,0,160,6,124,8,161,1,125,10, + 87,0,110,20,4,0,116,4,107,10,114,154,1,0,1,0, + 1,0,89,0,110,218,88,0,124,1,124,8,100,5,156,2, + 125,11,122,148,116,7,124,10,124,1,124,11,131,3,125,12, + 116,8,124,10,131,1,100,6,100,1,133,2,25,0,125,13, + 124,12,100,7,64,0,100,8,107,3,125,6,124,6,144,1, + 114,36,124,12,100,9,64,0,100,8,107,3,125,7,116,9, + 106,10,100,10,107,3,144,1,114,56,124,7,115,254,116,9, + 106,10,100,11,107,2,144,1,114,56,124,0,160,6,124,2, + 161,1,125,4,116,9,160,11,116,12,124,4,161,2,125,5, + 116,13,124,10,124,5,124,1,124,11,131,4,1,0,110,20, + 116,14,124,10,124,3,124,9,100,12,25,0,124,1,124,11, + 131,5,1,0,87,0,110,26,4,0,116,15,116,16,102,2, + 107,10,144,1,114,84,1,0,1,0,1,0,89,0,110,32, + 88,0,116,17,160,18,100,13,124,8,124,2,161,3,1,0, + 116,19,124,13,124,1,124,8,124,2,100,14,141,4,83,0, + 124,4,100,1,107,8,144,1,114,136,124,0,160,6,124,2, + 161,1,125,4,124,0,160,20,124,4,124,2,161,2,125,14, + 116,17,160,18,100,15,124,2,161,2,1,0,116,21,106,22, + 144,2,115,42,124,8,100,1,107,9,144,2,114,42,124,3, + 100,1,107,9,144,2,114,42,124,6,144,1,114,228,124,5, + 100,1,107,8,144,1,114,214,116,9,160,11,124,4,161,1, + 125,5,116,23,124,14,124,5,124,7,131,3,125,10,110,16, + 116,24,124,14,124,3,116,25,124,4,131,1,131,3,125,10, + 122,30,124,0,160,26,124,2,124,8,124,10,161,3,1,0, + 116,17,160,18,100,16,124,8,161,2,1,0,87,0,110,22, + 4,0,116,2,107,10,144,2,114,40,1,0,1,0,1,0, + 89,0,110,2,88,0,124,14,83,0,41,17,122,190,67,111, + 110,99,114,101,116,101,32,105,109,112,108,101,109,101,110,116, + 97,116,105,111,110,32,111,102,32,73,110,115,112,101,99,116, + 76,111,97,100,101,114,46,103,101,116,95,99,111,100,101,46, + 10,10,32,32,32,32,32,32,32,32,82,101,97,100,105,110, + 103,32,111,102,32,98,121,116,101,99,111,100,101,32,114,101, + 113,117,105,114,101,115,32,112,97,116,104,95,115,116,97,116, + 115,32,116,111,32,98,101,32,105,109,112,108,101,109,101,110, + 116,101,100,46,32,84,111,32,119,114,105,116,101,10,32,32, + 32,32,32,32,32,32,98,121,116,101,99,111,100,101,44,32, + 115,101,116,95,100,97,116,97,32,109,117,115,116,32,97,108, + 115,111,32,98,101,32,105,109,112,108,101,109,101,110,116,101, + 100,46,10,10,32,32,32,32,32,32,32,32,78,70,84,114, + 149,0,0,0,41,2,114,100,0,0,0,114,35,0,0,0, + 114,126,0,0,0,114,29,0,0,0,114,60,0,0,0,114, + 57,0,0,0,90,5,110,101,118,101,114,90,6,97,108,119, + 97,121,115,218,4,115,105,122,101,122,13,123,125,32,109,97, + 116,99,104,101,115,32,123,125,41,3,114,100,0,0,0,114, + 91,0,0,0,114,92,0,0,0,122,19,99,111,100,101,32, + 111,98,106,101,99,116,32,102,114,111,109,32,123,125,122,10, + 119,114,111,116,101,32,123,33,114,125,41,27,114,159,0,0, + 0,114,81,0,0,0,114,68,0,0,0,114,197,0,0,0, + 114,40,0,0,0,114,14,0,0,0,114,200,0,0,0,114, + 133,0,0,0,218,10,109,101,109,111,114,121,118,105,101,119, + 114,143,0,0,0,90,21,99,104,101,99,107,95,104,97,115, + 104,95,98,97,115,101,100,95,112,121,99,115,114,138,0,0, + 0,218,17,95,82,65,87,95,77,65,71,73,67,95,78,85, + 77,66,69,82,114,139,0,0,0,114,137,0,0,0,114,101, + 0,0,0,114,131,0,0,0,114,116,0,0,0,114,130,0, + 0,0,114,145,0,0,0,114,206,0,0,0,114,6,0,0, + 0,218,19,100,111,110,116,95,119,114,105,116,101,95,98,121, + 116,101,99,111,100,101,114,152,0,0,0,114,150,0,0,0, + 114,31,0,0,0,114,199,0,0,0,41,15,114,102,0,0, + 0,114,121,0,0,0,114,92,0,0,0,114,135,0,0,0, + 114,155,0,0,0,114,138,0,0,0,90,10,104,97,115,104, + 95,98,97,115,101,100,90,12,99,104,101,99,107,95,115,111, + 117,114,99,101,114,91,0,0,0,218,2,115,116,114,54,0, + 0,0,114,132,0,0,0,114,69,0,0,0,90,10,98,121, + 116,101,115,95,100,97,116,97,90,11,99,111,100,101,95,111, + 98,106,101,99,116,114,2,0,0,0,114,2,0,0,0,114, + 4,0,0,0,114,188,0,0,0,25,3,0,0,115,134,0, + 0,0,0,7,10,1,4,1,4,1,4,1,4,1,4,1, + 2,1,12,1,14,1,12,2,2,1,14,1,14,1,8,2, + 12,1,2,1,14,1,14,1,6,3,2,1,8,2,2,1, + 12,1,16,1,12,1,6,1,12,1,12,1,4,1,12,1, + 10,1,4,1,2,1,6,2,8,1,8,2,2,1,2,1, + 2,1,6,1,2,1,10,2,20,1,6,2,8,1,6,1, + 6,1,2,1,8,1,10,1,10,1,12,1,12,1,18,1, + 10,1,6,1,10,1,10,1,14,2,6,1,10,1,2,1, + 14,1,16,1,16,1,6,1,122,21,83,111,117,114,99,101, + 76,111,97,100,101,114,46,103,101,116,95,99,111,100,101,78, + 41,10,114,107,0,0,0,114,106,0,0,0,114,108,0,0, + 0,114,196,0,0,0,114,197,0,0,0,114,199,0,0,0, + 114,198,0,0,0,114,202,0,0,0,114,206,0,0,0,114, + 188,0,0,0,114,2,0,0,0,114,2,0,0,0,114,2, + 0,0,0,114,4,0,0,0,114,195,0,0,0,223,2,0, + 0,115,14,0,0,0,8,2,8,8,8,13,8,10,8,7, + 8,10,14,8,114,195,0,0,0,99,0,0,0,0,0,0, + 0,0,0,0,0,0,4,0,0,0,0,0,0,0,115,124, + 0,0,0,101,0,90,1,100,0,90,2,100,1,90,3,100, + 2,100,3,132,0,90,4,100,4,100,5,132,0,90,5,100, + 6,100,7,132,0,90,6,101,7,135,0,102,1,100,8,100, + 9,132,8,131,1,90,8,101,7,100,10,100,11,132,0,131, + 1,90,9,100,12,100,13,132,0,90,10,101,7,100,14,100, + 15,132,0,131,1,90,11,100,16,100,17,132,0,90,12,100, + 18,100,19,132,0,90,13,100,20,100,21,132,0,90,14,100, + 22,100,23,132,0,90,15,135,0,4,0,90,16,83,0,41, + 24,218,10,70,105,108,101,76,111,97,100,101,114,122,103,66, + 97,115,101,32,102,105,108,101,32,108,111,97,100,101,114,32, + 99,108,97,115,115,32,119,104,105,99,104,32,105,109,112,108, + 101,109,101,110,116,115,32,116,104,101,32,108,111,97,100,101, + 114,32,112,114,111,116,111,99,111,108,32,109,101,116,104,111, + 100,115,32,116,104,97,116,10,32,32,32,32,114,101,113,117, + 105,114,101,32,102,105,108,101,32,115,121,115,116,101,109,32, + 117,115,97,103,101,46,99,3,0,0,0,0,0,0,0,3, + 0,0,0,2,0,0,0,67,0,0,0,115,16,0,0,0, + 124,1,124,0,95,0,124,2,124,0,95,1,100,1,83,0, + 41,2,122,75,67,97,99,104,101,32,116,104,101,32,109,111, + 100,117,108,101,32,110,97,109,101,32,97,110,100,32,116,104, + 101,32,112,97,116,104,32,116,111,32,116,104,101,32,102,105, + 108,101,32,102,111,117,110,100,32,98,121,32,116,104,101,10, + 32,32,32,32,32,32,32,32,102,105,110,100,101,114,46,78, + 41,2,114,100,0,0,0,114,35,0,0,0,41,3,114,102, + 0,0,0,114,121,0,0,0,114,35,0,0,0,114,2,0, + 0,0,114,2,0,0,0,114,4,0,0,0,114,186,0,0, + 0,116,3,0,0,115,4,0,0,0,0,3,6,1,122,19, + 70,105,108,101,76,111,97,100,101,114,46,95,95,105,110,105, + 116,95,95,99,2,0,0,0,0,0,0,0,2,0,0,0, + 2,0,0,0,67,0,0,0,115,24,0,0,0,124,0,106, + 0,124,1,106,0,107,2,111,22,124,0,106,1,124,1,106, + 1,107,2,83,0,41,1,78,41,2,218,9,95,95,99,108, + 97,115,115,95,95,114,113,0,0,0,41,2,114,102,0,0, + 0,218,5,111,116,104,101,114,114,2,0,0,0,114,2,0, + 0,0,114,4,0,0,0,218,6,95,95,101,113,95,95,122, + 3,0,0,115,4,0,0,0,0,1,12,1,122,17,70,105, + 108,101,76,111,97,100,101,114,46,95,95,101,113,95,95,99, + 1,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0, + 67,0,0,0,115,20,0,0,0,116,0,124,0,106,1,131, + 1,116,0,124,0,106,2,131,1,65,0,83,0,41,1,78, + 41,3,218,4,104,97,115,104,114,100,0,0,0,114,35,0, + 0,0,41,1,114,102,0,0,0,114,2,0,0,0,114,2, + 0,0,0,114,4,0,0,0,218,8,95,95,104,97,115,104, + 95,95,126,3,0,0,115,2,0,0,0,0,1,122,19,70, + 105,108,101,76,111,97,100,101,114,46,95,95,104,97,115,104, + 95,95,99,2,0,0,0,0,0,0,0,2,0,0,0,3, + 0,0,0,3,0,0,0,115,16,0,0,0,116,0,116,1, + 124,0,131,2,160,2,124,1,161,1,83,0,41,1,122,100, + 76,111,97,100,32,97,32,109,111,100,117,108,101,32,102,114, + 111,109,32,97,32,102,105,108,101,46,10,10,32,32,32,32, + 32,32,32,32,84,104,105,115,32,109,101,116,104,111,100,32, + 105,115,32,100,101,112,114,101,99,97,116,101,100,46,32,32, + 85,115,101,32,101,120,101,99,95,109,111,100,117,108,101,40, + 41,32,105,110,115,116,101,97,100,46,10,10,32,32,32,32, + 32,32,32,32,41,3,218,5,115,117,112,101,114,114,212,0, + 0,0,114,194,0,0,0,41,2,114,102,0,0,0,114,121, + 0,0,0,41,1,114,213,0,0,0,114,2,0,0,0,114, + 4,0,0,0,114,194,0,0,0,129,3,0,0,115,2,0, + 0,0,0,10,122,22,70,105,108,101,76,111,97,100,101,114, + 46,108,111,97,100,95,109,111,100,117,108,101,99,2,0,0, + 0,0,0,0,0,2,0,0,0,1,0,0,0,67,0,0, + 0,115,6,0,0,0,124,0,106,0,83,0,41,1,122,58, + 82,101,116,117,114,110,32,116,104,101,32,112,97,116,104,32, + 116,111,32,116,104,101,32,115,111,117,114,99,101,32,102,105, + 108,101,32,97,115,32,102,111,117,110,100,32,98,121,32,116, + 104,101,32,102,105,110,100,101,114,46,41,1,114,35,0,0, + 0,41,2,114,102,0,0,0,114,121,0,0,0,114,2,0, + 0,0,114,2,0,0,0,114,4,0,0,0,114,159,0,0, + 0,141,3,0,0,115,2,0,0,0,0,3,122,23,70,105, + 108,101,76,111,97,100,101,114,46,103,101,116,95,102,105,108, + 101,110,97,109,101,99,2,0,0,0,0,0,0,0,3,0, + 0,0,10,0,0,0,67,0,0,0,115,44,0,0,0,116, + 0,160,1,124,1,100,1,161,2,143,22,125,2,124,2,160, + 2,161,0,87,0,2,0,53,0,81,0,82,0,163,0,83, + 0,81,0,82,0,88,0,100,2,83,0,41,3,122,39,82, + 101,116,117,114,110,32,116,104,101,32,100,97,116,97,32,102, + 114,111,109,32,112,97,116,104,32,97,115,32,114,97,119,32, + 98,121,116,101,115,46,218,1,114,78,41,3,114,50,0,0, + 0,114,51,0,0,0,90,4,114,101,97,100,41,3,114,102, + 0,0,0,114,35,0,0,0,114,55,0,0,0,114,2,0, + 0,0,114,2,0,0,0,114,4,0,0,0,114,200,0,0, + 0,146,3,0,0,115,4,0,0,0,0,2,14,1,122,19, + 70,105,108,101,76,111,97,100,101,114,46,103,101,116,95,100, + 97,116,97,99,2,0,0,0,0,0,0,0,2,0,0,0, + 3,0,0,0,67,0,0,0,115,18,0,0,0,124,0,160, + 0,124,1,161,1,114,14,124,0,83,0,100,0,83,0,41, + 1,78,41,1,114,161,0,0,0,41,2,114,102,0,0,0, + 114,191,0,0,0,114,2,0,0,0,114,2,0,0,0,114, + 4,0,0,0,218,19,103,101,116,95,114,101,115,111,117,114, + 99,101,95,114,101,97,100,101,114,153,3,0,0,115,6,0, + 0,0,0,2,10,1,4,1,122,30,70,105,108,101,76,111, + 97,100,101,114,46,103,101,116,95,114,101,115,111,117,114,99, + 101,95,114,101,97,100,101,114,99,2,0,0,0,0,0,0, + 0,3,0,0,0,4,0,0,0,67,0,0,0,115,32,0, + 0,0,116,0,116,1,124,0,106,2,131,1,100,1,25,0, + 124,1,131,2,125,2,116,3,160,4,124,2,100,2,161,2, + 83,0,41,3,78,114,60,0,0,0,114,219,0,0,0,41, + 5,114,28,0,0,0,114,38,0,0,0,114,35,0,0,0, + 114,50,0,0,0,114,51,0,0,0,41,3,114,102,0,0, + 0,218,8,114,101,115,111,117,114,99,101,114,35,0,0,0, + 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,218, + 13,111,112,101,110,95,114,101,115,111,117,114,99,101,159,3, + 0,0,115,4,0,0,0,0,1,20,1,122,24,70,105,108, + 101,76,111,97,100,101,114,46,111,112,101,110,95,114,101,115, + 111,117,114,99,101,99,2,0,0,0,0,0,0,0,3,0, + 0,0,3,0,0,0,67,0,0,0,115,38,0,0,0,124, + 0,160,0,124,1,161,1,115,14,116,1,130,1,116,2,116, + 3,124,0,106,4,131,1,100,1,25,0,124,1,131,2,125, + 2,124,2,83,0,41,2,78,114,60,0,0,0,41,5,218, + 11,105,115,95,114,101,115,111,117,114,99,101,218,17,70,105, + 108,101,78,111,116,70,111,117,110,100,69,114,114,111,114,114, + 28,0,0,0,114,38,0,0,0,114,35,0,0,0,41,3, + 114,102,0,0,0,114,221,0,0,0,114,35,0,0,0,114, + 2,0,0,0,114,2,0,0,0,114,4,0,0,0,218,13, + 114,101,115,111,117,114,99,101,95,112,97,116,104,163,3,0, + 0,115,8,0,0,0,0,1,10,1,4,1,20,1,122,24, + 70,105,108,101,76,111,97,100,101,114,46,114,101,115,111,117, + 114,99,101,95,112,97,116,104,99,2,0,0,0,0,0,0, + 0,3,0,0,0,3,0,0,0,67,0,0,0,115,40,0, + 0,0,116,0,124,1,107,6,114,12,100,1,83,0,116,1, + 116,2,124,0,106,3,131,1,100,2,25,0,124,1,131,2, + 125,2,116,4,124,2,131,1,83,0,41,3,78,70,114,60, + 0,0,0,41,5,114,25,0,0,0,114,28,0,0,0,114, + 38,0,0,0,114,35,0,0,0,114,44,0,0,0,41,3, + 114,102,0,0,0,114,100,0,0,0,114,35,0,0,0,114, + 2,0,0,0,114,2,0,0,0,114,4,0,0,0,114,223, + 0,0,0,169,3,0,0,115,8,0,0,0,0,1,8,1, + 4,1,20,1,122,22,70,105,108,101,76,111,97,100,101,114, + 46,105,115,95,114,101,115,111,117,114,99,101,99,1,0,0, + 0,0,0,0,0,1,0,0,0,5,0,0,0,67,0,0, + 0,115,24,0,0,0,116,0,116,1,160,2,116,3,124,0, + 106,4,131,1,100,1,25,0,161,1,131,1,83,0,41,2, + 78,114,60,0,0,0,41,5,218,4,105,116,101,114,114,1, + 0,0,0,218,7,108,105,115,116,100,105,114,114,38,0,0, + 0,114,35,0,0,0,41,1,114,102,0,0,0,114,2,0, + 0,0,114,2,0,0,0,114,4,0,0,0,218,8,99,111, + 110,116,101,110,116,115,175,3,0,0,115,2,0,0,0,0, + 1,122,19,70,105,108,101,76,111,97,100,101,114,46,99,111, + 110,116,101,110,116,115,41,17,114,107,0,0,0,114,106,0, + 0,0,114,108,0,0,0,114,109,0,0,0,114,186,0,0, + 0,114,215,0,0,0,114,217,0,0,0,114,118,0,0,0, + 114,194,0,0,0,114,159,0,0,0,114,200,0,0,0,114, + 220,0,0,0,114,222,0,0,0,114,225,0,0,0,114,223, + 0,0,0,114,228,0,0,0,90,13,95,95,99,108,97,115, + 115,99,101,108,108,95,95,114,2,0,0,0,114,2,0,0, + 0,41,1,114,213,0,0,0,114,4,0,0,0,114,212,0, + 0,0,111,3,0,0,115,24,0,0,0,8,3,4,2,8, + 6,8,4,8,3,16,12,12,5,8,7,12,6,8,4,8, + 6,8,6,114,212,0,0,0,99,0,0,0,0,0,0,0, + 0,0,0,0,0,3,0,0,0,64,0,0,0,115,46,0, + 0,0,101,0,90,1,100,0,90,2,100,1,90,3,100,2, + 100,3,132,0,90,4,100,4,100,5,132,0,90,5,100,6, + 100,7,156,1,100,8,100,9,132,2,90,6,100,10,83,0, + 41,11,218,16,83,111,117,114,99,101,70,105,108,101,76,111, + 97,100,101,114,122,62,67,111,110,99,114,101,116,101,32,105, + 109,112,108,101,109,101,110,116,97,116,105,111,110,32,111,102, + 32,83,111,117,114,99,101,76,111,97,100,101,114,32,117,115, + 105,110,103,32,116,104,101,32,102,105,108,101,32,115,121,115, + 116,101,109,46,99,2,0,0,0,0,0,0,0,3,0,0, + 0,3,0,0,0,67,0,0,0,115,22,0,0,0,116,0, + 124,1,131,1,125,2,124,2,106,1,124,2,106,2,100,1, + 156,2,83,0,41,2,122,33,82,101,116,117,114,110,32,116, + 104,101,32,109,101,116,97,100,97,116,97,32,102,111,114,32, + 116,104,101,32,112,97,116,104,46,41,2,114,149,0,0,0, + 114,207,0,0,0,41,3,114,39,0,0,0,218,8,115,116, + 95,109,116,105,109,101,90,7,115,116,95,115,105,122,101,41, + 3,114,102,0,0,0,114,35,0,0,0,114,211,0,0,0, 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,114, - 188,0,0,0,36,4,0,0,115,2,0,0,0,0,2,122, - 28,69,120,116,101,110,115,105,111,110,70,105,108,101,76,111, - 97,100,101,114,46,103,101,116,95,99,111,100,101,99,2,0, - 0,0,0,0,0,0,2,0,0,0,1,0,0,0,67,0, - 0,0,115,4,0,0,0,100,1,83,0,41,2,122,53,82, - 101,116,117,114,110,32,78,111,110,101,32,97,115,32,101,120, - 116,101,110,115,105,111,110,32,109,111,100,117,108,101,115,32, - 104,97,118,101,32,110,111,32,115,111,117,114,99,101,32,99, + 197,0,0,0,183,3,0,0,115,4,0,0,0,0,2,8, + 1,122,27,83,111,117,114,99,101,70,105,108,101,76,111,97, + 100,101,114,46,112,97,116,104,95,115,116,97,116,115,99,4, + 0,0,0,0,0,0,0,5,0,0,0,5,0,0,0,67, + 0,0,0,115,24,0,0,0,116,0,124,1,131,1,125,4, + 124,0,106,1,124,2,124,3,124,4,100,1,141,3,83,0, + 41,2,78,41,1,218,5,95,109,111,100,101,41,2,114,99, + 0,0,0,114,198,0,0,0,41,5,114,102,0,0,0,114, + 92,0,0,0,114,91,0,0,0,114,54,0,0,0,114,42, + 0,0,0,114,2,0,0,0,114,2,0,0,0,114,4,0, + 0,0,114,199,0,0,0,188,3,0,0,115,4,0,0,0, + 0,2,8,1,122,32,83,111,117,114,99,101,70,105,108,101, + 76,111,97,100,101,114,46,95,99,97,99,104,101,95,98,121, + 116,101,99,111,100,101,105,182,1,0,0,41,1,114,231,0, + 0,0,99,3,0,0,0,1,0,0,0,9,0,0,0,11, + 0,0,0,67,0,0,0,115,252,0,0,0,116,0,124,1, + 131,1,92,2,125,4,125,5,103,0,125,6,124,4,114,52, + 116,1,124,4,131,1,115,52,116,0,124,4,131,1,92,2, + 125,4,125,7,124,6,160,2,124,7,161,1,1,0,113,16, + 116,3,124,6,131,1,68,0,93,108,125,7,116,4,124,4, + 124,7,131,2,125,4,122,14,116,5,160,6,124,4,161,1, + 1,0,87,0,113,60,4,0,116,7,107,10,114,112,1,0, + 1,0,1,0,89,0,113,60,89,0,113,60,4,0,116,8, + 107,10,114,166,1,0,125,8,1,0,122,26,116,9,160,10, + 100,1,124,4,124,8,161,3,1,0,87,0,89,0,162,6, + 1,0,100,2,83,0,100,2,125,8,126,8,88,0,89,0, + 113,60,88,0,113,60,122,28,116,11,124,1,124,2,124,3, + 131,3,1,0,116,9,160,10,100,3,124,1,161,2,1,0, + 87,0,110,48,4,0,116,8,107,10,114,246,1,0,125,8, + 1,0,122,18,116,9,160,10,100,1,124,1,124,8,161,3, + 1,0,87,0,53,0,100,2,125,8,126,8,88,0,89,0, + 110,2,88,0,100,2,83,0,41,4,122,27,87,114,105,116, + 101,32,98,121,116,101,115,32,100,97,116,97,32,116,111,32, + 97,32,102,105,108,101,46,122,27,99,111,117,108,100,32,110, + 111,116,32,99,114,101,97,116,101,32,123,33,114,125,58,32, + 123,33,114,125,78,122,12,99,114,101,97,116,101,100,32,123, + 33,114,125,41,12,114,38,0,0,0,114,46,0,0,0,114, + 165,0,0,0,114,33,0,0,0,114,28,0,0,0,114,1, + 0,0,0,90,5,109,107,100,105,114,218,15,70,105,108,101, + 69,120,105,115,116,115,69,114,114,111,114,114,40,0,0,0, + 114,116,0,0,0,114,130,0,0,0,114,56,0,0,0,41, + 9,114,102,0,0,0,114,35,0,0,0,114,54,0,0,0, + 114,231,0,0,0,218,6,112,97,114,101,110,116,114,96,0, + 0,0,114,27,0,0,0,114,23,0,0,0,114,201,0,0, + 0,114,2,0,0,0,114,2,0,0,0,114,4,0,0,0, + 114,198,0,0,0,193,3,0,0,115,42,0,0,0,0,2, + 12,1,4,2,12,1,12,1,12,2,12,1,10,1,2,1, + 14,1,14,2,8,1,16,3,6,1,8,1,28,1,2,1, + 12,1,16,1,16,2,8,1,122,25,83,111,117,114,99,101, + 70,105,108,101,76,111,97,100,101,114,46,115,101,116,95,100, + 97,116,97,78,41,7,114,107,0,0,0,114,106,0,0,0, + 114,108,0,0,0,114,109,0,0,0,114,197,0,0,0,114, + 199,0,0,0,114,198,0,0,0,114,2,0,0,0,114,2, + 0,0,0,114,2,0,0,0,114,4,0,0,0,114,229,0, + 0,0,179,3,0,0,115,8,0,0,0,8,2,4,2,8, + 5,8,5,114,229,0,0,0,99,0,0,0,0,0,0,0, + 0,0,0,0,0,2,0,0,0,64,0,0,0,115,32,0, + 0,0,101,0,90,1,100,0,90,2,100,1,90,3,100,2, + 100,3,132,0,90,4,100,4,100,5,132,0,90,5,100,6, + 83,0,41,7,218,20,83,111,117,114,99,101,108,101,115,115, + 70,105,108,101,76,111,97,100,101,114,122,45,76,111,97,100, + 101,114,32,119,104,105,99,104,32,104,97,110,100,108,101,115, + 32,115,111,117,114,99,101,108,101,115,115,32,102,105,108,101, + 32,105,109,112,111,114,116,115,46,99,2,0,0,0,0,0, + 0,0,5,0,0,0,5,0,0,0,67,0,0,0,115,68, + 0,0,0,124,0,160,0,124,1,161,1,125,2,124,0,160, + 1,124,2,161,1,125,3,124,1,124,2,100,1,156,2,125, + 4,116,2,124,3,124,1,124,4,131,3,1,0,116,3,116, + 4,124,3,131,1,100,2,100,0,133,2,25,0,124,1,124, + 2,100,3,141,3,83,0,41,4,78,41,2,114,100,0,0, + 0,114,35,0,0,0,114,126,0,0,0,41,2,114,100,0, + 0,0,114,91,0,0,0,41,5,114,159,0,0,0,114,200, + 0,0,0,114,133,0,0,0,114,145,0,0,0,114,208,0, + 0,0,41,5,114,102,0,0,0,114,121,0,0,0,114,35, + 0,0,0,114,54,0,0,0,114,132,0,0,0,114,2,0, + 0,0,114,2,0,0,0,114,4,0,0,0,114,188,0,0, + 0,228,3,0,0,115,18,0,0,0,0,1,10,1,10,4, + 2,1,8,2,12,1,2,1,14,1,2,1,122,29,83,111, + 117,114,99,101,108,101,115,115,70,105,108,101,76,111,97,100, + 101,114,46,103,101,116,95,99,111,100,101,99,2,0,0,0, + 0,0,0,0,2,0,0,0,1,0,0,0,67,0,0,0, + 115,4,0,0,0,100,1,83,0,41,2,122,39,82,101,116, + 117,114,110,32,78,111,110,101,32,97,115,32,116,104,101,114, + 101,32,105,115,32,110,111,32,115,111,117,114,99,101,32,99, 111,100,101,46,78,114,2,0,0,0,41,2,114,102,0,0, 0,114,121,0,0,0,114,2,0,0,0,114,2,0,0,0, - 114,4,0,0,0,114,202,0,0,0,40,4,0,0,115,2, - 0,0,0,0,2,122,30,69,120,116,101,110,115,105,111,110, - 70,105,108,101,76,111,97,100,101,114,46,103,101,116,95,115, - 111,117,114,99,101,99,2,0,0,0,0,0,0,0,2,0, - 0,0,1,0,0,0,67,0,0,0,115,6,0,0,0,124, - 0,106,0,83,0,41,1,122,58,82,101,116,117,114,110,32, - 116,104,101,32,112,97,116,104,32,116,111,32,116,104,101,32, - 115,111,117,114,99,101,32,102,105,108,101,32,97,115,32,102, - 111,117,110,100,32,98,121,32,116,104,101,32,102,105,110,100, - 101,114,46,41,1,114,35,0,0,0,41,2,114,102,0,0, - 0,114,121,0,0,0,114,2,0,0,0,114,2,0,0,0, - 114,4,0,0,0,114,159,0,0,0,44,4,0,0,115,2, - 0,0,0,0,3,122,32,69,120,116,101,110,115,105,111,110, - 70,105,108,101,76,111,97,100,101,114,46,103,101,116,95,102, - 105,108,101,110,97,109,101,78,41,14,114,107,0,0,0,114, - 106,0,0,0,114,108,0,0,0,114,109,0,0,0,114,186, - 0,0,0,114,215,0,0,0,114,217,0,0,0,114,187,0, - 0,0,114,192,0,0,0,114,161,0,0,0,114,188,0,0, - 0,114,202,0,0,0,114,118,0,0,0,114,159,0,0,0, - 114,2,0,0,0,114,2,0,0,0,114,2,0,0,0,114, - 4,0,0,0,114,235,0,0,0,253,3,0,0,115,18,0, - 0,0,12,8,8,4,8,4,8,3,8,8,8,6,8,6, + 114,4,0,0,0,114,202,0,0,0,244,3,0,0,115,2, + 0,0,0,0,2,122,31,83,111,117,114,99,101,108,101,115, + 115,70,105,108,101,76,111,97,100,101,114,46,103,101,116,95, + 115,111,117,114,99,101,78,41,6,114,107,0,0,0,114,106, + 0,0,0,114,108,0,0,0,114,109,0,0,0,114,188,0, + 0,0,114,202,0,0,0,114,2,0,0,0,114,2,0,0, + 0,114,2,0,0,0,114,4,0,0,0,114,234,0,0,0, + 224,3,0,0,115,6,0,0,0,8,2,4,2,8,16,114, + 234,0,0,0,99,0,0,0,0,0,0,0,0,0,0,0, + 0,3,0,0,0,64,0,0,0,115,92,0,0,0,101,0, + 90,1,100,0,90,2,100,1,90,3,100,2,100,3,132,0, + 90,4,100,4,100,5,132,0,90,5,100,6,100,7,132,0, + 90,6,100,8,100,9,132,0,90,7,100,10,100,11,132,0, + 90,8,100,12,100,13,132,0,90,9,100,14,100,15,132,0, + 90,10,100,16,100,17,132,0,90,11,101,12,100,18,100,19, + 132,0,131,1,90,13,100,20,83,0,41,21,218,19,69,120, + 116,101,110,115,105,111,110,70,105,108,101,76,111,97,100,101, + 114,122,93,76,111,97,100,101,114,32,102,111,114,32,101,120, + 116,101,110,115,105,111,110,32,109,111,100,117,108,101,115,46, + 10,10,32,32,32,32,84,104,101,32,99,111,110,115,116,114, + 117,99,116,111,114,32,105,115,32,100,101,115,105,103,110,101, + 100,32,116,111,32,119,111,114,107,32,119,105,116,104,32,70, + 105,108,101,70,105,110,100,101,114,46,10,10,32,32,32,32, + 99,3,0,0,0,0,0,0,0,3,0,0,0,2,0,0, + 0,67,0,0,0,115,16,0,0,0,124,1,124,0,95,0, + 124,2,124,0,95,1,100,0,83,0,41,1,78,41,2,114, + 100,0,0,0,114,35,0,0,0,41,3,114,102,0,0,0, + 114,100,0,0,0,114,35,0,0,0,114,2,0,0,0,114, + 2,0,0,0,114,4,0,0,0,114,186,0,0,0,5,4, + 0,0,115,4,0,0,0,0,1,6,1,122,28,69,120,116, + 101,110,115,105,111,110,70,105,108,101,76,111,97,100,101,114, + 46,95,95,105,110,105,116,95,95,99,2,0,0,0,0,0, + 0,0,2,0,0,0,2,0,0,0,67,0,0,0,115,24, + 0,0,0,124,0,106,0,124,1,106,0,107,2,111,22,124, + 0,106,1,124,1,106,1,107,2,83,0,41,1,78,41,2, + 114,213,0,0,0,114,113,0,0,0,41,2,114,102,0,0, + 0,114,214,0,0,0,114,2,0,0,0,114,2,0,0,0, + 114,4,0,0,0,114,215,0,0,0,9,4,0,0,115,4, + 0,0,0,0,1,12,1,122,26,69,120,116,101,110,115,105, + 111,110,70,105,108,101,76,111,97,100,101,114,46,95,95,101, + 113,95,95,99,1,0,0,0,0,0,0,0,1,0,0,0, + 3,0,0,0,67,0,0,0,115,20,0,0,0,116,0,124, + 0,106,1,131,1,116,0,124,0,106,2,131,1,65,0,83, + 0,41,1,78,41,3,114,216,0,0,0,114,100,0,0,0, + 114,35,0,0,0,41,1,114,102,0,0,0,114,2,0,0, + 0,114,2,0,0,0,114,4,0,0,0,114,217,0,0,0, + 13,4,0,0,115,2,0,0,0,0,1,122,28,69,120,116, + 101,110,115,105,111,110,70,105,108,101,76,111,97,100,101,114, + 46,95,95,104,97,115,104,95,95,99,2,0,0,0,0,0, + 0,0,3,0,0,0,5,0,0,0,67,0,0,0,115,36, + 0,0,0,116,0,160,1,116,2,106,3,124,1,161,2,125, + 2,116,0,160,4,100,1,124,1,106,5,124,0,106,6,161, + 3,1,0,124,2,83,0,41,2,122,38,67,114,101,97,116, + 101,32,97,110,32,117,110,105,116,105,97,108,105,122,101,100, + 32,101,120,116,101,110,115,105,111,110,32,109,111,100,117,108, + 101,122,38,101,120,116,101,110,115,105,111,110,32,109,111,100, + 117,108,101,32,123,33,114,125,32,108,111,97,100,101,100,32, + 102,114,111,109,32,123,33,114,125,41,7,114,116,0,0,0, + 114,189,0,0,0,114,143,0,0,0,90,14,99,114,101,97, + 116,101,95,100,121,110,97,109,105,99,114,130,0,0,0,114, + 100,0,0,0,114,35,0,0,0,41,3,114,102,0,0,0, + 114,166,0,0,0,114,191,0,0,0,114,2,0,0,0,114, + 2,0,0,0,114,4,0,0,0,114,187,0,0,0,16,4, + 0,0,115,10,0,0,0,0,2,4,1,10,1,6,1,12, + 1,122,33,69,120,116,101,110,115,105,111,110,70,105,108,101, + 76,111,97,100,101,114,46,99,114,101,97,116,101,95,109,111, + 100,117,108,101,99,2,0,0,0,0,0,0,0,2,0,0, + 0,5,0,0,0,67,0,0,0,115,36,0,0,0,116,0, + 160,1,116,2,106,3,124,1,161,2,1,0,116,0,160,4, + 100,1,124,0,106,5,124,0,106,6,161,3,1,0,100,2, + 83,0,41,3,122,30,73,110,105,116,105,97,108,105,122,101, + 32,97,110,32,101,120,116,101,110,115,105,111,110,32,109,111, + 100,117,108,101,122,40,101,120,116,101,110,115,105,111,110,32, + 109,111,100,117,108,101,32,123,33,114,125,32,101,120,101,99, + 117,116,101,100,32,102,114,111,109,32,123,33,114,125,78,41, + 7,114,116,0,0,0,114,189,0,0,0,114,143,0,0,0, + 90,12,101,120,101,99,95,100,121,110,97,109,105,99,114,130, + 0,0,0,114,100,0,0,0,114,35,0,0,0,41,2,114, + 102,0,0,0,114,191,0,0,0,114,2,0,0,0,114,2, + 0,0,0,114,4,0,0,0,114,192,0,0,0,24,4,0, + 0,115,6,0,0,0,0,2,14,1,6,1,122,31,69,120, + 116,101,110,115,105,111,110,70,105,108,101,76,111,97,100,101, + 114,46,101,120,101,99,95,109,111,100,117,108,101,99,2,0, + 0,0,0,0,0,0,2,0,0,0,4,0,0,0,3,0, + 0,0,115,36,0,0,0,116,0,124,0,106,1,131,1,100, + 1,25,0,137,0,116,2,135,0,102,1,100,2,100,3,132, + 8,116,3,68,0,131,1,131,1,83,0,41,4,122,49,82, + 101,116,117,114,110,32,84,114,117,101,32,105,102,32,116,104, + 101,32,101,120,116,101,110,115,105,111,110,32,109,111,100,117, + 108,101,32,105,115,32,97,32,112,97,99,107,97,103,101,46, + 114,29,0,0,0,99,1,0,0,0,0,0,0,0,2,0, + 0,0,4,0,0,0,51,0,0,0,115,26,0,0,0,124, + 0,93,18,125,1,136,0,100,0,124,1,23,0,107,2,86, + 0,1,0,113,2,100,1,83,0,41,2,114,186,0,0,0, + 78,114,2,0,0,0,41,2,114,22,0,0,0,218,6,115, + 117,102,102,105,120,41,1,218,9,102,105,108,101,95,110,97, + 109,101,114,2,0,0,0,114,4,0,0,0,218,9,60,103, + 101,110,101,120,112,114,62,33,4,0,0,115,2,0,0,0, + 4,1,122,49,69,120,116,101,110,115,105,111,110,70,105,108, + 101,76,111,97,100,101,114,46,105,115,95,112,97,99,107,97, + 103,101,46,60,108,111,99,97,108,115,62,46,60,103,101,110, + 101,120,112,114,62,41,4,114,38,0,0,0,114,35,0,0, + 0,218,3,97,110,121,218,18,69,88,84,69,78,83,73,79, + 78,95,83,85,70,70,73,88,69,83,41,2,114,102,0,0, + 0,114,121,0,0,0,114,2,0,0,0,41,1,114,237,0, + 0,0,114,4,0,0,0,114,161,0,0,0,30,4,0,0, + 115,6,0,0,0,0,2,14,1,12,1,122,30,69,120,116, + 101,110,115,105,111,110,70,105,108,101,76,111,97,100,101,114, + 46,105,115,95,112,97,99,107,97,103,101,99,2,0,0,0, + 0,0,0,0,2,0,0,0,1,0,0,0,67,0,0,0, + 115,4,0,0,0,100,1,83,0,41,2,122,63,82,101,116, + 117,114,110,32,78,111,110,101,32,97,115,32,97,110,32,101, + 120,116,101,110,115,105,111,110,32,109,111,100,117,108,101,32, + 99,97,110,110,111,116,32,99,114,101,97,116,101,32,97,32, + 99,111,100,101,32,111,98,106,101,99,116,46,78,114,2,0, + 0,0,41,2,114,102,0,0,0,114,121,0,0,0,114,2, + 0,0,0,114,2,0,0,0,114,4,0,0,0,114,188,0, + 0,0,36,4,0,0,115,2,0,0,0,0,2,122,28,69, + 120,116,101,110,115,105,111,110,70,105,108,101,76,111,97,100, + 101,114,46,103,101,116,95,99,111,100,101,99,2,0,0,0, + 0,0,0,0,2,0,0,0,1,0,0,0,67,0,0,0, + 115,4,0,0,0,100,1,83,0,41,2,122,53,82,101,116, + 117,114,110,32,78,111,110,101,32,97,115,32,101,120,116,101, + 110,115,105,111,110,32,109,111,100,117,108,101,115,32,104,97, + 118,101,32,110,111,32,115,111,117,114,99,101,32,99,111,100, + 101,46,78,114,2,0,0,0,41,2,114,102,0,0,0,114, + 121,0,0,0,114,2,0,0,0,114,2,0,0,0,114,4, + 0,0,0,114,202,0,0,0,40,4,0,0,115,2,0,0, + 0,0,2,122,30,69,120,116,101,110,115,105,111,110,70,105, + 108,101,76,111,97,100,101,114,46,103,101,116,95,115,111,117, + 114,99,101,99,2,0,0,0,0,0,0,0,2,0,0,0, + 1,0,0,0,67,0,0,0,115,6,0,0,0,124,0,106, + 0,83,0,41,1,122,58,82,101,116,117,114,110,32,116,104, + 101,32,112,97,116,104,32,116,111,32,116,104,101,32,115,111, + 117,114,99,101,32,102,105,108,101,32,97,115,32,102,111,117, + 110,100,32,98,121,32,116,104,101,32,102,105,110,100,101,114, + 46,41,1,114,35,0,0,0,41,2,114,102,0,0,0,114, + 121,0,0,0,114,2,0,0,0,114,2,0,0,0,114,4, + 0,0,0,114,159,0,0,0,44,4,0,0,115,2,0,0, + 0,0,3,122,32,69,120,116,101,110,115,105,111,110,70,105, + 108,101,76,111,97,100,101,114,46,103,101,116,95,102,105,108, + 101,110,97,109,101,78,41,14,114,107,0,0,0,114,106,0, + 0,0,114,108,0,0,0,114,109,0,0,0,114,186,0,0, + 0,114,215,0,0,0,114,217,0,0,0,114,187,0,0,0, + 114,192,0,0,0,114,161,0,0,0,114,188,0,0,0,114, + 202,0,0,0,114,118,0,0,0,114,159,0,0,0,114,2, + 0,0,0,114,2,0,0,0,114,2,0,0,0,114,4,0, + 0,0,114,235,0,0,0,253,3,0,0,115,20,0,0,0, + 8,6,4,2,8,4,8,4,8,3,8,8,8,6,8,6, 8,4,8,4,114,235,0,0,0,99,0,0,0,0,0,0, 0,0,0,0,0,0,2,0,0,0,64,0,0,0,115,96, 0,0,0,101,0,90,1,100,0,90,2,100,1,90,3,100, @@ -1874,740 +1875,741 @@ const unsigned char _Py_M__importlib_external[] = { 114,254,0,0,0,114,255,0,0,0,114,0,1,0,0,114, 2,1,0,0,114,165,0,0,0,114,2,0,0,0,114,2, 0,0,0,114,2,0,0,0,114,4,0,0,0,114,241,0, - 0,0,50,4,0,0,115,20,0,0,0,12,7,8,6,8, - 10,8,4,8,13,8,3,8,3,8,3,8,3,8,3,114, - 241,0,0,0,99,0,0,0,0,0,0,0,0,0,0,0, - 0,3,0,0,0,64,0,0,0,115,80,0,0,0,101,0, - 90,1,100,0,90,2,100,1,100,2,132,0,90,3,101,4, - 100,3,100,4,132,0,131,1,90,5,100,5,100,6,132,0, - 90,6,100,7,100,8,132,0,90,7,100,9,100,10,132,0, - 90,8,100,11,100,12,132,0,90,9,100,13,100,14,132,0, - 90,10,100,15,100,16,132,0,90,11,100,17,83,0,41,18, - 218,16,95,78,97,109,101,115,112,97,99,101,76,111,97,100, - 101,114,99,4,0,0,0,0,0,0,0,4,0,0,0,4, - 0,0,0,67,0,0,0,115,18,0,0,0,116,0,124,1, - 124,2,124,3,131,3,124,0,95,1,100,0,83,0,41,1, - 78,41,2,114,241,0,0,0,114,243,0,0,0,41,4,114, - 102,0,0,0,114,100,0,0,0,114,35,0,0,0,114,247, - 0,0,0,114,2,0,0,0,114,2,0,0,0,114,4,0, - 0,0,114,186,0,0,0,111,4,0,0,115,2,0,0,0, - 0,1,122,25,95,78,97,109,101,115,112,97,99,101,76,111, - 97,100,101,114,46,95,95,105,110,105,116,95,95,99,2,0, - 0,0,0,0,0,0,2,0,0,0,3,0,0,0,67,0, - 0,0,115,12,0,0,0,100,1,160,0,124,1,106,1,161, - 1,83,0,41,2,122,115,82,101,116,117,114,110,32,114,101, - 112,114,32,102,111,114,32,116,104,101,32,109,111,100,117,108, - 101,46,10,10,32,32,32,32,32,32,32,32,84,104,101,32, - 109,101,116,104,111,100,32,105,115,32,100,101,112,114,101,99, - 97,116,101,100,46,32,32,84,104,101,32,105,109,112,111,114, - 116,32,109,97,99,104,105,110,101,114,121,32,100,111,101,115, - 32,116,104,101,32,106,111,98,32,105,116,115,101,108,102,46, - 10,10,32,32,32,32,32,32,32,32,122,25,60,109,111,100, - 117,108,101,32,123,33,114,125,32,40,110,97,109,101,115,112, - 97,99,101,41,62,41,2,114,48,0,0,0,114,107,0,0, - 0,41,2,114,172,0,0,0,114,191,0,0,0,114,2,0, - 0,0,114,2,0,0,0,114,4,0,0,0,218,11,109,111, - 100,117,108,101,95,114,101,112,114,114,4,0,0,115,2,0, - 0,0,0,7,122,28,95,78,97,109,101,115,112,97,99,101, - 76,111,97,100,101,114,46,109,111,100,117,108,101,95,114,101, - 112,114,99,2,0,0,0,0,0,0,0,2,0,0,0,1, - 0,0,0,67,0,0,0,115,4,0,0,0,100,1,83,0, - 41,2,78,84,114,2,0,0,0,41,2,114,102,0,0,0, - 114,121,0,0,0,114,2,0,0,0,114,2,0,0,0,114, - 4,0,0,0,114,161,0,0,0,123,4,0,0,115,2,0, - 0,0,0,1,122,27,95,78,97,109,101,115,112,97,99,101, - 76,111,97,100,101,114,46,105,115,95,112,97,99,107,97,103, - 101,99,2,0,0,0,0,0,0,0,2,0,0,0,1,0, - 0,0,67,0,0,0,115,4,0,0,0,100,1,83,0,41, - 2,78,114,30,0,0,0,114,2,0,0,0,41,2,114,102, - 0,0,0,114,121,0,0,0,114,2,0,0,0,114,2,0, - 0,0,114,4,0,0,0,114,202,0,0,0,126,4,0,0, - 115,2,0,0,0,0,1,122,27,95,78,97,109,101,115,112, - 97,99,101,76,111,97,100,101,114,46,103,101,116,95,115,111, - 117,114,99,101,99,2,0,0,0,0,0,0,0,2,0,0, - 0,6,0,0,0,67,0,0,0,115,16,0,0,0,116,0, - 100,1,100,2,100,3,100,4,100,5,141,4,83,0,41,6, - 78,114,30,0,0,0,122,8,60,115,116,114,105,110,103,62, - 114,190,0,0,0,84,41,1,114,204,0,0,0,41,1,114, - 205,0,0,0,41,2,114,102,0,0,0,114,121,0,0,0, - 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,114, - 188,0,0,0,129,4,0,0,115,2,0,0,0,0,1,122, - 25,95,78,97,109,101,115,112,97,99,101,76,111,97,100,101, - 114,46,103,101,116,95,99,111,100,101,99,2,0,0,0,0, - 0,0,0,2,0,0,0,1,0,0,0,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,2,0,0,0,41,2,114,102, - 0,0,0,114,166,0,0,0,114,2,0,0,0,114,2,0, - 0,0,114,4,0,0,0,114,187,0,0,0,132,4,0,0, - 115,0,0,0,0,122,30,95,78,97,109,101,115,112,97,99, - 101,76,111,97,100,101,114,46,99,114,101,97,116,101,95,109, - 111,100,117,108,101,99,2,0,0,0,0,0,0,0,2,0, - 0,0,1,0,0,0,67,0,0,0,115,4,0,0,0,100, - 0,83,0,41,1,78,114,2,0,0,0,41,2,114,102,0, - 0,0,114,191,0,0,0,114,2,0,0,0,114,2,0,0, - 0,114,4,0,0,0,114,192,0,0,0,135,4,0,0,115, - 2,0,0,0,0,1,122,28,95,78,97,109,101,115,112,97, - 99,101,76,111,97,100,101,114,46,101,120,101,99,95,109,111, - 100,117,108,101,99,2,0,0,0,0,0,0,0,2,0,0, - 0,4,0,0,0,67,0,0,0,115,26,0,0,0,116,0, - 160,1,100,1,124,0,106,2,161,2,1,0,116,0,160,3, - 124,0,124,1,161,2,83,0,41,2,122,98,76,111,97,100, - 32,97,32,110,97,109,101,115,112,97,99,101,32,109,111,100, + 0,0,50,4,0,0,115,22,0,0,0,8,5,4,2,8, + 6,8,10,8,4,8,13,8,3,8,3,8,3,8,3,8, + 3,114,241,0,0,0,99,0,0,0,0,0,0,0,0,0, + 0,0,0,3,0,0,0,64,0,0,0,115,80,0,0,0, + 101,0,90,1,100,0,90,2,100,1,100,2,132,0,90,3, + 101,4,100,3,100,4,132,0,131,1,90,5,100,5,100,6, + 132,0,90,6,100,7,100,8,132,0,90,7,100,9,100,10, + 132,0,90,8,100,11,100,12,132,0,90,9,100,13,100,14, + 132,0,90,10,100,15,100,16,132,0,90,11,100,17,83,0, + 41,18,218,16,95,78,97,109,101,115,112,97,99,101,76,111, + 97,100,101,114,99,4,0,0,0,0,0,0,0,4,0,0, + 0,4,0,0,0,67,0,0,0,115,18,0,0,0,116,0, + 124,1,124,2,124,3,131,3,124,0,95,1,100,0,83,0, + 41,1,78,41,2,114,241,0,0,0,114,243,0,0,0,41, + 4,114,102,0,0,0,114,100,0,0,0,114,35,0,0,0, + 114,247,0,0,0,114,2,0,0,0,114,2,0,0,0,114, + 4,0,0,0,114,186,0,0,0,111,4,0,0,115,2,0, + 0,0,0,1,122,25,95,78,97,109,101,115,112,97,99,101, + 76,111,97,100,101,114,46,95,95,105,110,105,116,95,95,99, + 2,0,0,0,0,0,0,0,2,0,0,0,3,0,0,0, + 67,0,0,0,115,12,0,0,0,100,1,160,0,124,1,106, + 1,161,1,83,0,41,2,122,115,82,101,116,117,114,110,32, + 114,101,112,114,32,102,111,114,32,116,104,101,32,109,111,100, 117,108,101,46,10,10,32,32,32,32,32,32,32,32,84,104, - 105,115,32,109,101,116,104,111,100,32,105,115,32,100,101,112, - 114,101,99,97,116,101,100,46,32,32,85,115,101,32,101,120, - 101,99,95,109,111,100,117,108,101,40,41,32,105,110,115,116, - 101,97,100,46,10,10,32,32,32,32,32,32,32,32,122,38, - 110,97,109,101,115,112,97,99,101,32,109,111,100,117,108,101, - 32,108,111,97,100,101,100,32,119,105,116,104,32,112,97,116, - 104,32,123,33,114,125,41,4,114,116,0,0,0,114,130,0, - 0,0,114,243,0,0,0,114,193,0,0,0,41,2,114,102, - 0,0,0,114,121,0,0,0,114,2,0,0,0,114,2,0, - 0,0,114,4,0,0,0,114,194,0,0,0,138,4,0,0, - 115,6,0,0,0,0,7,6,1,8,1,122,28,95,78,97, - 109,101,115,112,97,99,101,76,111,97,100,101,114,46,108,111, - 97,100,95,109,111,100,117,108,101,78,41,12,114,107,0,0, - 0,114,106,0,0,0,114,108,0,0,0,114,186,0,0,0, - 114,184,0,0,0,114,4,1,0,0,114,161,0,0,0,114, - 202,0,0,0,114,188,0,0,0,114,187,0,0,0,114,192, - 0,0,0,114,194,0,0,0,114,2,0,0,0,114,2,0, - 0,0,114,2,0,0,0,114,4,0,0,0,114,3,1,0, - 0,110,4,0,0,115,16,0,0,0,8,1,8,3,12,9, - 8,3,8,3,8,3,8,3,8,3,114,3,1,0,0,99, - 0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0, - 64,0,0,0,115,106,0,0,0,101,0,90,1,100,0,90, - 2,100,1,90,3,101,4,100,2,100,3,132,0,131,1,90, - 5,101,4,100,4,100,5,132,0,131,1,90,6,101,4,100, - 6,100,7,132,0,131,1,90,7,101,4,100,8,100,9,132, - 0,131,1,90,8,101,4,100,17,100,11,100,12,132,1,131, - 1,90,9,101,4,100,18,100,13,100,14,132,1,131,1,90, - 10,101,4,100,19,100,15,100,16,132,1,131,1,90,11,100, - 10,83,0,41,20,218,10,80,97,116,104,70,105,110,100,101, - 114,122,62,77,101,116,97,32,112,97,116,104,32,102,105,110, - 100,101,114,32,102,111,114,32,115,121,115,46,112,97,116,104, - 32,97,110,100,32,112,97,99,107,97,103,101,32,95,95,112, - 97,116,104,95,95,32,97,116,116,114,105,98,117,116,101,115, - 46,99,1,0,0,0,0,0,0,0,3,0,0,0,4,0, - 0,0,67,0,0,0,115,64,0,0,0,116,0,116,1,106, - 2,160,3,161,0,131,1,68,0,93,44,92,2,125,1,125, - 2,124,2,100,1,107,8,114,40,116,1,106,2,124,1,61, - 0,113,14,116,4,124,2,100,2,131,2,114,14,124,2,160, - 5,161,0,1,0,113,14,100,1,83,0,41,3,122,125,67, - 97,108,108,32,116,104,101,32,105,110,118,97,108,105,100,97, - 116,101,95,99,97,99,104,101,115,40,41,32,109,101,116,104, - 111,100,32,111,110,32,97,108,108,32,112,97,116,104,32,101, - 110,116,114,121,32,102,105,110,100,101,114,115,10,32,32,32, - 32,32,32,32,32,115,116,111,114,101,100,32,105,110,32,115, - 121,115,46,112,97,116,104,95,105,109,112,111,114,116,101,114, - 95,99,97,99,104,101,115,32,40,119,104,101,114,101,32,105, - 109,112,108,101,109,101,110,116,101,100,41,46,78,218,17,105, - 110,118,97,108,105,100,97,116,101,95,99,97,99,104,101,115, - 41,6,218,4,108,105,115,116,114,6,0,0,0,218,19,112, - 97,116,104,95,105,109,112,111,114,116,101,114,95,99,97,99, - 104,101,218,5,105,116,101,109,115,114,110,0,0,0,114,6, - 1,0,0,41,3,114,172,0,0,0,114,100,0,0,0,218, - 6,102,105,110,100,101,114,114,2,0,0,0,114,2,0,0, - 0,114,4,0,0,0,114,6,1,0,0,156,4,0,0,115, - 10,0,0,0,0,4,22,1,8,1,10,1,10,1,122,28, - 80,97,116,104,70,105,110,100,101,114,46,105,110,118,97,108, - 105,100,97,116,101,95,99,97,99,104,101,115,99,2,0,0, - 0,0,0,0,0,3,0,0,0,9,0,0,0,67,0,0, - 0,115,84,0,0,0,116,0,106,1,100,1,107,9,114,28, - 116,0,106,1,115,28,116,2,160,3,100,2,116,4,161,2, - 1,0,116,0,106,1,68,0,93,44,125,2,122,14,124,2, - 124,1,131,1,87,0,2,0,1,0,83,0,4,0,116,5, - 107,10,114,76,1,0,1,0,1,0,89,0,113,34,89,0, - 113,34,88,0,113,34,100,1,83,0,41,3,122,46,83,101, - 97,114,99,104,32,115,121,115,46,112,97,116,104,95,104,111, - 111,107,115,32,102,111,114,32,97,32,102,105,110,100,101,114, - 32,102,111,114,32,39,112,97,116,104,39,46,78,122,23,115, - 121,115,46,112,97,116,104,95,104,111,111,107,115,32,105,115, - 32,101,109,112,116,121,41,6,114,6,0,0,0,218,10,112, - 97,116,104,95,104,111,111,107,115,114,61,0,0,0,114,62, - 0,0,0,114,120,0,0,0,114,101,0,0,0,41,3,114, - 172,0,0,0,114,35,0,0,0,90,4,104,111,111,107,114, + 101,32,109,101,116,104,111,100,32,105,115,32,100,101,112,114, + 101,99,97,116,101,100,46,32,32,84,104,101,32,105,109,112, + 111,114,116,32,109,97,99,104,105,110,101,114,121,32,100,111, + 101,115,32,116,104,101,32,106,111,98,32,105,116,115,101,108, + 102,46,10,10,32,32,32,32,32,32,32,32,122,25,60,109, + 111,100,117,108,101,32,123,33,114,125,32,40,110,97,109,101, + 115,112,97,99,101,41,62,41,2,114,48,0,0,0,114,107, + 0,0,0,41,2,114,172,0,0,0,114,191,0,0,0,114, 2,0,0,0,114,2,0,0,0,114,4,0,0,0,218,11, - 95,112,97,116,104,95,104,111,111,107,115,166,4,0,0,115, - 16,0,0,0,0,3,16,1,12,1,10,1,2,1,14,1, - 14,1,12,2,122,22,80,97,116,104,70,105,110,100,101,114, - 46,95,112,97,116,104,95,104,111,111,107,115,99,2,0,0, - 0,0,0,0,0,3,0,0,0,8,0,0,0,67,0,0, - 0,115,104,0,0,0,124,1,100,1,107,2,114,44,122,12, - 116,0,160,1,161,0,125,1,87,0,110,22,4,0,116,2, - 107,10,114,42,1,0,1,0,1,0,89,0,100,2,83,0, - 88,0,122,14,116,3,106,4,124,1,25,0,125,2,87,0, - 110,40,4,0,116,5,107,10,114,98,1,0,1,0,1,0, - 124,0,160,6,124,1,161,1,125,2,124,2,116,3,106,4, - 124,1,60,0,89,0,110,2,88,0,124,2,83,0,41,3, - 122,210,71,101,116,32,116,104,101,32,102,105,110,100,101,114, - 32,102,111,114,32,116,104,101,32,112,97,116,104,32,101,110, - 116,114,121,32,102,114,111,109,32,115,121,115,46,112,97,116, - 104,95,105,109,112,111,114,116,101,114,95,99,97,99,104,101, - 46,10,10,32,32,32,32,32,32,32,32,73,102,32,116,104, - 101,32,112,97,116,104,32,101,110,116,114,121,32,105,115,32, - 110,111,116,32,105,110,32,116,104,101,32,99,97,99,104,101, - 44,32,102,105,110,100,32,116,104,101,32,97,112,112,114,111, - 112,114,105,97,116,101,32,102,105,110,100,101,114,10,32,32, - 32,32,32,32,32,32,97,110,100,32,99,97,99,104,101,32, - 105,116,46,32,73,102,32,110,111,32,102,105,110,100,101,114, - 32,105,115,32,97,118,97,105,108,97,98,108,101,44,32,115, - 116,111,114,101,32,78,111,110,101,46,10,10,32,32,32,32, - 32,32,32,32,114,30,0,0,0,78,41,7,114,1,0,0, - 0,114,45,0,0,0,114,224,0,0,0,114,6,0,0,0, - 114,8,1,0,0,218,8,75,101,121,69,114,114,111,114,114, - 12,1,0,0,41,3,114,172,0,0,0,114,35,0,0,0, - 114,10,1,0,0,114,2,0,0,0,114,2,0,0,0,114, - 4,0,0,0,218,20,95,112,97,116,104,95,105,109,112,111, - 114,116,101,114,95,99,97,99,104,101,179,4,0,0,115,22, - 0,0,0,0,8,8,1,2,1,12,1,14,3,8,1,2, - 1,14,1,14,1,10,1,16,1,122,31,80,97,116,104,70, - 105,110,100,101,114,46,95,112,97,116,104,95,105,109,112,111, - 114,116,101,114,95,99,97,99,104,101,99,3,0,0,0,0, - 0,0,0,6,0,0,0,4,0,0,0,67,0,0,0,115, - 82,0,0,0,116,0,124,2,100,1,131,2,114,26,124,2, - 160,1,124,1,161,1,92,2,125,3,125,4,110,14,124,2, - 160,2,124,1,161,1,125,3,103,0,125,4,124,3,100,0, - 107,9,114,60,116,3,160,4,124,1,124,3,161,2,83,0, - 116,3,160,5,124,1,100,0,161,2,125,5,124,4,124,5, - 95,6,124,5,83,0,41,2,78,114,119,0,0,0,41,7, - 114,110,0,0,0,114,119,0,0,0,114,183,0,0,0,114, - 116,0,0,0,114,180,0,0,0,114,162,0,0,0,114,158, - 0,0,0,41,6,114,172,0,0,0,114,121,0,0,0,114, - 10,1,0,0,114,122,0,0,0,114,123,0,0,0,114,166, - 0,0,0,114,2,0,0,0,114,2,0,0,0,114,4,0, - 0,0,218,16,95,108,101,103,97,99,121,95,103,101,116,95, - 115,112,101,99,201,4,0,0,115,18,0,0,0,0,4,10, - 1,16,2,10,1,4,1,8,1,12,1,12,1,6,1,122, - 27,80,97,116,104,70,105,110,100,101,114,46,95,108,101,103, - 97,99,121,95,103,101,116,95,115,112,101,99,78,99,4,0, - 0,0,0,0,0,0,9,0,0,0,5,0,0,0,67,0, - 0,0,115,166,0,0,0,103,0,125,4,124,2,68,0,93, - 134,125,5,116,0,124,5,116,1,116,2,102,2,131,2,115, - 28,113,8,124,0,160,3,124,5,161,1,125,6,124,6,100, - 1,107,9,114,8,116,4,124,6,100,2,131,2,114,70,124, - 6,160,5,124,1,124,3,161,2,125,7,110,12,124,0,160, - 6,124,1,124,6,161,2,125,7,124,7,100,1,107,8,114, - 92,113,8,124,7,106,7,100,1,107,9,114,110,124,7,2, - 0,1,0,83,0,124,7,106,8,125,8,124,8,100,1,107, - 8,114,132,116,9,100,3,131,1,130,1,124,4,160,10,124, - 8,161,1,1,0,113,8,116,11,160,12,124,1,100,1,161, - 2,125,7,124,4,124,7,95,8,124,7,83,0,41,4,122, - 63,70,105,110,100,32,116,104,101,32,108,111,97,100,101,114, - 32,111,114,32,110,97,109,101,115,112,97,99,101,95,112,97, - 116,104,32,102,111,114,32,116,104,105,115,32,109,111,100,117, - 108,101,47,112,97,99,107,97,103,101,32,110,97,109,101,46, - 78,114,182,0,0,0,122,19,115,112,101,99,32,109,105,115, - 115,105,110,103,32,108,111,97,100,101,114,41,13,114,141,0, - 0,0,114,71,0,0,0,218,5,98,121,116,101,115,114,14, - 1,0,0,114,110,0,0,0,114,182,0,0,0,114,15,1, - 0,0,114,122,0,0,0,114,158,0,0,0,114,101,0,0, - 0,114,147,0,0,0,114,116,0,0,0,114,162,0,0,0, - 41,9,114,172,0,0,0,114,121,0,0,0,114,35,0,0, - 0,114,181,0,0,0,218,14,110,97,109,101,115,112,97,99, - 101,95,112,97,116,104,90,5,101,110,116,114,121,114,10,1, - 0,0,114,166,0,0,0,114,123,0,0,0,114,2,0,0, - 0,114,2,0,0,0,114,4,0,0,0,218,9,95,103,101, - 116,95,115,112,101,99,216,4,0,0,115,40,0,0,0,0, - 5,4,1,8,1,14,1,2,1,10,1,8,1,10,1,14, - 2,12,1,8,1,2,1,10,1,8,1,6,1,8,1,8, - 5,12,2,12,1,6,1,122,20,80,97,116,104,70,105,110, - 100,101,114,46,95,103,101,116,95,115,112,101,99,99,4,0, - 0,0,0,0,0,0,6,0,0,0,5,0,0,0,67,0, - 0,0,115,100,0,0,0,124,2,100,1,107,8,114,14,116, - 0,106,1,125,2,124,0,160,2,124,1,124,2,124,3,161, - 3,125,4,124,4,100,1,107,8,114,40,100,1,83,0,124, - 4,106,3,100,1,107,8,114,92,124,4,106,4,125,5,124, - 5,114,86,100,1,124,4,95,5,116,6,124,1,124,5,124, - 0,106,2,131,3,124,4,95,4,124,4,83,0,100,1,83, - 0,110,4,124,4,83,0,100,1,83,0,41,2,122,141,84, - 114,121,32,116,111,32,102,105,110,100,32,97,32,115,112,101, - 99,32,102,111,114,32,39,102,117,108,108,110,97,109,101,39, - 32,111,110,32,115,121,115,46,112,97,116,104,32,111,114,32, - 39,112,97,116,104,39,46,10,10,32,32,32,32,32,32,32, - 32,84,104,101,32,115,101,97,114,99,104,32,105,115,32,98, - 97,115,101,100,32,111,110,32,115,121,115,46,112,97,116,104, - 95,104,111,111,107,115,32,97,110,100,32,115,121,115,46,112, - 97,116,104,95,105,109,112,111,114,116,101,114,95,99,97,99, - 104,101,46,10,32,32,32,32,32,32,32,32,78,41,7,114, - 6,0,0,0,114,35,0,0,0,114,18,1,0,0,114,122, - 0,0,0,114,158,0,0,0,114,160,0,0,0,114,241,0, - 0,0,41,6,114,172,0,0,0,114,121,0,0,0,114,35, - 0,0,0,114,181,0,0,0,114,166,0,0,0,114,17,1, - 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, - 0,114,182,0,0,0,248,4,0,0,115,26,0,0,0,0, - 6,8,1,6,1,14,1,8,1,4,1,10,1,6,1,4, - 3,6,1,16,1,4,2,6,2,122,20,80,97,116,104,70, - 105,110,100,101,114,46,102,105,110,100,95,115,112,101,99,99, - 3,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0, - 67,0,0,0,115,30,0,0,0,124,0,160,0,124,1,124, - 2,161,2,125,3,124,3,100,1,107,8,114,24,100,1,83, - 0,124,3,106,1,83,0,41,2,122,170,102,105,110,100,32, - 116,104,101,32,109,111,100,117,108,101,32,111,110,32,115,121, - 115,46,112,97,116,104,32,111,114,32,39,112,97,116,104,39, - 32,98,97,115,101,100,32,111,110,32,115,121,115,46,112,97, - 116,104,95,104,111,111,107,115,32,97,110,100,10,32,32,32, - 32,32,32,32,32,115,121,115,46,112,97,116,104,95,105,109, - 112,111,114,116,101,114,95,99,97,99,104,101,46,10,10,32, - 32,32,32,32,32,32,32,84,104,105,115,32,109,101,116,104, - 111,100,32,105,115,32,100,101,112,114,101,99,97,116,101,100, - 46,32,32,85,115,101,32,102,105,110,100,95,115,112,101,99, - 40,41,32,105,110,115,116,101,97,100,46,10,10,32,32,32, - 32,32,32,32,32,78,41,2,114,182,0,0,0,114,122,0, - 0,0,41,4,114,172,0,0,0,114,121,0,0,0,114,35, - 0,0,0,114,166,0,0,0,114,2,0,0,0,114,2,0, - 0,0,114,4,0,0,0,114,183,0,0,0,16,5,0,0, - 115,8,0,0,0,0,8,12,1,8,1,4,1,122,22,80, - 97,116,104,70,105,110,100,101,114,46,102,105,110,100,95,109, - 111,100,117,108,101,41,1,78,41,2,78,78,41,1,78,41, - 12,114,107,0,0,0,114,106,0,0,0,114,108,0,0,0, - 114,109,0,0,0,114,184,0,0,0,114,6,1,0,0,114, - 12,1,0,0,114,14,1,0,0,114,15,1,0,0,114,18, - 1,0,0,114,182,0,0,0,114,183,0,0,0,114,2,0, + 109,111,100,117,108,101,95,114,101,112,114,114,4,0,0,115, + 2,0,0,0,0,7,122,28,95,78,97,109,101,115,112,97, + 99,101,76,111,97,100,101,114,46,109,111,100,117,108,101,95, + 114,101,112,114,99,2,0,0,0,0,0,0,0,2,0,0, + 0,1,0,0,0,67,0,0,0,115,4,0,0,0,100,1, + 83,0,41,2,78,84,114,2,0,0,0,41,2,114,102,0, + 0,0,114,121,0,0,0,114,2,0,0,0,114,2,0,0, + 0,114,4,0,0,0,114,161,0,0,0,123,4,0,0,115, + 2,0,0,0,0,1,122,27,95,78,97,109,101,115,112,97, + 99,101,76,111,97,100,101,114,46,105,115,95,112,97,99,107, + 97,103,101,99,2,0,0,0,0,0,0,0,2,0,0,0, + 1,0,0,0,67,0,0,0,115,4,0,0,0,100,1,83, + 0,41,2,78,114,30,0,0,0,114,2,0,0,0,41,2, + 114,102,0,0,0,114,121,0,0,0,114,2,0,0,0,114, + 2,0,0,0,114,4,0,0,0,114,202,0,0,0,126,4, + 0,0,115,2,0,0,0,0,1,122,27,95,78,97,109,101, + 115,112,97,99,101,76,111,97,100,101,114,46,103,101,116,95, + 115,111,117,114,99,101,99,2,0,0,0,0,0,0,0,2, + 0,0,0,6,0,0,0,67,0,0,0,115,16,0,0,0, + 116,0,100,1,100,2,100,3,100,4,100,5,141,4,83,0, + 41,6,78,114,30,0,0,0,122,8,60,115,116,114,105,110, + 103,62,114,190,0,0,0,84,41,1,114,204,0,0,0,41, + 1,114,205,0,0,0,41,2,114,102,0,0,0,114,121,0, 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, - 0,114,5,1,0,0,152,4,0,0,115,20,0,0,0,12, - 4,12,10,12,13,12,22,12,15,2,1,12,31,2,1,12, - 23,2,1,114,5,1,0,0,99,0,0,0,0,0,0,0, - 0,0,0,0,0,3,0,0,0,64,0,0,0,115,90,0, - 0,0,101,0,90,1,100,0,90,2,100,1,90,3,100,2, - 100,3,132,0,90,4,100,4,100,5,132,0,90,5,101,6, - 90,7,100,6,100,7,132,0,90,8,100,8,100,9,132,0, - 90,9,100,19,100,11,100,12,132,1,90,10,100,13,100,14, - 132,0,90,11,101,12,100,15,100,16,132,0,131,1,90,13, - 100,17,100,18,132,0,90,14,100,10,83,0,41,20,218,10, - 70,105,108,101,70,105,110,100,101,114,122,172,70,105,108,101, - 45,98,97,115,101,100,32,102,105,110,100,101,114,46,10,10, - 32,32,32,32,73,110,116,101,114,97,99,116,105,111,110,115, - 32,119,105,116,104,32,116,104,101,32,102,105,108,101,32,115, - 121,115,116,101,109,32,97,114,101,32,99,97,99,104,101,100, - 32,102,111,114,32,112,101,114,102,111,114,109,97,110,99,101, - 44,32,98,101,105,110,103,10,32,32,32,32,114,101,102,114, - 101,115,104,101,100,32,119,104,101,110,32,116,104,101,32,100, - 105,114,101,99,116,111,114,121,32,116,104,101,32,102,105,110, - 100,101,114,32,105,115,32,104,97,110,100,108,105,110,103,32, - 104,97,115,32,98,101,101,110,32,109,111,100,105,102,105,101, - 100,46,10,10,32,32,32,32,99,2,0,0,0,0,0,0, - 0,5,0,0,0,6,0,0,0,7,0,0,0,115,84,0, - 0,0,103,0,125,3,124,2,68,0,93,32,92,2,137,0, - 125,4,124,3,160,0,135,0,102,1,100,1,100,2,132,8, - 124,4,68,0,131,1,161,1,1,0,113,8,124,3,124,0, - 95,1,124,1,112,54,100,3,124,0,95,2,100,4,124,0, - 95,3,116,4,131,0,124,0,95,5,116,4,131,0,124,0, - 95,6,100,5,83,0,41,6,122,154,73,110,105,116,105,97, - 108,105,122,101,32,119,105,116,104,32,116,104,101,32,112,97, - 116,104,32,116,111,32,115,101,97,114,99,104,32,111,110,32, - 97,110,100,32,97,32,118,97,114,105,97,98,108,101,32,110, - 117,109,98,101,114,32,111,102,10,32,32,32,32,32,32,32, - 32,50,45,116,117,112,108,101,115,32,99,111,110,116,97,105, - 110,105,110,103,32,116,104,101,32,108,111,97,100,101,114,32, - 97,110,100,32,116,104,101,32,102,105,108,101,32,115,117,102, - 102,105,120,101,115,32,116,104,101,32,108,111,97,100,101,114, - 10,32,32,32,32,32,32,32,32,114,101,99,111,103,110,105, - 122,101,115,46,99,1,0,0,0,0,0,0,0,2,0,0, - 0,3,0,0,0,51,0,0,0,115,22,0,0,0,124,0, - 93,14,125,1,124,1,136,0,102,2,86,0,1,0,113,2, - 100,0,83,0,41,1,78,114,2,0,0,0,41,2,114,22, - 0,0,0,114,236,0,0,0,41,1,114,122,0,0,0,114, - 2,0,0,0,114,4,0,0,0,114,238,0,0,0,45,5, - 0,0,115,2,0,0,0,4,0,122,38,70,105,108,101,70, - 105,110,100,101,114,46,95,95,105,110,105,116,95,95,46,60, - 108,111,99,97,108,115,62,46,60,103,101,110,101,120,112,114, - 62,114,59,0,0,0,114,89,0,0,0,78,41,7,114,147, - 0,0,0,218,8,95,108,111,97,100,101,114,115,114,35,0, - 0,0,218,11,95,112,97,116,104,95,109,116,105,109,101,218, - 3,115,101,116,218,11,95,112,97,116,104,95,99,97,99,104, - 101,218,19,95,114,101,108,97,120,101,100,95,112,97,116,104, - 95,99,97,99,104,101,41,5,114,102,0,0,0,114,35,0, - 0,0,218,14,108,111,97,100,101,114,95,100,101,116,97,105, - 108,115,90,7,108,111,97,100,101,114,115,114,168,0,0,0, - 114,2,0,0,0,41,1,114,122,0,0,0,114,4,0,0, - 0,114,186,0,0,0,39,5,0,0,115,16,0,0,0,0, - 4,4,1,12,1,26,1,6,2,10,1,6,1,8,1,122, - 19,70,105,108,101,70,105,110,100,101,114,46,95,95,105,110, - 105,116,95,95,99,1,0,0,0,0,0,0,0,1,0,0, - 0,2,0,0,0,67,0,0,0,115,10,0,0,0,100,1, - 124,0,95,0,100,2,83,0,41,3,122,31,73,110,118,97, - 108,105,100,97,116,101,32,116,104,101,32,100,105,114,101,99, - 116,111,114,121,32,109,116,105,109,101,46,114,89,0,0,0, - 78,41,1,114,21,1,0,0,41,1,114,102,0,0,0,114, - 2,0,0,0,114,2,0,0,0,114,4,0,0,0,114,6, - 1,0,0,53,5,0,0,115,2,0,0,0,0,2,122,28, - 70,105,108,101,70,105,110,100,101,114,46,105,110,118,97,108, - 105,100,97,116,101,95,99,97,99,104,101,115,99,2,0,0, - 0,0,0,0,0,3,0,0,0,3,0,0,0,67,0,0, - 0,115,42,0,0,0,124,0,160,0,124,1,161,1,125,2, - 124,2,100,1,107,8,114,26,100,1,103,0,102,2,83,0, - 124,2,106,1,124,2,106,2,112,38,103,0,102,2,83,0, - 41,2,122,197,84,114,121,32,116,111,32,102,105,110,100,32, - 97,32,108,111,97,100,101,114,32,102,111,114,32,116,104,101, - 32,115,112,101,99,105,102,105,101,100,32,109,111,100,117,108, - 101,44,32,111,114,32,116,104,101,32,110,97,109,101,115,112, - 97,99,101,10,32,32,32,32,32,32,32,32,112,97,99,107, - 97,103,101,32,112,111,114,116,105,111,110,115,46,32,82,101, - 116,117,114,110,115,32,40,108,111,97,100,101,114,44,32,108, - 105,115,116,45,111,102,45,112,111,114,116,105,111,110,115,41, + 0,114,188,0,0,0,129,4,0,0,115,2,0,0,0,0, + 1,122,25,95,78,97,109,101,115,112,97,99,101,76,111,97, + 100,101,114,46,103,101,116,95,99,111,100,101,99,2,0,0, + 0,0,0,0,0,2,0,0,0,1,0,0,0,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,2,0,0,0,41,2, + 114,102,0,0,0,114,166,0,0,0,114,2,0,0,0,114, + 2,0,0,0,114,4,0,0,0,114,187,0,0,0,132,4, + 0,0,115,2,0,0,0,0,1,122,30,95,78,97,109,101, + 115,112,97,99,101,76,111,97,100,101,114,46,99,114,101,97, + 116,101,95,109,111,100,117,108,101,99,2,0,0,0,0,0, + 0,0,2,0,0,0,1,0,0,0,67,0,0,0,115,4, + 0,0,0,100,0,83,0,41,1,78,114,2,0,0,0,41, + 2,114,102,0,0,0,114,191,0,0,0,114,2,0,0,0, + 114,2,0,0,0,114,4,0,0,0,114,192,0,0,0,135, + 4,0,0,115,2,0,0,0,0,1,122,28,95,78,97,109, + 101,115,112,97,99,101,76,111,97,100,101,114,46,101,120,101, + 99,95,109,111,100,117,108,101,99,2,0,0,0,0,0,0, + 0,2,0,0,0,4,0,0,0,67,0,0,0,115,26,0, + 0,0,116,0,160,1,100,1,124,0,106,2,161,2,1,0, + 116,0,160,3,124,0,124,1,161,2,83,0,41,2,122,98, + 76,111,97,100,32,97,32,110,97,109,101,115,112,97,99,101, + 32,109,111,100,117,108,101,46,10,10,32,32,32,32,32,32, + 32,32,84,104,105,115,32,109,101,116,104,111,100,32,105,115, + 32,100,101,112,114,101,99,97,116,101,100,46,32,32,85,115, + 101,32,101,120,101,99,95,109,111,100,117,108,101,40,41,32, + 105,110,115,116,101,97,100,46,10,10,32,32,32,32,32,32, + 32,32,122,38,110,97,109,101,115,112,97,99,101,32,109,111, + 100,117,108,101,32,108,111,97,100,101,100,32,119,105,116,104, + 32,112,97,116,104,32,123,33,114,125,41,4,114,116,0,0, + 0,114,130,0,0,0,114,243,0,0,0,114,193,0,0,0, + 41,2,114,102,0,0,0,114,121,0,0,0,114,2,0,0, + 0,114,2,0,0,0,114,4,0,0,0,114,194,0,0,0, + 138,4,0,0,115,6,0,0,0,0,7,6,1,8,1,122, + 28,95,78,97,109,101,115,112,97,99,101,76,111,97,100,101, + 114,46,108,111,97,100,95,109,111,100,117,108,101,78,41,12, + 114,107,0,0,0,114,106,0,0,0,114,108,0,0,0,114, + 186,0,0,0,114,184,0,0,0,114,4,1,0,0,114,161, + 0,0,0,114,202,0,0,0,114,188,0,0,0,114,187,0, + 0,0,114,192,0,0,0,114,194,0,0,0,114,2,0,0, + 0,114,2,0,0,0,114,2,0,0,0,114,4,0,0,0, + 114,3,1,0,0,110,4,0,0,115,16,0,0,0,8,1, + 8,3,12,9,8,3,8,3,8,3,8,3,8,3,114,3, + 1,0,0,99,0,0,0,0,0,0,0,0,0,0,0,0, + 4,0,0,0,64,0,0,0,115,106,0,0,0,101,0,90, + 1,100,0,90,2,100,1,90,3,101,4,100,2,100,3,132, + 0,131,1,90,5,101,4,100,4,100,5,132,0,131,1,90, + 6,101,4,100,6,100,7,132,0,131,1,90,7,101,4,100, + 8,100,9,132,0,131,1,90,8,101,4,100,17,100,11,100, + 12,132,1,131,1,90,9,101,4,100,18,100,13,100,14,132, + 1,131,1,90,10,101,4,100,19,100,15,100,16,132,1,131, + 1,90,11,100,10,83,0,41,20,218,10,80,97,116,104,70, + 105,110,100,101,114,122,62,77,101,116,97,32,112,97,116,104, + 32,102,105,110,100,101,114,32,102,111,114,32,115,121,115,46, + 112,97,116,104,32,97,110,100,32,112,97,99,107,97,103,101, + 32,95,95,112,97,116,104,95,95,32,97,116,116,114,105,98, + 117,116,101,115,46,99,1,0,0,0,0,0,0,0,3,0, + 0,0,4,0,0,0,67,0,0,0,115,64,0,0,0,116, + 0,116,1,106,2,160,3,161,0,131,1,68,0,93,44,92, + 2,125,1,125,2,124,2,100,1,107,8,114,40,116,1,106, + 2,124,1,61,0,113,14,116,4,124,2,100,2,131,2,114, + 14,124,2,160,5,161,0,1,0,113,14,100,1,83,0,41, + 3,122,125,67,97,108,108,32,116,104,101,32,105,110,118,97, + 108,105,100,97,116,101,95,99,97,99,104,101,115,40,41,32, + 109,101,116,104,111,100,32,111,110,32,97,108,108,32,112,97, + 116,104,32,101,110,116,114,121,32,102,105,110,100,101,114,115, + 10,32,32,32,32,32,32,32,32,115,116,111,114,101,100,32, + 105,110,32,115,121,115,46,112,97,116,104,95,105,109,112,111, + 114,116,101,114,95,99,97,99,104,101,115,32,40,119,104,101, + 114,101,32,105,109,112,108,101,109,101,110,116,101,100,41,46, + 78,218,17,105,110,118,97,108,105,100,97,116,101,95,99,97, + 99,104,101,115,41,6,218,4,108,105,115,116,114,6,0,0, + 0,218,19,112,97,116,104,95,105,109,112,111,114,116,101,114, + 95,99,97,99,104,101,218,5,105,116,101,109,115,114,110,0, + 0,0,114,6,1,0,0,41,3,114,172,0,0,0,114,100, + 0,0,0,218,6,102,105,110,100,101,114,114,2,0,0,0, + 114,2,0,0,0,114,4,0,0,0,114,6,1,0,0,156, + 4,0,0,115,10,0,0,0,0,4,22,1,8,1,10,1, + 10,1,122,28,80,97,116,104,70,105,110,100,101,114,46,105, + 110,118,97,108,105,100,97,116,101,95,99,97,99,104,101,115, + 99,2,0,0,0,0,0,0,0,3,0,0,0,9,0,0, + 0,67,0,0,0,115,84,0,0,0,116,0,106,1,100,1, + 107,9,114,28,116,0,106,1,115,28,116,2,160,3,100,2, + 116,4,161,2,1,0,116,0,106,1,68,0,93,44,125,2, + 122,14,124,2,124,1,131,1,87,0,2,0,1,0,83,0, + 4,0,116,5,107,10,114,76,1,0,1,0,1,0,89,0, + 113,34,89,0,113,34,88,0,113,34,100,1,83,0,41,3, + 122,46,83,101,97,114,99,104,32,115,121,115,46,112,97,116, + 104,95,104,111,111,107,115,32,102,111,114,32,97,32,102,105, + 110,100,101,114,32,102,111,114,32,39,112,97,116,104,39,46, + 78,122,23,115,121,115,46,112,97,116,104,95,104,111,111,107, + 115,32,105,115,32,101,109,112,116,121,41,6,114,6,0,0, + 0,218,10,112,97,116,104,95,104,111,111,107,115,114,61,0, + 0,0,114,62,0,0,0,114,120,0,0,0,114,101,0,0, + 0,41,3,114,172,0,0,0,114,35,0,0,0,90,4,104, + 111,111,107,114,2,0,0,0,114,2,0,0,0,114,4,0, + 0,0,218,11,95,112,97,116,104,95,104,111,111,107,115,166, + 4,0,0,115,16,0,0,0,0,3,16,1,12,1,10,1, + 2,1,14,1,14,1,12,2,122,22,80,97,116,104,70,105, + 110,100,101,114,46,95,112,97,116,104,95,104,111,111,107,115, + 99,2,0,0,0,0,0,0,0,3,0,0,0,8,0,0, + 0,67,0,0,0,115,104,0,0,0,124,1,100,1,107,2, + 114,44,122,12,116,0,160,1,161,0,125,1,87,0,110,22, + 4,0,116,2,107,10,114,42,1,0,1,0,1,0,89,0, + 100,2,83,0,88,0,122,14,116,3,106,4,124,1,25,0, + 125,2,87,0,110,40,4,0,116,5,107,10,114,98,1,0, + 1,0,1,0,124,0,160,6,124,1,161,1,125,2,124,2, + 116,3,106,4,124,1,60,0,89,0,110,2,88,0,124,2, + 83,0,41,3,122,210,71,101,116,32,116,104,101,32,102,105, + 110,100,101,114,32,102,111,114,32,116,104,101,32,112,97,116, + 104,32,101,110,116,114,121,32,102,114,111,109,32,115,121,115, + 46,112,97,116,104,95,105,109,112,111,114,116,101,114,95,99, + 97,99,104,101,46,10,10,32,32,32,32,32,32,32,32,73, + 102,32,116,104,101,32,112,97,116,104,32,101,110,116,114,121, + 32,105,115,32,110,111,116,32,105,110,32,116,104,101,32,99, + 97,99,104,101,44,32,102,105,110,100,32,116,104,101,32,97, + 112,112,114,111,112,114,105,97,116,101,32,102,105,110,100,101, + 114,10,32,32,32,32,32,32,32,32,97,110,100,32,99,97, + 99,104,101,32,105,116,46,32,73,102,32,110,111,32,102,105, + 110,100,101,114,32,105,115,32,97,118,97,105,108,97,98,108, + 101,44,32,115,116,111,114,101,32,78,111,110,101,46,10,10, + 32,32,32,32,32,32,32,32,114,30,0,0,0,78,41,7, + 114,1,0,0,0,114,45,0,0,0,114,224,0,0,0,114, + 6,0,0,0,114,8,1,0,0,218,8,75,101,121,69,114, + 114,111,114,114,12,1,0,0,41,3,114,172,0,0,0,114, + 35,0,0,0,114,10,1,0,0,114,2,0,0,0,114,2, + 0,0,0,114,4,0,0,0,218,20,95,112,97,116,104,95, + 105,109,112,111,114,116,101,114,95,99,97,99,104,101,179,4, + 0,0,115,22,0,0,0,0,8,8,1,2,1,12,1,14, + 3,8,1,2,1,14,1,14,1,10,1,16,1,122,31,80, + 97,116,104,70,105,110,100,101,114,46,95,112,97,116,104,95, + 105,109,112,111,114,116,101,114,95,99,97,99,104,101,99,3, + 0,0,0,0,0,0,0,6,0,0,0,4,0,0,0,67, + 0,0,0,115,82,0,0,0,116,0,124,2,100,1,131,2, + 114,26,124,2,160,1,124,1,161,1,92,2,125,3,125,4, + 110,14,124,2,160,2,124,1,161,1,125,3,103,0,125,4, + 124,3,100,0,107,9,114,60,116,3,160,4,124,1,124,3, + 161,2,83,0,116,3,160,5,124,1,100,0,161,2,125,5, + 124,4,124,5,95,6,124,5,83,0,41,2,78,114,119,0, + 0,0,41,7,114,110,0,0,0,114,119,0,0,0,114,183, + 0,0,0,114,116,0,0,0,114,180,0,0,0,114,162,0, + 0,0,114,158,0,0,0,41,6,114,172,0,0,0,114,121, + 0,0,0,114,10,1,0,0,114,122,0,0,0,114,123,0, + 0,0,114,166,0,0,0,114,2,0,0,0,114,2,0,0, + 0,114,4,0,0,0,218,16,95,108,101,103,97,99,121,95, + 103,101,116,95,115,112,101,99,201,4,0,0,115,18,0,0, + 0,0,4,10,1,16,2,10,1,4,1,8,1,12,1,12, + 1,6,1,122,27,80,97,116,104,70,105,110,100,101,114,46, + 95,108,101,103,97,99,121,95,103,101,116,95,115,112,101,99, + 78,99,4,0,0,0,0,0,0,0,9,0,0,0,5,0, + 0,0,67,0,0,0,115,166,0,0,0,103,0,125,4,124, + 2,68,0,93,134,125,5,116,0,124,5,116,1,116,2,102, + 2,131,2,115,28,113,8,124,0,160,3,124,5,161,1,125, + 6,124,6,100,1,107,9,114,8,116,4,124,6,100,2,131, + 2,114,70,124,6,160,5,124,1,124,3,161,2,125,7,110, + 12,124,0,160,6,124,1,124,6,161,2,125,7,124,7,100, + 1,107,8,114,92,113,8,124,7,106,7,100,1,107,9,114, + 110,124,7,2,0,1,0,83,0,124,7,106,8,125,8,124, + 8,100,1,107,8,114,132,116,9,100,3,131,1,130,1,124, + 4,160,10,124,8,161,1,1,0,113,8,116,11,160,12,124, + 1,100,1,161,2,125,7,124,4,124,7,95,8,124,7,83, + 0,41,4,122,63,70,105,110,100,32,116,104,101,32,108,111, + 97,100,101,114,32,111,114,32,110,97,109,101,115,112,97,99, + 101,95,112,97,116,104,32,102,111,114,32,116,104,105,115,32, + 109,111,100,117,108,101,47,112,97,99,107,97,103,101,32,110, + 97,109,101,46,78,114,182,0,0,0,122,19,115,112,101,99, + 32,109,105,115,115,105,110,103,32,108,111,97,100,101,114,41, + 13,114,141,0,0,0,114,71,0,0,0,218,5,98,121,116, + 101,115,114,14,1,0,0,114,110,0,0,0,114,182,0,0, + 0,114,15,1,0,0,114,122,0,0,0,114,158,0,0,0, + 114,101,0,0,0,114,147,0,0,0,114,116,0,0,0,114, + 162,0,0,0,41,9,114,172,0,0,0,114,121,0,0,0, + 114,35,0,0,0,114,181,0,0,0,218,14,110,97,109,101, + 115,112,97,99,101,95,112,97,116,104,90,5,101,110,116,114, + 121,114,10,1,0,0,114,166,0,0,0,114,123,0,0,0, + 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,218, + 9,95,103,101,116,95,115,112,101,99,216,4,0,0,115,40, + 0,0,0,0,5,4,1,8,1,14,1,2,1,10,1,8, + 1,10,1,14,2,12,1,8,1,2,1,10,1,8,1,6, + 1,8,1,8,5,12,2,12,1,6,1,122,20,80,97,116, + 104,70,105,110,100,101,114,46,95,103,101,116,95,115,112,101, + 99,99,4,0,0,0,0,0,0,0,6,0,0,0,5,0, + 0,0,67,0,0,0,115,100,0,0,0,124,2,100,1,107, + 8,114,14,116,0,106,1,125,2,124,0,160,2,124,1,124, + 2,124,3,161,3,125,4,124,4,100,1,107,8,114,40,100, + 1,83,0,124,4,106,3,100,1,107,8,114,92,124,4,106, + 4,125,5,124,5,114,86,100,1,124,4,95,5,116,6,124, + 1,124,5,124,0,106,2,131,3,124,4,95,4,124,4,83, + 0,100,1,83,0,110,4,124,4,83,0,100,1,83,0,41, + 2,122,141,84,114,121,32,116,111,32,102,105,110,100,32,97, + 32,115,112,101,99,32,102,111,114,32,39,102,117,108,108,110, + 97,109,101,39,32,111,110,32,115,121,115,46,112,97,116,104, + 32,111,114,32,39,112,97,116,104,39,46,10,10,32,32,32, + 32,32,32,32,32,84,104,101,32,115,101,97,114,99,104,32, + 105,115,32,98,97,115,101,100,32,111,110,32,115,121,115,46, + 112,97,116,104,95,104,111,111,107,115,32,97,110,100,32,115, + 121,115,46,112,97,116,104,95,105,109,112,111,114,116,101,114, + 95,99,97,99,104,101,46,10,32,32,32,32,32,32,32,32, + 78,41,7,114,6,0,0,0,114,35,0,0,0,114,18,1, + 0,0,114,122,0,0,0,114,158,0,0,0,114,160,0,0, + 0,114,241,0,0,0,41,6,114,172,0,0,0,114,121,0, + 0,0,114,35,0,0,0,114,181,0,0,0,114,166,0,0, + 0,114,17,1,0,0,114,2,0,0,0,114,2,0,0,0, + 114,4,0,0,0,114,182,0,0,0,248,4,0,0,115,26, + 0,0,0,0,6,8,1,6,1,14,1,8,1,4,1,10, + 1,6,1,4,3,6,1,16,1,4,2,6,2,122,20,80, + 97,116,104,70,105,110,100,101,114,46,102,105,110,100,95,115, + 112,101,99,99,3,0,0,0,0,0,0,0,4,0,0,0, + 4,0,0,0,67,0,0,0,115,30,0,0,0,124,0,160, + 0,124,1,124,2,161,2,125,3,124,3,100,1,107,8,114, + 24,100,1,83,0,124,3,106,1,83,0,41,2,122,170,102, + 105,110,100,32,116,104,101,32,109,111,100,117,108,101,32,111, + 110,32,115,121,115,46,112,97,116,104,32,111,114,32,39,112, + 97,116,104,39,32,98,97,115,101,100,32,111,110,32,115,121, + 115,46,112,97,116,104,95,104,111,111,107,115,32,97,110,100, + 10,32,32,32,32,32,32,32,32,115,121,115,46,112,97,116, + 104,95,105,109,112,111,114,116,101,114,95,99,97,99,104,101, 46,10,10,32,32,32,32,32,32,32,32,84,104,105,115,32, 109,101,116,104,111,100,32,105,115,32,100,101,112,114,101,99, 97,116,101,100,46,32,32,85,115,101,32,102,105,110,100,95, 115,112,101,99,40,41,32,105,110,115,116,101,97,100,46,10, - 10,32,32,32,32,32,32,32,32,78,41,3,114,182,0,0, - 0,114,122,0,0,0,114,158,0,0,0,41,3,114,102,0, - 0,0,114,121,0,0,0,114,166,0,0,0,114,2,0,0, - 0,114,2,0,0,0,114,4,0,0,0,114,119,0,0,0, - 59,5,0,0,115,8,0,0,0,0,7,10,1,8,1,8, - 1,122,22,70,105,108,101,70,105,110,100,101,114,46,102,105, - 110,100,95,108,111,97,100,101,114,99,6,0,0,0,0,0, - 0,0,7,0,0,0,6,0,0,0,67,0,0,0,115,26, - 0,0,0,124,1,124,2,124,3,131,2,125,6,116,0,124, - 2,124,3,124,6,124,4,100,1,141,4,83,0,41,2,78, - 41,2,114,122,0,0,0,114,158,0,0,0,41,1,114,169, - 0,0,0,41,7,114,102,0,0,0,114,167,0,0,0,114, - 121,0,0,0,114,35,0,0,0,90,4,115,109,115,108,114, - 181,0,0,0,114,122,0,0,0,114,2,0,0,0,114,2, - 0,0,0,114,4,0,0,0,114,18,1,0,0,71,5,0, - 0,115,6,0,0,0,0,1,10,1,8,1,122,20,70,105, - 108,101,70,105,110,100,101,114,46,95,103,101,116,95,115,112, - 101,99,78,99,3,0,0,0,0,0,0,0,14,0,0,0, - 8,0,0,0,67,0,0,0,115,98,1,0,0,100,1,125, - 3,124,1,160,0,100,2,161,1,100,3,25,0,125,4,122, - 24,116,1,124,0,106,2,112,34,116,3,160,4,161,0,131, - 1,106,5,125,5,87,0,110,24,4,0,116,6,107,10,114, - 66,1,0,1,0,1,0,100,4,125,5,89,0,110,2,88, - 0,124,5,124,0,106,7,107,3,114,92,124,0,160,8,161, - 0,1,0,124,5,124,0,95,7,116,9,131,0,114,114,124, - 0,106,10,125,6,124,4,160,11,161,0,125,7,110,10,124, - 0,106,12,125,6,124,4,125,7,124,7,124,6,107,6,114, - 218,116,13,124,0,106,2,124,4,131,2,125,8,124,0,106, - 14,68,0,93,58,92,2,125,9,125,10,100,5,124,9,23, - 0,125,11,116,13,124,8,124,11,131,2,125,12,116,15,124, - 12,131,1,114,150,124,0,160,16,124,10,124,1,124,12,124, - 8,103,1,124,2,161,5,2,0,1,0,83,0,113,150,116, - 17,124,8,131,1,125,3,124,0,106,14,68,0,93,82,92, - 2,125,9,125,10,116,13,124,0,106,2,124,4,124,9,23, - 0,131,2,125,12,116,18,106,19,100,6,124,12,100,3,100, - 7,141,3,1,0,124,7,124,9,23,0,124,6,107,6,114, - 224,116,15,124,12,131,1,114,224,124,0,160,16,124,10,124, - 1,124,12,100,8,124,2,161,5,2,0,1,0,83,0,113, - 224,124,3,144,1,114,94,116,18,160,19,100,9,124,8,161, - 2,1,0,116,18,160,20,124,1,100,8,161,2,125,13,124, - 8,103,1,124,13,95,21,124,13,83,0,100,8,83,0,41, - 10,122,111,84,114,121,32,116,111,32,102,105,110,100,32,97, - 32,115,112,101,99,32,102,111,114,32,116,104,101,32,115,112, - 101,99,105,102,105,101,100,32,109,111,100,117,108,101,46,10, - 10,32,32,32,32,32,32,32,32,82,101,116,117,114,110,115, - 32,116,104,101,32,109,97,116,99,104,105,110,103,32,115,112, - 101,99,44,32,111,114,32,78,111,110,101,32,105,102,32,110, - 111,116,32,102,111,117,110,100,46,10,32,32,32,32,32,32, - 32,32,70,114,59,0,0,0,114,57,0,0,0,114,89,0, - 0,0,114,186,0,0,0,122,9,116,114,121,105,110,103,32, - 123,125,41,1,90,9,118,101,114,98,111,115,105,116,121,78, - 122,25,112,111,115,115,105,98,108,101,32,110,97,109,101,115, - 112,97,99,101,32,102,111,114,32,123,125,41,22,114,32,0, - 0,0,114,39,0,0,0,114,35,0,0,0,114,1,0,0, - 0,114,45,0,0,0,114,230,0,0,0,114,40,0,0,0, - 114,21,1,0,0,218,11,95,102,105,108,108,95,99,97,99, - 104,101,114,5,0,0,0,114,24,1,0,0,114,90,0,0, - 0,114,23,1,0,0,114,28,0,0,0,114,20,1,0,0, - 114,44,0,0,0,114,18,1,0,0,114,46,0,0,0,114, - 116,0,0,0,114,130,0,0,0,114,162,0,0,0,114,158, - 0,0,0,41,14,114,102,0,0,0,114,121,0,0,0,114, - 181,0,0,0,90,12,105,115,95,110,97,109,101,115,112,97, - 99,101,90,11,116,97,105,108,95,109,111,100,117,108,101,114, - 149,0,0,0,90,5,99,97,99,104,101,90,12,99,97,99, - 104,101,95,109,111,100,117,108,101,90,9,98,97,115,101,95, - 112,97,116,104,114,236,0,0,0,114,167,0,0,0,90,13, - 105,110,105,116,95,102,105,108,101,110,97,109,101,90,9,102, - 117,108,108,95,112,97,116,104,114,166,0,0,0,114,2,0, - 0,0,114,2,0,0,0,114,4,0,0,0,114,182,0,0, - 0,76,5,0,0,115,70,0,0,0,0,5,4,1,14,1, - 2,1,24,1,14,1,10,1,10,1,8,1,6,2,6,1, - 6,1,10,2,6,1,4,2,8,1,12,1,14,1,8,1, - 10,1,8,1,26,4,8,2,14,1,16,1,16,1,12,1, - 8,1,10,1,14,1,6,1,12,1,12,1,8,1,4,1, - 122,20,70,105,108,101,70,105,110,100,101,114,46,102,105,110, - 100,95,115,112,101,99,99,1,0,0,0,0,0,0,0,9, - 0,0,0,10,0,0,0,67,0,0,0,115,190,0,0,0, - 124,0,106,0,125,1,122,22,116,1,160,2,124,1,112,22, - 116,1,160,3,161,0,161,1,125,2,87,0,110,30,4,0, - 116,4,116,5,116,6,102,3,107,10,114,58,1,0,1,0, - 1,0,103,0,125,2,89,0,110,2,88,0,116,7,106,8, - 160,9,100,1,161,1,115,84,116,10,124,2,131,1,124,0, - 95,11,110,74,116,10,131,0,125,3,124,2,68,0,93,56, - 125,4,124,4,160,12,100,2,161,1,92,3,125,5,125,6, - 125,7,124,6,114,136,100,3,160,13,124,5,124,7,160,14, - 161,0,161,2,125,8,110,4,124,5,125,8,124,3,160,15, - 124,8,161,1,1,0,113,94,124,3,124,0,95,11,116,7, - 106,8,160,9,116,16,161,1,114,186,100,4,100,5,132,0, - 124,2,68,0,131,1,124,0,95,17,100,6,83,0,41,7, - 122,68,70,105,108,108,32,116,104,101,32,99,97,99,104,101, - 32,111,102,32,112,111,116,101,110,116,105,97,108,32,109,111, - 100,117,108,101,115,32,97,110,100,32,112,97,99,107,97,103, - 101,115,32,102,111,114,32,116,104,105,115,32,100,105,114,101, - 99,116,111,114,121,46,114,0,0,0,0,114,59,0,0,0, - 122,5,123,125,46,123,125,99,1,0,0,0,0,0,0,0, - 2,0,0,0,4,0,0,0,83,0,0,0,115,20,0,0, - 0,104,0,124,0,93,12,125,1,124,1,160,0,161,0,146, - 2,113,4,83,0,114,2,0,0,0,41,1,114,90,0,0, - 0,41,2,114,22,0,0,0,90,2,102,110,114,2,0,0, - 0,114,2,0,0,0,114,4,0,0,0,218,9,60,115,101, - 116,99,111,109,112,62,153,5,0,0,115,2,0,0,0,6, - 0,122,41,70,105,108,101,70,105,110,100,101,114,46,95,102, - 105,108,108,95,99,97,99,104,101,46,60,108,111,99,97,108, - 115,62,46,60,115,101,116,99,111,109,112,62,78,41,18,114, - 35,0,0,0,114,1,0,0,0,114,227,0,0,0,114,45, - 0,0,0,114,224,0,0,0,218,15,80,101,114,109,105,115, - 115,105,111,110,69,114,114,111,114,218,18,78,111,116,65,68, - 105,114,101,99,116,111,114,121,69,114,114,111,114,114,6,0, - 0,0,114,7,0,0,0,114,8,0,0,0,114,22,1,0, - 0,114,23,1,0,0,114,85,0,0,0,114,48,0,0,0, - 114,90,0,0,0,218,3,97,100,100,114,9,0,0,0,114, - 24,1,0,0,41,9,114,102,0,0,0,114,35,0,0,0, - 114,228,0,0,0,90,21,108,111,119,101,114,95,115,117,102, - 102,105,120,95,99,111,110,116,101,110,116,115,114,1,1,0, - 0,114,100,0,0,0,114,248,0,0,0,114,236,0,0,0, - 90,8,110,101,119,95,110,97,109,101,114,2,0,0,0,114, - 2,0,0,0,114,4,0,0,0,114,26,1,0,0,124,5, - 0,0,115,34,0,0,0,0,2,6,1,2,1,22,1,20, - 3,10,3,12,1,12,7,6,1,8,1,16,1,4,1,18, - 2,4,1,12,1,6,1,12,1,122,22,70,105,108,101,70, - 105,110,100,101,114,46,95,102,105,108,108,95,99,97,99,104, - 101,99,1,0,0,0,0,0,0,0,3,0,0,0,3,0, - 0,0,7,0,0,0,115,18,0,0,0,135,0,135,1,102, - 2,100,1,100,2,132,8,125,2,124,2,83,0,41,3,97, - 20,1,0,0,65,32,99,108,97,115,115,32,109,101,116,104, - 111,100,32,119,104,105,99,104,32,114,101,116,117,114,110,115, - 32,97,32,99,108,111,115,117,114,101,32,116,111,32,117,115, - 101,32,111,110,32,115,121,115,46,112,97,116,104,95,104,111, - 111,107,10,32,32,32,32,32,32,32,32,119,104,105,99,104, - 32,119,105,108,108,32,114,101,116,117,114,110,32,97,110,32, - 105,110,115,116,97,110,99,101,32,117,115,105,110,103,32,116, - 104,101,32,115,112,101,99,105,102,105,101,100,32,108,111,97, - 100,101,114,115,32,97,110,100,32,116,104,101,32,112,97,116, - 104,10,32,32,32,32,32,32,32,32,99,97,108,108,101,100, - 32,111,110,32,116,104,101,32,99,108,111,115,117,114,101,46, - 10,10,32,32,32,32,32,32,32,32,73,102,32,116,104,101, - 32,112,97,116,104,32,99,97,108,108,101,100,32,111,110,32, - 116,104,101,32,99,108,111,115,117,114,101,32,105,115,32,110, - 111,116,32,97,32,100,105,114,101,99,116,111,114,121,44,32, - 73,109,112,111,114,116,69,114,114,111,114,32,105,115,10,32, - 32,32,32,32,32,32,32,114,97,105,115,101,100,46,10,10, - 32,32,32,32,32,32,32,32,99,1,0,0,0,0,0,0, - 0,1,0,0,0,4,0,0,0,19,0,0,0,115,34,0, - 0,0,116,0,124,0,131,1,115,20,116,1,100,1,124,0, - 100,2,141,2,130,1,136,0,124,0,102,1,136,1,158,2, - 142,0,83,0,41,3,122,45,80,97,116,104,32,104,111,111, - 107,32,102,111,114,32,105,109,112,111,114,116,108,105,98,46, - 109,97,99,104,105,110,101,114,121,46,70,105,108,101,70,105, - 110,100,101,114,46,122,30,111,110,108,121,32,100,105,114,101, - 99,116,111,114,105,101,115,32,97,114,101,32,115,117,112,112, - 111,114,116,101,100,41,1,114,35,0,0,0,41,2,114,46, - 0,0,0,114,101,0,0,0,41,1,114,35,0,0,0,41, - 2,114,172,0,0,0,114,25,1,0,0,114,2,0,0,0, - 114,4,0,0,0,218,24,112,97,116,104,95,104,111,111,107, - 95,102,111,114,95,70,105,108,101,70,105,110,100,101,114,165, - 5,0,0,115,6,0,0,0,0,2,8,1,12,1,122,54, - 70,105,108,101,70,105,110,100,101,114,46,112,97,116,104,95, - 104,111,111,107,46,60,108,111,99,97,108,115,62,46,112,97, - 116,104,95,104,111,111,107,95,102,111,114,95,70,105,108,101, - 70,105,110,100,101,114,114,2,0,0,0,41,3,114,172,0, - 0,0,114,25,1,0,0,114,31,1,0,0,114,2,0,0, - 0,41,2,114,172,0,0,0,114,25,1,0,0,114,4,0, - 0,0,218,9,112,97,116,104,95,104,111,111,107,155,5,0, - 0,115,4,0,0,0,0,10,14,6,122,20,70,105,108,101, - 70,105,110,100,101,114,46,112,97,116,104,95,104,111,111,107, - 99,1,0,0,0,0,0,0,0,1,0,0,0,3,0,0, - 0,67,0,0,0,115,12,0,0,0,100,1,160,0,124,0, - 106,1,161,1,83,0,41,2,78,122,16,70,105,108,101,70, - 105,110,100,101,114,40,123,33,114,125,41,41,2,114,48,0, - 0,0,114,35,0,0,0,41,1,114,102,0,0,0,114,2, - 0,0,0,114,2,0,0,0,114,4,0,0,0,114,0,1, - 0,0,173,5,0,0,115,2,0,0,0,0,1,122,19,70, - 105,108,101,70,105,110,100,101,114,46,95,95,114,101,112,114, - 95,95,41,1,78,41,15,114,107,0,0,0,114,106,0,0, - 0,114,108,0,0,0,114,109,0,0,0,114,186,0,0,0, - 114,6,1,0,0,114,125,0,0,0,114,183,0,0,0,114, - 119,0,0,0,114,18,1,0,0,114,182,0,0,0,114,26, - 1,0,0,114,184,0,0,0,114,32,1,0,0,114,0,1, - 0,0,114,2,0,0,0,114,2,0,0,0,114,2,0,0, - 0,114,4,0,0,0,114,19,1,0,0,30,5,0,0,115, - 18,0,0,0,12,9,8,14,8,4,4,2,8,12,8,5, - 10,48,8,31,12,18,114,19,1,0,0,99,4,0,0,0, - 0,0,0,0,6,0,0,0,8,0,0,0,67,0,0,0, - 115,146,0,0,0,124,0,160,0,100,1,161,1,125,4,124, - 0,160,0,100,2,161,1,125,5,124,4,115,66,124,5,114, - 36,124,5,106,1,125,4,110,30,124,2,124,3,107,2,114, - 56,116,2,124,1,124,2,131,2,125,4,110,10,116,3,124, - 1,124,2,131,2,125,4,124,5,115,84,116,4,124,1,124, - 2,124,4,100,3,141,3,125,5,122,36,124,5,124,0,100, - 2,60,0,124,4,124,0,100,1,60,0,124,2,124,0,100, - 4,60,0,124,3,124,0,100,5,60,0,87,0,110,20,4, - 0,116,5,107,10,114,140,1,0,1,0,1,0,89,0,110, - 2,88,0,100,0,83,0,41,6,78,218,10,95,95,108,111, - 97,100,101,114,95,95,218,8,95,95,115,112,101,99,95,95, - 41,1,114,122,0,0,0,90,8,95,95,102,105,108,101,95, - 95,90,10,95,95,99,97,99,104,101,100,95,95,41,6,218, - 3,103,101,116,114,122,0,0,0,114,234,0,0,0,114,229, - 0,0,0,114,169,0,0,0,218,9,69,120,99,101,112,116, - 105,111,110,41,6,90,2,110,115,114,100,0,0,0,90,8, - 112,97,116,104,110,97,109,101,90,9,99,112,97,116,104,110, - 97,109,101,114,122,0,0,0,114,166,0,0,0,114,2,0, - 0,0,114,2,0,0,0,114,4,0,0,0,218,14,95,102, - 105,120,95,117,112,95,109,111,100,117,108,101,179,5,0,0, - 115,34,0,0,0,0,2,10,1,10,1,4,1,4,1,8, - 1,8,1,12,2,10,1,4,1,14,1,2,1,8,1,8, - 1,8,1,12,1,14,2,114,37,1,0,0,99,0,0,0, - 0,0,0,0,0,3,0,0,0,3,0,0,0,67,0,0, - 0,115,38,0,0,0,116,0,116,1,160,2,161,0,102,2, - 125,0,116,3,116,4,102,2,125,1,116,5,116,6,102,2, - 125,2,124,0,124,1,124,2,103,3,83,0,41,1,122,95, - 82,101,116,117,114,110,115,32,97,32,108,105,115,116,32,111, - 102,32,102,105,108,101,45,98,97,115,101,100,32,109,111,100, - 117,108,101,32,108,111,97,100,101,114,115,46,10,10,32,32, - 32,32,69,97,99,104,32,105,116,101,109,32,105,115,32,97, - 32,116,117,112,108,101,32,40,108,111,97,100,101,114,44,32, - 115,117,102,102,105,120,101,115,41,46,10,32,32,32,32,41, - 7,114,235,0,0,0,114,143,0,0,0,218,18,101,120,116, - 101,110,115,105,111,110,95,115,117,102,102,105,120,101,115,114, - 229,0,0,0,114,86,0,0,0,114,234,0,0,0,114,76, - 0,0,0,41,3,90,10,101,120,116,101,110,115,105,111,110, - 115,90,6,115,111,117,114,99,101,90,8,98,121,116,101,99, - 111,100,101,114,2,0,0,0,114,2,0,0,0,114,4,0, - 0,0,114,163,0,0,0,202,5,0,0,115,8,0,0,0, - 0,5,12,1,8,1,8,1,114,163,0,0,0,99,1,0, - 0,0,0,0,0,0,12,0,0,0,9,0,0,0,67,0, - 0,0,115,156,1,0,0,124,0,97,0,116,0,106,1,97, - 1,116,0,106,2,97,2,116,1,106,3,116,4,25,0,125, - 1,100,1,68,0,93,48,125,2,124,2,116,1,106,3,107, - 7,114,56,116,0,160,5,124,2,161,1,125,3,110,10,116, - 1,106,3,124,2,25,0,125,3,116,6,124,1,124,2,124, - 3,131,3,1,0,113,30,100,2,100,3,103,1,102,2,100, - 4,100,5,100,3,103,2,102,2,102,2,125,4,124,4,68, - 0,93,110,92,2,125,5,125,6,116,7,100,6,100,7,132, - 0,124,6,68,0,131,1,131,1,115,136,116,8,130,1,124, - 6,100,8,25,0,125,7,124,5,116,1,106,3,107,6,114, - 170,116,1,106,3,124,5,25,0,125,8,1,0,113,226,113, - 106,122,20,116,0,160,5,124,5,161,1,125,8,87,0,1, - 0,113,226,87,0,113,106,4,0,116,9,107,10,114,214,1, - 0,1,0,1,0,89,0,113,106,89,0,113,106,88,0,113, - 106,116,9,100,9,131,1,130,1,116,6,124,1,100,10,124, - 8,131,3,1,0,116,6,124,1,100,11,124,7,131,3,1, - 0,116,6,124,1,100,12,100,13,160,10,124,6,161,1,131, - 3,1,0,116,0,160,5,100,14,161,1,125,9,116,6,124, - 1,100,14,124,9,131,3,1,0,116,0,160,5,100,15,161, - 1,125,10,116,6,124,1,100,15,124,10,131,3,1,0,124, - 5,100,4,107,2,144,1,114,88,116,0,160,5,100,16,161, - 1,125,11,116,6,124,1,100,17,124,11,131,3,1,0,116, - 6,124,1,100,18,116,11,131,0,131,3,1,0,116,12,160, - 13,116,2,160,14,161,0,161,1,1,0,124,5,100,4,107, - 2,144,1,114,152,116,15,160,16,100,19,161,1,1,0,100, - 20,116,12,107,6,144,1,114,152,100,21,116,17,95,18,100, - 22,83,0,41,23,122,205,83,101,116,117,112,32,116,104,101, - 32,112,97,116,104,45,98,97,115,101,100,32,105,109,112,111, - 114,116,101,114,115,32,102,111,114,32,105,109,112,111,114,116, - 108,105,98,32,98,121,32,105,109,112,111,114,116,105,110,103, - 32,110,101,101,100,101,100,10,32,32,32,32,98,117,105,108, - 116,45,105,110,32,109,111,100,117,108,101,115,32,97,110,100, - 32,105,110,106,101,99,116,105,110,103,32,116,104,101,109,32, - 105,110,116,111,32,116,104,101,32,103,108,111,98,97,108,32, - 110,97,109,101,115,112,97,99,101,46,10,10,32,32,32,32, - 79,116,104,101,114,32,99,111,109,112,111,110,101,110,116,115, - 32,97,114,101,32,101,120,116,114,97,99,116,101,100,32,102, - 114,111,109,32,116,104,101,32,99,111,114,101,32,98,111,111, - 116,115,116,114,97,112,32,109,111,100,117,108,101,46,10,10, - 32,32,32,32,41,4,114,50,0,0,0,114,61,0,0,0, - 218,8,98,117,105,108,116,105,110,115,114,140,0,0,0,90, - 5,112,111,115,105,120,250,1,47,90,2,110,116,250,1,92, - 99,1,0,0,0,0,0,0,0,2,0,0,0,3,0,0, - 0,115,0,0,0,115,26,0,0,0,124,0,93,18,125,1, - 116,0,124,1,131,1,100,0,107,2,86,0,1,0,113,2, - 100,1,83,0,41,2,114,29,0,0,0,78,41,1,114,31, - 0,0,0,41,2,114,22,0,0,0,114,79,0,0,0,114, - 2,0,0,0,114,2,0,0,0,114,4,0,0,0,114,238, - 0,0,0,238,5,0,0,115,2,0,0,0,4,0,122,25, - 95,115,101,116,117,112,46,60,108,111,99,97,108,115,62,46, - 60,103,101,110,101,120,112,114,62,114,60,0,0,0,122,30, - 105,109,112,111,114,116,108,105,98,32,114,101,113,117,105,114, - 101,115,32,112,111,115,105,120,32,111,114,32,110,116,114,1, - 0,0,0,114,25,0,0,0,114,21,0,0,0,114,30,0, - 0,0,90,7,95,116,104,114,101,97,100,90,8,95,119,101, - 97,107,114,101,102,90,6,119,105,110,114,101,103,114,171,0, - 0,0,114,5,0,0,0,122,4,46,112,121,119,122,6,95, - 100,46,112,121,100,84,78,41,19,114,116,0,0,0,114,6, - 0,0,0,114,143,0,0,0,114,250,0,0,0,114,107,0, - 0,0,90,18,95,98,117,105,108,116,105,110,95,102,114,111, - 109,95,110,97,109,101,114,111,0,0,0,218,3,97,108,108, - 114,151,0,0,0,114,101,0,0,0,114,26,0,0,0,114, - 11,0,0,0,114,240,0,0,0,114,147,0,0,0,114,38, - 1,0,0,114,86,0,0,0,114,165,0,0,0,114,170,0, - 0,0,114,174,0,0,0,41,12,218,17,95,98,111,111,116, - 115,116,114,97,112,95,109,111,100,117,108,101,90,11,115,101, - 108,102,95,109,111,100,117,108,101,90,12,98,117,105,108,116, - 105,110,95,110,97,109,101,90,14,98,117,105,108,116,105,110, - 95,109,111,100,117,108,101,90,10,111,115,95,100,101,116,97, - 105,108,115,90,10,98,117,105,108,116,105,110,95,111,115,114, - 21,0,0,0,114,25,0,0,0,90,9,111,115,95,109,111, - 100,117,108,101,90,13,116,104,114,101,97,100,95,109,111,100, - 117,108,101,90,14,119,101,97,107,114,101,102,95,109,111,100, - 117,108,101,90,13,119,105,110,114,101,103,95,109,111,100,117, - 108,101,114,2,0,0,0,114,2,0,0,0,114,4,0,0, - 0,218,6,95,115,101,116,117,112,213,5,0,0,115,76,0, - 0,0,0,8,4,1,6,1,6,3,10,1,8,1,10,1, - 12,2,10,1,14,3,22,1,12,2,22,1,8,1,10,1, - 10,1,6,2,2,1,10,1,10,1,14,1,12,2,8,1, - 12,1,12,1,18,3,10,1,12,3,10,1,12,3,10,1, - 10,1,12,3,14,1,14,1,10,1,10,1,10,1,114,44, - 1,0,0,99,1,0,0,0,0,0,0,0,2,0,0,0, - 4,0,0,0,67,0,0,0,115,50,0,0,0,116,0,124, - 0,131,1,1,0,116,1,131,0,125,1,116,2,106,3,160, - 4,116,5,106,6,124,1,142,0,103,1,161,1,1,0,116, - 2,106,7,160,8,116,9,161,1,1,0,100,1,83,0,41, - 2,122,41,73,110,115,116,97,108,108,32,116,104,101,32,112, - 97,116,104,45,98,97,115,101,100,32,105,109,112,111,114,116, - 32,99,111,109,112,111,110,101,110,116,115,46,78,41,10,114, - 44,1,0,0,114,163,0,0,0,114,6,0,0,0,114,11, - 1,0,0,114,147,0,0,0,114,19,1,0,0,114,32,1, - 0,0,218,9,109,101,116,97,95,112,97,116,104,114,165,0, - 0,0,114,5,1,0,0,41,2,114,43,1,0,0,90,17, - 115,117,112,112,111,114,116,101,100,95,108,111,97,100,101,114, - 115,114,2,0,0,0,114,2,0,0,0,114,4,0,0,0, - 218,8,95,105,110,115,116,97,108,108,21,6,0,0,115,8, - 0,0,0,0,2,8,1,6,1,20,1,114,46,1,0,0, - 41,1,114,47,0,0,0,41,1,78,41,3,78,78,78,41, - 2,114,60,0,0,0,114,60,0,0,0,41,1,84,41,1, - 78,41,1,78,41,61,114,109,0,0,0,114,10,0,0,0, - 90,37,95,67,65,83,69,95,73,78,83,69,78,83,73,84, - 73,86,69,95,80,76,65,84,70,79,82,77,83,95,66,89, - 84,69,83,95,75,69,89,114,9,0,0,0,114,11,0,0, - 0,114,17,0,0,0,114,19,0,0,0,114,28,0,0,0, - 114,38,0,0,0,114,39,0,0,0,114,43,0,0,0,114, - 44,0,0,0,114,46,0,0,0,114,56,0,0,0,218,4, - 116,121,112,101,218,8,95,95,99,111,100,101,95,95,114,142, - 0,0,0,114,15,0,0,0,114,129,0,0,0,114,14,0, - 0,0,114,18,0,0,0,114,209,0,0,0,114,75,0,0, - 0,114,74,0,0,0,114,86,0,0,0,114,76,0,0,0, - 90,23,68,69,66,85,71,95,66,89,84,69,67,79,68,69, - 95,83,85,70,70,73,88,69,83,90,27,79,80,84,73,77, - 73,90,69,68,95,66,89,84,69,67,79,68,69,95,83,85, - 70,70,73,88,69,83,114,81,0,0,0,114,87,0,0,0, - 114,93,0,0,0,114,97,0,0,0,114,99,0,0,0,114, - 118,0,0,0,114,125,0,0,0,114,133,0,0,0,114,137, - 0,0,0,114,139,0,0,0,114,145,0,0,0,114,150,0, - 0,0,114,152,0,0,0,114,157,0,0,0,218,6,111,98, - 106,101,99,116,114,164,0,0,0,114,169,0,0,0,114,170, - 0,0,0,114,185,0,0,0,114,195,0,0,0,114,212,0, - 0,0,114,229,0,0,0,114,234,0,0,0,114,240,0,0, - 0,114,235,0,0,0,114,241,0,0,0,114,3,1,0,0, - 114,5,1,0,0,114,19,1,0,0,114,37,1,0,0,114, - 163,0,0,0,114,44,1,0,0,114,46,1,0,0,114,2, + 10,32,32,32,32,32,32,32,32,78,41,2,114,182,0,0, + 0,114,122,0,0,0,41,4,114,172,0,0,0,114,121,0, + 0,0,114,35,0,0,0,114,166,0,0,0,114,2,0,0, + 0,114,2,0,0,0,114,4,0,0,0,114,183,0,0,0, + 16,5,0,0,115,8,0,0,0,0,8,12,1,8,1,4, + 1,122,22,80,97,116,104,70,105,110,100,101,114,46,102,105, + 110,100,95,109,111,100,117,108,101,41,1,78,41,2,78,78, + 41,1,78,41,12,114,107,0,0,0,114,106,0,0,0,114, + 108,0,0,0,114,109,0,0,0,114,184,0,0,0,114,6, + 1,0,0,114,12,1,0,0,114,14,1,0,0,114,15,1, + 0,0,114,18,1,0,0,114,182,0,0,0,114,183,0,0, + 0,114,2,0,0,0,114,2,0,0,0,114,2,0,0,0, + 114,4,0,0,0,114,5,1,0,0,152,4,0,0,115,22, + 0,0,0,8,2,4,2,12,10,12,13,12,22,12,15,2, + 1,12,31,2,1,12,23,2,1,114,5,1,0,0,99,0, + 0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,64, + 0,0,0,115,90,0,0,0,101,0,90,1,100,0,90,2, + 100,1,90,3,100,2,100,3,132,0,90,4,100,4,100,5, + 132,0,90,5,101,6,90,7,100,6,100,7,132,0,90,8, + 100,8,100,9,132,0,90,9,100,19,100,11,100,12,132,1, + 90,10,100,13,100,14,132,0,90,11,101,12,100,15,100,16, + 132,0,131,1,90,13,100,17,100,18,132,0,90,14,100,10, + 83,0,41,20,218,10,70,105,108,101,70,105,110,100,101,114, + 122,172,70,105,108,101,45,98,97,115,101,100,32,102,105,110, + 100,101,114,46,10,10,32,32,32,32,73,110,116,101,114,97, + 99,116,105,111,110,115,32,119,105,116,104,32,116,104,101,32, + 102,105,108,101,32,115,121,115,116,101,109,32,97,114,101,32, + 99,97,99,104,101,100,32,102,111,114,32,112,101,114,102,111, + 114,109,97,110,99,101,44,32,98,101,105,110,103,10,32,32, + 32,32,114,101,102,114,101,115,104,101,100,32,119,104,101,110, + 32,116,104,101,32,100,105,114,101,99,116,111,114,121,32,116, + 104,101,32,102,105,110,100,101,114,32,105,115,32,104,97,110, + 100,108,105,110,103,32,104,97,115,32,98,101,101,110,32,109, + 111,100,105,102,105,101,100,46,10,10,32,32,32,32,99,2, + 0,0,0,0,0,0,0,5,0,0,0,6,0,0,0,7, + 0,0,0,115,84,0,0,0,103,0,125,3,124,2,68,0, + 93,32,92,2,137,0,125,4,124,3,160,0,135,0,102,1, + 100,1,100,2,132,8,124,4,68,0,131,1,161,1,1,0, + 113,8,124,3,124,0,95,1,124,1,112,54,100,3,124,0, + 95,2,100,4,124,0,95,3,116,4,131,0,124,0,95,5, + 116,4,131,0,124,0,95,6,100,5,83,0,41,6,122,154, + 73,110,105,116,105,97,108,105,122,101,32,119,105,116,104,32, + 116,104,101,32,112,97,116,104,32,116,111,32,115,101,97,114, + 99,104,32,111,110,32,97,110,100,32,97,32,118,97,114,105, + 97,98,108,101,32,110,117,109,98,101,114,32,111,102,10,32, + 32,32,32,32,32,32,32,50,45,116,117,112,108,101,115,32, + 99,111,110,116,97,105,110,105,110,103,32,116,104,101,32,108, + 111,97,100,101,114,32,97,110,100,32,116,104,101,32,102,105, + 108,101,32,115,117,102,102,105,120,101,115,32,116,104,101,32, + 108,111,97,100,101,114,10,32,32,32,32,32,32,32,32,114, + 101,99,111,103,110,105,122,101,115,46,99,1,0,0,0,0, + 0,0,0,2,0,0,0,3,0,0,0,51,0,0,0,115, + 22,0,0,0,124,0,93,14,125,1,124,1,136,0,102,2, + 86,0,1,0,113,2,100,0,83,0,41,1,78,114,2,0, + 0,0,41,2,114,22,0,0,0,114,236,0,0,0,41,1, + 114,122,0,0,0,114,2,0,0,0,114,4,0,0,0,114, + 238,0,0,0,45,5,0,0,115,2,0,0,0,4,0,122, + 38,70,105,108,101,70,105,110,100,101,114,46,95,95,105,110, + 105,116,95,95,46,60,108,111,99,97,108,115,62,46,60,103, + 101,110,101,120,112,114,62,114,59,0,0,0,114,89,0,0, + 0,78,41,7,114,147,0,0,0,218,8,95,108,111,97,100, + 101,114,115,114,35,0,0,0,218,11,95,112,97,116,104,95, + 109,116,105,109,101,218,3,115,101,116,218,11,95,112,97,116, + 104,95,99,97,99,104,101,218,19,95,114,101,108,97,120,101, + 100,95,112,97,116,104,95,99,97,99,104,101,41,5,114,102, + 0,0,0,114,35,0,0,0,218,14,108,111,97,100,101,114, + 95,100,101,116,97,105,108,115,90,7,108,111,97,100,101,114, + 115,114,168,0,0,0,114,2,0,0,0,41,1,114,122,0, + 0,0,114,4,0,0,0,114,186,0,0,0,39,5,0,0, + 115,16,0,0,0,0,4,4,1,12,1,26,1,6,2,10, + 1,6,1,8,1,122,19,70,105,108,101,70,105,110,100,101, + 114,46,95,95,105,110,105,116,95,95,99,1,0,0,0,0, + 0,0,0,1,0,0,0,2,0,0,0,67,0,0,0,115, + 10,0,0,0,100,1,124,0,95,0,100,2,83,0,41,3, + 122,31,73,110,118,97,108,105,100,97,116,101,32,116,104,101, + 32,100,105,114,101,99,116,111,114,121,32,109,116,105,109,101, + 46,114,89,0,0,0,78,41,1,114,21,1,0,0,41,1, + 114,102,0,0,0,114,2,0,0,0,114,2,0,0,0,114, + 4,0,0,0,114,6,1,0,0,53,5,0,0,115,2,0, + 0,0,0,2,122,28,70,105,108,101,70,105,110,100,101,114, + 46,105,110,118,97,108,105,100,97,116,101,95,99,97,99,104, + 101,115,99,2,0,0,0,0,0,0,0,3,0,0,0,3, + 0,0,0,67,0,0,0,115,42,0,0,0,124,0,160,0, + 124,1,161,1,125,2,124,2,100,1,107,8,114,26,100,1, + 103,0,102,2,83,0,124,2,106,1,124,2,106,2,112,38, + 103,0,102,2,83,0,41,2,122,197,84,114,121,32,116,111, + 32,102,105,110,100,32,97,32,108,111,97,100,101,114,32,102, + 111,114,32,116,104,101,32,115,112,101,99,105,102,105,101,100, + 32,109,111,100,117,108,101,44,32,111,114,32,116,104,101,32, + 110,97,109,101,115,112,97,99,101,10,32,32,32,32,32,32, + 32,32,112,97,99,107,97,103,101,32,112,111,114,116,105,111, + 110,115,46,32,82,101,116,117,114,110,115,32,40,108,111,97, + 100,101,114,44,32,108,105,115,116,45,111,102,45,112,111,114, + 116,105,111,110,115,41,46,10,10,32,32,32,32,32,32,32, + 32,84,104,105,115,32,109,101,116,104,111,100,32,105,115,32, + 100,101,112,114,101,99,97,116,101,100,46,32,32,85,115,101, + 32,102,105,110,100,95,115,112,101,99,40,41,32,105,110,115, + 116,101,97,100,46,10,10,32,32,32,32,32,32,32,32,78, + 41,3,114,182,0,0,0,114,122,0,0,0,114,158,0,0, + 0,41,3,114,102,0,0,0,114,121,0,0,0,114,166,0, + 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, + 0,114,119,0,0,0,59,5,0,0,115,8,0,0,0,0, + 7,10,1,8,1,8,1,122,22,70,105,108,101,70,105,110, + 100,101,114,46,102,105,110,100,95,108,111,97,100,101,114,99, + 6,0,0,0,0,0,0,0,7,0,0,0,6,0,0,0, + 67,0,0,0,115,26,0,0,0,124,1,124,2,124,3,131, + 2,125,6,116,0,124,2,124,3,124,6,124,4,100,1,141, + 4,83,0,41,2,78,41,2,114,122,0,0,0,114,158,0, + 0,0,41,1,114,169,0,0,0,41,7,114,102,0,0,0, + 114,167,0,0,0,114,121,0,0,0,114,35,0,0,0,90, + 4,115,109,115,108,114,181,0,0,0,114,122,0,0,0,114, + 2,0,0,0,114,2,0,0,0,114,4,0,0,0,114,18, + 1,0,0,71,5,0,0,115,6,0,0,0,0,1,10,1, + 8,1,122,20,70,105,108,101,70,105,110,100,101,114,46,95, + 103,101,116,95,115,112,101,99,78,99,3,0,0,0,0,0, + 0,0,14,0,0,0,8,0,0,0,67,0,0,0,115,98, + 1,0,0,100,1,125,3,124,1,160,0,100,2,161,1,100, + 3,25,0,125,4,122,24,116,1,124,0,106,2,112,34,116, + 3,160,4,161,0,131,1,106,5,125,5,87,0,110,24,4, + 0,116,6,107,10,114,66,1,0,1,0,1,0,100,4,125, + 5,89,0,110,2,88,0,124,5,124,0,106,7,107,3,114, + 92,124,0,160,8,161,0,1,0,124,5,124,0,95,7,116, + 9,131,0,114,114,124,0,106,10,125,6,124,4,160,11,161, + 0,125,7,110,10,124,0,106,12,125,6,124,4,125,7,124, + 7,124,6,107,6,114,218,116,13,124,0,106,2,124,4,131, + 2,125,8,124,0,106,14,68,0,93,58,92,2,125,9,125, + 10,100,5,124,9,23,0,125,11,116,13,124,8,124,11,131, + 2,125,12,116,15,124,12,131,1,114,150,124,0,160,16,124, + 10,124,1,124,12,124,8,103,1,124,2,161,5,2,0,1, + 0,83,0,113,150,116,17,124,8,131,1,125,3,124,0,106, + 14,68,0,93,82,92,2,125,9,125,10,116,13,124,0,106, + 2,124,4,124,9,23,0,131,2,125,12,116,18,106,19,100, + 6,124,12,100,3,100,7,141,3,1,0,124,7,124,9,23, + 0,124,6,107,6,114,224,116,15,124,12,131,1,114,224,124, + 0,160,16,124,10,124,1,124,12,100,8,124,2,161,5,2, + 0,1,0,83,0,113,224,124,3,144,1,114,94,116,18,160, + 19,100,9,124,8,161,2,1,0,116,18,160,20,124,1,100, + 8,161,2,125,13,124,8,103,1,124,13,95,21,124,13,83, + 0,100,8,83,0,41,10,122,111,84,114,121,32,116,111,32, + 102,105,110,100,32,97,32,115,112,101,99,32,102,111,114,32, + 116,104,101,32,115,112,101,99,105,102,105,101,100,32,109,111, + 100,117,108,101,46,10,10,32,32,32,32,32,32,32,32,82, + 101,116,117,114,110,115,32,116,104,101,32,109,97,116,99,104, + 105,110,103,32,115,112,101,99,44,32,111,114,32,78,111,110, + 101,32,105,102,32,110,111,116,32,102,111,117,110,100,46,10, + 32,32,32,32,32,32,32,32,70,114,59,0,0,0,114,57, + 0,0,0,114,89,0,0,0,114,186,0,0,0,122,9,116, + 114,121,105,110,103,32,123,125,41,1,90,9,118,101,114,98, + 111,115,105,116,121,78,122,25,112,111,115,115,105,98,108,101, + 32,110,97,109,101,115,112,97,99,101,32,102,111,114,32,123, + 125,41,22,114,32,0,0,0,114,39,0,0,0,114,35,0, + 0,0,114,1,0,0,0,114,45,0,0,0,114,230,0,0, + 0,114,40,0,0,0,114,21,1,0,0,218,11,95,102,105, + 108,108,95,99,97,99,104,101,114,5,0,0,0,114,24,1, + 0,0,114,90,0,0,0,114,23,1,0,0,114,28,0,0, + 0,114,20,1,0,0,114,44,0,0,0,114,18,1,0,0, + 114,46,0,0,0,114,116,0,0,0,114,130,0,0,0,114, + 162,0,0,0,114,158,0,0,0,41,14,114,102,0,0,0, + 114,121,0,0,0,114,181,0,0,0,90,12,105,115,95,110, + 97,109,101,115,112,97,99,101,90,11,116,97,105,108,95,109, + 111,100,117,108,101,114,149,0,0,0,90,5,99,97,99,104, + 101,90,12,99,97,99,104,101,95,109,111,100,117,108,101,90, + 9,98,97,115,101,95,112,97,116,104,114,236,0,0,0,114, + 167,0,0,0,90,13,105,110,105,116,95,102,105,108,101,110, + 97,109,101,90,9,102,117,108,108,95,112,97,116,104,114,166, 0,0,0,114,2,0,0,0,114,2,0,0,0,114,4,0, - 0,0,218,8,60,109,111,100,117,108,101,62,23,0,0,0, - 115,118,0,0,0,4,0,4,1,4,1,2,1,6,3,8, - 17,8,5,8,5,8,6,8,12,8,10,8,9,8,5,8, - 7,10,22,10,127,0,5,16,1,12,2,4,1,4,2,6, - 2,6,2,8,2,16,45,8,34,8,19,8,12,8,12,8, - 28,8,17,8,33,8,28,8,24,10,13,10,10,10,11,8, - 14,6,3,4,1,14,67,14,64,14,29,16,127,0,17,14, - 68,18,45,18,26,4,3,18,53,14,60,14,42,14,127,0, - 7,14,127,0,22,10,23,8,11,8,64, + 0,0,114,182,0,0,0,76,5,0,0,115,70,0,0,0, + 0,5,4,1,14,1,2,1,24,1,14,1,10,1,10,1, + 8,1,6,2,6,1,6,1,10,2,6,1,4,2,8,1, + 12,1,14,1,8,1,10,1,8,1,26,4,8,2,14,1, + 16,1,16,1,12,1,8,1,10,1,14,1,6,1,12,1, + 12,1,8,1,4,1,122,20,70,105,108,101,70,105,110,100, + 101,114,46,102,105,110,100,95,115,112,101,99,99,1,0,0, + 0,0,0,0,0,9,0,0,0,10,0,0,0,67,0,0, + 0,115,190,0,0,0,124,0,106,0,125,1,122,22,116,1, + 160,2,124,1,112,22,116,1,160,3,161,0,161,1,125,2, + 87,0,110,30,4,0,116,4,116,5,116,6,102,3,107,10, + 114,58,1,0,1,0,1,0,103,0,125,2,89,0,110,2, + 88,0,116,7,106,8,160,9,100,1,161,1,115,84,116,10, + 124,2,131,1,124,0,95,11,110,74,116,10,131,0,125,3, + 124,2,68,0,93,56,125,4,124,4,160,12,100,2,161,1, + 92,3,125,5,125,6,125,7,124,6,114,136,100,3,160,13, + 124,5,124,7,160,14,161,0,161,2,125,8,110,4,124,5, + 125,8,124,3,160,15,124,8,161,1,1,0,113,94,124,3, + 124,0,95,11,116,7,106,8,160,9,116,16,161,1,114,186, + 100,4,100,5,132,0,124,2,68,0,131,1,124,0,95,17, + 100,6,83,0,41,7,122,68,70,105,108,108,32,116,104,101, + 32,99,97,99,104,101,32,111,102,32,112,111,116,101,110,116, + 105,97,108,32,109,111,100,117,108,101,115,32,97,110,100,32, + 112,97,99,107,97,103,101,115,32,102,111,114,32,116,104,105, + 115,32,100,105,114,101,99,116,111,114,121,46,114,0,0,0, + 0,114,59,0,0,0,122,5,123,125,46,123,125,99,1,0, + 0,0,0,0,0,0,2,0,0,0,4,0,0,0,83,0, + 0,0,115,20,0,0,0,104,0,124,0,93,12,125,1,124, + 1,160,0,161,0,146,2,113,4,83,0,114,2,0,0,0, + 41,1,114,90,0,0,0,41,2,114,22,0,0,0,90,2, + 102,110,114,2,0,0,0,114,2,0,0,0,114,4,0,0, + 0,218,9,60,115,101,116,99,111,109,112,62,153,5,0,0, + 115,2,0,0,0,6,0,122,41,70,105,108,101,70,105,110, + 100,101,114,46,95,102,105,108,108,95,99,97,99,104,101,46, + 60,108,111,99,97,108,115,62,46,60,115,101,116,99,111,109, + 112,62,78,41,18,114,35,0,0,0,114,1,0,0,0,114, + 227,0,0,0,114,45,0,0,0,114,224,0,0,0,218,15, + 80,101,114,109,105,115,115,105,111,110,69,114,114,111,114,218, + 18,78,111,116,65,68,105,114,101,99,116,111,114,121,69,114, + 114,111,114,114,6,0,0,0,114,7,0,0,0,114,8,0, + 0,0,114,22,1,0,0,114,23,1,0,0,114,85,0,0, + 0,114,48,0,0,0,114,90,0,0,0,218,3,97,100,100, + 114,9,0,0,0,114,24,1,0,0,41,9,114,102,0,0, + 0,114,35,0,0,0,114,228,0,0,0,90,21,108,111,119, + 101,114,95,115,117,102,102,105,120,95,99,111,110,116,101,110, + 116,115,114,1,1,0,0,114,100,0,0,0,114,248,0,0, + 0,114,236,0,0,0,90,8,110,101,119,95,110,97,109,101, + 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,114, + 26,1,0,0,124,5,0,0,115,34,0,0,0,0,2,6, + 1,2,1,22,1,20,3,10,3,12,1,12,7,6,1,8, + 1,16,1,4,1,18,2,4,1,12,1,6,1,12,1,122, + 22,70,105,108,101,70,105,110,100,101,114,46,95,102,105,108, + 108,95,99,97,99,104,101,99,1,0,0,0,0,0,0,0, + 3,0,0,0,3,0,0,0,7,0,0,0,115,18,0,0, + 0,135,0,135,1,102,2,100,1,100,2,132,8,125,2,124, + 2,83,0,41,3,97,20,1,0,0,65,32,99,108,97,115, + 115,32,109,101,116,104,111,100,32,119,104,105,99,104,32,114, + 101,116,117,114,110,115,32,97,32,99,108,111,115,117,114,101, + 32,116,111,32,117,115,101,32,111,110,32,115,121,115,46,112, + 97,116,104,95,104,111,111,107,10,32,32,32,32,32,32,32, + 32,119,104,105,99,104,32,119,105,108,108,32,114,101,116,117, + 114,110,32,97,110,32,105,110,115,116,97,110,99,101,32,117, + 115,105,110,103,32,116,104,101,32,115,112,101,99,105,102,105, + 101,100,32,108,111,97,100,101,114,115,32,97,110,100,32,116, + 104,101,32,112,97,116,104,10,32,32,32,32,32,32,32,32, + 99,97,108,108,101,100,32,111,110,32,116,104,101,32,99,108, + 111,115,117,114,101,46,10,10,32,32,32,32,32,32,32,32, + 73,102,32,116,104,101,32,112,97,116,104,32,99,97,108,108, + 101,100,32,111,110,32,116,104,101,32,99,108,111,115,117,114, + 101,32,105,115,32,110,111,116,32,97,32,100,105,114,101,99, + 116,111,114,121,44,32,73,109,112,111,114,116,69,114,114,111, + 114,32,105,115,10,32,32,32,32,32,32,32,32,114,97,105, + 115,101,100,46,10,10,32,32,32,32,32,32,32,32,99,1, + 0,0,0,0,0,0,0,1,0,0,0,4,0,0,0,19, + 0,0,0,115,34,0,0,0,116,0,124,0,131,1,115,20, + 116,1,100,1,124,0,100,2,141,2,130,1,136,0,124,0, + 102,1,136,1,158,2,142,0,83,0,41,3,122,45,80,97, + 116,104,32,104,111,111,107,32,102,111,114,32,105,109,112,111, + 114,116,108,105,98,46,109,97,99,104,105,110,101,114,121,46, + 70,105,108,101,70,105,110,100,101,114,46,122,30,111,110,108, + 121,32,100,105,114,101,99,116,111,114,105,101,115,32,97,114, + 101,32,115,117,112,112,111,114,116,101,100,41,1,114,35,0, + 0,0,41,2,114,46,0,0,0,114,101,0,0,0,41,1, + 114,35,0,0,0,41,2,114,172,0,0,0,114,25,1,0, + 0,114,2,0,0,0,114,4,0,0,0,218,24,112,97,116, + 104,95,104,111,111,107,95,102,111,114,95,70,105,108,101,70, + 105,110,100,101,114,165,5,0,0,115,6,0,0,0,0,2, + 8,1,12,1,122,54,70,105,108,101,70,105,110,100,101,114, + 46,112,97,116,104,95,104,111,111,107,46,60,108,111,99,97, + 108,115,62,46,112,97,116,104,95,104,111,111,107,95,102,111, + 114,95,70,105,108,101,70,105,110,100,101,114,114,2,0,0, + 0,41,3,114,172,0,0,0,114,25,1,0,0,114,31,1, + 0,0,114,2,0,0,0,41,2,114,172,0,0,0,114,25, + 1,0,0,114,4,0,0,0,218,9,112,97,116,104,95,104, + 111,111,107,155,5,0,0,115,4,0,0,0,0,10,14,6, + 122,20,70,105,108,101,70,105,110,100,101,114,46,112,97,116, + 104,95,104,111,111,107,99,1,0,0,0,0,0,0,0,1, + 0,0,0,3,0,0,0,67,0,0,0,115,12,0,0,0, + 100,1,160,0,124,0,106,1,161,1,83,0,41,2,78,122, + 16,70,105,108,101,70,105,110,100,101,114,40,123,33,114,125, + 41,41,2,114,48,0,0,0,114,35,0,0,0,41,1,114, + 102,0,0,0,114,2,0,0,0,114,2,0,0,0,114,4, + 0,0,0,114,0,1,0,0,173,5,0,0,115,2,0,0, + 0,0,1,122,19,70,105,108,101,70,105,110,100,101,114,46, + 95,95,114,101,112,114,95,95,41,1,78,41,15,114,107,0, + 0,0,114,106,0,0,0,114,108,0,0,0,114,109,0,0, + 0,114,186,0,0,0,114,6,1,0,0,114,125,0,0,0, + 114,183,0,0,0,114,119,0,0,0,114,18,1,0,0,114, + 182,0,0,0,114,26,1,0,0,114,184,0,0,0,114,32, + 1,0,0,114,0,1,0,0,114,2,0,0,0,114,2,0, + 0,0,114,2,0,0,0,114,4,0,0,0,114,19,1,0, + 0,30,5,0,0,115,20,0,0,0,8,7,4,2,8,14, + 8,4,4,2,8,12,8,5,10,48,8,31,12,18,114,19, + 1,0,0,99,4,0,0,0,0,0,0,0,6,0,0,0, + 8,0,0,0,67,0,0,0,115,146,0,0,0,124,0,160, + 0,100,1,161,1,125,4,124,0,160,0,100,2,161,1,125, + 5,124,4,115,66,124,5,114,36,124,5,106,1,125,4,110, + 30,124,2,124,3,107,2,114,56,116,2,124,1,124,2,131, + 2,125,4,110,10,116,3,124,1,124,2,131,2,125,4,124, + 5,115,84,116,4,124,1,124,2,124,4,100,3,141,3,125, + 5,122,36,124,5,124,0,100,2,60,0,124,4,124,0,100, + 1,60,0,124,2,124,0,100,4,60,0,124,3,124,0,100, + 5,60,0,87,0,110,20,4,0,116,5,107,10,114,140,1, + 0,1,0,1,0,89,0,110,2,88,0,100,0,83,0,41, + 6,78,218,10,95,95,108,111,97,100,101,114,95,95,218,8, + 95,95,115,112,101,99,95,95,41,1,114,122,0,0,0,90, + 8,95,95,102,105,108,101,95,95,90,10,95,95,99,97,99, + 104,101,100,95,95,41,6,218,3,103,101,116,114,122,0,0, + 0,114,234,0,0,0,114,229,0,0,0,114,169,0,0,0, + 218,9,69,120,99,101,112,116,105,111,110,41,6,90,2,110, + 115,114,100,0,0,0,90,8,112,97,116,104,110,97,109,101, + 90,9,99,112,97,116,104,110,97,109,101,114,122,0,0,0, + 114,166,0,0,0,114,2,0,0,0,114,2,0,0,0,114, + 4,0,0,0,218,14,95,102,105,120,95,117,112,95,109,111, + 100,117,108,101,179,5,0,0,115,34,0,0,0,0,2,10, + 1,10,1,4,1,4,1,8,1,8,1,12,2,10,1,4, + 1,14,1,2,1,8,1,8,1,8,1,12,1,14,2,114, + 37,1,0,0,99,0,0,0,0,0,0,0,0,3,0,0, + 0,3,0,0,0,67,0,0,0,115,38,0,0,0,116,0, + 116,1,160,2,161,0,102,2,125,0,116,3,116,4,102,2, + 125,1,116,5,116,6,102,2,125,2,124,0,124,1,124,2, + 103,3,83,0,41,1,122,95,82,101,116,117,114,110,115,32, + 97,32,108,105,115,116,32,111,102,32,102,105,108,101,45,98, + 97,115,101,100,32,109,111,100,117,108,101,32,108,111,97,100, + 101,114,115,46,10,10,32,32,32,32,69,97,99,104,32,105, + 116,101,109,32,105,115,32,97,32,116,117,112,108,101,32,40, + 108,111,97,100,101,114,44,32,115,117,102,102,105,120,101,115, + 41,46,10,32,32,32,32,41,7,114,235,0,0,0,114,143, + 0,0,0,218,18,101,120,116,101,110,115,105,111,110,95,115, + 117,102,102,105,120,101,115,114,229,0,0,0,114,86,0,0, + 0,114,234,0,0,0,114,76,0,0,0,41,3,90,10,101, + 120,116,101,110,115,105,111,110,115,90,6,115,111,117,114,99, + 101,90,8,98,121,116,101,99,111,100,101,114,2,0,0,0, + 114,2,0,0,0,114,4,0,0,0,114,163,0,0,0,202, + 5,0,0,115,8,0,0,0,0,5,12,1,8,1,8,1, + 114,163,0,0,0,99,1,0,0,0,0,0,0,0,12,0, + 0,0,9,0,0,0,67,0,0,0,115,156,1,0,0,124, + 0,97,0,116,0,106,1,97,1,116,0,106,2,97,2,116, + 1,106,3,116,4,25,0,125,1,100,1,68,0,93,48,125, + 2,124,2,116,1,106,3,107,7,114,56,116,0,160,5,124, + 2,161,1,125,3,110,10,116,1,106,3,124,2,25,0,125, + 3,116,6,124,1,124,2,124,3,131,3,1,0,113,30,100, + 2,100,3,103,1,102,2,100,4,100,5,100,3,103,2,102, + 2,102,2,125,4,124,4,68,0,93,110,92,2,125,5,125, + 6,116,7,100,6,100,7,132,0,124,6,68,0,131,1,131, + 1,115,136,116,8,130,1,124,6,100,8,25,0,125,7,124, + 5,116,1,106,3,107,6,114,170,116,1,106,3,124,5,25, + 0,125,8,1,0,113,226,113,106,122,20,116,0,160,5,124, + 5,161,1,125,8,87,0,1,0,113,226,87,0,113,106,4, + 0,116,9,107,10,114,214,1,0,1,0,1,0,89,0,113, + 106,89,0,113,106,88,0,113,106,116,9,100,9,131,1,130, + 1,116,6,124,1,100,10,124,8,131,3,1,0,116,6,124, + 1,100,11,124,7,131,3,1,0,116,6,124,1,100,12,100, + 13,160,10,124,6,161,1,131,3,1,0,116,0,160,5,100, + 14,161,1,125,9,116,6,124,1,100,14,124,9,131,3,1, + 0,116,0,160,5,100,15,161,1,125,10,116,6,124,1,100, + 15,124,10,131,3,1,0,124,5,100,4,107,2,144,1,114, + 88,116,0,160,5,100,16,161,1,125,11,116,6,124,1,100, + 17,124,11,131,3,1,0,116,6,124,1,100,18,116,11,131, + 0,131,3,1,0,116,12,160,13,116,2,160,14,161,0,161, + 1,1,0,124,5,100,4,107,2,144,1,114,152,116,15,160, + 16,100,19,161,1,1,0,100,20,116,12,107,6,144,1,114, + 152,100,21,116,17,95,18,100,22,83,0,41,23,122,205,83, + 101,116,117,112,32,116,104,101,32,112,97,116,104,45,98,97, + 115,101,100,32,105,109,112,111,114,116,101,114,115,32,102,111, + 114,32,105,109,112,111,114,116,108,105,98,32,98,121,32,105, + 109,112,111,114,116,105,110,103,32,110,101,101,100,101,100,10, + 32,32,32,32,98,117,105,108,116,45,105,110,32,109,111,100, + 117,108,101,115,32,97,110,100,32,105,110,106,101,99,116,105, + 110,103,32,116,104,101,109,32,105,110,116,111,32,116,104,101, + 32,103,108,111,98,97,108,32,110,97,109,101,115,112,97,99, + 101,46,10,10,32,32,32,32,79,116,104,101,114,32,99,111, + 109,112,111,110,101,110,116,115,32,97,114,101,32,101,120,116, + 114,97,99,116,101,100,32,102,114,111,109,32,116,104,101,32, + 99,111,114,101,32,98,111,111,116,115,116,114,97,112,32,109, + 111,100,117,108,101,46,10,10,32,32,32,32,41,4,114,50, + 0,0,0,114,61,0,0,0,218,8,98,117,105,108,116,105, + 110,115,114,140,0,0,0,90,5,112,111,115,105,120,250,1, + 47,90,2,110,116,250,1,92,99,1,0,0,0,0,0,0, + 0,2,0,0,0,3,0,0,0,115,0,0,0,115,26,0, + 0,0,124,0,93,18,125,1,116,0,124,1,131,1,100,0, + 107,2,86,0,1,0,113,2,100,1,83,0,41,2,114,29, + 0,0,0,78,41,1,114,31,0,0,0,41,2,114,22,0, + 0,0,114,79,0,0,0,114,2,0,0,0,114,2,0,0, + 0,114,4,0,0,0,114,238,0,0,0,238,5,0,0,115, + 2,0,0,0,4,0,122,25,95,115,101,116,117,112,46,60, + 108,111,99,97,108,115,62,46,60,103,101,110,101,120,112,114, + 62,114,60,0,0,0,122,30,105,109,112,111,114,116,108,105, + 98,32,114,101,113,117,105,114,101,115,32,112,111,115,105,120, + 32,111,114,32,110,116,114,1,0,0,0,114,25,0,0,0, + 114,21,0,0,0,114,30,0,0,0,90,7,95,116,104,114, + 101,97,100,90,8,95,119,101,97,107,114,101,102,90,6,119, + 105,110,114,101,103,114,171,0,0,0,114,5,0,0,0,122, + 4,46,112,121,119,122,6,95,100,46,112,121,100,84,78,41, + 19,114,116,0,0,0,114,6,0,0,0,114,143,0,0,0, + 114,250,0,0,0,114,107,0,0,0,90,18,95,98,117,105, + 108,116,105,110,95,102,114,111,109,95,110,97,109,101,114,111, + 0,0,0,218,3,97,108,108,114,151,0,0,0,114,101,0, + 0,0,114,26,0,0,0,114,11,0,0,0,114,240,0,0, + 0,114,147,0,0,0,114,38,1,0,0,114,86,0,0,0, + 114,165,0,0,0,114,170,0,0,0,114,174,0,0,0,41, + 12,218,17,95,98,111,111,116,115,116,114,97,112,95,109,111, + 100,117,108,101,90,11,115,101,108,102,95,109,111,100,117,108, + 101,90,12,98,117,105,108,116,105,110,95,110,97,109,101,90, + 14,98,117,105,108,116,105,110,95,109,111,100,117,108,101,90, + 10,111,115,95,100,101,116,97,105,108,115,90,10,98,117,105, + 108,116,105,110,95,111,115,114,21,0,0,0,114,25,0,0, + 0,90,9,111,115,95,109,111,100,117,108,101,90,13,116,104, + 114,101,97,100,95,109,111,100,117,108,101,90,14,119,101,97, + 107,114,101,102,95,109,111,100,117,108,101,90,13,119,105,110, + 114,101,103,95,109,111,100,117,108,101,114,2,0,0,0,114, + 2,0,0,0,114,4,0,0,0,218,6,95,115,101,116,117, + 112,213,5,0,0,115,76,0,0,0,0,8,4,1,6,1, + 6,3,10,1,8,1,10,1,12,2,10,1,14,3,22,1, + 12,2,22,1,8,1,10,1,10,1,6,2,2,1,10,1, + 10,1,14,1,12,2,8,1,12,1,12,1,18,3,10,1, + 12,3,10,1,12,3,10,1,10,1,12,3,14,1,14,1, + 10,1,10,1,10,1,114,44,1,0,0,99,1,0,0,0, + 0,0,0,0,2,0,0,0,4,0,0,0,67,0,0,0, + 115,50,0,0,0,116,0,124,0,131,1,1,0,116,1,131, + 0,125,1,116,2,106,3,160,4,116,5,106,6,124,1,142, + 0,103,1,161,1,1,0,116,2,106,7,160,8,116,9,161, + 1,1,0,100,1,83,0,41,2,122,41,73,110,115,116,97, + 108,108,32,116,104,101,32,112,97,116,104,45,98,97,115,101, + 100,32,105,109,112,111,114,116,32,99,111,109,112,111,110,101, + 110,116,115,46,78,41,10,114,44,1,0,0,114,163,0,0, + 0,114,6,0,0,0,114,11,1,0,0,114,147,0,0,0, + 114,19,1,0,0,114,32,1,0,0,218,9,109,101,116,97, + 95,112,97,116,104,114,165,0,0,0,114,5,1,0,0,41, + 2,114,43,1,0,0,90,17,115,117,112,112,111,114,116,101, + 100,95,108,111,97,100,101,114,115,114,2,0,0,0,114,2, + 0,0,0,114,4,0,0,0,218,8,95,105,110,115,116,97, + 108,108,21,6,0,0,115,8,0,0,0,0,2,8,1,6, + 1,20,1,114,46,1,0,0,41,1,114,47,0,0,0,41, + 1,78,41,3,78,78,78,41,2,114,60,0,0,0,114,60, + 0,0,0,41,1,84,41,1,78,41,1,78,41,61,114,109, + 0,0,0,114,10,0,0,0,90,37,95,67,65,83,69,95, + 73,78,83,69,78,83,73,84,73,86,69,95,80,76,65,84, + 70,79,82,77,83,95,66,89,84,69,83,95,75,69,89,114, + 9,0,0,0,114,11,0,0,0,114,17,0,0,0,114,19, + 0,0,0,114,28,0,0,0,114,38,0,0,0,114,39,0, + 0,0,114,43,0,0,0,114,44,0,0,0,114,46,0,0, + 0,114,56,0,0,0,218,4,116,121,112,101,218,8,95,95, + 99,111,100,101,95,95,114,142,0,0,0,114,15,0,0,0, + 114,129,0,0,0,114,14,0,0,0,114,18,0,0,0,114, + 209,0,0,0,114,75,0,0,0,114,74,0,0,0,114,86, + 0,0,0,114,76,0,0,0,90,23,68,69,66,85,71,95, + 66,89,84,69,67,79,68,69,95,83,85,70,70,73,88,69, + 83,90,27,79,80,84,73,77,73,90,69,68,95,66,89,84, + 69,67,79,68,69,95,83,85,70,70,73,88,69,83,114,81, + 0,0,0,114,87,0,0,0,114,93,0,0,0,114,97,0, + 0,0,114,99,0,0,0,114,118,0,0,0,114,125,0,0, + 0,114,133,0,0,0,114,137,0,0,0,114,139,0,0,0, + 114,145,0,0,0,114,150,0,0,0,114,152,0,0,0,114, + 157,0,0,0,218,6,111,98,106,101,99,116,114,164,0,0, + 0,114,169,0,0,0,114,170,0,0,0,114,185,0,0,0, + 114,195,0,0,0,114,212,0,0,0,114,229,0,0,0,114, + 234,0,0,0,114,240,0,0,0,114,235,0,0,0,114,241, + 0,0,0,114,3,1,0,0,114,5,1,0,0,114,19,1, + 0,0,114,37,1,0,0,114,163,0,0,0,114,44,1,0, + 0,114,46,1,0,0,114,2,0,0,0,114,2,0,0,0, + 114,2,0,0,0,114,4,0,0,0,218,8,60,109,111,100, + 117,108,101,62,8,0,0,0,115,118,0,0,0,4,15,4, + 1,4,1,2,1,6,3,8,17,8,5,8,5,8,6,8, + 12,8,10,8,9,8,5,8,7,10,22,10,127,0,5,16, + 1,12,2,4,1,4,2,6,2,6,2,8,2,16,45,8, + 34,8,19,8,12,8,12,8,28,8,17,8,33,8,28,8, + 24,10,13,10,10,10,11,8,14,6,3,4,1,14,67,14, + 64,14,29,16,127,0,17,14,68,18,45,18,26,4,3,18, + 53,14,60,14,42,14,127,0,7,14,127,0,22,10,23,8, + 11,8,64, }; diff --git a/Tools/parser/unparse.py b/Tools/parser/unparse.py index 3eb63108c590..7e1cc4ea5db9 100644 --- a/Tools/parser/unparse.py +++ b/Tools/parser/unparse.py @@ -71,8 +71,6 @@ def dispatch(self, tree): ######################################################## def _Module(self, tree): - if tree.docstring is not None: - self.fill(repr(tree.docstring)) for stmt in tree.body: self.dispatch(stmt) @@ -237,8 +235,6 @@ def _ClassDef(self, t): self.write(")") self.enter() - if t.docstring is not None: - self.fill(repr(t.docstring)) self.dispatch(t.body) self.leave() @@ -261,8 +257,6 @@ def __FunctionDef_helper(self, t, fill_suffix): self.write(" -> ") self.dispatch(t.returns) self.enter() - if t.docstring is not None: - self.fill(repr(t.docstring)) self.dispatch(t.body) self.leave() From solipsis at pitrou.net Tue May 29 05:13:53 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Tue, 29 May 2018 09:13:53 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=4 Message-ID: <20180529091353.1.1F5C38051A21FB61@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_functools leaked [0, 3, 1] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogIe6RFL', '--timeout', '7200'] From webhook-mailer at python.org Tue May 29 05:19:16 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 29 May 2018 09:19:16 -0000 Subject: [Python-checkins] bpo-33654: Support protocol type switching in SSLTransport.set_protocol() (GH-7194) Message-ID: <mailman.54.1527585558.2800.python-checkins@python.org> https://github.com/python/cpython/commit/be5d616e5529a1388a0b451bf6a65ad5bdb70d29 commit: be5d616e5529a1388a0b451bf6a65ad5bdb70d29 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-29T02:19:09-07:00 summary: bpo-33654: Support protocol type switching in SSLTransport.set_protocol() (GH-7194) (cherry picked from commit 2179022d94937d7b0600b0dc192ca6fa5f53d830) Co-authored-by: Yury Selivanov <yury at magic.io> files: A Misc/NEWS.d/next/Library/2018-05-29-01-13-39.bpo-33654.sa81Si.rst M Lib/asyncio/sslproto.py M Lib/test/test_asyncio/test_sslproto.py diff --git a/Lib/asyncio/sslproto.py b/Lib/asyncio/sslproto.py index ab43e93b28bc..a6d382ecd3de 100644 --- a/Lib/asyncio/sslproto.py +++ b/Lib/asyncio/sslproto.py @@ -295,7 +295,7 @@ def get_extra_info(self, name, default=None): return self._ssl_protocol._get_extra_info(name, default) def set_protocol(self, protocol): - self._ssl_protocol._app_protocol = protocol + self._ssl_protocol._set_app_protocol(protocol) def get_protocol(self): return self._ssl_protocol._app_protocol @@ -440,9 +440,7 @@ def __init__(self, loop, app_protocol, sslcontext, waiter, self._waiter = waiter self._loop = loop - self._app_protocol = app_protocol - self._app_protocol_is_buffer = \ - isinstance(app_protocol, protocols.BufferedProtocol) + self._set_app_protocol(app_protocol) self._app_transport = _SSLProtocolTransport(self._loop, self) # _SSLPipe instance (None until the connection is made) self._sslpipe = None @@ -454,6 +452,11 @@ def __init__(self, loop, app_protocol, sslcontext, waiter, self._call_connection_made = call_connection_made self._ssl_handshake_timeout = ssl_handshake_timeout + def _set_app_protocol(self, app_protocol): + self._app_protocol = app_protocol + self._app_protocol_is_buffer = \ + isinstance(app_protocol, protocols.BufferedProtocol) + def _wakeup_waiter(self, exc=None): if self._waiter is None: return diff --git a/Lib/test/test_asyncio/test_sslproto.py b/Lib/test/test_asyncio/test_sslproto.py index 1b2f9d2a3a2a..fa9cbd56ed42 100644 --- a/Lib/test/test_asyncio/test_sslproto.py +++ b/Lib/test/test_asyncio/test_sslproto.py @@ -302,6 +302,7 @@ def test_start_tls_client_buf_proto_1(self): server_context = test_utils.simple_server_sslcontext() client_context = test_utils.simple_client_sslcontext() + client_con_made_calls = 0 def serve(sock): sock.settimeout(self.TIMEOUT) @@ -315,20 +316,21 @@ def serve(sock): data = sock.recv_all(len(HELLO_MSG)) self.assertEqual(len(data), len(HELLO_MSG)) + sock.sendall(b'2') + data = sock.recv_all(len(HELLO_MSG)) + self.assertEqual(len(data), len(HELLO_MSG)) + sock.shutdown(socket.SHUT_RDWR) sock.close() - class ClientProto(asyncio.BufferedProtocol): - def __init__(self, on_data, on_eof): + class ClientProtoFirst(asyncio.BufferedProtocol): + def __init__(self, on_data): self.on_data = on_data - self.on_eof = on_eof - self.con_made_cnt = 0 self.buf = bytearray(1) - def connection_made(proto, tr): - proto.con_made_cnt += 1 - # Ensure connection_made gets called only once. - self.assertEqual(proto.con_made_cnt, 1) + def connection_made(self, tr): + nonlocal client_con_made_calls + client_con_made_calls += 1 def get_buffer(self, sizehint): return self.buf @@ -337,27 +339,50 @@ def buffer_updated(self, nsize): assert nsize == 1 self.on_data.set_result(bytes(self.buf[:nsize])) + class ClientProtoSecond(asyncio.Protocol): + def __init__(self, on_data, on_eof): + self.on_data = on_data + self.on_eof = on_eof + self.con_made_cnt = 0 + + def connection_made(self, tr): + nonlocal client_con_made_calls + client_con_made_calls += 1 + + def data_received(self, data): + self.on_data.set_result(data) + def eof_received(self): self.on_eof.set_result(True) async def client(addr): await asyncio.sleep(0.5, loop=self.loop) - on_data = self.loop.create_future() + on_data1 = self.loop.create_future() + on_data2 = self.loop.create_future() on_eof = self.loop.create_future() tr, proto = await self.loop.create_connection( - lambda: ClientProto(on_data, on_eof), *addr) + lambda: ClientProtoFirst(on_data1), *addr) tr.write(HELLO_MSG) new_tr = await self.loop.start_tls(tr, proto, client_context) - self.assertEqual(await on_data, b'O') + self.assertEqual(await on_data1, b'O') + new_tr.write(HELLO_MSG) + + new_tr.set_protocol(ClientProtoSecond(on_data2, on_eof)) + self.assertEqual(await on_data2, b'2') new_tr.write(HELLO_MSG) await on_eof new_tr.close() + # connection_made() should be called only once -- when + # we establish connection for the first time. Start TLS + # doesn't call connection_made() on application protocols. + self.assertEqual(client_con_made_calls, 1) + with self.tcp_server(serve, timeout=self.TIMEOUT) as srv: self.loop.run_until_complete( asyncio.wait_for(client(srv.addr), diff --git a/Misc/NEWS.d/next/Library/2018-05-29-01-13-39.bpo-33654.sa81Si.rst b/Misc/NEWS.d/next/Library/2018-05-29-01-13-39.bpo-33654.sa81Si.rst new file mode 100644 index 000000000000..39e8e615d8c4 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-29-01-13-39.bpo-33654.sa81Si.rst @@ -0,0 +1 @@ +Support protocol type switching in SSLTransport.set_protocol(). From webhook-mailer at python.org Tue May 29 10:02:10 2018 From: webhook-mailer at python.org (Victor Stinner) Date: Tue, 29 May 2018 14:02:10 -0000 Subject: [Python-checkins] bpo-33353: test_asyncio use set_write_buffer_limits() (GH-7200) Message-ID: <mailman.55.1527602533.2800.python-checkins@python.org> https://github.com/python/cpython/commit/9551f7719213243fd96c4f284079243773c26b3c commit: 9551f7719213243fd96c4f284079243773c26b3c branch: master author: Victor Stinner <vstinner at redhat.com> committer: GitHub <noreply at github.com> date: 2018-05-29T16:02:07+02:00 summary: bpo-33353: test_asyncio use set_write_buffer_limits() (GH-7200) Use transport.set_write_buffer_limits() in sendfile tests of test_asyncio to make sure that the protocol is paused after sending 4 KiB. Previously, test_sendfile_fallback_close_peer_in_the_middle_of_receiving() failed on FreeBSD if the DATA was smaller than the default limit of 64 KiB. files: M Lib/asyncio/streams.py M Lib/test/test_asyncio/test_events.py diff --git a/Lib/asyncio/streams.py b/Lib/asyncio/streams.py index 9a53ee482478..d6531f88a74d 100644 --- a/Lib/asyncio/streams.py +++ b/Lib/asyncio/streams.py @@ -16,7 +16,7 @@ from .tasks import sleep -_DEFAULT_LIMIT = 2 ** 16 +_DEFAULT_LIMIT = 2 ** 16 # 64 KiB class IncompleteReadError(EOFError): diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index e7c4fa6cecec..01ed47b36495 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -2113,7 +2113,10 @@ def test_subprocess_shell_invalid_args(self): class SendfileBase: - DATA = b"12345abcde" * 64 * 1024 # 64 KiB (don't use smaller sizes) + DATA = b"SendfileBaseData" * (1024 * 8) # 128 KiB + + # Reduce socket buffer size to test on relative small data sets. + BUF_SIZE = 4 * 1024 # 4 KiB @classmethod def setUpClass(cls): @@ -2171,12 +2174,6 @@ def tearDownClass(cls): constants.SENDFILE_FALLBACK_READBUFFER_SIZE = cls.__old_bufsize super().tearDownClass() - def set_socket_opts(self, sock): - # On macOS, SO_SNDBUF is reset by connect(). So this method - # should be called after the socket is connected. - sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 1024) - sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 1024) - def make_socket(self, cleanup=True): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setblocking(False) @@ -2184,17 +2181,33 @@ def make_socket(self, cleanup=True): self.addCleanup(sock.close) return sock + def reduce_receive_buffer_size(self, sock): + # Reduce receive socket buffer size to test on relative + # small data sets. + sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, self.BUF_SIZE) + + def reduce_send_buffer_size(self, sock, transport=None): + # Reduce send socket buffer size to test on relative small data sets. + + # On macOS, SO_SNDBUF is reset by connect(). So this method + # should be called after the socket is connected. + sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, self.BUF_SIZE) + + if transport is not None: + transport.set_write_buffer_limits(high=self.BUF_SIZE) + def prepare_socksendfile(self): - sock = self.make_socket() proto = self.MyProto(self.loop) port = support.find_unused_port() srv_sock = self.make_socket(cleanup=False) srv_sock.bind((support.HOST, port)) server = self.run_loop(self.loop.create_server( lambda: proto, sock=srv_sock)) - self.set_socket_opts(srv_sock) + self.reduce_receive_buffer_size(srv_sock) + + sock = self.make_socket() self.run_loop(self.loop.sock_connect(sock, ('127.0.0.1', port))) - self.set_socket_opts(sock) + self.reduce_send_buffer_size(sock) def cleanup(): if proto.transport is not None: @@ -2243,7 +2256,7 @@ def test_sock_sendfile_zero_size(self): self.assertEqual(self.file.tell(), 0) def test_sock_sendfile_mix_with_regular_send(self): - buf = b"X" * 160 * 1024 # 160 KiB + buf = b"mix_regular_send" * (4 * 1024) # 64 KiB sock, proto = self.prepare_socksendfile() self.run_loop(self.loop.sock_sendall(sock, buf)) ret = self.run_loop(self.loop.sock_sendfile(sock, self.file)) @@ -2288,11 +2301,10 @@ def prepare_sendfile(self, *, is_ssl=False, close_after=0): srv_ctx = None cli_ctx = None srv_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - # reduce recv socket buffer size to test on relative small data sets - srv_sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 1024) srv_sock.bind((support.HOST, port)) server = self.run_loop(self.loop.create_server( lambda: srv_proto, sock=srv_sock, ssl=srv_ctx)) + self.reduce_receive_buffer_size(srv_sock) if is_ssl: server_hostname = support.HOST @@ -2300,12 +2312,12 @@ def prepare_sendfile(self, *, is_ssl=False, close_after=0): server_hostname = None cli_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) cli_sock.connect((support.HOST, port)) - # reduce send socket buffer size to test on relative small data sets - cli_sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 1024) + cli_proto = self.MySendfileProto(loop=self.loop) tr, pr = self.run_loop(self.loop.create_connection( lambda: cli_proto, sock=cli_sock, ssl=cli_ctx, server_hostname=server_hostname)) + self.reduce_send_buffer_size(cli_sock, transport=tr) def cleanup(): srv_proto.transport.close() @@ -2410,8 +2422,8 @@ def test_sendfile_for_closing_transp(self): def test_sendfile_pre_and_post_data(self): srv_proto, cli_proto = self.prepare_sendfile() - PREFIX = b'zxcvbnm' * 1024 - SUFFIX = b'0987654321' * 1024 + PREFIX = b'PREFIX__' * 1024 # 8 KiB + SUFFIX = b'--SUFFIX' * 1024 # 8 KiB cli_proto.transport.write(PREFIX) ret = self.run_loop( self.loop.sendfile(cli_proto.transport, self.file)) From webhook-mailer at python.org Tue May 29 10:21:50 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 29 May 2018 14:21:50 -0000 Subject: [Python-checkins] bpo-33353: test_asyncio use set_write_buffer_limits() (GH-7200) Message-ID: <mailman.57.1527603713.2800.python-checkins@python.org> https://github.com/python/cpython/commit/441afbd9c3ae3a9f1d6c985c8aa13e6205ba080b commit: 441afbd9c3ae3a9f1d6c985c8aa13e6205ba080b branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-29T07:21:46-07:00 summary: bpo-33353: test_asyncio use set_write_buffer_limits() (GH-7200) Use transport.set_write_buffer_limits() in sendfile tests of test_asyncio to make sure that the protocol is paused after sending 4 KiB. Previously, test_sendfile_fallback_close_peer_in_the_middle_of_receiving() failed on FreeBSD if the DATA was smaller than the default limit of 64 KiB. (cherry picked from commit 9551f7719213243fd96c4f284079243773c26b3c) Co-authored-by: Victor Stinner <vstinner at redhat.com> files: M Lib/asyncio/streams.py M Lib/test/test_asyncio/test_events.py diff --git a/Lib/asyncio/streams.py b/Lib/asyncio/streams.py index 9a53ee482478..d6531f88a74d 100644 --- a/Lib/asyncio/streams.py +++ b/Lib/asyncio/streams.py @@ -16,7 +16,7 @@ from .tasks import sleep -_DEFAULT_LIMIT = 2 ** 16 +_DEFAULT_LIMIT = 2 ** 16 # 64 KiB class IncompleteReadError(EOFError): diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index e7c4fa6cecec..01ed47b36495 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -2113,7 +2113,10 @@ def test_subprocess_shell_invalid_args(self): class SendfileBase: - DATA = b"12345abcde" * 64 * 1024 # 64 KiB (don't use smaller sizes) + DATA = b"SendfileBaseData" * (1024 * 8) # 128 KiB + + # Reduce socket buffer size to test on relative small data sets. + BUF_SIZE = 4 * 1024 # 4 KiB @classmethod def setUpClass(cls): @@ -2171,12 +2174,6 @@ def tearDownClass(cls): constants.SENDFILE_FALLBACK_READBUFFER_SIZE = cls.__old_bufsize super().tearDownClass() - def set_socket_opts(self, sock): - # On macOS, SO_SNDBUF is reset by connect(). So this method - # should be called after the socket is connected. - sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 1024) - sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 1024) - def make_socket(self, cleanup=True): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setblocking(False) @@ -2184,17 +2181,33 @@ def make_socket(self, cleanup=True): self.addCleanup(sock.close) return sock + def reduce_receive_buffer_size(self, sock): + # Reduce receive socket buffer size to test on relative + # small data sets. + sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, self.BUF_SIZE) + + def reduce_send_buffer_size(self, sock, transport=None): + # Reduce send socket buffer size to test on relative small data sets. + + # On macOS, SO_SNDBUF is reset by connect(). So this method + # should be called after the socket is connected. + sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, self.BUF_SIZE) + + if transport is not None: + transport.set_write_buffer_limits(high=self.BUF_SIZE) + def prepare_socksendfile(self): - sock = self.make_socket() proto = self.MyProto(self.loop) port = support.find_unused_port() srv_sock = self.make_socket(cleanup=False) srv_sock.bind((support.HOST, port)) server = self.run_loop(self.loop.create_server( lambda: proto, sock=srv_sock)) - self.set_socket_opts(srv_sock) + self.reduce_receive_buffer_size(srv_sock) + + sock = self.make_socket() self.run_loop(self.loop.sock_connect(sock, ('127.0.0.1', port))) - self.set_socket_opts(sock) + self.reduce_send_buffer_size(sock) def cleanup(): if proto.transport is not None: @@ -2243,7 +2256,7 @@ def test_sock_sendfile_zero_size(self): self.assertEqual(self.file.tell(), 0) def test_sock_sendfile_mix_with_regular_send(self): - buf = b"X" * 160 * 1024 # 160 KiB + buf = b"mix_regular_send" * (4 * 1024) # 64 KiB sock, proto = self.prepare_socksendfile() self.run_loop(self.loop.sock_sendall(sock, buf)) ret = self.run_loop(self.loop.sock_sendfile(sock, self.file)) @@ -2288,11 +2301,10 @@ def prepare_sendfile(self, *, is_ssl=False, close_after=0): srv_ctx = None cli_ctx = None srv_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - # reduce recv socket buffer size to test on relative small data sets - srv_sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 1024) srv_sock.bind((support.HOST, port)) server = self.run_loop(self.loop.create_server( lambda: srv_proto, sock=srv_sock, ssl=srv_ctx)) + self.reduce_receive_buffer_size(srv_sock) if is_ssl: server_hostname = support.HOST @@ -2300,12 +2312,12 @@ def prepare_sendfile(self, *, is_ssl=False, close_after=0): server_hostname = None cli_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) cli_sock.connect((support.HOST, port)) - # reduce send socket buffer size to test on relative small data sets - cli_sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 1024) + cli_proto = self.MySendfileProto(loop=self.loop) tr, pr = self.run_loop(self.loop.create_connection( lambda: cli_proto, sock=cli_sock, ssl=cli_ctx, server_hostname=server_hostname)) + self.reduce_send_buffer_size(cli_sock, transport=tr) def cleanup(): srv_proto.transport.close() @@ -2410,8 +2422,8 @@ def test_sendfile_for_closing_transp(self): def test_sendfile_pre_and_post_data(self): srv_proto, cli_proto = self.prepare_sendfile() - PREFIX = b'zxcvbnm' * 1024 - SUFFIX = b'0987654321' * 1024 + PREFIX = b'PREFIX__' * 1024 # 8 KiB + SUFFIX = b'--SUFFIX' * 1024 # 8 KiB cli_proto.transport.write(PREFIX) ret = self.run_loop( self.loop.sendfile(cli_proto.transport, self.file)) From webhook-mailer at python.org Tue May 29 11:04:19 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Tue, 29 May 2018 15:04:19 -0000 Subject: [Python-checkins] bpo-33197: Update a error message of invalid inspect.Parameters. (GH-6636) Message-ID: <mailman.58.1527606263.2800.python-checkins@python.org> https://github.com/python/cpython/commit/a9cab433bbf02f3a1de59d14dc8f583181ffe2d5 commit: a9cab433bbf02f3a1de59d14dc8f583181ffe2d5 branch: master author: Dong-hee Na <donghee.na92 at gmail.com> committer: Yury Selivanov <yury at magic.io> date: 2018-05-29T11:04:08-04:00 summary: bpo-33197: Update a error message of invalid inspect.Parameters. (GH-6636) files: A Misc/NEWS.d/next/Library/2018-04-29-23-56-20.bpo-33197.dgRLqr.rst M Lib/inspect.py M Lib/test/test_inspect.py diff --git a/Lib/inspect.py b/Lib/inspect.py index e5d312eb3021..409c05880de0 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -2402,6 +2402,16 @@ def __str__(self): _KEYWORD_ONLY = _ParameterKind.KEYWORD_ONLY _VAR_KEYWORD = _ParameterKind.VAR_KEYWORD +_PARAM_NAME_MAPPING = { + _POSITIONAL_ONLY: 'positional-only', + _POSITIONAL_OR_KEYWORD: 'positional or keyword', + _VAR_POSITIONAL: 'variadic positional', + _KEYWORD_ONLY: 'keyword-only', + _VAR_KEYWORD: 'variadic keyword' +} + +_get_paramkind_descr = _PARAM_NAME_MAPPING.__getitem__ + class Parameter: """Represents a parameter in a function signature. @@ -2436,15 +2446,14 @@ class Parameter: empty = _empty def __init__(self, name, kind, *, default=_empty, annotation=_empty): - - if kind not in (_POSITIONAL_ONLY, _POSITIONAL_OR_KEYWORD, - _VAR_POSITIONAL, _KEYWORD_ONLY, _VAR_KEYWORD): - raise ValueError("invalid value for 'Parameter.kind' attribute") - self._kind = kind - + try: + self._kind = _ParameterKind(kind) + except ValueError: + raise ValueError(f'value {kind!r} is not a valid Parameter.kind') if default is not _empty: - if kind in (_VAR_POSITIONAL, _VAR_KEYWORD): - msg = '{} parameters cannot have default values'.format(kind) + if self._kind in (_VAR_POSITIONAL, _VAR_KEYWORD): + msg = '{} parameters cannot have default values' + msg = msg.format(_get_paramkind_descr(self._kind)) raise ValueError(msg) self._default = default self._annotation = annotation @@ -2453,19 +2462,21 @@ def __init__(self, name, kind, *, default=_empty, annotation=_empty): raise ValueError('name is a required attribute for Parameter') if not isinstance(name, str): - raise TypeError("name must be a str, not a {!r}".format(name)) + msg = 'name must be a str, not a {}'.format(type(name).__name__) + raise TypeError(msg) if name[0] == '.' and name[1:].isdigit(): # These are implicit arguments generated by comprehensions. In # order to provide a friendlier interface to users, we recast # their name as "implicitN" and treat them as positional-only. # See issue 19611. - if kind != _POSITIONAL_OR_KEYWORD: - raise ValueError( - 'implicit arguments must be passed in as {}'.format( - _POSITIONAL_OR_KEYWORD - ) + if self._kind != _POSITIONAL_OR_KEYWORD: + msg = ( + 'implicit arguments must be passed as ' + 'positional or keyword arguments, not {}' ) + msg = msg.format(_get_paramkind_descr(self._kind)) + raise ValueError(msg) self._kind = _POSITIONAL_ONLY name = 'implicit{}'.format(name[1:]) @@ -2736,8 +2747,12 @@ def __init__(self, parameters=None, *, return_annotation=_empty, name = param.name if kind < top_kind: - msg = 'wrong parameter order: {!r} before {!r}' - msg = msg.format(top_kind, kind) + msg = ( + 'wrong parameter order: {} parameter before {} ' + 'parameter' + ) + msg = msg.format(_get_paramkind_descr(top_kind), + _get_paramkind_descr(kind)) raise ValueError(msg) elif kind > top_kind: kind_defaults = False diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index ee227a66b17c..35e86b5748e7 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -1499,6 +1499,20 @@ def f6(a, b, c): with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"): inspect.getcallargs(f6) + # bpo-33197 + with self.assertRaisesRegex(ValueError, + 'variadic keyword parameters cannot' + ' have default values'): + inspect.Parameter("foo", kind=inspect.Parameter.VAR_KEYWORD, + default=42) + with self.assertRaisesRegex(ValueError, + "value 5 is not a valid Parameter.kind"): + inspect.Parameter("bar", kind=5, default=42) + + with self.assertRaisesRegex(TypeError, + 'name must be a str, not a int'): + inspect.Parameter(123, kind=4) + class TestGetcallargsMethods(TestGetcallargsFunctions): def setUp(self): @@ -3099,7 +3113,8 @@ def test_signature_parameter_object(self): self.assertIs(p.annotation, p.empty) self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY) - with self.assertRaisesRegex(ValueError, 'invalid value'): + with self.assertRaisesRegex(ValueError, "value '123' is " + "not a valid Parameter.kind"): inspect.Parameter('foo', default=10, kind='123') with self.assertRaisesRegex(ValueError, 'not a valid parameter name'): @@ -3189,7 +3204,9 @@ def test_signature_parameter_replace(self): self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD) self.assertNotEqual(p2, p) - with self.assertRaisesRegex(ValueError, 'invalid value for'): + with self.assertRaisesRegex(ValueError, + "value <class 'inspect._empty'> " + "is not a valid Parameter.kind"): p2 = p2.replace(kind=p2.empty) p2 = p2.replace(kind=p2.KEYWORD_ONLY) @@ -3202,7 +3219,9 @@ def test_signature_parameter_positional_only(self): @cpython_only def test_signature_parameter_implicit(self): with self.assertRaisesRegex(ValueError, - 'implicit arguments must be passed in as'): + 'implicit arguments must be passed as ' + 'positional or keyword arguments, ' + 'not positional-only'): inspect.Parameter('.0', kind=inspect.Parameter.POSITIONAL_ONLY) param = inspect.Parameter( diff --git a/Misc/NEWS.d/next/Library/2018-04-29-23-56-20.bpo-33197.dgRLqr.rst b/Misc/NEWS.d/next/Library/2018-04-29-23-56-20.bpo-33197.dgRLqr.rst new file mode 100644 index 000000000000..1bbb44b2fc39 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-04-29-23-56-20.bpo-33197.dgRLqr.rst @@ -0,0 +1,2 @@ +Update error message when constructing invalid inspect.Parameters +Patch by Dong-hee Na. From webhook-mailer at python.org Tue May 29 11:43:58 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Tue, 29 May 2018 15:43:58 -0000 Subject: [Python-checkins] bpo-33197: Update a error message of invalid inspect.Parameters. (GH-6636) (GH-7204) Message-ID: <mailman.59.1527608639.2800.python-checkins@python.org> https://github.com/python/cpython/commit/cb055bcc2bbfa5dcc6b0332305918a2118d9ebbc commit: cb055bcc2bbfa5dcc6b0332305918a2118d9ebbc branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Yury Selivanov <yury at magic.io> date: 2018-05-29T11:43:54-04:00 summary: bpo-33197: Update a error message of invalid inspect.Parameters. (GH-6636) (GH-7204) (cherry picked from commit a9cab433bbf02f3a1de59d14dc8f583181ffe2d5) Co-authored-by: Dong-hee Na <donghee.na92 at gmail.com> files: A Misc/NEWS.d/next/Library/2018-04-29-23-56-20.bpo-33197.dgRLqr.rst M Lib/inspect.py M Lib/test/test_inspect.py diff --git a/Lib/inspect.py b/Lib/inspect.py index f2719923e1ae..022cc1922c7a 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -2402,6 +2402,16 @@ def __str__(self): _KEYWORD_ONLY = _ParameterKind.KEYWORD_ONLY _VAR_KEYWORD = _ParameterKind.VAR_KEYWORD +_PARAM_NAME_MAPPING = { + _POSITIONAL_ONLY: 'positional-only', + _POSITIONAL_OR_KEYWORD: 'positional or keyword', + _VAR_POSITIONAL: 'variadic positional', + _KEYWORD_ONLY: 'keyword-only', + _VAR_KEYWORD: 'variadic keyword' +} + +_get_paramkind_descr = _PARAM_NAME_MAPPING.__getitem__ + class Parameter: """Represents a parameter in a function signature. @@ -2436,15 +2446,14 @@ class Parameter: empty = _empty def __init__(self, name, kind, *, default=_empty, annotation=_empty): - - if kind not in (_POSITIONAL_ONLY, _POSITIONAL_OR_KEYWORD, - _VAR_POSITIONAL, _KEYWORD_ONLY, _VAR_KEYWORD): - raise ValueError("invalid value for 'Parameter.kind' attribute") - self._kind = kind - + try: + self._kind = _ParameterKind(kind) + except ValueError: + raise ValueError(f'value {kind!r} is not a valid Parameter.kind') if default is not _empty: - if kind in (_VAR_POSITIONAL, _VAR_KEYWORD): - msg = '{} parameters cannot have default values'.format(kind) + if self._kind in (_VAR_POSITIONAL, _VAR_KEYWORD): + msg = '{} parameters cannot have default values' + msg = msg.format(_get_paramkind_descr(self._kind)) raise ValueError(msg) self._default = default self._annotation = annotation @@ -2453,19 +2462,21 @@ def __init__(self, name, kind, *, default=_empty, annotation=_empty): raise ValueError('name is a required attribute for Parameter') if not isinstance(name, str): - raise TypeError("name must be a str, not a {!r}".format(name)) + msg = 'name must be a str, not a {}'.format(type(name).__name__) + raise TypeError(msg) if name[0] == '.' and name[1:].isdigit(): # These are implicit arguments generated by comprehensions. In # order to provide a friendlier interface to users, we recast # their name as "implicitN" and treat them as positional-only. # See issue 19611. - if kind != _POSITIONAL_OR_KEYWORD: - raise ValueError( - 'implicit arguments must be passed in as {}'.format( - _POSITIONAL_OR_KEYWORD - ) + if self._kind != _POSITIONAL_OR_KEYWORD: + msg = ( + 'implicit arguments must be passed as ' + 'positional or keyword arguments, not {}' ) + msg = msg.format(_get_paramkind_descr(self._kind)) + raise ValueError(msg) self._kind = _POSITIONAL_ONLY name = 'implicit{}'.format(name[1:]) @@ -2736,8 +2747,12 @@ def __init__(self, parameters=None, *, return_annotation=_empty, name = param.name if kind < top_kind: - msg = 'wrong parameter order: {!r} before {!r}' - msg = msg.format(top_kind, kind) + msg = ( + 'wrong parameter order: {} parameter before {} ' + 'parameter' + ) + msg = msg.format(_get_paramkind_descr(top_kind), + _get_paramkind_descr(kind)) raise ValueError(msg) elif kind > top_kind: kind_defaults = False diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index 3481a57ec833..ff6f01454513 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -1444,6 +1444,20 @@ def f6(a, b, c): with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"): inspect.getcallargs(f6) + # bpo-33197 + with self.assertRaisesRegex(ValueError, + 'variadic keyword parameters cannot' + ' have default values'): + inspect.Parameter("foo", kind=inspect.Parameter.VAR_KEYWORD, + default=42) + with self.assertRaisesRegex(ValueError, + "value 5 is not a valid Parameter.kind"): + inspect.Parameter("bar", kind=5, default=42) + + with self.assertRaisesRegex(TypeError, + 'name must be a str, not a int'): + inspect.Parameter(123, kind=4) + class TestGetcallargsMethods(TestGetcallargsFunctions): def setUp(self): @@ -3044,7 +3058,8 @@ def test_signature_parameter_object(self): self.assertIs(p.annotation, p.empty) self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY) - with self.assertRaisesRegex(ValueError, 'invalid value'): + with self.assertRaisesRegex(ValueError, "value '123' is " + "not a valid Parameter.kind"): inspect.Parameter('foo', default=10, kind='123') with self.assertRaisesRegex(ValueError, 'not a valid parameter name'): @@ -3134,7 +3149,9 @@ def test_signature_parameter_replace(self): self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD) self.assertNotEqual(p2, p) - with self.assertRaisesRegex(ValueError, 'invalid value for'): + with self.assertRaisesRegex(ValueError, + "value <class 'inspect._empty'> " + "is not a valid Parameter.kind"): p2 = p2.replace(kind=p2.empty) p2 = p2.replace(kind=p2.KEYWORD_ONLY) @@ -3147,7 +3164,9 @@ def test_signature_parameter_positional_only(self): @cpython_only def test_signature_parameter_implicit(self): with self.assertRaisesRegex(ValueError, - 'implicit arguments must be passed in as'): + 'implicit arguments must be passed as ' + 'positional or keyword arguments, ' + 'not positional-only'): inspect.Parameter('.0', kind=inspect.Parameter.POSITIONAL_ONLY) param = inspect.Parameter( diff --git a/Misc/NEWS.d/next/Library/2018-04-29-23-56-20.bpo-33197.dgRLqr.rst b/Misc/NEWS.d/next/Library/2018-04-29-23-56-20.bpo-33197.dgRLqr.rst new file mode 100644 index 000000000000..1bbb44b2fc39 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-04-29-23-56-20.bpo-33197.dgRLqr.rst @@ -0,0 +1,2 @@ +Update error message when constructing invalid inspect.Parameters +Patch by Dong-hee Na. From webhook-mailer at python.org Tue May 29 11:50:14 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Tue, 29 May 2018 15:50:14 -0000 Subject: [Python-checkins] bpo-33622: Add checks for exceptions leaks in the garbage collector. (GH-7126) Message-ID: <mailman.60.1527609017.2800.python-checkins@python.org> https://github.com/python/cpython/commit/c4653c9bf159c3919a50f4ced32eef713e7e764e commit: c4653c9bf159c3919a50f4ced32eef713e7e764e branch: master author: Serhiy Storchaka <storchaka at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-29T18:50:10+03:00 summary: bpo-33622: Add checks for exceptions leaks in the garbage collector. (GH-7126) * Failure in adding to gc.garbage is no longer fatal. * An exception in tp_clear() no longer lead to crash (though tp_clear() should not leave exceptions). files: M Modules/gcmodule.c diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index 4d701cb72e8c..7d23fc22c81d 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -654,6 +654,7 @@ handle_legacy_finalizers(PyGC_Head *finalizers, PyGC_Head *old) { PyGC_Head *gc = finalizers->gc.gc_next; + assert(!PyErr_Occurred()); if (_PyRuntime.gc.garbage == NULL) { _PyRuntime.gc.garbage = PyList_New(0); if (_PyRuntime.gc.garbage == NULL) @@ -663,8 +664,10 @@ handle_legacy_finalizers(PyGC_Head *finalizers, PyGC_Head *old) PyObject *op = FROM_GC(gc); if ((_PyRuntime.gc.debug & DEBUG_SAVEALL) || has_legacy_finalizer(op)) { - if (PyList_Append(_PyRuntime.gc.garbage, op) < 0) + if (PyList_Append(_PyRuntime.gc.garbage, op) < 0) { + PyErr_Clear(); break; + } } } @@ -701,6 +704,7 @@ finalize_garbage(PyGC_Head *collectable) _PyGCHead_SET_FINALIZED(gc, 1); Py_INCREF(op); finalize(op); + assert(!PyErr_Occurred()); Py_DECREF(op); } } @@ -748,17 +752,26 @@ delete_garbage(PyGC_Head *collectable, PyGC_Head *old) { inquiry clear; + assert(!PyErr_Occurred()); while (!gc_list_is_empty(collectable)) { PyGC_Head *gc = collectable->gc.gc_next; PyObject *op = FROM_GC(gc); if (_PyRuntime.gc.debug & DEBUG_SAVEALL) { - PyList_Append(_PyRuntime.gc.garbage, op); + assert(_PyRuntime.gc.garbage != NULL); + if (PyList_Append(_PyRuntime.gc.garbage, op) < 0) { + PyErr_Clear(); + } } else { if ((clear = Py_TYPE(op)->tp_clear) != NULL) { Py_INCREF(op); - clear(op); + (void) clear(op); + if (PyErr_Occurred()) { + PySys_WriteStderr("Exception ignored in tp_clear of " + "%.50s\n", Py_TYPE(op)->tp_name); + PyErr_WriteUnraisable(NULL); + } Py_DECREF(op); } } @@ -974,6 +987,7 @@ collect(int generation, Py_ssize_t *n_collected, Py_ssize_t *n_uncollectable, if (PyDTrace_GC_DONE_ENABLED()) PyDTrace_GC_DONE(n+m); + assert(!PyErr_Occurred()); return n+m; } @@ -987,11 +1001,12 @@ invoke_gc_callback(const char *phase, int generation, Py_ssize_t i; PyObject *info = NULL; + assert(!PyErr_Occurred()); /* we may get called very early */ if (_PyRuntime.gc.callbacks == NULL) return; /* The local variable cannot be rebound, check it for sanity */ - assert(_PyRuntime.gc.callbacks != NULL && PyList_CheckExact(_PyRuntime.gc.callbacks)); + assert(PyList_CheckExact(_PyRuntime.gc.callbacks)); if (PyList_GET_SIZE(_PyRuntime.gc.callbacks) != 0) { info = Py_BuildValue("{sisnsn}", "generation", generation, @@ -1015,6 +1030,7 @@ invoke_gc_callback(const char *phase, int generation, Py_DECREF(cb); } Py_XDECREF(info); + assert(!PyErr_Occurred()); } /* Perform garbage collection of a generation and invoke @@ -1024,9 +1040,11 @@ static Py_ssize_t collect_with_callback(int generation) { Py_ssize_t result, collected, uncollectable; + assert(!PyErr_Occurred()); invoke_gc_callback("start", generation, 0, 0); result = collect(generation, &collected, &uncollectable, 0); invoke_gc_callback("stop", generation, collected, uncollectable); + assert(!PyErr_Occurred()); return result; } @@ -1592,6 +1610,7 @@ _PyGC_CollectNoFail(void) { Py_ssize_t n; + assert(!PyErr_Occurred()); /* Ideally, this function is only called on interpreter shutdown, and therefore not recursively. Unfortunately, when there are daemon threads, a daemon thread can start a cyclic garbage collection From webhook-mailer at python.org Tue May 29 11:59:30 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Tue, 29 May 2018 15:59:30 -0000 Subject: [Python-checkins] bpo-33197: Update a error message of invalid inspect.Parameters. (GH-6636) (#7205) Message-ID: <mailman.61.1527609573.2800.python-checkins@python.org> https://github.com/python/cpython/commit/5e9e9db9d9b648d2326e2853dc07377e12498e3f commit: 5e9e9db9d9b648d2326e2853dc07377e12498e3f branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Yury Selivanov <yury at magic.io> date: 2018-05-29T11:59:27-04:00 summary: bpo-33197: Update a error message of invalid inspect.Parameters. (GH-6636) (#7205) (cherry picked from commit a9cab433bbf02f3a1de59d14dc8f583181ffe2d5) Co-authored-by: Dong-hee Na <donghee.na92 at gmail.com> files: A Misc/NEWS.d/next/Library/2018-04-29-23-56-20.bpo-33197.dgRLqr.rst M Lib/inspect.py M Lib/test/test_inspect.py diff --git a/Lib/inspect.py b/Lib/inspect.py index dc2aab2826af..362ae9abeb66 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -2399,6 +2399,16 @@ def __str__(self): _KEYWORD_ONLY = _ParameterKind.KEYWORD_ONLY _VAR_KEYWORD = _ParameterKind.VAR_KEYWORD +_PARAM_NAME_MAPPING = { + _POSITIONAL_ONLY: 'positional-only', + _POSITIONAL_OR_KEYWORD: 'positional or keyword', + _VAR_POSITIONAL: 'variadic positional', + _KEYWORD_ONLY: 'keyword-only', + _VAR_KEYWORD: 'variadic keyword' +} + +_get_paramkind_descr = _PARAM_NAME_MAPPING.__getitem__ + class Parameter: """Represents a parameter in a function signature. @@ -2433,15 +2443,14 @@ class Parameter: empty = _empty def __init__(self, name, kind, *, default=_empty, annotation=_empty): - - if kind not in (_POSITIONAL_ONLY, _POSITIONAL_OR_KEYWORD, - _VAR_POSITIONAL, _KEYWORD_ONLY, _VAR_KEYWORD): - raise ValueError("invalid value for 'Parameter.kind' attribute") - self._kind = kind - + try: + self._kind = _ParameterKind(kind) + except ValueError: + raise ValueError(f'value {kind!r} is not a valid Parameter.kind') if default is not _empty: - if kind in (_VAR_POSITIONAL, _VAR_KEYWORD): - msg = '{} parameters cannot have default values'.format(kind) + if self._kind in (_VAR_POSITIONAL, _VAR_KEYWORD): + msg = '{} parameters cannot have default values' + msg = msg.format(_get_paramkind_descr(self._kind)) raise ValueError(msg) self._default = default self._annotation = annotation @@ -2450,19 +2459,21 @@ def __init__(self, name, kind, *, default=_empty, annotation=_empty): raise ValueError('name is a required attribute for Parameter') if not isinstance(name, str): - raise TypeError("name must be a str, not a {!r}".format(name)) + msg = 'name must be a str, not a {}'.format(type(name).__name__) + raise TypeError(msg) if name[0] == '.' and name[1:].isdigit(): # These are implicit arguments generated by comprehensions. In # order to provide a friendlier interface to users, we recast # their name as "implicitN" and treat them as positional-only. # See issue 19611. - if kind != _POSITIONAL_OR_KEYWORD: - raise ValueError( - 'implicit arguments must be passed in as {}'.format( - _POSITIONAL_OR_KEYWORD - ) + if self._kind != _POSITIONAL_OR_KEYWORD: + msg = ( + 'implicit arguments must be passed as ' + 'positional or keyword arguments, not {}' ) + msg = msg.format(_get_paramkind_descr(self._kind)) + raise ValueError(msg) self._kind = _POSITIONAL_ONLY name = 'implicit{}'.format(name[1:]) @@ -2730,8 +2741,12 @@ def __init__(self, parameters=None, *, return_annotation=_empty, name = param.name if kind < top_kind: - msg = 'wrong parameter order: {!r} before {!r}' - msg = msg.format(top_kind, kind) + msg = ( + 'wrong parameter order: {} parameter before {} ' + 'parameter' + ) + msg = msg.format(_get_paramkind_descr(top_kind), + _get_paramkind_descr(kind)) raise ValueError(msg) elif kind > top_kind: kind_defaults = False diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index 126b26e49227..d64bd453d540 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -1390,6 +1390,20 @@ def f6(a, b, c): with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"): inspect.getcallargs(f6) + # bpo-33197 + with self.assertRaisesRegex(ValueError, + 'variadic keyword parameters cannot' + ' have default values'): + inspect.Parameter("foo", kind=inspect.Parameter.VAR_KEYWORD, + default=42) + with self.assertRaisesRegex(ValueError, + "value 5 is not a valid Parameter.kind"): + inspect.Parameter("bar", kind=5, default=42) + + with self.assertRaisesRegex(TypeError, + 'name must be a str, not a int'): + inspect.Parameter(123, kind=4) + class TestGetcallargsMethods(TestGetcallargsFunctions): def setUp(self): @@ -2979,7 +2993,8 @@ def test_signature_parameter_object(self): self.assertIs(p.annotation, p.empty) self.assertEqual(p.kind, inspect.Parameter.POSITIONAL_ONLY) - with self.assertRaisesRegex(ValueError, 'invalid value'): + with self.assertRaisesRegex(ValueError, "value '123' is " + "not a valid Parameter.kind"): inspect.Parameter('foo', default=10, kind='123') with self.assertRaisesRegex(ValueError, 'not a valid parameter name'): @@ -3069,7 +3084,9 @@ def test_signature_parameter_replace(self): self.assertEqual(p2.kind, p2.POSITIONAL_OR_KEYWORD) self.assertNotEqual(p2, p) - with self.assertRaisesRegex(ValueError, 'invalid value for'): + with self.assertRaisesRegex(ValueError, + "value <class 'inspect._empty'> " + "is not a valid Parameter.kind"): p2 = p2.replace(kind=p2.empty) p2 = p2.replace(kind=p2.KEYWORD_ONLY) @@ -3082,7 +3099,9 @@ def test_signature_parameter_positional_only(self): @cpython_only def test_signature_parameter_implicit(self): with self.assertRaisesRegex(ValueError, - 'implicit arguments must be passed in as'): + 'implicit arguments must be passed as ' + 'positional or keyword arguments, ' + 'not positional-only'): inspect.Parameter('.0', kind=inspect.Parameter.POSITIONAL_ONLY) param = inspect.Parameter( diff --git a/Misc/NEWS.d/next/Library/2018-04-29-23-56-20.bpo-33197.dgRLqr.rst b/Misc/NEWS.d/next/Library/2018-04-29-23-56-20.bpo-33197.dgRLqr.rst new file mode 100644 index 000000000000..1bbb44b2fc39 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-04-29-23-56-20.bpo-33197.dgRLqr.rst @@ -0,0 +1,2 @@ +Update error message when constructing invalid inspect.Parameters +Patch by Dong-hee Na. From webhook-mailer at python.org Tue May 29 13:40:58 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Tue, 29 May 2018 17:40:58 -0000 Subject: [Python-checkins] Attempt to fix test_stdin_broken_pipe on Travis (#7210) Message-ID: <mailman.62.1527615658.2800.python-checkins@python.org> https://github.com/python/cpython/commit/4fadf0c639476fa50a40ec6f119f98c01e56ad95 commit: 4fadf0c639476fa50a40ec6f119f98c01e56ad95 branch: master author: Yury Selivanov <yury at magic.io> committer: GitHub <noreply at github.com> date: 2018-05-29T13:40:47-04:00 summary: Attempt to fix test_stdin_broken_pipe on Travis (#7210) files: M Lib/test/test_asyncio/test_subprocess.py diff --git a/Lib/test/test_asyncio/test_subprocess.py b/Lib/test/test_asyncio/test_subprocess.py index 428510f77161..235813aa977c 100644 --- a/Lib/test/test_asyncio/test_subprocess.py +++ b/Lib/test/test_asyncio/test_subprocess.py @@ -228,6 +228,7 @@ def test_stdin_broken_pipe(self): proc, large_data = self.prepare_broken_pipe_test() async def write_stdin(proc, data): + await asyncio.sleep(0.5, loop=self.loop) proc.stdin.write(data) await proc.stdin.drain() From webhook-mailer at python.org Tue May 29 14:32:10 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Tue, 29 May 2018 18:32:10 -0000 Subject: [Python-checkins] Attempt to fix test_stdin_broken_pipe on Travis (GH-7210) (#7211) Message-ID: <mailman.63.1527618731.2800.python-checkins@python.org> https://github.com/python/cpython/commit/b3e12c0817a8308d021eab8e22486a036124b41e commit: b3e12c0817a8308d021eab8e22486a036124b41e branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Yury Selivanov <yury at magic.io> date: 2018-05-29T14:32:07-04:00 summary: Attempt to fix test_stdin_broken_pipe on Travis (GH-7210) (#7211) (cherry picked from commit 4fadf0c639476fa50a40ec6f119f98c01e56ad95) Co-authored-by: Yury Selivanov <yury at magic.io> files: M Lib/test/test_asyncio/test_subprocess.py diff --git a/Lib/test/test_asyncio/test_subprocess.py b/Lib/test/test_asyncio/test_subprocess.py index 428510f77161..235813aa977c 100644 --- a/Lib/test/test_asyncio/test_subprocess.py +++ b/Lib/test/test_asyncio/test_subprocess.py @@ -228,6 +228,7 @@ def test_stdin_broken_pipe(self): proc, large_data = self.prepare_broken_pipe_test() async def write_stdin(proc, data): + await asyncio.sleep(0.5, loop=self.loop) proc.stdin.write(data) await proc.stdin.drain() From webhook-mailer at python.org Tue May 29 14:37:12 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Tue, 29 May 2018 18:37:12 -0000 Subject: [Python-checkins] bpo-30935: update get_event_loop docs (GH-2731) Message-ID: <mailman.64.1527619035.2800.python-checkins@python.org> https://github.com/python/cpython/commit/e55de2d77f10d524be0b426e587fbc820f76de71 commit: e55de2d77f10d524be0b426e587fbc820f76de71 branch: master author: Mandeep Singh <daxlab at users.noreply.github.com> committer: Yury Selivanov <yury at magic.io> date: 2018-05-29T14:37:08-04:00 summary: bpo-30935: update get_event_loop docs (GH-2731) files: M Doc/library/asyncio-eventloops.rst M Doc/whatsnew/3.6.rst diff --git a/Doc/library/asyncio-eventloops.rst b/Doc/library/asyncio-eventloops.rst index 3051fde5b93b..7f6e9535a8a5 100644 --- a/Doc/library/asyncio-eventloops.rst +++ b/Doc/library/asyncio-eventloops.rst @@ -176,12 +176,15 @@ An event loop policy must implement the following interface: Get the event loop for the current context. Returns an event loop object implementing the :class:`AbstractEventLoop` - interface. + interface. In case called from coroutine, it returns the currently + running event loop. Raises an exception in case no event loop has been set for the current context and the current policy does not specify to create one. It must never return ``None``. + .. versionchanged:: 3.6 + .. method:: set_event_loop(loop) Set the event loop for the current context to *loop*. diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst index c4b639528969..cb8c53ac3b18 100644 --- a/Doc/whatsnew/3.6.rst +++ b/Doc/whatsnew/3.6.rst @@ -819,7 +819,7 @@ Notable changes in the :mod:`asyncio` module since Python 3.5.0 (all backported to 3.5.x due to the provisional status): * The :func:`~asyncio.get_event_loop` function has been changed to - always return the currently running loop when called from couroutines + always return the currently running loop when called from coroutines and callbacks. (Contributed by Yury Selivanov in :issue:`28613`.) From webhook-mailer at python.org Tue May 29 14:57:48 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Tue, 29 May 2018 18:57:48 -0000 Subject: [Python-checkins] Fix ci for 3.6 / asyncio / test_stdin_broken_pipe (#7212) Message-ID: <mailman.65.1527620270.2800.python-checkins@python.org> https://github.com/python/cpython/commit/6aacc160a880de3b82c51193a4594b87fb7ace5f commit: 6aacc160a880de3b82c51193a4594b87fb7ace5f branch: 3.6 author: Yury Selivanov <yury at magic.io> committer: GitHub <noreply at github.com> date: 2018-05-29T14:57:38-04:00 summary: Fix ci for 3.6 / asyncio / test_stdin_broken_pipe (#7212) files: M Lib/test/test_asyncio/test_subprocess.py diff --git a/Lib/test/test_asyncio/test_subprocess.py b/Lib/test/test_asyncio/test_subprocess.py index e8822c366982..0b2b17a4c3f9 100644 --- a/Lib/test/test_asyncio/test_subprocess.py +++ b/Lib/test/test_asyncio/test_subprocess.py @@ -210,6 +210,7 @@ def test_stdin_broken_pipe(self): @asyncio.coroutine def write_stdin(proc, data): + yield from asyncio.sleep(0.5, loop=self.loop) proc.stdin.write(data) yield from proc.stdin.drain() From webhook-mailer at python.org Tue May 29 15:29:01 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 29 May 2018 19:29:01 -0000 Subject: [Python-checkins] bpo-30935: update get_event_loop docs (GH-2731) Message-ID: <mailman.66.1527622143.2800.python-checkins@python.org> https://github.com/python/cpython/commit/ca64f3ee5acf61e096eb1bb9fba3baeff0610de4 commit: ca64f3ee5acf61e096eb1bb9fba3baeff0610de4 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-29T12:28:57-07:00 summary: bpo-30935: update get_event_loop docs (GH-2731) (cherry picked from commit e55de2d77f10d524be0b426e587fbc820f76de71) Co-authored-by: Mandeep Singh <daxlab at users.noreply.github.com> files: M Doc/library/asyncio-eventloops.rst M Doc/whatsnew/3.6.rst diff --git a/Doc/library/asyncio-eventloops.rst b/Doc/library/asyncio-eventloops.rst index 3051fde5b93b..7f6e9535a8a5 100644 --- a/Doc/library/asyncio-eventloops.rst +++ b/Doc/library/asyncio-eventloops.rst @@ -176,12 +176,15 @@ An event loop policy must implement the following interface: Get the event loop for the current context. Returns an event loop object implementing the :class:`AbstractEventLoop` - interface. + interface. In case called from coroutine, it returns the currently + running event loop. Raises an exception in case no event loop has been set for the current context and the current policy does not specify to create one. It must never return ``None``. + .. versionchanged:: 3.6 + .. method:: set_event_loop(loop) Set the event loop for the current context to *loop*. diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst index c4b639528969..cb8c53ac3b18 100644 --- a/Doc/whatsnew/3.6.rst +++ b/Doc/whatsnew/3.6.rst @@ -819,7 +819,7 @@ Notable changes in the :mod:`asyncio` module since Python 3.5.0 (all backported to 3.5.x due to the provisional status): * The :func:`~asyncio.get_event_loop` function has been changed to - always return the currently running loop when called from couroutines + always return the currently running loop when called from coroutines and callbacks. (Contributed by Yury Selivanov in :issue:`28613`.) From webhook-mailer at python.org Tue May 29 15:33:32 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 29 May 2018 19:33:32 -0000 Subject: [Python-checkins] bpo-30935: update get_event_loop docs (GH-2731) Message-ID: <mailman.67.1527622415.2800.python-checkins@python.org> https://github.com/python/cpython/commit/51bf38f796c74c7dac5a3d09ad0004494470091c commit: 51bf38f796c74c7dac5a3d09ad0004494470091c branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-29T12:33:29-07:00 summary: bpo-30935: update get_event_loop docs (GH-2731) (cherry picked from commit e55de2d77f10d524be0b426e587fbc820f76de71) Co-authored-by: Mandeep Singh <daxlab at users.noreply.github.com> files: M Doc/library/asyncio-eventloops.rst M Doc/whatsnew/3.6.rst diff --git a/Doc/library/asyncio-eventloops.rst b/Doc/library/asyncio-eventloops.rst index 7970e9039dfd..3aa9ffeff268 100644 --- a/Doc/library/asyncio-eventloops.rst +++ b/Doc/library/asyncio-eventloops.rst @@ -169,12 +169,15 @@ An event loop policy must implement the following interface: Get the event loop for the current context. Returns an event loop object implementing the :class:`AbstractEventLoop` - interface. + interface. In case called from coroutine, it returns the currently + running event loop. Raises an exception in case no event loop has been set for the current context and the current policy does not specify to create one. It must never return ``None``. + .. versionchanged:: 3.6 + .. method:: set_event_loop(loop) Set the event loop for the current context to *loop*. diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst index 88146dc7bcb8..c5ccd85603c0 100644 --- a/Doc/whatsnew/3.6.rst +++ b/Doc/whatsnew/3.6.rst @@ -818,7 +818,7 @@ Notable changes in the :mod:`asyncio` module since Python 3.5.0 (all backported to 3.5.x due to the provisional status): * The :func:`~asyncio.get_event_loop` function has been changed to - always return the currently running loop when called from couroutines + always return the currently running loop when called from coroutines and callbacks. (Contributed by Yury Selivanov in :issue:`28613`.) From webhook-mailer at python.org Tue May 29 15:38:10 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Tue, 29 May 2018 19:38:10 -0000 Subject: [Python-checkins] bpo-22087: Fix Policy.get_event_loop() to detect fork (GH-7208) Message-ID: <mailman.68.1527622692.2800.python-checkins@python.org> https://github.com/python/cpython/commit/5d97b7bcc19496617bf8c448d2f149cc28c73bc7 commit: 5d97b7bcc19496617bf8c448d2f149cc28c73bc7 branch: master author: Yury Selivanov <yury at magic.io> committer: GitHub <noreply at github.com> date: 2018-05-29T15:38:07-04:00 summary: bpo-22087: Fix Policy.get_event_loop() to detect fork (GH-7208) Original patch by Dan O'Reilly. files: A Misc/NEWS.d/next/Library/2018-05-29-12-06-54.bpo-22087.uv7_Y6.rst M Lib/asyncio/events.py M Lib/test/test_asyncio/test_unix_events.py diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py index 40946bbf6529..68dc25e1e8be 100644 --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -625,16 +625,23 @@ class BaseDefaultEventLoopPolicy(AbstractEventLoopPolicy): class _Local(threading.local): _loop = None + _pid = None _set_called = False def __init__(self): self._local = self._Local() + self._local._pid = os.getpid() def get_event_loop(self): """Get the event loop. This may be None or an instance of EventLoop. """ + if self._local._pid != os.getpid(): + # If we detect we're in a child process forked by multiprocessing, + # we reset self._local so that we'll get a new event loop. + self._local = self._Local() + if (self._local._loop is None and not self._local._set_called and isinstance(threading.current_thread(), threading._MainThread)): diff --git a/Lib/test/test_asyncio/test_unix_events.py b/Lib/test/test_asyncio/test_unix_events.py index a01efedf66d9..1bc2d8658d8a 100644 --- a/Lib/test/test_asyncio/test_unix_events.py +++ b/Lib/test/test_asyncio/test_unix_events.py @@ -13,6 +13,7 @@ import tempfile import threading import unittest +import multiprocessing from unittest import mock from test import support @@ -1804,6 +1805,37 @@ def create_watcher(self): return asyncio.FastChildWatcher() +class ForkedProcessTests(unittest.TestCase): + def setUp(self): + self.parent_loop = asyncio.SelectorEventLoop() + asyncio.set_event_loop(self.parent_loop) + self.ctx = multiprocessing.get_context("fork") + + def tearDown(self): + self.parent_loop.close() + + def _check_loops_not_equal(self, old_loop): + loop = asyncio.get_event_loop() + if loop is old_loop: + raise RuntimeError("Child process inherited parent's event loop") + + try: + val = loop.run_until_complete(asyncio.sleep(0.05, result=42)) + if val != 42: + raise RuntimeError("new event loop does not work") + finally: + loop.close() + + sys.exit(loop is old_loop) + + def test_new_loop_in_child(self): + p = self.ctx.Process(target=self._check_loops_not_equal, + args=(self.parent_loop,)) + p.start() + p.join() + self.assertEqual(p.exitcode, 0) + + class PolicyTests(unittest.TestCase): def create_policy(self): diff --git a/Misc/NEWS.d/next/Library/2018-05-29-12-06-54.bpo-22087.uv7_Y6.rst b/Misc/NEWS.d/next/Library/2018-05-29-12-06-54.bpo-22087.uv7_Y6.rst new file mode 100644 index 000000000000..92127cd57a91 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-29-12-06-54.bpo-22087.uv7_Y6.rst @@ -0,0 +1,3 @@ +Fix Policy.get_event_loop() to detect fork and return a new loop. + +Original patch by Dan O'Reilly. From webhook-mailer at python.org Tue May 29 16:10:33 2018 From: webhook-mailer at python.org (Julien Palard) Date: Tue, 29 May 2018 20:10:33 -0000 Subject: [Python-checkins] bpo-31639: Change ThreadedHTTPServer to ThreadingHTTPServer class name (GH-7195) Message-ID: <mailman.69.1527624635.2800.python-checkins@python.org> https://github.com/python/cpython/commit/1cee216cf383eade641aed22f4ec7d4cb565ecff commit: 1cee216cf383eade641aed22f4ec7d4cb565ecff branch: master author: G?ry Ogam <gery.ogam at gmail.com> committer: Julien Palard <julien at palard.fr> date: 2018-05-29T22:10:30+02:00 summary: bpo-31639: Change ThreadedHTTPServer to ThreadingHTTPServer class name (GH-7195) files: M Doc/library/http.server.rst M Lib/http/server.py M Misc/NEWS.d/next/Library/2017-12-27-21-55-19.bpo-31639.l3avDJ.rst diff --git a/Doc/library/http.server.rst b/Doc/library/http.server.rst index 16cfa1798aef..0bd7f778cec0 100644 --- a/Doc/library/http.server.rst +++ b/Doc/library/http.server.rst @@ -33,7 +33,7 @@ handler. Code to create and run the server looks like this:: :attr:`server_port`. The server is accessible by the handler, typically through the handler's :attr:`server` instance variable. -.. class:: ThreadedHTTPServer(server_address, RequestHandlerClass) +.. class:: ThreadingHTTPServer(server_address, RequestHandlerClass) This class is identical to HTTPServer but uses threads to handle requests by using the :class:`~socketserver.ThreadingMixIn`. This @@ -43,7 +43,7 @@ handler. Code to create and run the server looks like this:: .. versionadded:: 3.7 -The :class:`HTTPServer` and :class:`ThreadedHTTPServer` must be given +The :class:`HTTPServer` and :class:`ThreadingHTTPServer` must be given a *RequestHandlerClass* on instantiation, of which this module provides three different variants: diff --git a/Lib/http/server.py b/Lib/http/server.py index a2726ab89750..ea0e295d2834 100644 --- a/Lib/http/server.py +++ b/Lib/http/server.py @@ -83,7 +83,7 @@ __version__ = "0.6" __all__ = [ - "HTTPServer", "ThreadedHTTPServer", "BaseHTTPRequestHandler", + "HTTPServer", "ThreadingHTTPServer", "BaseHTTPRequestHandler", "SimpleHTTPRequestHandler", "CGIHTTPRequestHandler", ] @@ -140,7 +140,7 @@ def server_bind(self): self.server_port = port -class ThreadedHTTPServer(socketserver.ThreadingMixIn, HTTPServer): +class ThreadingHTTPServer(socketserver.ThreadingMixIn, HTTPServer): daemon_threads = True @@ -1217,7 +1217,7 @@ def run_cgi(self): def test(HandlerClass=BaseHTTPRequestHandler, - ServerClass=ThreadedHTTPServer, + ServerClass=ThreadingHTTPServer, protocol="HTTP/1.0", port=8000, bind=""): """Test the HTTP request handler class. diff --git a/Misc/NEWS.d/next/Library/2017-12-27-21-55-19.bpo-31639.l3avDJ.rst b/Misc/NEWS.d/next/Library/2017-12-27-21-55-19.bpo-31639.l3avDJ.rst index 581ac8266b16..741b276a3022 100644 --- a/Misc/NEWS.d/next/Library/2017-12-27-21-55-19.bpo-31639.l3avDJ.rst +++ b/Misc/NEWS.d/next/Library/2017-12-27-21-55-19.bpo-31639.l3avDJ.rst @@ -1,2 +1,2 @@ -http.server now exposes a ThreadedHTTPServer class and uses it when the +http.server now exposes a ThreadingHTTPServer class and uses it when the module is run with ``-m`` to cope with web browsers pre-opening sockets. From webhook-mailer at python.org Tue May 29 17:09:25 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 29 May 2018 21:09:25 -0000 Subject: [Python-checkins] bpo-22087: Fix Policy.get_event_loop() to detect fork (GH-7208) Message-ID: <mailman.70.1527628168.2800.python-checkins@python.org> https://github.com/python/cpython/commit/2a7eb0b531656f4a77d85078e6e009e4b3639ef9 commit: 2a7eb0b531656f4a77d85078e6e009e4b3639ef9 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-29T14:09:17-07:00 summary: bpo-22087: Fix Policy.get_event_loop() to detect fork (GH-7208) Original patch by Dan O'Reilly. (cherry picked from commit 5d97b7bcc19496617bf8c448d2f149cc28c73bc7) Co-authored-by: Yury Selivanov <yury at magic.io> files: A Misc/NEWS.d/next/Library/2018-05-29-12-06-54.bpo-22087.uv7_Y6.rst M Lib/asyncio/events.py M Lib/test/test_asyncio/test_unix_events.py diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py index 40946bbf6529..68dc25e1e8be 100644 --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -625,16 +625,23 @@ class BaseDefaultEventLoopPolicy(AbstractEventLoopPolicy): class _Local(threading.local): _loop = None + _pid = None _set_called = False def __init__(self): self._local = self._Local() + self._local._pid = os.getpid() def get_event_loop(self): """Get the event loop. This may be None or an instance of EventLoop. """ + if self._local._pid != os.getpid(): + # If we detect we're in a child process forked by multiprocessing, + # we reset self._local so that we'll get a new event loop. + self._local = self._Local() + if (self._local._loop is None and not self._local._set_called and isinstance(threading.current_thread(), threading._MainThread)): diff --git a/Lib/test/test_asyncio/test_unix_events.py b/Lib/test/test_asyncio/test_unix_events.py index 104f99593797..577566851223 100644 --- a/Lib/test/test_asyncio/test_unix_events.py +++ b/Lib/test/test_asyncio/test_unix_events.py @@ -13,6 +13,7 @@ import tempfile import threading import unittest +import multiprocessing from unittest import mock from test import support @@ -1792,6 +1793,37 @@ def create_watcher(self): return asyncio.FastChildWatcher() +class ForkedProcessTests(unittest.TestCase): + def setUp(self): + self.parent_loop = asyncio.SelectorEventLoop() + asyncio.set_event_loop(self.parent_loop) + self.ctx = multiprocessing.get_context("fork") + + def tearDown(self): + self.parent_loop.close() + + def _check_loops_not_equal(self, old_loop): + loop = asyncio.get_event_loop() + if loop is old_loop: + raise RuntimeError("Child process inherited parent's event loop") + + try: + val = loop.run_until_complete(asyncio.sleep(0.05, result=42)) + if val != 42: + raise RuntimeError("new event loop does not work") + finally: + loop.close() + + sys.exit(loop is old_loop) + + def test_new_loop_in_child(self): + p = self.ctx.Process(target=self._check_loops_not_equal, + args=(self.parent_loop,)) + p.start() + p.join() + self.assertEqual(p.exitcode, 0) + + class PolicyTests(unittest.TestCase): def create_policy(self): diff --git a/Misc/NEWS.d/next/Library/2018-05-29-12-06-54.bpo-22087.uv7_Y6.rst b/Misc/NEWS.d/next/Library/2018-05-29-12-06-54.bpo-22087.uv7_Y6.rst new file mode 100644 index 000000000000..92127cd57a91 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-29-12-06-54.bpo-22087.uv7_Y6.rst @@ -0,0 +1,3 @@ +Fix Policy.get_event_loop() to detect fork and return a new loop. + +Original patch by Dan O'Reilly. From webhook-mailer at python.org Tue May 29 17:20:11 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Tue, 29 May 2018 21:20:11 -0000 Subject: [Python-checkins] bpo-32684: Fix gather to propagate cancel of itself with return_exceptions (GH-7209) Message-ID: <mailman.71.1527628814.2800.python-checkins@python.org> https://github.com/python/cpython/commit/863b6749093a86810c4077112a857363410cc221 commit: 863b6749093a86810c4077112a857363410cc221 branch: master author: Yury Selivanov <yury at magic.io> committer: GitHub <noreply at github.com> date: 2018-05-29T17:20:02-04:00 summary: bpo-32684: Fix gather to propagate cancel of itself with return_exceptions (GH-7209) files: A Misc/NEWS.d/next/Library/2018-05-29-12-51-18.bpo-32684.ZEIism.rst M Doc/library/asyncio-task.rst M Lib/asyncio/tasks.py M Lib/test/test_asyncio/test_tasks.py diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index 233cc9454967..dc450c375aad 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -640,6 +640,10 @@ Task functions outer Future is *not* cancelled in this case. (This is to prevent the cancellation of one child to cause other children to be cancelled.) + .. versionchanged:: 3.7.0 + If the *gather* itself is cancelled, the cancellation is propagated + regardless of *return_exceptions*. + .. function:: iscoroutine(obj) Return ``True`` if *obj* is a :ref:`coroutine object <coroutine>`, diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index 67fb57c6a781..6cef33d5212e 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -591,6 +591,7 @@ class _GatheringFuture(futures.Future): def __init__(self, children, *, loop=None): super().__init__(loop=loop) self._children = children + self._cancel_requested = False def cancel(self): if self.done(): @@ -599,6 +600,11 @@ def cancel(self): for child in self._children: if child.cancel(): ret = True + if ret: + # If any child tasks were actually cancelled, we should + # propagate the cancellation request regardless of + # *return_exceptions* argument. See issue 32684. + self._cancel_requested = True return ret @@ -673,7 +679,13 @@ def _done_callback(fut): res = fut.result() results.append(res) - outer.set_result(results) + if outer._cancel_requested: + # If gather is being cancelled we must propagate the + # cancellation regardless of *return_exceptions* argument. + # See issue 32684. + outer.set_exception(futures.CancelledError()) + else: + outer.set_result(results) arg_to_fut = {} children = [] diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index 33300c91a367..1280584d318c 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -2037,7 +2037,7 @@ def test_cancel_blocking_wait_for(self): def test_cancel_wait_for(self): self._test_cancel_wait_for(60.0) - def test_cancel_gather(self): + def test_cancel_gather_1(self): """Ensure that a gathering future refuses to be cancelled once all children are done""" loop = asyncio.new_event_loop() @@ -2067,6 +2067,33 @@ def cancelling_callback(_): self.assertFalse(gather_task.cancelled()) self.assertEqual(gather_task.result(), [42]) + def test_cancel_gather_2(self): + loop = asyncio.new_event_loop() + self.addCleanup(loop.close) + + async def test(): + time = 0 + while True: + time += 0.05 + await asyncio.gather(asyncio.sleep(0.05), + return_exceptions=True, + loop=loop) + if time > 1: + return + + async def main(): + qwe = asyncio.Task(test()) + await asyncio.sleep(0.2) + qwe.cancel() + try: + await qwe + except asyncio.CancelledError: + pass + else: + self.fail('gather did not propagate the cancellation request') + + loop.run_until_complete(main()) + def test_exception_traceback(self): # See http://bugs.python.org/issue28843 diff --git a/Misc/NEWS.d/next/Library/2018-05-29-12-51-18.bpo-32684.ZEIism.rst b/Misc/NEWS.d/next/Library/2018-05-29-12-51-18.bpo-32684.ZEIism.rst new file mode 100644 index 000000000000..b360bbcf7998 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-29-12-51-18.bpo-32684.ZEIism.rst @@ -0,0 +1 @@ +Fix gather to propagate cancellation of itself even with return_exceptions. From webhook-mailer at python.org Tue May 29 17:31:05 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Tue, 29 May 2018 21:31:05 -0000 Subject: [Python-checkins] bpo-32751: Wait for task cancellation in asyncio.wait_for() (GH-7216) Message-ID: <mailman.72.1527629471.2800.python-checkins@python.org> https://github.com/python/cpython/commit/e2b340ab4196e1beb902327f503574b5d7369185 commit: e2b340ab4196e1beb902327f503574b5d7369185 branch: master author: Elvis Pranskevichus <elvis at magic.io> committer: Yury Selivanov <yury at magic.io> date: 2018-05-29T17:31:01-04:00 summary: bpo-32751: Wait for task cancellation in asyncio.wait_for() (GH-7216) Currently, asyncio.wait_for(fut), upon reaching the timeout deadline, cancels the future and returns immediately. This is problematic for when *fut* is a Task, because it will be left running for an arbitrary amount of time. This behavior is iself surprising and may lead to related bugs such as the one described in bpo-33638: condition = asyncio.Condition() async with condition: await asyncio.wait_for(condition.wait(), timeout=0.5) Currently, instead of raising a TimeoutError, the above code will fail with `RuntimeError: cannot wait on un-acquired lock`, because `__aexit__` is reached _before_ `condition.wait()` finishes its cancellation and re-acquires the condition lock. To resolve this, make `wait_for` await for the task cancellation. The tradeoff here is that the `timeout` promise may be broken if the task decides to handle its cancellation in a slow way. This represents a behavior change and should probably not be back-patched to 3.6 and earlier. files: A Misc/NEWS.d/next/Library/2018-05-29-15-32-18.bpo-32751.oBTqr7.rst M Doc/library/asyncio-task.rst M Lib/asyncio/tasks.py M Lib/test/test_asyncio/test_locks.py M Lib/test/test_asyncio/test_tasks.py diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index dc450c375aad..3121b4718332 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -790,7 +790,9 @@ Task functions Returns result of the Future or coroutine. When a timeout occurs, it cancels the task and raises :exc:`asyncio.TimeoutError`. To avoid the task - cancellation, wrap it in :func:`shield`. + cancellation, wrap it in :func:`shield`. The function will wait until + the future is actually cancelled, so the total wait time may exceed + the *timeout*. If the wait is cancelled, the future *fut* is also cancelled. @@ -800,3 +802,8 @@ Task functions .. versionchanged:: 3.4.3 If the wait is cancelled, the future *fut* is now also cancelled. + + .. versionchanged:: 3.7 + When *fut* is cancelled due to a timeout, ``wait_for`` now waits + for *fut* to be cancelled. Previously, + it raised :exc:`~asyncio.TimeoutError` immediately. diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index 6cef33d5212e..72792a25cf55 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -412,14 +412,17 @@ def _release_waiter(waiter, *args): return fut.result() else: fut.remove_done_callback(cb) - fut.cancel() + # We must ensure that the task is not running + # after wait_for() returns. + # See https://bugs.python.org/issue32751 + await _cancel_and_wait(fut, loop=loop) raise futures.TimeoutError() finally: timeout_handle.cancel() async def _wait(fs, timeout, return_when, loop): - """Internal helper for wait() and wait_for(). + """Internal helper for wait(). The fs argument must be a collection of Futures. """ @@ -461,6 +464,22 @@ def _on_completion(f): return done, pending +async def _cancel_and_wait(fut, loop): + """Cancel the *fut* future or task and wait until it completes.""" + + waiter = loop.create_future() + cb = functools.partial(_release_waiter, waiter) + fut.add_done_callback(cb) + + try: + fut.cancel() + # We cannot wait on *fut* directly to make + # sure _cancel_and_wait itself is reliably cancellable. + await waiter + finally: + fut.remove_done_callback(cb) + + # This is *not* a @coroutine! It is just an iterator (yielding Futures). def as_completed(fs, *, loop=None, timeout=None): """Return an iterator whose values are coroutines. diff --git a/Lib/test/test_asyncio/test_locks.py b/Lib/test/test_asyncio/test_locks.py index 8642aa86b92b..b8d155e1d034 100644 --- a/Lib/test/test_asyncio/test_locks.py +++ b/Lib/test/test_asyncio/test_locks.py @@ -807,6 +807,19 @@ def test_ambiguous_loops(self): with self.assertRaises(ValueError): asyncio.Condition(lock, loop=loop) + def test_timeout_in_block(self): + loop = asyncio.new_event_loop() + self.addCleanup(loop.close) + + async def task_timeout(): + condition = asyncio.Condition(loop=loop) + async with condition: + with self.assertRaises(asyncio.TimeoutError): + await asyncio.wait_for(condition.wait(), timeout=0.5, + loop=loop) + + loop.run_until_complete(task_timeout()) + class SemaphoreTests(test_utils.TestCase): diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index 1280584d318c..1282a98c218f 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -789,6 +789,62 @@ def gen(): res = loop.run_until_complete(task) self.assertEqual(res, "ok") + def test_wait_for_waits_for_task_cancellation(self): + loop = asyncio.new_event_loop() + self.addCleanup(loop.close) + + task_done = False + + async def foo(): + async def inner(): + nonlocal task_done + try: + await asyncio.sleep(0.2, loop=loop) + finally: + task_done = True + + inner_task = self.new_task(loop, inner()) + + with self.assertRaises(asyncio.TimeoutError): + await asyncio.wait_for(inner_task, timeout=0.1, loop=loop) + + self.assertTrue(task_done) + + loop.run_until_complete(foo()) + + def test_wait_for_self_cancellation(self): + loop = asyncio.new_event_loop() + self.addCleanup(loop.close) + + async def foo(): + async def inner(): + try: + await asyncio.sleep(0.3, loop=loop) + except asyncio.CancelledError: + try: + await asyncio.sleep(0.3, loop=loop) + except asyncio.CancelledError: + await asyncio.sleep(0.3, loop=loop) + + return 42 + + inner_task = self.new_task(loop, inner()) + + wait = asyncio.wait_for(inner_task, timeout=0.1, loop=loop) + + # Test that wait_for itself is properly cancellable + # even when the initial task holds up the initial cancellation. + task = self.new_task(loop, wait) + await asyncio.sleep(0.2, loop=loop) + task.cancel() + + with self.assertRaises(asyncio.CancelledError): + await task + + self.assertEqual(await inner_task, 42) + + loop.run_until_complete(foo()) + def test_wait(self): def gen(): diff --git a/Misc/NEWS.d/next/Library/2018-05-29-15-32-18.bpo-32751.oBTqr7.rst b/Misc/NEWS.d/next/Library/2018-05-29-15-32-18.bpo-32751.oBTqr7.rst new file mode 100644 index 000000000000..3e27cd461ca8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-29-15-32-18.bpo-32751.oBTqr7.rst @@ -0,0 +1,2 @@ +When cancelling the task due to a timeout, :meth:`asyncio.wait_for` will now +wait until the cancellation is complete. From webhook-mailer at python.org Tue May 29 18:21:54 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Tue, 29 May 2018 22:21:54 -0000 Subject: [Python-checkins] bpo-23859: Document that asyncio.wait() does not cancel its futures (#7217) Message-ID: <mailman.73.1527632517.2800.python-checkins@python.org> https://github.com/python/cpython/commit/f9aeca2085464838f04bf13f816a1f861d43541f commit: f9aeca2085464838f04bf13f816a1f861d43541f branch: master author: Elvis Pranskevichus <elvis at magic.io> committer: Yury Selivanov <yury at magic.io> date: 2018-05-29T18:21:44-04:00 summary: bpo-23859: Document that asyncio.wait() does not cancel its futures (#7217) Unlike `asyncio.wait_for()`, `asyncio.wait()` does not cancel the passed futures when a timeout accurs. files: A Misc/NEWS.d/next/Documentation/2018-05-29-16-02-31.bpo-23859.E5gba1.rst M Doc/library/asyncio-task.rst diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index 3121b4718332..ba2cc12a8a75 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -768,6 +768,9 @@ Task functions | | futures finish or are cancelled. | +-----------------------------+----------------------------------------+ + Unlike :func:`~asyncio.wait_for`, ``wait()`` will not cancel the futures + when a timeout accurs. + This function is a :ref:`coroutine <coroutine>`. Usage:: diff --git a/Misc/NEWS.d/next/Documentation/2018-05-29-16-02-31.bpo-23859.E5gba1.rst b/Misc/NEWS.d/next/Documentation/2018-05-29-16-02-31.bpo-23859.E5gba1.rst new file mode 100644 index 000000000000..b372faa5eb97 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2018-05-29-16-02-31.bpo-23859.E5gba1.rst @@ -0,0 +1 @@ +Document that `asyncio.wait()` does not cancel its futures on timeout. From webhook-mailer at python.org Tue May 29 18:29:15 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Tue, 29 May 2018 22:29:15 -0000 Subject: [Python-checkins] bpo-32684: Fix gather to propagate cancel of itself with return_exceptions (GH-7209) (#7222) Message-ID: <mailman.74.1527632958.2800.python-checkins@python.org> https://github.com/python/cpython/commit/036434273e6f6905403432c973d98ade1ae58197 commit: 036434273e6f6905403432c973d98ade1ae58197 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Yury Selivanov <yury at magic.io> date: 2018-05-29T18:29:12-04:00 summary: bpo-32684: Fix gather to propagate cancel of itself with return_exceptions (GH-7209) (#7222) (cherry picked from commit 863b6749093a86810c4077112a857363410cc221) Co-authored-by: Yury Selivanov <yury at magic.io> files: A Misc/NEWS.d/next/Library/2018-05-29-12-51-18.bpo-32684.ZEIism.rst M Doc/library/asyncio-task.rst M Lib/asyncio/tasks.py M Lib/test/test_asyncio/test_tasks.py diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index 233cc9454967..dc450c375aad 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -640,6 +640,10 @@ Task functions outer Future is *not* cancelled in this case. (This is to prevent the cancellation of one child to cause other children to be cancelled.) + .. versionchanged:: 3.7.0 + If the *gather* itself is cancelled, the cancellation is propagated + regardless of *return_exceptions*. + .. function:: iscoroutine(obj) Return ``True`` if *obj* is a :ref:`coroutine object <coroutine>`, diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index 67fb57c6a781..6cef33d5212e 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -591,6 +591,7 @@ class _GatheringFuture(futures.Future): def __init__(self, children, *, loop=None): super().__init__(loop=loop) self._children = children + self._cancel_requested = False def cancel(self): if self.done(): @@ -599,6 +600,11 @@ def cancel(self): for child in self._children: if child.cancel(): ret = True + if ret: + # If any child tasks were actually cancelled, we should + # propagate the cancellation request regardless of + # *return_exceptions* argument. See issue 32684. + self._cancel_requested = True return ret @@ -673,7 +679,13 @@ def _done_callback(fut): res = fut.result() results.append(res) - outer.set_result(results) + if outer._cancel_requested: + # If gather is being cancelled we must propagate the + # cancellation regardless of *return_exceptions* argument. + # See issue 32684. + outer.set_exception(futures.CancelledError()) + else: + outer.set_result(results) arg_to_fut = {} children = [] diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index 33300c91a367..1280584d318c 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -2037,7 +2037,7 @@ def test_cancel_blocking_wait_for(self): def test_cancel_wait_for(self): self._test_cancel_wait_for(60.0) - def test_cancel_gather(self): + def test_cancel_gather_1(self): """Ensure that a gathering future refuses to be cancelled once all children are done""" loop = asyncio.new_event_loop() @@ -2067,6 +2067,33 @@ def cancelling_callback(_): self.assertFalse(gather_task.cancelled()) self.assertEqual(gather_task.result(), [42]) + def test_cancel_gather_2(self): + loop = asyncio.new_event_loop() + self.addCleanup(loop.close) + + async def test(): + time = 0 + while True: + time += 0.05 + await asyncio.gather(asyncio.sleep(0.05), + return_exceptions=True, + loop=loop) + if time > 1: + return + + async def main(): + qwe = asyncio.Task(test()) + await asyncio.sleep(0.2) + qwe.cancel() + try: + await qwe + except asyncio.CancelledError: + pass + else: + self.fail('gather did not propagate the cancellation request') + + loop.run_until_complete(main()) + def test_exception_traceback(self): # See http://bugs.python.org/issue28843 diff --git a/Misc/NEWS.d/next/Library/2018-05-29-12-51-18.bpo-32684.ZEIism.rst b/Misc/NEWS.d/next/Library/2018-05-29-12-51-18.bpo-32684.ZEIism.rst new file mode 100644 index 000000000000..b360bbcf7998 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-29-12-51-18.bpo-32684.ZEIism.rst @@ -0,0 +1 @@ +Fix gather to propagate cancellation of itself even with return_exceptions. From webhook-mailer at python.org Tue May 29 18:30:53 2018 From: webhook-mailer at python.org (Steve Dower) Date: Tue, 29 May 2018 22:30:53 -0000 Subject: [Python-checkins] [2.7] bpo-33670: Expose Sphinx errorlevel (GH-7156). (GH-7201) Message-ID: <mailman.75.1527633056.2800.python-checkins@python.org> https://github.com/python/cpython/commit/5583ef4777452e79278de80755d403f1c5b7781d commit: 5583ef4777452e79278de80755d403f1c5b7781d branch: 2.7 author: Andr?s Delfino <adelfino at gmail.com> committer: Steve Dower <steve.dower at microsoft.com> date: 2018-05-29T15:30:50-07:00 summary: [2.7] bpo-33670: Expose Sphinx errorlevel (GH-7156). (GH-7201) (cherry picked from commit 8c1ad0c4f69390fded09012e1ed5242c45753bb4) Co-authored-by: Andr?s Delfino <adelfino at gmail.com> files: M Doc/make.bat diff --git a/Doc/make.bat b/Doc/make.bat index ae6224ab4ca3..d50c0c36ed4b 100644 --- a/Doc/make.bat +++ b/Doc/make.bat @@ -13,7 +13,7 @@ if not defined SPHINXBUILD if defined PYTHON ( %PYTHON% -m pip install sphinx if errorlevel 1 exit /B ) - set SPHINXBUILD=%PYTHON% -c "import sphinx, sys; sys.argv[0] = 'sphinx-build'; sphinx.main()" + set SPHINXBUILD=%PYTHON% -c "import sphinx, sys; sys.argv[0] = 'sphinx-build'; sys.exit(sphinx.main())" ) if not defined PYTHON set PYTHON=py From webhook-mailer at python.org Tue May 29 18:37:10 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 29 May 2018 22:37:10 -0000 Subject: [Python-checkins] bpo-32751: Wait for task cancellation in asyncio.wait_for() (GH-7216) Message-ID: <mailman.76.1527633435.2800.python-checkins@python.org> https://github.com/python/cpython/commit/d8948c5e09c4a2a818f6f6cfaf8064f2c2138fa5 commit: d8948c5e09c4a2a818f6f6cfaf8064f2c2138fa5 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-29T15:37:06-07:00 summary: bpo-32751: Wait for task cancellation in asyncio.wait_for() (GH-7216) Currently, asyncio.wait_for(fut), upon reaching the timeout deadline, cancels the future and returns immediately. This is problematic for when *fut* is a Task, because it will be left running for an arbitrary amount of time. This behavior is iself surprising and may lead to related bugs such as the one described in bpo-33638: condition = asyncio.Condition() async with condition: await asyncio.wait_for(condition.wait(), timeout=0.5) Currently, instead of raising a TimeoutError, the above code will fail with `RuntimeError: cannot wait on un-acquired lock`, because `__aexit__` is reached _before_ `condition.wait()` finishes its cancellation and re-acquires the condition lock. To resolve this, make `wait_for` await for the task cancellation. The tradeoff here is that the `timeout` promise may be broken if the task decides to handle its cancellation in a slow way. This represents a behavior change and should probably not be back-patched to 3.6 and earlier. (cherry picked from commit e2b340ab4196e1beb902327f503574b5d7369185) Co-authored-by: Elvis Pranskevichus <elvis at magic.io> files: A Misc/NEWS.d/next/Library/2018-05-29-15-32-18.bpo-32751.oBTqr7.rst M Doc/library/asyncio-task.rst M Lib/asyncio/tasks.py M Lib/test/test_asyncio/test_locks.py M Lib/test/test_asyncio/test_tasks.py diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index dc450c375aad..3121b4718332 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -790,7 +790,9 @@ Task functions Returns result of the Future or coroutine. When a timeout occurs, it cancels the task and raises :exc:`asyncio.TimeoutError`. To avoid the task - cancellation, wrap it in :func:`shield`. + cancellation, wrap it in :func:`shield`. The function will wait until + the future is actually cancelled, so the total wait time may exceed + the *timeout*. If the wait is cancelled, the future *fut* is also cancelled. @@ -800,3 +802,8 @@ Task functions .. versionchanged:: 3.4.3 If the wait is cancelled, the future *fut* is now also cancelled. + + .. versionchanged:: 3.7 + When *fut* is cancelled due to a timeout, ``wait_for`` now waits + for *fut* to be cancelled. Previously, + it raised :exc:`~asyncio.TimeoutError` immediately. diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index 6cef33d5212e..72792a25cf55 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -412,14 +412,17 @@ def _release_waiter(waiter, *args): return fut.result() else: fut.remove_done_callback(cb) - fut.cancel() + # We must ensure that the task is not running + # after wait_for() returns. + # See https://bugs.python.org/issue32751 + await _cancel_and_wait(fut, loop=loop) raise futures.TimeoutError() finally: timeout_handle.cancel() async def _wait(fs, timeout, return_when, loop): - """Internal helper for wait() and wait_for(). + """Internal helper for wait(). The fs argument must be a collection of Futures. """ @@ -461,6 +464,22 @@ def _on_completion(f): return done, pending +async def _cancel_and_wait(fut, loop): + """Cancel the *fut* future or task and wait until it completes.""" + + waiter = loop.create_future() + cb = functools.partial(_release_waiter, waiter) + fut.add_done_callback(cb) + + try: + fut.cancel() + # We cannot wait on *fut* directly to make + # sure _cancel_and_wait itself is reliably cancellable. + await waiter + finally: + fut.remove_done_callback(cb) + + # This is *not* a @coroutine! It is just an iterator (yielding Futures). def as_completed(fs, *, loop=None, timeout=None): """Return an iterator whose values are coroutines. diff --git a/Lib/test/test_asyncio/test_locks.py b/Lib/test/test_asyncio/test_locks.py index 8642aa86b92b..b8d155e1d034 100644 --- a/Lib/test/test_asyncio/test_locks.py +++ b/Lib/test/test_asyncio/test_locks.py @@ -807,6 +807,19 @@ def test_ambiguous_loops(self): with self.assertRaises(ValueError): asyncio.Condition(lock, loop=loop) + def test_timeout_in_block(self): + loop = asyncio.new_event_loop() + self.addCleanup(loop.close) + + async def task_timeout(): + condition = asyncio.Condition(loop=loop) + async with condition: + with self.assertRaises(asyncio.TimeoutError): + await asyncio.wait_for(condition.wait(), timeout=0.5, + loop=loop) + + loop.run_until_complete(task_timeout()) + class SemaphoreTests(test_utils.TestCase): diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index 1280584d318c..1282a98c218f 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -789,6 +789,62 @@ def gen(): res = loop.run_until_complete(task) self.assertEqual(res, "ok") + def test_wait_for_waits_for_task_cancellation(self): + loop = asyncio.new_event_loop() + self.addCleanup(loop.close) + + task_done = False + + async def foo(): + async def inner(): + nonlocal task_done + try: + await asyncio.sleep(0.2, loop=loop) + finally: + task_done = True + + inner_task = self.new_task(loop, inner()) + + with self.assertRaises(asyncio.TimeoutError): + await asyncio.wait_for(inner_task, timeout=0.1, loop=loop) + + self.assertTrue(task_done) + + loop.run_until_complete(foo()) + + def test_wait_for_self_cancellation(self): + loop = asyncio.new_event_loop() + self.addCleanup(loop.close) + + async def foo(): + async def inner(): + try: + await asyncio.sleep(0.3, loop=loop) + except asyncio.CancelledError: + try: + await asyncio.sleep(0.3, loop=loop) + except asyncio.CancelledError: + await asyncio.sleep(0.3, loop=loop) + + return 42 + + inner_task = self.new_task(loop, inner()) + + wait = asyncio.wait_for(inner_task, timeout=0.1, loop=loop) + + # Test that wait_for itself is properly cancellable + # even when the initial task holds up the initial cancellation. + task = self.new_task(loop, wait) + await asyncio.sleep(0.2, loop=loop) + task.cancel() + + with self.assertRaises(asyncio.CancelledError): + await task + + self.assertEqual(await inner_task, 42) + + loop.run_until_complete(foo()) + def test_wait(self): def gen(): diff --git a/Misc/NEWS.d/next/Library/2018-05-29-15-32-18.bpo-32751.oBTqr7.rst b/Misc/NEWS.d/next/Library/2018-05-29-15-32-18.bpo-32751.oBTqr7.rst new file mode 100644 index 000000000000..3e27cd461ca8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-29-15-32-18.bpo-32751.oBTqr7.rst @@ -0,0 +1,2 @@ +When cancelling the task due to a timeout, :meth:`asyncio.wait_for` will now +wait until the cancellation is complete. From webhook-mailer at python.org Tue May 29 18:44:16 2018 From: webhook-mailer at python.org (Julien Palard) Date: Tue, 29 May 2018 22:44:16 -0000 Subject: [Python-checkins] Fix whatsnew entry about ThreadedHTTPServer. (GH-7220) Message-ID: <mailman.77.1527633858.2800.python-checkins@python.org> https://github.com/python/cpython/commit/a34e424bdbc62b4d83593af1c0d459d8aaac90f3 commit: a34e424bdbc62b4d83593af1c0d459d8aaac90f3 branch: master author: Julien Palard <julien at palard.fr> committer: GitHub <noreply at github.com> date: 2018-05-30T00:44:12+02:00 summary: Fix whatsnew entry about ThreadedHTTPServer. (GH-7220) files: M Doc/whatsnew/3.7.rst diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 8b94cdcc9e6a..2471989ec7b9 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -929,7 +929,7 @@ With this parameter, the server serves the specified directory, by default it uses the current working directory. (Contributed by St?phane Wirtel and Julien Palard in :issue:`28707`.) -The new :class:`ThreadedHTTPServer <http.server.ThreadedHTTPServer>` class +The new :class:`ThreadingHTTPServer <http.server.ThreadingHTTPServer>` class uses threads to handle requests using :class:`~socketserver.ThreadingMixin`. It is used when ``http.server`` is run with ``-m``. (Contributed by Julien Palard in :issue:`31639`.) From webhook-mailer at python.org Tue May 29 19:20:05 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Tue, 29 May 2018 23:20:05 -0000 Subject: [Python-checkins] bpo-32684: Fix gather to propagate cancel of itself with return_exceptions (GH-7224) Message-ID: <mailman.78.1527636008.2800.python-checkins@python.org> https://github.com/python/cpython/commit/3b263e65a80cfcb1fc751834372533773ec024a4 commit: 3b263e65a80cfcb1fc751834372533773ec024a4 branch: 3.6 author: Yury Selivanov <yury at magic.io> committer: GitHub <noreply at github.com> date: 2018-05-29T19:20:01-04:00 summary: bpo-32684: Fix gather to propagate cancel of itself with return_exceptions (GH-7224) files: A Misc/NEWS.d/next/Library/2018-05-29-12-51-18.bpo-32684.ZEIism.rst M Doc/library/asyncio-task.rst M Lib/asyncio/tasks.py M Lib/test/test_asyncio/test_tasks.py diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index 5b801aaf8ecc..c0383331c1ed 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -568,6 +568,10 @@ Task functions outer Future is *not* cancelled in this case. (This is to prevent the cancellation of one child to cause other children to be cancelled.) + .. versionchanged:: 3.6.6 + If the *gather* itself is cancelled, the cancellation is propagated + regardless of *return_exceptions*. + .. function:: iscoroutine(obj) Return ``True`` if *obj* is a :ref:`coroutine object <coroutine>`, diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py index a294dfbf5e57..4cd2c6ac6c7c 100644 --- a/Lib/asyncio/tasks.py +++ b/Lib/asyncio/tasks.py @@ -548,6 +548,7 @@ class _GatheringFuture(futures.Future): def __init__(self, children, *, loop=None): super().__init__(loop=loop) self._children = children + self._cancel_requested = False def cancel(self): if self.done(): @@ -556,6 +557,11 @@ def cancel(self): for child in self._children: if child.cancel(): ret = True + if ret: + # If any child tasks were actually cancelled, we should + # propagate the cancellation request regardless of + # *return_exceptions* argument. See issue 32684. + self._cancel_requested = True return ret @@ -636,7 +642,10 @@ def _done_callback(i, fut): results[i] = res nfinished += 1 if nfinished == nchildren: - outer.set_result(results) + if outer._cancel_requested: + outer.set_exception(futures.CancelledError()) + else: + outer.set_result(results) for i, fut in enumerate(children): fut.add_done_callback(functools.partial(_done_callback, i)) diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index f41160ba3222..7c5187348bc4 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -1991,7 +1991,7 @@ def test_cancel_blocking_wait_for(self): def test_cancel_wait_for(self): self._test_cancel_wait_for(60.0) - def test_cancel_gather(self): + def test_cancel_gather_1(self): """Ensure that a gathering future refuses to be cancelled once all children are done""" loop = asyncio.new_event_loop() @@ -2021,6 +2021,33 @@ def cancelling_callback(_): self.assertFalse(gather_task.cancelled()) self.assertEqual(gather_task.result(), [42]) + def test_cancel_gather_2(self): + loop = asyncio.new_event_loop() + self.addCleanup(loop.close) + + async def test(): + time = 0 + while True: + time += 0.05 + await asyncio.gather(asyncio.sleep(0.05, loop=loop), + return_exceptions=True, + loop=loop) + if time > 1: + return + + async def main(): + qwe = self.new_task(loop, test()) + await asyncio.sleep(0.2, loop=loop) + qwe.cancel() + try: + await qwe + except asyncio.CancelledError: + pass + else: + self.fail('gather did not propagate the cancellation request') + + loop.run_until_complete(main()) + def test_exception_traceback(self): # See http://bugs.python.org/issue28843 diff --git a/Misc/NEWS.d/next/Library/2018-05-29-12-51-18.bpo-32684.ZEIism.rst b/Misc/NEWS.d/next/Library/2018-05-29-12-51-18.bpo-32684.ZEIism.rst new file mode 100644 index 000000000000..b360bbcf7998 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-29-12-51-18.bpo-32684.ZEIism.rst @@ -0,0 +1 @@ +Fix gather to propagate cancellation of itself even with return_exceptions. From webhook-mailer at python.org Tue May 29 19:20:29 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Tue, 29 May 2018 23:20:29 -0000 Subject: [Python-checkins] bpo-32684: Fix nits in tests (GH-7225) Message-ID: <mailman.79.1527636031.2800.python-checkins@python.org> https://github.com/python/cpython/commit/6f75bae74866b6acf638e3aa610d830d55b7e314 commit: 6f75bae74866b6acf638e3aa610d830d55b7e314 branch: master author: Yury Selivanov <yury at magic.io> committer: GitHub <noreply at github.com> date: 2018-05-29T19:20:26-04:00 summary: bpo-32684: Fix nits in tests (GH-7225) files: M Lib/test/test_asyncio/test_tasks.py diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index 1282a98c218f..d95c98f0a617 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -2131,15 +2131,15 @@ def test_cancel_gather_2(self): time = 0 while True: time += 0.05 - await asyncio.gather(asyncio.sleep(0.05), + await asyncio.gather(asyncio.sleep(0.05, loop=loop), return_exceptions=True, loop=loop) if time > 1: return async def main(): - qwe = asyncio.Task(test()) - await asyncio.sleep(0.2) + qwe = self.new_task(loop, test()) + await asyncio.sleep(0.2, loop=loop) qwe.cancel() try: await qwe From webhook-mailer at python.org Tue May 29 20:15:09 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Wed, 30 May 2018 00:15:09 -0000 Subject: [Python-checkins] Fix typo introduced in GH-7217 (#7230) Message-ID: <mailman.80.1527639310.2800.python-checkins@python.org> https://github.com/python/cpython/commit/dec947ca26bd598a26869226dcac592a7ccf0d56 commit: dec947ca26bd598a26869226dcac592a7ccf0d56 branch: master author: Elvis Pranskevichus <elvis at magic.io> committer: Yury Selivanov <yury at magic.io> date: 2018-05-29T20:14:59-04:00 summary: Fix typo introduced in GH-7217 (#7230) files: M Doc/library/asyncio-task.rst diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index ba2cc12a8a75..2b480d4be3fb 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -769,7 +769,7 @@ Task functions +-----------------------------+----------------------------------------+ Unlike :func:`~asyncio.wait_for`, ``wait()`` will not cancel the futures - when a timeout accurs. + when a timeout occurs. This function is a :ref:`coroutine <coroutine>`. From webhook-mailer at python.org Tue May 29 20:24:21 2018 From: webhook-mailer at python.org (Julien Palard) Date: Wed, 30 May 2018 00:24:21 -0000 Subject: [Python-checkins] [3.7] bpo-31639: Change ThreadedHTTPServer to ThreadingHTTPServer class name (GH-7195) (GH-7219) Message-ID: <mailman.81.1527639862.2800.python-checkins@python.org> https://github.com/python/cpython/commit/4f53e2ac16e0bebae0a0c18f220295035b081ee3 commit: 4f53e2ac16e0bebae0a0c18f220295035b081ee3 branch: 3.7 author: Julien Palard <julien at palard.fr> committer: GitHub <noreply at github.com> date: 2018-05-30T02:24:17+02:00 summary: [3.7] bpo-31639: Change ThreadedHTTPServer to ThreadingHTTPServer class name (GH-7195) (GH-7219) * [3.7] bpo-31639: Change ThreadedHTTPServer to ThreadingHTTPServer class name (GH-7195). (cherry picked from commit 1cee216cf383eade641aed22f4ec7d4cb565ecff) * Fix whatsnew entry about ThreadedHTTPServer. (GH-7220) (cherry picked from commit a34e424bdbc62b4d83593af1c0d459d8aaac90f3) files: M Doc/library/http.server.rst M Doc/whatsnew/3.7.rst M Lib/http/server.py diff --git a/Doc/library/http.server.rst b/Doc/library/http.server.rst index 16cfa1798aef..0bd7f778cec0 100644 --- a/Doc/library/http.server.rst +++ b/Doc/library/http.server.rst @@ -33,7 +33,7 @@ handler. Code to create and run the server looks like this:: :attr:`server_port`. The server is accessible by the handler, typically through the handler's :attr:`server` instance variable. -.. class:: ThreadedHTTPServer(server_address, RequestHandlerClass) +.. class:: ThreadingHTTPServer(server_address, RequestHandlerClass) This class is identical to HTTPServer but uses threads to handle requests by using the :class:`~socketserver.ThreadingMixIn`. This @@ -43,7 +43,7 @@ handler. Code to create and run the server looks like this:: .. versionadded:: 3.7 -The :class:`HTTPServer` and :class:`ThreadedHTTPServer` must be given +The :class:`HTTPServer` and :class:`ThreadingHTTPServer` must be given a *RequestHandlerClass* on instantiation, of which this module provides three different variants: diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 8b94cdcc9e6a..2471989ec7b9 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -929,7 +929,7 @@ With this parameter, the server serves the specified directory, by default it uses the current working directory. (Contributed by St?phane Wirtel and Julien Palard in :issue:`28707`.) -The new :class:`ThreadedHTTPServer <http.server.ThreadedHTTPServer>` class +The new :class:`ThreadingHTTPServer <http.server.ThreadingHTTPServer>` class uses threads to handle requests using :class:`~socketserver.ThreadingMixin`. It is used when ``http.server`` is run with ``-m``. (Contributed by Julien Palard in :issue:`31639`.) diff --git a/Lib/http/server.py b/Lib/http/server.py index a2726ab89750..ea0e295d2834 100644 --- a/Lib/http/server.py +++ b/Lib/http/server.py @@ -83,7 +83,7 @@ __version__ = "0.6" __all__ = [ - "HTTPServer", "ThreadedHTTPServer", "BaseHTTPRequestHandler", + "HTTPServer", "ThreadingHTTPServer", "BaseHTTPRequestHandler", "SimpleHTTPRequestHandler", "CGIHTTPRequestHandler", ] @@ -140,7 +140,7 @@ def server_bind(self): self.server_port = port -class ThreadedHTTPServer(socketserver.ThreadingMixIn, HTTPServer): +class ThreadingHTTPServer(socketserver.ThreadingMixIn, HTTPServer): daemon_threads = True @@ -1217,7 +1217,7 @@ def run_cgi(self): def test(HandlerClass=BaseHTTPRequestHandler, - ServerClass=ThreadedHTTPServer, + ServerClass=ThreadingHTTPServer, protocol="HTTP/1.0", port=8000, bind=""): """Test the HTTP request handler class. From webhook-mailer at python.org Tue May 29 20:40:59 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Wed, 30 May 2018 00:40:59 -0000 Subject: [Python-checkins] bpo-32684: Fix nits in tests (GH-7225) (#7231) Message-ID: <mailman.82.1527640860.2800.python-checkins@python.org> https://github.com/python/cpython/commit/3ddee64587482082fcbab930ff82ed67aa9f4a0d commit: 3ddee64587482082fcbab930ff82ed67aa9f4a0d branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Yury Selivanov <yury at magic.io> date: 2018-05-29T20:40:54-04:00 summary: bpo-32684: Fix nits in tests (GH-7225) (#7231) (cherry picked from commit 6f75bae74866b6acf638e3aa610d830d55b7e314) Co-authored-by: Yury Selivanov <yury at magic.io> files: M Lib/test/test_asyncio/test_tasks.py diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index 1282a98c218f..d95c98f0a617 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -2131,15 +2131,15 @@ def test_cancel_gather_2(self): time = 0 while True: time += 0.05 - await asyncio.gather(asyncio.sleep(0.05), + await asyncio.gather(asyncio.sleep(0.05, loop=loop), return_exceptions=True, loop=loop) if time > 1: return async def main(): - qwe = asyncio.Task(test()) - await asyncio.sleep(0.2) + qwe = self.new_task(loop, test()) + await asyncio.sleep(0.2, loop=loop) qwe.cancel() try: await qwe From webhook-mailer at python.org Tue May 29 20:47:59 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Wed, 30 May 2018 00:47:59 -0000 Subject: [Python-checkins] Revert "bpo-22087: Fix Policy.get_event_loop() to detect fork (GH-7208)" (#7232) Message-ID: <mailman.83.1527641282.2800.python-checkins@python.org> https://github.com/python/cpython/commit/99279ad823a758288e4e41962abfc4dad8943ce8 commit: 99279ad823a758288e4e41962abfc4dad8943ce8 branch: master author: Yury Selivanov <yury at magic.io> committer: GitHub <noreply at github.com> date: 2018-05-29T20:47:56-04:00 summary: Revert "bpo-22087: Fix Policy.get_event_loop() to detect fork (GH-7208)" (#7232) This reverts commit 5d97b7bcc19496617bf8c448d2f149cc28c73bc7. files: D Misc/NEWS.d/next/Library/2018-05-29-12-06-54.bpo-22087.uv7_Y6.rst M Lib/asyncio/events.py M Lib/test/test_asyncio/test_unix_events.py diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py index 68dc25e1e8be..40946bbf6529 100644 --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -625,23 +625,16 @@ class BaseDefaultEventLoopPolicy(AbstractEventLoopPolicy): class _Local(threading.local): _loop = None - _pid = None _set_called = False def __init__(self): self._local = self._Local() - self._local._pid = os.getpid() def get_event_loop(self): """Get the event loop. This may be None or an instance of EventLoop. """ - if self._local._pid != os.getpid(): - # If we detect we're in a child process forked by multiprocessing, - # we reset self._local so that we'll get a new event loop. - self._local = self._Local() - if (self._local._loop is None and not self._local._set_called and isinstance(threading.current_thread(), threading._MainThread)): diff --git a/Lib/test/test_asyncio/test_unix_events.py b/Lib/test/test_asyncio/test_unix_events.py index 1bc2d8658d8a..a01efedf66d9 100644 --- a/Lib/test/test_asyncio/test_unix_events.py +++ b/Lib/test/test_asyncio/test_unix_events.py @@ -13,7 +13,6 @@ import tempfile import threading import unittest -import multiprocessing from unittest import mock from test import support @@ -1805,37 +1804,6 @@ def create_watcher(self): return asyncio.FastChildWatcher() -class ForkedProcessTests(unittest.TestCase): - def setUp(self): - self.parent_loop = asyncio.SelectorEventLoop() - asyncio.set_event_loop(self.parent_loop) - self.ctx = multiprocessing.get_context("fork") - - def tearDown(self): - self.parent_loop.close() - - def _check_loops_not_equal(self, old_loop): - loop = asyncio.get_event_loop() - if loop is old_loop: - raise RuntimeError("Child process inherited parent's event loop") - - try: - val = loop.run_until_complete(asyncio.sleep(0.05, result=42)) - if val != 42: - raise RuntimeError("new event loop does not work") - finally: - loop.close() - - sys.exit(loop is old_loop) - - def test_new_loop_in_child(self): - p = self.ctx.Process(target=self._check_loops_not_equal, - args=(self.parent_loop,)) - p.start() - p.join() - self.assertEqual(p.exitcode, 0) - - class PolicyTests(unittest.TestCase): def create_policy(self): diff --git a/Misc/NEWS.d/next/Library/2018-05-29-12-06-54.bpo-22087.uv7_Y6.rst b/Misc/NEWS.d/next/Library/2018-05-29-12-06-54.bpo-22087.uv7_Y6.rst deleted file mode 100644 index 92127cd57a91..000000000000 --- a/Misc/NEWS.d/next/Library/2018-05-29-12-06-54.bpo-22087.uv7_Y6.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix Policy.get_event_loop() to detect fork and return a new loop. - -Original patch by Dan O'Reilly. From webhook-mailer at python.org Tue May 29 20:56:36 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Wed, 30 May 2018 00:56:36 -0000 Subject: [Python-checkins] Revert "bpo-22087: Fix Policy.get_event_loop() to detect fork (GH-7208)" (GH-7233) Message-ID: <mailman.84.1527641798.2800.python-checkins@python.org> https://github.com/python/cpython/commit/af9cda9845666e2f704177a431d29f91efbf828a commit: af9cda9845666e2f704177a431d29f91efbf828a branch: 3.7 author: Yury Selivanov <yury at magic.io> committer: GitHub <noreply at github.com> date: 2018-05-29T20:56:33-04:00 summary: Revert "bpo-22087: Fix Policy.get_event_loop() to detect fork (GH-7208)" (GH-7233) This reverts commit 2a7eb0b531656f4a77d85078e6e009e4b3639ef9. files: D Misc/NEWS.d/next/Library/2018-05-29-12-06-54.bpo-22087.uv7_Y6.rst M Lib/asyncio/events.py M Lib/test/test_asyncio/test_unix_events.py diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py index 68dc25e1e8be..40946bbf6529 100644 --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -625,23 +625,16 @@ class BaseDefaultEventLoopPolicy(AbstractEventLoopPolicy): class _Local(threading.local): _loop = None - _pid = None _set_called = False def __init__(self): self._local = self._Local() - self._local._pid = os.getpid() def get_event_loop(self): """Get the event loop. This may be None or an instance of EventLoop. """ - if self._local._pid != os.getpid(): - # If we detect we're in a child process forked by multiprocessing, - # we reset self._local so that we'll get a new event loop. - self._local = self._Local() - if (self._local._loop is None and not self._local._set_called and isinstance(threading.current_thread(), threading._MainThread)): diff --git a/Lib/test/test_asyncio/test_unix_events.py b/Lib/test/test_asyncio/test_unix_events.py index 577566851223..104f99593797 100644 --- a/Lib/test/test_asyncio/test_unix_events.py +++ b/Lib/test/test_asyncio/test_unix_events.py @@ -13,7 +13,6 @@ import tempfile import threading import unittest -import multiprocessing from unittest import mock from test import support @@ -1793,37 +1792,6 @@ def create_watcher(self): return asyncio.FastChildWatcher() -class ForkedProcessTests(unittest.TestCase): - def setUp(self): - self.parent_loop = asyncio.SelectorEventLoop() - asyncio.set_event_loop(self.parent_loop) - self.ctx = multiprocessing.get_context("fork") - - def tearDown(self): - self.parent_loop.close() - - def _check_loops_not_equal(self, old_loop): - loop = asyncio.get_event_loop() - if loop is old_loop: - raise RuntimeError("Child process inherited parent's event loop") - - try: - val = loop.run_until_complete(asyncio.sleep(0.05, result=42)) - if val != 42: - raise RuntimeError("new event loop does not work") - finally: - loop.close() - - sys.exit(loop is old_loop) - - def test_new_loop_in_child(self): - p = self.ctx.Process(target=self._check_loops_not_equal, - args=(self.parent_loop,)) - p.start() - p.join() - self.assertEqual(p.exitcode, 0) - - class PolicyTests(unittest.TestCase): def create_policy(self): diff --git a/Misc/NEWS.d/next/Library/2018-05-29-12-06-54.bpo-22087.uv7_Y6.rst b/Misc/NEWS.d/next/Library/2018-05-29-12-06-54.bpo-22087.uv7_Y6.rst deleted file mode 100644 index 92127cd57a91..000000000000 --- a/Misc/NEWS.d/next/Library/2018-05-29-12-06-54.bpo-22087.uv7_Y6.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix Policy.get_event_loop() to detect fork and return a new loop. - -Original patch by Dan O'Reilly. From webhook-mailer at python.org Tue May 29 20:57:53 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Wed, 30 May 2018 00:57:53 -0000 Subject: [Python-checkins] A better fix for asyncio test_stdin_broken_pipe (#7221) Message-ID: <mailman.85.1527641874.2800.python-checkins@python.org> https://github.com/python/cpython/commit/ad74d50517c069359578014bb32e660828d68332 commit: ad74d50517c069359578014bb32e660828d68332 branch: master author: Yury Selivanov <yury at magic.io> committer: GitHub <noreply at github.com> date: 2018-05-29T20:57:50-04:00 summary: A better fix for asyncio test_stdin_broken_pipe (#7221) files: M Lib/test/test_asyncio/test_subprocess.py diff --git a/Lib/test/test_asyncio/test_subprocess.py b/Lib/test/test_asyncio/test_subprocess.py index 235813aa977c..01583376e571 100644 --- a/Lib/test/test_asyncio/test_subprocess.py +++ b/Lib/test/test_asyncio/test_subprocess.py @@ -218,8 +218,10 @@ def prepare_broken_pipe_test(self): # the program ends before the stdin can be feeded create = asyncio.create_subprocess_exec( - sys.executable, '-c', 'pass', + sys.executable, + '-c', 'print("hello", flush=True)', stdin=subprocess.PIPE, + stdout=subprocess.PIPE, loop=self.loop) proc = self.loop.run_until_complete(create) return (proc, large_data) @@ -228,7 +230,7 @@ def test_stdin_broken_pipe(self): proc, large_data = self.prepare_broken_pipe_test() async def write_stdin(proc, data): - await asyncio.sleep(0.5, loop=self.loop) + await proc.stdout.readline() proc.stdin.write(data) await proc.stdin.drain() From lp_benchmark_robot at intel.com Tue May 29 20:59:44 2018 From: lp_benchmark_robot at intel.com (lp_benchmark_robot at intel.com) Date: Tue, 29 May 2018 17:59:44 -0700 Subject: [Python-checkins] [65 flat] Results for Python (master branch) 2018-05-28 Message-ID: <e7e31c28-a836-45c1-b8c2-421fececab7a@orsmsx104.amr.corp.intel.com> Results for project python/master, build date: 2018-05-28 03:03:44-07:00. - commit: c651275 - previous commit: 6e413f4 - revision date: 2018-05-26 13:38:33-07:00 - environment: Broadwell-EP - cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores, stepping 1, LLC 55 MB - mem: 128 GB - os: Ubuntu 16.04.2 LTS - kernel: 4.4.0-62-generic x86_64 GNU/Linux Baseline results were generated using release v3.6.0, with hash 5c4568a from 2016-12-22 23:38:47+00:00. +-----+------------------------+--------+------------+------------+------------+ | | |relative|change since|change since|current rev | | | benchmark|std_dev*| last run | baseline |run with PGO| +-----+------------------------+--------+------------+------------+------------+ | :-| | 2to3| 0.604% | -0.139% | +8.945% | +6.964% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method| 0.765% | +0.651% | +24.242% | +13.944% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_slots| 0.733% | +0.694% | +25.961% | +12.263% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_unknown| 1.242% | -0.144% | +22.245% | +14.424% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_simple| 4.096% | -0.823% | +10.456% | +12.871% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chameleon| 1.448% | +0.497% | +12.627% | +11.354% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chaos| 0.831% | -0.066% | +8.461% | +10.520% | +-----+------------------------+--------+------------+------------+------------+ | :-| | crypto_pyaes| 0.525% | -0.051% | -0.511% | +8.045% | +-----+------------------------+--------+------------+------------+------------+ | :-| | deltablue| 3.764% | -1.008% | +11.391% | +17.084% | +-----+------------------------+--------+------------+------------+------------+ | :-| | django_template| 3.608% | -2.678% | +20.301% | +13.639% | +-----+------------------------+--------+------------+------------+------------+ | :-| | dulwich_log| 1.506% | -0.629% | +4.591% | +7.490% | +-----+------------------------+--------+------------+------------+------------+ | :-| | fannkuch| 0.423% | -0.062% | +6.104% | +6.527% | +-----+------------------------+--------+------------+------------+------------+ | :-| | float| 1.491% | +0.648% | +2.727% | +8.218% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_text| 1.140% | -0.253% | +14.171% | +10.308% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_xml| 1.430% | -0.665% | +11.043% | +9.983% | +-----+------------------------+--------+------------+------------+------------+ | :-| | go| 5.790% | +0.216% | +5.427% | +10.440% | +-----+------------------------+--------+------------+------------+------------+ | :-| | hexiom| 0.445% | +0.214% | +12.159% | +11.171% | +-----+------------------------+--------+------------+------------+------------+ | :-| | html5lib| 4.485% | -2.128% | +9.717% | +10.556% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_dumps| 2.136% | -0.053% | +3.573% | +9.583% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_loads| 4.848% | +0.552% | -3.626% | +13.601% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_format| 1.775% | -0.892% | +16.477% | +13.100% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_silent| 2.527% | +0.057% | +48.001% | +13.482% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_simple| 1.559% | -0.803% | +11.409% | +13.940% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mako| 0.760% | -0.216% | +16.476% | +14.242% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mdp| 5.554% | -0.030% | +1.303% | +16.346% | +-----+------------------------+--------+------------+------------+------------+ | :-| | meteor_contest| 0.938% | +0.014% | +4.627% | +6.176% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nbody| 0.679% | +0.543% | +0.033% | +0.650% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nqueens| 0.529% | -0.060% | +5.313% | +8.069% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pathlib| 1.572% | -0.946% | +0.112% | +10.730% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle| 4.688% | -0.994% | -1.950% | +24.649% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_dict| 5.842% | -0.913% | +6.715% | +19.150% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_list| 2.222% | +0.109% | +6.800% | +17.806% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_pure_python| 4.798% | -0.713% | +11.233% | +11.059% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pidigits| 0.066% | +0.049% | +0.221% | +9.848% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup| 0.127% | -0.204% | +18.870% | +5.079% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup_no_site| 0.084% | -0.222% | +5.863% | +5.331% | +-----+------------------------+--------+------------+------------+------------+ | :-| | raytrace| 0.864% | -0.598% | +10.019% | +15.174% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_compile| 5.735% | +0.606% | +4.300% | +10.772% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_dna| 0.499% | -0.168% | -2.236% | +12.652% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_effbot| 3.846% | -1.080% | -8.058% | +9.952% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_v8| 1.595% | -0.487% | +3.567% | +9.321% | +-----+------------------------+--------+------------+------------+------------+ | :-| | richards| 1.411% | +0.199% | +9.448% | +16.164% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_fft| 0.516% | -0.043% | -1.661% | +3.515% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_lu| 3.645% | +0.798% | +23.042% | +12.732% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_monte_carlo| 2.144% | +0.014% | +5.120% | +5.756% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sor| 1.160% | +0.306% | +15.300% | +8.982% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sparse_mat_mult| 2.793% | -0.667% | -3.832% | +3.032% | +-----+------------------------+--------+------------+------------+------------+ | :-| | spectral_norm| 0.556% | -0.166% | +4.514% | +6.817% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_declarative| 1.396% | -1.131% | +6.481% | +6.701% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_imperative| 3.609% | +0.115% | +7.596% | +4.962% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlite_synth| 3.390% | -0.383% | -0.081% | +10.628% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_expand| 2.852% | +0.225% | +18.044% | +7.085% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_integrate| 1.624% | -0.210% | +18.551% | +6.409% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_str| 4.193% | -0.532% | +19.247% | +7.472% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_sum| 6.348% | -1.509% | +14.980% | +11.302% | +-----+------------------------+--------+------------+------------+------------+ | :-| | telco| 3.468% | +0.052% | +20.003% | +9.386% | +-----+------------------------+--------+------------+------------+------------+ | :-| | tornado_http| 0.993% | -0.235% | +7.466% | +6.322% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpack_sequence| 0.960% | +0.299% | +2.715% | -0.621% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle| 9.000% | -0.139% | +5.976% | +23.435% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_list| 1.912% | -0.583% | -3.534% | +15.606% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_pure_python| 1.752% | +0.305% | +7.499% | +8.264% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_generate| 1.248% | -0.199% | +2.325% | +12.892% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_iterparse| 1.727% | -0.157% | +4.120% | +9.860% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_parse| 3.083% | -1.695% | -7.095% | +12.286% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_process| 2.164% | -0.477% | +4.263% | +12.258% | +-----+------------------------+--------+------------+------------+------------+ * Relative Standard Deviation (Standard Deviation/Average) If this is not displayed properly please visit our results page here: http://languagesperformance.intel.com/65-flat-results-for-python-master-branch-2018-05-28 Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. From webhook-mailer at python.org Tue May 29 21:26:25 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Wed, 30 May 2018 01:26:25 -0000 Subject: [Python-checkins] [3.7] bpo-23859: Document that asyncio.wait() does not cancel its futures (GH-7217) (#7227) Message-ID: <mailman.86.1527643588.2800.python-checkins@python.org> https://github.com/python/cpython/commit/f95269404c03bd769a3551cd851b51b8f89672df commit: f95269404c03bd769a3551cd851b51b8f89672df branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Yury Selivanov <yury at magic.io> date: 2018-05-29T21:26:22-04:00 summary: [3.7] bpo-23859: Document that asyncio.wait() does not cancel its futures (GH-7217) (#7227) * bpo-23859: Document that asyncio.wait() does not cancel its futures (GH-7217) Unlike `asyncio.wait_for()`, `asyncio.wait()` does not cancel the passed futures when a timeout accurs. (cherry picked from commit f9aeca2085464838f04bf13f816a1f861d43541f) Co-authored-by: Elvis Pranskevichus <elvis at magic.io> * Update asyncio-task.rst files: A Misc/NEWS.d/next/Documentation/2018-05-29-16-02-31.bpo-23859.E5gba1.rst M Doc/library/asyncio-task.rst diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index 3121b4718332..2b480d4be3fb 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -768,6 +768,9 @@ Task functions | | futures finish or are cancelled. | +-----------------------------+----------------------------------------+ + Unlike :func:`~asyncio.wait_for`, ``wait()`` will not cancel the futures + when a timeout occurs. + This function is a :ref:`coroutine <coroutine>`. Usage:: diff --git a/Misc/NEWS.d/next/Documentation/2018-05-29-16-02-31.bpo-23859.E5gba1.rst b/Misc/NEWS.d/next/Documentation/2018-05-29-16-02-31.bpo-23859.E5gba1.rst new file mode 100644 index 000000000000..b372faa5eb97 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2018-05-29-16-02-31.bpo-23859.E5gba1.rst @@ -0,0 +1 @@ +Document that `asyncio.wait()` does not cancel its futures on timeout. From webhook-mailer at python.org Tue May 29 22:00:37 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Wed, 30 May 2018 02:00:37 -0000 Subject: [Python-checkins] Revert "A better fix for asyncio test_stdin_broken_pipe (GH-7221)" (GH-7235) Message-ID: <mailman.87.1527645638.2800.python-checkins@python.org> https://github.com/python/cpython/commit/bb9474f1fb2fc7c7ed9f826b78262d6a12b5f9e8 commit: bb9474f1fb2fc7c7ed9f826b78262d6a12b5f9e8 branch: master author: Yury Selivanov <yury at magic.io> committer: GitHub <noreply at github.com> date: 2018-05-29T22:00:31-04:00 summary: Revert "A better fix for asyncio test_stdin_broken_pipe (GH-7221)" (GH-7235) This reverts commit ad74d50517c069359578014bb32e660828d68332. Turns out it's not a good fix -- Travis has just crashed on this test. files: M Lib/test/test_asyncio/test_subprocess.py diff --git a/Lib/test/test_asyncio/test_subprocess.py b/Lib/test/test_asyncio/test_subprocess.py index 01583376e571..235813aa977c 100644 --- a/Lib/test/test_asyncio/test_subprocess.py +++ b/Lib/test/test_asyncio/test_subprocess.py @@ -218,10 +218,8 @@ def prepare_broken_pipe_test(self): # the program ends before the stdin can be feeded create = asyncio.create_subprocess_exec( - sys.executable, - '-c', 'print("hello", flush=True)', + sys.executable, '-c', 'pass', stdin=subprocess.PIPE, - stdout=subprocess.PIPE, loop=self.loop) proc = self.loop.run_until_complete(create) return (proc, large_data) @@ -230,7 +228,7 @@ def test_stdin_broken_pipe(self): proc, large_data = self.prepare_broken_pipe_test() async def write_stdin(proc, data): - await proc.stdout.readline() + await asyncio.sleep(0.5, loop=self.loop) proc.stdin.write(data) await proc.stdin.drain() From webhook-mailer at python.org Wed May 30 03:15:16 2018 From: webhook-mailer at python.org (Andrew Svetlov) Date: Wed, 30 May 2018 07:15:16 -0000 Subject: [Python-checkins] bpo-33238: Add InvalidStateError to concurrent.futures. (GH-7056) Message-ID: <mailman.88.1527664520.2800.python-checkins@python.org> https://github.com/python/cpython/commit/0a28c0d12ee7201de039ced4d815f57f1f8fd48c commit: 0a28c0d12ee7201de039ced4d815f57f1f8fd48c branch: master author: jhaydaman <33549221+jhaydaman at users.noreply.github.com> committer: Andrew Svetlov <andrew.svetlov at gmail.com> date: 2018-05-30T10:15:06+03:00 summary: bpo-33238: Add InvalidStateError to concurrent.futures. (GH-7056) Future.set_result and Future.set_exception now raise InvalidStateError if the futures are not pending or running. This mirrors the behavior of asyncio.Future, and prevents AssertionErrors in asyncio.wrap_future when set_result is called multiple times. files: A Misc/NEWS.d/next/Library/2018-05-24-09-15-52.bpo-33238.ooDfoo.rst M Doc/library/concurrent.futures.rst M Lib/asyncio/base_futures.py M Lib/concurrent/futures/__init__.py M Lib/concurrent/futures/_base.py M Lib/test/test_concurrent_futures.py diff --git a/Doc/library/concurrent.futures.rst b/Doc/library/concurrent.futures.rst index 707d24dc2529..6934acc7f88e 100644 --- a/Doc/library/concurrent.futures.rst +++ b/Doc/library/concurrent.futures.rst @@ -380,6 +380,11 @@ The :class:`Future` class encapsulates the asynchronous execution of a callable. This method should only be used by :class:`Executor` implementations and unit tests. + .. versionchanged:: 3.8 + This method raises + :exc:`concurrent.futures.InvalidStateError` if the :class:`Future` is + already done. + .. method:: set_exception(exception) Sets the result of the work associated with the :class:`Future` to the @@ -388,6 +393,10 @@ The :class:`Future` class encapsulates the asynchronous execution of a callable. This method should only be used by :class:`Executor` implementations and unit tests. + .. versionchanged:: 3.8 + This method raises + :exc:`concurrent.futures.InvalidStateError` if the :class:`Future` is + already done. Module Functions ---------------- @@ -466,6 +475,13 @@ Exception classes .. versionadded:: 3.7 +.. exception:: InvalidStateError + + Raised when an operation is performed on a future that is not allowed + in the current state. + + .. versionadded:: 3.8 + .. currentmodule:: concurrent.futures.thread .. exception:: BrokenThreadPool diff --git a/Lib/asyncio/base_futures.py b/Lib/asyncio/base_futures.py index 5182884e16d6..bd65beec553c 100644 --- a/Lib/asyncio/base_futures.py +++ b/Lib/asyncio/base_futures.py @@ -1,17 +1,13 @@ __all__ = () -import concurrent.futures._base +import concurrent.futures import reprlib from . import format_helpers -Error = concurrent.futures._base.Error CancelledError = concurrent.futures.CancelledError TimeoutError = concurrent.futures.TimeoutError - - -class InvalidStateError(Error): - """The operation is not allowed in this state.""" +InvalidStateError = concurrent.futures.InvalidStateError # States for Future. diff --git a/Lib/concurrent/futures/__init__.py b/Lib/concurrent/futures/__init__.py index 8434fcf4b5ea..d746aeac50a9 100644 --- a/Lib/concurrent/futures/__init__.py +++ b/Lib/concurrent/futures/__init__.py @@ -10,6 +10,7 @@ ALL_COMPLETED, CancelledError, TimeoutError, + InvalidStateError, BrokenExecutor, Future, Executor, diff --git a/Lib/concurrent/futures/_base.py b/Lib/concurrent/futures/_base.py index 4f22f7ee0e6d..d4416c62450e 100644 --- a/Lib/concurrent/futures/_base.py +++ b/Lib/concurrent/futures/_base.py @@ -53,6 +53,10 @@ class TimeoutError(Error): """The operation exceeded the given deadline.""" pass +class InvalidStateError(Error): + """The operation is not allowed in this state.""" + pass + class _Waiter(object): """Provides the event that wait() and as_completed() block on.""" def __init__(self): @@ -513,6 +517,8 @@ def set_result(self, result): Should only be used by Executor implementations and unit tests. """ with self._condition: + if self._state in {CANCELLED, CANCELLED_AND_NOTIFIED, FINISHED}: + raise InvalidStateError('{}: {!r}'.format(self._state, self)) self._result = result self._state = FINISHED for waiter in self._waiters: @@ -526,6 +532,8 @@ def set_exception(self, exception): Should only be used by Executor implementations and unit tests. """ with self._condition: + if self._state in {CANCELLED, CANCELLED_AND_NOTIFIED, FINISHED}: + raise InvalidStateError('{}: {!r}'.format(self._state, self)) self._exception = exception self._state = FINISHED for waiter in self._waiters: diff --git a/Lib/test/test_concurrent_futures.py b/Lib/test/test_concurrent_futures.py index b258a0eafde6..f2c28ac12b1d 100644 --- a/Lib/test/test_concurrent_futures.py +++ b/Lib/test/test_concurrent_futures.py @@ -1206,6 +1206,34 @@ def notification(): self.assertTrue(isinstance(f1.exception(timeout=5), OSError)) t.join() + def test_multiple_set_result(self): + f = create_future(state=PENDING) + f.set_result(1) + + with self.assertRaisesRegex( + futures.InvalidStateError, + 'FINISHED: <Future at 0x[0-9a-f]+ ' + 'state=finished returned int>' + ): + f.set_result(2) + + self.assertTrue(f.done()) + self.assertEqual(f.result(), 1) + + def test_multiple_set_exception(self): + f = create_future(state=PENDING) + e = ValueError() + f.set_exception(e) + + with self.assertRaisesRegex( + futures.InvalidStateError, + 'FINISHED: <Future at 0x[0-9a-f]+ ' + 'state=finished raised ValueError>' + ): + f.set_exception(Exception()) + + self.assertEqual(f.exception(), e) + @test.support.reap_threads def test_main(): diff --git a/Misc/NEWS.d/next/Library/2018-05-24-09-15-52.bpo-33238.ooDfoo.rst b/Misc/NEWS.d/next/Library/2018-05-24-09-15-52.bpo-33238.ooDfoo.rst new file mode 100644 index 000000000000..b03ab1068889 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-05-24-09-15-52.bpo-33238.ooDfoo.rst @@ -0,0 +1,4 @@ +Add ``InvalidStateError`` to :mod:`concurrent.futures`. +``Future.set_result`` and ``Future.set_exception`` now raise +``InvalidStateError`` if the futures are not pending or running. Patch by +Jason Haydaman. From webhook-mailer at python.org Wed May 30 03:46:05 2018 From: webhook-mailer at python.org (Petr Viktorin) Date: Wed, 30 May 2018 07:46:05 -0000 Subject: [Python-checkins] Improve ensurepip's --help (GH-4686) Message-ID: <mailman.89.1527666366.2800.python-checkins@python.org> https://github.com/python/cpython/commit/e9537ad6a128924dd610bea2268065500c174181 commit: e9537ad6a128924dd610bea2268065500c174181 branch: master author: Wieland Hoffmann <mineo at users.noreply.github.com> committer: Petr Viktorin <encukou at gmail.com> date: 2018-05-30T09:45:55+02:00 summary: Improve ensurepip's --help (GH-4686) * Add a space to ensurepip's --altinstall option * Add periods to the arguments of ensurepip that didn't have it This makes --help for all optional arguments consistent and also makes it consistent with pip --help. files: M Lib/ensurepip/__init__.py diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py index 8dc2354ce287..4748ba4efc4d 100644 --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -182,15 +182,15 @@ def _main(argv=None): "--altinstall", action="store_true", default=False, - help=("Make an alternate install, installing only the X.Y versioned" - "scripts (Default: pipX, pipX.Y, easy_install-X.Y)"), + help=("Make an alternate install, installing only the X.Y versioned " + "scripts (Default: pipX, pipX.Y, easy_install-X.Y)."), ) parser.add_argument( "--default-pip", action="store_true", default=False, help=("Make a default pip install, installing the unqualified pip " - "and easy_install in addition to the versioned scripts"), + "and easy_install in addition to the versioned scripts."), ) args = parser.parse_args(argv) From webhook-mailer at python.org Wed May 30 03:56:19 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Wed, 30 May 2018 07:56:19 -0000 Subject: [Python-checkins] bpo-33691: Add _PyAST_GetDocString(). (GH-7236) Message-ID: <mailman.90.1527666982.2800.python-checkins@python.org> https://github.com/python/cpython/commit/143ce5c6db77a0b9d451b8463dee6752358a9ea4 commit: 143ce5c6db77a0b9d451b8463dee6752358a9ea4 branch: master author: Serhiy Storchaka <storchaka at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-30T10:56:16+03:00 summary: bpo-33691: Add _PyAST_GetDocString(). (GH-7236) files: M Include/ast.h M Python/ast.c M Python/ast_opt.c M Python/compile.c M Python/future.c diff --git a/Include/ast.h b/Include/ast.h index 5bc2b05b3e94..c824554cf492 100644 --- a/Include/ast.h +++ b/Include/ast.h @@ -21,6 +21,11 @@ PyAPI_FUNC(mod_ty) PyAST_FromNodeObject( /* _PyAST_ExprAsUnicode is defined in ast_unparse.c */ PyAPI_FUNC(PyObject *) _PyAST_ExprAsUnicode(expr_ty); +/* Return the borrowed reference to the first literal string in the + sequence of statemnts or NULL if it doesn't start from a literal string. + Doesn't set exception. */ +PyAPI_FUNC(PyObject *) _PyAST_GetDocString(asdl_seq *); + #endif /* !Py_LIMITED_API */ #ifdef __cplusplus diff --git a/Python/ast.c b/Python/ast.c index 43bd786015a7..3b4cd162fcce 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -5260,3 +5260,23 @@ parsestrplus(struct compiling *c, const node *n) FstringParser_Dealloc(&state); return NULL; } + +PyObject * +_PyAST_GetDocString(asdl_seq *body) +{ + if (!asdl_seq_LEN(body)) { + return NULL; + } + stmt_ty st = (stmt_ty)asdl_seq_GET(body, 0); + if (st->kind != Expr_kind) { + return NULL; + } + expr_ty e = st->v.Expr.value; + if (e->kind == Str_kind) { + return e->v.Str.s; + } + if (e->kind == Constant_kind && PyUnicode_CheckExact(e->v.Constant.value)) { + return e->v.Constant.value; + } + return NULL; +} diff --git a/Python/ast_opt.c b/Python/ast_opt.c index a998d1fb6014..5e57638e3d01 100644 --- a/Python/ast_opt.c +++ b/Python/ast_opt.c @@ -1,6 +1,8 @@ /* AST Optimizer */ #include "Python.h" #include "Python-ast.h" +#include "node.h" +#include "ast.h" /* TODO: is_const and get_const_value are copied from Python/compile.c. @@ -467,37 +469,19 @@ static int astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, int opti } \ } -static int -isdocstring(stmt_ty s) -{ - if (s->kind != Expr_kind) - return 0; - if (s->v.Expr.value->kind == Str_kind) - return 1; - if (s->v.Expr.value->kind == Constant_kind) - return PyUnicode_CheckExact(s->v.Expr.value->v.Constant.value); - return 0; -} - static int astfold_body(asdl_seq *stmts, PyArena *ctx_, int optimize_) { - if (!asdl_seq_LEN(stmts)) { - return 1; - } - int docstring = isdocstring((stmt_ty)asdl_seq_GET(stmts, 0)); + int docstring = _PyAST_GetDocString(stmts) != NULL; CALL_SEQ(astfold_stmt, stmt_ty, stmts); - if (docstring) { - return 1; - } - stmt_ty st = (stmt_ty)asdl_seq_GET(stmts, 0); - if (isdocstring(st)) { + if (!docstring && _PyAST_GetDocString(stmts) != NULL) { + stmt_ty st = (stmt_ty)asdl_seq_GET(stmts, 0); asdl_seq *values = _Py_asdl_seq_new(1, ctx_); if (!values) { return 0; } asdl_seq_SET(values, 0, st->v.Expr.value); - expr_ty expr = _Py_JoinedStr(values, st->lineno, st->col_offset, ctx_); + expr_ty expr = JoinedStr(values, st->lineno, st->col_offset, ctx_); if (!expr) { return 0; } diff --git a/Python/compile.c b/Python/compile.c index 42ae5082593c..3528670ef675 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1392,18 +1392,6 @@ compiler_addop_j(struct compiler *c, int opcode, basicblock *b, int absolute) } \ } -static int -compiler_isdocstring(stmt_ty s) -{ - if (s->kind != Expr_kind) - return 0; - if (s->v.Expr.value->kind == Str_kind) - return 1; - if (s->v.Expr.value->kind == Constant_kind) - return PyUnicode_CheckExact(s->v.Expr.value->v.Constant.value); - return 0; -} - static int is_const(expr_ty e) { @@ -1603,6 +1591,7 @@ compiler_body(struct compiler *c, asdl_seq *stmts) { int i = 0; stmt_ty st; + PyObject *docstring; /* Set current line number to the line number of first statement. This way line number for SETUP_ANNOTATIONS will always @@ -1619,14 +1608,17 @@ compiler_body(struct compiler *c, asdl_seq *stmts) } if (!asdl_seq_LEN(stmts)) return 1; - st = (stmt_ty)asdl_seq_GET(stmts, 0); /* if not -OO mode, set docstring */ - if (compiler_isdocstring(st) && c->c_optimize < 2) { - /* don't generate docstrings if -OO */ - i = 1; - VISIT(c, expr, st->v.Expr.value); - if (!compiler_nameop(c, __doc__, Store)) - return 0; + if (c->c_optimize < 2) { + docstring = _PyAST_GetDocString(stmts); + if (docstring) { + i = 1; + st = (stmt_ty)asdl_seq_GET(stmts, 0); + assert(st->kind == Expr_kind); + VISIT(c, expr, st->v.Expr.value); + if (!compiler_nameop(c, __doc__, Store)) + return 0; + } } for (; i < asdl_seq_LEN(stmts); i++) VISIT(c, stmt, (stmt_ty)asdl_seq_GET(stmts, i)); @@ -1979,15 +1971,13 @@ static int compiler_function(struct compiler *c, stmt_ty s, int is_async) { PyCodeObject *co; - PyObject *qualname, *first_const = Py_None; + PyObject *qualname, *docstring = NULL; arguments_ty args; expr_ty returns; identifier name; asdl_seq* decos; asdl_seq *body; - stmt_ty st; Py_ssize_t i, funcflags; - int docstring; int annotations; int scope_type; @@ -2034,15 +2024,10 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async) } /* if not -OO mode, add docstring */ - st = (stmt_ty)asdl_seq_GET(body, 0); - docstring = compiler_isdocstring(st); - if (docstring && c->c_optimize < 2) { - if (st->v.Expr.value->kind == Constant_kind) - first_const = st->v.Expr.value->v.Constant.value; - else - first_const = st->v.Expr.value->v.Str.s; + if (c->c_optimize < 2) { + docstring = _PyAST_GetDocString(body); } - if (compiler_add_const(c, first_const) < 0) { + if (compiler_add_const(c, docstring ? docstring : Py_None) < 0) { compiler_exit_scope(c); return 0; } diff --git a/Python/future.c b/Python/future.c index 03a97c865a82..4ea6827723bf 100644 --- a/Python/future.c +++ b/Python/future.c @@ -5,6 +5,7 @@ #include "graminit.h" #include "code.h" #include "symtable.h" +#include "ast.h" #define UNDEFINED_FUTURE_FEATURE "future feature %.100s is not defined" #define ERR_LATE_FUTURE \ @@ -63,7 +64,6 @@ static int future_parse(PyFutureFeatures *ff, mod_ty mod, PyObject *filename) { int i, done = 0, prev_line = 0; - stmt_ty first; if (!(mod->kind == Module_kind || mod->kind == Interactive_kind)) return 1; @@ -80,11 +80,7 @@ future_parse(PyFutureFeatures *ff, mod_ty mod, PyObject *filename) */ i = 0; - first = (stmt_ty)asdl_seq_GET(mod->v.Module.body, i); - if (first->kind == Expr_kind - && (first->v.Expr.value->kind == Str_kind - || (first->v.Expr.value->kind == Constant_kind - && PyUnicode_CheckExact(first->v.Expr.value->v.Constant.value)))) + if (_PyAST_GetDocString(mod->v.Module.body) != NULL) i++; for (; i < asdl_seq_LEN(mod->v.Module.body); i++) { From webhook-mailer at python.org Wed May 30 04:34:42 2018 From: webhook-mailer at python.org (Petr Viktorin) Date: Wed, 30 May 2018 08:34:42 -0000 Subject: [Python-checkins] Improve ensurepip's --help (GH-4686) (GH-7238) Message-ID: <mailman.91.1527669283.2800.python-checkins@python.org> https://github.com/python/cpython/commit/d9b118284c629cba27fae7b4362933967a4715af commit: d9b118284c629cba27fae7b4362933967a4715af branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Petr Viktorin <encukou at gmail.com> date: 2018-05-30T10:34:32+02:00 summary: Improve ensurepip's --help (GH-4686) (GH-7238) * Add a space to ensurepip's --altinstall option * Add periods to the arguments of ensurepip that didn't have it This makes --help for all optional arguments consistent and also makes it consistent with pip --help. (cherry picked from commit e9537ad6a128924dd610bea2268065500c174181) Co-authored-by: Wieland Hoffmann <mineo at users.noreply.github.com> files: M Lib/ensurepip/__init__.py diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py index 8dc2354ce287..4748ba4efc4d 100644 --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -182,15 +182,15 @@ def _main(argv=None): "--altinstall", action="store_true", default=False, - help=("Make an alternate install, installing only the X.Y versioned" - "scripts (Default: pipX, pipX.Y, easy_install-X.Y)"), + help=("Make an alternate install, installing only the X.Y versioned " + "scripts (Default: pipX, pipX.Y, easy_install-X.Y)."), ) parser.add_argument( "--default-pip", action="store_true", default=False, help=("Make a default pip install, installing the unqualified pip " - "and easy_install in addition to the versioned scripts"), + "and easy_install in addition to the versioned scripts."), ) args = parser.parse_args(argv) From solipsis at pitrou.net Wed May 30 05:16:32 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 30 May 2018 09:16:32 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=1 Message-ID: <20180530091632.1.BB7A4BAF09FF2734@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_asyncio leaked [0, 3, 0] memory blocks, sum=3 test_collections leaked [-7, 8, -7] memory blocks, sum=-6 test_functools leaked [0, 3, 1] memory blocks, sum=4 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogSZBIkg', '--timeout', '7200'] From webhook-mailer at python.org Wed May 30 06:36:20 2018 From: webhook-mailer at python.org (Petr Viktorin) Date: Wed, 30 May 2018 10:36:20 -0000 Subject: [Python-checkins] [2.7] Improve ensurepip's --help (GH-4686) (GH-7240) Message-ID: <mailman.92.1527676582.2800.python-checkins@python.org> https://github.com/python/cpython/commit/f3d269a366d6c6cf07561d3495e74be5a98de27c commit: f3d269a366d6c6cf07561d3495e74be5a98de27c branch: 2.7 author: Petr Viktorin <encukou at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-30T12:36:17+02:00 summary: [2.7] Improve ensurepip's --help (GH-4686) (GH-7240) * Add a space to ensurepip's --altinstall option * Add periods to the arguments of ensurepip that didn't have it This makes --help for all optional arguments consistent and also makes it consistent with pip --help.. (cherry picked from commit e9537ad6a128924dd610bea2268065500c174181) Co-authored-by: Wieland Hoffmann <mineo at users.noreply.github.com> files: M Lib/ensurepip/__init__.py diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py index 49d74cda436b..3c679e596874 100644 --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -190,8 +190,8 @@ def _main(argv=None): "--altinstall", action="store_true", default=False, - help=("Make an alternate install, installing only the X.Y versioned" - "scripts (Default: pipX, pipX.Y, easy_install-X.Y)"), + help=("Make an alternate install, installing only the X.Y versioned " + "scripts (Default: pipX, pipX.Y, easy_install-X.Y)."), ) parser.add_argument( "--default-pip", From webhook-mailer at python.org Wed May 30 07:56:24 2018 From: webhook-mailer at python.org (Petr Viktorin) Date: Wed, 30 May 2018 11:56:24 -0000 Subject: [Python-checkins] Improve ensurepip's --help (GH-4686) (GH-7239) Message-ID: <mailman.93.1527681386.2800.python-checkins@python.org> https://github.com/python/cpython/commit/be325e6132c9198f7b8e9c7da2dd0017a33212cc commit: be325e6132c9198f7b8e9c7da2dd0017a33212cc branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Petr Viktorin <encukou at gmail.com> date: 2018-05-30T13:56:19+02:00 summary: Improve ensurepip's --help (GH-4686) (GH-7239) * Add a space to ensurepip's --altinstall option * Add periods to the arguments of ensurepip that didn't have it This makes --help for all optional arguments consistent and also makes it consistent with pip --help. (cherry picked from commit e9537ad6a128924dd610bea2268065500c174181) Co-authored-by: Wieland Hoffmann <mineo at users.noreply.github.com> files: M Lib/ensurepip/__init__.py diff --git a/Lib/ensurepip/__init__.py b/Lib/ensurepip/__init__.py index 8dc2354ce287..4748ba4efc4d 100644 --- a/Lib/ensurepip/__init__.py +++ b/Lib/ensurepip/__init__.py @@ -182,15 +182,15 @@ def _main(argv=None): "--altinstall", action="store_true", default=False, - help=("Make an alternate install, installing only the X.Y versioned" - "scripts (Default: pipX, pipX.Y, easy_install-X.Y)"), + help=("Make an alternate install, installing only the X.Y versioned " + "scripts (Default: pipX, pipX.Y, easy_install-X.Y)."), ) parser.add_argument( "--default-pip", action="store_true", default=False, help=("Make a default pip install, installing the unqualified pip " - "and easy_install in addition to the versioned scripts"), + "and easy_install in addition to the versioned scripts."), ) args = parser.parse_args(argv) From webhook-mailer at python.org Wed May 30 10:49:10 2018 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 30 May 2018 14:49:10 -0000 Subject: [Python-checkins] bpo-33692: pythoninfo detect libedit on Python 3.6 (GH-7244) Message-ID: <mailman.94.1527691754.2800.python-checkins@python.org> https://github.com/python/cpython/commit/f7a19c28bda7b0ed3a440db80202013a86af6850 commit: f7a19c28bda7b0ed3a440db80202013a86af6850 branch: 3.6 author: Victor Stinner <vstinner at redhat.com> committer: GitHub <noreply at github.com> date: 2018-05-30T16:49:07+02:00 summary: bpo-33692: pythoninfo detect libedit on Python 3.6 (GH-7244) Check which readline implementation is used based on the readline docstring. files: M Lib/test/pythoninfo.py diff --git a/Lib/test/pythoninfo.py b/Lib/test/pythoninfo.py index f1b02336f7e3..26f493ee29ff 100644 --- a/Lib/test/pythoninfo.py +++ b/Lib/test/pythoninfo.py @@ -275,6 +275,14 @@ def format_attr(attr, value): copy_attributes(info_add, readline, 'readline.%s', attributes, formatter=format_attr) + if not hasattr(readline, "_READLINE_LIBRARY_VERSION"): + # _READLINE_LIBRARY_VERSION has been added to CPython 3.7 + doc = getattr(readline, '__doc__', '') + if 'libedit readline' in doc: + info_add('readline.library', 'libedit readline') + elif 'GNU readline' in doc: + info_add('readline.library', 'GNU readline') + def collect_gdb(info_add): import subprocess From webhook-mailer at python.org Wed May 30 11:24:44 2018 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 30 May 2018 15:24:44 -0000 Subject: [Python-checkins] bpo-29512: Rename Lib/test/bisect.py to bisect_cmd.py (#7229) Message-ID: <mailman.95.1527693885.2800.python-checkins@python.org> https://github.com/python/cpython/commit/823c295efa4efea93cadc640ed6122cd9d86cec4 commit: 823c295efa4efea93cadc640ed6122cd9d86cec4 branch: 2.7 author: Victor Stinner <vstinner at redhat.com> committer: GitHub <noreply at github.com> date: 2018-05-30T17:24:40+02:00 summary: bpo-29512: Rename Lib/test/bisect.py to bisect_cmd.py (#7229) Rename Lib/test/bisect.py to Lib/test/bisect_cmd.py. The old name was in conflict with Lib/bisect.py, causing test failures, depending how tests were run. For example, "python2.7 Lib/test/test_httpservers.py" imported indirectly Lib/test/bisect.py instead of Lib/bisect.py on "import bisect". files: A Lib/test/bisect_cmd.py A Misc/NEWS.d/next/Tests/2018-05-30-00-39-57.bpo-29512.EHrDzs.rst D Lib/test/bisect.py diff --git a/Lib/test/bisect.py b/Lib/test/bisect_cmd.py similarity index 100% rename from Lib/test/bisect.py rename to Lib/test/bisect_cmd.py diff --git a/Misc/NEWS.d/next/Tests/2018-05-30-00-39-57.bpo-29512.EHrDzs.rst b/Misc/NEWS.d/next/Tests/2018-05-30-00-39-57.bpo-29512.EHrDzs.rst new file mode 100644 index 000000000000..aa5dc64e3b0a --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2018-05-30-00-39-57.bpo-29512.EHrDzs.rst @@ -0,0 +1,3 @@ +Rename Lib/test/bisect.py to Lib/test/bisect_cmd.py. The old name was in +conflict with Lib/bisect.py, causing test failures, depending how tests +were run. From webhook-mailer at python.org Wed May 30 11:41:33 2018 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 30 May 2018 15:41:33 -0000 Subject: [Python-checkins] regrtest: repeat summary after re-run (GH-7159) (GH-7245) Message-ID: <mailman.96.1527694895.2800.python-checkins@python.org> https://github.com/python/cpython/commit/b729af3d9dfdf215556b83488e5585331e69b994 commit: b729af3d9dfdf215556b83488e5585331e69b994 branch: 3.6 author: Victor Stinner <vstinner at redhat.com> committer: GitHub <noreply at github.com> date: 2018-05-30T17:41:30+02:00 summary: regrtest: repeat summary after re-run (GH-7159) (GH-7245) Using -w, when failing tests are re-run in verbose mode, display again the tests results at the end. (cherry picked from commit c6c05d0e69cd5a7d0205019c29a1236b7bf3f5b9) files: M Lib/test/libregrtest/main.py diff --git a/Lib/test/libregrtest/main.py b/Lib/test/libregrtest/main.py index 15e51525c362..0ae40ac84312 100644 --- a/Lib/test/libregrtest/main.py +++ b/Lib/test/libregrtest/main.py @@ -88,6 +88,7 @@ def __init__(self): self.skipped = [] self.resource_denieds = [] self.environment_changed = [] + self.rerun = [] self.interrupted = False # used by --slow @@ -282,8 +283,10 @@ def rerun_failed_tests(self): self.ns.verbose3 = False self.ns.match_tests = None + print() print("Re-running failed tests in verbose mode") - for test in self.bad[:]: + self.rerun = self.bad[:] + for test in self.rerun: print("Re-running test %r in verbose mode" % test, flush=True) try: self.ns.verbose = True @@ -301,22 +304,32 @@ def rerun_failed_tests(self): print(count(len(self.bad), 'test'), "failed again:") printlist(self.bad) + self.display_result() + def display_result(self): + # If running the test suite for PGO then no one cares about results. + if self.ns.pgo: + return + + print() + print("== Tests result ==") + if self.interrupted: - # print a newline after ^C print() + # print a newline after ^C print("Test suite interrupted by signal SIGINT.") executed = set(self.good) | set(self.bad) | set(self.skipped) omitted = set(self.selected) - executed print(count(len(omitted), "test"), "omitted:") printlist(omitted) - # If running the test suite for PGO then no one cares about - # results. - if self.ns.pgo: - return + if self.rerun: + print() + print(count(len(self.rerun), "test"), "re-run tests:") + printlist(self.rerun) if self.good and not self.ns.quiet: + print() if (not self.bad and not self.skipped and not self.interrupted From webhook-mailer at python.org Wed May 30 12:08:29 2018 From: webhook-mailer at python.org (Steve Dower) Date: Wed, 30 May 2018 16:08:29 -0000 Subject: [Python-checkins] bpo-33696: Install python-docs-theme even if SPHINXBUILD is defined (GH-7242) Message-ID: <mailman.97.1527696511.2800.python-checkins@python.org> https://github.com/python/cpython/commit/05f1c8902c78dce66aed067444e2b973221bae2b commit: 05f1c8902c78dce66aed067444e2b973221bae2b branch: master author: Andr?s Delfino <adelfino at gmail.com> committer: Steve Dower <steve.dower at microsoft.com> date: 2018-05-30T09:08:25-07:00 summary: bpo-33696: Install python-docs-theme even if SPHINXBUILD is defined (GH-7242) files: M Doc/make.bat diff --git a/Doc/make.bat b/Doc/make.bat index 7ca84979a300..0808e0cd09f5 100644 --- a/Doc/make.bat +++ b/Doc/make.bat @@ -16,15 +16,16 @@ if not defined SPHINXBUILD ( %PYTHON% -m pip install sphinx if errorlevel 1 exit /B ) - %PYTHON% -c "import python_docs_theme" > nul 2> nul - if errorlevel 1 ( - echo Installing python-docs-theme with %PYTHON% - %PYTHON% -m pip install python-docs-theme - if errorlevel 1 exit /B - ) set SPHINXBUILD=%PYTHON% -c "import sphinx, sys; sys.argv[0] = 'sphinx-build'; sys.exit(sphinx.main())" ) +%PYTHON% -c "import python_docs_theme" > nul 2> nul +if errorlevel 1 ( + echo Installing python-docs-theme with %PYTHON% + %PYTHON% -m pip install python-docs-theme + if errorlevel 1 exit /B +) + if not defined BLURB ( %PYTHON% -c "import blurb" > nul 2> nul if errorlevel 1 ( @@ -35,9 +36,6 @@ if not defined BLURB ( set BLURB=%PYTHON% -m blurb ) -if not defined SPHINXBUILD set SPHINXBUILD=sphinx-build -if not defined BLURB set BLURB=blurb - if "%1" NEQ "htmlhelp" goto :skiphhcsearch if exist "%HTMLHELP%" goto :skiphhcsearch From webhook-mailer at python.org Wed May 30 13:32:44 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 30 May 2018 17:32:44 -0000 Subject: [Python-checkins] bpo-33696: Install python-docs-theme even if SPHINXBUILD is defined (GH-7242) Message-ID: <mailman.98.1527701566.2800.python-checkins@python.org> https://github.com/python/cpython/commit/ea1982a475a619500c93bc3d60c6cb63a202b7ed commit: ea1982a475a619500c93bc3d60c6cb63a202b7ed branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-30T10:32:33-07:00 summary: bpo-33696: Install python-docs-theme even if SPHINXBUILD is defined (GH-7242) (cherry picked from commit 05f1c8902c78dce66aed067444e2b973221bae2b) Co-authored-by: Andr?s Delfino <adelfino at gmail.com> files: M Doc/make.bat diff --git a/Doc/make.bat b/Doc/make.bat index 7ca84979a300..0808e0cd09f5 100644 --- a/Doc/make.bat +++ b/Doc/make.bat @@ -16,15 +16,16 @@ if not defined SPHINXBUILD ( %PYTHON% -m pip install sphinx if errorlevel 1 exit /B ) - %PYTHON% -c "import python_docs_theme" > nul 2> nul - if errorlevel 1 ( - echo Installing python-docs-theme with %PYTHON% - %PYTHON% -m pip install python-docs-theme - if errorlevel 1 exit /B - ) set SPHINXBUILD=%PYTHON% -c "import sphinx, sys; sys.argv[0] = 'sphinx-build'; sys.exit(sphinx.main())" ) +%PYTHON% -c "import python_docs_theme" > nul 2> nul +if errorlevel 1 ( + echo Installing python-docs-theme with %PYTHON% + %PYTHON% -m pip install python-docs-theme + if errorlevel 1 exit /B +) + if not defined BLURB ( %PYTHON% -c "import blurb" > nul 2> nul if errorlevel 1 ( @@ -35,9 +36,6 @@ if not defined BLURB ( set BLURB=%PYTHON% -m blurb ) -if not defined SPHINXBUILD set SPHINXBUILD=sphinx-build -if not defined BLURB set BLURB=blurb - if "%1" NEQ "htmlhelp" goto :skiphhcsearch if exist "%HTMLHELP%" goto :skiphhcsearch From webhook-mailer at python.org Wed May 30 13:37:58 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 30 May 2018 17:37:58 -0000 Subject: [Python-checkins] bpo-33696: Install python-docs-theme even if SPHINXBUILD is defined (GH-7242) Message-ID: <mailman.99.1527701879.2800.python-checkins@python.org> https://github.com/python/cpython/commit/7301dd91e8326e9b74932e81f400aaee76d3cda1 commit: 7301dd91e8326e9b74932e81f400aaee76d3cda1 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-30T10:37:52-07:00 summary: bpo-33696: Install python-docs-theme even if SPHINXBUILD is defined (GH-7242) (cherry picked from commit 05f1c8902c78dce66aed067444e2b973221bae2b) Co-authored-by: Andr?s Delfino <adelfino at gmail.com> files: M Doc/make.bat diff --git a/Doc/make.bat b/Doc/make.bat index 7ca84979a300..0808e0cd09f5 100644 --- a/Doc/make.bat +++ b/Doc/make.bat @@ -16,15 +16,16 @@ if not defined SPHINXBUILD ( %PYTHON% -m pip install sphinx if errorlevel 1 exit /B ) - %PYTHON% -c "import python_docs_theme" > nul 2> nul - if errorlevel 1 ( - echo Installing python-docs-theme with %PYTHON% - %PYTHON% -m pip install python-docs-theme - if errorlevel 1 exit /B - ) set SPHINXBUILD=%PYTHON% -c "import sphinx, sys; sys.argv[0] = 'sphinx-build'; sys.exit(sphinx.main())" ) +%PYTHON% -c "import python_docs_theme" > nul 2> nul +if errorlevel 1 ( + echo Installing python-docs-theme with %PYTHON% + %PYTHON% -m pip install python-docs-theme + if errorlevel 1 exit /B +) + if not defined BLURB ( %PYTHON% -c "import blurb" > nul 2> nul if errorlevel 1 ( @@ -35,9 +36,6 @@ if not defined BLURB ( set BLURB=%PYTHON% -m blurb ) -if not defined SPHINXBUILD set SPHINXBUILD=sphinx-build -if not defined BLURB set BLURB=blurb - if "%1" NEQ "htmlhelp" goto :skiphhcsearch if exist "%HTMLHELP%" goto :skiphhcsearch From webhook-mailer at python.org Wed May 30 17:36:15 2018 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 30 May 2018 21:36:15 -0000 Subject: [Python-checkins] bpo-33692: pythoninfo detect libedit on Python 2.7 (#7246) Message-ID: <mailman.100.1527716178.2800.python-checkins@python.org> https://github.com/python/cpython/commit/9994eff17f943fb2c190708b12c96fef9838a425 commit: 9994eff17f943fb2c190708b12c96fef9838a425 branch: 2.7 author: Victor Stinner <vstinner at redhat.com> committer: GitHub <noreply at github.com> date: 2018-05-30T23:36:04+02:00 summary: bpo-33692: pythoninfo detect libedit on Python 2.7 (#7246) Check which readline implementation is used based on the readline docstring. files: M Lib/test/pythoninfo.py diff --git a/Lib/test/pythoninfo.py b/Lib/test/pythoninfo.py index f40ff8d0eba1..92b515803991 100644 --- a/Lib/test/pythoninfo.py +++ b/Lib/test/pythoninfo.py @@ -275,6 +275,14 @@ def format_attr(attr, value): copy_attributes(info_add, readline, 'readline.%s', attributes, formatter=format_attr) + if not hasattr(readline, "_READLINE_LIBRARY_VERSION"): + # _READLINE_LIBRARY_VERSION has been added to CPython 3.7 + doc = getattr(readline, '__doc__', '') + if 'libedit readline' in doc: + info_add('readline.library', 'libedit readline') + elif 'GNU readline' in doc: + info_add('readline.library', 'GNU readline') + def collect_gdb(info_add): import subprocess From webhook-mailer at python.org Wed May 30 18:52:48 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Wed, 30 May 2018 22:52:48 -0000 Subject: [Python-checkins] 3.6 what's new: fix a reference to PEP 528 (#7113) Message-ID: <mailman.101.1527720770.2800.python-checkins@python.org> https://github.com/python/cpython/commit/495e567a2b3bbe3b99f0c253edf12997a9ff4ee1 commit: 495e567a2b3bbe3b99f0c253edf12997a9ff4ee1 branch: master author: Dmitry Shachnev <mitya57 at users.noreply.github.com> committer: Yury Selivanov <yury at magic.io> date: 2018-05-30T18:52:43-04:00 summary: 3.6 what's new: fix a reference to PEP 528 (#7113) files: M Doc/whatsnew/3.6.rst diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst index cb8c53ac3b18..ed489c101c1b 100644 --- a/Doc/whatsnew/3.6.rst +++ b/Doc/whatsnew/3.6.rst @@ -148,7 +148,7 @@ Security improvements: Windows improvements: -* :ref:`PEP 528 <whatsnew36-pep529>` and :ref:`PEP 529 <whatsnew36-pep529>`, +* :ref:`PEP 528 <whatsnew36-pep528>` and :ref:`PEP 529 <whatsnew36-pep529>`, Windows filesystem and console encoding changed to UTF-8. * The ``py.exe`` launcher, when used interactively, no longer prefers From webhook-mailer at python.org Wed May 30 19:00:09 2018 From: webhook-mailer at python.org (Victor Stinner) Date: Wed, 30 May 2018 23:00:09 -0000 Subject: [Python-checkins] bpo-31368: Enhance os.preadv() documentation (GH-7254) Message-ID: <mailman.102.1527721212.2800.python-checkins@python.org> https://github.com/python/cpython/commit/02e2a085dc1740b1cbf4ba2ed77335c84ce8a367 commit: 02e2a085dc1740b1cbf4ba2ed77335c84ce8a367 branch: master author: Pablo Galindo <Pablogsal at gmail.com> committer: Victor Stinner <vstinner at redhat.com> date: 2018-05-31T01:00:04+02:00 summary: bpo-31368: Enhance os.preadv() documentation (GH-7254) files: M Doc/library/os.rst M Doc/whatsnew/3.7.rst diff --git a/Doc/library/os.rst b/Doc/library/os.rst index d5bc612f451c..c64f93211437 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -1082,20 +1082,81 @@ or `the MSDN <https://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx>`_ on Windo .. versionadded:: 3.3 -.. function:: pread(fd, buffersize, offset) +.. function:: pread(fd, n, offset) - Read from a file descriptor, *fd*, at a position of *offset*. It will read up - to *buffersize* number of bytes. The file offset remains unchanged. + Read at most *n* bytes from file descriptor *fd* at a position of *offset*, + leaving the file offset unchanged. + + Return a bytestring containing the bytes read. If the end of the file + referred to by *fd* has been reached, an empty bytes object is returned. Availability: Unix. .. versionadded:: 3.3 +.. function:: preadv(fd, buffers, offset, flags=0) + + Read from a file descriptor *fd* at a position of *offset* into mutable + :term:`bytes-like objects <bytes-like object>` *buffers*, leaving the file + offset unchanged. Transfer data into each buffer until it is full and then + move on to the next buffer in the sequence to hold the rest of the data. + + The flags argument contains a bitwise OR of zero or more of the following + flags: + + - :data:`RWF_HIPRI` + - :data:`RWF_NOWAIT` + + Return the total number of bytes actually read which can be less than the + total capacity of all the objects. + + The operating system may set a limit (:func:`sysconf` value + ``'SC_IOV_MAX'``) on the number of buffers that can be used. + + Combine the functionality of :func:`os.readv` and :func:`os.pread`. + + Availability: Linux 2.6.30 and newer, FreeBSD 6.0 and newer, + OpenBSD 2.7 and newer. Using flags requires Linux 4.6 or newer. + + .. versionadded:: 3.7 + + +.. data:: RWF_NOWAIT + + Do not wait for data which is not immediately available. If this flag is + specified, the system call will return instantly if it would have to read + data from the backing storage or wait for a lock. + + If some data was successfully read, it will return the number of bytes read. + If no bytes were read, it will return ``-1`` and set errno to + :data:`errno.EAGAIN`. + + Availability: Linux 4.14 and newer. + + .. versionadded:: 3.7 + + +.. data:: RWF_HIPRI + + High priority read/write. Allows block-based filesystems to use polling + of the device, which provides lower latency, but may use additional + resources. + + Currently, on Linux, this feature is usable only on a file descriptor opened + using the :data:`O_DIRECT` flag. + + Availability: Linux 4.6 and newer. + + .. versionadded:: 3.7 + + .. function:: pwrite(fd, str, offset) - Write *bytestring* to a file descriptor, *fd*, from *offset*, - leaving the file offset unchanged. + Write the bytestring in *str* to file descriptor *fd* at position of + *offset*, leaving the file offset unchanged. + + Return the number of bytes actually written. Availability: Unix. @@ -1104,54 +1165,57 @@ or `the MSDN <https://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx>`_ on Windo .. function:: pwritev(fd, buffers, offset, flags=0) - Combines the functionality of :func:`os.writev` and :func:`os.pwrite`. It - writes the contents of *buffers* to file descriptor *fd* at offset *offset*. - *buffers* must be a sequence of :term:`bytes-like objects <bytes-like object>`. - Buffers are processed in array order. Entire contents of first buffer is written - before proceeding to second, and so on. The operating system may set a limit - (sysconf() value SC_IOV_MAX) on the number of buffers that can be used. - :func:`~os.pwritev` writes the contents of each object to the file descriptor - and returns the total number of bytes written. + Write the *buffers* contents to file descriptor *fd* at a offset *offset*, + leaving the file offset unchanged. *buffers* must be a sequence of + :term:`bytes-like objects <bytes-like object>`. Buffers are processed in + array order. Entire contents of the first buffer is written before + proceeding to the second, and so on. - The *flags* argument contains a bitwise OR of zero or more of the following + The flags argument contains a bitwise OR of zero or more of the following flags: - - RWF_DSYNC - - RWF_SYNC + - :data:`RWF_DSYNC` + - :data:`RWF_SYNC` - Using non-zero flags requires Linux 4.7 or newer. + Return the total number of bytes actually written. - Availability: Linux (version 2.6.30), FreeBSD 6.0 and newer, - OpenBSD (version 2.7 and newer). + The operating system may set a limit (:func:`sysconf` value + ``'SC_IOV_MAX'``) on the number of buffers that can be used. + + Combine the functionality of :func:`os.writev` and :func:`os.pwrite`. + + Availability: Linux 2.6.30 and newer, FreeBSD 6.0 and newer, + OpenBSD 2.7 and newer. Using flags requires Linux 4.7 or newer. .. versionadded:: 3.7 + .. data:: RWF_DSYNC - Provide a per-write equivalent of the O_DSYNC open(2) flag. This flag - is meaningful only for pwritev2(), and its effect applies only to the - data range written by the system call. + Provide a per-write equivalent of the :data:`O_DSYNC` ``open(2)`` flag. This + flag effect applies only to the data range written by the system call. - Availability: Linux (version 4.7). + Availability: Linux 4.7 and newer. .. versionadded:: 3.7 + .. data:: RWF_SYNC - Provide a per-write equivalent of the O_SYNC open(2) flag. This flag is - meaningful only for pwritev2(), and its effect applies only to the data - range written by the system call. + Provide a per-write equivalent of the :data:`O_SYNC` ``open(2)`` flag. This + flag effect applies only to the data range written by the system call. - Availability: Linux (version 4.7). + Availability: Linux 4.7 and newer. .. versionadded:: 3.7 .. function:: read(fd, n) - Read at most *n* bytes from file descriptor *fd*. Return a bytestring containing the - bytes read. If the end of the file referred to by *fd* has been reached, an - empty bytes object is returned. + Read at most *n* bytes from file descriptor *fd*. + + Return a bytestring containing the bytes read. If the end of the file + referred to by *fd* has been reached, an empty bytes object is returned. .. note:: @@ -1230,66 +1294,19 @@ or `the MSDN <https://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx>`_ on Windo .. function:: readv(fd, buffers) Read from a file descriptor *fd* into a number of mutable :term:`bytes-like - objects <bytes-like object>` *buffers*. :func:`~os.readv` will transfer data - into each buffer until it is full and then move on to the next buffer in the - sequence to hold the rest of the data. :func:`~os.readv` returns the total - number of bytes read (which may be less than the total capacity of all the - objects). + objects <bytes-like object>` *buffers*. Transfer data into each buffer until + it is full and then move on to the next buffer in the sequence to hold the + rest of the data. - Availability: Unix. - - .. versionadded:: 3.3 + Return the total number of bytes actually read which can be less than the + total capacity of all the objects. + The operating system may set a limit (:func:`sysconf` value + ``'SC_IOV_MAX'``) on the number of buffers that can be used. -.. function:: preadv(fd, buffers, offset, flags=0) - - Combines the functionality of :func:`os.readv` and :func:`os.pread`. It - reads from a file descriptor *fd* into a number of mutable :term:`bytes-like - objects <bytes-like object>` *buffers*. As :func:`os.readv`, it will transfer - data into each buffer until it is full and then move on to the next buffer in - the sequence to hold the rest of the data. Its fourth argument, *offset*, - specifies the file offset at which the input operation is to be performed. - :func:`~os.preadv` return the total number of bytes read (which can be less than - the total capacity of all the objects). - - The flags argument contains a bitwise OR of zero or more of the following - flags: - - - RWF_HIPRI - - RWF_NOWAIT - - Using non-zero flags requires Linux 4.6 or newer. - - Availability: Linux (version 2.6.30), FreeBSD 6.0 and newer, - OpenBSD (version 2.7 and newer). - - .. versionadded:: 3.7 - - -.. data:: RWF_HIPRI - - High priority read/write. Allows block-based filesystems to use polling - of the device, which provides lower latency, but may use additional - resources. (Currently, this feature is usable only on a file descriptor - opened using the O_DIRECT flag.) - - Availability: Linux (version 4.6). - - .. versionadded:: 3.7 - - -.. data:: RWF_NOWAIT - - Do not wait for data which is not immediately available. If this flag - is specified, the preadv2() system call will return instantly - if it would have to read data from the backing storage or wait for a lock. - If some data was successfully read, it will return the number of bytes - read. If no bytes were read, it will return -1 and set errno to EAGAIN. - Currently, this flag is meaningful only for preadv2(). - - Availability: Linux (version 4.14). + Availability: Unix. - .. versionadded:: 3.7 + .. versionadded:: 3.3 .. function:: tcgetpgrp(fd) @@ -1319,8 +1336,9 @@ or `the MSDN <https://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx>`_ on Windo .. function:: write(fd, str) - Write the bytestring in *str* to file descriptor *fd*. Return the number of - bytes actually written. + Write the bytestring in *str* to file descriptor *fd*. + + Return the number of bytes actually written. .. note:: @@ -1338,14 +1356,15 @@ or `the MSDN <https://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx>`_ on Windo .. function:: writev(fd, buffers) - Write the contents of *buffers* to file descriptor *fd*. *buffers* must be a - sequence of :term:`bytes-like objects <bytes-like object>`. Buffers are - processed in array order. Entire contents of first buffer is written before - proceeding to second, and so on. The operating system may set a limit - (sysconf() value SC_IOV_MAX) on the number of buffers that can be used. + Write the contents of *buffers* to file descriptor *fd*. *buffers* must be + a sequence of :term:`bytes-like objects <bytes-like object>`. Buffers are + processed in array order. Entire contents of the first buffer is written + before proceeding to the second, and so on. + + Returns the total number of bytes actually written. - :func:`~os.writev` writes the contents of each object to the file descriptor - and returns the total number of bytes written. + The operating system may set a limit (:func:`sysconf` value + ``'SC_IOV_MAX'``) on the number of buffers that can be used. Availability: Unix. diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 2471989ec7b9..9989eaf5eac5 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -1091,9 +1091,10 @@ The new :func:`~os.register_at_fork` function allows registering Python callbacks to be executed at process fork. (Contributed by Antoine Pitrou in :issue:`16500`.) -Exposed the *preadv*, *preadv2*, *pwritev* and *pwritev2* system calls through -the new :func:`~os.preadv` and :func:`~os.pwritev` functions. -(Contributed by Pablo Galindo in :issue:`31368`.) +Added :func:`os.preadv` (combine the functionality of :func:`os.readv` and +:func:`os.pread`) and :func:`os.pwritev` functions (combine the functionality +of :func:`os.writev` and :func:`os.pwrite`). (Contributed by Pablo Galindo in +:issue:`31368`.) The mode argument of :func:`os.makedirs` no longer affects the file permission bits of newly-created intermediate-level directories. From webhook-mailer at python.org Wed May 30 19:09:03 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Wed, 30 May 2018 23:09:03 -0000 Subject: [Python-checkins] 3.6 what's new: fix a reference to PEP 528 (GH-7113) (#7256) Message-ID: <mailman.103.1527721744.2800.python-checkins@python.org> https://github.com/python/cpython/commit/5191892c29e1d84c9135f15e7620b89c75e03d56 commit: 5191892c29e1d84c9135f15e7620b89c75e03d56 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Yury Selivanov <yury at magic.io> date: 2018-05-30T19:09:00-04:00 summary: 3.6 what's new: fix a reference to PEP 528 (GH-7113) (#7256) (cherry picked from commit 495e567a2b3bbe3b99f0c253edf12997a9ff4ee1) Co-authored-by: Dmitry Shachnev <mitya57 at users.noreply.github.com> files: M Doc/whatsnew/3.6.rst diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst index cb8c53ac3b18..ed489c101c1b 100644 --- a/Doc/whatsnew/3.6.rst +++ b/Doc/whatsnew/3.6.rst @@ -148,7 +148,7 @@ Security improvements: Windows improvements: -* :ref:`PEP 528 <whatsnew36-pep529>` and :ref:`PEP 529 <whatsnew36-pep529>`, +* :ref:`PEP 528 <whatsnew36-pep528>` and :ref:`PEP 529 <whatsnew36-pep529>`, Windows filesystem and console encoding changed to UTF-8. * The ``py.exe`` launcher, when used interactively, no longer prefers From webhook-mailer at python.org Wed May 30 19:22:16 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 30 May 2018 23:22:16 -0000 Subject: [Python-checkins] bpo-31368: Enhance os.preadv() documentation (GH-7254) Message-ID: <mailman.104.1527722540.2800.python-checkins@python.org> https://github.com/python/cpython/commit/0e823c6efa4729f3cd19f96af82c673b10cd3ee2 commit: 0e823c6efa4729f3cd19f96af82c673b10cd3ee2 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-30T16:22:13-07:00 summary: bpo-31368: Enhance os.preadv() documentation (GH-7254) (cherry picked from commit 02e2a085dc1740b1cbf4ba2ed77335c84ce8a367) Co-authored-by: Pablo Galindo <Pablogsal at gmail.com> files: M Doc/library/os.rst M Doc/whatsnew/3.7.rst diff --git a/Doc/library/os.rst b/Doc/library/os.rst index 60ab94f4769e..d937451be51e 100644 --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -1082,20 +1082,81 @@ or `the MSDN <https://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx>`_ on Windo .. versionadded:: 3.3 -.. function:: pread(fd, buffersize, offset) +.. function:: pread(fd, n, offset) - Read from a file descriptor, *fd*, at a position of *offset*. It will read up - to *buffersize* number of bytes. The file offset remains unchanged. + Read at most *n* bytes from file descriptor *fd* at a position of *offset*, + leaving the file offset unchanged. + + Return a bytestring containing the bytes read. If the end of the file + referred to by *fd* has been reached, an empty bytes object is returned. Availability: Unix. .. versionadded:: 3.3 +.. function:: preadv(fd, buffers, offset, flags=0) + + Read from a file descriptor *fd* at a position of *offset* into mutable + :term:`bytes-like objects <bytes-like object>` *buffers*, leaving the file + offset unchanged. Transfer data into each buffer until it is full and then + move on to the next buffer in the sequence to hold the rest of the data. + + The flags argument contains a bitwise OR of zero or more of the following + flags: + + - :data:`RWF_HIPRI` + - :data:`RWF_NOWAIT` + + Return the total number of bytes actually read which can be less than the + total capacity of all the objects. + + The operating system may set a limit (:func:`sysconf` value + ``'SC_IOV_MAX'``) on the number of buffers that can be used. + + Combine the functionality of :func:`os.readv` and :func:`os.pread`. + + Availability: Linux 2.6.30 and newer, FreeBSD 6.0 and newer, + OpenBSD 2.7 and newer. Using flags requires Linux 4.6 or newer. + + .. versionadded:: 3.7 + + +.. data:: RWF_NOWAIT + + Do not wait for data which is not immediately available. If this flag is + specified, the system call will return instantly if it would have to read + data from the backing storage or wait for a lock. + + If some data was successfully read, it will return the number of bytes read. + If no bytes were read, it will return ``-1`` and set errno to + :data:`errno.EAGAIN`. + + Availability: Linux 4.14 and newer. + + .. versionadded:: 3.7 + + +.. data:: RWF_HIPRI + + High priority read/write. Allows block-based filesystems to use polling + of the device, which provides lower latency, but may use additional + resources. + + Currently, on Linux, this feature is usable only on a file descriptor opened + using the :data:`O_DIRECT` flag. + + Availability: Linux 4.6 and newer. + + .. versionadded:: 3.7 + + .. function:: pwrite(fd, str, offset) - Write *bytestring* to a file descriptor, *fd*, from *offset*, - leaving the file offset unchanged. + Write the bytestring in *str* to file descriptor *fd* at position of + *offset*, leaving the file offset unchanged. + + Return the number of bytes actually written. Availability: Unix. @@ -1104,54 +1165,57 @@ or `the MSDN <https://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx>`_ on Windo .. function:: pwritev(fd, buffers, offset, flags=0) - Combines the functionality of :func:`os.writev` and :func:`os.pwrite`. It - writes the contents of *buffers* to file descriptor *fd* at offset *offset*. - *buffers* must be a sequence of :term:`bytes-like objects <bytes-like object>`. - Buffers are processed in array order. Entire contents of first buffer is written - before proceeding to second, and so on. The operating system may set a limit - (sysconf() value SC_IOV_MAX) on the number of buffers that can be used. - :func:`~os.pwritev` writes the contents of each object to the file descriptor - and returns the total number of bytes written. + Write the *buffers* contents to file descriptor *fd* at a offset *offset*, + leaving the file offset unchanged. *buffers* must be a sequence of + :term:`bytes-like objects <bytes-like object>`. Buffers are processed in + array order. Entire contents of the first buffer is written before + proceeding to the second, and so on. - The *flags* argument contains a bitwise OR of zero or more of the following + The flags argument contains a bitwise OR of zero or more of the following flags: - - RWF_DSYNC - - RWF_SYNC + - :data:`RWF_DSYNC` + - :data:`RWF_SYNC` - Using non-zero flags requires Linux 4.7 or newer. + Return the total number of bytes actually written. - Availability: Linux (version 2.6.30), FreeBSD 6.0 and newer, - OpenBSD (version 2.7 and newer). + The operating system may set a limit (:func:`sysconf` value + ``'SC_IOV_MAX'``) on the number of buffers that can be used. + + Combine the functionality of :func:`os.writev` and :func:`os.pwrite`. + + Availability: Linux 2.6.30 and newer, FreeBSD 6.0 and newer, + OpenBSD 2.7 and newer. Using flags requires Linux 4.7 or newer. .. versionadded:: 3.7 + .. data:: RWF_DSYNC - Provide a per-write equivalent of the O_DSYNC open(2) flag. This flag - is meaningful only for pwritev2(), and its effect applies only to the - data range written by the system call. + Provide a per-write equivalent of the :data:`O_DSYNC` ``open(2)`` flag. This + flag effect applies only to the data range written by the system call. - Availability: Linux (version 4.7). + Availability: Linux 4.7 and newer. .. versionadded:: 3.7 + .. data:: RWF_SYNC - Provide a per-write equivalent of the O_SYNC open(2) flag. This flag is - meaningful only for pwritev2(), and its effect applies only to the data - range written by the system call. + Provide a per-write equivalent of the :data:`O_SYNC` ``open(2)`` flag. This + flag effect applies only to the data range written by the system call. - Availability: Linux (version 4.7). + Availability: Linux 4.7 and newer. .. versionadded:: 3.7 .. function:: read(fd, n) - Read at most *n* bytes from file descriptor *fd*. Return a bytestring containing the - bytes read. If the end of the file referred to by *fd* has been reached, an - empty bytes object is returned. + Read at most *n* bytes from file descriptor *fd*. + + Return a bytestring containing the bytes read. If the end of the file + referred to by *fd* has been reached, an empty bytes object is returned. .. note:: @@ -1230,66 +1294,19 @@ or `the MSDN <https://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx>`_ on Windo .. function:: readv(fd, buffers) Read from a file descriptor *fd* into a number of mutable :term:`bytes-like - objects <bytes-like object>` *buffers*. :func:`~os.readv` will transfer data - into each buffer until it is full and then move on to the next buffer in the - sequence to hold the rest of the data. :func:`~os.readv` returns the total - number of bytes read (which may be less than the total capacity of all the - objects). + objects <bytes-like object>` *buffers*. Transfer data into each buffer until + it is full and then move on to the next buffer in the sequence to hold the + rest of the data. - Availability: Unix. - - .. versionadded:: 3.3 + Return the total number of bytes actually read which can be less than the + total capacity of all the objects. + The operating system may set a limit (:func:`sysconf` value + ``'SC_IOV_MAX'``) on the number of buffers that can be used. -.. function:: preadv(fd, buffers, offset, flags=0) - - Combines the functionality of :func:`os.readv` and :func:`os.pread`. It - reads from a file descriptor *fd* into a number of mutable :term:`bytes-like - objects <bytes-like object>` *buffers*. As :func:`os.readv`, it will transfer - data into each buffer until it is full and then move on to the next buffer in - the sequence to hold the rest of the data. Its fourth argument, *offset*, - specifies the file offset at which the input operation is to be performed. - :func:`~os.preadv` return the total number of bytes read (which can be less than - the total capacity of all the objects). - - The flags argument contains a bitwise OR of zero or more of the following - flags: - - - RWF_HIPRI - - RWF_NOWAIT - - Using non-zero flags requires Linux 4.6 or newer. - - Availability: Linux (version 2.6.30), FreeBSD 6.0 and newer, - OpenBSD (version 2.7 and newer). - - .. versionadded:: 3.7 - - -.. data:: RWF_HIPRI - - High priority read/write. Allows block-based filesystems to use polling - of the device, which provides lower latency, but may use additional - resources. (Currently, this feature is usable only on a file descriptor - opened using the O_DIRECT flag.) - - Availability: Linux (version 4.6). - - .. versionadded:: 3.7 - - -.. data:: RWF_NOWAIT - - Do not wait for data which is not immediately available. If this flag - is specified, the preadv2() system call will return instantly - if it would have to read data from the backing storage or wait for a lock. - If some data was successfully read, it will return the number of bytes - read. If no bytes were read, it will return -1 and set errno to EAGAIN. - Currently, this flag is meaningful only for preadv2(). - - Availability: Linux (version 4.14). + Availability: Unix. - .. versionadded:: 3.7 + .. versionadded:: 3.3 .. function:: tcgetpgrp(fd) @@ -1319,8 +1336,9 @@ or `the MSDN <https://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx>`_ on Windo .. function:: write(fd, str) - Write the bytestring in *str* to file descriptor *fd*. Return the number of - bytes actually written. + Write the bytestring in *str* to file descriptor *fd*. + + Return the number of bytes actually written. .. note:: @@ -1338,14 +1356,15 @@ or `the MSDN <https://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx>`_ on Windo .. function:: writev(fd, buffers) - Write the contents of *buffers* to file descriptor *fd*. *buffers* must be a - sequence of :term:`bytes-like objects <bytes-like object>`. Buffers are - processed in array order. Entire contents of first buffer is written before - proceeding to second, and so on. The operating system may set a limit - (sysconf() value SC_IOV_MAX) on the number of buffers that can be used. + Write the contents of *buffers* to file descriptor *fd*. *buffers* must be + a sequence of :term:`bytes-like objects <bytes-like object>`. Buffers are + processed in array order. Entire contents of the first buffer is written + before proceeding to the second, and so on. + + Returns the total number of bytes actually written. - :func:`~os.writev` writes the contents of each object to the file descriptor - and returns the total number of bytes written. + The operating system may set a limit (:func:`sysconf` value + ``'SC_IOV_MAX'``) on the number of buffers that can be used. Availability: Unix. diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 2471989ec7b9..9989eaf5eac5 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -1091,9 +1091,10 @@ The new :func:`~os.register_at_fork` function allows registering Python callbacks to be executed at process fork. (Contributed by Antoine Pitrou in :issue:`16500`.) -Exposed the *preadv*, *preadv2*, *pwritev* and *pwritev2* system calls through -the new :func:`~os.preadv` and :func:`~os.pwritev` functions. -(Contributed by Pablo Galindo in :issue:`31368`.) +Added :func:`os.preadv` (combine the functionality of :func:`os.readv` and +:func:`os.pread`) and :func:`os.pwritev` functions (combine the functionality +of :func:`os.writev` and :func:`os.pwrite`). (Contributed by Pablo Galindo in +:issue:`31368`.) The mode argument of :func:`os.makedirs` no longer affects the file permission bits of newly-created intermediate-level directories. From webhook-mailer at python.org Wed May 30 19:35:18 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Wed, 30 May 2018 23:35:18 -0000 Subject: [Python-checkins] 3.6 what's new: fix a reference to PEP 528 (GH-7113) (#7257) Message-ID: <mailman.105.1527723319.2800.python-checkins@python.org> https://github.com/python/cpython/commit/7da7a01f9949f625f29960883b001af44d54402a commit: 7da7a01f9949f625f29960883b001af44d54402a branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Yury Selivanov <yury at magic.io> date: 2018-05-30T19:35:15-04:00 summary: 3.6 what's new: fix a reference to PEP 528 (GH-7113) (#7257) (cherry picked from commit 495e567a2b3bbe3b99f0c253edf12997a9ff4ee1) Co-authored-by: Dmitry Shachnev <mitya57 at users.noreply.github.com> files: M Doc/whatsnew/3.6.rst diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst index c5ccd85603c0..19ab734f92f7 100644 --- a/Doc/whatsnew/3.6.rst +++ b/Doc/whatsnew/3.6.rst @@ -147,7 +147,7 @@ Security improvements: Windows improvements: -* :ref:`PEP 528 <whatsnew36-pep529>` and :ref:`PEP 529 <whatsnew36-pep529>`, +* :ref:`PEP 528 <whatsnew36-pep528>` and :ref:`PEP 529 <whatsnew36-pep529>`, Windows filesystem and console encoding changed to UTF-8. * The ``py.exe`` launcher, when used interactively, no longer prefers From webhook-mailer at python.org Wed May 30 20:55:29 2018 From: webhook-mailer at python.org (Ned Deily) Date: Thu, 31 May 2018 00:55:29 -0000 Subject: [Python-checkins] 3.7.0b5 Message-ID: <mailman.106.1527728130.2800.python-checkins@python.org> https://github.com/python/cpython/commit/abb88023896f545b18d20c7d0d5934b11230a12f commit: abb88023896f545b18d20c7d0d5934b11230a12f branch: 3.7 author: Ned Deily <nad at python.org> committer: Ned Deily <nad at python.org> date: 2018-05-30T19:50:49-04:00 summary: 3.7.0b5 files: A Misc/NEWS.d/3.7.0b5.rst D Misc/NEWS.d/next/Build/2018-05-10-21-10-01.bpo-33012.5Zfjac.rst D Misc/NEWS.d/next/Build/2018-05-15-12-44-50.bpo-33522.mJoNcA.rst D Misc/NEWS.d/next/Build/2018-05-28-11-40-22.bpo-33614.28e0sE.rst D Misc/NEWS.d/next/Core and Builtins/2017-10-02-21-02-14.bpo-21983.UoC319.rst D Misc/NEWS.d/next/Core and Builtins/2018-02-27-20-57-00.bpo-32911.cmKfco.rst D Misc/NEWS.d/next/Core and Builtins/2018-04-25-20-44-42.bpo-28055.f49kfC.rst D Misc/NEWS.d/next/Core and Builtins/2018-05-02-08-36-03.bpo-33391.z4a7rb.rst D Misc/NEWS.d/next/Core and Builtins/2018-05-13-01-26-18.bpo-33475.rI0y1U.rst D Misc/NEWS.d/next/Core and Builtins/2018-05-14-11-34-55.bpo-20104.kqBNzv.rst D Misc/NEWS.d/next/Core and Builtins/2018-05-14-17-31-02.bpo-33509.pIUfTd.rst D Misc/NEWS.d/next/Core and Builtins/2018-05-23-20-46-14.bpo-33622.xPucO9.rst D Misc/NEWS.d/next/Documentation/2018-05-14-15-15-41.bpo-33421.3GU_QO.rst D Misc/NEWS.d/next/Documentation/2018-05-14-20-08-58.bpo-33503.Wvt0qg.rst D Misc/NEWS.d/next/Documentation/2018-05-22-11-47-14.bpo-33604.5YHTpz.rst D Misc/NEWS.d/next/Documentation/2018-05-23-11-59-51.bpo-32436.S1LGPa.rst D Misc/NEWS.d/next/Documentation/2018-05-29-16-02-31.bpo-23859.E5gba1.rst D Misc/NEWS.d/next/IDLE/2018-02-12-08-08-45.bpo-32831.srDRvU.rst D Misc/NEWS.d/next/IDLE/2018-05-17-19-41-12.bpo-33564.XzHZJe.rst D Misc/NEWS.d/next/IDLE/2018-05-23-19-51-07.bpo-33628.sLlFLO.rst D Misc/NEWS.d/next/Library/2017-09-29-16-40-38.bpo-16865.l-f6I_.rst D Misc/NEWS.d/next/Library/2018-02-26-09-08-07.bpo-32257.6ElnUt.rst D Misc/NEWS.d/next/Library/2018-04-02-20-44-54.bpo-32861.HeBjzN.rst D Misc/NEWS.d/next/Library/2018-04-11-20-29-19.bpo-33263.B56Hc1.rst D Misc/NEWS.d/next/Library/2018-04-29-23-56-20.bpo-33197.dgRLqr.rst D Misc/NEWS.d/next/Library/2018-05-02-07-26-29.bpo-28167.7FwDfN.rst D Misc/NEWS.d/next/Library/2018-05-05-09-53-05.bpo-33422.4FtQ0q.rst D Misc/NEWS.d/next/Library/2018-05-05-18-02-24.bpo-20087.lJrvXL.rst D Misc/NEWS.d/next/Library/2018-05-08-16-43-42.bpo-28556._xr5mp.rst D Misc/NEWS.d/next/Library/2018-05-12-06-01-02.bpo-33453.Fj-jMD.rst D Misc/NEWS.d/next/Library/2018-05-14-10-29-03.bpo-33495.TeGTQJ.rst D Misc/NEWS.d/next/Library/2018-05-14-17-49-34.bpo-33497.wWT6XM.rst D Misc/NEWS.d/next/Library/2018-05-14-18-05-35.bpo-33505.L8pAyt.rst D Misc/NEWS.d/next/Library/2018-05-15-18-02-03.bpo-0.pj2Mbb.rst D Misc/NEWS.d/next/Library/2018-05-16-05-24-43.bpo-26819.taxbVT.rst D Misc/NEWS.d/next/Library/2018-05-16-09-30-27.bpo-33542.idNAcs.rst D Misc/NEWS.d/next/Library/2018-05-16-10-07-40.bpo-33536._s0TE8.rst D Misc/NEWS.d/next/Library/2018-05-16-14-57-58.bpo-33109.nPLL_S.rst D Misc/NEWS.d/next/Library/2018-05-16-17-05-48.bpo-33548.xWslmx.rst D Misc/NEWS.d/next/Library/2018-05-16-18-10-38.bpo-33540.wy9LRV.rst D Misc/NEWS.d/next/Library/2018-05-17-22-53-08.bpo-28556.C6Hnd1.rst D Misc/NEWS.d/next/Library/2018-05-18-21-50-47.bpo-33570.7CZy4t.rst D Misc/NEWS.d/next/Library/2018-05-22-13-05-12.bpo-30877.JZEGjI.rst D Misc/NEWS.d/next/Library/2018-05-23-14-58-05.bpo-33623.wAw1cF.rst D Misc/NEWS.d/next/Library/2018-05-23-20-14-34.bpo-33618.xU39lr.rst D Misc/NEWS.d/next/Library/2018-05-24-17-41-36.bpo-32493.5tAoAu.rst D Misc/NEWS.d/next/Library/2018-05-26-10-13-59.bpo-33652.humFJ1.rst D Misc/NEWS.d/next/Library/2018-05-26-13-09-34.bpo-33654.IbYWxA.rst D Misc/NEWS.d/next/Library/2018-05-28-12-29-54.bpo-33672.GM_Xm_.rst D Misc/NEWS.d/next/Library/2018-05-28-15-55-12.bpo-33469.hmXBpY.rst D Misc/NEWS.d/next/Library/2018-05-28-16-19-35.bpo-32410.Z1DZaF.rst D Misc/NEWS.d/next/Library/2018-05-28-16-40-32.bpo-32610.KvUAsL.rst D Misc/NEWS.d/next/Library/2018-05-28-18-40-26.bpo-31467.s4Fad3.rst D Misc/NEWS.d/next/Library/2018-05-28-22-49-59.bpo-33674.6LFFj7.rst D Misc/NEWS.d/next/Library/2018-05-29-00-37-56.bpo-33674.2IkGhL.rst D Misc/NEWS.d/next/Library/2018-05-29-01-13-39.bpo-33654.sa81Si.rst D Misc/NEWS.d/next/Library/2018-05-29-12-51-18.bpo-32684.ZEIism.rst D Misc/NEWS.d/next/Library/2018-05-29-15-32-18.bpo-32751.oBTqr7.rst D Misc/NEWS.d/next/Tests/2018-05-14-13-32-46.bpo-32604.a_z6D_.rst D Misc/NEWS.d/next/Tests/2018-05-26-16-01-40.bpo-33655.Frb4LA.rst D Misc/NEWS.d/next/macOS/2018-05-16-13-25-58.bpo-13631.UIjDyY.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 d7bd1d394454..bcba96770fc1 100644 --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -20,10 +20,10 @@ #define PY_MINOR_VERSION 7 #define PY_MICRO_VERSION 0 #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_BETA -#define PY_RELEASE_SERIAL 4 +#define PY_RELEASE_SERIAL 5 /* Version as a string */ -#define PY_VERSION "3.7.0b4+" +#define PY_VERSION "3.7.0b5" /*--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 e138d49821aa..09016ac99068 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 May 2 03:29:32 2018 +# Autogenerated by Sphinx on Wed May 30 19:43:20 2018 topics = {'assert': 'The "assert" statement\n' '**********************\n' '\n' @@ -403,6 +403,134 @@ 'See also: **PEP 526** - Variable and attribute annotation ' 'syntax\n' ' **PEP 484** - Type hints\n', + 'async': 'Coroutines\n' + '**********\n' + '\n' + 'New in version 3.5.\n' + '\n' + '\n' + 'Coroutine function definition\n' + '=============================\n' + '\n' + ' async_funcdef ::= [decorators] "async" "def" funcname "(" ' + '[parameter_list] ")" ["->" expression] ":" suite\n' + '\n' + 'Execution of Python coroutines can be suspended and resumed at ' + 'many\n' + 'points (see *coroutine*). In the body of a coroutine, any "await" ' + 'and\n' + '"async" identifiers become reserved keywords; "await" expressions,\n' + '"async for" and "async with" can only be used in coroutine bodies.\n' + '\n' + 'Functions defined with "async def" syntax are always coroutine\n' + 'functions, even if they do not contain "await" or "async" ' + 'keywords.\n' + '\n' + 'It is a "SyntaxError" to use "yield from" expressions in "async ' + 'def"\n' + 'coroutines.\n' + '\n' + 'An example of a coroutine function:\n' + '\n' + ' async def func(param1, param2):\n' + ' do_stuff()\n' + ' await some_coroutine()\n' + '\n' + '\n' + 'The "async for" statement\n' + '=========================\n' + '\n' + ' async_for_stmt ::= "async" for_stmt\n' + '\n' + 'An *asynchronous iterable* is able to call asynchronous code in ' + 'its\n' + '*iter* implementation, and *asynchronous iterator* can call\n' + 'asynchronous code in its *next* method.\n' + '\n' + 'The "async for" statement allows convenient iteration over\n' + 'asynchronous iterators.\n' + '\n' + 'The following code:\n' + '\n' + ' async for TARGET in ITER:\n' + ' BLOCK\n' + ' else:\n' + ' BLOCK2\n' + '\n' + 'Is semantically equivalent to:\n' + '\n' + ' iter = (ITER)\n' + ' iter = type(iter).__aiter__(iter)\n' + ' running = True\n' + ' while running:\n' + ' try:\n' + ' TARGET = await type(iter).__anext__(iter)\n' + ' except StopAsyncIteration:\n' + ' running = False\n' + ' else:\n' + ' BLOCK\n' + ' else:\n' + ' BLOCK2\n' + '\n' + 'See also "__aiter__()" and "__anext__()" for details.\n' + '\n' + 'It is a "SyntaxError" to use "async for" statement outside of an\n' + '"async def" function.\n' + '\n' + '\n' + 'The "async with" statement\n' + '==========================\n' + '\n' + ' async_with_stmt ::= "async" with_stmt\n' + '\n' + 'An *asynchronous context manager* is a *context manager* that is ' + 'able\n' + 'to suspend execution in its *enter* and *exit* methods.\n' + '\n' + 'The following code:\n' + '\n' + ' async with EXPR as VAR:\n' + ' BLOCK\n' + '\n' + 'Is semantically equivalent to:\n' + '\n' + ' mgr = (EXPR)\n' + ' aexit = type(mgr).__aexit__\n' + ' aenter = type(mgr).__aenter__(mgr)\n' + '\n' + ' VAR = await aenter\n' + ' try:\n' + ' BLOCK\n' + ' except:\n' + ' if not await aexit(mgr, *sys.exc_info()):\n' + ' raise\n' + ' else:\n' + ' await aexit(mgr, None, None, None)\n' + '\n' + 'See also "__aenter__()" and "__aexit__()" for details.\n' + '\n' + 'It is a "SyntaxError" to use "async with" statement outside of an\n' + '"async def" function.\n' + '\n' + 'See also: **PEP 492** - Coroutines with async and await syntax\n' + '\n' + '-[ Footnotes ]-\n' + '\n' + '[1] The exception is propagated to the invocation stack unless\n' + ' there is a "finally" clause which happens to raise another\n' + ' exception. That new exception causes the old one to be lost.\n' + '\n' + '[2] Currently, control ?flows off the end? except in the case of\n' + ' an exception or the execution of a "return", "continue", or\n' + ' "break" statement.\n' + '\n' + '[3] A string literal appearing as the first statement in the\n' + ' function body is transformed into the function?s "__doc__"\n' + ' attribute and therefore the function?s *docstring*.\n' + '\n' + '[4] A string literal appearing as the first statement in the class\n' + ' body is transformed into the namespace?s "__doc__" item and\n' + ' therefore the class?s *docstring*.\n', 'atom-identifiers': 'Identifiers (Names)\n' '*******************\n' '\n' @@ -6222,13 +6350,13 @@ '\n' 'Lambda expressions (sometimes called lambda forms) are used to ' 'create\n' - 'anonymous functions. The expression "lambda arguments: ' + 'anonymous functions. The expression "lambda parameters: ' 'expression"\n' 'yields a function object. The unnamed object behaves like a ' 'function\n' 'object defined with:\n' '\n' - ' def <lambda>(arguments):\n' + ' def <lambda>(parameters):\n' ' return expression\n' '\n' 'See section Function definitions for the syntax of parameter ' @@ -8593,6 +8721,8 @@ 'When a class definition is executed, the following steps ' 'occur:\n' '\n' + '* MRO entries are resolved\n' + '\n' '* the appropriate metaclass is determined\n' '\n' '* the class namespace is prepared\n' @@ -8602,6 +8732,24 @@ '* the class object is created\n' '\n' '\n' + 'Resolving MRO entries\n' + '---------------------\n' + '\n' + 'If a base that appears in class definition is not an ' + 'instance of\n' + '"type", then an "__mro_entries__" method is searched on it. ' + 'If found,\n' + 'it is called with the original bases tuple. This method must ' + 'return a\n' + 'tuple of classes that will be used instead of this base. The ' + 'tuple may\n' + 'be empty, in such case the original base is ignored.\n' + '\n' + 'See also: **PEP 560** - Core support for typing module and ' + 'generic\n' + ' types\n' + '\n' + '\n' 'Determining the appropriate metaclass\n' '-------------------------------------\n' '\n' @@ -8720,7 +8868,7 @@ 'initialised\n' 'correctly. Failing to do so will result in a ' '"DeprecationWarning" in\n' - 'Python 3.6, and a "RuntimeWarning" in the future.\n' + 'Python 3.6, and a "RuntimeError" in Python 3.8.\n' '\n' 'When using the default metaclass "type", or any metaclass ' 'that\n' @@ -8872,6 +9020,32 @@ ' module) to the language.\n' '\n' '\n' + 'Emulating generic types\n' + '=======================\n' + '\n' + 'One can implement the generic class syntax as specified by ' + '**PEP 484**\n' + '(for example "List[int]") by defining a special method\n' + '\n' + 'classmethod object.__class_getitem__(cls, key)\n' + '\n' + ' Return an object representing the specialization of a ' + 'generic class\n' + ' by type arguments found in *key*.\n' + '\n' + 'This method is looked up on the class object itself, and ' + 'when defined\n' + 'in the class body, this method is implicitly a class ' + 'method. Note,\n' + 'this mechanism is primarily reserved for use with static ' + 'type hints,\n' + 'other usage is discouraged.\n' + '\n' + 'See also: **PEP 560** - Core support for typing module and ' + 'generic\n' + ' types\n' + '\n' + '\n' 'Emulating callable objects\n' '==========================\n' '\n' diff --git a/Misc/NEWS.d/3.7.0b5.rst b/Misc/NEWS.d/3.7.0b5.rst new file mode 100644 index 000000000000..2e2fb9ee0469 --- /dev/null +++ b/Misc/NEWS.d/3.7.0b5.rst @@ -0,0 +1,592 @@ +.. bpo: 33622 +.. date: 2018-05-23-20-46-14 +.. nonce: xPucO9 +.. release date: 2018-05-30 +.. section: Core and Builtins + +Fixed a leak when the garbage collector fails to add an object with the +``__del__`` method or referenced by it into the :data:`gc.garbage` list. +:c:func:`PyGC_Collect` can now be called when an exception is set and +preserves it. + +.. + +.. bpo: 33509 +.. date: 2018-05-14-17-31-02 +.. nonce: pIUfTd +.. section: Core and Builtins + +Fix module_globals parameter of warnings.warn_explicit(): don't crash if +module_globals is not a dict. + +.. + +.. bpo: 20104 +.. date: 2018-05-14-11-34-55 +.. nonce: kqBNzv +.. section: Core and Builtins + +The new `os.posix_spawn` added in 3.7.0b1 was removed as we are still +working on what the API should look like. Expect this in 3.8 instead. + +.. + +.. bpo: 33475 +.. date: 2018-05-13-01-26-18 +.. nonce: rI0y1U +.. section: Core and Builtins + +Fixed miscellaneous bugs in converting annotations to strings and optimized +parentheses in the string representation. + +.. + +.. bpo: 33391 +.. date: 2018-05-02-08-36-03 +.. nonce: z4a7rb +.. section: Core and Builtins + +Fix a leak in set_symmetric_difference(). + +.. + +.. bpo: 28055 +.. date: 2018-04-25-20-44-42 +.. nonce: f49kfC +.. section: Core and Builtins + +Fix unaligned accesses in siphash24(). Patch by Rolf Eike Beer. + +.. + +.. bpo: 32911 +.. date: 2018-02-27-20-57-00 +.. nonce: cmKfco +.. section: Core and Builtins + +Due to unexpected compatibility issues discovered during downstream beta +testing, reverted :issue:`29463`. ``docstring`` field is removed from +Module, ClassDef, FunctionDef, and AsyncFunctionDef ast nodes which was +added in 3.7a1. Docstring expression is restored as a first statement in +their body. Based on patch by Inada Naoki. + +.. + +.. bpo: 21983 +.. date: 2017-10-02-21-02-14 +.. nonce: UoC319 +.. section: Core and Builtins + +Fix a crash in `ctypes.cast()` in case the type argument is a ctypes +structured data type. Patch by Eryk Sun and Oren Milman. + +.. + +.. bpo: 32751 +.. date: 2018-05-29-15-32-18 +.. nonce: oBTqr7 +.. section: Library + +When cancelling the task due to a timeout, :meth:`asyncio.wait_for` will now +wait until the cancellation is complete. + +.. + +.. bpo: 32684 +.. date: 2018-05-29-12-51-18 +.. nonce: ZEIism +.. section: Library + +Fix gather to propagate cancellation of itself even with return_exceptions. + +.. + +.. bpo: 33654 +.. date: 2018-05-29-01-13-39 +.. nonce: sa81Si +.. section: Library + +Support protocol type switching in SSLTransport.set_protocol(). + +.. + +.. bpo: 33674 +.. date: 2018-05-29-00-37-56 +.. nonce: 2IkGhL +.. section: Library + +Pause the transport as early as possible to further reduce the risk of +data_received() being called before connection_made(). + +.. + +.. bpo: 33674 +.. date: 2018-05-28-22-49-59 +.. nonce: 6LFFj7 +.. section: Library + +Fix a race condition in SSLProtocol.connection_made() of asyncio.sslproto: +start immediately the handshake instead of using call_soon(). Previously, +data_received() could be called before the handshake started, causing the +handshake to hang or fail. + +.. + +.. bpo: 31467 +.. date: 2018-05-28-18-40-26 +.. nonce: s4Fad3 +.. section: Library + +Fixed bug where calling write_eof() on a _SelectorSocketTransport after it's +already closed raises AttributeError. + +.. + +.. bpo: 32610 +.. date: 2018-05-28-16-40-32 +.. nonce: KvUAsL +.. section: Library + +Make asyncio.all_tasks() return only pending tasks. + +.. + +.. bpo: 32410 +.. date: 2018-05-28-16-19-35 +.. nonce: Z1DZaF +.. section: Library + +Avoid blocking on file IO in sendfile fallback code + +.. + +.. bpo: 33469 +.. date: 2018-05-28-15-55-12 +.. nonce: hmXBpY +.. section: Library + +Fix RuntimeError after closing loop that used run_in_executor + +.. + +.. bpo: 33672 +.. date: 2018-05-28-12-29-54 +.. nonce: GM_Xm_ +.. section: Library + +Fix Task.__repr__ crash with Cython's bogus coroutines + +.. + +.. bpo: 33654 +.. date: 2018-05-26-13-09-34 +.. nonce: IbYWxA +.. section: Library + +Fix transport.set_protocol() to support switching between asyncio.Protocol +and asyncio.BufferedProtocol. Fix loop.start_tls() to work with +asyncio.BufferedProtocols. + +.. + +.. bpo: 33652 +.. date: 2018-05-26-10-13-59 +.. nonce: humFJ1 +.. section: Library + +Pickles of type variables and subscripted generics are now future-proof and +compatible with older Python versions. + +.. + +.. bpo: 32493 +.. date: 2018-05-24-17-41-36 +.. nonce: 5tAoAu +.. section: Library + +Fixed :func:`uuid.uuid1` on FreeBSD. + +.. + +.. bpo: 33618 +.. date: 2018-05-23-20-14-34 +.. nonce: xU39lr +.. section: Library + +Finalize and document preliminary and experimental TLS 1.3 support with +OpenSSL 1.1.1 + +.. + +.. bpo: 33623 +.. date: 2018-05-23-14-58-05 +.. nonce: wAw1cF +.. section: Library + +Fix possible SIGSGV when asyncio.Future is created in __del__ + +.. + +.. bpo: 30877 +.. date: 2018-05-22-13-05-12 +.. nonce: JZEGjI +.. section: Library + +Fixed a bug in the Python implementation of the JSON decoder that prevented +the cache of parsed strings from clearing after finishing the decoding. +Based on patch by c-fos. + +.. + +.. bpo: 33570 +.. date: 2018-05-18-21-50-47 +.. nonce: 7CZy4t +.. section: Library + +Change TLS 1.3 cipher suite settings for compatibility with OpenSSL +1.1.1-pre6 and newer. OpenSSL 1.1.1 will have TLS 1.3 cipers enabled by +default. + +.. + +.. bpo: 28556 +.. date: 2018-05-17-22-53-08 +.. nonce: C6Hnd1 +.. section: Library + +Do not simplify arguments to `typing.Union`. Now `Union[Manager, Employee]` +is not simplified to `Employee` at runtime. Such simplification previously +caused several bugs and limited possibilities for introspection. + +.. + +.. bpo: 33540 +.. date: 2018-05-16-18-10-38 +.. nonce: wy9LRV +.. section: Library + +Add a new ``block_on_close`` class attribute to ``ForkingMixIn`` and +``ThreadingMixIn`` classes of :mod:`socketserver`. + +.. + +.. bpo: 33548 +.. date: 2018-05-16-17-05-48 +.. nonce: xWslmx +.. section: Library + +tempfile._candidate_tempdir_list should consider common TEMP locations + +.. + +.. bpo: 33109 +.. date: 2018-05-16-14-57-58 +.. nonce: nPLL_S +.. section: Library + +argparse subparsers are once again not required by default, reverting the +change in behavior introduced by bpo-26510 in 3.7.0a2. + +.. + +.. bpo: 33536 +.. date: 2018-05-16-10-07-40 +.. nonce: _s0TE8 +.. section: Library + +dataclasses.make_dataclass now checks for invalid field names and duplicate +fields. Also, added a check for invalid field specifications. + +.. + +.. bpo: 33542 +.. date: 2018-05-16-09-30-27 +.. nonce: idNAcs +.. section: Library + +Prevent ``uuid.get_node`` from using a DUID instead of a MAC on Windows. +Patch by Zvi Effron + +.. + +.. bpo: 26819 +.. date: 2018-05-16-05-24-43 +.. nonce: taxbVT +.. section: Library + +Fix race condition with `ReadTransport.resume_reading` in Windows proactor +event loop. + +.. + +.. bpo: 0 +.. date: 2018-05-15-18-02-03 +.. nonce: pj2Mbb +.. section: Library + +Fix failure in `typing.get_type_hints()` when ClassVar was provided as a +string forward reference. + +.. + +.. bpo: 33505 +.. date: 2018-05-14-18-05-35 +.. nonce: L8pAyt +.. section: Library + +Optimize asyncio.ensure_future() by reordering if checks: 1.17x faster. + +.. + +.. bpo: 33497 +.. date: 2018-05-14-17-49-34 +.. nonce: wWT6XM +.. section: Library + +Add errors param to cgi.parse_multipart and make an encoding in FieldStorage +use the given errors (needed for Twisted). Patch by Amber Brown. + +.. + +.. bpo: 33495 +.. date: 2018-05-14-10-29-03 +.. nonce: TeGTQJ +.. section: Library + +Change dataclasses.Fields repr to use the repr of each of its members, +instead of str. This makes it more clear what each field actually +represents. This is especially true for the 'type' member. + +.. + +.. bpo: 33453 +.. date: 2018-05-12-06-01-02 +.. nonce: Fj-jMD +.. section: Library + +Fix dataclasses to work if using literal string type annotations or if using +PEP 563 "Postponed Evaluation of Annotations". Only specific string +prefixes are detected for both ClassVar ("ClassVar" and "typing.ClassVar") +and InitVar ("InitVar" and "dataclasses.InitVar"). + +.. + +.. bpo: 28556 +.. date: 2018-05-08-16-43-42 +.. nonce: _xr5mp +.. section: Library + +Minor fixes in typing module: add annotations to ``NamedTuple.__new__``, +pass ``*args`` and ``**kwds`` in ``Generic.__new__``. Original PRs by +Paulius ?arka and Chad Dombrova. + +.. + +.. bpo: 20087 +.. date: 2018-05-05-18-02-24 +.. nonce: lJrvXL +.. section: Library + +Updated alias mapping with glibc 2.27 supported locales. + +.. + +.. bpo: 33422 +.. date: 2018-05-05-09-53-05 +.. nonce: 4FtQ0q +.. section: Library + +Fix trailing quotation marks getting deleted when looking up byte/string +literals on pydoc. Patch by Andr?s Delfino. + +.. + +.. bpo: 28167 +.. date: 2018-05-02-07-26-29 +.. nonce: 7FwDfN +.. section: Library + +The function ``platform.linux_ditribution`` and ``platform.dist`` now +trigger a ``DeprecationWarning`` and have been marked for removal in Python +3.8 + +.. + +.. bpo: 33197 +.. date: 2018-04-29-23-56-20 +.. nonce: dgRLqr +.. section: Library + +Update error message when constructing invalid inspect.Parameters Patch by +Dong-hee Na. + +.. + +.. bpo: 33263 +.. date: 2018-04-11-20-29-19 +.. nonce: B56Hc1 +.. section: Library + +Fix FD leak in `_SelectorSocketTransport` Patch by Vlad Starostin. + +.. + +.. bpo: 32861 +.. date: 2018-04-02-20-44-54 +.. nonce: HeBjzN +.. section: Library + +The urllib.robotparser's ``__str__`` representation now includes wildcard +entries and the "Crawl-delay" and "Request-rate" fields. Patch by Michael +Lazar. + +.. + +.. bpo: 32257 +.. date: 2018-02-26-09-08-07 +.. nonce: 6ElnUt +.. section: Library + +The ssl module now contains OP_NO_RENEGOTIATION constant, available with +OpenSSL 1.1.0h or 1.1.1. + +.. + +.. bpo: 16865 +.. date: 2017-09-29-16-40-38 +.. nonce: l-f6I_ +.. section: Library + +Support arrays >=2GiB in :mod:`ctypes`. Patch by Segev Finer. + +.. + +.. bpo: 23859 +.. date: 2018-05-29-16-02-31 +.. nonce: E5gba1 +.. section: Documentation + +Document that `asyncio.wait()` does not cancel its futures on timeout. + +.. + +.. bpo: 32436 +.. date: 2018-05-23-11-59-51 +.. nonce: S1LGPa +.. section: Documentation + +Document PEP 567 changes to asyncio. + +.. + +.. bpo: 33604 +.. date: 2018-05-22-11-47-14 +.. nonce: 5YHTpz +.. section: Documentation + +Update HMAC md5 default to a DeprecationWarning, bump removal to 3.8. + +.. + +.. bpo: 33503 +.. date: 2018-05-14-20-08-58 +.. nonce: Wvt0qg +.. section: Documentation + +Fix broken pypi link + +.. + +.. bpo: 33421 +.. date: 2018-05-14-15-15-41 +.. nonce: 3GU_QO +.. section: Documentation + +Add missing documentation for ``typing.AsyncContextManager``. + +.. + +.. bpo: 33655 +.. date: 2018-05-26-16-01-40 +.. nonce: Frb4LA +.. section: Tests + +Ignore test_posix_fallocate failures on BSD platforms that might be due to +running on ZFS. + +.. + +.. bpo: 32604 +.. date: 2018-05-14-13-32-46 +.. nonce: a_z6D_ +.. section: Tests + +Remove the _xxsubinterpreters module (meant for testing) and associated +helpers. This module was originally added recently in 3.7b1. + +.. + +.. bpo: 33614 +.. date: 2018-05-28-11-40-22 +.. nonce: 28e0sE +.. section: Build + +Ensures module definition files for the stable ABI on Windows are correctly +regenerated. + +.. + +.. bpo: 33522 +.. date: 2018-05-15-12-44-50 +.. nonce: mJoNcA +.. section: Build + +Enable CI builds on Visual Studio Team Services at +https://python.visualstudio.com/cpython + +.. + +.. bpo: 33012 +.. date: 2018-05-10-21-10-01 +.. nonce: 5Zfjac +.. section: Build + +Add ``-Wno-cast-function-type`` for gcc 8 for silencing warnings about +function casts like casting to PyCFunction in method definition lists. + +.. + +.. bpo: 13631 +.. date: 2018-05-16-13-25-58 +.. nonce: UIjDyY +.. section: macOS + +The .editrc file in user's home directory is now processed correctly during +the readline initialization through editline emulation on macOS. + +.. + +.. bpo: 33628 +.. date: 2018-05-23-19-51-07 +.. nonce: sLlFLO +.. section: IDLE + +IDLE: Cleanup codecontext.py and its test. + +.. + +.. bpo: 33564 +.. date: 2018-05-17-19-41-12 +.. nonce: XzHZJe +.. section: IDLE + +IDLE's code context now recognizes async as a block opener. + +.. + +.. bpo: 32831 +.. date: 2018-02-12-08-08-45 +.. nonce: srDRvU +.. section: IDLE + +Add docstrings and tests for codecontext. diff --git a/Misc/NEWS.d/next/Build/2018-05-10-21-10-01.bpo-33012.5Zfjac.rst b/Misc/NEWS.d/next/Build/2018-05-10-21-10-01.bpo-33012.5Zfjac.rst deleted file mode 100644 index ecaa5c6117a0..000000000000 --- a/Misc/NEWS.d/next/Build/2018-05-10-21-10-01.bpo-33012.5Zfjac.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add ``-Wno-cast-function-type`` for gcc 8 for silencing warnings about -function casts like casting to PyCFunction in method definition lists. diff --git a/Misc/NEWS.d/next/Build/2018-05-15-12-44-50.bpo-33522.mJoNcA.rst b/Misc/NEWS.d/next/Build/2018-05-15-12-44-50.bpo-33522.mJoNcA.rst deleted file mode 100644 index f44862f0c454..000000000000 --- a/Misc/NEWS.d/next/Build/2018-05-15-12-44-50.bpo-33522.mJoNcA.rst +++ /dev/null @@ -1,2 +0,0 @@ -Enable CI builds on Visual Studio Team Services at -https://python.visualstudio.com/cpython diff --git a/Misc/NEWS.d/next/Build/2018-05-28-11-40-22.bpo-33614.28e0sE.rst b/Misc/NEWS.d/next/Build/2018-05-28-11-40-22.bpo-33614.28e0sE.rst deleted file mode 100644 index 9091c282ad0a..000000000000 --- a/Misc/NEWS.d/next/Build/2018-05-28-11-40-22.bpo-33614.28e0sE.rst +++ /dev/null @@ -1,2 +0,0 @@ -Ensures module definition files for the stable ABI on Windows are correctly -regenerated. diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-10-02-21-02-14.bpo-21983.UoC319.rst b/Misc/NEWS.d/next/Core and Builtins/2017-10-02-21-02-14.bpo-21983.UoC319.rst deleted file mode 100644 index 88a03685073c..000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2017-10-02-21-02-14.bpo-21983.UoC319.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix a crash in `ctypes.cast()` in case the type argument is a ctypes -structured data type. Patch by Eryk Sun and Oren Milman. diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-02-27-20-57-00.bpo-32911.cmKfco.rst b/Misc/NEWS.d/next/Core and Builtins/2018-02-27-20-57-00.bpo-32911.cmKfco.rst deleted file mode 100644 index 0c2ae756b65c..000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2018-02-27-20-57-00.bpo-32911.cmKfco.rst +++ /dev/null @@ -1,5 +0,0 @@ -Due to unexpected compatibility issues discovered during downstream beta -testing, reverted :issue:`29463`. ``docstring`` field is removed from Module, -ClassDef, FunctionDef, and AsyncFunctionDef ast nodes which was added in -3.7a1. Docstring expression is restored as a first statement in their body. -Based on patch by Inada Naoki. diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-04-25-20-44-42.bpo-28055.f49kfC.rst b/Misc/NEWS.d/next/Core and Builtins/2018-04-25-20-44-42.bpo-28055.f49kfC.rst deleted file mode 100644 index c7d849906fc9..000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2018-04-25-20-44-42.bpo-28055.f49kfC.rst +++ /dev/null @@ -1 +0,0 @@ -Fix unaligned accesses in siphash24(). Patch by Rolf Eike Beer. diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-05-02-08-36-03.bpo-33391.z4a7rb.rst b/Misc/NEWS.d/next/Core and Builtins/2018-05-02-08-36-03.bpo-33391.z4a7rb.rst deleted file mode 100644 index ab17aa408c06..000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2018-05-02-08-36-03.bpo-33391.z4a7rb.rst +++ /dev/null @@ -1 +0,0 @@ -Fix a leak in set_symmetric_difference(). diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-05-13-01-26-18.bpo-33475.rI0y1U.rst b/Misc/NEWS.d/next/Core and Builtins/2018-05-13-01-26-18.bpo-33475.rI0y1U.rst deleted file mode 100644 index cd714b9d1e89..000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2018-05-13-01-26-18.bpo-33475.rI0y1U.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed miscellaneous bugs in converting annotations to strings and optimized -parentheses in the string representation. diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-05-14-11-34-55.bpo-20104.kqBNzv.rst b/Misc/NEWS.d/next/Core and Builtins/2018-05-14-11-34-55.bpo-20104.kqBNzv.rst deleted file mode 100644 index 28c5b3302b4a..000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2018-05-14-11-34-55.bpo-20104.kqBNzv.rst +++ /dev/null @@ -1,2 +0,0 @@ -The new `os.posix_spawn` added in 3.7.0b1 was removed as we are still -working on what the API should look like. Expect this in 3.8 instead. diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-05-14-17-31-02.bpo-33509.pIUfTd.rst b/Misc/NEWS.d/next/Core and Builtins/2018-05-14-17-31-02.bpo-33509.pIUfTd.rst deleted file mode 100644 index 3d80a8c7f3eb..000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2018-05-14-17-31-02.bpo-33509.pIUfTd.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix module_globals parameter of warnings.warn_explicit(): don't crash if -module_globals is not a dict. diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-05-23-20-46-14.bpo-33622.xPucO9.rst b/Misc/NEWS.d/next/Core and Builtins/2018-05-23-20-46-14.bpo-33622.xPucO9.rst deleted file mode 100644 index e589b4503229..000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2018-05-23-20-46-14.bpo-33622.xPucO9.rst +++ /dev/null @@ -1,4 +0,0 @@ -Fixed a leak when the garbage collector fails to add an object with the -``__del__`` method or referenced by it into the :data:`gc.garbage` list. -:c:func:`PyGC_Collect` can now be called when an exception is set and -preserves it. diff --git a/Misc/NEWS.d/next/Documentation/2018-05-14-15-15-41.bpo-33421.3GU_QO.rst b/Misc/NEWS.d/next/Documentation/2018-05-14-15-15-41.bpo-33421.3GU_QO.rst deleted file mode 100644 index 75694b7be1e7..000000000000 --- a/Misc/NEWS.d/next/Documentation/2018-05-14-15-15-41.bpo-33421.3GU_QO.rst +++ /dev/null @@ -1 +0,0 @@ -Add missing documentation for ``typing.AsyncContextManager``. diff --git a/Misc/NEWS.d/next/Documentation/2018-05-14-20-08-58.bpo-33503.Wvt0qg.rst b/Misc/NEWS.d/next/Documentation/2018-05-14-20-08-58.bpo-33503.Wvt0qg.rst deleted file mode 100644 index 27025c31a036..000000000000 --- a/Misc/NEWS.d/next/Documentation/2018-05-14-20-08-58.bpo-33503.Wvt0qg.rst +++ /dev/null @@ -1 +0,0 @@ -Fix broken pypi link diff --git a/Misc/NEWS.d/next/Documentation/2018-05-22-11-47-14.bpo-33604.5YHTpz.rst b/Misc/NEWS.d/next/Documentation/2018-05-22-11-47-14.bpo-33604.5YHTpz.rst deleted file mode 100644 index 3c2f2d0b8230..000000000000 --- a/Misc/NEWS.d/next/Documentation/2018-05-22-11-47-14.bpo-33604.5YHTpz.rst +++ /dev/null @@ -1 +0,0 @@ -Update HMAC md5 default to a DeprecationWarning, bump removal to 3.8. diff --git a/Misc/NEWS.d/next/Documentation/2018-05-23-11-59-51.bpo-32436.S1LGPa.rst b/Misc/NEWS.d/next/Documentation/2018-05-23-11-59-51.bpo-32436.S1LGPa.rst deleted file mode 100644 index 8eeb561921a8..000000000000 --- a/Misc/NEWS.d/next/Documentation/2018-05-23-11-59-51.bpo-32436.S1LGPa.rst +++ /dev/null @@ -1 +0,0 @@ -Document PEP 567 changes to asyncio. diff --git a/Misc/NEWS.d/next/Documentation/2018-05-29-16-02-31.bpo-23859.E5gba1.rst b/Misc/NEWS.d/next/Documentation/2018-05-29-16-02-31.bpo-23859.E5gba1.rst deleted file mode 100644 index b372faa5eb97..000000000000 --- a/Misc/NEWS.d/next/Documentation/2018-05-29-16-02-31.bpo-23859.E5gba1.rst +++ /dev/null @@ -1 +0,0 @@ -Document that `asyncio.wait()` does not cancel its futures on timeout. diff --git a/Misc/NEWS.d/next/IDLE/2018-02-12-08-08-45.bpo-32831.srDRvU.rst b/Misc/NEWS.d/next/IDLE/2018-02-12-08-08-45.bpo-32831.srDRvU.rst deleted file mode 100644 index 583e341f94f0..000000000000 --- a/Misc/NEWS.d/next/IDLE/2018-02-12-08-08-45.bpo-32831.srDRvU.rst +++ /dev/null @@ -1 +0,0 @@ -Add docstrings and tests for codecontext. diff --git a/Misc/NEWS.d/next/IDLE/2018-05-17-19-41-12.bpo-33564.XzHZJe.rst b/Misc/NEWS.d/next/IDLE/2018-05-17-19-41-12.bpo-33564.XzHZJe.rst deleted file mode 100644 index df828485f69e..000000000000 --- a/Misc/NEWS.d/next/IDLE/2018-05-17-19-41-12.bpo-33564.XzHZJe.rst +++ /dev/null @@ -1 +0,0 @@ -IDLE's code context now recognizes async as a block opener. diff --git a/Misc/NEWS.d/next/IDLE/2018-05-23-19-51-07.bpo-33628.sLlFLO.rst b/Misc/NEWS.d/next/IDLE/2018-05-23-19-51-07.bpo-33628.sLlFLO.rst deleted file mode 100644 index f0b13a21c346..000000000000 --- a/Misc/NEWS.d/next/IDLE/2018-05-23-19-51-07.bpo-33628.sLlFLO.rst +++ /dev/null @@ -1,2 +0,0 @@ -IDLE: Cleanup codecontext.py and its test. - diff --git a/Misc/NEWS.d/next/Library/2017-09-29-16-40-38.bpo-16865.l-f6I_.rst b/Misc/NEWS.d/next/Library/2017-09-29-16-40-38.bpo-16865.l-f6I_.rst deleted file mode 100644 index afaff736bf1c..000000000000 --- a/Misc/NEWS.d/next/Library/2017-09-29-16-40-38.bpo-16865.l-f6I_.rst +++ /dev/null @@ -1 +0,0 @@ -Support arrays >=2GiB in :mod:`ctypes`. Patch by Segev Finer. diff --git a/Misc/NEWS.d/next/Library/2018-02-26-09-08-07.bpo-32257.6ElnUt.rst b/Misc/NEWS.d/next/Library/2018-02-26-09-08-07.bpo-32257.6ElnUt.rst deleted file mode 100644 index e74c39b68100..000000000000 --- a/Misc/NEWS.d/next/Library/2018-02-26-09-08-07.bpo-32257.6ElnUt.rst +++ /dev/null @@ -1,2 +0,0 @@ -The ssl module now contains OP_NO_RENEGOTIATION constant, available with -OpenSSL 1.1.0h or 1.1.1. diff --git a/Misc/NEWS.d/next/Library/2018-04-02-20-44-54.bpo-32861.HeBjzN.rst b/Misc/NEWS.d/next/Library/2018-04-02-20-44-54.bpo-32861.HeBjzN.rst deleted file mode 100644 index 13defbb03cff..000000000000 --- a/Misc/NEWS.d/next/Library/2018-04-02-20-44-54.bpo-32861.HeBjzN.rst +++ /dev/null @@ -1,3 +0,0 @@ -The urllib.robotparser's ``__str__`` representation now includes wildcard -entries and the "Crawl-delay" and "Request-rate" fields. Patch by -Michael Lazar. diff --git a/Misc/NEWS.d/next/Library/2018-04-11-20-29-19.bpo-33263.B56Hc1.rst b/Misc/NEWS.d/next/Library/2018-04-11-20-29-19.bpo-33263.B56Hc1.rst deleted file mode 100644 index 77994f6a5986..000000000000 --- a/Misc/NEWS.d/next/Library/2018-04-11-20-29-19.bpo-33263.B56Hc1.rst +++ /dev/null @@ -1 +0,0 @@ -Fix FD leak in `_SelectorSocketTransport` Patch by Vlad Starostin. diff --git a/Misc/NEWS.d/next/Library/2018-04-29-23-56-20.bpo-33197.dgRLqr.rst b/Misc/NEWS.d/next/Library/2018-04-29-23-56-20.bpo-33197.dgRLqr.rst deleted file mode 100644 index 1bbb44b2fc39..000000000000 --- a/Misc/NEWS.d/next/Library/2018-04-29-23-56-20.bpo-33197.dgRLqr.rst +++ /dev/null @@ -1,2 +0,0 @@ -Update error message when constructing invalid inspect.Parameters -Patch by Dong-hee Na. diff --git a/Misc/NEWS.d/next/Library/2018-05-02-07-26-29.bpo-28167.7FwDfN.rst b/Misc/NEWS.d/next/Library/2018-05-02-07-26-29.bpo-28167.7FwDfN.rst deleted file mode 100644 index a4971e5b77ba..000000000000 --- a/Misc/NEWS.d/next/Library/2018-05-02-07-26-29.bpo-28167.7FwDfN.rst +++ /dev/null @@ -1,3 +0,0 @@ -The function ``platform.linux_ditribution`` and ``platform.dist`` now -trigger a ``DeprecationWarning`` and have been marked for removal in Python -3.8 diff --git a/Misc/NEWS.d/next/Library/2018-05-05-09-53-05.bpo-33422.4FtQ0q.rst b/Misc/NEWS.d/next/Library/2018-05-05-09-53-05.bpo-33422.4FtQ0q.rst deleted file mode 100644 index 0d284d508f10..000000000000 --- a/Misc/NEWS.d/next/Library/2018-05-05-09-53-05.bpo-33422.4FtQ0q.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix trailing quotation marks getting deleted when looking up byte/string -literals on pydoc. Patch by Andr?s Delfino. diff --git a/Misc/NEWS.d/next/Library/2018-05-05-18-02-24.bpo-20087.lJrvXL.rst b/Misc/NEWS.d/next/Library/2018-05-05-18-02-24.bpo-20087.lJrvXL.rst deleted file mode 100644 index 2342cb781926..000000000000 --- a/Misc/NEWS.d/next/Library/2018-05-05-18-02-24.bpo-20087.lJrvXL.rst +++ /dev/null @@ -1 +0,0 @@ -Updated alias mapping with glibc 2.27 supported locales. diff --git a/Misc/NEWS.d/next/Library/2018-05-08-16-43-42.bpo-28556._xr5mp.rst b/Misc/NEWS.d/next/Library/2018-05-08-16-43-42.bpo-28556._xr5mp.rst deleted file mode 100644 index 8ed4658211fb..000000000000 --- a/Misc/NEWS.d/next/Library/2018-05-08-16-43-42.bpo-28556._xr5mp.rst +++ /dev/null @@ -1,3 +0,0 @@ -Minor fixes in typing module: add annotations to ``NamedTuple.__new__``, -pass ``*args`` and ``**kwds`` in ``Generic.__new__``. Original PRs by -Paulius ?arka and Chad Dombrova. diff --git a/Misc/NEWS.d/next/Library/2018-05-12-06-01-02.bpo-33453.Fj-jMD.rst b/Misc/NEWS.d/next/Library/2018-05-12-06-01-02.bpo-33453.Fj-jMD.rst deleted file mode 100644 index 6595b1265a4e..000000000000 --- a/Misc/NEWS.d/next/Library/2018-05-12-06-01-02.bpo-33453.Fj-jMD.rst +++ /dev/null @@ -1,4 +0,0 @@ -Fix dataclasses to work if using literal string type annotations or if using -PEP 563 "Postponed Evaluation of Annotations". Only specific string -prefixes are detected for both ClassVar ("ClassVar" and "typing.ClassVar") -and InitVar ("InitVar" and "dataclasses.InitVar"). diff --git a/Misc/NEWS.d/next/Library/2018-05-14-10-29-03.bpo-33495.TeGTQJ.rst b/Misc/NEWS.d/next/Library/2018-05-14-10-29-03.bpo-33495.TeGTQJ.rst deleted file mode 100644 index 22cf04cd2e43..000000000000 --- a/Misc/NEWS.d/next/Library/2018-05-14-10-29-03.bpo-33495.TeGTQJ.rst +++ /dev/null @@ -1,3 +0,0 @@ -Change dataclasses.Fields repr to use the repr of each of its members, -instead of str. This makes it more clear what each field actually -represents. This is especially true for the 'type' member. diff --git a/Misc/NEWS.d/next/Library/2018-05-14-17-49-34.bpo-33497.wWT6XM.rst b/Misc/NEWS.d/next/Library/2018-05-14-17-49-34.bpo-33497.wWT6XM.rst deleted file mode 100644 index d919dfdca75e..000000000000 --- a/Misc/NEWS.d/next/Library/2018-05-14-17-49-34.bpo-33497.wWT6XM.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add errors param to cgi.parse_multipart and make an encoding in FieldStorage -use the given errors (needed for Twisted). Patch by Amber Brown. diff --git a/Misc/NEWS.d/next/Library/2018-05-14-18-05-35.bpo-33505.L8pAyt.rst b/Misc/NEWS.d/next/Library/2018-05-14-18-05-35.bpo-33505.L8pAyt.rst deleted file mode 100644 index 201b02781c18..000000000000 --- a/Misc/NEWS.d/next/Library/2018-05-14-18-05-35.bpo-33505.L8pAyt.rst +++ /dev/null @@ -1 +0,0 @@ -Optimize asyncio.ensure_future() by reordering if checks: 1.17x faster. diff --git a/Misc/NEWS.d/next/Library/2018-05-15-18-02-03.bpo-0.pj2Mbb.rst b/Misc/NEWS.d/next/Library/2018-05-15-18-02-03.bpo-0.pj2Mbb.rst deleted file mode 100644 index ba8514cdd895..000000000000 --- a/Misc/NEWS.d/next/Library/2018-05-15-18-02-03.bpo-0.pj2Mbb.rst +++ /dev/null @@ -1 +0,0 @@ -Fix failure in `typing.get_type_hints()` when ClassVar was provided as a string forward reference. diff --git a/Misc/NEWS.d/next/Library/2018-05-16-05-24-43.bpo-26819.taxbVT.rst b/Misc/NEWS.d/next/Library/2018-05-16-05-24-43.bpo-26819.taxbVT.rst deleted file mode 100644 index d407a5800318..000000000000 --- a/Misc/NEWS.d/next/Library/2018-05-16-05-24-43.bpo-26819.taxbVT.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix race condition with `ReadTransport.resume_reading` in Windows proactor -event loop. diff --git a/Misc/NEWS.d/next/Library/2018-05-16-09-30-27.bpo-33542.idNAcs.rst b/Misc/NEWS.d/next/Library/2018-05-16-09-30-27.bpo-33542.idNAcs.rst deleted file mode 100644 index 16ba799131f4..000000000000 --- a/Misc/NEWS.d/next/Library/2018-05-16-09-30-27.bpo-33542.idNAcs.rst +++ /dev/null @@ -1,2 +0,0 @@ -Prevent ``uuid.get_node`` from using a DUID instead of a MAC on Windows. -Patch by Zvi Effron diff --git a/Misc/NEWS.d/next/Library/2018-05-16-10-07-40.bpo-33536._s0TE8.rst b/Misc/NEWS.d/next/Library/2018-05-16-10-07-40.bpo-33536._s0TE8.rst deleted file mode 100644 index 2c1024180d34..000000000000 --- a/Misc/NEWS.d/next/Library/2018-05-16-10-07-40.bpo-33536._s0TE8.rst +++ /dev/null @@ -1,2 +0,0 @@ -dataclasses.make_dataclass now checks for invalid field names and duplicate -fields. Also, added a check for invalid field specifications. diff --git a/Misc/NEWS.d/next/Library/2018-05-16-14-57-58.bpo-33109.nPLL_S.rst b/Misc/NEWS.d/next/Library/2018-05-16-14-57-58.bpo-33109.nPLL_S.rst deleted file mode 100644 index be731f99f7f0..000000000000 --- a/Misc/NEWS.d/next/Library/2018-05-16-14-57-58.bpo-33109.nPLL_S.rst +++ /dev/null @@ -1,2 +0,0 @@ -argparse subparsers are once again not required by default, reverting the -change in behavior introduced by bpo-26510 in 3.7.0a2. diff --git a/Misc/NEWS.d/next/Library/2018-05-16-17-05-48.bpo-33548.xWslmx.rst b/Misc/NEWS.d/next/Library/2018-05-16-17-05-48.bpo-33548.xWslmx.rst deleted file mode 100644 index 65585c152987..000000000000 --- a/Misc/NEWS.d/next/Library/2018-05-16-17-05-48.bpo-33548.xWslmx.rst +++ /dev/null @@ -1 +0,0 @@ -tempfile._candidate_tempdir_list should consider common TEMP locations diff --git a/Misc/NEWS.d/next/Library/2018-05-16-18-10-38.bpo-33540.wy9LRV.rst b/Misc/NEWS.d/next/Library/2018-05-16-18-10-38.bpo-33540.wy9LRV.rst deleted file mode 100644 index 9019cc14f515..000000000000 --- a/Misc/NEWS.d/next/Library/2018-05-16-18-10-38.bpo-33540.wy9LRV.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add a new ``block_on_close`` class attribute to ``ForkingMixIn`` and -``ThreadingMixIn`` classes of :mod:`socketserver`. diff --git a/Misc/NEWS.d/next/Library/2018-05-17-22-53-08.bpo-28556.C6Hnd1.rst b/Misc/NEWS.d/next/Library/2018-05-17-22-53-08.bpo-28556.C6Hnd1.rst deleted file mode 100644 index 35e13bde1897..000000000000 --- a/Misc/NEWS.d/next/Library/2018-05-17-22-53-08.bpo-28556.C6Hnd1.rst +++ /dev/null @@ -1,3 +0,0 @@ -Do not simplify arguments to `typing.Union`. Now `Union[Manager, Employee]` -is not simplified to `Employee` at runtime. Such simplification previously -caused several bugs and limited possibilities for introspection. diff --git a/Misc/NEWS.d/next/Library/2018-05-18-21-50-47.bpo-33570.7CZy4t.rst b/Misc/NEWS.d/next/Library/2018-05-18-21-50-47.bpo-33570.7CZy4t.rst deleted file mode 100644 index bd719a47e8f8..000000000000 --- a/Misc/NEWS.d/next/Library/2018-05-18-21-50-47.bpo-33570.7CZy4t.rst +++ /dev/null @@ -1,3 +0,0 @@ -Change TLS 1.3 cipher suite settings for compatibility with OpenSSL -1.1.1-pre6 and newer. OpenSSL 1.1.1 will have TLS 1.3 cipers enabled by -default. diff --git a/Misc/NEWS.d/next/Library/2018-05-22-13-05-12.bpo-30877.JZEGjI.rst b/Misc/NEWS.d/next/Library/2018-05-22-13-05-12.bpo-30877.JZEGjI.rst deleted file mode 100644 index 4be0fae4ecb6..000000000000 --- a/Misc/NEWS.d/next/Library/2018-05-22-13-05-12.bpo-30877.JZEGjI.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fixed a bug in the Python implementation of the JSON decoder that prevented -the cache of parsed strings from clearing after finishing the decoding. -Based on patch by c-fos. diff --git a/Misc/NEWS.d/next/Library/2018-05-23-14-58-05.bpo-33623.wAw1cF.rst b/Misc/NEWS.d/next/Library/2018-05-23-14-58-05.bpo-33623.wAw1cF.rst deleted file mode 100644 index 641874c3ca39..000000000000 --- a/Misc/NEWS.d/next/Library/2018-05-23-14-58-05.bpo-33623.wAw1cF.rst +++ /dev/null @@ -1 +0,0 @@ -Fix possible SIGSGV when asyncio.Future is created in __del__ diff --git a/Misc/NEWS.d/next/Library/2018-05-23-20-14-34.bpo-33618.xU39lr.rst b/Misc/NEWS.d/next/Library/2018-05-23-20-14-34.bpo-33618.xU39lr.rst deleted file mode 100644 index 6cc2452b145c..000000000000 --- a/Misc/NEWS.d/next/Library/2018-05-23-20-14-34.bpo-33618.xU39lr.rst +++ /dev/null @@ -1,2 +0,0 @@ -Finalize and document preliminary and experimental TLS 1.3 support with -OpenSSL 1.1.1 diff --git a/Misc/NEWS.d/next/Library/2018-05-24-17-41-36.bpo-32493.5tAoAu.rst b/Misc/NEWS.d/next/Library/2018-05-24-17-41-36.bpo-32493.5tAoAu.rst deleted file mode 100644 index 32f88dd0388d..000000000000 --- a/Misc/NEWS.d/next/Library/2018-05-24-17-41-36.bpo-32493.5tAoAu.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed :func:`uuid.uuid1` on FreeBSD. diff --git a/Misc/NEWS.d/next/Library/2018-05-26-10-13-59.bpo-33652.humFJ1.rst b/Misc/NEWS.d/next/Library/2018-05-26-10-13-59.bpo-33652.humFJ1.rst deleted file mode 100644 index f5499f1b53ce..000000000000 --- a/Misc/NEWS.d/next/Library/2018-05-26-10-13-59.bpo-33652.humFJ1.rst +++ /dev/null @@ -1,2 +0,0 @@ -Pickles of type variables and subscripted generics are now future-proof and -compatible with older Python versions. diff --git a/Misc/NEWS.d/next/Library/2018-05-26-13-09-34.bpo-33654.IbYWxA.rst b/Misc/NEWS.d/next/Library/2018-05-26-13-09-34.bpo-33654.IbYWxA.rst deleted file mode 100644 index 3ae506ddc55f..000000000000 --- a/Misc/NEWS.d/next/Library/2018-05-26-13-09-34.bpo-33654.IbYWxA.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix transport.set_protocol() to support switching between asyncio.Protocol -and asyncio.BufferedProtocol. Fix loop.start_tls() to work with -asyncio.BufferedProtocols. diff --git a/Misc/NEWS.d/next/Library/2018-05-28-12-29-54.bpo-33672.GM_Xm_.rst b/Misc/NEWS.d/next/Library/2018-05-28-12-29-54.bpo-33672.GM_Xm_.rst deleted file mode 100644 index 36373c028639..000000000000 --- a/Misc/NEWS.d/next/Library/2018-05-28-12-29-54.bpo-33672.GM_Xm_.rst +++ /dev/null @@ -1 +0,0 @@ -Fix Task.__repr__ crash with Cython's bogus coroutines diff --git a/Misc/NEWS.d/next/Library/2018-05-28-15-55-12.bpo-33469.hmXBpY.rst b/Misc/NEWS.d/next/Library/2018-05-28-15-55-12.bpo-33469.hmXBpY.rst deleted file mode 100644 index cc1b2e436f2a..000000000000 --- a/Misc/NEWS.d/next/Library/2018-05-28-15-55-12.bpo-33469.hmXBpY.rst +++ /dev/null @@ -1 +0,0 @@ -Fix RuntimeError after closing loop that used run_in_executor diff --git a/Misc/NEWS.d/next/Library/2018-05-28-16-19-35.bpo-32410.Z1DZaF.rst b/Misc/NEWS.d/next/Library/2018-05-28-16-19-35.bpo-32410.Z1DZaF.rst deleted file mode 100644 index 2d7bb2032ac5..000000000000 --- a/Misc/NEWS.d/next/Library/2018-05-28-16-19-35.bpo-32410.Z1DZaF.rst +++ /dev/null @@ -1 +0,0 @@ -Avoid blocking on file IO in sendfile fallback code diff --git a/Misc/NEWS.d/next/Library/2018-05-28-16-40-32.bpo-32610.KvUAsL.rst b/Misc/NEWS.d/next/Library/2018-05-28-16-40-32.bpo-32610.KvUAsL.rst deleted file mode 100644 index 372908063247..000000000000 --- a/Misc/NEWS.d/next/Library/2018-05-28-16-40-32.bpo-32610.KvUAsL.rst +++ /dev/null @@ -1 +0,0 @@ -Make asyncio.all_tasks() return only pending tasks. diff --git a/Misc/NEWS.d/next/Library/2018-05-28-18-40-26.bpo-31467.s4Fad3.rst b/Misc/NEWS.d/next/Library/2018-05-28-18-40-26.bpo-31467.s4Fad3.rst deleted file mode 100644 index 61cc8baa1cd5..000000000000 --- a/Misc/NEWS.d/next/Library/2018-05-28-18-40-26.bpo-31467.s4Fad3.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed bug where calling write_eof() on a _SelectorSocketTransport after it's -already closed raises AttributeError. diff --git a/Misc/NEWS.d/next/Library/2018-05-28-22-49-59.bpo-33674.6LFFj7.rst b/Misc/NEWS.d/next/Library/2018-05-28-22-49-59.bpo-33674.6LFFj7.rst deleted file mode 100644 index 1e9868073f78..000000000000 --- a/Misc/NEWS.d/next/Library/2018-05-28-22-49-59.bpo-33674.6LFFj7.rst +++ /dev/null @@ -1,4 +0,0 @@ -Fix a race condition in SSLProtocol.connection_made() of asyncio.sslproto: -start immediately the handshake instead of using call_soon(). Previously, -data_received() could be called before the handshake started, causing the -handshake to hang or fail. diff --git a/Misc/NEWS.d/next/Library/2018-05-29-00-37-56.bpo-33674.2IkGhL.rst b/Misc/NEWS.d/next/Library/2018-05-29-00-37-56.bpo-33674.2IkGhL.rst deleted file mode 100644 index 66baca16d69f..000000000000 --- a/Misc/NEWS.d/next/Library/2018-05-29-00-37-56.bpo-33674.2IkGhL.rst +++ /dev/null @@ -1,2 +0,0 @@ -Pause the transport as early as possible to further reduce the risk of -data_received() being called before connection_made(). diff --git a/Misc/NEWS.d/next/Library/2018-05-29-01-13-39.bpo-33654.sa81Si.rst b/Misc/NEWS.d/next/Library/2018-05-29-01-13-39.bpo-33654.sa81Si.rst deleted file mode 100644 index 39e8e615d8c4..000000000000 --- a/Misc/NEWS.d/next/Library/2018-05-29-01-13-39.bpo-33654.sa81Si.rst +++ /dev/null @@ -1 +0,0 @@ -Support protocol type switching in SSLTransport.set_protocol(). diff --git a/Misc/NEWS.d/next/Library/2018-05-29-12-51-18.bpo-32684.ZEIism.rst b/Misc/NEWS.d/next/Library/2018-05-29-12-51-18.bpo-32684.ZEIism.rst deleted file mode 100644 index b360bbcf7998..000000000000 --- a/Misc/NEWS.d/next/Library/2018-05-29-12-51-18.bpo-32684.ZEIism.rst +++ /dev/null @@ -1 +0,0 @@ -Fix gather to propagate cancellation of itself even with return_exceptions. diff --git a/Misc/NEWS.d/next/Library/2018-05-29-15-32-18.bpo-32751.oBTqr7.rst b/Misc/NEWS.d/next/Library/2018-05-29-15-32-18.bpo-32751.oBTqr7.rst deleted file mode 100644 index 3e27cd461ca8..000000000000 --- a/Misc/NEWS.d/next/Library/2018-05-29-15-32-18.bpo-32751.oBTqr7.rst +++ /dev/null @@ -1,2 +0,0 @@ -When cancelling the task due to a timeout, :meth:`asyncio.wait_for` will now -wait until the cancellation is complete. diff --git a/Misc/NEWS.d/next/Tests/2018-05-14-13-32-46.bpo-32604.a_z6D_.rst b/Misc/NEWS.d/next/Tests/2018-05-14-13-32-46.bpo-32604.a_z6D_.rst deleted file mode 100644 index f854dd95412a..000000000000 --- a/Misc/NEWS.d/next/Tests/2018-05-14-13-32-46.bpo-32604.a_z6D_.rst +++ /dev/null @@ -1,2 +0,0 @@ -Remove the _xxsubinterpreters module (meant for testing) and associated -helpers. This module was originally added recently in 3.7b1. diff --git a/Misc/NEWS.d/next/Tests/2018-05-26-16-01-40.bpo-33655.Frb4LA.rst b/Misc/NEWS.d/next/Tests/2018-05-26-16-01-40.bpo-33655.Frb4LA.rst deleted file mode 100644 index 7ed2ea232371..000000000000 --- a/Misc/NEWS.d/next/Tests/2018-05-26-16-01-40.bpo-33655.Frb4LA.rst +++ /dev/null @@ -1,2 +0,0 @@ -Ignore test_posix_fallocate failures on BSD platforms that might be due to -running on ZFS. diff --git a/Misc/NEWS.d/next/macOS/2018-05-16-13-25-58.bpo-13631.UIjDyY.rst b/Misc/NEWS.d/next/macOS/2018-05-16-13-25-58.bpo-13631.UIjDyY.rst deleted file mode 100644 index d9d505e937a8..000000000000 --- a/Misc/NEWS.d/next/macOS/2018-05-16-13-25-58.bpo-13631.UIjDyY.rst +++ /dev/null @@ -1,2 +0,0 @@ -The .editrc file in user's home directory is now processed correctly during -the readline initialization through editline emulation on macOS. diff --git a/README.rst b/README.rst index 2341b53c7102..411a38fb09d7 100644 --- a/README.rst +++ b/README.rst @@ -1,5 +1,5 @@ -This is Python version 3.7.0 beta 4+ -==================================== +This is Python version 3.7.0 beta 5 +=================================== .. image:: https://travis-ci.org/python/cpython.svg?branch=master :alt: CPython build status on Travis CI From lp_benchmark_robot at intel.com Wed May 30 21:32:33 2018 From: lp_benchmark_robot at intel.com (lp_benchmark_robot at intel.com) Date: Wed, 30 May 2018 18:32:33 -0700 Subject: [Python-checkins] [65 flat] Results for Python (master branch) 2018-05-28 Message-ID: <3cbe39e4-18d7-46bf-8f2c-d3c8dfa8f115@orsmsx109.amr.corp.intel.com> Results for project python/master, build date: 2018-05-28 03:03:44-07:00. - commit: c651275 - previous commit: 6e413f4 - revision date: 2018-05-26 13:38:33-07:00 - environment: Broadwell-EP - cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores, stepping 1, LLC 55 MB - mem: 128 GB - os: Ubuntu 16.04.2 LTS - kernel: 4.4.0-62-generic x86_64 GNU/Linux Baseline results were generated using release v3.6.0, with hash 5c4568a from 2016-12-22 23:38:47+00:00. +-----+------------------------+--------+------------+------------+------------+ | | |relative|change since|change since|current rev | | | benchmark|std_dev*| last run | baseline |run with PGO| +-----+------------------------+--------+------------+------------+------------+ | :-| | 2to3| 0.604% | -0.139% | +8.945% | +6.964% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method| 0.765% | +0.651% | +24.242% | +13.944% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_slots| 0.733% | +0.694% | +25.961% | +12.263% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_method_unknown| 1.242% | -0.144% | +22.245% | +14.424% | +-----+------------------------+--------+------------+------------+------------+ | :-| | call_simple| 4.096% | -0.823% | +10.456% | +12.871% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chameleon| 1.448% | +0.497% | +12.627% | +11.354% | +-----+------------------------+--------+------------+------------+------------+ | :-| | chaos| 0.831% | -0.066% | +8.461% | +10.520% | +-----+------------------------+--------+------------+------------+------------+ | :-| | crypto_pyaes| 0.525% | -0.051% | -0.511% | +8.045% | +-----+------------------------+--------+------------+------------+------------+ | :-| | deltablue| 3.764% | -1.008% | +11.391% | +17.084% | +-----+------------------------+--------+------------+------------+------------+ | :-| | django_template| 3.608% | -2.678% | +20.301% | +13.639% | +-----+------------------------+--------+------------+------------+------------+ | :-| | dulwich_log| 1.506% | -0.629% | +4.591% | +7.490% | +-----+------------------------+--------+------------+------------+------------+ | :-| | fannkuch| 0.423% | -0.062% | +6.104% | +6.527% | +-----+------------------------+--------+------------+------------+------------+ | :-| | float| 1.491% | +0.648% | +2.727% | +8.218% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_text| 1.140% | -0.253% | +14.171% | +10.308% | +-----+------------------------+--------+------------+------------+------------+ | :-| | genshi_xml| 1.430% | -0.665% | +11.043% | +9.983% | +-----+------------------------+--------+------------+------------+------------+ | :-| | go| 5.790% | +0.216% | +5.427% | +10.440% | +-----+------------------------+--------+------------+------------+------------+ | :-| | hexiom| 0.445% | +0.214% | +12.159% | +11.171% | +-----+------------------------+--------+------------+------------+------------+ | :-| | html5lib| 4.485% | -2.128% | +9.717% | +10.556% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_dumps| 2.136% | -0.053% | +3.573% | +9.583% | +-----+------------------------+--------+------------+------------+------------+ | :-| | json_loads| 4.848% | +0.552% | -3.626% | +13.601% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_format| 1.775% | -0.892% | +16.477% | +13.100% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_silent| 2.527% | +0.057% | +48.001% | +13.482% | +-----+------------------------+--------+------------+------------+------------+ | :-| | logging_simple| 1.559% | -0.803% | +11.409% | +13.940% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mako| 0.760% | -0.216% | +16.476% | +14.242% | +-----+------------------------+--------+------------+------------+------------+ | :-| | mdp| 5.554% | -0.030% | +1.303% | +16.346% | +-----+------------------------+--------+------------+------------+------------+ | :-| | meteor_contest| 0.938% | +0.014% | +4.627% | +6.176% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nbody| 0.679% | +0.543% | +0.033% | +0.650% | +-----+------------------------+--------+------------+------------+------------+ | :-| | nqueens| 0.529% | -0.060% | +5.313% | +8.069% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pathlib| 1.572% | -0.946% | +0.112% | +10.730% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle| 4.688% | -0.994% | -1.950% | +24.649% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_dict| 5.842% | -0.913% | +6.715% | +19.150% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_list| 2.222% | +0.109% | +6.800% | +17.806% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pickle_pure_python| 4.798% | -0.713% | +11.233% | +11.059% | +-----+------------------------+--------+------------+------------+------------+ | :-| | pidigits| 0.066% | +0.049% | +0.221% | +9.848% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup| 0.127% | -0.204% | +18.870% | +5.079% | +-----+------------------------+--------+------------+------------+------------+ | :-| | python_startup_no_site| 0.084% | -0.222% | +5.863% | +5.331% | +-----+------------------------+--------+------------+------------+------------+ | :-| | raytrace| 0.864% | -0.598% | +10.019% | +15.174% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_compile| 5.735% | +0.606% | +4.300% | +10.772% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_dna| 0.499% | -0.168% | -2.236% | +12.652% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_effbot| 3.846% | -1.080% | -8.058% | +9.952% | +-----+------------------------+--------+------------+------------+------------+ | :-| | regex_v8| 1.595% | -0.487% | +3.567% | +9.321% | +-----+------------------------+--------+------------+------------+------------+ | :-| | richards| 1.411% | +0.199% | +9.448% | +16.164% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_fft| 0.516% | -0.043% | -1.661% | +3.515% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_lu| 3.645% | +0.798% | +23.042% | +12.732% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_monte_carlo| 2.144% | +0.014% | +5.120% | +5.756% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sor| 1.160% | +0.306% | +15.300% | +8.982% | +-----+------------------------+--------+------------+------------+------------+ | :-| | scimark_sparse_mat_mult| 2.793% | -0.667% | -3.832% | +3.032% | +-----+------------------------+--------+------------+------------+------------+ | :-| | spectral_norm| 0.556% | -0.166% | +4.514% | +6.817% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_declarative| 1.396% | -1.131% | +6.481% | +6.701% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlalchemy_imperative| 3.609% | +0.115% | +7.596% | +4.962% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sqlite_synth| 3.390% | -0.383% | -0.081% | +10.628% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_expand| 2.852% | +0.225% | +18.044% | +7.085% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_integrate| 1.624% | -0.210% | +18.551% | +6.409% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_str| 4.193% | -0.532% | +19.247% | +7.472% | +-----+------------------------+--------+------------+------------+------------+ | :-| | sympy_sum| 6.348% | -1.509% | +14.980% | +11.302% | +-----+------------------------+--------+------------+------------+------------+ | :-| | telco| 3.468% | +0.052% | +20.003% | +9.386% | +-----+------------------------+--------+------------+------------+------------+ | :-| | tornado_http| 0.993% | -0.235% | +7.466% | +6.322% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpack_sequence| 0.960% | +0.299% | +2.715% | -0.621% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle| 9.000% | -0.139% | +5.976% | +23.435% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_list| 1.912% | -0.583% | -3.534% | +15.606% | +-----+------------------------+--------+------------+------------+------------+ | :-| | unpickle_pure_python| 1.752% | +0.305% | +7.499% | +8.264% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_generate| 1.248% | -0.199% | +2.325% | +12.892% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_iterparse| 1.727% | -0.157% | +4.120% | +9.860% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_parse| 3.083% | -1.695% | -7.095% | +12.286% | +-----+------------------------+--------+------------+------------+------------+ | :-| | xml_etree_process| 2.164% | -0.477% | +4.263% | +12.258% | +-----+------------------------+--------+------------+------------+------------+ * Relative Standard Deviation (Standard Deviation/Average) If this is not displayed properly please visit our results page here: http://languagesperformance.intel.com/65-flat-results-for-python-master-branch-2018-05-28 Our lab does a nightly source pull and build of the Python project and measures performance changes against the previous stable version and the previous nightly measurement. This is provided as a service to the community so that quality issues with current hardware can be identified quickly. Intel technologies' features and benefits depend on system configuration and may require enabled hardware, software or service activation. Performance varies depending on system configuration. From webhook-mailer at python.org Wed May 30 23:08:45 2018 From: webhook-mailer at python.org (Victor Stinner) Date: Thu, 31 May 2018 03:08:45 -0000 Subject: [Python-checkins] bpo-33532: Fix multiprocessing test_ignore() (#7262) Message-ID: <mailman.107.1527736126.2800.python-checkins@python.org> https://github.com/python/cpython/commit/5d6c7ed5e340b2311a15f34e968d4bef09c71922 commit: 5d6c7ed5e340b2311a15f34e968d4bef09c71922 branch: master author: Victor Stinner <vstinner at redhat.com> committer: GitHub <noreply at github.com> date: 2018-05-31T05:08:42+02:00 summary: bpo-33532: Fix multiprocessing test_ignore() (#7262) Fix test_ignore() of multiprocessing tests like test_multiprocessing_forkserver: use support.PIPE_MAX_SIZE to make sure that send_bytes() blocks. files: M Lib/test/_test_multiprocessing.py diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index 8b6bc4b23a02..2e24e9bc1565 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -4338,7 +4338,7 @@ def handler(signum, frame): conn.send('ready') x = conn.recv() conn.send(x) - conn.send_bytes(b'x' * (1024 * 1024)) # sending 1 MiB should block + conn.send_bytes(b'x' * support.PIPE_MAX_SIZE) @unittest.skipUnless(hasattr(signal, 'SIGUSR1'), 'requires SIGUSR1') def test_ignore(self): @@ -4357,7 +4357,7 @@ def test_ignore(self): self.assertEqual(conn.recv(), 1234) time.sleep(0.1) os.kill(p.pid, signal.SIGUSR1) - self.assertEqual(conn.recv_bytes(), b'x'*(1024*1024)) + self.assertEqual(conn.recv_bytes(), b'x' * support.PIPE_MAX_SIZE) time.sleep(0.1) p.join() finally: From webhook-mailer at python.org Wed May 30 23:28:09 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 31 May 2018 03:28:09 -0000 Subject: [Python-checkins] bpo-33532: Fix multiprocessing test_ignore() (GH-7262) Message-ID: <mailman.108.1527737295.2800.python-checkins@python.org> https://github.com/python/cpython/commit/9d273344238330d634acb4a7d427a8fb732ae62e commit: 9d273344238330d634acb4a7d427a8fb732ae62e branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-30T20:28:04-07:00 summary: bpo-33532: Fix multiprocessing test_ignore() (GH-7262) Fix test_ignore() of multiprocessing tests like test_multiprocessing_forkserver: use support.PIPE_MAX_SIZE to make sure that send_bytes() blocks. (cherry picked from commit 5d6c7ed5e340b2311a15f34e968d4bef09c71922) Co-authored-by: Victor Stinner <vstinner at redhat.com> files: M Lib/test/_test_multiprocessing.py diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index aa8eb7564130..f29dda70029b 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -4303,7 +4303,7 @@ def handler(signum, frame): conn.send('ready') x = conn.recv() conn.send(x) - conn.send_bytes(b'x' * (1024 * 1024)) # sending 1 MiB should block + conn.send_bytes(b'x' * support.PIPE_MAX_SIZE) @unittest.skipUnless(hasattr(signal, 'SIGUSR1'), 'requires SIGUSR1') def test_ignore(self): @@ -4322,7 +4322,7 @@ def test_ignore(self): self.assertEqual(conn.recv(), 1234) time.sleep(0.1) os.kill(p.pid, signal.SIGUSR1) - self.assertEqual(conn.recv_bytes(), b'x'*(1024*1024)) + self.assertEqual(conn.recv_bytes(), b'x' * support.PIPE_MAX_SIZE) time.sleep(0.1) p.join() finally: From webhook-mailer at python.org Thu May 31 00:34:38 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Thu, 31 May 2018 04:34:38 -0000 Subject: [Python-checkins] bpo-33677: Fix signatures of tp_clear handlers for AST and deque. (GH-7196) Message-ID: <mailman.109.1527741282.2800.python-checkins@python.org> https://github.com/python/cpython/commit/a5c42284e69fb309bdd17ee8c1c120d1be383012 commit: a5c42284e69fb309bdd17ee8c1c120d1be383012 branch: master author: Serhiy Storchaka <storchaka at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-31T07:34:34+03:00 summary: bpo-33677: Fix signatures of tp_clear handlers for AST and deque. (GH-7196) files: M Modules/_collectionsmodule.c M Parser/asdl_c.py M Python/Python-ast.c diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c index 55132e786d5b..65d556c5a0e5 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -575,7 +575,7 @@ deque_concat(dequeobject *deque, PyObject *other) return new_deque; } -static void +static int deque_clear(dequeobject *deque) { block *b; @@ -587,7 +587,7 @@ deque_clear(dequeobject *deque) PyObject **itemptr, **limit; if (Py_SIZE(deque) == 0) - return; + return 0; /* During the process of clearing a deque, decrefs can cause the deque to mutate. To avoid fatal confusion, we have to make the @@ -648,7 +648,7 @@ deque_clear(dequeobject *deque) } CHECK_END(leftblock->rightlink); freeblock(leftblock); - return; + return 0; alternate_method: while (Py_SIZE(deque)) { @@ -656,6 +656,7 @@ deque_clear(dequeobject *deque) assert (item != NULL); Py_DECREF(item); } + return 0; } static PyObject * diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py index 399e79e0597f..44e3d40c6155 100644 --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -647,10 +647,11 @@ def visitModule(self, mod): return 0; } -static void +static int ast_clear(AST_object *self) { Py_CLEAR(self->dict); + return 0; } static int diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 38b9292577f2..6a2f28e0e712 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -528,10 +528,11 @@ ast_traverse(AST_object *self, visitproc visit, void *arg) return 0; } -static void +static int ast_clear(AST_object *self) { Py_CLEAR(self->dict); + return 0; } static int From webhook-mailer at python.org Thu May 31 00:35:42 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Thu, 31 May 2018 04:35:42 -0000 Subject: [Python-checkins] bpo-33645: Fix an "unknown parsing error" in the parser. (GH-7119) Message-ID: <mailman.110.1527741346.2800.python-checkins@python.org> https://github.com/python/cpython/commit/d5e7556e522f4662ad34b35924b6c76895df340e commit: d5e7556e522f4662ad34b35924b6c76895df340e branch: 2.7 author: Serhiy Storchaka <storchaka at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-31T07:35:39+03:00 summary: bpo-33645: Fix an "unknown parsing error" in the parser. (GH-7119) It is reproduced when parse the "<>" operator and run Python with both options -3 and -We. files: A Misc/NEWS.d/next/Core and Builtins/2018-05-25-18-20-04.bpo-33645.GYGIPH.rst M Lib/test/test_grammar.py M Parser/tokenizer.c diff --git a/Lib/test/test_grammar.py b/Lib/test/test_grammar.py index 23b6ce8d3c5c..228586ece02a 100644 --- a/Lib/test/test_grammar.py +++ b/Lib/test/test_grammar.py @@ -5,6 +5,7 @@ check_py3k_warnings import unittest import sys +import warnings # testing import * from sys import * @@ -628,7 +629,6 @@ def check(code, warntext): with check_py3k_warnings((warntext, DeprecationWarning)): compile(code, '<test string>', 'exec') if sys.py3kwarning: - import warnings with warnings.catch_warnings(): warnings.filterwarnings('error', category=DeprecationWarning) with self.assertRaises(SyntaxError) as cm: @@ -883,6 +883,13 @@ def test_comparison(self): with check_py3k_warnings(('<> not supported in 3.x; use !=', DeprecationWarning)): if eval('1 < 1 > 1 == 1 >= 1 <= 1 <> 1 != 1 in 1 not in 1 is 1 is not 1'): pass + if sys.py3kwarning: + with warnings.catch_warnings(): + warnings.filterwarnings('error', category=DeprecationWarning) + with self.assertRaises(DeprecationWarning) as cm: + compile('1 <> 1', '<test string>', 'eval') + self.assertIn('<> not supported in 3.x; use !=', + str(cm.exception)) def test_binary_mask_ops(self): x = 1 & 1 diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-05-25-18-20-04.bpo-33645.GYGIPH.rst b/Misc/NEWS.d/next/Core and Builtins/2018-05-25-18-20-04.bpo-33645.GYGIPH.rst new file mode 100644 index 000000000000..5cc47f1532d3 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-05-25-18-20-04.bpo-33645.GYGIPH.rst @@ -0,0 +1,2 @@ +Fixed an "unknown parsing error" on parsing the "<>" operator when run +Python with both options ``-3`` and ``-We``. diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c index 4fdbad939341..61bfb4e1b7af 100644 --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -1636,6 +1636,8 @@ tok_get(register struct tok_state *tok, char **p_start, char **p_end) "<> not supported in 3.x; use !=", tok->filename, tok->lineno, NULL, NULL)) { + tok->done = E_ERROR; + tok->cur = tok->inp; return ERRORTOKEN; } } From webhook-mailer at python.org Thu May 31 00:39:03 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Thu, 31 May 2018 04:39:03 -0000 Subject: [Python-checkins] bpo-33641: Convert RFC references into links. (GH-7103) Message-ID: <mailman.111.1527741547.2800.python-checkins@python.org> https://github.com/python/cpython/commit/0a36ac1a09587735237c5978ebd046313922869c commit: 0a36ac1a09587735237c5978ebd046313922869c branch: master author: Serhiy Storchaka <storchaka at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-31T07:39:00+03:00 summary: bpo-33641: Convert RFC references into links. (GH-7103) 85% of them are already links. files: M Doc/howto/logging-cookbook.rst M Doc/howto/logging.rst M Doc/howto/urllib2.rst M Doc/library/binascii.rst M Doc/library/codecs.rst M Doc/library/email.examples.rst M Doc/library/ftplib.rst M Doc/library/hashlib.rst M Doc/library/http.cookiejar.rst M Doc/library/imaplib.rst M Doc/library/logging.handlers.rst M Doc/library/logging.rst M Doc/library/nntplib.rst M Doc/library/ssl.rst M Doc/library/stringprep.rst M Doc/library/urllib.error.rst M Doc/library/urllib.parse.rst M Doc/library/urllib.request.rst M Doc/library/uuid.rst M Doc/library/wsgiref.rst M Doc/library/xmlrpc.client.rst M Doc/tutorial/stdlib.rst M Doc/whatsnew/2.4.rst diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst index fdf7874883ee..b1930a791fca 100644 --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -1652,11 +1652,11 @@ works:: Inserting a BOM into messages sent to a SysLogHandler ----------------------------------------------------- -`RFC 5424 <https://tools.ietf.org/html/rfc5424>`_ requires that a +:rfc:`5424` requires that a Unicode message be sent to a syslog daemon as a set of bytes which have the following structure: an optional pure-ASCII component, followed by a UTF-8 Byte -Order Mark (BOM), followed by Unicode encoded using UTF-8. (See the `relevant -section of the specification <https://tools.ietf.org/html/rfc5424#section-6>`_.) +Order Mark (BOM), followed by Unicode encoded using UTF-8. (See the +:rfc:`relevant section of the specification <5424#section-6>`.) In Python 3.1, code was added to :class:`~logging.handlers.SysLogHandler` to insert a BOM into the message, but @@ -1666,7 +1666,7 @@ appear before it. As this behaviour is broken, the incorrect BOM insertion code is being removed from Python 3.2.4 and later. However, it is not being replaced, and if you -want to produce RFC 5424-compliant messages which include a BOM, an optional +want to produce :rfc:`5424`-compliant messages which include a BOM, an optional pure-ASCII sequence before it and arbitrary Unicode after it, encoded using UTF-8, then you need to do the following: @@ -1689,7 +1689,7 @@ UTF-8, then you need to do the following: The formatted message *will* be encoded using UTF-8 encoding by ``SysLogHandler``. If you follow the above rules, you should be able to produce -RFC 5424-compliant messages. If you don't, logging may not complain, but your +:rfc:`5424`-compliant messages. If you don't, logging may not complain, but your messages will not be RFC 5424-compliant, and your syslog daemon may complain. diff --git a/Doc/howto/logging.rst b/Doc/howto/logging.rst index e9e5580df969..47b5c680c424 100644 --- a/Doc/howto/logging.rst +++ b/Doc/howto/logging.rst @@ -297,7 +297,7 @@ which should print something like this: 2010-12-12 11:41:42,612 is when this event was logged. The default format for date/time display (shown above) is like ISO8601 or -RFC 3339. If you need more control over the formatting of the date/time, provide +:rfc:`3339`. If you need more control over the formatting of the date/time, provide a *datefmt* argument to ``basicConfig``, as in this example:: import logging diff --git a/Doc/howto/urllib2.rst b/Doc/howto/urllib2.rst index ef1791cebec5..046a88af62f0 100644 --- a/Doc/howto/urllib2.rst +++ b/Doc/howto/urllib2.rst @@ -239,7 +239,7 @@ a different URL, urllib will handle that for you). For those it can't handle, urlopen will raise an :exc:`HTTPError`. Typical errors include '404' (page not found), '403' (request forbidden), and '401' (authentication required). -See section 10 of RFC 2616 for a reference on all the HTTP error codes. +See section 10 of :rfc:`2616` for a reference on all the HTTP error codes. The :exc:`HTTPError` instance raised will have an integer 'code' attribute, which corresponds to the error sent by the server. @@ -252,7 +252,7 @@ codes in the 100--299 range indicate success, you will usually only see error codes in the 400--599 range. :attr:`http.server.BaseHTTPRequestHandler.responses` is a useful dictionary of -response codes in that shows all the response codes used by RFC 2616. The +response codes in that shows all the response codes used by :rfc:`2616`. The dictionary is reproduced here for convenience :: # Table mapping response codes to messages; entries have the diff --git a/Doc/library/binascii.rst b/Doc/library/binascii.rst index 4d3d0e07f186..a4efef846572 100644 --- a/Doc/library/binascii.rst +++ b/Doc/library/binascii.rst @@ -80,7 +80,7 @@ The :mod:`binascii` module defines the following functions: *quotetabs* is present and true, all tabs and spaces will be encoded. If the optional argument *istext* is present and true, newlines are not encoded but trailing whitespace will be encoded. If the optional argument *header* is - present and true, spaces will be encoded as underscores per RFC1522. If the + present and true, spaces will be encoded as underscores per :rfc:`1522`. If the optional argument *header* is present and false, newline characters will be encoded as well; otherwise linefeed conversion might corrupt the binary data stream. diff --git a/Doc/library/codecs.rst b/Doc/library/codecs.rst index 74b24e10ede6..24008a0b3f00 100644 --- a/Doc/library/codecs.rst +++ b/Doc/library/codecs.rst @@ -1425,7 +1425,7 @@ to the user. Python supports this conversion in several ways: the ``idna`` codec performs conversion between Unicode and ACE, separating an input string into labels -based on the separator characters defined in `section 3.1`_ (1) of :rfc:`3490` +based on the separator characters defined in :rfc:`section 3.1 of RFC 3490 <3490#section-3.1>` and converting each label to ACE as required, and conversely separating an input byte string into labels based on the ``.`` separator and converting any ACE labels found into unicode. Furthermore, the :mod:`socket` module @@ -1436,8 +1436,6 @@ parameters, such as :mod:`http.client` and :mod:`ftplib`, accept Unicode host names (:mod:`http.client` then also transparently sends an IDNA hostname in the :mailheader:`Host` field if it sends that field at all). -.. _section 3.1: https://tools.ietf.org/html/rfc3490#section-3.1 - When receiving host names from the wire (such as in reverse name lookup), no automatic conversion to Unicode is performed: Applications wishing to present such host names to the user should decode them to Unicode. diff --git a/Doc/library/email.examples.rst b/Doc/library/email.examples.rst index 84e9aee0bc48..fc964622809d 100644 --- a/Doc/library/email.examples.rst +++ b/Doc/library/email.examples.rst @@ -12,7 +12,7 @@ text content and the addresses may contain unicode characters): .. literalinclude:: ../includes/email-simple.py -Parsing RFC822 headers can easily be done by the using the classes +Parsing :rfc:`822` headers can easily be done by the using the classes from the :mod:`~email.parser` module: .. literalinclude:: ../includes/email-headers.py diff --git a/Doc/library/ftplib.rst b/Doc/library/ftplib.rst index 7291dfe84811..6c39f9a59fc1 100644 --- a/Doc/library/ftplib.rst +++ b/Doc/library/ftplib.rst @@ -295,7 +295,7 @@ followed by ``lines`` for the text version or ``binary`` for the binary version. If optional *rest* is given, a ``REST`` command is sent to the server, passing *rest* as an argument. *rest* is usually a byte offset into the requested file, telling the server to restart sending the file's bytes at the requested offset, - skipping over the initial bytes. Note however that RFC 959 requires only that + skipping over the initial bytes. Note however that :rfc:`959` requires only that *rest* be a string containing characters in the printable range from ASCII code 33 to ASCII code 126. The :meth:`transfercmd` method, therefore, converts *rest* to a string, but no check is performed on the string's contents. If the diff --git a/Doc/library/hashlib.rst b/Doc/library/hashlib.rst index eda18adc9e5e..0ed0482dc54c 100644 --- a/Doc/library/hashlib.rst +++ b/Doc/library/hashlib.rst @@ -283,7 +283,7 @@ BLAKE2 .. index:: single: blake2b, blake2s -BLAKE2_ is a cryptographic hash function defined in RFC-7693_ that comes in two +BLAKE2_ is a cryptographic hash function defined in :rfc:`7693` that comes in two flavors: * **BLAKE2b**, optimized for 64-bit platforms and produces digests of any size @@ -707,7 +707,6 @@ Domain Dedication 1.0 Universal: * *Alexandr Sokolovskiy* -.. _RFC-7693: https://tools.ietf.org/html/rfc7693 .. _BLAKE2: https://blake2.net .. _HMAC: https://en.wikipedia.org/wiki/Hash-based_message_authentication_code .. _BLAKE: https://131002.net/blake/ diff --git a/Doc/library/http.cookiejar.rst b/Doc/library/http.cookiejar.rst index 5370601544c7..d8da6683a3a5 100644 --- a/Doc/library/http.cookiejar.rst +++ b/Doc/library/http.cookiejar.rst @@ -88,7 +88,7 @@ The following classes are provided: :class:`DefaultCookiePolicy` objects. :class:`DefaultCookiePolicy` implements the standard accept / reject rules for - Netscape and RFC 2965 cookies. By default, RFC 2109 cookies (ie. cookies + Netscape and :rfc:`2965` cookies. By default, :rfc:`2109` cookies (ie. cookies received in a :mailheader:`Set-Cookie` header with a version cookie-attribute of 1) are treated according to the RFC 2965 rules. However, if RFC 2965 handling is turned off or :attr:`rfc2109_as_netscape` is ``True``, RFC 2109 cookies are @@ -100,7 +100,7 @@ The following classes are provided: .. class:: Cookie() - This class represents Netscape, RFC 2109 and RFC 2965 cookies. It is not + This class represents Netscape, :rfc:`2109` and :rfc:`2965` cookies. It is not expected that users of :mod:`http.cookiejar` construct their own :class:`Cookie` instances. Instead, if necessary, call :meth:`make_cookies` on a :class:`CookieJar` instance. @@ -123,14 +123,14 @@ The following classes are provided: the one sketched out in ``cookie_spec.html``. :rfc:`2109` - HTTP State Management Mechanism - Obsoleted by RFC 2965. Uses :mailheader:`Set-Cookie` with version=1. + Obsoleted by :rfc:`2965`. Uses :mailheader:`Set-Cookie` with version=1. :rfc:`2965` - HTTP State Management Mechanism The Netscape protocol with the bugs fixed. Uses :mailheader:`Set-Cookie2` in place of :mailheader:`Set-Cookie`. Not widely used. http://kristol.org/cookie/errata.html - Unfinished errata to RFC 2965. + Unfinished errata to :rfc:`2965`. :rfc:`2964` - Use of HTTP State Management @@ -320,7 +320,7 @@ writing. .. note:: - This loses information about RFC 2965 cookies, and also about newer or + This loses information about :rfc:`2965` cookies, and also about newer or non-standard cookie-attributes such as ``port``. .. warning:: @@ -410,13 +410,13 @@ be assigned to. .. attribute:: CookiePolicy.rfc2965 - Implement RFC 2965 protocol. + Implement :rfc:`2965` protocol. .. attribute:: CookiePolicy.hide_cookie2 Don't add :mailheader:`Cookie2` header to requests (the presence of this header - indicates to the server that we understand RFC 2965 cookies). + indicates to the server that we understand :rfc:`2965` cookies). The most useful way to define a :class:`CookiePolicy` class is by subclassing from :class:`DefaultCookiePolicy` and overriding some or all of the methods @@ -431,7 +431,7 @@ DefaultCookiePolicy Objects Implements the standard rules for accepting and returning cookies. -Both RFC 2965 and Netscape cookies are covered. RFC 2965 handling is switched +Both :rfc:`2965` and Netscape cookies are covered. RFC 2965 handling is switched off by default. The easiest way to provide your own policy is to override this class and call @@ -510,11 +510,11 @@ all be assigned to. .. attribute:: DefaultCookiePolicy.rfc2109_as_netscape - If true, request that the :class:`CookieJar` instance downgrade RFC 2109 cookies + If true, request that the :class:`CookieJar` instance downgrade :rfc:`2109` cookies (ie. cookies received in a :mailheader:`Set-Cookie` header with a version cookie-attribute of 1) to Netscape cookies by setting the version attribute of the :class:`Cookie` instance to 0. The default value is :const:`None`, in which - case RFC 2109 cookies are downgraded if and only if RFC 2965 handling is turned + case RFC 2109 cookies are downgraded if and only if :rfc:`2965` handling is turned off. Therefore, RFC 2109 cookies are downgraded by default. @@ -527,11 +527,11 @@ General strictness switches: and isn't guaranteed to work! -RFC 2965 protocol strictness switches: +:rfc:`2965` protocol strictness switches: .. attribute:: DefaultCookiePolicy.strict_rfc2965_unverifiable - Follow RFC 2965 rules on unverifiable transactions (usually, an unverifiable + Follow :rfc:`2965` rules on unverifiable transactions (usually, an unverifiable transaction is one resulting from a redirect or a request for an image hosted on another site). If this is false, cookies are *never* blocked on the basis of verifiability @@ -541,7 +541,7 @@ Netscape protocol strictness switches: .. attribute:: DefaultCookiePolicy.strict_ns_unverifiable - Apply RFC 2965 rules on unverifiable transactions even to Netscape cookies. + Apply :rfc:`2965` rules on unverifiable transactions even to Netscape cookies. .. attribute:: DefaultCookiePolicy.strict_ns_domain @@ -581,7 +581,7 @@ both flags are set). .. attribute:: DefaultCookiePolicy.DomainRFC2965Match - When setting cookies, require a full RFC 2965 domain-match. + When setting cookies, require a full :rfc:`2965` domain-match. The following attributes are provided for convenience, and are the most useful combinations of the above flags: @@ -605,7 +605,7 @@ Cookie Objects standard cookie-attributes specified in the various cookie standards. The correspondence is not one-to-one, because there are complicated rules for assigning default values, because the ``max-age`` and ``expires`` -cookie-attributes contain equivalent information, and because RFC 2109 cookies +cookie-attributes contain equivalent information, and because :rfc:`2109` cookies may be 'downgraded' by :mod:`http.cookiejar` from version 1 to version 0 (Netscape) cookies. @@ -616,8 +616,8 @@ internal consistency, so you should know what you're doing if you do that. .. attribute:: Cookie.version - Integer or :const:`None`. Netscape cookies have :attr:`version` 0. RFC 2965 and - RFC 2109 cookies have a ``version`` cookie-attribute of 1. However, note that + Integer or :const:`None`. Netscape cookies have :attr:`version` 0. :rfc:`2965` and + :rfc:`2109` cookies have a ``version`` cookie-attribute of 1. However, note that :mod:`http.cookiejar` may 'downgrade' RFC 2109 cookies to Netscape cookies, in which case :attr:`version` is 0. @@ -673,7 +673,7 @@ internal consistency, so you should know what you're doing if you do that. .. attribute:: Cookie.rfc2109 - ``True`` if this cookie was received as an RFC 2109 cookie (ie. the cookie + ``True`` if this cookie was received as an :rfc:`2109` cookie (ie. the cookie arrived in a :mailheader:`Set-Cookie` header, and the value of the Version cookie-attribute in that header was 1). This attribute is provided because :mod:`http.cookiejar` may 'downgrade' RFC 2109 cookies to Netscape cookies, in @@ -745,7 +745,7 @@ cookies (assumes Unix/Netscape convention for location of the cookies file):: r = opener.open("http://example.com/") The next example illustrates the use of :class:`DefaultCookiePolicy`. Turn on -RFC 2965 cookies, be more strict about domains when setting and returning +:rfc:`2965` cookies, be more strict about domains when setting and returning Netscape cookies, and block some domains from setting cookies or having them returned:: diff --git a/Doc/library/imaplib.rst b/Doc/library/imaplib.rst index 1632eb7aed36..2e2c59c9ce00 100644 --- a/Doc/library/imaplib.rst +++ b/Doc/library/imaplib.rst @@ -342,7 +342,7 @@ An :class:`IMAP4` instance has the following methods: .. method:: IMAP4.namespace() - Returns IMAP namespaces as defined in RFC2342. + Returns IMAP namespaces as defined in :rfc:`2342`. .. method:: IMAP4.noop() diff --git a/Doc/library/logging.handlers.rst b/Doc/library/logging.handlers.rst index f7262e60a31b..bdf16a8177e9 100644 --- a/Doc/library/logging.handlers.rst +++ b/Doc/library/logging.handlers.rst @@ -596,7 +596,7 @@ supports sending logging messages to a remote or local Unix syslog. (See: :issue:`12168`.) In earlier versions, the message sent to the syslog daemons was always terminated with a NUL byte, because early versions of these daemons expected a NUL terminated message - even - though it's not in the relevant specification (RFC 5424). More recent + though it's not in the relevant specification (:rfc:`5424`). More recent versions of these daemons don't expect the NUL byte but strip it off if it's there, and even more recent daemons (which adhere more closely to RFC 5424) pass the NUL byte on as part of the message. diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst index 9a54bf9325a0..6b48d6406aa2 100644 --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -516,7 +516,7 @@ The useful mapping keys in a :class:`LogRecord` are given in the section on initialized with a format string for the message as a whole, as well as a format string for the date/time portion of a message. If no *fmt* is specified, ``'%(message)s'`` is used. If no *datefmt* is specified, an - ISO8601-like (or RFC3339-like) date format is used. See the + ISO8601-like (or :rfc:`3339`-like) date format is used. See the :meth:`formatTime` documentation for more details. The *style* parameter can be one of '%', '{' or '$' and determines how diff --git a/Doc/library/nntplib.rst b/Doc/library/nntplib.rst index 2c3cd8dafe6e..d8ef8a692a95 100644 --- a/Doc/library/nntplib.rst +++ b/Doc/library/nntplib.rst @@ -542,7 +542,7 @@ them have been superseded by newer commands in :rfc:`3977`. is supplied, then the returned *list* is an empty list. This is an optional NNTP extension, and may not be supported by all servers. - RFC2980 says "It is suggested that this extension be deprecated". Use + :rfc:`2980` says "It is suggested that this extension be deprecated". Use :meth:`descriptions` or :meth:`description` instead. diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 14eac2c58947..7a058245ca82 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -2638,25 +2638,25 @@ with LibreSSL. `SSL/TLS Strong Encryption: An Introduction <https://httpd.apache.org/docs/trunk/en/ssl/ssl_intro.html>`_ Intro from the Apache HTTP Server documentation - `RFC 1422: Privacy Enhancement for Internet Electronic Mail: Part II: Certificate-Based Key Management <https://www.ietf.org/rfc/rfc1422>`_ + :rfc:`RFC 1422: Privacy Enhancement for Internet Electronic Mail: Part II: Certificate-Based Key Management <1422>` Steve Kent - `RFC 4086: Randomness Requirements for Security <https://datatracker.ietf.org/doc/rfc4086/>`_ + :rfc:`RFC 4086: Randomness Requirements for Security <4086>` Donald E., Jeffrey I. Schiller - `RFC 5280: Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile <https://datatracker.ietf.org/doc/rfc5280/>`_ + :rfc:`RFC 5280: Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile <5280>` D. Cooper - `RFC 5246: The Transport Layer Security (TLS) Protocol Version 1.2 <https://tools.ietf.org/html/rfc5246>`_ + :rfc:`RFC 5246: The Transport Layer Security (TLS) Protocol Version 1.2 <5246>` T. Dierks et. al. - `RFC 6066: Transport Layer Security (TLS) Extensions <https://tools.ietf.org/html/rfc6066>`_ + :rfc:`RFC 6066: Transport Layer Security (TLS) Extensions <6066>` D. Eastlake `IANA TLS: Transport Layer Security (TLS) Parameters <https://www.iana.org/assignments/tls-parameters/tls-parameters.xml>`_ IANA - `RFC 7525: Recommendations for Secure Use of Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS) <https://tools.ietf.org/html/rfc7525>`_ + :rfc:`RFC 7525: Recommendations for Secure Use of Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS) <7525>` IETF `Mozilla's Server Side TLS recommendations <https://wiki.mozilla.org/Security/Server_Side_TLS>`_ diff --git a/Doc/library/stringprep.rst b/Doc/library/stringprep.rst index e7fae5631d87..330032ba1c0b 100644 --- a/Doc/library/stringprep.rst +++ b/Doc/library/stringprep.rst @@ -26,7 +26,7 @@ define which tables it uses, and what other optional parts of the ``stringprep`` procedure are part of the profile. One example of a ``stringprep`` profile is ``nameprep``, which is used for internationalized domain names. -The module :mod:`stringprep` only exposes the tables from RFC 3454. As these +The module :mod:`stringprep` only exposes the tables from :rfc:`3454`. As these tables would be very large to represent them as dictionaries or lists, the module uses the Unicode character database internally. The module source code itself was generated using the ``mkstringprep.py`` utility. diff --git a/Doc/library/urllib.error.rst b/Doc/library/urllib.error.rst index 5517b04f5ddf..f7d47ed76aca 100644 --- a/Doc/library/urllib.error.rst +++ b/Doc/library/urllib.error.rst @@ -41,8 +41,7 @@ The following exceptions are raised by :mod:`urllib.error` as appropriate: .. attribute:: code - An HTTP status code as defined in `RFC 2616 - <http://www.faqs.org/rfcs/rfc2616.html>`_. This numeric value corresponds + An HTTP status code as defined in :rfc:`2616`. This numeric value corresponds to a value found in the dictionary of codes as found in :attr:`http.server.BaseHTTPRequestHandler.responses`. diff --git a/Doc/library/urllib.parse.rst b/Doc/library/urllib.parse.rst index c0a388c5153e..2d3488bb5eef 100644 --- a/Doc/library/urllib.parse.rst +++ b/Doc/library/urllib.parse.rst @@ -468,7 +468,7 @@ task isn't already covered by the URL parsing functions above. *string* may be either a :class:`str` or a :class:`bytes`. .. versionchanged:: 3.7 - Moved from RFC 2396 to RFC 3986 for quoting URL strings. "~" is now + Moved from :rfc:`2396` to :rfc:`3986` for quoting URL strings. "~" is now included in the set of reserved characters. The optional *encoding* and *errors* parameters specify how to deal with diff --git a/Doc/library/urllib.request.rst b/Doc/library/urllib.request.rst index 413d8b6ffdfe..b7116fabcd99 100644 --- a/Doc/library/urllib.request.rst +++ b/Doc/library/urllib.request.rst @@ -232,7 +232,7 @@ The following classes are provided: containing the image. *unverifiable* should indicate whether the request is unverifiable, - as defined by RFC 2965. It defaults to ``False``. An unverifiable + as defined by :rfc:`2965`. It defaults to ``False``. An unverifiable request is one whose URL the user did not have the option to approve. For example, if the request is for an image in an HTML document, and the user had no option to approve the automatic @@ -504,7 +504,7 @@ request. .. attribute:: Request.unverifiable boolean, indicates whether the request is unverifiable as defined - by RFC 2965. + by :rfc:`2965`. .. attribute:: Request.method diff --git a/Doc/library/uuid.rst b/Doc/library/uuid.rst index 8ec75a79acfa..09c56e537bd8 100644 --- a/Doc/library/uuid.rst +++ b/Doc/library/uuid.rst @@ -1,5 +1,5 @@ -:mod:`uuid` --- UUID objects according to RFC 4122 -================================================== +:mod:`uuid` --- UUID objects according to :rfc:`4122` +===================================================== .. module:: uuid :synopsis: UUID objects (universally unique identifiers) according to RFC 4122 @@ -64,7 +64,7 @@ which relays any information about the UUID's safety, using this enumeration: Exactly one of *hex*, *bytes*, *bytes_le*, *fields*, or *int* must be given. The *version* argument is optional; if given, the resulting UUID will have its - variant and version number set according to RFC 4122, overriding bits in the + variant and version number set according to :rfc:`4122`, overriding bits in the given *hex*, *bytes*, *bytes_le*, *fields*, or *int*. Comparison of UUID objects are made by way of comparing their @@ -127,7 +127,7 @@ which relays any information about the UUID's safety, using this enumeration: .. attribute:: UUID.urn - The UUID as a URN as specified in RFC 4122. + The UUID as a URN as specified in :rfc:`4122`. .. attribute:: UUID.variant @@ -158,7 +158,7 @@ The :mod:`uuid` module defines the following functions: runs, it may launch a separate program, which could be quite slow. If all attempts to obtain the hardware address fail, we choose a random 48-bit number with the multicast bit (least significant bit of the first octet) - set to 1 as recommended in RFC 4122. "Hardware address" means the MAC + set to 1 as recommended in :rfc:`4122`. "Hardware address" means the MAC address of a network interface. On a machine with multiple network interfaces, universally administered MAC addresses (i.e. where the second least significant bit of the first octet is *unset*) will be preferred over diff --git a/Doc/library/wsgiref.rst b/Doc/library/wsgiref.rst index b0ef3465b04f..2d9b7b359e80 100644 --- a/Doc/library/wsgiref.rst +++ b/Doc/library/wsgiref.rst @@ -397,7 +397,7 @@ Paste" library. Wrap *application* and return a new WSGI application object. The returned application will forward all requests to the original *application*, and will check that both the *application* and the server invoking it are conforming to - the WSGI specification and to RFC 2616. + the WSGI specification and to :rfc:`2616`. Any detected nonconformance results in an :exc:`AssertionError` being raised; note, however, that how these errors are handled is server-dependent. For diff --git a/Doc/library/xmlrpc.client.rst b/Doc/library/xmlrpc.client.rst index 390828ef3d98..ed2ccaeae07a 100644 --- a/Doc/library/xmlrpc.client.rst +++ b/Doc/library/xmlrpc.client.rst @@ -328,7 +328,7 @@ Binary Objects Write the XML-RPC base 64 encoding of this binary item to the *out* stream object. The encoded data will have newlines every 76 characters as per - `RFC 2045 section 6.8 <https://tools.ietf.org/html/rfc2045#section-6.8>`_, + :rfc:`RFC 2045 section 6.8 <2045#section-6.8>`, which was the de facto standard base64 specification when the XML-RPC spec was written. diff --git a/Doc/tutorial/stdlib.rst b/Doc/tutorial/stdlib.rst index 4934d695180e..82261a651348 100644 --- a/Doc/tutorial/stdlib.rst +++ b/Doc/tutorial/stdlib.rst @@ -317,7 +317,7 @@ sophisticated and robust capabilities of its larger packages. For example: names, no direct knowledge or handling of XML is needed. * The :mod:`email` package is a library for managing email messages, including - MIME and other RFC 2822-based message documents. Unlike :mod:`smtplib` and + MIME and other :rfc:`2822`-based message documents. Unlike :mod:`smtplib` and :mod:`poplib` which actually send and receive messages, the email package has a complete toolset for building or decoding complex message structures (including attachments) and for implementing internet encoding and header diff --git a/Doc/whatsnew/2.4.rst b/Doc/whatsnew/2.4.rst index 7c125ffd2ad0..7e11c98399cc 100644 --- a/Doc/whatsnew/2.4.rst +++ b/Doc/whatsnew/2.4.rst @@ -998,7 +998,7 @@ complete list of changes, or look through the CVS logs for all the details. that lets you perform a limited number of passes through the polling loop. The default is still to loop forever. -* The :mod:`base64` module now has more complete RFC 3548 support for Base64, +* The :mod:`base64` module now has more complete :rfc:`3548` support for Base64, Base32, and Base16 encoding and decoding, including optional case folding and optional alternative alphabets. (Contributed by Barry Warsaw.) From webhook-mailer at python.org Thu May 31 01:13:48 2018 From: webhook-mailer at python.org (Steve Dower) Date: Thu, 31 May 2018 05:13:48 -0000 Subject: [Python-checkins] Adds new upload script for Windows releases (GH-7268) Message-ID: <mailman.112.1527743629.2800.python-checkins@python.org> https://github.com/python/cpython/commit/e1c54f4330bc8eb61dbcbd4f9b14d4e222f2be29 commit: e1c54f4330bc8eb61dbcbd4f9b14d4e222f2be29 branch: master author: Steve Dower <steve.dower at microsoft.com> committer: GitHub <noreply at github.com> date: 2018-05-30T22:13:43-07:00 summary: Adds new upload script for Windows releases (GH-7268) files: A Tools/msi/uploadrelease.ps1 diff --git a/Tools/msi/uploadrelease.ps1 b/Tools/msi/uploadrelease.ps1 new file mode 100644 index 000000000000..1fe9bca0cc5b --- /dev/null +++ b/Tools/msi/uploadrelease.ps1 @@ -0,0 +1,121 @@ +<# +.Synopsis + Uploads from a VSTS release build layout to python.org +.Description + Given the downloaded/extracted build artifact from a release + build run on python.visualstudio.com, this script uploads + the files to the correct locations. +.Parameter build + The location on disk of the extracted build artifact. +.Parameter user + The username to use when logging into the host. +.Parameter server + The host or PuTTY session name. +.Parameter target + The subdirectory on the host to copy files to. +.Parameter tests + The path to run download tests in. +.Parameter skipupload + Skip uploading +.Parameter skippurge + Skip purging the CDN +.Parameter skiptest + Skip the download tests +.Parameter skiphash + Skip displaying hashes +#> +param( + [Parameter(Mandatory=$true)][string]$build, + [Parameter(Mandatory=$true)][string]$user, + [string]$server="python-downloads", + [string]$target="/srv/www.python.org/ftp/python", + [string]$tests=${env:TEMP}, + [switch]$skipupload, + [switch]$skippurge, + [switch]$skiptest, + [switch]$skiphash +) + +if (-not $build) { throw "-build option is required" } +if (-not $user) { throw "-user option is required" } + +function find-putty-tool { + param ([string]$n) + $t = gcm $n -EA 0 + if (-not $t) { $t = gcm ".\$n" -EA 0 } + if (-not $t) { $t = gcm "${env:ProgramFiles}\PuTTY\$n" -EA 0 } + if (-not $t) { $t = gcm "${env:ProgramFiles(x86)}\PuTTY\$n" -EA 0 } + if (-not $t) { throw "Unable to locate $n.exe. Please put it on $PATH" } + return gi $t.Path +} + +$p = gci -r "$build\python-*.exe" | ` + ?{ $_.Name -match '^python-(\d+\.\d+\.\d+)((a|b|rc)\d+)?-.+' } | ` + select -first 1 | ` + %{ $Matches[1], $Matches[2] } + +"Uploading version $($p[0]) $($p[1])" +" from: $build" +" to: $($server):$target/$($p[0])" +" using: $plink and $pscp" +"" + +if (-not $skipupload) { + # Upload files to the server + $pscp = find-putty-tool "pscp" + $plink = find-putty-tool "plink" + + pushd $build + $doc = gci python*.chm, python*.chm.asc + popd + + $d = "$target/$($p[0])/" + & $plink -batch $user@$server mkdir $d "&&" chgrp downloads $d "&&" chmod g-x,o+rx $d + & $pscp -batch $doc.FullName "$user@${server}:$d" + + foreach ($a in gci "$build" -Directory) { + "Uploading files from $($a.FullName)" + pushd "$($a.FullName)" + $exe = gci *.exe, *.exe.asc, *.zip, *.zip.asc + $msi = gci *.msi, *.msi.asc, *.msu, *.msu.asc + popd + + & $pscp -batch $exe.FullName "$user@${server}:$d" + + $sd = "$d$($a.Name)$($p[1])/" + & $plink -batch $user@$server mkdir $sd "&&" chgrp downloads $sd "&&" chmod g-x,o+rx $sd + & $pscp -batch $msi.FullName "$user@${server}:$sd" + & $plink -batch $user@$server chgrp downloads $sd* "&&" chmod g-x,o+rx $sd* + } + + & $plink -batch $user@$server chgrp downloads $d* "&&" chmod g-x,o+rx $d* +} + +if (-not $skippurge) { + # Run a CDN purge + py purge.py "$($p[0])$($p[1])" +} + +if (-not $skiptest) { + # Use each web installer to produce a layout. This will download + # each referenced file and validate their signatures/hashes. + gci "$build\*-webinstall.exe" -r -File | %{ + $d = mkdir "$tests\$($_.BaseName)" -Force + gci $d -r -File | del + $ic = copy $_ $d -PassThru + "Checking layout for $($ic.Name)" + Start-Process -wait $ic "/passive", "/layout", "$d\layout", "/log", "$d\log\install.log" + if (-not $?) { + Write-Error "Failed to validate layout of $($inst.Name)" + } + } +} + +if (-not $skiphash) { + # Display MD5 hash and size of each downloadable file + pushd $build + gci python*.chm, *\*.exe, *\*.zip | ` + Sort-Object Name | ` + Format-Table Name, @{Label="MD5"; Expression={(Get-FileHash $_ -Algorithm MD5).Hash}}, Length + popd +} From webhook-mailer at python.org Thu May 31 01:18:51 2018 From: webhook-mailer at python.org (Ned Deily) Date: Thu, 31 May 2018 05:18:51 -0000 Subject: [Python-checkins] Fix "ditribution" typo in NEWS entry. (GH-7274) Message-ID: <mailman.113.1527743932.2800.python-checkins@python.org> https://github.com/python/cpython/commit/126869f308d446c1960c542197a1aadacff9ab26 commit: 126869f308d446c1960c542197a1aadacff9ab26 branch: master author: Ned Deily <nad at python.org> committer: GitHub <noreply at github.com> date: 2018-05-31T01:18:49-04:00 summary: Fix "ditribution" typo in NEWS entry. (GH-7274) files: M Misc/NEWS.d/next/Library/2018-05-02-07-26-29.bpo-28167.7FwDfN.rst diff --git a/Misc/NEWS.d/next/Library/2018-05-02-07-26-29.bpo-28167.7FwDfN.rst b/Misc/NEWS.d/next/Library/2018-05-02-07-26-29.bpo-28167.7FwDfN.rst index a4971e5b77ba..2d7cf01961ff 100644 --- a/Misc/NEWS.d/next/Library/2018-05-02-07-26-29.bpo-28167.7FwDfN.rst +++ b/Misc/NEWS.d/next/Library/2018-05-02-07-26-29.bpo-28167.7FwDfN.rst @@ -1,3 +1,3 @@ -The function ``platform.linux_ditribution`` and ``platform.dist`` now +The function ``platform.linux_distribution`` and ``platform.dist`` now trigger a ``DeprecationWarning`` and have been marked for removal in Python 3.8 From webhook-mailer at python.org Thu May 31 01:20:01 2018 From: webhook-mailer at python.org (Ned Deily) Date: Thu, 31 May 2018 05:20:01 -0000 Subject: [Python-checkins] Fix "ditribution" typo in NEWS entry. (GH-7275) Message-ID: <mailman.114.1527744001.2800.python-checkins@python.org> https://github.com/python/cpython/commit/e76b8c446493d0f028d9e4d9876ad1348fefde1c commit: e76b8c446493d0f028d9e4d9876ad1348fefde1c branch: 3.7 author: Ned Deily <nad at python.org> committer: GitHub <noreply at github.com> date: 2018-05-31T01:19:58-04:00 summary: Fix "ditribution" typo in NEWS entry. (GH-7275) files: M Misc/NEWS.d/3.7.0b5.rst diff --git a/Misc/NEWS.d/3.7.0b5.rst b/Misc/NEWS.d/3.7.0b5.rst index 2e2fb9ee0469..202e50b4e035 100644 --- a/Misc/NEWS.d/3.7.0b5.rst +++ b/Misc/NEWS.d/3.7.0b5.rst @@ -406,7 +406,7 @@ literals on pydoc. Patch by Andr?s Delfino. .. nonce: 7FwDfN .. section: Library -The function ``platform.linux_ditribution`` and ``platform.dist`` now +The function ``platform.linux_distribution`` and ``platform.dist`` now trigger a ``DeprecationWarning`` and have been marked for removal in Python 3.8 From webhook-mailer at python.org Thu May 31 01:31:25 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 31 May 2018 05:31:25 -0000 Subject: [Python-checkins] bpo-33677: Fix signatures of tp_clear handlers for AST and deque. (GH-7196) Message-ID: <mailman.115.1527744687.2800.python-checkins@python.org> https://github.com/python/cpython/commit/a4dd46a47fe1d4fe1f1738c2f5b3712de41056b9 commit: a4dd46a47fe1d4fe1f1738c2f5b3712de41056b9 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-30T22:31:21-07:00 summary: bpo-33677: Fix signatures of tp_clear handlers for AST and deque. (GH-7196) (cherry picked from commit a5c42284e69fb309bdd17ee8c1c120d1be383012) Co-authored-by: Serhiy Storchaka <storchaka at gmail.com> files: M Modules/_collectionsmodule.c M Parser/asdl_c.py M Python/Python-ast.c diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c index 5753dd946a5a..4116d4053547 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -575,7 +575,7 @@ deque_concat(dequeobject *deque, PyObject *other) return new_deque; } -static void +static int deque_clear(dequeobject *deque) { block *b; @@ -587,7 +587,7 @@ deque_clear(dequeobject *deque) PyObject **itemptr, **limit; if (Py_SIZE(deque) == 0) - return; + return 0; /* During the process of clearing a deque, decrefs can cause the deque to mutate. To avoid fatal confusion, we have to make the @@ -648,7 +648,7 @@ deque_clear(dequeobject *deque) } CHECK_END(leftblock->rightlink); freeblock(leftblock); - return; + return 0; alternate_method: while (Py_SIZE(deque)) { @@ -656,6 +656,7 @@ deque_clear(dequeobject *deque) assert (item != NULL); Py_DECREF(item); } + return 0; } static PyObject * diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py index 399e79e0597f..44e3d40c6155 100644 --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -647,10 +647,11 @@ def visitModule(self, mod): return 0; } -static void +static int ast_clear(AST_object *self) { Py_CLEAR(self->dict); + return 0; } static int diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 38b9292577f2..6a2f28e0e712 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -528,10 +528,11 @@ ast_traverse(AST_object *self, visitproc visit, void *arg) return 0; } -static void +static int ast_clear(AST_object *self) { Py_CLEAR(self->dict); + return 0; } static int From webhook-mailer at python.org Thu May 31 01:33:26 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 31 May 2018 05:33:26 -0000 Subject: [Python-checkins] bpo-33641: Convert RFC references into links. (GH-7103) Message-ID: <mailman.116.1527744809.2800.python-checkins@python.org> https://github.com/python/cpython/commit/0f1a18326902ad3d0a30fdecbe40513cc5d85879 commit: 0f1a18326902ad3d0a30fdecbe40513cc5d85879 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-30T22:33:23-07:00 summary: bpo-33641: Convert RFC references into links. (GH-7103) 85% of them are already links. (cherry picked from commit 0a36ac1a09587735237c5978ebd046313922869c) Co-authored-by: Serhiy Storchaka <storchaka at gmail.com> files: M Doc/howto/logging-cookbook.rst M Doc/howto/logging.rst M Doc/howto/urllib2.rst M Doc/library/binascii.rst M Doc/library/codecs.rst M Doc/library/email.examples.rst M Doc/library/ftplib.rst M Doc/library/hashlib.rst M Doc/library/http.cookiejar.rst M Doc/library/imaplib.rst M Doc/library/logging.handlers.rst M Doc/library/logging.rst M Doc/library/nntplib.rst M Doc/library/ssl.rst M Doc/library/stringprep.rst M Doc/library/urllib.error.rst M Doc/library/urllib.parse.rst M Doc/library/urllib.request.rst M Doc/library/uuid.rst M Doc/library/wsgiref.rst M Doc/library/xmlrpc.client.rst M Doc/tutorial/stdlib.rst M Doc/whatsnew/2.4.rst diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst index fdf7874883ee..b1930a791fca 100644 --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -1652,11 +1652,11 @@ works:: Inserting a BOM into messages sent to a SysLogHandler ----------------------------------------------------- -`RFC 5424 <https://tools.ietf.org/html/rfc5424>`_ requires that a +:rfc:`5424` requires that a Unicode message be sent to a syslog daemon as a set of bytes which have the following structure: an optional pure-ASCII component, followed by a UTF-8 Byte -Order Mark (BOM), followed by Unicode encoded using UTF-8. (See the `relevant -section of the specification <https://tools.ietf.org/html/rfc5424#section-6>`_.) +Order Mark (BOM), followed by Unicode encoded using UTF-8. (See the +:rfc:`relevant section of the specification <5424#section-6>`.) In Python 3.1, code was added to :class:`~logging.handlers.SysLogHandler` to insert a BOM into the message, but @@ -1666,7 +1666,7 @@ appear before it. As this behaviour is broken, the incorrect BOM insertion code is being removed from Python 3.2.4 and later. However, it is not being replaced, and if you -want to produce RFC 5424-compliant messages which include a BOM, an optional +want to produce :rfc:`5424`-compliant messages which include a BOM, an optional pure-ASCII sequence before it and arbitrary Unicode after it, encoded using UTF-8, then you need to do the following: @@ -1689,7 +1689,7 @@ UTF-8, then you need to do the following: The formatted message *will* be encoded using UTF-8 encoding by ``SysLogHandler``. If you follow the above rules, you should be able to produce -RFC 5424-compliant messages. If you don't, logging may not complain, but your +:rfc:`5424`-compliant messages. If you don't, logging may not complain, but your messages will not be RFC 5424-compliant, and your syslog daemon may complain. diff --git a/Doc/howto/logging.rst b/Doc/howto/logging.rst index e9e5580df969..47b5c680c424 100644 --- a/Doc/howto/logging.rst +++ b/Doc/howto/logging.rst @@ -297,7 +297,7 @@ which should print something like this: 2010-12-12 11:41:42,612 is when this event was logged. The default format for date/time display (shown above) is like ISO8601 or -RFC 3339. If you need more control over the formatting of the date/time, provide +:rfc:`3339`. If you need more control over the formatting of the date/time, provide a *datefmt* argument to ``basicConfig``, as in this example:: import logging diff --git a/Doc/howto/urllib2.rst b/Doc/howto/urllib2.rst index ef1791cebec5..046a88af62f0 100644 --- a/Doc/howto/urllib2.rst +++ b/Doc/howto/urllib2.rst @@ -239,7 +239,7 @@ a different URL, urllib will handle that for you). For those it can't handle, urlopen will raise an :exc:`HTTPError`. Typical errors include '404' (page not found), '403' (request forbidden), and '401' (authentication required). -See section 10 of RFC 2616 for a reference on all the HTTP error codes. +See section 10 of :rfc:`2616` for a reference on all the HTTP error codes. The :exc:`HTTPError` instance raised will have an integer 'code' attribute, which corresponds to the error sent by the server. @@ -252,7 +252,7 @@ codes in the 100--299 range indicate success, you will usually only see error codes in the 400--599 range. :attr:`http.server.BaseHTTPRequestHandler.responses` is a useful dictionary of -response codes in that shows all the response codes used by RFC 2616. The +response codes in that shows all the response codes used by :rfc:`2616`. The dictionary is reproduced here for convenience :: # Table mapping response codes to messages; entries have the diff --git a/Doc/library/binascii.rst b/Doc/library/binascii.rst index 4d3d0e07f186..a4efef846572 100644 --- a/Doc/library/binascii.rst +++ b/Doc/library/binascii.rst @@ -80,7 +80,7 @@ The :mod:`binascii` module defines the following functions: *quotetabs* is present and true, all tabs and spaces will be encoded. If the optional argument *istext* is present and true, newlines are not encoded but trailing whitespace will be encoded. If the optional argument *header* is - present and true, spaces will be encoded as underscores per RFC1522. If the + present and true, spaces will be encoded as underscores per :rfc:`1522`. If the optional argument *header* is present and false, newline characters will be encoded as well; otherwise linefeed conversion might corrupt the binary data stream. diff --git a/Doc/library/codecs.rst b/Doc/library/codecs.rst index 74b24e10ede6..24008a0b3f00 100644 --- a/Doc/library/codecs.rst +++ b/Doc/library/codecs.rst @@ -1425,7 +1425,7 @@ to the user. Python supports this conversion in several ways: the ``idna`` codec performs conversion between Unicode and ACE, separating an input string into labels -based on the separator characters defined in `section 3.1`_ (1) of :rfc:`3490` +based on the separator characters defined in :rfc:`section 3.1 of RFC 3490 <3490#section-3.1>` and converting each label to ACE as required, and conversely separating an input byte string into labels based on the ``.`` separator and converting any ACE labels found into unicode. Furthermore, the :mod:`socket` module @@ -1436,8 +1436,6 @@ parameters, such as :mod:`http.client` and :mod:`ftplib`, accept Unicode host names (:mod:`http.client` then also transparently sends an IDNA hostname in the :mailheader:`Host` field if it sends that field at all). -.. _section 3.1: https://tools.ietf.org/html/rfc3490#section-3.1 - When receiving host names from the wire (such as in reverse name lookup), no automatic conversion to Unicode is performed: Applications wishing to present such host names to the user should decode them to Unicode. diff --git a/Doc/library/email.examples.rst b/Doc/library/email.examples.rst index 84e9aee0bc48..fc964622809d 100644 --- a/Doc/library/email.examples.rst +++ b/Doc/library/email.examples.rst @@ -12,7 +12,7 @@ text content and the addresses may contain unicode characters): .. literalinclude:: ../includes/email-simple.py -Parsing RFC822 headers can easily be done by the using the classes +Parsing :rfc:`822` headers can easily be done by the using the classes from the :mod:`~email.parser` module: .. literalinclude:: ../includes/email-headers.py diff --git a/Doc/library/ftplib.rst b/Doc/library/ftplib.rst index 7291dfe84811..6c39f9a59fc1 100644 --- a/Doc/library/ftplib.rst +++ b/Doc/library/ftplib.rst @@ -295,7 +295,7 @@ followed by ``lines`` for the text version or ``binary`` for the binary version. If optional *rest* is given, a ``REST`` command is sent to the server, passing *rest* as an argument. *rest* is usually a byte offset into the requested file, telling the server to restart sending the file's bytes at the requested offset, - skipping over the initial bytes. Note however that RFC 959 requires only that + skipping over the initial bytes. Note however that :rfc:`959` requires only that *rest* be a string containing characters in the printable range from ASCII code 33 to ASCII code 126. The :meth:`transfercmd` method, therefore, converts *rest* to a string, but no check is performed on the string's contents. If the diff --git a/Doc/library/hashlib.rst b/Doc/library/hashlib.rst index eda18adc9e5e..0ed0482dc54c 100644 --- a/Doc/library/hashlib.rst +++ b/Doc/library/hashlib.rst @@ -283,7 +283,7 @@ BLAKE2 .. index:: single: blake2b, blake2s -BLAKE2_ is a cryptographic hash function defined in RFC-7693_ that comes in two +BLAKE2_ is a cryptographic hash function defined in :rfc:`7693` that comes in two flavors: * **BLAKE2b**, optimized for 64-bit platforms and produces digests of any size @@ -707,7 +707,6 @@ Domain Dedication 1.0 Universal: * *Alexandr Sokolovskiy* -.. _RFC-7693: https://tools.ietf.org/html/rfc7693 .. _BLAKE2: https://blake2.net .. _HMAC: https://en.wikipedia.org/wiki/Hash-based_message_authentication_code .. _BLAKE: https://131002.net/blake/ diff --git a/Doc/library/http.cookiejar.rst b/Doc/library/http.cookiejar.rst index 5370601544c7..d8da6683a3a5 100644 --- a/Doc/library/http.cookiejar.rst +++ b/Doc/library/http.cookiejar.rst @@ -88,7 +88,7 @@ The following classes are provided: :class:`DefaultCookiePolicy` objects. :class:`DefaultCookiePolicy` implements the standard accept / reject rules for - Netscape and RFC 2965 cookies. By default, RFC 2109 cookies (ie. cookies + Netscape and :rfc:`2965` cookies. By default, :rfc:`2109` cookies (ie. cookies received in a :mailheader:`Set-Cookie` header with a version cookie-attribute of 1) are treated according to the RFC 2965 rules. However, if RFC 2965 handling is turned off or :attr:`rfc2109_as_netscape` is ``True``, RFC 2109 cookies are @@ -100,7 +100,7 @@ The following classes are provided: .. class:: Cookie() - This class represents Netscape, RFC 2109 and RFC 2965 cookies. It is not + This class represents Netscape, :rfc:`2109` and :rfc:`2965` cookies. It is not expected that users of :mod:`http.cookiejar` construct their own :class:`Cookie` instances. Instead, if necessary, call :meth:`make_cookies` on a :class:`CookieJar` instance. @@ -123,14 +123,14 @@ The following classes are provided: the one sketched out in ``cookie_spec.html``. :rfc:`2109` - HTTP State Management Mechanism - Obsoleted by RFC 2965. Uses :mailheader:`Set-Cookie` with version=1. + Obsoleted by :rfc:`2965`. Uses :mailheader:`Set-Cookie` with version=1. :rfc:`2965` - HTTP State Management Mechanism The Netscape protocol with the bugs fixed. Uses :mailheader:`Set-Cookie2` in place of :mailheader:`Set-Cookie`. Not widely used. http://kristol.org/cookie/errata.html - Unfinished errata to RFC 2965. + Unfinished errata to :rfc:`2965`. :rfc:`2964` - Use of HTTP State Management @@ -320,7 +320,7 @@ writing. .. note:: - This loses information about RFC 2965 cookies, and also about newer or + This loses information about :rfc:`2965` cookies, and also about newer or non-standard cookie-attributes such as ``port``. .. warning:: @@ -410,13 +410,13 @@ be assigned to. .. attribute:: CookiePolicy.rfc2965 - Implement RFC 2965 protocol. + Implement :rfc:`2965` protocol. .. attribute:: CookiePolicy.hide_cookie2 Don't add :mailheader:`Cookie2` header to requests (the presence of this header - indicates to the server that we understand RFC 2965 cookies). + indicates to the server that we understand :rfc:`2965` cookies). The most useful way to define a :class:`CookiePolicy` class is by subclassing from :class:`DefaultCookiePolicy` and overriding some or all of the methods @@ -431,7 +431,7 @@ DefaultCookiePolicy Objects Implements the standard rules for accepting and returning cookies. -Both RFC 2965 and Netscape cookies are covered. RFC 2965 handling is switched +Both :rfc:`2965` and Netscape cookies are covered. RFC 2965 handling is switched off by default. The easiest way to provide your own policy is to override this class and call @@ -510,11 +510,11 @@ all be assigned to. .. attribute:: DefaultCookiePolicy.rfc2109_as_netscape - If true, request that the :class:`CookieJar` instance downgrade RFC 2109 cookies + If true, request that the :class:`CookieJar` instance downgrade :rfc:`2109` cookies (ie. cookies received in a :mailheader:`Set-Cookie` header with a version cookie-attribute of 1) to Netscape cookies by setting the version attribute of the :class:`Cookie` instance to 0. The default value is :const:`None`, in which - case RFC 2109 cookies are downgraded if and only if RFC 2965 handling is turned + case RFC 2109 cookies are downgraded if and only if :rfc:`2965` handling is turned off. Therefore, RFC 2109 cookies are downgraded by default. @@ -527,11 +527,11 @@ General strictness switches: and isn't guaranteed to work! -RFC 2965 protocol strictness switches: +:rfc:`2965` protocol strictness switches: .. attribute:: DefaultCookiePolicy.strict_rfc2965_unverifiable - Follow RFC 2965 rules on unverifiable transactions (usually, an unverifiable + Follow :rfc:`2965` rules on unverifiable transactions (usually, an unverifiable transaction is one resulting from a redirect or a request for an image hosted on another site). If this is false, cookies are *never* blocked on the basis of verifiability @@ -541,7 +541,7 @@ Netscape protocol strictness switches: .. attribute:: DefaultCookiePolicy.strict_ns_unverifiable - Apply RFC 2965 rules on unverifiable transactions even to Netscape cookies. + Apply :rfc:`2965` rules on unverifiable transactions even to Netscape cookies. .. attribute:: DefaultCookiePolicy.strict_ns_domain @@ -581,7 +581,7 @@ both flags are set). .. attribute:: DefaultCookiePolicy.DomainRFC2965Match - When setting cookies, require a full RFC 2965 domain-match. + When setting cookies, require a full :rfc:`2965` domain-match. The following attributes are provided for convenience, and are the most useful combinations of the above flags: @@ -605,7 +605,7 @@ Cookie Objects standard cookie-attributes specified in the various cookie standards. The correspondence is not one-to-one, because there are complicated rules for assigning default values, because the ``max-age`` and ``expires`` -cookie-attributes contain equivalent information, and because RFC 2109 cookies +cookie-attributes contain equivalent information, and because :rfc:`2109` cookies may be 'downgraded' by :mod:`http.cookiejar` from version 1 to version 0 (Netscape) cookies. @@ -616,8 +616,8 @@ internal consistency, so you should know what you're doing if you do that. .. attribute:: Cookie.version - Integer or :const:`None`. Netscape cookies have :attr:`version` 0. RFC 2965 and - RFC 2109 cookies have a ``version`` cookie-attribute of 1. However, note that + Integer or :const:`None`. Netscape cookies have :attr:`version` 0. :rfc:`2965` and + :rfc:`2109` cookies have a ``version`` cookie-attribute of 1. However, note that :mod:`http.cookiejar` may 'downgrade' RFC 2109 cookies to Netscape cookies, in which case :attr:`version` is 0. @@ -673,7 +673,7 @@ internal consistency, so you should know what you're doing if you do that. .. attribute:: Cookie.rfc2109 - ``True`` if this cookie was received as an RFC 2109 cookie (ie. the cookie + ``True`` if this cookie was received as an :rfc:`2109` cookie (ie. the cookie arrived in a :mailheader:`Set-Cookie` header, and the value of the Version cookie-attribute in that header was 1). This attribute is provided because :mod:`http.cookiejar` may 'downgrade' RFC 2109 cookies to Netscape cookies, in @@ -745,7 +745,7 @@ cookies (assumes Unix/Netscape convention for location of the cookies file):: r = opener.open("http://example.com/") The next example illustrates the use of :class:`DefaultCookiePolicy`. Turn on -RFC 2965 cookies, be more strict about domains when setting and returning +:rfc:`2965` cookies, be more strict about domains when setting and returning Netscape cookies, and block some domains from setting cookies or having them returned:: diff --git a/Doc/library/imaplib.rst b/Doc/library/imaplib.rst index 1632eb7aed36..2e2c59c9ce00 100644 --- a/Doc/library/imaplib.rst +++ b/Doc/library/imaplib.rst @@ -342,7 +342,7 @@ An :class:`IMAP4` instance has the following methods: .. method:: IMAP4.namespace() - Returns IMAP namespaces as defined in RFC2342. + Returns IMAP namespaces as defined in :rfc:`2342`. .. method:: IMAP4.noop() diff --git a/Doc/library/logging.handlers.rst b/Doc/library/logging.handlers.rst index f7262e60a31b..bdf16a8177e9 100644 --- a/Doc/library/logging.handlers.rst +++ b/Doc/library/logging.handlers.rst @@ -596,7 +596,7 @@ supports sending logging messages to a remote or local Unix syslog. (See: :issue:`12168`.) In earlier versions, the message sent to the syslog daemons was always terminated with a NUL byte, because early versions of these daemons expected a NUL terminated message - even - though it's not in the relevant specification (RFC 5424). More recent + though it's not in the relevant specification (:rfc:`5424`). More recent versions of these daemons don't expect the NUL byte but strip it off if it's there, and even more recent daemons (which adhere more closely to RFC 5424) pass the NUL byte on as part of the message. diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst index 9a54bf9325a0..6b48d6406aa2 100644 --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -516,7 +516,7 @@ The useful mapping keys in a :class:`LogRecord` are given in the section on initialized with a format string for the message as a whole, as well as a format string for the date/time portion of a message. If no *fmt* is specified, ``'%(message)s'`` is used. If no *datefmt* is specified, an - ISO8601-like (or RFC3339-like) date format is used. See the + ISO8601-like (or :rfc:`3339`-like) date format is used. See the :meth:`formatTime` documentation for more details. The *style* parameter can be one of '%', '{' or '$' and determines how diff --git a/Doc/library/nntplib.rst b/Doc/library/nntplib.rst index 2c3cd8dafe6e..d8ef8a692a95 100644 --- a/Doc/library/nntplib.rst +++ b/Doc/library/nntplib.rst @@ -542,7 +542,7 @@ them have been superseded by newer commands in :rfc:`3977`. is supplied, then the returned *list* is an empty list. This is an optional NNTP extension, and may not be supported by all servers. - RFC2980 says "It is suggested that this extension be deprecated". Use + :rfc:`2980` says "It is suggested that this extension be deprecated". Use :meth:`descriptions` or :meth:`description` instead. diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 14eac2c58947..7a058245ca82 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -2638,25 +2638,25 @@ with LibreSSL. `SSL/TLS Strong Encryption: An Introduction <https://httpd.apache.org/docs/trunk/en/ssl/ssl_intro.html>`_ Intro from the Apache HTTP Server documentation - `RFC 1422: Privacy Enhancement for Internet Electronic Mail: Part II: Certificate-Based Key Management <https://www.ietf.org/rfc/rfc1422>`_ + :rfc:`RFC 1422: Privacy Enhancement for Internet Electronic Mail: Part II: Certificate-Based Key Management <1422>` Steve Kent - `RFC 4086: Randomness Requirements for Security <https://datatracker.ietf.org/doc/rfc4086/>`_ + :rfc:`RFC 4086: Randomness Requirements for Security <4086>` Donald E., Jeffrey I. Schiller - `RFC 5280: Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile <https://datatracker.ietf.org/doc/rfc5280/>`_ + :rfc:`RFC 5280: Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile <5280>` D. Cooper - `RFC 5246: The Transport Layer Security (TLS) Protocol Version 1.2 <https://tools.ietf.org/html/rfc5246>`_ + :rfc:`RFC 5246: The Transport Layer Security (TLS) Protocol Version 1.2 <5246>` T. Dierks et. al. - `RFC 6066: Transport Layer Security (TLS) Extensions <https://tools.ietf.org/html/rfc6066>`_ + :rfc:`RFC 6066: Transport Layer Security (TLS) Extensions <6066>` D. Eastlake `IANA TLS: Transport Layer Security (TLS) Parameters <https://www.iana.org/assignments/tls-parameters/tls-parameters.xml>`_ IANA - `RFC 7525: Recommendations for Secure Use of Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS) <https://tools.ietf.org/html/rfc7525>`_ + :rfc:`RFC 7525: Recommendations for Secure Use of Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS) <7525>` IETF `Mozilla's Server Side TLS recommendations <https://wiki.mozilla.org/Security/Server_Side_TLS>`_ diff --git a/Doc/library/stringprep.rst b/Doc/library/stringprep.rst index e7fae5631d87..330032ba1c0b 100644 --- a/Doc/library/stringprep.rst +++ b/Doc/library/stringprep.rst @@ -26,7 +26,7 @@ define which tables it uses, and what other optional parts of the ``stringprep`` procedure are part of the profile. One example of a ``stringprep`` profile is ``nameprep``, which is used for internationalized domain names. -The module :mod:`stringprep` only exposes the tables from RFC 3454. As these +The module :mod:`stringprep` only exposes the tables from :rfc:`3454`. As these tables would be very large to represent them as dictionaries or lists, the module uses the Unicode character database internally. The module source code itself was generated using the ``mkstringprep.py`` utility. diff --git a/Doc/library/urllib.error.rst b/Doc/library/urllib.error.rst index 5517b04f5ddf..f7d47ed76aca 100644 --- a/Doc/library/urllib.error.rst +++ b/Doc/library/urllib.error.rst @@ -41,8 +41,7 @@ The following exceptions are raised by :mod:`urllib.error` as appropriate: .. attribute:: code - An HTTP status code as defined in `RFC 2616 - <http://www.faqs.org/rfcs/rfc2616.html>`_. This numeric value corresponds + An HTTP status code as defined in :rfc:`2616`. This numeric value corresponds to a value found in the dictionary of codes as found in :attr:`http.server.BaseHTTPRequestHandler.responses`. diff --git a/Doc/library/urllib.parse.rst b/Doc/library/urllib.parse.rst index c0a388c5153e..2d3488bb5eef 100644 --- a/Doc/library/urllib.parse.rst +++ b/Doc/library/urllib.parse.rst @@ -468,7 +468,7 @@ task isn't already covered by the URL parsing functions above. *string* may be either a :class:`str` or a :class:`bytes`. .. versionchanged:: 3.7 - Moved from RFC 2396 to RFC 3986 for quoting URL strings. "~" is now + Moved from :rfc:`2396` to :rfc:`3986` for quoting URL strings. "~" is now included in the set of reserved characters. The optional *encoding* and *errors* parameters specify how to deal with diff --git a/Doc/library/urllib.request.rst b/Doc/library/urllib.request.rst index 413d8b6ffdfe..b7116fabcd99 100644 --- a/Doc/library/urllib.request.rst +++ b/Doc/library/urllib.request.rst @@ -232,7 +232,7 @@ The following classes are provided: containing the image. *unverifiable* should indicate whether the request is unverifiable, - as defined by RFC 2965. It defaults to ``False``. An unverifiable + as defined by :rfc:`2965`. It defaults to ``False``. An unverifiable request is one whose URL the user did not have the option to approve. For example, if the request is for an image in an HTML document, and the user had no option to approve the automatic @@ -504,7 +504,7 @@ request. .. attribute:: Request.unverifiable boolean, indicates whether the request is unverifiable as defined - by RFC 2965. + by :rfc:`2965`. .. attribute:: Request.method diff --git a/Doc/library/uuid.rst b/Doc/library/uuid.rst index 8ec75a79acfa..09c56e537bd8 100644 --- a/Doc/library/uuid.rst +++ b/Doc/library/uuid.rst @@ -1,5 +1,5 @@ -:mod:`uuid` --- UUID objects according to RFC 4122 -================================================== +:mod:`uuid` --- UUID objects according to :rfc:`4122` +===================================================== .. module:: uuid :synopsis: UUID objects (universally unique identifiers) according to RFC 4122 @@ -64,7 +64,7 @@ which relays any information about the UUID's safety, using this enumeration: Exactly one of *hex*, *bytes*, *bytes_le*, *fields*, or *int* must be given. The *version* argument is optional; if given, the resulting UUID will have its - variant and version number set according to RFC 4122, overriding bits in the + variant and version number set according to :rfc:`4122`, overriding bits in the given *hex*, *bytes*, *bytes_le*, *fields*, or *int*. Comparison of UUID objects are made by way of comparing their @@ -127,7 +127,7 @@ which relays any information about the UUID's safety, using this enumeration: .. attribute:: UUID.urn - The UUID as a URN as specified in RFC 4122. + The UUID as a URN as specified in :rfc:`4122`. .. attribute:: UUID.variant @@ -158,7 +158,7 @@ The :mod:`uuid` module defines the following functions: runs, it may launch a separate program, which could be quite slow. If all attempts to obtain the hardware address fail, we choose a random 48-bit number with the multicast bit (least significant bit of the first octet) - set to 1 as recommended in RFC 4122. "Hardware address" means the MAC + set to 1 as recommended in :rfc:`4122`. "Hardware address" means the MAC address of a network interface. On a machine with multiple network interfaces, universally administered MAC addresses (i.e. where the second least significant bit of the first octet is *unset*) will be preferred over diff --git a/Doc/library/wsgiref.rst b/Doc/library/wsgiref.rst index b0ef3465b04f..2d9b7b359e80 100644 --- a/Doc/library/wsgiref.rst +++ b/Doc/library/wsgiref.rst @@ -397,7 +397,7 @@ Paste" library. Wrap *application* and return a new WSGI application object. The returned application will forward all requests to the original *application*, and will check that both the *application* and the server invoking it are conforming to - the WSGI specification and to RFC 2616. + the WSGI specification and to :rfc:`2616`. Any detected nonconformance results in an :exc:`AssertionError` being raised; note, however, that how these errors are handled is server-dependent. For diff --git a/Doc/library/xmlrpc.client.rst b/Doc/library/xmlrpc.client.rst index 390828ef3d98..ed2ccaeae07a 100644 --- a/Doc/library/xmlrpc.client.rst +++ b/Doc/library/xmlrpc.client.rst @@ -328,7 +328,7 @@ Binary Objects Write the XML-RPC base 64 encoding of this binary item to the *out* stream object. The encoded data will have newlines every 76 characters as per - `RFC 2045 section 6.8 <https://tools.ietf.org/html/rfc2045#section-6.8>`_, + :rfc:`RFC 2045 section 6.8 <2045#section-6.8>`, which was the de facto standard base64 specification when the XML-RPC spec was written. diff --git a/Doc/tutorial/stdlib.rst b/Doc/tutorial/stdlib.rst index 6ac29fc6025f..f5ec8acf58ad 100644 --- a/Doc/tutorial/stdlib.rst +++ b/Doc/tutorial/stdlib.rst @@ -317,7 +317,7 @@ sophisticated and robust capabilities of its larger packages. For example: names, no direct knowledge or handling of XML is needed. * The :mod:`email` package is a library for managing email messages, including - MIME and other RFC 2822-based message documents. Unlike :mod:`smtplib` and + MIME and other :rfc:`2822`-based message documents. Unlike :mod:`smtplib` and :mod:`poplib` which actually send and receive messages, the email package has a complete toolset for building or decoding complex message structures (including attachments) and for implementing internet encoding and header diff --git a/Doc/whatsnew/2.4.rst b/Doc/whatsnew/2.4.rst index 7c125ffd2ad0..7e11c98399cc 100644 --- a/Doc/whatsnew/2.4.rst +++ b/Doc/whatsnew/2.4.rst @@ -998,7 +998,7 @@ complete list of changes, or look through the CVS logs for all the details. that lets you perform a limited number of passes through the polling loop. The default is still to loop forever. -* The :mod:`base64` module now has more complete RFC 3548 support for Base64, +* The :mod:`base64` module now has more complete :rfc:`3548` support for Base64, Base32, and Base16 encoding and decoding, including optional case folding and optional alternative alphabets. (Contributed by Barry Warsaw.) From webhook-mailer at python.org Thu May 31 01:35:06 2018 From: webhook-mailer at python.org (Victor Stinner) Date: Thu, 31 May 2018 05:35:06 -0000 Subject: [Python-checkins] bpo-33532: Fix multiprocessing test_ignore() (GH-7262) (#7266) Message-ID: <mailman.117.1527744912.2800.python-checkins@python.org> https://github.com/python/cpython/commit/c2870b699eb899f358b843c2d706ce8ca89b2bf4 commit: c2870b699eb899f358b843c2d706ce8ca89b2bf4 branch: 3.6 author: Victor Stinner <vstinner at redhat.com> committer: GitHub <noreply at github.com> date: 2018-05-31T07:35:03+02:00 summary: bpo-33532: Fix multiprocessing test_ignore() (GH-7262) (#7266) Fix test_ignore() of multiprocessing tests like test_multiprocessing_forkserver: use support.PIPE_MAX_SIZE to make sure that send_bytes() blocks. (cherry picked from commit 5d6c7ed5e340b2311a15f34e968d4bef09c71922) files: M Lib/test/_test_multiprocessing.py diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index dd0a9d7a862a..d7eb69bb8b8f 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -4029,7 +4029,7 @@ def handler(signum, frame): conn.send('ready') x = conn.recv() conn.send(x) - conn.send_bytes(b'x'*(1024*1024)) # sending 1 MB should block + conn.send_bytes(b'x' * test.support.PIPE_MAX_SIZE) @unittest.skipUnless(hasattr(signal, 'SIGUSR1'), 'requires SIGUSR1') def test_ignore(self): @@ -4048,7 +4048,8 @@ def test_ignore(self): self.assertEqual(conn.recv(), 1234) time.sleep(0.1) os.kill(p.pid, signal.SIGUSR1) - self.assertEqual(conn.recv_bytes(), b'x'*(1024*1024)) + self.assertEqual(conn.recv_bytes(), + b'x' * test.support.PIPE_MAX_SIZE) time.sleep(0.1) p.join() finally: From webhook-mailer at python.org Thu May 31 01:35:36 2018 From: webhook-mailer at python.org (Victor Stinner) Date: Thu, 31 May 2018 05:35:36 -0000 Subject: [Python-checkins] bpo-33532: Fix multiprocessing test_ignore() (GH-7265) Message-ID: <mailman.118.1527744937.2800.python-checkins@python.org> https://github.com/python/cpython/commit/82c456fa37d4b87da0d64e574bd8adc665abc4c8 commit: 82c456fa37d4b87da0d64e574bd8adc665abc4c8 branch: 2.7 author: Victor Stinner <vstinner at redhat.com> committer: GitHub <noreply at github.com> date: 2018-05-31T07:35:34+02:00 summary: bpo-33532: Fix multiprocessing test_ignore() (GH-7265) Fix test_multiprocessing.test_ignore(): use support.PIPE_MAX_SIZE to make sure that send_bytes() blocks. files: M Lib/test/test_multiprocessing.py diff --git a/Lib/test/test_multiprocessing.py b/Lib/test/test_multiprocessing.py index 1071d7fac653..b293e2fbc4ea 100644 --- a/Lib/test/test_multiprocessing.py +++ b/Lib/test/test_multiprocessing.py @@ -2689,7 +2689,7 @@ def handler(signum, frame): conn.send('ready') x = conn.recv() conn.send(x) - conn.send_bytes(b'x'*(1024*1024)) # sending 1 MB should block + conn.send_bytes(b'x' * test_support.PIPE_MAX_SIZE) @unittest.skipUnless(hasattr(signal, 'SIGUSR1'), 'requires SIGUSR1') def test_ignore(self): @@ -2708,7 +2708,8 @@ def test_ignore(self): self.assertEqual(conn.recv(), 1234) time.sleep(0.1) os.kill(p.pid, signal.SIGUSR1) - self.assertEqual(conn.recv_bytes(), b'x'*(1024*1024)) + self.assertEqual(conn.recv_bytes(), + b'x' * test_support.PIPE_MAX_SIZE) time.sleep(0.1) p.join() finally: From webhook-mailer at python.org Thu May 31 02:10:31 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Thu, 31 May 2018 06:10:31 -0000 Subject: [Python-checkins] bpo-33677: Fix signatures of tp_clear handlers for AST and deque. (GH-7196) (GH-7269) Message-ID: <mailman.119.1527747033.2800.python-checkins@python.org> https://github.com/python/cpython/commit/0fe3be03926c3468ed4c10980d1a030c8ef4e37e commit: 0fe3be03926c3468ed4c10980d1a030c8ef4e37e branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Serhiy Storchaka <storchaka at gmail.com> date: 2018-05-31T09:10:28+03:00 summary: bpo-33677: Fix signatures of tp_clear handlers for AST and deque. (GH-7196) (GH-7269) (cherry picked from commit a5c42284e69fb309bdd17ee8c1c120d1be383012) Co-authored-by: Serhiy Storchaka <storchaka at gmail.com> files: M Modules/_collectionsmodule.c M Parser/asdl_c.py M Python/Python-ast.c diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c index af20d6edd918..d7b344be692c 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -574,7 +574,7 @@ deque_concat(dequeobject *deque, PyObject *other) return new_deque; } -static void +static int deque_clear(dequeobject *deque) { block *b; @@ -586,7 +586,7 @@ deque_clear(dequeobject *deque) PyObject **itemptr, **limit; if (Py_SIZE(deque) == 0) - return; + return 0; /* During the process of clearing a deque, decrefs can cause the deque to mutate. To avoid fatal confusion, we have to make the @@ -647,7 +647,7 @@ deque_clear(dequeobject *deque) } CHECK_END(leftblock->rightlink); freeblock(leftblock); - return; + return 0; alternate_method: while (Py_SIZE(deque)) { @@ -655,6 +655,7 @@ deque_clear(dequeobject *deque) assert (item != NULL); Py_DECREF(item); } + return 0; } static PyObject * diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py index 6302af6fa3e3..90c5feaa7e71 100644 --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -643,10 +643,11 @@ def visitModule(self, mod): return 0; } -static void +static int ast_clear(AST_object *self) { Py_CLEAR(self->dict); + return 0; } static int diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 212211c5f435..8e383ad14cae 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -525,10 +525,11 @@ ast_traverse(AST_object *self, visitproc visit, void *arg) return 0; } -static void +static int ast_clear(AST_object *self) { Py_CLEAR(self->dict); + return 0; } static int From webhook-mailer at python.org Thu May 31 02:11:10 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Thu, 31 May 2018 06:11:10 -0000 Subject: [Python-checkins] [3.6] bpo-33641: Convert RFC references into links. (GH-7103) (GH-7276) Message-ID: <mailman.120.1527747074.2800.python-checkins@python.org> https://github.com/python/cpython/commit/55d9e865cb3b50587c17c8a7beee090c4ac8d535 commit: 55d9e865cb3b50587c17c8a7beee090c4ac8d535 branch: 3.6 author: Serhiy Storchaka <storchaka at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-31T09:11:07+03:00 summary: [3.6] bpo-33641: Convert RFC references into links. (GH-7103) (GH-7276) 85% of them are already links. (cherry picked from commit 0a36ac1a09587735237c5978ebd046313922869c) files: M Doc/howto/logging-cookbook.rst M Doc/howto/logging.rst M Doc/howto/urllib2.rst M Doc/library/binascii.rst M Doc/library/codecs.rst M Doc/library/email.examples.rst M Doc/library/ftplib.rst M Doc/library/hashlib.rst M Doc/library/http.cookiejar.rst M Doc/library/imaplib.rst M Doc/library/logging.handlers.rst M Doc/library/logging.rst M Doc/library/nntplib.rst M Doc/library/ssl.rst M Doc/library/stringprep.rst M Doc/library/urllib.error.rst M Doc/library/urllib.request.rst M Doc/library/uuid.rst M Doc/library/wsgiref.rst M Doc/library/xmlrpc.client.rst M Doc/tutorial/stdlib.rst M Doc/whatsnew/2.4.rst diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst index b43dc2b1fa09..96d550c457b8 100644 --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -1652,11 +1652,11 @@ works:: Inserting a BOM into messages sent to a SysLogHandler ----------------------------------------------------- -`RFC 5424 <https://tools.ietf.org/html/rfc5424>`_ requires that a +:rfc:`5424` requires that a Unicode message be sent to a syslog daemon as a set of bytes which have the following structure: an optional pure-ASCII component, followed by a UTF-8 Byte -Order Mark (BOM), followed by Unicode encoded using UTF-8. (See the `relevant -section of the specification <https://tools.ietf.org/html/rfc5424#section-6>`_.) +Order Mark (BOM), followed by Unicode encoded using UTF-8. (See the +:rfc:`relevant section of the specification <5424#section-6>`.) In Python 3.1, code was added to :class:`~logging.handlers.SysLogHandler` to insert a BOM into the message, but @@ -1666,7 +1666,7 @@ appear before it. As this behaviour is broken, the incorrect BOM insertion code is being removed from Python 3.2.4 and later. However, it is not being replaced, and if you -want to produce RFC 5424-compliant messages which include a BOM, an optional +want to produce :rfc:`5424`-compliant messages which include a BOM, an optional pure-ASCII sequence before it and arbitrary Unicode after it, encoded using UTF-8, then you need to do the following: @@ -1689,7 +1689,7 @@ UTF-8, then you need to do the following: The formatted message *will* be encoded using UTF-8 encoding by ``SysLogHandler``. If you follow the above rules, you should be able to produce -RFC 5424-compliant messages. If you don't, logging may not complain, but your +:rfc:`5424`-compliant messages. If you don't, logging may not complain, but your messages will not be RFC 5424-compliant, and your syslog daemon may complain. diff --git a/Doc/howto/logging.rst b/Doc/howto/logging.rst index 5976c32d93b0..9914f8d154ab 100644 --- a/Doc/howto/logging.rst +++ b/Doc/howto/logging.rst @@ -297,7 +297,7 @@ which should print something like this: 2010-12-12 11:41:42,612 is when this event was logged. The default format for date/time display (shown above) is like ISO8601 or -RFC 3339. If you need more control over the formatting of the date/time, provide +:rfc:`3339`. If you need more control over the formatting of the date/time, provide a *datefmt* argument to ``basicConfig``, as in this example:: import logging diff --git a/Doc/howto/urllib2.rst b/Doc/howto/urllib2.rst index 8b93d701869d..7505e7564422 100644 --- a/Doc/howto/urllib2.rst +++ b/Doc/howto/urllib2.rst @@ -239,7 +239,7 @@ a different URL, urllib will handle that for you). For those it can't handle, urlopen will raise an :exc:`HTTPError`. Typical errors include '404' (page not found), '403' (request forbidden), and '401' (authentication required). -See section 10 of RFC 2616 for a reference on all the HTTP error codes. +See section 10 of :rfc:`2616` for a reference on all the HTTP error codes. The :exc:`HTTPError` instance raised will have an integer 'code' attribute, which corresponds to the error sent by the server. @@ -252,7 +252,7 @@ codes in the 100--299 range indicate success, you will usually only see error codes in the 400--599 range. :attr:`http.server.BaseHTTPRequestHandler.responses` is a useful dictionary of -response codes in that shows all the response codes used by RFC 2616. The +response codes in that shows all the response codes used by :rfc:`2616`. The dictionary is reproduced here for convenience :: # Table mapping response codes to messages; entries have the diff --git a/Doc/library/binascii.rst b/Doc/library/binascii.rst index 0476f507717c..adb087ef8826 100644 --- a/Doc/library/binascii.rst +++ b/Doc/library/binascii.rst @@ -77,7 +77,7 @@ The :mod:`binascii` module defines the following functions: *quotetabs* is present and true, all tabs and spaces will be encoded. If the optional argument *istext* is present and true, newlines are not encoded but trailing whitespace will be encoded. If the optional argument *header* is - present and true, spaces will be encoded as underscores per RFC1522. If the + present and true, spaces will be encoded as underscores per :rfc:`1522`. If the optional argument *header* is present and false, newline characters will be encoded as well; otherwise linefeed conversion might corrupt the binary data stream. diff --git a/Doc/library/codecs.rst b/Doc/library/codecs.rst index 74b24e10ede6..24008a0b3f00 100644 --- a/Doc/library/codecs.rst +++ b/Doc/library/codecs.rst @@ -1425,7 +1425,7 @@ to the user. Python supports this conversion in several ways: the ``idna`` codec performs conversion between Unicode and ACE, separating an input string into labels -based on the separator characters defined in `section 3.1`_ (1) of :rfc:`3490` +based on the separator characters defined in :rfc:`section 3.1 of RFC 3490 <3490#section-3.1>` and converting each label to ACE as required, and conversely separating an input byte string into labels based on the ``.`` separator and converting any ACE labels found into unicode. Furthermore, the :mod:`socket` module @@ -1436,8 +1436,6 @@ parameters, such as :mod:`http.client` and :mod:`ftplib`, accept Unicode host names (:mod:`http.client` then also transparently sends an IDNA hostname in the :mailheader:`Host` field if it sends that field at all). -.. _section 3.1: https://tools.ietf.org/html/rfc3490#section-3.1 - When receiving host names from the wire (such as in reverse name lookup), no automatic conversion to Unicode is performed: Applications wishing to present such host names to the user should decode them to Unicode. diff --git a/Doc/library/email.examples.rst b/Doc/library/email.examples.rst index 84e9aee0bc48..fc964622809d 100644 --- a/Doc/library/email.examples.rst +++ b/Doc/library/email.examples.rst @@ -12,7 +12,7 @@ text content and the addresses may contain unicode characters): .. literalinclude:: ../includes/email-simple.py -Parsing RFC822 headers can easily be done by the using the classes +Parsing :rfc:`822` headers can easily be done by the using the classes from the :mod:`~email.parser` module: .. literalinclude:: ../includes/email-headers.py diff --git a/Doc/library/ftplib.rst b/Doc/library/ftplib.rst index 7291dfe84811..6c39f9a59fc1 100644 --- a/Doc/library/ftplib.rst +++ b/Doc/library/ftplib.rst @@ -295,7 +295,7 @@ followed by ``lines`` for the text version or ``binary`` for the binary version. If optional *rest* is given, a ``REST`` command is sent to the server, passing *rest* as an argument. *rest* is usually a byte offset into the requested file, telling the server to restart sending the file's bytes at the requested offset, - skipping over the initial bytes. Note however that RFC 959 requires only that + skipping over the initial bytes. Note however that :rfc:`959` requires only that *rest* be a string containing characters in the printable range from ASCII code 33 to ASCII code 126. The :meth:`transfercmd` method, therefore, converts *rest* to a string, but no check is performed on the string's contents. If the diff --git a/Doc/library/hashlib.rst b/Doc/library/hashlib.rst index 3a27a5b566f5..9bd39cb4a51b 100644 --- a/Doc/library/hashlib.rst +++ b/Doc/library/hashlib.rst @@ -283,7 +283,7 @@ BLAKE2 .. index:: single: blake2b, blake2s -BLAKE2_ is a cryptographic hash function defined in RFC-7693_ that comes in two +BLAKE2_ is a cryptographic hash function defined in :rfc:`7693` that comes in two flavors: * **BLAKE2b**, optimized for 64-bit platforms and produces digests of any size @@ -707,7 +707,6 @@ Domain Dedication 1.0 Universal: * *Alexandr Sokolovskiy* -.. _RFC-7693: https://tools.ietf.org/html/rfc7693 .. _BLAKE2: https://blake2.net .. _HMAC: https://en.wikipedia.org/wiki/Hash-based_message_authentication_code .. _BLAKE: https://131002.net/blake/ diff --git a/Doc/library/http.cookiejar.rst b/Doc/library/http.cookiejar.rst index 5370601544c7..d8da6683a3a5 100644 --- a/Doc/library/http.cookiejar.rst +++ b/Doc/library/http.cookiejar.rst @@ -88,7 +88,7 @@ The following classes are provided: :class:`DefaultCookiePolicy` objects. :class:`DefaultCookiePolicy` implements the standard accept / reject rules for - Netscape and RFC 2965 cookies. By default, RFC 2109 cookies (ie. cookies + Netscape and :rfc:`2965` cookies. By default, :rfc:`2109` cookies (ie. cookies received in a :mailheader:`Set-Cookie` header with a version cookie-attribute of 1) are treated according to the RFC 2965 rules. However, if RFC 2965 handling is turned off or :attr:`rfc2109_as_netscape` is ``True``, RFC 2109 cookies are @@ -100,7 +100,7 @@ The following classes are provided: .. class:: Cookie() - This class represents Netscape, RFC 2109 and RFC 2965 cookies. It is not + This class represents Netscape, :rfc:`2109` and :rfc:`2965` cookies. It is not expected that users of :mod:`http.cookiejar` construct their own :class:`Cookie` instances. Instead, if necessary, call :meth:`make_cookies` on a :class:`CookieJar` instance. @@ -123,14 +123,14 @@ The following classes are provided: the one sketched out in ``cookie_spec.html``. :rfc:`2109` - HTTP State Management Mechanism - Obsoleted by RFC 2965. Uses :mailheader:`Set-Cookie` with version=1. + Obsoleted by :rfc:`2965`. Uses :mailheader:`Set-Cookie` with version=1. :rfc:`2965` - HTTP State Management Mechanism The Netscape protocol with the bugs fixed. Uses :mailheader:`Set-Cookie2` in place of :mailheader:`Set-Cookie`. Not widely used. http://kristol.org/cookie/errata.html - Unfinished errata to RFC 2965. + Unfinished errata to :rfc:`2965`. :rfc:`2964` - Use of HTTP State Management @@ -320,7 +320,7 @@ writing. .. note:: - This loses information about RFC 2965 cookies, and also about newer or + This loses information about :rfc:`2965` cookies, and also about newer or non-standard cookie-attributes such as ``port``. .. warning:: @@ -410,13 +410,13 @@ be assigned to. .. attribute:: CookiePolicy.rfc2965 - Implement RFC 2965 protocol. + Implement :rfc:`2965` protocol. .. attribute:: CookiePolicy.hide_cookie2 Don't add :mailheader:`Cookie2` header to requests (the presence of this header - indicates to the server that we understand RFC 2965 cookies). + indicates to the server that we understand :rfc:`2965` cookies). The most useful way to define a :class:`CookiePolicy` class is by subclassing from :class:`DefaultCookiePolicy` and overriding some or all of the methods @@ -431,7 +431,7 @@ DefaultCookiePolicy Objects Implements the standard rules for accepting and returning cookies. -Both RFC 2965 and Netscape cookies are covered. RFC 2965 handling is switched +Both :rfc:`2965` and Netscape cookies are covered. RFC 2965 handling is switched off by default. The easiest way to provide your own policy is to override this class and call @@ -510,11 +510,11 @@ all be assigned to. .. attribute:: DefaultCookiePolicy.rfc2109_as_netscape - If true, request that the :class:`CookieJar` instance downgrade RFC 2109 cookies + If true, request that the :class:`CookieJar` instance downgrade :rfc:`2109` cookies (ie. cookies received in a :mailheader:`Set-Cookie` header with a version cookie-attribute of 1) to Netscape cookies by setting the version attribute of the :class:`Cookie` instance to 0. The default value is :const:`None`, in which - case RFC 2109 cookies are downgraded if and only if RFC 2965 handling is turned + case RFC 2109 cookies are downgraded if and only if :rfc:`2965` handling is turned off. Therefore, RFC 2109 cookies are downgraded by default. @@ -527,11 +527,11 @@ General strictness switches: and isn't guaranteed to work! -RFC 2965 protocol strictness switches: +:rfc:`2965` protocol strictness switches: .. attribute:: DefaultCookiePolicy.strict_rfc2965_unverifiable - Follow RFC 2965 rules on unverifiable transactions (usually, an unverifiable + Follow :rfc:`2965` rules on unverifiable transactions (usually, an unverifiable transaction is one resulting from a redirect or a request for an image hosted on another site). If this is false, cookies are *never* blocked on the basis of verifiability @@ -541,7 +541,7 @@ Netscape protocol strictness switches: .. attribute:: DefaultCookiePolicy.strict_ns_unverifiable - Apply RFC 2965 rules on unverifiable transactions even to Netscape cookies. + Apply :rfc:`2965` rules on unverifiable transactions even to Netscape cookies. .. attribute:: DefaultCookiePolicy.strict_ns_domain @@ -581,7 +581,7 @@ both flags are set). .. attribute:: DefaultCookiePolicy.DomainRFC2965Match - When setting cookies, require a full RFC 2965 domain-match. + When setting cookies, require a full :rfc:`2965` domain-match. The following attributes are provided for convenience, and are the most useful combinations of the above flags: @@ -605,7 +605,7 @@ Cookie Objects standard cookie-attributes specified in the various cookie standards. The correspondence is not one-to-one, because there are complicated rules for assigning default values, because the ``max-age`` and ``expires`` -cookie-attributes contain equivalent information, and because RFC 2109 cookies +cookie-attributes contain equivalent information, and because :rfc:`2109` cookies may be 'downgraded' by :mod:`http.cookiejar` from version 1 to version 0 (Netscape) cookies. @@ -616,8 +616,8 @@ internal consistency, so you should know what you're doing if you do that. .. attribute:: Cookie.version - Integer or :const:`None`. Netscape cookies have :attr:`version` 0. RFC 2965 and - RFC 2109 cookies have a ``version`` cookie-attribute of 1. However, note that + Integer or :const:`None`. Netscape cookies have :attr:`version` 0. :rfc:`2965` and + :rfc:`2109` cookies have a ``version`` cookie-attribute of 1. However, note that :mod:`http.cookiejar` may 'downgrade' RFC 2109 cookies to Netscape cookies, in which case :attr:`version` is 0. @@ -673,7 +673,7 @@ internal consistency, so you should know what you're doing if you do that. .. attribute:: Cookie.rfc2109 - ``True`` if this cookie was received as an RFC 2109 cookie (ie. the cookie + ``True`` if this cookie was received as an :rfc:`2109` cookie (ie. the cookie arrived in a :mailheader:`Set-Cookie` header, and the value of the Version cookie-attribute in that header was 1). This attribute is provided because :mod:`http.cookiejar` may 'downgrade' RFC 2109 cookies to Netscape cookies, in @@ -745,7 +745,7 @@ cookies (assumes Unix/Netscape convention for location of the cookies file):: r = opener.open("http://example.com/") The next example illustrates the use of :class:`DefaultCookiePolicy`. Turn on -RFC 2965 cookies, be more strict about domains when setting and returning +:rfc:`2965` cookies, be more strict about domains when setting and returning Netscape cookies, and block some domains from setting cookies or having them returned:: diff --git a/Doc/library/imaplib.rst b/Doc/library/imaplib.rst index 1632eb7aed36..2e2c59c9ce00 100644 --- a/Doc/library/imaplib.rst +++ b/Doc/library/imaplib.rst @@ -342,7 +342,7 @@ An :class:`IMAP4` instance has the following methods: .. method:: IMAP4.namespace() - Returns IMAP namespaces as defined in RFC2342. + Returns IMAP namespaces as defined in :rfc:`2342`. .. method:: IMAP4.noop() diff --git a/Doc/library/logging.handlers.rst b/Doc/library/logging.handlers.rst index 6bb7b13af813..a31ee31922fc 100644 --- a/Doc/library/logging.handlers.rst +++ b/Doc/library/logging.handlers.rst @@ -583,7 +583,7 @@ supports sending logging messages to a remote or local Unix syslog. (See: :issue:`12168`.) In earlier versions, the message sent to the syslog daemons was always terminated with a NUL byte, because early versions of these daemons expected a NUL terminated message - even - though it's not in the relevant specification (RFC 5424). More recent + though it's not in the relevant specification (:rfc:`5424`). More recent versions of these daemons don't expect the NUL byte but strip it off if it's there, and even more recent daemons (which adhere more closely to RFC 5424) pass the NUL byte on as part of the message. diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst index d0a6e613d8ee..3072a53ef4bf 100644 --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -516,7 +516,7 @@ The useful mapping keys in a :class:`LogRecord` are given in the section on initialized with a format string for the message as a whole, as well as a format string for the date/time portion of a message. If no *fmt* is specified, ``'%(message)s'`` is used. If no *datefmt* is specified, an - ISO8601-like (or RFC3339-like) date format is used. See the + ISO8601-like (or :rfc:`3339`-like) date format is used. See the :meth:`formatTime` documentation for more details. The *style* parameter can be one of '%', '{' or '$' and determines how diff --git a/Doc/library/nntplib.rst b/Doc/library/nntplib.rst index 2c3cd8dafe6e..d8ef8a692a95 100644 --- a/Doc/library/nntplib.rst +++ b/Doc/library/nntplib.rst @@ -542,7 +542,7 @@ them have been superseded by newer commands in :rfc:`3977`. is supplied, then the returned *list* is an empty list. This is an optional NNTP extension, and may not be supported by all servers. - RFC2980 says "It is suggested that this extension be deprecated". Use + :rfc:`2980` says "It is suggested that this extension be deprecated". Use :meth:`descriptions` or :meth:`description` instead. diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index cb17742bcc8b..caf298ae02b8 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -2345,25 +2345,25 @@ with LibreSSL. `SSL/TLS Strong Encryption: An Introduction <https://httpd.apache.org/docs/trunk/en/ssl/ssl_intro.html>`_ Intro from the Apache HTTP Server documentation - `RFC 1422: Privacy Enhancement for Internet Electronic Mail: Part II: Certificate-Based Key Management <https://www.ietf.org/rfc/rfc1422>`_ + :rfc:`RFC 1422: Privacy Enhancement for Internet Electronic Mail: Part II: Certificate-Based Key Management <1422>` Steve Kent - `RFC 4086: Randomness Requirements for Security <http://datatracker.ietf.org/doc/rfc4086/>`_ + :rfc:`RFC 4086: Randomness Requirements for Security <4086>` Donald E., Jeffrey I. Schiller - `RFC 5280: Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile <http://datatracker.ietf.org/doc/rfc5280/>`_ + :rfc:`RFC 5280: Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile <5280>` D. Cooper - `RFC 5246: The Transport Layer Security (TLS) Protocol Version 1.2 <https://tools.ietf.org/html/rfc5246>`_ + :rfc:`RFC 5246: The Transport Layer Security (TLS) Protocol Version 1.2 <5246>` T. Dierks et. al. - `RFC 6066: Transport Layer Security (TLS) Extensions <https://tools.ietf.org/html/rfc6066>`_ + :rfc:`RFC 6066: Transport Layer Security (TLS) Extensions <6066>` D. Eastlake `IANA TLS: Transport Layer Security (TLS) Parameters <https://www.iana.org/assignments/tls-parameters/tls-parameters.xml>`_ IANA - `RFC 7525: Recommendations for Secure Use of Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS) <https://tools.ietf.org/html/rfc7525>`_ + :rfc:`RFC 7525: Recommendations for Secure Use of Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS) <7525>` IETF `Mozilla's Server Side TLS recommendations <https://wiki.mozilla.org/Security/Server_Side_TLS>`_ diff --git a/Doc/library/stringprep.rst b/Doc/library/stringprep.rst index e7fae5631d87..330032ba1c0b 100644 --- a/Doc/library/stringprep.rst +++ b/Doc/library/stringprep.rst @@ -26,7 +26,7 @@ define which tables it uses, and what other optional parts of the ``stringprep`` procedure are part of the profile. One example of a ``stringprep`` profile is ``nameprep``, which is used for internationalized domain names. -The module :mod:`stringprep` only exposes the tables from RFC 3454. As these +The module :mod:`stringprep` only exposes the tables from :rfc:`3454`. As these tables would be very large to represent them as dictionaries or lists, the module uses the Unicode character database internally. The module source code itself was generated using the ``mkstringprep.py`` utility. diff --git a/Doc/library/urllib.error.rst b/Doc/library/urllib.error.rst index 5517b04f5ddf..f7d47ed76aca 100644 --- a/Doc/library/urllib.error.rst +++ b/Doc/library/urllib.error.rst @@ -41,8 +41,7 @@ The following exceptions are raised by :mod:`urllib.error` as appropriate: .. attribute:: code - An HTTP status code as defined in `RFC 2616 - <http://www.faqs.org/rfcs/rfc2616.html>`_. This numeric value corresponds + An HTTP status code as defined in :rfc:`2616`. This numeric value corresponds to a value found in the dictionary of codes as found in :attr:`http.server.BaseHTTPRequestHandler.responses`. diff --git a/Doc/library/urllib.request.rst b/Doc/library/urllib.request.rst index 5a10f9571e9e..705517a32e33 100644 --- a/Doc/library/urllib.request.rst +++ b/Doc/library/urllib.request.rst @@ -232,7 +232,7 @@ The following classes are provided: containing the image. *unverifiable* should indicate whether the request is unverifiable, - as defined by RFC 2965. It defaults to ``False``. An unverifiable + as defined by :rfc:`2965`. It defaults to ``False``. An unverifiable request is one whose URL the user did not have the option to approve. For example, if the request is for an image in an HTML document, and the user had no option to approve the automatic @@ -504,7 +504,7 @@ request. .. attribute:: Request.unverifiable boolean, indicates whether the request is unverifiable as defined - by RFC 2965. + by :rfc:`2965`. .. attribute:: Request.method diff --git a/Doc/library/uuid.rst b/Doc/library/uuid.rst index edbf832529a6..6ac1ffb96584 100644 --- a/Doc/library/uuid.rst +++ b/Doc/library/uuid.rst @@ -1,5 +1,5 @@ -:mod:`uuid` --- UUID objects according to RFC 4122 -================================================== +:mod:`uuid` --- UUID objects according to :rfc:`4122` +===================================================== .. module:: uuid :synopsis: UUID objects (universally unique identifiers) according to RFC 4122 @@ -42,7 +42,7 @@ random UUID. Exactly one of *hex*, *bytes*, *bytes_le*, *fields*, or *int* must be given. The *version* argument is optional; if given, the resulting UUID will have its - variant and version number set according to RFC 4122, overriding bits in the + variant and version number set according to :rfc:`4122`, overriding bits in the given *hex*, *bytes*, *bytes_le*, *fields*, or *int*. Comparison of UUID objects are made by way of comparing their @@ -105,7 +105,7 @@ random UUID. .. attribute:: UUID.urn - The UUID as a URN as specified in RFC 4122. + The UUID as a URN as specified in :rfc:`4122`. .. attribute:: UUID.variant @@ -128,7 +128,7 @@ The :mod:`uuid` module defines the following functions: Get the hardware address as a 48-bit positive integer. The first time this runs, it may launch a separate program, which could be quite slow. If all attempts to obtain the hardware address fail, we choose a random 48-bit number - with its eighth bit set to 1 as recommended in RFC 4122. "Hardware address" + with its eighth bit set to 1 as recommended in :rfc:`4122`. "Hardware address" means the MAC address of a network interface, and on a machine with multiple network interfaces the MAC address of any one of them may be returned. diff --git a/Doc/library/wsgiref.rst b/Doc/library/wsgiref.rst index a1d446902b83..ddfc2e54732b 100644 --- a/Doc/library/wsgiref.rst +++ b/Doc/library/wsgiref.rst @@ -397,7 +397,7 @@ Paste" library. Wrap *application* and return a new WSGI application object. The returned application will forward all requests to the original *application*, and will check that both the *application* and the server invoking it are conforming to - the WSGI specification and to RFC 2616. + the WSGI specification and to :rfc:`2616`. Any detected nonconformance results in an :exc:`AssertionError` being raised; note, however, that how these errors are handled is server-dependent. For diff --git a/Doc/library/xmlrpc.client.rst b/Doc/library/xmlrpc.client.rst index 390828ef3d98..ed2ccaeae07a 100644 --- a/Doc/library/xmlrpc.client.rst +++ b/Doc/library/xmlrpc.client.rst @@ -328,7 +328,7 @@ Binary Objects Write the XML-RPC base 64 encoding of this binary item to the *out* stream object. The encoded data will have newlines every 76 characters as per - `RFC 2045 section 6.8 <https://tools.ietf.org/html/rfc2045#section-6.8>`_, + :rfc:`RFC 2045 section 6.8 <2045#section-6.8>`, which was the de facto standard base64 specification when the XML-RPC spec was written. diff --git a/Doc/tutorial/stdlib.rst b/Doc/tutorial/stdlib.rst index 1dd06c233826..110e6e546668 100644 --- a/Doc/tutorial/stdlib.rst +++ b/Doc/tutorial/stdlib.rst @@ -317,7 +317,7 @@ sophisticated and robust capabilities of its larger packages. For example: names, no direct knowledge or handling of XML is needed. * The :mod:`email` package is a library for managing email messages, including - MIME and other RFC 2822-based message documents. Unlike :mod:`smtplib` and + MIME and other :rfc:`2822`-based message documents. Unlike :mod:`smtplib` and :mod:`poplib` which actually send and receive messages, the email package has a complete toolset for building or decoding complex message structures (including attachments) and for implementing internet encoding and header diff --git a/Doc/whatsnew/2.4.rst b/Doc/whatsnew/2.4.rst index 7c125ffd2ad0..7e11c98399cc 100644 --- a/Doc/whatsnew/2.4.rst +++ b/Doc/whatsnew/2.4.rst @@ -998,7 +998,7 @@ complete list of changes, or look through the CVS logs for all the details. that lets you perform a limited number of passes through the polling loop. The default is still to loop forever. -* The :mod:`base64` module now has more complete RFC 3548 support for Base64, +* The :mod:`base64` module now has more complete :rfc:`3548` support for Base64, Base32, and Base16 encoding and decoding, including optional case folding and optional alternative alphabets. (Contributed by Barry Warsaw.) From webhook-mailer at python.org Thu May 31 02:11:59 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Thu, 31 May 2018 06:11:59 -0000 Subject: [Python-checkins] bpo-32911: Add the historical note about the magic number. (GH-7273) Message-ID: <mailman.121.1527747122.2800.python-checkins@python.org> https://github.com/python/cpython/commit/941ec210aaef517cf818b043ec28345962f78465 commit: 941ec210aaef517cf818b043ec28345962f78465 branch: master author: Serhiy Storchaka <storchaka at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-31T09:11:55+03:00 summary: bpo-32911: Add the historical note about the magic number. (GH-7273) files: M Lib/importlib/_bootstrap_external.py M Python/importlib_external.h diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index da9a75c673bc..bdd7859ea03a 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -246,6 +246,8 @@ def _write_atomic(path, data, mode=0o666): # Python 3.7a2 3391 (update GET_AITER #31709) # Python 3.7a4 3392 (PEP 552: Deterministic pycs #31650) # Python 3.7b1 3393 (remove STORE_ANNOTATION opcode #32550) +# Python 3.7b5 3394 (restored docstring as the firts stmt in the body; +# this might affected the first line number #32911) # Python 3.8a1 3400 (move frame block handling to compiler #17611) # Python 3.8a1 3401 (add END_ASYNC_FOR #33041) # diff --git a/Python/importlib_external.h b/Python/importlib_external.h index 26a0383588a4..16a9fc0c9195 100644 --- a/Python/importlib_external.h +++ b/Python/importlib_external.h @@ -348,7 +348,7 @@ const unsigned char _Py_M__importlib_external[] = { 15,97,108,109,111,115,116,95,102,105,108,101,110,97,109,101, 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,218, 17,99,97,99,104,101,95,102,114,111,109,95,115,111,117,114, - 99,101,15,1,0,0,115,48,0,0,0,0,18,8,1,6, + 99,101,17,1,0,0,115,48,0,0,0,0,18,8,1,6, 1,6,1,8,1,4,1,8,1,12,1,10,1,12,1,16, 1,8,1,8,1,8,1,24,1,8,1,12,1,6,2,8, 1,8,1,8,1,8,1,14,1,14,1,114,81,0,0,0, @@ -422,7 +422,7 @@ const unsigned char _Py_M__importlib_external[] = { 95,108,101,118,101,108,90,13,98,97,115,101,95,102,105,108, 101,110,97,109,101,114,2,0,0,0,114,2,0,0,0,114, 4,0,0,0,218,17,115,111,117,114,99,101,95,102,114,111, - 109,95,99,97,99,104,101,60,1,0,0,115,46,0,0,0, + 109,95,99,97,99,104,101,62,1,0,0,115,46,0,0,0, 0,9,12,1,8,1,10,1,12,1,12,1,8,1,6,1, 10,1,10,1,8,1,6,1,10,1,8,1,16,1,10,1, 6,1,8,1,16,1,8,1,6,1,8,1,14,1,114,87, @@ -456,7 +456,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,114,36,0,0,0,90,9,101,120,116,101,110,115,105,111, 110,218,11,115,111,117,114,99,101,95,112,97,116,104,114,2, 0,0,0,114,2,0,0,0,114,4,0,0,0,218,15,95, - 103,101,116,95,115,111,117,114,99,101,102,105,108,101,94,1, + 103,101,116,95,115,111,117,114,99,101,102,105,108,101,96,1, 0,0,115,20,0,0,0,0,7,12,1,4,1,16,1,24, 1,4,1,2,1,12,1,18,1,18,1,114,93,0,0,0, 99,1,0,0,0,0,0,0,0,1,0,0,0,8,0,0, @@ -470,7 +470,7 @@ const unsigned char _Py_M__importlib_external[] = { 81,0,0,0,114,68,0,0,0,114,76,0,0,0,41,1, 218,8,102,105,108,101,110,97,109,101,114,2,0,0,0,114, 2,0,0,0,114,4,0,0,0,218,11,95,103,101,116,95, - 99,97,99,104,101,100,113,1,0,0,115,16,0,0,0,0, + 99,97,99,104,101,100,115,1,0,0,115,16,0,0,0,0, 1,14,1,2,1,10,1,14,1,8,1,14,1,4,2,114, 97,0,0,0,99,1,0,0,0,0,0,0,0,2,0,0, 0,8,0,0,0,67,0,0,0,115,52,0,0,0,122,14, @@ -484,7 +484,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,0,41,3,114,39,0,0,0,114,41,0,0,0,114, 40,0,0,0,41,2,114,35,0,0,0,114,42,0,0,0, 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,218, - 10,95,99,97,108,99,95,109,111,100,101,125,1,0,0,115, + 10,95,99,97,108,99,95,109,111,100,101,127,1,0,0,115, 12,0,0,0,0,2,2,1,14,1,14,1,10,3,8,1, 114,99,0,0,0,99,1,0,0,0,0,0,0,0,3,0, 0,0,8,0,0,0,3,0,0,0,115,68,0,0,0,100, @@ -522,7 +522,7 @@ const unsigned char _Py_M__importlib_external[] = { 103,115,90,6,107,119,97,114,103,115,41,1,218,6,109,101, 116,104,111,100,114,2,0,0,0,114,4,0,0,0,218,19, 95,99,104,101,99,107,95,110,97,109,101,95,119,114,97,112, - 112,101,114,145,1,0,0,115,12,0,0,0,0,1,8,1, + 112,101,114,147,1,0,0,115,12,0,0,0,0,1,8,1, 8,1,10,1,4,1,18,1,122,40,95,99,104,101,99,107, 95,110,97,109,101,46,60,108,111,99,97,108,115,62,46,95, 99,104,101,99,107,95,110,97,109,101,95,119,114,97,112,112, @@ -539,7 +539,7 @@ const unsigned char _Py_M__importlib_external[] = { 116,116,114,218,8,95,95,100,105,99,116,95,95,218,6,117, 112,100,97,116,101,41,3,90,3,110,101,119,90,3,111,108, 100,114,53,0,0,0,114,2,0,0,0,114,2,0,0,0, - 114,4,0,0,0,218,5,95,119,114,97,112,156,1,0,0, + 114,4,0,0,0,218,5,95,119,114,97,112,158,1,0,0, 115,8,0,0,0,0,1,8,1,10,1,20,1,122,26,95, 99,104,101,99,107,95,110,97,109,101,46,60,108,111,99,97, 108,115,62,46,95,119,114,97,112,41,1,78,41,3,218,10, @@ -547,7 +547,7 @@ const unsigned char _Py_M__importlib_external[] = { 9,78,97,109,101,69,114,114,111,114,41,3,114,104,0,0, 0,114,105,0,0,0,114,115,0,0,0,114,2,0,0,0, 41,1,114,104,0,0,0,114,4,0,0,0,218,11,95,99, - 104,101,99,107,95,110,97,109,101,137,1,0,0,115,14,0, + 104,101,99,107,95,110,97,109,101,139,1,0,0,115,14,0, 0,0,0,8,14,7,2,1,10,1,14,2,14,5,10,1, 114,118,0,0,0,99,2,0,0,0,0,0,0,0,5,0, 0,0,6,0,0,0,67,0,0,0,115,60,0,0,0,124, @@ -575,7 +575,7 @@ const unsigned char _Py_M__importlib_external[] = { 101,218,6,108,111,97,100,101,114,218,8,112,111,114,116,105, 111,110,115,218,3,109,115,103,114,2,0,0,0,114,2,0, 0,0,114,4,0,0,0,218,17,95,102,105,110,100,95,109, - 111,100,117,108,101,95,115,104,105,109,165,1,0,0,115,10, + 111,100,117,108,101,95,115,104,105,109,167,1,0,0,115,10, 0,0,0,0,10,14,1,16,1,4,1,22,1,114,125,0, 0,0,99,3,0,0,0,0,0,0,0,6,0,0,0,4, 0,0,0,67,0,0,0,115,158,0,0,0,124,0,100,1, @@ -642,7 +642,7 @@ const unsigned char _Py_M__importlib_external[] = { 115,90,5,109,97,103,105,99,114,77,0,0,0,114,69,0, 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, 0,218,13,95,99,108,97,115,115,105,102,121,95,112,121,99, - 182,1,0,0,115,28,0,0,0,0,16,12,1,8,1,16, + 184,1,0,0,115,28,0,0,0,0,16,12,1,8,1,16, 1,12,1,12,1,12,1,10,1,12,1,8,1,16,2,8, 1,16,1,12,1,114,133,0,0,0,99,5,0,0,0,0, 0,0,0,6,0,0,0,4,0,0,0,67,0,0,0,115, @@ -696,7 +696,7 @@ const unsigned char _Py_M__importlib_external[] = { 101,114,100,0,0,0,114,132,0,0,0,114,77,0,0,0, 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,218, 23,95,118,97,108,105,100,97,116,101,95,116,105,109,101,115, - 116,97,109,112,95,112,121,99,215,1,0,0,115,14,0,0, + 116,97,109,112,95,112,121,99,217,1,0,0,115,14,0,0, 0,0,19,24,1,10,1,12,1,12,1,8,1,24,1,114, 137,0,0,0,99,4,0,0,0,0,0,0,0,4,0,0, 0,3,0,0,0,67,0,0,0,115,38,0,0,0,124,0, @@ -742,7 +742,7 @@ const unsigned char _Py_M__importlib_external[] = { 104,97,115,104,114,100,0,0,0,114,132,0,0,0,114,2, 0,0,0,114,2,0,0,0,114,4,0,0,0,218,18,95, 118,97,108,105,100,97,116,101,95,104,97,115,104,95,112,121, - 99,243,1,0,0,115,8,0,0,0,0,17,16,1,2,1, + 99,245,1,0,0,115,8,0,0,0,0,17,16,1,2,1, 10,1,114,139,0,0,0,99,4,0,0,0,0,0,0,0, 5,0,0,0,5,0,0,0,67,0,0,0,115,80,0,0, 0,116,0,160,1,124,0,161,1,125,4,116,2,124,4,116, @@ -765,7 +765,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,114,100,0,0,0,114,91,0,0,0,114,92,0,0, 0,218,4,99,111,100,101,114,2,0,0,0,114,2,0,0, 0,114,4,0,0,0,218,17,95,99,111,109,112,105,108,101, - 95,98,121,116,101,99,111,100,101,11,2,0,0,115,16,0, + 95,98,121,116,101,99,111,100,101,13,2,0,0,115,16,0, 0,0,0,2,10,1,10,1,12,1,8,1,12,1,4,2, 10,1,114,145,0,0,0,114,60,0,0,0,99,3,0,0, 0,0,0,0,0,4,0,0,0,5,0,0,0,67,0,0, @@ -783,7 +783,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,218,5,109,116,105,109,101,114,136,0,0,0,114,54, 0,0,0,114,2,0,0,0,114,2,0,0,0,114,4,0, 0,0,218,22,95,99,111,100,101,95,116,111,95,116,105,109, - 101,115,116,97,109,112,95,112,121,99,24,2,0,0,115,12, + 101,115,116,97,109,112,95,112,121,99,26,2,0,0,115,12, 0,0,0,0,2,8,1,14,1,14,1,14,1,16,1,114, 150,0,0,0,84,99,3,0,0,0,0,0,0,0,5,0, 0,0,5,0,0,0,67,0,0,0,115,80,0,0,0,116, @@ -802,7 +802,7 @@ const unsigned char _Py_M__importlib_external[] = { 138,0,0,0,90,7,99,104,101,99,107,101,100,114,54,0, 0,0,114,69,0,0,0,114,2,0,0,0,114,2,0,0, 0,114,4,0,0,0,218,17,95,99,111,100,101,95,116,111, - 95,104,97,115,104,95,112,121,99,34,2,0,0,115,14,0, + 95,104,97,115,104,95,112,121,99,36,2,0,0,115,14,0, 0,0,0,2,8,1,12,1,14,1,16,1,10,1,16,1, 114,152,0,0,0,99,1,0,0,0,0,0,0,0,5,0, 0,0,6,0,0,0,67,0,0,0,115,62,0,0,0,100, @@ -829,7 +829,7 @@ const unsigned char _Py_M__importlib_external[] = { 100,108,105,110,101,218,8,101,110,99,111,100,105,110,103,90, 15,110,101,119,108,105,110,101,95,100,101,99,111,100,101,114, 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,218, - 13,100,101,99,111,100,101,95,115,111,117,114,99,101,45,2, + 13,100,101,99,111,100,101,95,115,111,117,114,99,101,47,2, 0,0,115,10,0,0,0,0,5,8,1,12,1,10,1,12, 1,114,157,0,0,0,41,2,114,122,0,0,0,218,26,115, 117,98,109,111,100,117,108,101,95,115,101,97,114,99,104,95, @@ -891,7 +891,7 @@ const unsigned char _Py_M__importlib_external[] = { 161,0,0,0,90,7,100,105,114,110,97,109,101,114,2,0, 0,0,114,2,0,0,0,114,4,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,62,2,0,0,115,62,0,0,0,0,12, + 97,116,105,111,110,64,2,0,0,115,62,0,0,0,0,12, 8,4,4,1,10,2,2,1,14,1,14,1,8,2,10,8, 16,1,6,3,8,1,14,1,14,1,10,1,6,1,6,2, 4,3,8,2,10,1,2,1,14,1,14,1,6,2,4,1, @@ -928,7 +928,7 @@ const unsigned char _Py_M__importlib_external[] = { 65,76,95,77,65,67,72,73,78,69,41,2,218,3,99,108, 115,114,3,0,0,0,114,2,0,0,0,114,2,0,0,0, 114,4,0,0,0,218,14,95,111,112,101,110,95,114,101,103, - 105,115,116,114,121,142,2,0,0,115,8,0,0,0,0,2, + 105,115,116,114,121,144,2,0,0,115,8,0,0,0,0,2, 2,1,16,1,14,1,122,36,87,105,110,100,111,119,115,82, 101,103,105,115,116,114,121,70,105,110,100,101,114,46,95,111, 112,101,110,95,114,101,103,105,115,116,114,121,99,2,0,0, @@ -954,7 +954,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,0,90,4,104,107,101,121,218,8,102,105,108,101,112, 97,116,104,114,2,0,0,0,114,2,0,0,0,114,4,0, 0,0,218,16,95,115,101,97,114,99,104,95,114,101,103,105, - 115,116,114,121,149,2,0,0,115,22,0,0,0,0,2,6, + 115,116,114,121,151,2,0,0,115,22,0,0,0,0,2,6, 1,8,2,6,1,6,1,22,1,2,1,12,1,26,1,14, 1,8,1,122,38,87,105,110,100,111,119,115,82,101,103,105, 115,116,114,121,70,105,110,100,101,114,46,95,115,101,97,114, @@ -976,7 +976,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,218,6,116,97,114,103,101,116,114,178,0,0,0,114, 122,0,0,0,114,168,0,0,0,114,166,0,0,0,114,2, 0,0,0,114,2,0,0,0,114,4,0,0,0,218,9,102, - 105,110,100,95,115,112,101,99,164,2,0,0,115,26,0,0, + 105,110,100,95,115,112,101,99,166,2,0,0,115,26,0,0, 0,0,2,10,1,8,1,4,1,2,1,12,1,14,1,8, 1,14,1,14,1,6,1,8,1,8,1,122,31,87,105,110, 100,111,119,115,82,101,103,105,115,116,114,121,70,105,110,100, @@ -995,7 +995,7 @@ const unsigned char _Py_M__importlib_external[] = { 114,122,0,0,0,41,4,114,172,0,0,0,114,121,0,0, 0,114,35,0,0,0,114,166,0,0,0,114,2,0,0,0, 114,2,0,0,0,114,4,0,0,0,218,11,102,105,110,100, - 95,109,111,100,117,108,101,180,2,0,0,115,8,0,0,0, + 95,109,111,100,117,108,101,182,2,0,0,115,8,0,0,0, 0,7,12,1,8,1,6,2,122,33,87,105,110,100,111,119, 115,82,101,103,105,115,116,114,121,70,105,110,100,101,114,46, 102,105,110,100,95,109,111,100,117,108,101,41,2,78,78,41, @@ -1005,7 +1005,7 @@ const unsigned char _Py_M__importlib_external[] = { 116,104,111,100,114,173,0,0,0,114,179,0,0,0,114,182, 0,0,0,114,183,0,0,0,114,2,0,0,0,114,2,0, 0,0,114,2,0,0,0,114,4,0,0,0,114,170,0,0, - 0,130,2,0,0,115,20,0,0,0,8,2,4,3,4,3, + 0,132,2,0,0,115,20,0,0,0,8,2,4,3,4,3, 4,2,4,2,12,7,12,15,2,1,12,15,2,1,114,170, 0,0,0,99,0,0,0,0,0,0,0,0,0,0,0,0, 2,0,0,0,64,0,0,0,115,48,0,0,0,101,0,90, @@ -1040,7 +1040,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,0,90,13,102,105,108,101,110,97,109,101,95,98,97, 115,101,90,9,116,97,105,108,95,110,97,109,101,114,2,0, 0,0,114,2,0,0,0,114,4,0,0,0,114,161,0,0, - 0,199,2,0,0,115,8,0,0,0,0,3,18,1,16,1, + 0,201,2,0,0,115,8,0,0,0,0,3,18,1,16,1, 14,1,122,24,95,76,111,97,100,101,114,66,97,115,105,99, 115,46,105,115,95,112,97,99,107,97,103,101,99,2,0,0, 0,0,0,0,0,2,0,0,0,1,0,0,0,67,0,0, @@ -1050,7 +1050,7 @@ const unsigned char _Py_M__importlib_external[] = { 114,101,97,116,105,111,110,46,78,114,2,0,0,0,41,2, 114,102,0,0,0,114,166,0,0,0,114,2,0,0,0,114, 2,0,0,0,114,4,0,0,0,218,13,99,114,101,97,116, - 101,95,109,111,100,117,108,101,207,2,0,0,115,2,0,0, + 101,95,109,111,100,117,108,101,209,2,0,0,115,2,0,0, 0,0,1,122,27,95,76,111,97,100,101,114,66,97,115,105, 99,115,46,99,114,101,97,116,101,95,109,111,100,117,108,101, 99,2,0,0,0,0,0,0,0,3,0,0,0,5,0,0, @@ -1070,7 +1070,7 @@ const unsigned char _Py_M__importlib_external[] = { 99,114,113,0,0,0,41,3,114,102,0,0,0,218,6,109, 111,100,117,108,101,114,144,0,0,0,114,2,0,0,0,114, 2,0,0,0,114,4,0,0,0,218,11,101,120,101,99,95, - 109,111,100,117,108,101,210,2,0,0,115,10,0,0,0,0, + 109,111,100,117,108,101,212,2,0,0,115,10,0,0,0,0, 2,12,1,8,1,6,1,10,1,122,25,95,76,111,97,100, 101,114,66,97,115,105,99,115,46,101,120,101,99,95,109,111, 100,117,108,101,99,2,0,0,0,0,0,0,0,2,0,0, @@ -1081,14 +1081,14 @@ const unsigned char _Py_M__importlib_external[] = { 17,95,108,111,97,100,95,109,111,100,117,108,101,95,115,104, 105,109,41,2,114,102,0,0,0,114,121,0,0,0,114,2, 0,0,0,114,2,0,0,0,114,4,0,0,0,218,11,108, - 111,97,100,95,109,111,100,117,108,101,218,2,0,0,115,2, + 111,97,100,95,109,111,100,117,108,101,220,2,0,0,115,2, 0,0,0,0,2,122,25,95,76,111,97,100,101,114,66,97, 115,105,99,115,46,108,111,97,100,95,109,111,100,117,108,101, 78,41,8,114,107,0,0,0,114,106,0,0,0,114,108,0, 0,0,114,109,0,0,0,114,161,0,0,0,114,187,0,0, 0,114,192,0,0,0,114,194,0,0,0,114,2,0,0,0, 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,114, - 185,0,0,0,194,2,0,0,115,10,0,0,0,8,3,4, + 185,0,0,0,196,2,0,0,115,10,0,0,0,8,3,4, 2,8,8,8,3,8,8,114,185,0,0,0,99,0,0,0, 0,0,0,0,0,0,0,0,0,3,0,0,0,64,0,0, 0,115,74,0,0,0,101,0,90,1,100,0,90,2,100,1, @@ -1113,7 +1113,7 @@ const unsigned char _Py_M__importlib_external[] = { 32,32,32,32,32,32,32,32,78,41,1,114,40,0,0,0, 41,2,114,102,0,0,0,114,35,0,0,0,114,2,0,0, 0,114,2,0,0,0,114,4,0,0,0,218,10,112,97,116, - 104,95,109,116,105,109,101,225,2,0,0,115,2,0,0,0, + 104,95,109,116,105,109,101,227,2,0,0,115,2,0,0,0, 0,6,122,23,83,111,117,114,99,101,76,111,97,100,101,114, 46,112,97,116,104,95,109,116,105,109,101,99,2,0,0,0, 0,0,0,0,2,0,0,0,4,0,0,0,67,0,0,0, @@ -1148,7 +1148,7 @@ const unsigned char _Py_M__importlib_external[] = { 32,32,32,32,114,149,0,0,0,41,1,114,196,0,0,0, 41,2,114,102,0,0,0,114,35,0,0,0,114,2,0,0, 0,114,2,0,0,0,114,4,0,0,0,218,10,112,97,116, - 104,95,115,116,97,116,115,233,2,0,0,115,2,0,0,0, + 104,95,115,116,97,116,115,235,2,0,0,115,2,0,0,0, 0,11,122,23,83,111,117,114,99,101,76,111,97,100,101,114, 46,112,97,116,104,95,115,116,97,116,115,99,4,0,0,0, 0,0,0,0,4,0,0,0,4,0,0,0,67,0,0,0, @@ -1172,7 +1172,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,90,10,99,97,99,104,101,95,112,97,116,104,114,54,0, 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, 0,218,15,95,99,97,99,104,101,95,98,121,116,101,99,111, - 100,101,246,2,0,0,115,2,0,0,0,0,8,122,28,83, + 100,101,248,2,0,0,115,2,0,0,0,0,8,122,28,83, 111,117,114,99,101,76,111,97,100,101,114,46,95,99,97,99, 104,101,95,98,121,116,101,99,111,100,101,99,3,0,0,0, 0,0,0,0,3,0,0,0,1,0,0,0,67,0,0,0, @@ -1188,7 +1188,7 @@ const unsigned char _Py_M__importlib_external[] = { 111,100,101,32,102,105,108,101,115,46,10,32,32,32,32,32, 32,32,32,78,114,2,0,0,0,41,3,114,102,0,0,0, 114,35,0,0,0,114,54,0,0,0,114,2,0,0,0,114, - 2,0,0,0,114,4,0,0,0,114,198,0,0,0,0,3, + 2,0,0,0,114,4,0,0,0,114,198,0,0,0,2,3, 0,0,115,2,0,0,0,0,4,122,21,83,111,117,114,99, 101,76,111,97,100,101,114,46,115,101,116,95,100,97,116,97, 99,2,0,0,0,0,0,0,0,5,0,0,0,10,0,0, @@ -1209,7 +1209,7 @@ const unsigned char _Py_M__importlib_external[] = { 114,157,0,0,0,41,5,114,102,0,0,0,114,121,0,0, 0,114,35,0,0,0,114,155,0,0,0,218,3,101,120,99, 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,218, - 10,103,101,116,95,115,111,117,114,99,101,7,3,0,0,115, + 10,103,101,116,95,115,111,117,114,99,101,9,3,0,0,115, 14,0,0,0,0,2,10,1,2,1,14,1,16,1,4,1, 28,1,122,23,83,111,117,114,99,101,76,111,97,100,101,114, 46,103,101,116,95,115,111,117,114,99,101,114,89,0,0,0, @@ -1231,7 +1231,7 @@ const unsigned char _Py_M__importlib_external[] = { 105,108,101,41,4,114,102,0,0,0,114,54,0,0,0,114, 35,0,0,0,114,203,0,0,0,114,2,0,0,0,114,2, 0,0,0,114,4,0,0,0,218,14,115,111,117,114,99,101, - 95,116,111,95,99,111,100,101,17,3,0,0,115,4,0,0, + 95,116,111,95,99,111,100,101,19,3,0,0,115,4,0,0, 0,0,5,12,1,122,27,83,111,117,114,99,101,76,111,97, 100,101,114,46,115,111,117,114,99,101,95,116,111,95,99,111, 100,101,99,2,0,0,0,0,0,0,0,15,0,0,0,9, @@ -1310,7 +1310,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,114,132,0,0,0,114,69,0,0,0,90,10,98,121, 116,101,115,95,100,97,116,97,90,11,99,111,100,101,95,111, 98,106,101,99,116,114,2,0,0,0,114,2,0,0,0,114, - 4,0,0,0,114,188,0,0,0,25,3,0,0,115,134,0, + 4,0,0,0,114,188,0,0,0,27,3,0,0,115,134,0, 0,0,0,7,10,1,4,1,4,1,4,1,4,1,4,1, 2,1,12,1,14,1,12,2,2,1,14,1,14,1,8,2, 12,1,2,1,14,1,14,1,6,3,2,1,8,2,2,1, @@ -1325,7 +1325,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,114,196,0,0,0,114,197,0,0,0,114,199,0,0,0, 114,198,0,0,0,114,202,0,0,0,114,206,0,0,0,114, 188,0,0,0,114,2,0,0,0,114,2,0,0,0,114,2, - 0,0,0,114,4,0,0,0,114,195,0,0,0,223,2,0, + 0,0,0,114,4,0,0,0,114,195,0,0,0,225,2,0, 0,115,14,0,0,0,8,2,8,8,8,13,8,10,8,7, 8,10,14,8,114,195,0,0,0,99,0,0,0,0,0,0, 0,0,0,0,0,0,4,0,0,0,0,0,0,0,115,124, @@ -1355,7 +1355,7 @@ const unsigned char _Py_M__importlib_external[] = { 41,2,114,100,0,0,0,114,35,0,0,0,41,3,114,102, 0,0,0,114,121,0,0,0,114,35,0,0,0,114,2,0, 0,0,114,2,0,0,0,114,4,0,0,0,114,186,0,0, - 0,116,3,0,0,115,4,0,0,0,0,3,6,1,122,19, + 0,118,3,0,0,115,4,0,0,0,0,3,6,1,122,19, 70,105,108,101,76,111,97,100,101,114,46,95,95,105,110,105, 116,95,95,99,2,0,0,0,0,0,0,0,2,0,0,0, 2,0,0,0,67,0,0,0,115,24,0,0,0,124,0,106, @@ -1363,7 +1363,7 @@ const unsigned char _Py_M__importlib_external[] = { 1,107,2,83,0,41,1,78,41,2,218,9,95,95,99,108, 97,115,115,95,95,114,113,0,0,0,41,2,114,102,0,0, 0,218,5,111,116,104,101,114,114,2,0,0,0,114,2,0, - 0,0,114,4,0,0,0,218,6,95,95,101,113,95,95,122, + 0,0,114,4,0,0,0,218,6,95,95,101,113,95,95,124, 3,0,0,115,4,0,0,0,0,1,12,1,122,17,70,105, 108,101,76,111,97,100,101,114,46,95,95,101,113,95,95,99, 1,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0, @@ -1372,7 +1372,7 @@ const unsigned char _Py_M__importlib_external[] = { 41,3,218,4,104,97,115,104,114,100,0,0,0,114,35,0, 0,0,41,1,114,102,0,0,0,114,2,0,0,0,114,2, 0,0,0,114,4,0,0,0,218,8,95,95,104,97,115,104, - 95,95,126,3,0,0,115,2,0,0,0,0,1,122,19,70, + 95,95,128,3,0,0,115,2,0,0,0,0,1,122,19,70, 105,108,101,76,111,97,100,101,114,46,95,95,104,97,115,104, 95,95,99,2,0,0,0,0,0,0,0,2,0,0,0,3, 0,0,0,3,0,0,0,115,16,0,0,0,116,0,116,1, @@ -1386,7 +1386,7 @@ const unsigned char _Py_M__importlib_external[] = { 32,32,32,32,41,3,218,5,115,117,112,101,114,114,212,0, 0,0,114,194,0,0,0,41,2,114,102,0,0,0,114,121, 0,0,0,41,1,114,213,0,0,0,114,2,0,0,0,114, - 4,0,0,0,114,194,0,0,0,129,3,0,0,115,2,0, + 4,0,0,0,114,194,0,0,0,131,3,0,0,115,2,0, 0,0,0,10,122,22,70,105,108,101,76,111,97,100,101,114, 46,108,111,97,100,95,109,111,100,117,108,101,99,2,0,0, 0,0,0,0,0,2,0,0,0,1,0,0,0,67,0,0, @@ -1397,7 +1397,7 @@ const unsigned char _Py_M__importlib_external[] = { 104,101,32,102,105,110,100,101,114,46,41,1,114,35,0,0, 0,41,2,114,102,0,0,0,114,121,0,0,0,114,2,0, 0,0,114,2,0,0,0,114,4,0,0,0,114,159,0,0, - 0,141,3,0,0,115,2,0,0,0,0,3,122,23,70,105, + 0,143,3,0,0,115,2,0,0,0,0,3,122,23,70,105, 108,101,76,111,97,100,101,114,46,103,101,116,95,102,105,108, 101,110,97,109,101,99,2,0,0,0,0,0,0,0,3,0, 0,0,10,0,0,0,67,0,0,0,115,44,0,0,0,116, @@ -1410,7 +1410,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,114,51,0,0,0,90,4,114,101,97,100,41,3,114,102, 0,0,0,114,35,0,0,0,114,55,0,0,0,114,2,0, 0,0,114,2,0,0,0,114,4,0,0,0,114,200,0,0, - 0,146,3,0,0,115,4,0,0,0,0,2,14,1,122,19, + 0,148,3,0,0,115,4,0,0,0,0,2,14,1,122,19, 70,105,108,101,76,111,97,100,101,114,46,103,101,116,95,100, 97,116,97,99,2,0,0,0,0,0,0,0,2,0,0,0, 3,0,0,0,67,0,0,0,115,18,0,0,0,124,0,160, @@ -1418,7 +1418,7 @@ const unsigned char _Py_M__importlib_external[] = { 1,78,41,1,114,161,0,0,0,41,2,114,102,0,0,0, 114,191,0,0,0,114,2,0,0,0,114,2,0,0,0,114, 4,0,0,0,218,19,103,101,116,95,114,101,115,111,117,114, - 99,101,95,114,101,97,100,101,114,153,3,0,0,115,6,0, + 99,101,95,114,101,97,100,101,114,155,3,0,0,115,6,0, 0,0,0,2,10,1,4,1,122,30,70,105,108,101,76,111, 97,100,101,114,46,103,101,116,95,114,101,115,111,117,114,99, 101,95,114,101,97,100,101,114,99,2,0,0,0,0,0,0, @@ -1430,7 +1430,7 @@ const unsigned char _Py_M__importlib_external[] = { 114,50,0,0,0,114,51,0,0,0,41,3,114,102,0,0, 0,218,8,114,101,115,111,117,114,99,101,114,35,0,0,0, 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,218, - 13,111,112,101,110,95,114,101,115,111,117,114,99,101,159,3, + 13,111,112,101,110,95,114,101,115,111,117,114,99,101,161,3, 0,0,115,4,0,0,0,0,1,20,1,122,24,70,105,108, 101,76,111,97,100,101,114,46,111,112,101,110,95,114,101,115, 111,117,114,99,101,99,2,0,0,0,0,0,0,0,3,0, @@ -1443,7 +1443,7 @@ const unsigned char _Py_M__importlib_external[] = { 28,0,0,0,114,38,0,0,0,114,35,0,0,0,41,3, 114,102,0,0,0,114,221,0,0,0,114,35,0,0,0,114, 2,0,0,0,114,2,0,0,0,114,4,0,0,0,218,13, - 114,101,115,111,117,114,99,101,95,112,97,116,104,163,3,0, + 114,101,115,111,117,114,99,101,95,112,97,116,104,165,3,0, 0,115,8,0,0,0,0,1,10,1,4,1,20,1,122,24, 70,105,108,101,76,111,97,100,101,114,46,114,101,115,111,117, 114,99,101,95,112,97,116,104,99,2,0,0,0,0,0,0, @@ -1455,7 +1455,7 @@ const unsigned char _Py_M__importlib_external[] = { 38,0,0,0,114,35,0,0,0,114,44,0,0,0,41,3, 114,102,0,0,0,114,100,0,0,0,114,35,0,0,0,114, 2,0,0,0,114,2,0,0,0,114,4,0,0,0,114,223, - 0,0,0,169,3,0,0,115,8,0,0,0,0,1,8,1, + 0,0,0,171,3,0,0,115,8,0,0,0,0,1,8,1, 4,1,20,1,122,22,70,105,108,101,76,111,97,100,101,114, 46,105,115,95,114,101,115,111,117,114,99,101,99,1,0,0, 0,0,0,0,0,1,0,0,0,5,0,0,0,67,0,0, @@ -1465,7 +1465,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,0,218,7,108,105,115,116,100,105,114,114,38,0,0, 0,114,35,0,0,0,41,1,114,102,0,0,0,114,2,0, 0,0,114,2,0,0,0,114,4,0,0,0,218,8,99,111, - 110,116,101,110,116,115,175,3,0,0,115,2,0,0,0,0, + 110,116,101,110,116,115,177,3,0,0,115,2,0,0,0,0, 1,122,19,70,105,108,101,76,111,97,100,101,114,46,99,111, 110,116,101,110,116,115,41,17,114,107,0,0,0,114,106,0, 0,0,114,108,0,0,0,114,109,0,0,0,114,186,0,0, @@ -1475,7 +1475,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,0,114,228,0,0,0,90,13,95,95,99,108,97,115, 115,99,101,108,108,95,95,114,2,0,0,0,114,2,0,0, 0,41,1,114,213,0,0,0,114,4,0,0,0,114,212,0, - 0,0,111,3,0,0,115,24,0,0,0,8,3,4,2,8, + 0,0,113,3,0,0,115,24,0,0,0,8,3,4,2,8, 6,8,4,8,3,16,12,12,5,8,7,12,6,8,4,8, 6,8,6,114,212,0,0,0,99,0,0,0,0,0,0,0, 0,0,0,0,0,3,0,0,0,64,0,0,0,115,46,0, @@ -1497,7 +1497,7 @@ const unsigned char _Py_M__importlib_external[] = { 95,109,116,105,109,101,90,7,115,116,95,115,105,122,101,41, 3,114,102,0,0,0,114,35,0,0,0,114,211,0,0,0, 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,114, - 197,0,0,0,183,3,0,0,115,4,0,0,0,0,2,8, + 197,0,0,0,185,3,0,0,115,4,0,0,0,0,2,8, 1,122,27,83,111,117,114,99,101,70,105,108,101,76,111,97, 100,101,114,46,112,97,116,104,95,115,116,97,116,115,99,4, 0,0,0,0,0,0,0,5,0,0,0,5,0,0,0,67, @@ -1507,7 +1507,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,0,114,198,0,0,0,41,5,114,102,0,0,0,114, 92,0,0,0,114,91,0,0,0,114,54,0,0,0,114,42, 0,0,0,114,2,0,0,0,114,2,0,0,0,114,4,0, - 0,0,114,199,0,0,0,188,3,0,0,115,4,0,0,0, + 0,0,114,199,0,0,0,190,3,0,0,115,4,0,0,0, 0,2,8,1,122,32,83,111,117,114,99,101,70,105,108,101, 76,111,97,100,101,114,46,95,99,97,99,104,101,95,98,121, 116,101,99,111,100,101,105,182,1,0,0,41,1,114,231,0, @@ -1542,7 +1542,7 @@ const unsigned char _Py_M__importlib_external[] = { 114,231,0,0,0,218,6,112,97,114,101,110,116,114,96,0, 0,0,114,27,0,0,0,114,23,0,0,0,114,201,0,0, 0,114,2,0,0,0,114,2,0,0,0,114,4,0,0,0, - 114,198,0,0,0,193,3,0,0,115,42,0,0,0,0,2, + 114,198,0,0,0,195,3,0,0,115,42,0,0,0,0,2, 12,1,4,2,12,1,12,1,12,2,12,1,10,1,2,1, 14,1,14,2,8,1,16,3,6,1,8,1,28,1,2,1, 12,1,16,1,16,2,8,1,122,25,83,111,117,114,99,101, @@ -1551,7 +1551,7 @@ const unsigned char _Py_M__importlib_external[] = { 114,108,0,0,0,114,109,0,0,0,114,197,0,0,0,114, 199,0,0,0,114,198,0,0,0,114,2,0,0,0,114,2, 0,0,0,114,2,0,0,0,114,4,0,0,0,114,229,0, - 0,0,179,3,0,0,115,8,0,0,0,8,2,4,2,8, + 0,0,181,3,0,0,115,8,0,0,0,8,2,4,2,8, 5,8,5,114,229,0,0,0,99,0,0,0,0,0,0,0, 0,0,0,0,0,2,0,0,0,64,0,0,0,115,32,0, 0,0,101,0,90,1,100,0,90,2,100,1,90,3,100,2, @@ -1573,7 +1573,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,41,5,114,102,0,0,0,114,121,0,0,0,114,35, 0,0,0,114,54,0,0,0,114,132,0,0,0,114,2,0, 0,0,114,2,0,0,0,114,4,0,0,0,114,188,0,0, - 0,228,3,0,0,115,18,0,0,0,0,1,10,1,10,4, + 0,230,3,0,0,115,18,0,0,0,0,1,10,1,10,4, 2,1,8,2,12,1,2,1,14,1,2,1,122,29,83,111, 117,114,99,101,108,101,115,115,70,105,108,101,76,111,97,100, 101,114,46,103,101,116,95,99,111,100,101,99,2,0,0,0, @@ -1583,14 +1583,14 @@ const unsigned char _Py_M__importlib_external[] = { 101,32,105,115,32,110,111,32,115,111,117,114,99,101,32,99, 111,100,101,46,78,114,2,0,0,0,41,2,114,102,0,0, 0,114,121,0,0,0,114,2,0,0,0,114,2,0,0,0, - 114,4,0,0,0,114,202,0,0,0,244,3,0,0,115,2, + 114,4,0,0,0,114,202,0,0,0,246,3,0,0,115,2, 0,0,0,0,2,122,31,83,111,117,114,99,101,108,101,115, 115,70,105,108,101,76,111,97,100,101,114,46,103,101,116,95, 115,111,117,114,99,101,78,41,6,114,107,0,0,0,114,106, 0,0,0,114,108,0,0,0,114,109,0,0,0,114,188,0, 0,0,114,202,0,0,0,114,2,0,0,0,114,2,0,0, 0,114,2,0,0,0,114,4,0,0,0,114,234,0,0,0, - 224,3,0,0,115,6,0,0,0,8,2,4,2,8,16,114, + 226,3,0,0,115,6,0,0,0,8,2,4,2,8,16,114, 234,0,0,0,99,0,0,0,0,0,0,0,0,0,0,0, 0,3,0,0,0,64,0,0,0,115,92,0,0,0,101,0, 90,1,100,0,90,2,100,1,90,3,100,2,100,3,132,0, @@ -1611,7 +1611,7 @@ const unsigned char _Py_M__importlib_external[] = { 124,2,124,0,95,1,100,0,83,0,41,1,78,41,2,114, 100,0,0,0,114,35,0,0,0,41,3,114,102,0,0,0, 114,100,0,0,0,114,35,0,0,0,114,2,0,0,0,114, - 2,0,0,0,114,4,0,0,0,114,186,0,0,0,5,4, + 2,0,0,0,114,4,0,0,0,114,186,0,0,0,7,4, 0,0,115,4,0,0,0,0,1,6,1,122,28,69,120,116, 101,110,115,105,111,110,70,105,108,101,76,111,97,100,101,114, 46,95,95,105,110,105,116,95,95,99,2,0,0,0,0,0, @@ -1620,7 +1620,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,106,1,124,1,106,1,107,2,83,0,41,1,78,41,2, 114,213,0,0,0,114,113,0,0,0,41,2,114,102,0,0, 0,114,214,0,0,0,114,2,0,0,0,114,2,0,0,0, - 114,4,0,0,0,114,215,0,0,0,9,4,0,0,115,4, + 114,4,0,0,0,114,215,0,0,0,11,4,0,0,115,4, 0,0,0,0,1,12,1,122,26,69,120,116,101,110,115,105, 111,110,70,105,108,101,76,111,97,100,101,114,46,95,95,101, 113,95,95,99,1,0,0,0,0,0,0,0,1,0,0,0, @@ -1629,7 +1629,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,41,1,78,41,3,114,216,0,0,0,114,100,0,0,0, 114,35,0,0,0,41,1,114,102,0,0,0,114,2,0,0, 0,114,2,0,0,0,114,4,0,0,0,114,217,0,0,0, - 13,4,0,0,115,2,0,0,0,0,1,122,28,69,120,116, + 15,4,0,0,115,2,0,0,0,0,1,122,28,69,120,116, 101,110,115,105,111,110,70,105,108,101,76,111,97,100,101,114, 46,95,95,104,97,115,104,95,95,99,2,0,0,0,0,0, 0,0,3,0,0,0,5,0,0,0,67,0,0,0,115,36, @@ -1645,7 +1645,7 @@ const unsigned char _Py_M__importlib_external[] = { 116,101,95,100,121,110,97,109,105,99,114,130,0,0,0,114, 100,0,0,0,114,35,0,0,0,41,3,114,102,0,0,0, 114,166,0,0,0,114,191,0,0,0,114,2,0,0,0,114, - 2,0,0,0,114,4,0,0,0,114,187,0,0,0,16,4, + 2,0,0,0,114,4,0,0,0,114,187,0,0,0,18,4, 0,0,115,10,0,0,0,0,2,4,1,10,1,6,1,12, 1,122,33,69,120,116,101,110,115,105,111,110,70,105,108,101, 76,111,97,100,101,114,46,99,114,101,97,116,101,95,109,111, @@ -1662,7 +1662,7 @@ const unsigned char _Py_M__importlib_external[] = { 90,12,101,120,101,99,95,100,121,110,97,109,105,99,114,130, 0,0,0,114,100,0,0,0,114,35,0,0,0,41,2,114, 102,0,0,0,114,191,0,0,0,114,2,0,0,0,114,2, - 0,0,0,114,4,0,0,0,114,192,0,0,0,24,4,0, + 0,0,0,114,4,0,0,0,114,192,0,0,0,26,4,0, 0,115,6,0,0,0,0,2,14,1,6,1,122,31,69,120, 116,101,110,115,105,111,110,70,105,108,101,76,111,97,100,101, 114,46,101,120,101,99,95,109,111,100,117,108,101,99,2,0, @@ -1680,7 +1680,7 @@ const unsigned char _Py_M__importlib_external[] = { 78,114,2,0,0,0,41,2,114,22,0,0,0,218,6,115, 117,102,102,105,120,41,1,218,9,102,105,108,101,95,110,97, 109,101,114,2,0,0,0,114,4,0,0,0,218,9,60,103, - 101,110,101,120,112,114,62,33,4,0,0,115,2,0,0,0, + 101,110,101,120,112,114,62,35,4,0,0,115,2,0,0,0, 4,1,122,49,69,120,116,101,110,115,105,111,110,70,105,108, 101,76,111,97,100,101,114,46,105,115,95,112,97,99,107,97, 103,101,46,60,108,111,99,97,108,115,62,46,60,103,101,110, @@ -1688,7 +1688,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,218,3,97,110,121,218,18,69,88,84,69,78,83,73,79, 78,95,83,85,70,70,73,88,69,83,41,2,114,102,0,0, 0,114,121,0,0,0,114,2,0,0,0,41,1,114,237,0, - 0,0,114,4,0,0,0,114,161,0,0,0,30,4,0,0, + 0,0,114,4,0,0,0,114,161,0,0,0,32,4,0,0, 115,6,0,0,0,0,2,14,1,12,1,122,30,69,120,116, 101,110,115,105,111,110,70,105,108,101,76,111,97,100,101,114, 46,105,115,95,112,97,99,107,97,103,101,99,2,0,0,0, @@ -1700,7 +1700,7 @@ const unsigned char _Py_M__importlib_external[] = { 99,111,100,101,32,111,98,106,101,99,116,46,78,114,2,0, 0,0,41,2,114,102,0,0,0,114,121,0,0,0,114,2, 0,0,0,114,2,0,0,0,114,4,0,0,0,114,188,0, - 0,0,36,4,0,0,115,2,0,0,0,0,2,122,28,69, + 0,0,38,4,0,0,115,2,0,0,0,0,2,122,28,69, 120,116,101,110,115,105,111,110,70,105,108,101,76,111,97,100, 101,114,46,103,101,116,95,99,111,100,101,99,2,0,0,0, 0,0,0,0,2,0,0,0,1,0,0,0,67,0,0,0, @@ -1710,7 +1710,7 @@ const unsigned char _Py_M__importlib_external[] = { 118,101,32,110,111,32,115,111,117,114,99,101,32,99,111,100, 101,46,78,114,2,0,0,0,41,2,114,102,0,0,0,114, 121,0,0,0,114,2,0,0,0,114,2,0,0,0,114,4, - 0,0,0,114,202,0,0,0,40,4,0,0,115,2,0,0, + 0,0,0,114,202,0,0,0,42,4,0,0,115,2,0,0, 0,0,2,122,30,69,120,116,101,110,115,105,111,110,70,105, 108,101,76,111,97,100,101,114,46,103,101,116,95,115,111,117, 114,99,101,99,2,0,0,0,0,0,0,0,2,0,0,0, @@ -1721,7 +1721,7 @@ const unsigned char _Py_M__importlib_external[] = { 110,100,32,98,121,32,116,104,101,32,102,105,110,100,101,114, 46,41,1,114,35,0,0,0,41,2,114,102,0,0,0,114, 121,0,0,0,114,2,0,0,0,114,2,0,0,0,114,4, - 0,0,0,114,159,0,0,0,44,4,0,0,115,2,0,0, + 0,0,0,114,159,0,0,0,46,4,0,0,115,2,0,0, 0,0,3,122,32,69,120,116,101,110,115,105,111,110,70,105, 108,101,76,111,97,100,101,114,46,103,101,116,95,102,105,108, 101,110,97,109,101,78,41,14,114,107,0,0,0,114,106,0, @@ -1730,7 +1730,7 @@ const unsigned char _Py_M__importlib_external[] = { 114,192,0,0,0,114,161,0,0,0,114,188,0,0,0,114, 202,0,0,0,114,118,0,0,0,114,159,0,0,0,114,2, 0,0,0,114,2,0,0,0,114,2,0,0,0,114,4,0, - 0,0,114,235,0,0,0,253,3,0,0,115,20,0,0,0, + 0,0,114,235,0,0,0,255,3,0,0,115,20,0,0,0, 8,6,4,2,8,4,8,4,8,3,8,8,8,6,8,6, 8,4,8,4,114,235,0,0,0,99,0,0,0,0,0,0, 0,0,0,0,0,0,2,0,0,0,64,0,0,0,115,96, @@ -1771,7 +1771,7 @@ const unsigned char _Py_M__importlib_external[] = { 116,104,95,102,105,110,100,101,114,41,4,114,102,0,0,0, 114,100,0,0,0,114,35,0,0,0,218,11,112,97,116,104, 95,102,105,110,100,101,114,114,2,0,0,0,114,2,0,0, - 0,114,4,0,0,0,114,186,0,0,0,57,4,0,0,115, + 0,114,4,0,0,0,114,186,0,0,0,59,4,0,0,115, 8,0,0,0,0,1,6,1,6,1,14,1,122,23,95,78, 97,109,101,115,112,97,99,101,80,97,116,104,46,95,95,105, 110,105,116,95,95,99,1,0,0,0,0,0,0,0,4,0, @@ -1789,7 +1789,7 @@ const unsigned char _Py_M__importlib_external[] = { 3,100,111,116,90,2,109,101,114,2,0,0,0,114,2,0, 0,0,114,4,0,0,0,218,23,95,102,105,110,100,95,112, 97,114,101,110,116,95,112,97,116,104,95,110,97,109,101,115, - 63,4,0,0,115,8,0,0,0,0,2,18,1,8,2,4, + 65,4,0,0,115,8,0,0,0,0,2,18,1,8,2,4, 3,122,38,95,78,97,109,101,115,112,97,99,101,80,97,116, 104,46,95,102,105,110,100,95,112,97,114,101,110,116,95,112, 97,116,104,95,110,97,109,101,115,99,1,0,0,0,0,0, @@ -1801,7 +1801,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,0,90,18,112,97,114,101,110,116,95,109,111,100,117, 108,101,95,110,97,109,101,90,14,112,97,116,104,95,97,116, 116,114,95,110,97,109,101,114,2,0,0,0,114,2,0,0, - 0,114,4,0,0,0,114,244,0,0,0,73,4,0,0,115, + 0,114,4,0,0,0,114,244,0,0,0,75,4,0,0,115, 4,0,0,0,0,1,12,1,122,31,95,78,97,109,101,115, 112,97,99,101,80,97,116,104,46,95,103,101,116,95,112,97, 114,101,110,116,95,112,97,116,104,99,1,0,0,0,0,0, @@ -1817,7 +1817,7 @@ const unsigned char _Py_M__importlib_external[] = { 41,3,114,102,0,0,0,90,11,112,97,114,101,110,116,95, 112,97,116,104,114,166,0,0,0,114,2,0,0,0,114,2, 0,0,0,114,4,0,0,0,218,12,95,114,101,99,97,108, - 99,117,108,97,116,101,77,4,0,0,115,16,0,0,0,0, + 99,117,108,97,116,101,79,4,0,0,115,16,0,0,0,0, 2,12,1,10,1,14,3,18,1,6,1,8,1,6,1,122, 27,95,78,97,109,101,115,112,97,99,101,80,97,116,104,46, 95,114,101,99,97,108,99,117,108,97,116,101,99,1,0,0, @@ -1826,7 +1826,7 @@ const unsigned char _Py_M__importlib_external[] = { 83,0,41,1,78,41,2,114,226,0,0,0,114,251,0,0, 0,41,1,114,102,0,0,0,114,2,0,0,0,114,2,0, 0,0,114,4,0,0,0,218,8,95,95,105,116,101,114,95, - 95,90,4,0,0,115,2,0,0,0,0,1,122,23,95,78, + 95,92,4,0,0,115,2,0,0,0,0,1,122,23,95,78, 97,109,101,115,112,97,99,101,80,97,116,104,46,95,95,105, 116,101,114,95,95,99,3,0,0,0,0,0,0,0,3,0, 0,0,3,0,0,0,67,0,0,0,115,14,0,0,0,124, @@ -1834,7 +1834,7 @@ const unsigned char _Py_M__importlib_external[] = { 41,1,114,243,0,0,0,41,3,114,102,0,0,0,218,5, 105,110,100,101,120,114,35,0,0,0,114,2,0,0,0,114, 2,0,0,0,114,4,0,0,0,218,11,95,95,115,101,116, - 105,116,101,109,95,95,93,4,0,0,115,2,0,0,0,0, + 105,116,101,109,95,95,95,4,0,0,115,2,0,0,0,0, 1,122,26,95,78,97,109,101,115,112,97,99,101,80,97,116, 104,46,95,95,115,101,116,105,116,101,109,95,95,99,1,0, 0,0,0,0,0,0,1,0,0,0,3,0,0,0,67,0, @@ -1842,7 +1842,7 @@ const unsigned char _Py_M__importlib_external[] = { 1,83,0,41,1,78,41,2,114,31,0,0,0,114,251,0, 0,0,41,1,114,102,0,0,0,114,2,0,0,0,114,2, 0,0,0,114,4,0,0,0,218,7,95,95,108,101,110,95, - 95,96,4,0,0,115,2,0,0,0,0,1,122,22,95,78, + 95,98,4,0,0,115,2,0,0,0,0,1,122,22,95,78, 97,109,101,115,112,97,99,101,80,97,116,104,46,95,95,108, 101,110,95,95,99,1,0,0,0,0,0,0,0,1,0,0, 0,3,0,0,0,67,0,0,0,115,12,0,0,0,100,1, @@ -1850,7 +1850,7 @@ const unsigned char _Py_M__importlib_external[] = { 78,97,109,101,115,112,97,99,101,80,97,116,104,40,123,33, 114,125,41,41,2,114,48,0,0,0,114,243,0,0,0,41, 1,114,102,0,0,0,114,2,0,0,0,114,2,0,0,0, - 114,4,0,0,0,218,8,95,95,114,101,112,114,95,95,99, + 114,4,0,0,0,218,8,95,95,114,101,112,114,95,95,101, 4,0,0,115,2,0,0,0,0,1,122,23,95,78,97,109, 101,115,112,97,99,101,80,97,116,104,46,95,95,114,101,112, 114,95,95,99,2,0,0,0,0,0,0,0,2,0,0,0, @@ -1858,7 +1858,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,160,0,161,0,107,6,83,0,41,1,78,41,1,114,251, 0,0,0,41,2,114,102,0,0,0,218,4,105,116,101,109, 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,218, - 12,95,95,99,111,110,116,97,105,110,115,95,95,102,4,0, + 12,95,95,99,111,110,116,97,105,110,115,95,95,104,4,0, 0,115,2,0,0,0,0,1,122,27,95,78,97,109,101,115, 112,97,99,101,80,97,116,104,46,95,95,99,111,110,116,97, 105,110,115,95,95,99,2,0,0,0,0,0,0,0,2,0, @@ -1866,7 +1866,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,106,0,160,1,124,1,161,1,1,0,100,0,83,0,41, 1,78,41,2,114,243,0,0,0,114,165,0,0,0,41,2, 114,102,0,0,0,114,1,1,0,0,114,2,0,0,0,114, - 2,0,0,0,114,4,0,0,0,114,165,0,0,0,105,4, + 2,0,0,0,114,4,0,0,0,114,165,0,0,0,107,4, 0,0,115,2,0,0,0,0,1,122,21,95,78,97,109,101, 115,112,97,99,101,80,97,116,104,46,97,112,112,101,110,100, 78,41,14,114,107,0,0,0,114,106,0,0,0,114,108,0, @@ -1875,7 +1875,7 @@ const unsigned char _Py_M__importlib_external[] = { 114,254,0,0,0,114,255,0,0,0,114,0,1,0,0,114, 2,1,0,0,114,165,0,0,0,114,2,0,0,0,114,2, 0,0,0,114,2,0,0,0,114,4,0,0,0,114,241,0, - 0,0,50,4,0,0,115,22,0,0,0,8,5,4,2,8, + 0,0,52,4,0,0,115,22,0,0,0,8,5,4,2,8, 6,8,10,8,4,8,13,8,3,8,3,8,3,8,3,8, 3,114,241,0,0,0,99,0,0,0,0,0,0,0,0,0, 0,0,0,3,0,0,0,64,0,0,0,115,80,0,0,0, @@ -1891,7 +1891,7 @@ const unsigned char _Py_M__importlib_external[] = { 41,1,78,41,2,114,241,0,0,0,114,243,0,0,0,41, 4,114,102,0,0,0,114,100,0,0,0,114,35,0,0,0, 114,247,0,0,0,114,2,0,0,0,114,2,0,0,0,114, - 4,0,0,0,114,186,0,0,0,111,4,0,0,115,2,0, + 4,0,0,0,114,186,0,0,0,113,4,0,0,115,2,0, 0,0,0,1,122,25,95,78,97,109,101,115,112,97,99,101, 76,111,97,100,101,114,46,95,95,105,110,105,116,95,95,99, 2,0,0,0,0,0,0,0,2,0,0,0,3,0,0,0, @@ -1908,21 +1908,21 @@ const unsigned char _Py_M__importlib_external[] = { 115,112,97,99,101,41,62,41,2,114,48,0,0,0,114,107, 0,0,0,41,2,114,172,0,0,0,114,191,0,0,0,114, 2,0,0,0,114,2,0,0,0,114,4,0,0,0,218,11, - 109,111,100,117,108,101,95,114,101,112,114,114,4,0,0,115, + 109,111,100,117,108,101,95,114,101,112,114,116,4,0,0,115, 2,0,0,0,0,7,122,28,95,78,97,109,101,115,112,97, 99,101,76,111,97,100,101,114,46,109,111,100,117,108,101,95, 114,101,112,114,99,2,0,0,0,0,0,0,0,2,0,0, 0,1,0,0,0,67,0,0,0,115,4,0,0,0,100,1, 83,0,41,2,78,84,114,2,0,0,0,41,2,114,102,0, 0,0,114,121,0,0,0,114,2,0,0,0,114,2,0,0, - 0,114,4,0,0,0,114,161,0,0,0,123,4,0,0,115, + 0,114,4,0,0,0,114,161,0,0,0,125,4,0,0,115, 2,0,0,0,0,1,122,27,95,78,97,109,101,115,112,97, 99,101,76,111,97,100,101,114,46,105,115,95,112,97,99,107, 97,103,101,99,2,0,0,0,0,0,0,0,2,0,0,0, 1,0,0,0,67,0,0,0,115,4,0,0,0,100,1,83, 0,41,2,78,114,30,0,0,0,114,2,0,0,0,41,2, 114,102,0,0,0,114,121,0,0,0,114,2,0,0,0,114, - 2,0,0,0,114,4,0,0,0,114,202,0,0,0,126,4, + 2,0,0,0,114,4,0,0,0,114,202,0,0,0,128,4, 0,0,115,2,0,0,0,0,1,122,27,95,78,97,109,101, 115,112,97,99,101,76,111,97,100,101,114,46,103,101,116,95, 115,111,117,114,99,101,99,2,0,0,0,0,0,0,0,2, @@ -1932,7 +1932,7 @@ const unsigned char _Py_M__importlib_external[] = { 103,62,114,190,0,0,0,84,41,1,114,204,0,0,0,41, 1,114,205,0,0,0,41,2,114,102,0,0,0,114,121,0, 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, - 0,114,188,0,0,0,129,4,0,0,115,2,0,0,0,0, + 0,114,188,0,0,0,131,4,0,0,115,2,0,0,0,0, 1,122,25,95,78,97,109,101,115,112,97,99,101,76,111,97, 100,101,114,46,103,101,116,95,99,111,100,101,99,2,0,0, 0,0,0,0,0,2,0,0,0,1,0,0,0,67,0,0, @@ -1941,14 +1941,14 @@ const unsigned char _Py_M__importlib_external[] = { 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,2,0,0,0,41,2, 114,102,0,0,0,114,166,0,0,0,114,2,0,0,0,114, - 2,0,0,0,114,4,0,0,0,114,187,0,0,0,132,4, + 2,0,0,0,114,4,0,0,0,114,187,0,0,0,134,4, 0,0,115,2,0,0,0,0,1,122,30,95,78,97,109,101, 115,112,97,99,101,76,111,97,100,101,114,46,99,114,101,97, 116,101,95,109,111,100,117,108,101,99,2,0,0,0,0,0, 0,0,2,0,0,0,1,0,0,0,67,0,0,0,115,4, 0,0,0,100,0,83,0,41,1,78,114,2,0,0,0,41, 2,114,102,0,0,0,114,191,0,0,0,114,2,0,0,0, - 114,2,0,0,0,114,4,0,0,0,114,192,0,0,0,135, + 114,2,0,0,0,114,4,0,0,0,114,192,0,0,0,137, 4,0,0,115,2,0,0,0,0,1,122,28,95,78,97,109, 101,115,112,97,99,101,76,111,97,100,101,114,46,101,120,101, 99,95,109,111,100,117,108,101,99,2,0,0,0,0,0,0, @@ -1967,7 +1967,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,114,130,0,0,0,114,243,0,0,0,114,193,0,0,0, 41,2,114,102,0,0,0,114,121,0,0,0,114,2,0,0, 0,114,2,0,0,0,114,4,0,0,0,114,194,0,0,0, - 138,4,0,0,115,6,0,0,0,0,7,6,1,8,1,122, + 140,4,0,0,115,6,0,0,0,0,7,6,1,8,1,122, 28,95,78,97,109,101,115,112,97,99,101,76,111,97,100,101, 114,46,108,111,97,100,95,109,111,100,117,108,101,78,41,12, 114,107,0,0,0,114,106,0,0,0,114,108,0,0,0,114, @@ -1975,7 +1975,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,0,114,202,0,0,0,114,188,0,0,0,114,187,0, 0,0,114,192,0,0,0,114,194,0,0,0,114,2,0,0, 0,114,2,0,0,0,114,2,0,0,0,114,4,0,0,0, - 114,3,1,0,0,110,4,0,0,115,16,0,0,0,8,1, + 114,3,1,0,0,112,4,0,0,115,16,0,0,0,8,1, 8,3,12,9,8,3,8,3,8,3,8,3,8,3,114,3, 1,0,0,99,0,0,0,0,0,0,0,0,0,0,0,0, 4,0,0,0,64,0,0,0,115,106,0,0,0,101,0,90, @@ -2010,7 +2010,7 @@ const unsigned char _Py_M__importlib_external[] = { 95,99,97,99,104,101,218,5,105,116,101,109,115,114,110,0, 0,0,114,6,1,0,0,41,3,114,172,0,0,0,114,100, 0,0,0,218,6,102,105,110,100,101,114,114,2,0,0,0, - 114,2,0,0,0,114,4,0,0,0,114,6,1,0,0,156, + 114,2,0,0,0,114,4,0,0,0,114,6,1,0,0,158, 4,0,0,115,10,0,0,0,0,4,22,1,8,1,10,1, 10,1,122,28,80,97,116,104,70,105,110,100,101,114,46,105, 110,118,97,108,105,100,97,116,101,95,99,97,99,104,101,115, @@ -2030,7 +2030,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,114,62,0,0,0,114,120,0,0,0,114,101,0,0, 0,41,3,114,172,0,0,0,114,35,0,0,0,90,4,104, 111,111,107,114,2,0,0,0,114,2,0,0,0,114,4,0, - 0,0,218,11,95,112,97,116,104,95,104,111,111,107,115,166, + 0,0,218,11,95,112,97,116,104,95,104,111,111,107,115,168, 4,0,0,115,16,0,0,0,0,3,16,1,12,1,10,1, 2,1,14,1,14,1,12,2,122,22,80,97,116,104,70,105, 110,100,101,114,46,95,112,97,116,104,95,104,111,111,107,115, @@ -2061,7 +2061,7 @@ const unsigned char _Py_M__importlib_external[] = { 114,111,114,114,12,1,0,0,41,3,114,172,0,0,0,114, 35,0,0,0,114,10,1,0,0,114,2,0,0,0,114,2, 0,0,0,114,4,0,0,0,218,20,95,112,97,116,104,95, - 105,109,112,111,114,116,101,114,95,99,97,99,104,101,179,4, + 105,109,112,111,114,116,101,114,95,99,97,99,104,101,181,4, 0,0,115,22,0,0,0,0,8,8,1,2,1,12,1,14, 3,8,1,2,1,14,1,14,1,10,1,16,1,122,31,80, 97,116,104,70,105,110,100,101,114,46,95,112,97,116,104,95, @@ -2079,7 +2079,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,0,114,10,1,0,0,114,122,0,0,0,114,123,0, 0,0,114,166,0,0,0,114,2,0,0,0,114,2,0,0, 0,114,4,0,0,0,218,16,95,108,101,103,97,99,121,95, - 103,101,116,95,115,112,101,99,201,4,0,0,115,18,0,0, + 103,101,116,95,115,112,101,99,203,4,0,0,115,18,0,0, 0,0,4,10,1,16,2,10,1,4,1,8,1,12,1,12, 1,6,1,122,27,80,97,116,104,70,105,110,100,101,114,46, 95,108,101,103,97,99,121,95,103,101,116,95,115,112,101,99, @@ -2110,7 +2110,7 @@ const unsigned char _Py_M__importlib_external[] = { 115,112,97,99,101,95,112,97,116,104,90,5,101,110,116,114, 121,114,10,1,0,0,114,166,0,0,0,114,123,0,0,0, 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,218, - 9,95,103,101,116,95,115,112,101,99,216,4,0,0,115,40, + 9,95,103,101,116,95,115,112,101,99,218,4,0,0,115,40, 0,0,0,0,5,4,1,8,1,14,1,2,1,10,1,8, 1,10,1,14,2,12,1,8,1,2,1,10,1,8,1,6, 1,8,1,8,5,12,2,12,1,6,1,122,20,80,97,116, @@ -2137,7 +2137,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,114,241,0,0,0,41,6,114,172,0,0,0,114,121,0, 0,0,114,35,0,0,0,114,181,0,0,0,114,166,0,0, 0,114,17,1,0,0,114,2,0,0,0,114,2,0,0,0, - 114,4,0,0,0,114,182,0,0,0,248,4,0,0,115,26, + 114,4,0,0,0,114,182,0,0,0,250,4,0,0,115,26, 0,0,0,0,6,8,1,6,1,14,1,8,1,4,1,10, 1,6,1,4,3,6,1,16,1,4,2,6,2,122,20,80, 97,116,104,70,105,110,100,101,114,46,102,105,110,100,95,115, @@ -2159,7 +2159,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,114,122,0,0,0,41,4,114,172,0,0,0,114,121,0, 0,0,114,35,0,0,0,114,166,0,0,0,114,2,0,0, 0,114,2,0,0,0,114,4,0,0,0,114,183,0,0,0, - 16,5,0,0,115,8,0,0,0,0,8,12,1,8,1,4, + 18,5,0,0,115,8,0,0,0,0,8,12,1,8,1,4, 1,122,22,80,97,116,104,70,105,110,100,101,114,46,102,105, 110,100,95,109,111,100,117,108,101,41,1,78,41,2,78,78, 41,1,78,41,12,114,107,0,0,0,114,106,0,0,0,114, @@ -2167,7 +2167,7 @@ const unsigned char _Py_M__importlib_external[] = { 1,0,0,114,12,1,0,0,114,14,1,0,0,114,15,1, 0,0,114,18,1,0,0,114,182,0,0,0,114,183,0,0, 0,114,2,0,0,0,114,2,0,0,0,114,2,0,0,0, - 114,4,0,0,0,114,5,1,0,0,152,4,0,0,115,22, + 114,4,0,0,0,114,5,1,0,0,154,4,0,0,115,22, 0,0,0,8,2,4,2,12,10,12,13,12,22,12,15,2, 1,12,31,2,1,12,23,2,1,114,5,1,0,0,99,0, 0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,64, @@ -2211,7 +2211,7 @@ const unsigned char _Py_M__importlib_external[] = { 86,0,1,0,113,2,100,0,83,0,41,1,78,114,2,0, 0,0,41,2,114,22,0,0,0,114,236,0,0,0,41,1, 114,122,0,0,0,114,2,0,0,0,114,4,0,0,0,114, - 238,0,0,0,45,5,0,0,115,2,0,0,0,4,0,122, + 238,0,0,0,47,5,0,0,115,2,0,0,0,4,0,122, 38,70,105,108,101,70,105,110,100,101,114,46,95,95,105,110, 105,116,95,95,46,60,108,111,99,97,108,115,62,46,60,103, 101,110,101,120,112,114,62,114,59,0,0,0,114,89,0,0, @@ -2223,7 +2223,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,0,114,35,0,0,0,218,14,108,111,97,100,101,114, 95,100,101,116,97,105,108,115,90,7,108,111,97,100,101,114, 115,114,168,0,0,0,114,2,0,0,0,41,1,114,122,0, - 0,0,114,4,0,0,0,114,186,0,0,0,39,5,0,0, + 0,0,114,4,0,0,0,114,186,0,0,0,41,5,0,0, 115,16,0,0,0,0,4,4,1,12,1,26,1,6,2,10, 1,6,1,8,1,122,19,70,105,108,101,70,105,110,100,101, 114,46,95,95,105,110,105,116,95,95,99,1,0,0,0,0, @@ -2233,7 +2233,7 @@ const unsigned char _Py_M__importlib_external[] = { 32,100,105,114,101,99,116,111,114,121,32,109,116,105,109,101, 46,114,89,0,0,0,78,41,1,114,21,1,0,0,41,1, 114,102,0,0,0,114,2,0,0,0,114,2,0,0,0,114, - 4,0,0,0,114,6,1,0,0,53,5,0,0,115,2,0, + 4,0,0,0,114,6,1,0,0,55,5,0,0,115,2,0, 0,0,0,2,122,28,70,105,108,101,70,105,110,100,101,114, 46,105,110,118,97,108,105,100,97,116,101,95,99,97,99,104, 101,115,99,2,0,0,0,0,0,0,0,3,0,0,0,3, @@ -2256,7 +2256,7 @@ const unsigned char _Py_M__importlib_external[] = { 41,3,114,182,0,0,0,114,122,0,0,0,114,158,0,0, 0,41,3,114,102,0,0,0,114,121,0,0,0,114,166,0, 0,0,114,2,0,0,0,114,2,0,0,0,114,4,0,0, - 0,114,119,0,0,0,59,5,0,0,115,8,0,0,0,0, + 0,114,119,0,0,0,61,5,0,0,115,8,0,0,0,0, 7,10,1,8,1,8,1,122,22,70,105,108,101,70,105,110, 100,101,114,46,102,105,110,100,95,108,111,97,100,101,114,99, 6,0,0,0,0,0,0,0,7,0,0,0,6,0,0,0, @@ -2267,7 +2267,7 @@ const unsigned char _Py_M__importlib_external[] = { 114,167,0,0,0,114,121,0,0,0,114,35,0,0,0,90, 4,115,109,115,108,114,181,0,0,0,114,122,0,0,0,114, 2,0,0,0,114,2,0,0,0,114,4,0,0,0,114,18, - 1,0,0,71,5,0,0,115,6,0,0,0,0,1,10,1, + 1,0,0,73,5,0,0,115,6,0,0,0,0,1,10,1, 8,1,122,20,70,105,108,101,70,105,110,100,101,114,46,95, 103,101,116,95,115,112,101,99,78,99,3,0,0,0,0,0, 0,0,14,0,0,0,8,0,0,0,67,0,0,0,115,98, @@ -2321,7 +2321,7 @@ const unsigned char _Py_M__importlib_external[] = { 167,0,0,0,90,13,105,110,105,116,95,102,105,108,101,110, 97,109,101,90,9,102,117,108,108,95,112,97,116,104,114,166, 0,0,0,114,2,0,0,0,114,2,0,0,0,114,4,0, - 0,0,114,182,0,0,0,76,5,0,0,115,70,0,0,0, + 0,0,114,182,0,0,0,78,5,0,0,115,70,0,0,0, 0,5,4,1,14,1,2,1,24,1,14,1,10,1,10,1, 8,1,6,2,6,1,6,1,10,2,6,1,4,2,8,1, 12,1,14,1,8,1,10,1,8,1,26,4,8,2,14,1, @@ -2352,7 +2352,7 @@ const unsigned char _Py_M__importlib_external[] = { 1,160,0,161,0,146,2,113,4,83,0,114,2,0,0,0, 41,1,114,90,0,0,0,41,2,114,22,0,0,0,90,2, 102,110,114,2,0,0,0,114,2,0,0,0,114,4,0,0, - 0,218,9,60,115,101,116,99,111,109,112,62,153,5,0,0, + 0,218,9,60,115,101,116,99,111,109,112,62,155,5,0,0, 115,2,0,0,0,6,0,122,41,70,105,108,101,70,105,110, 100,101,114,46,95,102,105,108,108,95,99,97,99,104,101,46, 60,108,111,99,97,108,115,62,46,60,115,101,116,99,111,109, @@ -2369,7 +2369,7 @@ const unsigned char _Py_M__importlib_external[] = { 116,115,114,1,1,0,0,114,100,0,0,0,114,248,0,0, 0,114,236,0,0,0,90,8,110,101,119,95,110,97,109,101, 114,2,0,0,0,114,2,0,0,0,114,4,0,0,0,114, - 26,1,0,0,124,5,0,0,115,34,0,0,0,0,2,6, + 26,1,0,0,126,5,0,0,115,34,0,0,0,0,2,6, 1,2,1,22,1,20,3,10,3,12,1,12,7,6,1,8, 1,16,1,4,1,18,2,4,1,12,1,6,1,12,1,122, 22,70,105,108,101,70,105,110,100,101,114,46,95,102,105,108, @@ -2407,7 +2407,7 @@ const unsigned char _Py_M__importlib_external[] = { 114,35,0,0,0,41,2,114,172,0,0,0,114,25,1,0, 0,114,2,0,0,0,114,4,0,0,0,218,24,112,97,116, 104,95,104,111,111,107,95,102,111,114,95,70,105,108,101,70, - 105,110,100,101,114,165,5,0,0,115,6,0,0,0,0,2, + 105,110,100,101,114,167,5,0,0,115,6,0,0,0,0,2, 8,1,12,1,122,54,70,105,108,101,70,105,110,100,101,114, 46,112,97,116,104,95,104,111,111,107,46,60,108,111,99,97, 108,115,62,46,112,97,116,104,95,104,111,111,107,95,102,111, @@ -2415,7 +2415,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,41,3,114,172,0,0,0,114,25,1,0,0,114,31,1, 0,0,114,2,0,0,0,41,2,114,172,0,0,0,114,25, 1,0,0,114,4,0,0,0,218,9,112,97,116,104,95,104, - 111,111,107,155,5,0,0,115,4,0,0,0,0,10,14,6, + 111,111,107,157,5,0,0,115,4,0,0,0,0,10,14,6, 122,20,70,105,108,101,70,105,110,100,101,114,46,112,97,116, 104,95,104,111,111,107,99,1,0,0,0,0,0,0,0,1, 0,0,0,3,0,0,0,67,0,0,0,115,12,0,0,0, @@ -2423,7 +2423,7 @@ const unsigned char _Py_M__importlib_external[] = { 16,70,105,108,101,70,105,110,100,101,114,40,123,33,114,125, 41,41,2,114,48,0,0,0,114,35,0,0,0,41,1,114, 102,0,0,0,114,2,0,0,0,114,2,0,0,0,114,4, - 0,0,0,114,0,1,0,0,173,5,0,0,115,2,0,0, + 0,0,0,114,0,1,0,0,175,5,0,0,115,2,0,0, 0,0,1,122,19,70,105,108,101,70,105,110,100,101,114,46, 95,95,114,101,112,114,95,95,41,1,78,41,15,114,107,0, 0,0,114,106,0,0,0,114,108,0,0,0,114,109,0,0, @@ -2432,7 +2432,7 @@ const unsigned char _Py_M__importlib_external[] = { 182,0,0,0,114,26,1,0,0,114,184,0,0,0,114,32, 1,0,0,114,0,1,0,0,114,2,0,0,0,114,2,0, 0,0,114,2,0,0,0,114,4,0,0,0,114,19,1,0, - 0,30,5,0,0,115,20,0,0,0,8,7,4,2,8,14, + 0,32,5,0,0,115,20,0,0,0,8,7,4,2,8,14, 8,4,4,2,8,12,8,5,10,48,8,31,12,18,114,19, 1,0,0,99,4,0,0,0,0,0,0,0,6,0,0,0, 8,0,0,0,67,0,0,0,115,146,0,0,0,124,0,160, @@ -2455,7 +2455,7 @@ const unsigned char _Py_M__importlib_external[] = { 90,9,99,112,97,116,104,110,97,109,101,114,122,0,0,0, 114,166,0,0,0,114,2,0,0,0,114,2,0,0,0,114, 4,0,0,0,218,14,95,102,105,120,95,117,112,95,109,111, - 100,117,108,101,179,5,0,0,115,34,0,0,0,0,2,10, + 100,117,108,101,181,5,0,0,115,34,0,0,0,0,2,10, 1,10,1,4,1,4,1,8,1,8,1,12,2,10,1,4, 1,14,1,2,1,8,1,8,1,8,1,12,1,14,2,114, 37,1,0,0,99,0,0,0,0,0,0,0,0,3,0,0, @@ -2474,7 +2474,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,114,234,0,0,0,114,76,0,0,0,41,3,90,10,101, 120,116,101,110,115,105,111,110,115,90,6,115,111,117,114,99, 101,90,8,98,121,116,101,99,111,100,101,114,2,0,0,0, - 114,2,0,0,0,114,4,0,0,0,114,163,0,0,0,202, + 114,2,0,0,0,114,4,0,0,0,114,163,0,0,0,204, 5,0,0,115,8,0,0,0,0,5,12,1,8,1,8,1, 114,163,0,0,0,99,1,0,0,0,0,0,0,0,12,0, 0,0,9,0,0,0,67,0,0,0,115,156,1,0,0,124, @@ -2525,7 +2525,7 @@ const unsigned char _Py_M__importlib_external[] = { 107,2,86,0,1,0,113,2,100,1,83,0,41,2,114,29, 0,0,0,78,41,1,114,31,0,0,0,41,2,114,22,0, 0,0,114,79,0,0,0,114,2,0,0,0,114,2,0,0, - 0,114,4,0,0,0,114,238,0,0,0,238,5,0,0,115, + 0,114,4,0,0,0,114,238,0,0,0,240,5,0,0,115, 2,0,0,0,4,0,122,25,95,115,101,116,117,112,46,60, 108,111,99,97,108,115,62,46,60,103,101,110,101,120,112,114, 62,114,60,0,0,0,122,30,105,109,112,111,114,116,108,105, @@ -2553,7 +2553,7 @@ const unsigned char _Py_M__importlib_external[] = { 107,114,101,102,95,109,111,100,117,108,101,90,13,119,105,110, 114,101,103,95,109,111,100,117,108,101,114,2,0,0,0,114, 2,0,0,0,114,4,0,0,0,218,6,95,115,101,116,117, - 112,213,5,0,0,115,76,0,0,0,0,8,4,1,6,1, + 112,215,5,0,0,115,76,0,0,0,0,8,4,1,6,1, 6,3,10,1,8,1,10,1,12,2,10,1,14,3,22,1, 12,2,22,1,8,1,10,1,10,1,6,2,2,1,10,1, 10,1,14,1,12,2,8,1,12,1,12,1,18,3,10,1, @@ -2573,7 +2573,7 @@ const unsigned char _Py_M__importlib_external[] = { 2,114,43,1,0,0,90,17,115,117,112,112,111,114,116,101, 100,95,108,111,97,100,101,114,115,114,2,0,0,0,114,2, 0,0,0,114,4,0,0,0,218,8,95,105,110,115,116,97, - 108,108,21,6,0,0,115,8,0,0,0,0,2,8,1,6, + 108,108,23,6,0,0,115,8,0,0,0,0,2,8,1,6, 1,20,1,114,46,1,0,0,41,1,114,47,0,0,0,41, 1,78,41,3,78,78,78,41,2,114,60,0,0,0,114,60, 0,0,0,41,1,84,41,1,78,41,1,78,41,61,114,109, @@ -2605,7 +2605,7 @@ const unsigned char _Py_M__importlib_external[] = { 114,2,0,0,0,114,4,0,0,0,218,8,60,109,111,100, 117,108,101,62,8,0,0,0,115,118,0,0,0,4,15,4, 1,4,1,2,1,6,3,8,17,8,5,8,5,8,6,8, - 12,8,10,8,9,8,5,8,7,10,22,10,127,0,5,16, + 12,8,10,8,9,8,5,8,7,10,22,10,127,0,7,16, 1,12,2,4,1,4,2,6,2,6,2,8,2,16,45,8, 34,8,19,8,12,8,12,8,28,8,17,8,33,8,28,8, 24,10,13,10,10,10,11,8,14,6,3,4,1,14,67,14, From webhook-mailer at python.org Thu May 31 02:12:18 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Thu, 31 May 2018 06:12:18 -0000 Subject: [Python-checkins] bpo-32911: Update the historical note about the magic number. (GH-7272) Message-ID: <mailman.122.1527747139.2800.python-checkins@python.org> https://github.com/python/cpython/commit/d6bbb57855da3f92521edd901f49705be46fb203 commit: d6bbb57855da3f92521edd901f49705be46fb203 branch: 3.7 author: Serhiy Storchaka <storchaka at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-31T09:12:15+03:00 summary: bpo-32911: Update the historical note about the magic number. (GH-7272) files: M Lib/importlib/_bootstrap_external.py diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index f4be86274cab..53b24ff1b0f2 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -246,7 +246,7 @@ def _write_atomic(path, data, mode=0o666): # Python 3.7a2 3391 (update GET_AITER #31709) # Python 3.7a4 3392 (PEP 552: Deterministic pycs #31650) # Python 3.7b1 3393 (remove STORE_ANNOTATION opcode #32550) -# Python 3.7rc1 3394 (restored docstring as the firts stmt in the body; +# Python 3.7b5 3394 (restored docstring as the firts stmt in the body; # this might affected the first line number #32911) # # MAGIC must change whenever the bytecode emitted by the compiler may no From webhook-mailer at python.org Thu May 31 03:32:47 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Thu, 31 May 2018 07:32:47 -0000 Subject: [Python-checkins] [2.7] bpo-33677: Fix the signature of tp_clear handler for deque. (GH-7196). (GH-7277) Message-ID: <mailman.123.1527751970.2800.python-checkins@python.org> https://github.com/python/cpython/commit/db1074244d2c12961799f6f9353ae191f59cc497 commit: db1074244d2c12961799f6f9353ae191f59cc497 branch: 2.7 author: Serhiy Storchaka <storchaka at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-31T10:32:43+03:00 summary: [2.7] bpo-33677: Fix the signature of tp_clear handler for deque. (GH-7196). (GH-7277) (cherry picked from commit a5c42284e69fb309bdd17ee8c1c120d1be383012) files: M Modules/_collectionsmodule.c diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c index 2e4da4c211f8..9364aba549b1 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -639,7 +639,7 @@ deque_remove(dequeobject *deque, PyObject *value) PyDoc_STRVAR(remove_doc, "D.remove(value) -- remove first occurrence of value."); -static void +static int deque_clear(dequeobject *deque) { block *b; @@ -650,7 +650,7 @@ deque_clear(dequeobject *deque) PyObject *item; if (deque->len == 0) - return; + return 0; /* During the process of clearing a deque, decrefs can cause the deque to mutate. To avoid fatal confusion, we have to make the @@ -701,7 +701,7 @@ deque_clear(dequeobject *deque) } assert(leftblock->rightlink == NULL); freeblock(leftblock); - return; + return 0; alternate_method: while (deque->len) { @@ -709,6 +709,7 @@ deque_clear(dequeobject *deque) assert (item != NULL); Py_DECREF(item); } + return 0; } static PyObject * From solipsis at pitrou.net Thu May 31 05:09:31 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 31 May 2018 09:09:31 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=11 Message-ID: <20180531090931.1.7C1E29CF861649E6@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_collections leaked [0, 0, 7] memory blocks, sum=7 test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_forkserver leaked [-1, 2, -1] memory blocks, sum=0 test_multiprocessing_spawn leaked [-2, 2, 0] memory blocks, sum=0 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogFiHD02', '--timeout', '7200'] From webhook-mailer at python.org Thu May 31 06:20:50 2018 From: webhook-mailer at python.org (T. Wouters) Date: Thu, 31 May 2018 10:20:50 -0000 Subject: [Python-checkins] [3.6] bpo-32591: fix abort in _PyErr_WarnUnawaitedCoroutine during shutdown (GH-5337) (#6536) Message-ID: <mailman.124.1527762053.2800.python-checkins@python.org> https://github.com/python/cpython/commit/500a419a7a68c32650717b213f0f5ab0461bb16b commit: 500a419a7a68c32650717b213f0f5ab0461bb16b branch: 3.6 author: T. Wouters <thomas at python.org> committer: GitHub <noreply at github.com> date: 2018-05-31T12:20:46+02:00 summary: [3.6] bpo-32591: fix abort in _PyErr_WarnUnawaitedCoroutine during shutdown (GH-5337) (#6536) When an unawaited coroutine is collected very late in shutdown -- like, during the final GC at the end of PyImport_Cleanup -- then it was triggering an interpreter abort, because we'd try to look up the "warnings" module and not only was it missing (we were prepared for that), but the entire module system was missing (which we were not prepared for). I've tried to fix this at the source, by making the utility function get_warnings_attr robust against this in general. Note that it already has the convention that it can return NULL without setting an error, which is how it signals that the attribute it was asked to fetch is missing, and that all callers already check for NULL returns. There's a similar check for being late in shutdown at the top of warn_explicit, which might be unnecessary after this fix, but I'm not sure so I'm going to leave it.. (cherry picked from commit dba976b8a28d6e5daa66ef31a6a7c694a9193f6a) Co-authored-by: Nathaniel J. Smith <njs at pobox.com> files: M Python/_warnings.c diff --git a/Python/_warnings.c b/Python/_warnings.c index 0077b9b1c3d0..e96e154b0d54 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -63,6 +63,13 @@ get_warnings_attr(const char *attr, int try_import) } } else { + /* if we're so late into Python finalization that the module dict is + gone, then we can't even use PyImport_GetModule without triggering + an interpreter abort. + */ + if (!PyThreadState_GET()->interp->modules) { + return NULL; + } all_modules = PyImport_GetModuleDict(); warnings_module = PyDict_GetItem(all_modules, warnings_str); From webhook-mailer at python.org Thu May 31 06:22:14 2018 From: webhook-mailer at python.org (T. Wouters) Date: Thu, 31 May 2018 10:22:14 -0000 Subject: [Python-checkins] Add a crasher to Lib/test for issue #26153. This crasher doesn't crash (#6518) Message-ID: <mailman.125.1527762135.2800.python-checkins@python.org> https://github.com/python/cpython/commit/8b98d2a7397cade11393e951db60e4b9abbe1088 commit: 8b98d2a7397cade11393e951db60e4b9abbe1088 branch: 2.7 author: T. Wouters <thomas at python.org> committer: GitHub <noreply at github.com> date: 2018-05-31T12:22:11+02:00 summary: Add a crasher to Lib/test for issue #26153. This crasher doesn't crash (#6518) Python 3.6, although I've seen the same crash in 3.6 (when involving extension types and more complicated threading setups). files: A Lib/test/crashers/warnings_del_crasher.py diff --git a/Lib/test/crashers/warnings_del_crasher.py b/Lib/test/crashers/warnings_del_crasher.py new file mode 100644 index 000000000000..02e680520204 --- /dev/null +++ b/Lib/test/crashers/warnings_del_crasher.py @@ -0,0 +1,29 @@ +""" +Expose a race in the _warnings module, which is the C backend for the +warnings module. The "_warnings" module tries to access attributes of the +"warnings" module (because of the API it has to support), but doing so +during interpreter shutdown is problematic. Specifically, the call to +PyImport_GetModuleDict() in Python/_warnings.c:get_warnings_attr will +abort() if the modules dict has already been cleaned up. + +This crasher is timing-dependent, and more threads (NUM_THREADS) may be +necessary to expose it reliably on different systems. +""" + +import threading +import warnings + +NUM_THREADS = 10 + +class WarnOnDel(object): + def __del__(self): + warnings.warn("oh no something went wrong", UserWarning) + +def do_work(): + while True: + w = WarnOnDel() + +for i in range(NUM_THREADS): + t = threading.Thread(target=do_work) + t.setDaemon(1) + t.start() From webhook-mailer at python.org Thu May 31 09:09:31 2018 From: webhook-mailer at python.org (Victor Stinner) Date: Thu, 31 May 2018 13:09:31 -0000 Subject: [Python-checkins] bpo-33706: Fix pymain_parse_cmdline_impl() (GH-7283) Message-ID: <mailman.126.1527772175.2800.python-checkins@python.org> https://github.com/python/cpython/commit/58d1683255abb0df4fc70960da6121aeaa41e1d1 commit: 58d1683255abb0df4fc70960da6121aeaa41e1d1 branch: master author: Victor Stinner <vstinner at redhat.com> committer: GitHub <noreply at github.com> date: 2018-05-31T15:09:28+02:00 summary: bpo-33706: Fix pymain_parse_cmdline_impl() (GH-7283) Fix a crash in Python initialization when parsing the command line options. Fix memcpy() size parameter: previously, we read one wchar_t after the end of _PyOS_optarg. Moreover, don't copy the trailingg NUL character: we write it manually anyway. Thanks Christoph Gohlke for the bug report and the fix! files: A Misc/NEWS.d/next/Core and Builtins/2018-05-31-14-50-04.bpo-33706.ztlH04.rst M Modules/main.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-05-31-14-50-04.bpo-33706.ztlH04.rst b/Misc/NEWS.d/next/Core and Builtins/2018-05-31-14-50-04.bpo-33706.ztlH04.rst new file mode 100644 index 000000000000..d3b8477b2197 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-05-31-14-50-04.bpo-33706.ztlH04.rst @@ -0,0 +1,2 @@ +Fix a crash in Python initialization when parsing the command line options. +Thanks Christoph Gohlke for the bug report and the fix! diff --git a/Modules/main.c b/Modules/main.c index 9cbb3f1ce003..286ad418fe13 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -761,7 +761,7 @@ pymain_parse_cmdline_impl(_PyMain *pymain, _Py_CommandLineDetails *cmdline) pymain->err = _Py_INIT_NO_MEMORY(); return -1; } - memcpy(command, _PyOS_optarg, len * sizeof(wchar_t)); + memcpy(command, _PyOS_optarg, (len - 2) * sizeof(wchar_t)); command[len - 2] = '\n'; command[len - 1] = 0; pymain->command = command; From webhook-mailer at python.org Thu May 31 09:43:24 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 31 May 2018 13:43:24 -0000 Subject: [Python-checkins] bpo-33706: Fix pymain_parse_cmdline_impl() (GH-7283) Message-ID: <mailman.127.1527774207.2800.python-checkins@python.org> https://github.com/python/cpython/commit/c6de46e180e81508a3b43341791b56418bd811f9 commit: c6de46e180e81508a3b43341791b56418bd811f9 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub <noreply at github.com> date: 2018-05-31T06:43:21-07:00 summary: bpo-33706: Fix pymain_parse_cmdline_impl() (GH-7283) Fix a crash in Python initialization when parsing the command line options. Fix memcpy() size parameter: previously, we read one wchar_t after the end of _PyOS_optarg. Moreover, don't copy the trailingg NUL character: we write it manually anyway. Thanks Christoph Gohlke for the bug report and the fix! (cherry picked from commit 58d1683255abb0df4fc70960da6121aeaa41e1d1) Co-authored-by: Victor Stinner <vstinner at redhat.com> files: A Misc/NEWS.d/next/Core and Builtins/2018-05-31-14-50-04.bpo-33706.ztlH04.rst M Modules/main.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-05-31-14-50-04.bpo-33706.ztlH04.rst b/Misc/NEWS.d/next/Core and Builtins/2018-05-31-14-50-04.bpo-33706.ztlH04.rst new file mode 100644 index 000000000000..d3b8477b2197 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-05-31-14-50-04.bpo-33706.ztlH04.rst @@ -0,0 +1,2 @@ +Fix a crash in Python initialization when parsing the command line options. +Thanks Christoph Gohlke for the bug report and the fix! diff --git a/Modules/main.c b/Modules/main.c index 9cbb3f1ce003..286ad418fe13 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -761,7 +761,7 @@ pymain_parse_cmdline_impl(_PyMain *pymain, _Py_CommandLineDetails *cmdline) pymain->err = _Py_INIT_NO_MEMORY(); return -1; } - memcpy(command, _PyOS_optarg, len * sizeof(wchar_t)); + memcpy(command, _PyOS_optarg, (len - 2) * sizeof(wchar_t)); command[len - 2] = '\n'; command[len - 1] = 0; pymain->command = command; From webhook-mailer at python.org Thu May 31 12:17:35 2018 From: webhook-mailer at python.org (Eric Snow) Date: Thu, 31 May 2018 16:17:35 -0000 Subject: [Python-checkins] bpo-33615: Temporarily disable a test that is triggering crashes on a few buildbots. (gh-7288) Message-ID: <mailman.128.1527783463.2800.python-checkins@python.org> https://github.com/python/cpython/commit/110bc01407ac8c75545d0386577c6e17254d97d9 commit: 110bc01407ac8c75545d0386577c6e17254d97d9 branch: master author: Eric Snow <ericsnowcurrently at gmail.com> committer: GitHub <noreply at github.com> date: 2018-05-31T10:17:24-06:00 summary: bpo-33615: Temporarily disable a test that is triggering crashes on a few buildbots. (gh-7288) For bpo-32604 I added some subinterpreter-related tests (see #6914) that are causing crashes on a few buildbots. I'm working on fixing the crashes (see #7251). This change temporarily disables the triggering test. files: M Lib/test/test__xxsubinterpreters.py diff --git a/Lib/test/test__xxsubinterpreters.py b/Lib/test/test__xxsubinterpreters.py index f66cc9516926..0667f14f7bf4 100644 --- a/Lib/test/test__xxsubinterpreters.py +++ b/Lib/test/test__xxsubinterpreters.py @@ -1315,6 +1315,8 @@ def test_run_string_arg_unresolved(self): self.assertEqual(obj, b'spam') self.assertEqual(out.strip(), 'send') + # XXX Fix the crashes. + @unittest.skip('bpo-33615: triggering crashes so temporarily disabled') def test_run_string_arg_resolved(self): cid = interpreters.channel_create() cid = interpreters._channel_id(cid, _resolve=True) From webhook-mailer at python.org Thu May 31 18:33:07 2018 From: webhook-mailer at python.org (Victor Stinner) Date: Thu, 31 May 2018 22:33:07 -0000 Subject: [Python-checkins] bpo-33717: pythoninfo: add CC --version (#7290) Message-ID: <mailman.129.1527805990.2800.python-checkins@python.org> https://github.com/python/cpython/commit/56013218864d5eb81baab4665fcae13400934078 commit: 56013218864d5eb81baab4665fcae13400934078 branch: master author: Victor Stinner <vstinner at redhat.com> committer: GitHub <noreply at github.com> date: 2018-06-01T00:33:03+02:00 summary: bpo-33717: pythoninfo: add CC --version (#7290) Get the version of the C compiler. files: M Lib/test/pythoninfo.py diff --git a/Lib/test/pythoninfo.py b/Lib/test/pythoninfo.py index f1b02336f7e3..776f03f8b58b 100644 --- a/Lib/test/pythoninfo.py +++ b/Lib/test/pythoninfo.py @@ -489,6 +489,34 @@ def collect_test_support(info_add): call_func(info_add, 'test_support.python_is_optimized', support, 'python_is_optimized') +def collect_cc(info_add): + import subprocess + import sysconfig + + CC = sysconfig.get_config_var('CC') + if not CC: + return + + try: + import shlex + args = shlex.split(CC) + except ImportError: + args = CC.split() + args.append('--version') + proc = subprocess.Popen(args, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + universal_newlines=True) + stdout = proc.communicate()[0] + if proc.returncode: + # CC --version failed: ignore error + return + + text = stdout.splitlines()[0] + text = normalize_text(text) + info_add('CC.version', text) + + def collect_info(info): error = False info_add = info.add @@ -515,6 +543,7 @@ def collect_info(info): collect_decimal, collect_testcapi, collect_resource, + collect_cc, # Collecting from tests should be last as they have side effects. collect_test_socket, From webhook-mailer at python.org Thu May 31 18:49:01 2018 From: webhook-mailer at python.org (Victor Stinner) Date: Thu, 31 May 2018 22:49:01 -0000 Subject: [Python-checkins] bpo-33718: regrtest keeps filters to re-run fails (GH-7291) Message-ID: <mailman.130.1527806944.2800.python-checkins@python.org> https://github.com/python/cpython/commit/9e24930dfdc28e16dabbfd7dd1ead1336b7b0d6c commit: 9e24930dfdc28e16dabbfd7dd1ead1336b7b0d6c branch: master author: Victor Stinner <vstinner at redhat.com> committer: GitHub <noreply at github.com> date: 2018-06-01T00:48:57+02:00 summary: bpo-33718: regrtest keeps filters to re-run fails (GH-7291) * No longer clear filters, like --match, to re-run failed tests in verbose mode (-w option). * Tests result: always indicate if tests have been interrupted. * Enhance tests summary files: M Lib/test/libregrtest/main.py diff --git a/Lib/test/libregrtest/main.py b/Lib/test/libregrtest/main.py index 1ab47bf58d67..f0c1631509bd 100644 --- a/Lib/test/libregrtest/main.py +++ b/Lib/test/libregrtest/main.py @@ -282,7 +282,6 @@ def rerun_failed_tests(self): self.ns.verbose = True self.ns.failfast = False self.ns.verbose3 = False - self.ns.match_tests = None print() print("Re-running failed tests in verbose mode") @@ -313,7 +312,7 @@ def display_result(self): return print() - print("== Tests result ==") + print("== Tests result: %s ==" % self.get_tests_result()) if self.interrupted: print() @@ -324,11 +323,6 @@ def display_result(self): print(count(len(omitted), "test"), "omitted:") printlist(omitted) - if self.rerun: - print() - print(count(len(self.rerun), "test"), "re-run tests:") - printlist(self.rerun) - if self.good and not self.ns.quiet: print() if (not self.bad @@ -361,6 +355,11 @@ def display_result(self): print(count(len(self.skipped), "test"), "skipped:") printlist(self.skipped) + if self.rerun: + print() + print("%s:" % count(len(self.rerun), "re-run test")) + printlist(self.rerun) + def run_tests_sequential(self): if self.ns.trace: import trace @@ -445,6 +444,21 @@ def display_header(self): % (locale.getpreferredencoding(False), sys.getfilesystemencoding())) + def get_tests_result(self): + result = [] + if self.bad: + result.append("FAILURE") + elif self.ns.fail_env_changed and self.environment_changed: + result.append("ENV CHANGED") + + if self.interrupted: + result.append("INTERRUPTED") + + if not result: + result.append("SUCCESS") + + return ', '.join(result) + def run_tests(self): # For a partial run, we do not need to clutter the output. if (self.ns.header @@ -486,16 +500,7 @@ def finalize(self): print() duration = time.monotonic() - self.start_time print("Total duration: %s" % format_duration(duration)) - - if self.bad: - result = "FAILURE" - elif self.interrupted: - result = "INTERRUPTED" - elif self.ns.fail_env_changed and self.environment_changed: - result = "ENV CHANGED" - else: - result = "SUCCESS" - print("Tests result: %s" % result) + print("Tests result: %s" % self.get_tests_result()) if self.ns.runleaks: os.system("leaks %d" % os.getpid())