From webhook-mailer at python.org Thu Feb 1 02:31:11 2018 From: webhook-mailer at python.org (Xiang Zhang) Date: Thu, 01 Feb 2018 07:31:11 -0000 Subject: [Python-checkins] bpo-32722: Remove useless example in the Classes tutorial (#5446) Message-ID: https://github.com/python/cpython/commit/ab328756d7fd969ee4882458b07892dff135013c commit: ab328756d7fd969ee4882458b07892dff135013c branch: master author: St?phane Wirtel committer: Xiang Zhang date: 2018-02-01T15:31:07+08:00 summary: bpo-32722: Remove useless example in the Classes tutorial (#5446) In the tutorial about the Generator expression, there is an example with a dict comprehension and not with a generator expression, just removed the code. files: A Misc/NEWS.d/next/Documentation/2018-01-30-11-28-27.bpo-32722.frdp6A.rst M Doc/tutorial/classes.rst diff --git a/Doc/tutorial/classes.rst b/Doc/tutorial/classes.rst index 4676ef4b8a60..b8f1226e54a0 100644 --- a/Doc/tutorial/classes.rst +++ b/Doc/tutorial/classes.rst @@ -892,10 +892,7 @@ Examples:: >>> sum(x*y for x,y in zip(xvec, yvec)) # dot product 260 - >>> from math import pi, sin - >>> sine_table = {x: sin(x*pi/180) for x in range(0, 91)} - - >>> unique_words = set(word for line in page for word in line.split()) + >>> unique_words = set(word for line in page for word in line.split()) >>> valedictorian = max((student.gpa, student.name) for student in graduates) diff --git a/Misc/NEWS.d/next/Documentation/2018-01-30-11-28-27.bpo-32722.frdp6A.rst b/Misc/NEWS.d/next/Documentation/2018-01-30-11-28-27.bpo-32722.frdp6A.rst new file mode 100644 index 000000000000..c4ed27ee2780 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2018-01-30-11-28-27.bpo-32722.frdp6A.rst @@ -0,0 +1,2 @@ +Remove the bad example in the tutorial of the Generator Expression. Patch by +St?phane Wirtel From solipsis at pitrou.net Thu Feb 1 04:09:39 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 01 Feb 2018 09:09:39 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=-3 Message-ID: <20180201090939.1.FD6438136AAC846E@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_fork leaked [0, 1, -2] memory blocks, sum=-1 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogAmi_LL', '--timeout', '7200'] From webhook-mailer at python.org Thu Feb 1 06:48:40 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Thu, 01 Feb 2018 11:48:40 -0000 Subject: [Python-checkins] bpo-32565: Add missed versionadded directives for all new opcodes. (#5199) Message-ID: https://github.com/python/cpython/commit/12e7cd8a51956a5ce373aac692ae6366c5f86584 commit: 12e7cd8a51956a5ce373aac692ae6366c5f86584 branch: master author: Serhiy Storchaka committer: GitHub date: 2018-02-01T13:48:33+02:00 summary: bpo-32565: Add missed versionadded directives for all new opcodes. (#5199) files: M Doc/library/dis.rst diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index 48c42d119d5d..535b36efbf2e 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -339,12 +339,16 @@ The Python compiler currently generates the following bytecode instructions. Duplicates the reference on top of the stack. + .. versionadded:: 3.2 + .. opcode:: DUP_TOP_TWO Duplicates the two references on top of the stack, leaving them in the same order. + .. versionadded:: 3.2 + **Unary operations** @@ -555,11 +559,14 @@ the original TOS1. the CO_ITERABLE_COROUTINE flag, or resolves ``o.__await__``. + .. versionadded:: 3.5 + .. opcode:: GET_AITER Implements ``TOS = TOS.__aiter__()``. + .. versionadded:: 3.5 .. versionchanged:: 3.7 Returning awaitable objects from ``__aiter__`` is no longer supported. @@ -570,17 +577,23 @@ the original TOS1. Implements ``PUSH(get_awaitable(TOS.__anext__()))``. See ``GET_AWAITABLE`` for details about ``get_awaitable`` + .. versionadded:: 3.5 + .. opcode:: BEFORE_ASYNC_WITH Resolves ``__aenter__`` and ``__aexit__`` from the object on top of the stack. Pushes ``__aexit__`` and result of ``__aenter__()`` to the stack. + .. versionadded:: 3.5 + .. opcode:: SETUP_ASYNC_WITH Creates a new frame object. + .. versionadded:: 3.5 + **Miscellaneous opcodes** @@ -618,6 +631,8 @@ the original TOS1. Calls ``dict.setitem(TOS1[-i], TOS, TOS1)``. Used to implement dict comprehensions. + .. versionadded:: 3.1 + For all of the :opcode:`SET_ADD`, :opcode:`LIST_APPEND` and :opcode:`MAP_ADD` instructions, while the added value or key/value pair is popped off, the container object remains on the stack so that it is available for further @@ -640,6 +655,7 @@ iterations of the loop. .. versionadded:: 3.3 + .. opcode:: SETUP_ANNOTATIONS Checks whether ``__annotations__`` is defined in ``locals()``, if not it is @@ -649,6 +665,7 @@ iterations of the loop. .. versionadded:: 3.6 + .. opcode:: IMPORT_STAR Loads all symbols not starting with ``'_'`` directly from the module TOS to @@ -694,6 +711,8 @@ iterations of the loop. store it in (a) variable(s) (:opcode:`STORE_FAST`, :opcode:`STORE_NAME`, or :opcode:`UNPACK_SEQUENCE`). + .. versionadded:: 3.2 + .. opcode:: WITH_CLEANUP_START @@ -924,23 +943,31 @@ All of the following opcodes use their arguments. If TOS is true, sets the bytecode counter to *target*. TOS is popped. + .. versionadded:: 3.1 + .. opcode:: POP_JUMP_IF_FALSE (target) If TOS is false, sets the bytecode counter to *target*. TOS is popped. + .. versionadded:: 3.1 + .. opcode:: JUMP_IF_TRUE_OR_POP (target) If TOS is true, sets the bytecode counter to *target* and leaves TOS on the stack. Otherwise (TOS is false), TOS is popped. + .. versionadded:: 3.1 + .. opcode:: JUMP_IF_FALSE_OR_POP (target) If TOS is false, sets the bytecode counter to *target* and leaves TOS on the stack. Otherwise (TOS is true), TOS is popped. + .. versionadded:: 3.1 + .. opcode:: JUMP_ABSOLUTE (target) @@ -1013,6 +1040,8 @@ All of the following opcodes use their arguments. consulting the cell. This is used for loading free variables in class bodies. + .. versionadded:: 3.4 + .. opcode:: STORE_DEREF (i) @@ -1025,6 +1054,8 @@ All of the following opcodes use their arguments. Empties the cell contained in slot *i* of the cell and free variable storage. Used by the :keyword:`del` statement. + .. versionadded:: 3.2 + .. opcode:: RAISE_VARARGS (argc) From webhook-mailer at python.org Thu Feb 1 06:57:31 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Thu, 01 Feb 2018 11:57:31 -0000 Subject: [Python-checkins] bpo-32137: The repr of deeply nested dict now raises a RecursionError (GH-4570) (GH-4689) Message-ID: https://github.com/python/cpython/commit/688b6dec4e8847a154ef27257069291175764794 commit: 688b6dec4e8847a154ef27257069291175764794 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Serhiy Storchaka date: 2018-02-01T13:57:28+02:00 summary: bpo-32137: The repr of deeply nested dict now raises a RecursionError (GH-4570) (GH-4689) instead of crashing due to a stack overflow. This perhaps will fix similar problems in other extension types. (cherry picked from commit 1fb72d2ad243c965d4432b4e93884064001a2607) files: A Misc/NEWS.d/next/Core and Builtins/2017-11-26-14-36-30.bpo-32137.Stj5nL.rst M Lib/test/list_tests.py M Lib/test/mapping_tests.py M Lib/test/test_dict.py M Objects/listobject.c M Objects/object.c M Objects/tupleobject.c diff --git a/Lib/test/list_tests.py b/Lib/test/list_tests.py index 26e93687f411..05e771f944b9 100644 --- a/Lib/test/list_tests.py +++ b/Lib/test/list_tests.py @@ -53,10 +53,11 @@ def test_repr(self): self.assertEqual(str(a2), "[0, 1, 2, [...], 3]") self.assertEqual(repr(a2), "[0, 1, 2, [...], 3]") - l0 = [] + def test_repr_deep(self): + a = self.type2test([]) for i in range(sys.getrecursionlimit() + 100): - l0 = [l0] - self.assertRaises(RecursionError, repr, l0) + a = self.type2test([a]) + self.assertRaises(RecursionError, repr, a) def test_print(self): d = self.type2test(range(200)) diff --git a/Lib/test/mapping_tests.py b/Lib/test/mapping_tests.py index ff82f4eb7d89..53f29f605386 100644 --- a/Lib/test/mapping_tests.py +++ b/Lib/test/mapping_tests.py @@ -1,6 +1,7 @@ # tests common to dict and UserDict import unittest import collections +import sys class BasicTestMappingProtocol(unittest.TestCase): @@ -619,6 +620,14 @@ def __repr__(self): d = self._full_mapping({1: BadRepr()}) self.assertRaises(Exc, repr, d) + def test_repr_deep(self): + d = self._empty_mapping() + for i in range(sys.getrecursionlimit() + 100): + d0 = d + d = self._empty_mapping() + d[1] = d0 + self.assertRaises(RecursionError, repr, d) + def test_eq(self): self.assertEqual(self._empty_mapping(), self._empty_mapping()) self.assertEqual(self._full_mapping({1: 2}), diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py index 8013f37c88da..4386eda3ae48 100644 --- a/Lib/test/test_dict.py +++ b/Lib/test/test_dict.py @@ -468,6 +468,12 @@ def __repr__(self): d = {1: BadRepr()} self.assertRaises(Exc, repr, d) + def test_repr_deep(self): + d = {} + for i in range(sys.getrecursionlimit() + 100): + d = {1: d} + self.assertRaises(RecursionError, repr, d) + def test_eq(self): self.assertEqual({}, {}) self.assertEqual({1: 2}, {1: 2}) diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-11-26-14-36-30.bpo-32137.Stj5nL.rst b/Misc/NEWS.d/next/Core and Builtins/2017-11-26-14-36-30.bpo-32137.Stj5nL.rst new file mode 100644 index 000000000000..f8f4ab93c9e2 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-11-26-14-36-30.bpo-32137.Stj5nL.rst @@ -0,0 +1,2 @@ +The repr of deeply nested dict now raises a RecursionError instead of +crashing due to a stack overflow. diff --git a/Objects/listobject.c b/Objects/listobject.c index 547bdf0b95f1..ea8310f153ae 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -366,10 +366,7 @@ list_repr(PyListObject *v) goto error; } - if (Py_EnterRecursiveCall(" while getting the repr of a list")) - goto error; s = PyObject_Repr(v->ob_item[i]); - Py_LeaveRecursiveCall(); if (s == NULL) goto error; diff --git a/Objects/object.c b/Objects/object.c index d88ae3b94f3e..defff5579699 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -482,7 +482,12 @@ PyObject_Repr(PyObject *v) assert(!PyErr_Occurred()); #endif + /* It is possible for a type to have a tp_repr representation that loops + infinitely. */ + if (Py_EnterRecursiveCall(" while getting the repr of an object")) + return NULL; res = (*v->ob_type->tp_repr)(v); + Py_LeaveRecursiveCall(); if (res == NULL) return NULL; if (!PyUnicode_Check(res)) { diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index 0dada74dc7c9..047926f969b7 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -300,10 +300,7 @@ tuplerepr(PyTupleObject *v) goto error; } - if (Py_EnterRecursiveCall(" while getting the repr of a tuple")) - goto error; s = PyObject_Repr(v->ob_item[i]); - Py_LeaveRecursiveCall(); if (s == NULL) goto error; From webhook-mailer at python.org Thu Feb 1 07:47:26 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Thu, 01 Feb 2018 12:47:26 -0000 Subject: [Python-checkins] [3.6] bpo-32565: Add missed versionadded directives for all new opcodes. (GH-5199). (GH-5471) Message-ID: https://github.com/python/cpython/commit/8cf7ebb32dbdfb976ac92afd264e7587fb0da7ae commit: 8cf7ebb32dbdfb976ac92afd264e7587fb0da7ae branch: 3.6 author: Serhiy Storchaka committer: GitHub date: 2018-02-01T14:47:22+02:00 summary: [3.6] bpo-32565: Add missed versionadded directives for all new opcodes. (GH-5199). (GH-5471) (cherry picked from commit 12e7cd8a51956a5ce373aac692ae6366c5f86584) Co-authored-by: Serhiy Storchaka files: M Doc/library/dis.rst diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index c68b15a9d450..3f615dbd15ce 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -318,12 +318,16 @@ The Python compiler currently generates the following bytecode instructions. Duplicates the reference on top of the stack. + .. versionadded:: 3.2 + .. opcode:: DUP_TOP_TWO Duplicates the two references on top of the stack, leaving them in the same order. + .. versionadded:: 3.2 + **Unary operations** @@ -534,29 +538,39 @@ the original TOS1. the CO_ITERABLE_COROUTINE flag, or resolves ``o.__await__``. + .. versionadded:: 3.5 + .. opcode:: GET_AITER Implements ``TOS = get_awaitable(TOS.__aiter__())``. See ``GET_AWAITABLE`` for details about ``get_awaitable`` + .. versionadded:: 3.5 + .. opcode:: GET_ANEXT Implements ``PUSH(get_awaitable(TOS.__anext__()))``. See ``GET_AWAITABLE`` for details about ``get_awaitable`` + .. versionadded:: 3.5 + .. opcode:: BEFORE_ASYNC_WITH Resolves ``__aenter__`` and ``__aexit__`` from the object on top of the stack. Pushes ``__aexit__`` and result of ``__aenter__()`` to the stack. + .. versionadded:: 3.5 + .. opcode:: SETUP_ASYNC_WITH Creates a new frame object. + .. versionadded:: 3.5 + **Miscellaneous opcodes** @@ -594,6 +608,8 @@ the original TOS1. Calls ``dict.setitem(TOS1[-i], TOS, TOS1)``. Used to implement dict comprehensions. + .. versionadded:: 3.1 + For all of the :opcode:`SET_ADD`, :opcode:`LIST_APPEND` and :opcode:`MAP_ADD` instructions, while the added value or key/value pair is popped off, the container object remains on the stack so that it is available for further @@ -616,6 +632,7 @@ iterations of the loop. .. versionadded:: 3.3 + .. opcode:: SETUP_ANNOTATIONS Checks whether ``__annotations__`` is defined in ``locals()``, if not it is @@ -625,6 +642,7 @@ iterations of the loop. .. versionadded:: 3.6 + .. opcode:: IMPORT_STAR Loads all symbols not starting with ``'_'`` directly from the module TOS to @@ -670,6 +688,8 @@ iterations of the loop. store it in (a) variable(s) (:opcode:`STORE_FAST`, :opcode:`STORE_NAME`, or :opcode:`UNPACK_SEQUENCE`). + .. versionadded:: 3.2 + .. opcode:: WITH_CLEANUP_START @@ -900,23 +920,31 @@ All of the following opcodes use their arguments. If TOS is true, sets the bytecode counter to *target*. TOS is popped. + .. versionadded:: 3.1 + .. opcode:: POP_JUMP_IF_FALSE (target) If TOS is false, sets the bytecode counter to *target*. TOS is popped. + .. versionadded:: 3.1 + .. opcode:: JUMP_IF_TRUE_OR_POP (target) If TOS is true, sets the bytecode counter to *target* and leaves TOS on the stack. Otherwise (TOS is false), TOS is popped. + .. versionadded:: 3.1 + .. opcode:: JUMP_IF_FALSE_OR_POP (target) If TOS is false, sets the bytecode counter to *target* and leaves TOS on the stack. Otherwise (TOS is true), TOS is popped. + .. versionadded:: 3.1 + .. opcode:: JUMP_ABSOLUTE (target) @@ -996,6 +1024,8 @@ All of the following opcodes use their arguments. consulting the cell. This is used for loading free variables in class bodies. + .. versionadded:: 3.4 + .. opcode:: STORE_DEREF (i) @@ -1008,6 +1038,8 @@ All of the following opcodes use their arguments. Empties the cell contained in slot *i* of the cell and free variable storage. Used by the :keyword:`del` statement. + .. versionadded:: 3.2 + .. opcode:: RAISE_VARARGS (argc) From webhook-mailer at python.org Thu Feb 1 09:07:12 2018 From: webhook-mailer at python.org (Andrew Svetlov) Date: Thu, 01 Feb 2018 14:07:12 -0000 Subject: [Python-checkins] bpo-31106: Fix handling of erros in posix_fallocate() and posix_fadvise() (GH-3000) (GH-3000) (#4101) Message-ID: https://github.com/python/cpython/commit/3a04c52a9eb03e31c60037248b872f3662002a4d commit: 3a04c52a9eb03e31c60037248b872f3662002a4d branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Andrew Svetlov date: 2018-02-01T16:07:08+02:00 summary: bpo-31106: Fix handling of erros in posix_fallocate() and posix_fadvise() (GH-3000) (GH-3000) (#4101) (cherry picked from commit d4b93e21c2664d6a78e0656e7a7be0807be1c352) files: M Lib/test/test_posix.py M Modules/posixmodule.c diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py index 85eae47b8a5b..296e328a8044 100644 --- a/Lib/test/test_posix.py +++ b/Lib/test/test_posix.py @@ -235,6 +235,16 @@ def test_posix_fallocate(self): finally: os.close(fd) + # issue31106 - posix_fallocate() does not set error in errno. + @unittest.skipUnless(hasattr(posix, 'posix_fallocate'), + "test needs posix.posix_fallocate()") + def test_posix_fallocate_errno(self): + try: + posix.posix_fallocate(-42, 0, 10) + except OSError as inst: + if inst.errno != errno.EBADF: + raise + @unittest.skipUnless(hasattr(posix, 'posix_fadvise'), "test needs posix.posix_fadvise()") def test_posix_fadvise(self): @@ -244,6 +254,15 @@ def test_posix_fadvise(self): finally: os.close(fd) + @unittest.skipUnless(hasattr(posix, 'posix_fadvise'), + "test needs posix.posix_fadvise()") + def test_posix_fadvise_errno(self): + try: + posix.posix_fadvise(-42, 0, 0, posix.POSIX_FADV_WILLNEED) + except OSError as inst: + if inst.errno != errno.EBADF: + raise + @unittest.skipUnless(os.utime in os.supports_fd, "test needs fd support in os.utime") def test_utime_with_fd(self): now = time.time() diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 821b64ccbca0..e30d3c13bb2c 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -8792,11 +8792,16 @@ os_posix_fallocate_impl(PyObject *module, int fd, Py_off_t offset, Py_BEGIN_ALLOW_THREADS result = posix_fallocate(fd, offset, length); Py_END_ALLOW_THREADS - } while (result != 0 && errno == EINTR && - !(async_err = PyErr_CheckSignals())); - if (result != 0) - return (!async_err) ? posix_error() : NULL; - Py_RETURN_NONE; + } while (result == EINTR && !(async_err = PyErr_CheckSignals())); + + if (result == 0) + Py_RETURN_NONE; + + if (async_err) + return NULL; + + errno = result; + return posix_error(); } #endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG */ @@ -8834,11 +8839,16 @@ os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset, Py_BEGIN_ALLOW_THREADS result = posix_fadvise(fd, offset, length, advice); Py_END_ALLOW_THREADS - } while (result != 0 && errno == EINTR && - !(async_err = PyErr_CheckSignals())); - if (result != 0) - return (!async_err) ? posix_error() : NULL; - Py_RETURN_NONE; + } while (result == EINTR && !(async_err = PyErr_CheckSignals())); + + if (result == 0) + Py_RETURN_NONE; + + if (async_err) + return NULL; + + errno = result; + return posix_error(); } #endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */ From webhook-mailer at python.org Thu Feb 1 11:59:30 2018 From: webhook-mailer at python.org (Christian Heimes) Date: Thu, 01 Feb 2018 16:59:30 -0000 Subject: [Python-checkins] bpo-32711: Fix warnings for Python/ast_unparse.c (#5426) Message-ID: https://github.com/python/cpython/commit/83ab995871ffd504ac229bdbf5b9e9ffc1032815 commit: 83ab995871ffd504ac229bdbf5b9e9ffc1032815 branch: master author: St?phane Wirtel committer: Christian Heimes date: 2018-02-01T17:59:27+01:00 summary: bpo-32711: Fix warnings for Python/ast_unparse.c (#5426) * bpo-32711: Fix warnings for Python/ast_unparse.c files: A Misc/NEWS.d/next/Core and Builtins/2018-01-29-14-36-37.bpo-32711.8hQFJP.rst M Python/ast_unparse.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-01-29-14-36-37.bpo-32711.8hQFJP.rst b/Misc/NEWS.d/next/Core and Builtins/2018-01-29-14-36-37.bpo-32711.8hQFJP.rst new file mode 100644 index 000000000000..4d55b894ce10 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-01-29-14-36-37.bpo-32711.8hQFJP.rst @@ -0,0 +1 @@ +Fix the warning messages for Python/ast_unparse.c. Patch by St?phane Wirtel diff --git a/Python/ast_unparse.c b/Python/ast_unparse.c index ef9e948dc825..1345271e599b 100644 --- a/Python/ast_unparse.c +++ b/Python/ast_unparse.c @@ -20,7 +20,7 @@ append_formattedvalue(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec); static int append_charp(_PyUnicodeWriter *writer, const char *charp) { - return _PyUnicodeWriter_WriteASCIIString(writer, charp, -1); + return _PyUnicodeWriter_WriteASCIIString(writer, charp, -1); } static int @@ -100,6 +100,8 @@ append_ast_binop(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) case BitAnd: op = " & "; break; case FloorDiv: op = " // "; break; case Pow: op = " ** "; break; + default: + Py_UNREACHABLE(); } if (-1 == append_charp(writer, op)) { @@ -127,6 +129,8 @@ append_ast_unaryop(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) case Not: op = "not "; break; case UAdd: op = "+"; break; case USub: op = "-"; break; + default: + Py_UNREACHABLE(); } if (-1 == append_charp(writer, op)) { @@ -856,7 +860,7 @@ append_formattedvalue(_PyUnicodeWriter *writer, expr_ty e, bool is_format_spec) return -1; } } - if (e->v.FormattedValue.format_spec > 0) { + if (e->v.FormattedValue.format_spec) { if (-1 == _PyUnicodeWriter_WriteASCIIString(writer, ":", 1) || -1 == append_fstring_element(writer, e->v.FormattedValue.format_spec, @@ -1119,7 +1123,7 @@ append_ast_expr(_PyUnicodeWriter *writer, expr_ty e, bool omit_parens) } static int -maybe_init_static_strings() +maybe_init_static_strings(void) { if (!_str_open_br && !(_str_open_br = PyUnicode_InternFromString("{"))) { From webhook-mailer at python.org Thu Feb 1 12:59:37 2018 From: webhook-mailer at python.org (Andrew Svetlov) Date: Thu, 01 Feb 2018 17:59:37 -0000 Subject: [Python-checkins] Implement TimerHandle.when() (#5473) Message-ID: https://github.com/python/cpython/commit/3d4dbd8f019c0bbac99fc9248077044ff1039ca3 commit: 3d4dbd8f019c0bbac99fc9248077044ff1039ca3 branch: master author: Andrew Svetlov committer: GitHub date: 2018-02-01T19:59:32+02:00 summary: Implement TimerHandle.when() (#5473) files: A Misc/NEWS.d/next/Library/2018-02-01-17-54-08.bpo-32741.KUvOPL.rst M Doc/library/asyncio-eventloop.rst M Lib/asyncio/events.py M Lib/test/test_asyncio/test_events.py diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index 5f915c5c4392..a19c670d0f30 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -171,7 +171,7 @@ a different clock than :func:`time.time`. Arrange for the *callback* to be called after the given *delay* seconds (either an int or float). - An instance of :class:`asyncio.Handle` is returned, which can be + An instance of :class:`asyncio.TimerHandle` is returned, which can be used to cancel the callback. *callback* will be called exactly once per call to :meth:`call_later`. @@ -193,7 +193,7 @@ a different clock than :func:`time.time`. This method's behavior is the same as :meth:`call_later`. - An instance of :class:`asyncio.Handle` is returned, which can be + An instance of :class:`asyncio.TimerHandle` is returned, which can be used to cancel the callback. :ref:`Use functools.partial to pass keywords to the callback @@ -1076,8 +1076,7 @@ Handle .. class:: Handle A callback wrapper object returned by :func:`AbstractEventLoop.call_soon`, - :func:`AbstractEventLoop.call_soon_threadsafe`, :func:`AbstractEventLoop.call_later`, - and :func:`AbstractEventLoop.call_at`. + :func:`AbstractEventLoop.call_soon_threadsafe`. .. method:: cancel() @@ -1090,6 +1089,22 @@ Handle .. versionadded:: 3.7 +.. class:: TimerHandle + + A callback wrapper object returned by :func:`AbstractEventLoop.call_later`, + and :func:`AbstractEventLoop.call_at`. + + The class is inherited from :class:`Handle`. + + .. method:: when() + + Return a scheduled callback time as :class:`float` seconds. + + The time is an absolute timestamp, using the same time + reference as :meth:`AbstractEventLoop.time`. + + .. versionadded:: 3.7 + SendfileNotAvailableError ------------------------- diff --git a/Lib/asyncio/events.py b/Lib/asyncio/events.py index bdefcf62a05d..fcca5d4cb347 100644 --- a/Lib/asyncio/events.py +++ b/Lib/asyncio/events.py @@ -156,6 +156,14 @@ def cancel(self): self._loop._timer_handle_cancelled(self) super().cancel() + def when(self): + """Return a scheduled callback time. + + The time is an absolute timestamp, using the same time + reference as loop.time(). + """ + return self._when + class AbstractServer: """Abstract server returned by create_server().""" diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index f54802cf8af2..f5995974c683 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -2679,6 +2679,12 @@ def test_hash(self): mock.Mock()) self.assertEqual(hash(h), hash(when)) + def test_when(self): + when = time.monotonic() + h = asyncio.TimerHandle(when, lambda: False, (), + mock.Mock()) + self.assertEqual(when, h.when()) + def test_timer(self): def callback(*args): return args diff --git a/Misc/NEWS.d/next/Library/2018-02-01-17-54-08.bpo-32741.KUvOPL.rst b/Misc/NEWS.d/next/Library/2018-02-01-17-54-08.bpo-32741.KUvOPL.rst new file mode 100644 index 000000000000..651e7666157a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-01-17-54-08.bpo-32741.KUvOPL.rst @@ -0,0 +1 @@ +Implement ``asyncio.TimerHandle.when()`` method. From webhook-mailer at python.org Thu Feb 1 21:59:51 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Fri, 02 Feb 2018 02:59:51 -0000 Subject: [Python-checkins] Fix typo in hamt.c comments (#5478) Message-ID: https://github.com/python/cpython/commit/01a0cb891694cf73b86f799c48d8c78de1b8f74c commit: 01a0cb891694cf73b86f799c48d8c78de1b8f74c branch: master author: Dmitry Alimov committer: Yury Selivanov date: 2018-02-01T21:59:48-05:00 summary: Fix typo in hamt.c comments (#5478) files: M Python/hamt.c diff --git a/Python/hamt.c b/Python/hamt.c index 38f76d11e3eb..8998dbd76d2e 100644 --- a/Python/hamt.c +++ b/Python/hamt.c @@ -1476,7 +1476,7 @@ hamt_node_collision_without(PyHamtNode_Collision *self, if (new_count == 1) { /* The node has two keys, and after deletion the new Collision node would have one. Collision nodes - with one key shouldn't exist, co convert it to a + with one key shouldn't exist, so convert it to a Bitmap node. */ PyHamtNode_Bitmap *node = (PyHamtNode_Bitmap *) From webhook-mailer at python.org Thu Feb 1 22:24:59 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Fri, 02 Feb 2018 03:24:59 -0000 Subject: [Python-checkins] bpo-32436: Fix compiler warning (#5483) Message-ID: https://github.com/python/cpython/commit/55e0839f2672e029c2b96514028c77c31ffbe41f commit: 55e0839f2672e029c2b96514028c77c31ffbe41f branch: master author: Yury Selivanov committer: GitHub date: 2018-02-01T22:24:56-05:00 summary: bpo-32436: Fix compiler warning (#5483) files: M Python/hamt.c diff --git a/Python/hamt.c b/Python/hamt.c index 8998dbd76d2e..c9acbbcc5acc 100644 --- a/Python/hamt.c +++ b/Python/hamt.c @@ -2358,6 +2358,8 @@ _PyHamt_Without(PyHamtObject *o, PyObject *key) Py_INCREF(o); return o; case W_NEWNODE: { + assert(new_root != NULL); + PyHamtObject *new_o = hamt_alloc(); if (new_o == NULL) { Py_DECREF(new_root); From webhook-mailer at python.org Thu Feb 1 23:20:03 2018 From: webhook-mailer at python.org (Mariatta) Date: Fri, 02 Feb 2018 04:20:03 -0000 Subject: [Python-checkins] bpo-32674: Improve the docstring for __import__ (GH-5339) Message-ID: https://github.com/python/cpython/commit/461d225b195eec5269f317323b41115516144c41 commit: 461d225b195eec5269f317323b41115516144c41 branch: master author: oldk committer: Mariatta date: 2018-02-01T23:20:00-05:00 summary: bpo-32674: Improve the docstring for __import__ (GH-5339) Clarify that the level argument is used to determine whether to perform absolute or relative imports: 0 is absolute, while a positive number is the number of parent directories to search relative to the current module. files: M Python/bltinmodule.c diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index d8971bef2aeb..94f290853ccf 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -317,7 +317,7 @@ PyDoc_STRVAR(import_doc, "__import__(name, globals=None, locals=None, fromlist=(), level=0) -> module\n\ \n\ Import a module. Because this function is meant for use by the Python\n\ -interpreter and not for general use it is better to use\n\ +interpreter and not for general use, it is better to use\n\ importlib.import_module() to programmatically import a module.\n\ \n\ The globals argument is only used to determine the context;\n\ @@ -326,8 +326,8 @@ should be a list of names to emulate ``from name import ...'', or an\n\ empty list to emulate ``import name''.\n\ When importing a module from a package, note that __import__('A.B', ...)\n\ returns package A when fromlist is empty, but its submodule B when\n\ -fromlist is not empty. Level is used to determine whether to perform \n\ -absolute or relative imports. 0 is absolute while a positive number\n\ +fromlist is not empty. The level argument is used to determine whether to\n\ +perform absolute or relative imports: 0 is absolute, while a positive number\n\ is the number of parent directories to search relative to the current module."); From webhook-mailer at python.org Thu Feb 1 23:56:06 2018 From: webhook-mailer at python.org (Nathaniel J. Smith) Date: Fri, 02 Feb 2018 04:56:06 -0000 Subject: [Python-checkins] bpo-32733: Make test_coroutines robust against -Werror (GH-5487) Message-ID: https://github.com/python/cpython/commit/2efb9735899c7c642f3e75a121af82b1679577d3 commit: 2efb9735899c7c642f3e75a121af82b1679577d3 branch: master author: Nathaniel J. Smith committer: GitHub date: 2018-02-01T20:55:55-08:00 summary: bpo-32733: Make test_coroutines robust against -Werror (GH-5487) files: M Lib/test/test_coroutines.py diff --git a/Lib/test/test_coroutines.py b/Lib/test/test_coroutines.py index f3d77192ae76..b37b61b71959 100644 --- a/Lib/test/test_coroutines.py +++ b/Lib/test/test_coroutines.py @@ -2152,15 +2152,10 @@ def a2(): def check(depth, msg): sys.set_coroutine_origin_tracking_depth(depth) - with warnings.catch_warnings(record=True) as wlist: + with self.assertWarns(RuntimeWarning) as cm: a2() support.gc_collect() - # This might be fragile if other warnings somehow get triggered - # inside our 'with' block... let's worry about that if/when it - # happens. - self.assertTrue(len(wlist) == 1) - self.assertIs(wlist[0].category, RuntimeWarning) - self.assertEqual(msg, str(wlist[0].message)) + self.assertEqual(msg, str(cm.warning)) orig_depth = sys.get_coroutine_origin_tracking_depth() try: From webhook-mailer at python.org Fri Feb 2 03:52:59 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Fri, 02 Feb 2018 08:52:59 -0000 Subject: [Python-checkins] bpo-32747: Remove trailing spaces in docstrings. (GH-5491) Message-ID: https://github.com/python/cpython/commit/aa0735f597b072c0eb00404c4d7df359ddc26755 commit: aa0735f597b072c0eb00404c4d7df359ddc26755 branch: master author: oldk committer: Serhiy Storchaka date: 2018-02-02T10:52:55+02:00 summary: bpo-32747: Remove trailing spaces in docstrings. (GH-5491) files: M Modules/_csv.c M Modules/_threadmodule.c M Modules/arraymodule.c M Modules/fcntlmodule.c M Modules/itertoolsmodule.c M Modules/posixmodule.c M Modules/selectmodule.c M Modules/socketmodule.c M Objects/odictobject.c M Objects/unicodeobject.c M PC/winreg.c M Python/sysmodule.c diff --git a/Modules/_csv.c b/Modules/_csv.c index e616151bae63..610f7bb06325 100644 --- a/Modules/_csv.c +++ b/Modules/_csv.c @@ -1523,15 +1523,15 @@ PyDoc_STRVAR(csv_module_doc, "\n" "SETTINGS:\n" "\n" -" * quotechar - specifies a one-character string to use as the \n" +" * quotechar - specifies a one-character string to use as the\n" " quoting character. It defaults to '\"'.\n" -" * delimiter - specifies a one-character string to use as the \n" +" * delimiter - specifies a one-character string to use as the\n" " field separator. It defaults to ','.\n" " * skipinitialspace - specifies how to interpret whitespace which\n" " immediately follows a delimiter. It defaults to False, which\n" " means that whitespace immediately following a delimiter is part\n" " of the following field.\n" -" * lineterminator - specifies the character sequence which should \n" +" * lineterminator - specifies the character sequence which should\n" " terminate rows.\n" " * quoting - controls when quotes should be generated by the writer.\n" " It can take on any of the following module constants:\n" @@ -1543,7 +1543,7 @@ PyDoc_STRVAR(csv_module_doc, " fields which do not parse as integers or floating point\n" " numbers.\n" " csv.QUOTE_NONE means that quotes are never placed around fields.\n" -" * escapechar - specifies a one-character string used to escape \n" +" * escapechar - specifies a one-character string used to escape\n" " the delimiter when quoting is set to QUOTE_NONE.\n" " * doublequote - controls the handling of quotes inside fields. When\n" " True, two consecutive quotes are interpreted as one during read,\n" diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c index f594bda678a8..43898d838bea 100644 --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -1162,7 +1162,7 @@ PyDoc_STRVAR(_count_doc, "_count() -> integer\n\ \n\ \ -Return the number of currently running Python threads, excluding \n\ +Return the number of currently running Python threads, excluding\n\ the main thread. The returned number comprises all threads created\n\ through `start_new_thread()` as well as `threading.Thread`, and not\n\ yet finished.\n\ diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index 900c374c585e..6a9ff3ec6252 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -2772,26 +2772,26 @@ the type of objects stored in them is constrained. The type is specified\n\ at object creation time by using a type code, which is a single character.\n\ The following type codes are defined:\n\ \n\ - Type code C Type Minimum size in bytes \n\ - 'b' signed integer 1 \n\ - 'B' unsigned integer 1 \n\ - 'u' Unicode character 2 (see note) \n\ - 'h' signed integer 2 \n\ - 'H' unsigned integer 2 \n\ - 'i' signed integer 2 \n\ - 'I' unsigned integer 2 \n\ - 'l' signed integer 4 \n\ - 'L' unsigned integer 4 \n\ - 'q' signed integer 8 (see note) \n\ - 'Q' unsigned integer 8 (see note) \n\ - 'f' floating point 4 \n\ - 'd' floating point 8 \n\ + Type code C Type Minimum size in bytes\n\ + 'b' signed integer 1\n\ + 'B' unsigned integer 1\n\ + 'u' Unicode character 2 (see note)\n\ + 'h' signed integer 2\n\ + 'H' unsigned integer 2\n\ + 'i' signed integer 2\n\ + 'I' unsigned integer 2\n\ + 'l' signed integer 4\n\ + 'L' unsigned integer 4\n\ + 'q' signed integer 8 (see note)\n\ + 'Q' unsigned integer 8 (see note)\n\ + 'f' floating point 4\n\ + 'd' floating point 8\n\ \n\ -NOTE: The 'u' typecode corresponds to Python's unicode character. On \n\ +NOTE: The 'u' typecode corresponds to Python's unicode character. On\n\ narrow builds this is 2-bytes on wide builds this is 4-bytes.\n\ \n\ -NOTE: The 'q' and 'Q' type codes are only available if the platform \n\ -C compiler used to build Python supports 'long long', or, on Windows, \n\ +NOTE: The 'q' and 'Q' type codes are only available if the platform\n\ +C compiler used to build Python supports 'long long', or, on Windows,\n\ '__int64'.\n\ \n\ Methods:\n\ diff --git a/Modules/fcntlmodule.c b/Modules/fcntlmodule.c index 0baaa83d2aca..77ddebf3ee0d 100644 --- a/Modules/fcntlmodule.c +++ b/Modules/fcntlmodule.c @@ -430,7 +430,7 @@ static PyMethodDef fcntl_methods[] = { PyDoc_STRVAR(module_doc, -"This module performs file control and I/O control on file \n\ +"This module performs file control and I/O control on file\n\ descriptors. It is an interface to the fcntl() and ioctl() Unix\n\ routines. File descriptors can be obtained with the fileno() method of\n\ a file or socket object."); diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index 1113fb6b76c0..e0810c85c12b 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -1358,7 +1358,7 @@ static PyMethodDef takewhile_reduce_methods[] = { PyDoc_STRVAR(takewhile_doc, "takewhile(predicate, iterable) --> takewhile object\n\ \n\ -Return successive entries from an iterable as long as the \n\ +Return successive entries from an iterable as long as the\n\ predicate evaluates to true for each entry."); static PyTypeObject takewhile_type = { @@ -1616,7 +1616,7 @@ islice(iterable, start, stop[, step]) --> islice object\n\ Return an iterator whose next() method returns selected values from an\n\ iterable. If start is specified, will skip all preceding elements;\n\ otherwise, start defaults to zero. Step defaults to one. If\n\ -specified as another value, step determines how many values are \n\ +specified as another value, step determines how many values are\n\ skipped between successive calls. Works like a slice() on a list\n\ but returns an iterator."); @@ -4613,8 +4613,8 @@ repeat(elem [,n]) --> elem, elem, elem, ... endlessly or up to n times\n\ \n\ Iterators terminating on the shortest input sequence:\n\ accumulate(p[, func]) --> p0, p0+p1, p0+p1+p2\n\ -chain(p, q, ...) --> p0, p1, ... plast, q0, q1, ... \n\ -chain.from_iterable([p, q, ...]) --> p0, p1, ... plast, q0, q1, ... \n\ +chain(p, q, ...) --> p0, p1, ... plast, q0, q1, ...\n\ +chain.from_iterable([p, q, ...]) --> p0, p1, ... plast, q0, q1, ...\n\ compress(data, selectors) --> (d[0] if s[0]), (d[1] if s[1]), ...\n\ dropwhile(pred, seq) --> seq[n], seq[n+1], starting when pred fails\n\ groupby(iterable[, keyfunc]) --> sub-iterators grouped by value of keyfunc(v)\n\ @@ -4624,7 +4624,7 @@ islice(seq, [start,] stop [, step]) --> elements from\n\ starmap(fun, seq) --> fun(*seq[0]), fun(*seq[1]), ...\n\ tee(it, n=2) --> (it1, it2 , ... itn) splits one iterator into n\n\ takewhile(pred, seq) --> seq[0], seq[1], until pred fails\n\ -zip_longest(p, q, ...) --> (p[0], q[0]), (p[1], q[1]), ... \n\ +zip_longest(p, q, ...) --> (p[0], q[0]), (p[1], q[1]), ...\n\ \n\ Combinatoric generators:\n\ product(p, q, ... [repeat=1]) --> cartesian product\n\ diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 4a1c9f398a07..84b5b993cdfc 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -11472,7 +11472,7 @@ PyDoc_STRVAR(termsize__doc__, "This function will only be defined if an implementation is\n" \ "available for this system.\n" \ "\n" \ - "shutil.get_terminal_size is the high-level function which should \n" \ + "shutil.get_terminal_size is the high-level function which should\n" \ "normally be used, os.get_terminal_size is the low-level implementation."); static PyObject* diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c index 3b7713abab36..fe2968af8091 100644 --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -516,7 +516,7 @@ poll_unregister(pollObject *self, PyObject *o) PyDoc_STRVAR(poll_poll_doc, "poll( [timeout] ) -> list of (fd, event) 2-tuples\n\n\ -Polls the set of registered file descriptors, returning a list containing \n\ +Polls the set of registered file descriptors, returning a list containing\n\ any descriptors that have events or errors to report."); static PyObject * @@ -877,7 +877,7 @@ devpoll_unregister(devpollObject *self, PyObject *o) PyDoc_STRVAR(devpoll_poll_doc, "poll( [timeout] ) -> list of (fd, event) 2-tuples\n\n\ -Polls the set of registered file descriptors, returning a list containing \n\ +Polls the set of registered file descriptors, returning a list containing\n\ any descriptors that have events or errors to report."); static PyObject * diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 8cc5d14cbb20..ab3465a95f09 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -2661,8 +2661,8 @@ sock_gettimeout(PySocketSockObject *s) PyDoc_STRVAR(gettimeout_doc, "gettimeout() -> timeout\n\ \n\ -Returns the timeout in seconds (float) associated with socket \n\ -operations. A timeout of None indicates that timeouts on socket \n\ +Returns the timeout in seconds (float) associated with socket\n\ +operations. A timeout of None indicates that timeouts on socket\n\ operations are disabled."); /* s.setsockopt() method. @@ -2752,7 +2752,7 @@ setsockopt(level, option, value: buffer)\n\ setsockopt(level, option, None, optlen: int)\n\ \n\ Set a socket option. See the Unix manual for level and option.\n\ -The value argument can either be an integer, a string buffer, or \n\ +The value argument can either be an integer, a string buffer, or\n\ None, optlen."); @@ -3310,8 +3310,8 @@ sock_recv_into(PySocketSockObject *s, PyObject *args, PyObject *kwds) PyDoc_STRVAR(recv_into_doc, "recv_into(buffer, [nbytes[, flags]]) -> nbytes_read\n\ \n\ -A version of recv() that stores its data into a buffer rather than creating \n\ -a new string. Receive up to buffersize bytes from the socket. If buffersize \n\ +A version of recv() that stores its data into a buffer rather than creating\n\ +a new string. Receive up to buffersize bytes from the socket. If buffersize\n\ is not specified (or 0), receive up to the size available in the given buffer.\n\ \n\ See recv() for documentation about the flags."); @@ -5772,7 +5772,7 @@ Convert a 16-bit unsigned integer from network to host byte order.\n\ Note that in case the received integer does not fit in 16-bit unsigned\n\ integer, but does fit in a positive C int, it is silently truncated to\n\ 16-bit unsigned integer.\n\ -However, this silent truncation feature is deprecated, and will raise an \n\ +However, this silent truncation feature is deprecated, and will raise an\n\ exception in future versions of Python."); @@ -5843,7 +5843,7 @@ Convert a 16-bit unsigned integer from host to network byte order.\n\ Note that in case the received integer does not fit in 16-bit unsigned\n\ integer, but does fit in a positive C int, it is silently truncated to\n\ 16-bit unsigned integer.\n\ -However, this silent truncation feature is deprecated, and will raise an \n\ +However, this silent truncation feature is deprecated, and will raise an\n\ exception in future versions of Python."); diff --git a/Objects/odictobject.c b/Objects/odictobject.c index bf19fedb07f5..1796b968bfdd 100644 --- a/Objects/odictobject.c +++ b/Objects/odictobject.c @@ -866,7 +866,7 @@ PyDoc_STRVAR(odict_delitem__doc__, "od.__delitem__(y) <==> del od[y]"); /* __eq__() */ PyDoc_STRVAR(odict_eq__doc__, -"od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive \n\ +"od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive\n\ while comparison to a regular mapping is order-insensitive.\n\ "); diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 3d9e09d7fab1..f5e4ab62a333 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -11595,7 +11595,7 @@ unicode_hash(PyObject *self) PyDoc_STRVAR(index__doc__, "S.index(sub[, start[, end]]) -> int\n\ \n\ -Return the lowest index in S where substring sub is found, \n\ +Return the lowest index in S where substring sub is found,\n\ such that sub is contained within S[start:end]. Optional\n\ arguments start and end are interpreted as in slice notation.\n\ \n\ diff --git a/PC/winreg.c b/PC/winreg.c index ddaf3b1abc92..78864b1a69cf 100644 --- a/PC/winreg.c +++ b/PC/winreg.c @@ -83,7 +83,7 @@ PyDoc_STRVAR(PyHKEY_doc, "the object is destroyed. To guarantee cleanup, you can call either\n" "the Close() method on the PyHKEY, or the CloseKey() method.\n" "\n" -"All functions which accept a handle object also accept an integer - \n" +"All functions which accept a handle object also accept an integer --\n" "however, use of the handle object is encouraged.\n" "\n" "Functions:\n" diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 873657f4a4f1..fb1dcfa3afe8 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -365,7 +365,7 @@ sys_getdefaultencoding(PyObject *self) PyDoc_STRVAR(getdefaultencoding_doc, "getdefaultencoding() -> string\n\ \n\ -Return the current default string encoding used by the Unicode \n\ +Return the current default string encoding used by the Unicode\n\ implementation." ); @@ -1122,7 +1122,7 @@ PyDoc_STRVAR(enablelegacywindowsfsencoding_doc, Changes the default filesystem encoding to mbcs:replace for consistency\n\ with earlier versions of Python. See PEP 529 for more information.\n\ \n\ -This is equivalent to defining the PYTHONLEGACYWINDOWSFSENCODING \n\ +This is equivalent to defining the PYTHONLEGACYWINDOWSFSENCODING\n\ environment variable before launching Python." ); @@ -1812,7 +1812,7 @@ winver -- [Windows only] version number of the Python DLL\n\ #ifdef MS_WINDOWS /* concatenating string here */ PyDoc_STR( -"_enablelegacywindowsfsencoding -- [Windows only] \n\ +"_enablelegacywindowsfsencoding -- [Windows only]\n\ " ) #endif From solipsis at pitrou.net Fri Feb 2 04:10:35 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 02 Feb 2018 09:10:35 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=13 Message-ID: <20180202091035.1.AB0F6471905A0C72@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, 0, -1] memory blocks, sum=1 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/reflogQZd4oM', '--timeout', '7200'] From webhook-mailer at python.org Fri Feb 2 09:29:10 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Fri, 02 Feb 2018 14:29:10 -0000 Subject: [Python-checkins] [2.7] bpo-32137: The repr of deeply nested dict now raises a RuntimeError (GH-4570) (#5493) Message-ID: https://github.com/python/cpython/commit/b7a2c17be8411bc4c7a2babdc650074c14204aa8 commit: b7a2c17be8411bc4c7a2babdc650074c14204aa8 branch: 2.7 author: Serhiy Storchaka committer: GitHub date: 2018-02-02T16:29:02+02:00 summary: [2.7] bpo-32137: The repr of deeply nested dict now raises a RuntimeError (GH-4570) (#5493) instead of crashing due to a stack overflow. This perhaps will fix similar problems in other extension types. (cherry picked from commit 1fb72d2ad243c965d4432b4e93884064001a2607) files: A Misc/NEWS.d/next/Core and Builtins/2017-11-26-14-36-30.bpo-32137.Stj5nL.rst M Lib/test/list_tests.py M Lib/test/mapping_tests.py M Lib/test/test_dict.py M Objects/listobject.c M Objects/object.c M Objects/tupleobject.c diff --git a/Lib/test/list_tests.py b/Lib/test/list_tests.py index ed606db0d11d..54cfb97ccb8e 100644 --- a/Lib/test/list_tests.py +++ b/Lib/test/list_tests.py @@ -45,10 +45,11 @@ def test_repr(self): self.assertEqual(str(a2), "[0, 1, 2, [...], 3]") self.assertEqual(repr(a2), "[0, 1, 2, [...], 3]") - l0 = [] - for i in xrange(sys.getrecursionlimit() + 100): - l0 = [l0] - self.assertRaises(RuntimeError, repr, l0) + def test_repr_deep(self): + a = self.type2test([]) + for i in range(sys.getrecursionlimit() + 100): + a = self.type2test([a]) + self.assertRaises(RuntimeError, repr, a) def test_print(self): d = self.type2test(xrange(200)) diff --git a/Lib/test/mapping_tests.py b/Lib/test/mapping_tests.py index f43750bb83f6..248dee2fed18 100644 --- a/Lib/test/mapping_tests.py +++ b/Lib/test/mapping_tests.py @@ -2,6 +2,7 @@ import unittest import UserDict import test_support +import sys class BasicTestMappingProtocol(unittest.TestCase): @@ -645,6 +646,14 @@ def __repr__(self): d = self._full_mapping({1: BadRepr()}) self.assertRaises(Exc, repr, d) + def test_repr_deep(self): + d = self._empty_mapping() + for i in range(sys.getrecursionlimit() + 100): + d0 = d + d = self._empty_mapping() + d[1] = d0 + self.assertRaises(RuntimeError, repr, d) + def test_le(self): self.assertTrue(not (self._empty_mapping() < self._empty_mapping())) self.assertTrue(not (self._full_mapping({1: 2}) < self._full_mapping({1L: 2L}))) diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py index 6b2db34ef331..aacd4739ef3b 100644 --- a/Lib/test/test_dict.py +++ b/Lib/test/test_dict.py @@ -3,6 +3,7 @@ import UserDict, random, string import gc, weakref +import sys class DictTest(unittest.TestCase): @@ -422,6 +423,12 @@ def __repr__(self): d = {1: BadRepr()} self.assertRaises(Exc, repr, d) + def test_repr_deep(self): + d = {} + for i in range(sys.getrecursionlimit() + 100): + d = {1: d} + self.assertRaises(RuntimeError, repr, d) + def test_le(self): self.assertFalse({} < {}) self.assertFalse({1: 2} < {1L: 2L}) diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-11-26-14-36-30.bpo-32137.Stj5nL.rst b/Misc/NEWS.d/next/Core and Builtins/2017-11-26-14-36-30.bpo-32137.Stj5nL.rst new file mode 100644 index 000000000000..f8f4ab93c9e2 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-11-26-14-36-30.bpo-32137.Stj5nL.rst @@ -0,0 +1,2 @@ +The repr of deeply nested dict now raises a RecursionError instead of +crashing due to a stack overflow. diff --git a/Objects/listobject.c b/Objects/listobject.c index bb65e98714ee..24eff769c64e 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -383,10 +383,7 @@ list_repr(PyListObject *v) so must refetch the list size on each iteration. */ for (i = 0; i < Py_SIZE(v); ++i) { int status; - if (Py_EnterRecursiveCall(" while getting the repr of a list")) - goto Done; s = PyObject_Repr(v->ob_item[i]); - Py_LeaveRecursiveCall(); if (s == NULL) goto Done; status = PyList_Append(pieces, s); diff --git a/Objects/object.c b/Objects/object.c index 7a2821897999..65366b0b351b 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -378,7 +378,12 @@ PyObject_Repr(PyObject *v) Py_TYPE(v)->tp_name, v); else { PyObject *res; + /* It is possible for a type to have a tp_repr representation that + loops infinitely. */ + if (Py_EnterRecursiveCall(" while getting the repr of an object")) + return NULL; res = (*Py_TYPE(v)->tp_repr)(v); + Py_LeaveRecursiveCall(); if (res == NULL) return NULL; #ifdef Py_USING_UNICODE diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index a61c8aa013b4..6f4b18cc5c65 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -288,10 +288,7 @@ tuplerepr(PyTupleObject *v) /* Do repr() on each element. */ for (i = 0; i < n; ++i) { - if (Py_EnterRecursiveCall(" while getting the repr of a tuple")) - goto Done; s = PyObject_Repr(v->ob_item[i]); - Py_LeaveRecursiveCall(); if (s == NULL) goto Done; PyTuple_SET_ITEM(pieces, i, s); From webhook-mailer at python.org Fri Feb 2 09:31:09 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Fri, 02 Feb 2018 14:31:09 -0000 Subject: [Python-checkins] Revert "bpo-31356: Add context manager to temporarily disable GC GH-5495 Message-ID: https://github.com/python/cpython/commit/383b32fe108ea627699cc9c644fba5f8bae95d73 commit: 383b32fe108ea627699cc9c644fba5f8bae95d73 branch: master author: Yury Selivanov committer: GitHub date: 2018-02-02T09:31:06-05:00 summary: Revert "bpo-31356: Add context manager to temporarily disable GC GH-5495 This reverts commit 72a0d218dcc94a3cc409a9ef32dfcd5a7bbcb43c. The reverted commit had a few issues so it was unanimously decided to undo it. See the bpo issue for details. files: A Misc/NEWS.d/next/Core and Builtins/2018-02-02-08-50-46.bpo-31356.MNwUOQ.rst M Doc/library/gc.rst M Include/internal/mem.h M Lib/test/test_gc.py M Misc/NEWS.d/3.7.0b1.rst M Modules/gcmodule.c diff --git a/Doc/library/gc.rst b/Doc/library/gc.rst index 92240c760677..153d8fb70456 100644 --- a/Doc/library/gc.rst +++ b/Doc/library/gc.rst @@ -33,34 +33,6 @@ The :mod:`gc` module provides the following functions: Disable automatic garbage collection. -.. class:: ensure_disabled() - - Return a context manager object that disables the garbage collector and reenables the previous - state upon completion of the block. This is basically equivalent to:: - - from gc import enable, disable, isenabled - - @contextmanager - def ensure_disabled(): - was_enabled_previously = isenabled() - gc.disable() - yield - if was_enabled_previously: - gc.enable() - - And lets you write code like this:: - - with ensure_disabled(): - run_some_timing() - - with ensure_disabled(): - # do_something_that_has_real_time_guarantees - # such as a pair trade, robotic braking, etc - - without needing to explicitly enable and disable the garbage collector yourself. - This context manager is implemented in C to assure atomicity, thread safety and speed. - - .. function:: isenabled() Returns true if automatic collection is enabled. diff --git a/Include/internal/mem.h b/Include/internal/mem.h index 4a84b4a78d90..a731e30e6af7 100644 --- a/Include/internal/mem.h +++ b/Include/internal/mem.h @@ -116,7 +116,6 @@ struct _gc_runtime_state { int enabled; int debug; - long disabled_threads; /* linked lists of container objects */ struct gc_generation generations[NUM_GENERATIONS]; PyGC_Head *generation0; diff --git a/Lib/test/test_gc.py b/Lib/test/test_gc.py index 246980aa74c2..904fc7d88c03 100644 --- a/Lib/test/test_gc.py +++ b/Lib/test/test_gc.py @@ -1,7 +1,7 @@ import unittest from test.support import (verbose, refcount_test, run_unittest, strip_python_stderr, cpython_only, start_threads, - temp_dir, requires_type_collecting,reap_threads) + temp_dir, requires_type_collecting) from test.support.script_helper import assert_python_ok, make_script import sys @@ -9,8 +9,6 @@ import gc import weakref import threading -import warnings - try: from _testcapi import with_tp_del @@ -1009,73 +1007,6 @@ def __del__(self): # empty __dict__. self.assertEqual(x, None) - def test_ensure_disabled(self): - original_status = gc.isenabled() - - with gc.ensure_disabled(): - inside_status = gc.isenabled() - - after_status = gc.isenabled() - self.assertEqual(original_status, True) - self.assertEqual(inside_status, False) - self.assertEqual(after_status, True) - - def test_ensure_disabled_with_gc_disabled(self): - gc.disable() - - original_status = gc.isenabled() - - with gc.ensure_disabled(): - inside_status = gc.isenabled() - - after_status = gc.isenabled() - self.assertEqual(original_status, False) - self.assertEqual(inside_status, False) - self.assertEqual(after_status, False) - - @reap_threads - def test_ensure_disabled_thread(self): - - thread_original_status = None - thread_inside_status = None - thread_after_status = None - - def disabling_thread(): - nonlocal thread_original_status - nonlocal thread_inside_status - nonlocal thread_after_status - thread_original_status = gc.isenabled() - - with gc.ensure_disabled(): - time.sleep(0.01) - thread_inside_status = gc.isenabled() - - thread_after_status = gc.isenabled() - - original_status = gc.isenabled() - - with warnings.catch_warnings(record=True) as w, gc.ensure_disabled(): - inside_status_before_thread = gc.isenabled() - thread = threading.Thread(target=disabling_thread) - thread.start() - inside_status_after_thread = gc.isenabled() - - after_status = gc.isenabled() - thread.join() - - self.assertEqual(len(w), 1) - self.assertTrue(issubclass(w[-1].category, RuntimeWarning)) - self.assertEqual("Garbage collector enabled while another thread is " - "inside gc.ensure_enabled", str(w[-1].message)) - self.assertEqual(original_status, True) - self.assertEqual(inside_status_before_thread, False) - self.assertEqual(thread_original_status, False) - self.assertEqual(thread_inside_status, True) - self.assertEqual(thread_after_status, False) - self.assertEqual(inside_status_after_thread, False) - self.assertEqual(after_status, True) - - def test_main(): enabled = gc.isenabled() gc.disable() diff --git a/Misc/NEWS.d/3.7.0b1.rst b/Misc/NEWS.d/3.7.0b1.rst index 4f7bfee85cbb..bd3a6111df0b 100644 --- a/Misc/NEWS.d/3.7.0b1.rst +++ b/Misc/NEWS.d/3.7.0b1.rst @@ -196,17 +196,6 @@ by Sanyam Khurana. .. -.. bpo: 31356 -.. date: 2017-11-02-00-34-42 -.. nonce: 54Lb8U -.. section: Core and Builtins - -Add a new contextmanager to the gc module that temporarily disables the GC -and restores the previous state. The implementation is done in C to assure -atomicity and speed. - -.. - .. bpo: 31179 .. date: 2017-08-10-17-32-48 .. nonce: XcgLYI diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-02-02-08-50-46.bpo-31356.MNwUOQ.rst b/Misc/NEWS.d/next/Core and Builtins/2018-02-02-08-50-46.bpo-31356.MNwUOQ.rst new file mode 100644 index 000000000000..5022a1370609 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-02-02-08-50-46.bpo-31356.MNwUOQ.rst @@ -0,0 +1,2 @@ +Remove the new API added in bpo-31356 (gc.ensure_disabled() context +manager). diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index c057d25a12b0..8ba1093c029d 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -1067,10 +1067,6 @@ static PyObject * gc_enable_impl(PyObject *module) /*[clinic end generated code: output=45a427e9dce9155c input=81ac4940ca579707]*/ { - if(_PyRuntime.gc.disabled_threads){ - PyErr_WarnEx(PyExc_RuntimeWarning, "Garbage collector enabled while another " - "thread is inside gc.ensure_enabled",1); - } _PyRuntime.gc.enabled = 1; Py_RETURN_NONE; } @@ -1512,102 +1508,6 @@ static PyMethodDef GcMethods[] = { {NULL, NULL} /* Sentinel */ }; -typedef struct { - PyObject_HEAD - int previous_gc_state; -} ensure_disabled_object; - - -static void -ensure_disabled_object_dealloc(ensure_disabled_object *m_obj) -{ - Py_TYPE(m_obj)->tp_free((PyObject*)m_obj); -} - -static PyObject * -ensure_disabled__enter__method(ensure_disabled_object *self, PyObject *args) -{ - PyGILState_STATE gstate = PyGILState_Ensure(); - ++_PyRuntime.gc.disabled_threads; - self->previous_gc_state = _PyRuntime.gc.enabled; - gc_disable_impl(NULL); - PyGILState_Release(gstate); - Py_RETURN_NONE; -} - -static PyObject * -ensure_disabled__exit__method(ensure_disabled_object *self, PyObject *args) -{ - PyGILState_STATE gstate = PyGILState_Ensure(); - --_PyRuntime.gc.disabled_threads; - if(self->previous_gc_state){ - gc_enable_impl(NULL); - }else{ - gc_disable_impl(NULL); - } - PyGILState_Release(gstate); - Py_RETURN_NONE; -} - - - -static struct PyMethodDef ensure_disabled_object_methods[] = { - {"__enter__", (PyCFunction) ensure_disabled__enter__method, METH_NOARGS}, - {"__exit__", (PyCFunction) ensure_disabled__exit__method, METH_VARARGS}, - {NULL, NULL} /* sentinel */ -}; - -static PyObject * -new_disabled_obj(PyTypeObject *type, PyObject *args, PyObject *kwdict){ - ensure_disabled_object *self; - self = (ensure_disabled_object *)type->tp_alloc(type, 0); - return (PyObject *) self; -}; - -static PyTypeObject gc_ensure_disabled_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "gc.ensure_disabled", /* tp_name */ - sizeof(ensure_disabled_object), /* tp_size */ - 0, /* tp_itemsize */ - /* methods */ - (destructor) ensure_disabled_object_dealloc,/* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - PyObject_GenericGetAttr, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - 0, /*tp_doc*/ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - ensure_disabled_object_methods, /* 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 */ - PyType_GenericAlloc, /* tp_alloc */ - new_disabled_obj, /* tp_new */ - PyObject_Del, /* tp_free */ -}; - - static struct PyModuleDef gcmodule = { PyModuleDef_HEAD_INIT, "gc", /* m_name */ @@ -1648,12 +1548,6 @@ PyInit_gc(void) if (PyModule_AddObject(m, "callbacks", _PyRuntime.gc.callbacks) < 0) return NULL; - if (PyType_Ready(&gc_ensure_disabled_type) < 0) - return NULL; - if (PyModule_AddObject(m, "ensure_disabled", (PyObject*) &gc_ensure_disabled_type) < 0) - return NULL; - - #define ADD_INT(NAME) if (PyModule_AddIntConstant(m, #NAME, NAME) < 0) return NULL ADD_INT(DEBUG_STATS); ADD_INT(DEBUG_COLLECTABLE); From webhook-mailer at python.org Fri Feb 2 11:24:01 2018 From: webhook-mailer at python.org (Mariatta) Date: Fri, 02 Feb 2018 16:24:01 -0000 Subject: [Python-checkins] bpo-32674: Improve the docstring for __import__ (GH-5339) (GH-5494) Message-ID: https://github.com/python/cpython/commit/9b7b3a64560269188fcb43445becc5aacb4de2dc commit: 9b7b3a64560269188fcb43445becc5aacb4de2dc branch: 2.7 author: Mariatta committer: GitHub date: 2018-02-02T11:23:53-05:00 summary: bpo-32674: Improve the docstring for __import__ (GH-5339) (GH-5494) Clarify that the level argument is used to determine whether to perform absolute or relative imports: 0 is absolute, while a positive number is the number of parent directories to search relative to the current module.. (cherry picked from commit 461d225b195eec5269f317323b41115516144c41) Co-authored-by: oldk files: M Python/bltinmodule.c diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 0f2ee4ad1eb6..9ce3b275eab2 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -54,7 +54,7 @@ PyDoc_STRVAR(import_doc, "__import__(name, globals={}, locals={}, fromlist=[], level=-1) -> module\n\ \n\ Import a module. Because this function is meant for use by the Python\n\ -interpreter and not for general use it is better to use\n\ +interpreter and not for general use, it is better to use\n\ importlib.import_module() to programmatically import a module.\n\ \n\ The globals argument is only used to determine the context;\n\ @@ -63,9 +63,8 @@ should be a list of names to emulate ``from name import ...'', or an\n\ empty list to emulate ``import name''.\n\ When importing a module from a package, note that __import__('A.B', ...)\n\ returns package A when fromlist is empty, but its submodule B when\n\ -fromlist is not empty. Level is used to determine whether to perform \n\ -absolute or relative imports. -1 is the original strategy of attempting\n\ -both absolute and relative imports, 0 is absolute, a positive number\n\ +fromlist is not empty. The level argument is used to determine whether to\n\ +perform absolute or relative imports: 0 is absolute, while a positive number\n\ is the number of parent directories to search relative to the current module."); From webhook-mailer at python.org Fri Feb 2 15:16:01 2018 From: webhook-mailer at python.org (Barry Warsaw) Date: Fri, 02 Feb 2018 20:16:01 -0000 Subject: [Python-checkins] bpo-32303 - Consistency fixes for namespace loaders (#5481) Message-ID: https://github.com/python/cpython/commit/bbbcf8693b876daae4469765aa62f8924f39a7d2 commit: bbbcf8693b876daae4469765aa62f8924f39a7d2 branch: master author: Barry Warsaw committer: GitHub date: 2018-02-02T15:15:58-05:00 summary: bpo-32303 - Consistency fixes for namespace loaders (#5481) * Make sure ``__spec__.loader`` matches ``__loader__`` for namespace packages. * Make sure ``__spec__.origin` matches ``__file__`` for namespace packages. https://bugs.python.org/issue32303 https://bugs.python.org/issue32305 files: A Misc/NEWS.d/next/Core and Builtins/2018-02-01-10-16-28.bpo-32303.VsvhSl.rst A Misc/NEWS.d/next/Core and Builtins/2018-02-01-10-56-41.bpo-32305.dkU9Qa.rst M Doc/library/importlib.rst M Lib/importlib/_bootstrap.py M Lib/importlib/_bootstrap_external.py M Lib/importlib/resources.py M Lib/test/test_importlib/test_api.py M Lib/test/test_importlib/test_namespace_pkgs.py M Python/importlib.h M Python/importlib_external.h diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst index 5fa1d7d869dd..c80f4606f3d1 100644 --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -1291,7 +1291,7 @@ find and load modules. Name of the place from which the module is loaded, e.g. "builtin" for built-in modules and the filename for modules loaded from source. Normally "origin" should be set, but it may be ``None`` (the default) - which indicates it is unspecified. + which indicates it is unspecified (e.g. for namespace packages). .. attribute:: submodule_search_locations diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py index 5df6aa040a28..2bdd1929b42f 100644 --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -522,6 +522,18 @@ def _init_module_attrs(spec, module, *, override=False): loader = _NamespaceLoader.__new__(_NamespaceLoader) loader._path = spec.submodule_search_locations + spec.loader = loader + # While the docs say that module.__file__ is not set for + # built-in modules, and the code below will avoid setting it if + # spec.has_location is false, this is incorrect for namespace + # packages. Namespace packages have no location, but their + # __spec__.origin is None, and thus their module.__file__ + # should also be None for consistency. While a bit of a hack, + # this is the best place to ensure this consistency. + # + # See # https://docs.python.org/3/library/importlib.html#importlib.abc.Loader.load_module + # and bpo-32305 + module.__file__ = None try: module.__loader__ = loader except AttributeError: diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index d3f58af504d8..f9a708c29131 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -1276,9 +1276,9 @@ def find_spec(cls, fullname, path=None, target=None): elif spec.loader is None: namespace_path = spec.submodule_search_locations if namespace_path: - # We found at least one namespace path. Return a - # spec which can create the namespace package. - spec.origin = 'namespace' + # We found at least one namespace path. Return a spec which + # can create the namespace package. + spec.origin = None spec.submodule_search_locations = _NamespacePath(fullname, namespace_path, cls._get_spec) return spec else: diff --git a/Lib/importlib/resources.py b/Lib/importlib/resources.py index bf6d7035850c..c4f6bbde45fa 100644 --- a/Lib/importlib/resources.py +++ b/Lib/importlib/resources.py @@ -66,6 +66,11 @@ def _get_resource_reader( return None +def _check_location(package): + if package.__spec__.origin is None or not package.__spec__.has_location: + raise FileNotFoundError(f'Package has no location {package!r}') + + def open_binary(package: Package, resource: Resource) -> BinaryIO: """Return a file-like object opened for binary reading of the resource.""" resource = _normalize_path(resource) @@ -73,6 +78,7 @@ def open_binary(package: Package, resource: Resource) -> BinaryIO: reader = _get_resource_reader(package) if reader is not None: return reader.open_resource(resource) + _check_location(package) absolute_package_path = os.path.abspath(package.__spec__.origin) package_path = os.path.dirname(absolute_package_path) full_path = os.path.join(package_path, resource) @@ -106,6 +112,7 @@ def open_text(package: Package, reader = _get_resource_reader(package) if reader is not None: return TextIOWrapper(reader.open_resource(resource), encoding, errors) + _check_location(package) absolute_package_path = os.path.abspath(package.__spec__.origin) package_path = os.path.dirname(absolute_package_path) full_path = os.path.join(package_path, resource) @@ -172,6 +179,8 @@ def path(package: Package, resource: Resource) -> Iterator[Path]: return except FileNotFoundError: pass + else: + _check_location(package) # Fall-through for both the lack of resource_path() *and* if # resource_path() raises FileNotFoundError. package_directory = Path(package.__spec__.origin).parent @@ -232,9 +241,9 @@ def contents(package: Package) -> Iterator[str]: yield from reader.contents() return # Is the package a namespace package? By definition, namespace packages - # cannot have resources. - if (package.__spec__.origin == 'namespace' and - not package.__spec__.has_location): + # cannot have resources. We could use _check_location() and catch the + # exception, but that's extra work, so just inline the check. + if package.__spec__.origin is None or not package.__spec__.has_location: return [] package_directory = Path(package.__spec__.origin).parent yield from os.listdir(str(package_directory)) diff --git a/Lib/test/test_importlib/test_api.py b/Lib/test/test_importlib/test_api.py index 50dbfe1eda45..8beb4244eac8 100644 --- a/Lib/test/test_importlib/test_api.py +++ b/Lib/test/test_importlib/test_api.py @@ -305,6 +305,7 @@ def test_reload_namespace_changed(self): expected = {'__name__': name, '__package__': name, '__doc__': None, + '__file__': None, } os.mkdir(name) with open(bad_path, 'w') as init_file: @@ -316,8 +317,9 @@ def test_reload_namespace_changed(self): spec = ns.pop('__spec__') ns.pop('__builtins__', None) # An implementation detail. self.assertEqual(spec.name, name) - self.assertIs(spec.loader, None) - self.assertIsNot(loader, None) + self.assertIsNotNone(spec.loader) + self.assertIsNotNone(loader) + self.assertEqual(spec.loader, loader) self.assertEqual(set(path), set([os.path.dirname(bad_path)])) with self.assertRaises(AttributeError): diff --git a/Lib/test/test_importlib/test_namespace_pkgs.py b/Lib/test/test_importlib/test_namespace_pkgs.py index e37d8a18f4ac..8e4b5d66fecc 100644 --- a/Lib/test/test_importlib/test_namespace_pkgs.py +++ b/Lib/test/test_importlib/test_namespace_pkgs.py @@ -317,5 +317,21 @@ def test_dynamic_path(self): self.assertEqual(foo.two.attr, 'portion2 foo two') +class LoaderTests(NamespacePackageTest): + paths = ['portion1'] + + def test_namespace_loader_consistency(self): + # bpo-32303 + import foo + self.assertEqual(foo.__loader__, foo.__spec__.loader) + self.assertIsNotNone(foo.__loader__) + + def test_namespace_origin_consistency(self): + # bpo-32305 + import foo + self.assertIsNone(foo.__spec__.origin) + self.assertIsNone(foo.__file__) + + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-02-01-10-16-28.bpo-32303.VsvhSl.rst b/Misc/NEWS.d/next/Core and Builtins/2018-02-01-10-16-28.bpo-32303.VsvhSl.rst new file mode 100644 index 000000000000..b84448fb25a1 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-02-01-10-16-28.bpo-32303.VsvhSl.rst @@ -0,0 +1 @@ +Make sure ``__spec__.loader`` matches ``__loader__`` for namespace packages. diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-02-01-10-56-41.bpo-32305.dkU9Qa.rst b/Misc/NEWS.d/next/Core and Builtins/2018-02-01-10-56-41.bpo-32305.dkU9Qa.rst new file mode 100644 index 000000000000..204d74a49754 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-02-01-10-56-41.bpo-32305.dkU9Qa.rst @@ -0,0 +1,2 @@ +For namespace packages, ensure that both ``__file__`` and +``__spec__.origin`` are set to None. diff --git a/Python/importlib.h b/Python/importlib.h index 0636fdf0b34d..822ffa0c067e 100644 --- a/Python/importlib.h +++ b/Python/importlib.h @@ -860,963 +860,964 @@ const unsigned char _Py_M__importlib[] = { 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,212,1,0,0, + 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,166,124,0,106,4,125,3, - 124,3,100,0,107,8,114,134,124,0,106,5,100,0,107,9, - 114,134,116,6,100,0,107,8,114,110,116,7,130,1,116,6, + 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,121,10,124,3,124,1,95,11,87,0, - 110,20,4,0,116,3,107,10,114,164,1,0,1,0,1,0, - 89,0,110,2,88,0,124,2,115,186,116,0,124,1,100,3, - 100,0,131,3,100,0,107,8,114,220,121,12,124,0,106,12, - 124,1,95,13,87,0,110,20,4,0,116,3,107,10,114,218, - 1,0,1,0,1,0,89,0,110,2,88,0,121,10,124,0, - 124,1,95,14,87,0,110,20,4,0,116,3,107,10,114,250, - 1,0,1,0,1,0,89,0,110,2,88,0,124,2,144,1, - 115,20,116,0,124,1,100,4,100,0,131,3,100,0,107,8, - 144,1,114,68,124,0,106,5,100,0,107,9,144,1,114,68, - 121,12,124,0,106,5,124,1,95,15,87,0,110,22,4,0, - 116,3,107,10,144,1,114,66,1,0,1,0,1,0,89,0, - 110,2,88,0,124,0,106,16,144,1,114,208,124,2,144,1, - 115,100,116,0,124,1,100,5,100,0,131,3,100,0,107,8, - 144,1,114,136,121,12,124,0,106,17,124,1,95,18,87,0, - 110,22,4,0,116,3,107,10,144,1,114,134,1,0,1,0, - 1,0,89,0,110,2,88,0,124,2,144,1,115,160,116,0, - 124,1,100,6,100,0,131,3,100,0,107,8,144,1,114,208, - 124,0,106,19,100,0,107,9,144,1,114,208,121,12,124,0, - 106,19,124,1,95,20,87,0,110,22,4,0,116,3,107,10, - 144,1,114,206,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,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,92,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,92,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, - 2,1,10,1,14,1,6,2,20,1,2,1,12,1,14,1, - 6,2,2,1,10,1,14,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, + 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, - 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,52,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,69,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, - 86,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,110,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,139,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,162,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,186,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,195,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,204, - 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,216,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,224,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,229,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,235,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, + 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, - 105,0,0,0,241,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,177,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,3, - 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,12,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, + 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,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, - 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,19,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,28, - 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, - 32,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, + 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,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, + 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,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,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,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,41, - 3,0,0,115,2,0,0,0,0,7,122,26,70,114,111,122, - 101,110,73,109,112,111,114,116,101,114,46,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,50,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, + 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,148,0,0,0,56,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,62, - 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, + 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,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,114,151,0,0,0,250,2,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,75,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,79,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,71,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,84,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,93,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,102,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, + 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, - 13,95,115,97,110,105,116,121,95,99,104,101,99,107,149,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,168,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,198,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,214, - 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,229,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,11,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,38,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,73,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,80,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,115,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,123,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,60,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, + 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,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, }; diff --git a/Python/importlib_external.h b/Python/importlib_external.h index 6bf189d006ab..73376a02e97e 100644 --- a/Python/importlib_external.h +++ b/Python/importlib_external.h @@ -2115,10 +2115,10 @@ const unsigned char _Py_M__importlib_external[] = { 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,2,124,4,95, + 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,3,122,141,84,114,121,32,116,111,32,102,105, + 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, @@ -2127,485 +2127,484 @@ const unsigned char _Py_M__importlib_external[] = { 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,90,9,110,97,109,101,115,112,97,99,101, - 41,7,114,6,0,0,0,114,35,0,0,0,114,17,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,16,1,0,0,114,2,0,0,0,114,2,0,0,0,114, - 4,0,0,0,114,182,0,0,0,241,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,9, - 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,11,1,0,0,114,13,1,0,0,114,14,1,0, - 0,114,17,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,147,4,0,0,115,20,0, - 0,0,12,4,12,8,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,38,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,32,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,20,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,46,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,52,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, + 32,32,32,32,78,41,7,114,6,0,0,0,114,35,0,0, + 0,114,17,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,16,1,0,0,114,2,0,0,0,114, + 2,0,0,0,114,4,0,0,0,114,182,0,0,0,241,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, - 17,1,0,0,64,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,20,1,0,0,218,11,95,102, - 105,108,108,95,99,97,99,104,101,114,5,0,0,0,114,23, - 1,0,0,114,90,0,0,0,114,22,1,0,0,114,28,0, - 0,0,114,19,1,0,0,114,44,0,0,0,114,17,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,69,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,146,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,21,1,0,0,114,22,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,23,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,25,1,0,0,117,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,24,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,158,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,24,1, - 0,0,114,30,1,0,0,114,2,0,0,0,41,2,114,172, - 0,0,0,114,24,1,0,0,114,4,0,0,0,218,9,112, - 97,116,104,95,104,111,111,107,148,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,166,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, - 17,1,0,0,114,182,0,0,0,114,25,1,0,0,114,184, - 0,0,0,114,31,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,18,1,0,0,23,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,18,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, + 183,0,0,0,9,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,11,1,0,0,114,13,1,0, + 0,114,14,1,0,0,114,17,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,147,4, + 0,0,115,20,0,0,0,12,4,12,8,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,38,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,32,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, + 20,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,46, + 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,218,14,95,102,105,120,95,117,112, - 95,109,111,100,117,108,101,172,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,36,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,195,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,231,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,37,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,206,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,43,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,43,1,0,0,114, - 163,0,0,0,114,6,0,0,0,114,10,1,0,0,114,147, - 0,0,0,114,18,1,0,0,114,31,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,42,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,14,6,0,0,115,8,0,0,0,0,2, - 8,1,6,1,20,1,114,45,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,18,1,0,0,114,36,1,0,0,114,163,0,0,0,114, - 43,1,0,0,114,45,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,116,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, - 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,5,14,127,0,22,10,23, - 8,11,8,64, + 0,0,114,4,0,0,0,114,119,0,0,0,52,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,17,1,0,0,64,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,20,1,0, + 0,218,11,95,102,105,108,108,95,99,97,99,104,101,114,5, + 0,0,0,114,23,1,0,0,114,90,0,0,0,114,22,1, + 0,0,114,28,0,0,0,114,19,1,0,0,114,44,0,0, + 0,114,17,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,69,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,146,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,21,1,0, + 0,114,22,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, + 23,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,25,1,0,0,117,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,24,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,158, + 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,24,1,0,0,114,30,1,0,0,114,2,0,0, + 0,41,2,114,172,0,0,0,114,24,1,0,0,114,4,0, + 0,0,218,9,112,97,116,104,95,104,111,111,107,148,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,166,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,17,1,0,0,114,182,0,0,0,114,25, + 1,0,0,114,184,0,0,0,114,31,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,18,1,0,0,23,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,18,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,172,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,36,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,195,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,231,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,37, + 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,206,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,43, + 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, + 43,1,0,0,114,163,0,0,0,114,6,0,0,0,114,10, + 1,0,0,114,147,0,0,0,114,18,1,0,0,114,31,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,42,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,14,6,0,0,115,8, + 0,0,0,0,2,8,1,6,1,20,1,114,45,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,18,1,0,0,114,36,1,0,0,114, + 163,0,0,0,114,43,1,0,0,114,45,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,116,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,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,5,14, + 127,0,22,10,23,8,11,8,64, }; From webhook-mailer at python.org Fri Feb 2 16:16:36 2018 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Fri, 02 Feb 2018 21:16:36 -0000 Subject: [Python-checkins] bpo-32614: Modify re examples to use a raw string to prevent warning (GH-5265) Message-ID: https://github.com/python/cpython/commit/66771422d0541289d0b1287bc3c28e8b5609f6b4 commit: 66771422d0541289d0b1287bc3c28e8b5609f6b4 branch: master author: Cheryl Sabella committer: Terry Jan Reedy date: 2018-02-02T16:16:27-05:00 summary: bpo-32614: Modify re examples to use a raw string to prevent warning (GH-5265) Modify RE examples in documentation to use raw strings to prevent DeprecationWarning. Add text to REGEX HOWTO to highlight the deprecation. Approved by Serhiy Storchaka. files: A Misc/NEWS.d/next/Documentation/2018-02-02-07-41-57.bpo-32614.LSqzGw.rst M Doc/howto/regex.rst M Doc/howto/unicode.rst M Doc/library/re.rst diff --git a/Doc/howto/regex.rst b/Doc/howto/regex.rst index 87a6b1aba59f..bdf687ee4551 100644 --- a/Doc/howto/regex.rst +++ b/Doc/howto/regex.rst @@ -289,6 +289,8 @@ Putting REs in strings keeps the Python language simpler, but has one disadvantage which is the topic of the next section. +.. _the-backslash-plague: + The Backslash Plague -------------------- @@ -327,6 +329,13 @@ backslashes are not handled in any special way in a string literal prefixed with while ``"\n"`` is a one-character string containing a newline. Regular expressions will often be written in Python code using this raw string notation. +In addition, special escape sequences that are valid in regular expressions, +but not valid as Python string literals, now result in a +:exc:`DeprecationWarning` and will eventually become a :exc:`SyntaxError`, +which means the sequences will be invalid if raw string notation or escaping +the backslashes isn't used. + + +-------------------+------------------+ | Regular String | Raw string | +===================+==================+ @@ -457,10 +466,16 @@ In actual programs, the most common style is to store the Two pattern methods return all of the matches for a pattern. :meth:`~re.Pattern.findall` returns a list of matching strings:: - >>> p = re.compile('\d+') + >>> p = re.compile(r'\d+') >>> p.findall('12 drummers drumming, 11 pipers piping, 10 lords a-leaping') ['12', '11', '10'] +The ``r`` prefix, making the literal a raw string literal, is needed in this +example because escape sequences in a normal "cooked" string literal that are +not recognized by Python, as opposed to regular expressions, now result in a +:exc:`DeprecationWarning` and will eventually become a :exc:`SyntaxError`. See +:ref:`the-backslash-plague`. + :meth:`~re.Pattern.findall` has to create the entire list before it can be returned as the result. The :meth:`~re.Pattern.finditer` method returns a sequence of :ref:`match object ` instances as an :term:`iterator`:: @@ -1096,11 +1111,11 @@ following calls:: The module-level function :func:`re.split` adds the RE to be used as the first argument, but is otherwise the same. :: - >>> re.split('[\W]+', 'Words, words, words.') + >>> re.split(r'[\W]+', 'Words, words, words.') ['Words', 'words', 'words', ''] - >>> re.split('([\W]+)', 'Words, words, words.') + >>> re.split(r'([\W]+)', 'Words, words, words.') ['Words', ', ', 'words', ', ', 'words', '.', ''] - >>> re.split('[\W]+', 'Words, words, words.', 1) + >>> re.split(r'[\W]+', 'Words, words, words.', 1) ['Words', 'words, words.'] diff --git a/Doc/howto/unicode.rst b/Doc/howto/unicode.rst index d4b8f8d2204a..093f4454af1d 100644 --- a/Doc/howto/unicode.rst +++ b/Doc/howto/unicode.rst @@ -463,7 +463,7 @@ The string in this example has the number 57 written in both Thai and Arabic numerals:: import re - p = re.compile('\d+') + p = re.compile(r'\d+') s = "Over \u0e55\u0e57 57 flavours" m = p.search(s) diff --git a/Doc/library/re.rst b/Doc/library/re.rst index 9b175f4e9675..83ebe7db01ad 100644 --- a/Doc/library/re.rst +++ b/Doc/library/re.rst @@ -345,7 +345,7 @@ The special characters are: This example looks for a word following a hyphen: - >>> m = re.search('(?<=-)\w+', 'spam-egg') + >>> m = re.search(r'(?<=-)\w+', 'spam-egg') >>> m.group(0) 'egg' diff --git a/Misc/NEWS.d/next/Documentation/2018-02-02-07-41-57.bpo-32614.LSqzGw.rst b/Misc/NEWS.d/next/Documentation/2018-02-02-07-41-57.bpo-32614.LSqzGw.rst new file mode 100644 index 000000000000..9e9f3e3a74df --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2018-02-02-07-41-57.bpo-32614.LSqzGw.rst @@ -0,0 +1,3 @@ +Modify RE examples in documentation to use raw strings to prevent +:exc:`DeprecationWarning` and add text to REGEX HOWTO to highlight the +deprecation. From webhook-mailer at python.org Fri Feb 2 17:04:03 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Fri, 02 Feb 2018 22:04:03 -0000 Subject: [Python-checkins] bpo-32734: Fix asyncio.Lock multiple acquire safety issue (GH-5466) Message-ID: https://github.com/python/cpython/commit/2f79c014931cbb23b08a7d16c534a3cc9607ae14 commit: 2f79c014931cbb23b08a7d16c534a3cc9607ae14 branch: master author: Bar Harel committer: Yury Selivanov date: 2018-02-02T17:04:00-05:00 summary: bpo-32734: Fix asyncio.Lock multiple acquire safety issue (GH-5466) files: A Misc/NEWS.d/next/Library/2018-02-01-01-34-47.bpo-32734.gCV9AD.rst M Lib/asyncio/locks.py M Lib/test/test_asyncio/test_locks.py M Misc/ACKS diff --git a/Lib/asyncio/locks.py b/Lib/asyncio/locks.py index 619383735096..508a2142d842 100644 --- a/Lib/asyncio/locks.py +++ b/Lib/asyncio/locks.py @@ -183,16 +183,22 @@ def locked(self): fut = self._loop.create_future() self._waiters.append(fut) + + # Finally block should be called before the CancelledError + # handling as we don't want CancelledError to call + # _wake_up_first() and attempt to wake up itself. try: - await fut - self._locked = True - return True + try: + await fut + finally: + self._waiters.remove(fut) except futures.CancelledError: if not self._locked: self._wake_up_first() raise - finally: - self._waiters.remove(fut) + + self._locked = True + return True def release(self): """Release a lock. @@ -212,11 +218,17 @@ def release(self): raise RuntimeError('Lock is not acquired.') def _wake_up_first(self): - """Wake up the first waiter who isn't cancelled.""" - for fut in self._waiters: - if not fut.done(): - fut.set_result(True) - break + """Wake up the first waiter if it isn't done.""" + try: + fut = next(iter(self._waiters)) + except StopIteration: + return + + # .done() necessarily means that a waiter will wake up later on and + # either take the lock, or, if it was cancelled and lock wasn't + # taken already, will hit this again and wake up a new waiter. + if not fut.done(): + fut.set_result(True) class Event: diff --git a/Lib/test/test_asyncio/test_locks.py b/Lib/test/test_asyncio/test_locks.py index 3c5069778b50..3e3dd799273e 100644 --- a/Lib/test/test_asyncio/test_locks.py +++ b/Lib/test/test_asyncio/test_locks.py @@ -200,6 +200,56 @@ def test_cancel_race(self): self.assertTrue(tb.cancelled()) self.assertTrue(tc.done()) + def test_cancel_release_race(self): + # Issue 32734 + # Acquire 4 locks, cancel second, release first + # and 2 locks are taken at once. + lock = asyncio.Lock(loop=self.loop) + lock_count = 0 + call_count = 0 + + async def lockit(): + nonlocal lock_count + nonlocal call_count + call_count += 1 + await lock.acquire() + lock_count += 1 + + async def lockandtrigger(): + await lock.acquire() + self.loop.call_soon(trigger) + + def trigger(): + t1.cancel() + lock.release() + + t0 = self.loop.create_task(lockandtrigger()) + t1 = self.loop.create_task(lockit()) + t2 = self.loop.create_task(lockit()) + t3 = self.loop.create_task(lockit()) + + # First loop acquires all + test_utils.run_briefly(self.loop) + self.assertTrue(t0.done()) + + # Second loop calls trigger + test_utils.run_briefly(self.loop) + # Third loop calls cancellation + test_utils.run_briefly(self.loop) + + # Make sure only one lock was taken + self.assertEqual(lock_count, 1) + # While 3 calls were made to lockit() + self.assertEqual(call_count, 3) + self.assertTrue(t1.cancelled() and t2.done()) + + # Cleanup the task that is stuck on acquire. + t3.cancel() + test_utils.run_briefly(self.loop) + self.assertTrue(t3.cancelled()) + + + def test_finished_waiter_cancelled(self): lock = asyncio.Lock(loop=self.loop) diff --git a/Misc/ACKS b/Misc/ACKS index 3fdfa3041f87..c5eadc5ba017 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -602,6 +602,7 @@ Milton L. Hankins Stephen Hansen Barry Hantman Lynda Hardman +Bar Harel Derek Harland Jason Harper David Harrigan diff --git a/Misc/NEWS.d/next/Library/2018-02-01-01-34-47.bpo-32734.gCV9AD.rst b/Misc/NEWS.d/next/Library/2018-02-01-01-34-47.bpo-32734.gCV9AD.rst new file mode 100644 index 000000000000..14d4bbdade75 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-01-01-34-47.bpo-32734.gCV9AD.rst @@ -0,0 +1,2 @@ +Fixed ``asyncio.Lock()`` safety issue which allowed acquiring and locking +the same lock multiple times, without it being free. Patch by Bar Harel. From webhook-mailer at python.org Fri Feb 2 17:37:39 2018 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Fri, 02 Feb 2018 22:37:39 -0000 Subject: [Python-checkins] =?utf-8?q?=5B3=2E6=5D_bpo-32614=3A_Modify_re_e?= =?utf-8?q?xamples_to_use_a_raw_string_to_prevent_wa=E2=80=A6__=E2=80=A6rn?= =?utf-8?q?ing_=28GH-5265=29_=28GH-5500=29?= Message-ID: https://github.com/python/cpython/commit/fbf8e823c02ac1c93a48609cc74e439e19ccb426 commit: fbf8e823c02ac1c93a48609cc74e439e19ccb426 branch: 3.6 author: Terry Jan Reedy committer: GitHub date: 2018-02-02T17:37:30-05:00 summary: [3.6] bpo-32614: Modify re examples to use a raw string to prevent wa? ?rning (GH-5265) (GH-5500) Modify RE examples in documentation to use raw strings to prevent DeprecationWarning. Add text to REGEX HOWTO to highlight the deprecation. Approved by Serhiy Storchaka. (cherry picked from commit 66771422d0541289d0b1287bc3c28e8b5609f6b4) files: A Misc/NEWS.d/next/Documentation/2018-02-02-07-41-57.bpo-32614.LSqzGw.rst M Doc/howto/regex.rst M Doc/howto/unicode.rst M Doc/library/re.rst diff --git a/Doc/howto/regex.rst b/Doc/howto/regex.rst index eef63478beed..a3a655344af6 100644 --- a/Doc/howto/regex.rst +++ b/Doc/howto/regex.rst @@ -289,6 +289,8 @@ Putting REs in strings keeps the Python language simpler, but has one disadvantage which is the topic of the next section. +.. _the-backslash-plague: + The Backslash Plague -------------------- @@ -327,6 +329,13 @@ backslashes are not handled in any special way in a string literal prefixed with while ``"\n"`` is a one-character string containing a newline. Regular expressions will often be written in Python code using this raw string notation. +In addition, special escape sequences that are valid in regular expressions, +but not valid as Python string literals, now result in a +:exc:`DeprecationWarning` and will eventually become a :exc:`SyntaxError`, +which means the sequences will be invalid if raw string notation or escaping +the backslashes isn't used. + + +-------------------+------------------+ | Regular String | Raw string | +===================+==================+ @@ -457,12 +466,18 @@ In actual programs, the most common style is to store the Two pattern methods return all of the matches for a pattern. :meth:`~re.pattern.findall` returns a list of matching strings:: - >>> p = re.compile('\d+') + >>> p = re.compile(r'\d+') >>> p.findall('12 drummers drumming, 11 pipers piping, 10 lords a-leaping') ['12', '11', '10'] -:meth:`~re.pattern.findall` has to create the entire list before it can be returned as the -result. The :meth:`~re.pattern.finditer` method returns a sequence of +The ``r`` prefix, making the literal a raw string literal, is needed in this +example because escape sequences in a normal "cooked" string literal that are +not recognized by Python, as opposed to regular expressions, now result in a +:exc:`DeprecationWarning` and will eventually become a :exc:`SyntaxError`. See +:ref:`the-backslash-plague`. + +:meth:`~re.Pattern.findall` has to create the entire list before it can be returned as the +result. The :meth:`~re.Pattern.finditer` method returns a sequence of :ref:`match object ` instances as an :term:`iterator`:: >>> iterator = p.finditer('12 drummers drumming, 11 ... 10 ...') @@ -1096,11 +1111,11 @@ following calls:: The module-level function :func:`re.split` adds the RE to be used as the first argument, but is otherwise the same. :: - >>> re.split('[\W]+', 'Words, words, words.') + >>> re.split(r'[\W]+', 'Words, words, words.') ['Words', 'words', 'words', ''] - >>> re.split('([\W]+)', 'Words, words, words.') + >>> re.split(r'([\W]+)', 'Words, words, words.') ['Words', ', ', 'words', ', ', 'words', '.', ''] - >>> re.split('[\W]+', 'Words, words, words.', 1) + >>> re.split(r'[\W]+', 'Words, words, words.', 1) ['Words', 'words, words.'] diff --git a/Doc/howto/unicode.rst b/Doc/howto/unicode.rst index 9649b9c609c2..b54e15077936 100644 --- a/Doc/howto/unicode.rst +++ b/Doc/howto/unicode.rst @@ -463,7 +463,7 @@ The string in this example has the number 57 written in both Thai and Arabic numerals:: import re - p = re.compile('\d+') + p = re.compile(r'\d+') s = "Over \u0e55\u0e57 57 flavours" m = p.search(s) diff --git a/Doc/library/re.rst b/Doc/library/re.rst index 874c8ddce670..db92c4808554 100644 --- a/Doc/library/re.rst +++ b/Doc/library/re.rst @@ -315,7 +315,7 @@ The special characters are: This example looks for a word following a hyphen: - >>> m = re.search('(?<=-)\w+', 'spam-egg') + >>> m = re.search(r'(?<=-)\w+', 'spam-egg') >>> m.group(0) 'egg' diff --git a/Misc/NEWS.d/next/Documentation/2018-02-02-07-41-57.bpo-32614.LSqzGw.rst b/Misc/NEWS.d/next/Documentation/2018-02-02-07-41-57.bpo-32614.LSqzGw.rst new file mode 100644 index 000000000000..9e9f3e3a74df --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2018-02-02-07-41-57.bpo-32614.LSqzGw.rst @@ -0,0 +1,3 @@ +Modify RE examples in documentation to use raw strings to prevent +:exc:`DeprecationWarning` and add text to REGEX HOWTO to highlight the +deprecation. From webhook-mailer at python.org Fri Feb 2 18:15:34 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Fri, 02 Feb 2018 23:15:34 -0000 Subject: [Python-checkins] [3.6] bpo-32734: Fix asyncio.Lock multiple acquire safety issue (GH-5466) (#5502) Message-ID: https://github.com/python/cpython/commit/7e4cf8e95d2971ae0d5fb417152183070184293f commit: 7e4cf8e95d2971ae0d5fb417152183070184293f branch: 3.6 author: Bar Harel committer: Yury Selivanov date: 2018-02-02T18:15:31-05:00 summary: [3.6] bpo-32734: Fix asyncio.Lock multiple acquire safety issue (GH-5466) (#5502) (cherry picked from commit d41e9e0952393e64f2f9756d778553d704191086) files: A Misc/NEWS.d/next/Library/2018-02-01-01-34-47.bpo-32734.gCV9AD.rst M Lib/asyncio/locks.py M Lib/test/test_asyncio/test_locks.py M Misc/ACKS diff --git a/Lib/asyncio/locks.py b/Lib/asyncio/locks.py index 92661830a062..14d21ff4e6f7 100644 --- a/Lib/asyncio/locks.py +++ b/Lib/asyncio/locks.py @@ -172,16 +172,22 @@ def acquire(self): fut = self._loop.create_future() self._waiters.append(fut) + + # Finally block should be called before the CancelledError + # handling as we don't want CancelledError to call + # _wake_up_first() and attempt to wake up itself. try: - yield from fut - self._locked = True - return True + try: + yield from fut + finally: + self._waiters.remove(fut) except futures.CancelledError: if not self._locked: self._wake_up_first() raise - finally: - self._waiters.remove(fut) + + self._locked = True + return True def release(self): """Release a lock. @@ -201,11 +207,17 @@ def release(self): raise RuntimeError('Lock is not acquired.') def _wake_up_first(self): - """Wake up the first waiter who isn't cancelled.""" - for fut in self._waiters: - if not fut.done(): - fut.set_result(True) - break + """Wake up the first waiter if it isn't done.""" + try: + fut = next(iter(self._waiters)) + except StopIteration: + return + + # .done() necessarily means that a waiter will wake up later on and + # either take the lock, or, if it was cancelled and lock wasn't + # taken already, will hit this again and wake up a new waiter. + if not fut.done(): + fut.set_result(True) class Event: diff --git a/Lib/test/test_asyncio/test_locks.py b/Lib/test/test_asyncio/test_locks.py index c85e8b1a32f7..835d09ffc5d2 100644 --- a/Lib/test/test_asyncio/test_locks.py +++ b/Lib/test/test_asyncio/test_locks.py @@ -176,6 +176,56 @@ def lockit(name, blocker): self.assertTrue(tb.cancelled()) self.assertTrue(tc.done()) + def test_cancel_release_race(self): + # Issue 32734 + # Acquire 4 locks, cancel second, release first + # and 2 locks are taken at once. + lock = asyncio.Lock(loop=self.loop) + lock_count = 0 + call_count = 0 + + async def lockit(): + nonlocal lock_count + nonlocal call_count + call_count += 1 + await lock.acquire() + lock_count += 1 + + async def lockandtrigger(): + await lock.acquire() + self.loop.call_soon(trigger) + + def trigger(): + t1.cancel() + lock.release() + + t0 = self.loop.create_task(lockandtrigger()) + t1 = self.loop.create_task(lockit()) + t2 = self.loop.create_task(lockit()) + t3 = self.loop.create_task(lockit()) + + # First loop acquires all + test_utils.run_briefly(self.loop) + self.assertTrue(t0.done()) + + # Second loop calls trigger + test_utils.run_briefly(self.loop) + # Third loop calls cancellation + test_utils.run_briefly(self.loop) + + # Make sure only one lock was taken + self.assertEqual(lock_count, 1) + # While 3 calls were made to lockit() + self.assertEqual(call_count, 3) + self.assertTrue(t1.cancelled() and t2.done()) + + # Cleanup the task that is stuck on acquire. + t3.cancel() + test_utils.run_briefly(self.loop) + self.assertTrue(t3.cancelled()) + + + def test_finished_waiter_cancelled(self): lock = asyncio.Lock(loop=self.loop) diff --git a/Misc/ACKS b/Misc/ACKS index 0a0823cf6242..ac1345938cb4 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -589,6 +589,7 @@ Milton L. Hankins Stephen Hansen Barry Hantman Lynda Hardman +Bar Harel Derek Harland Jason Harper David Harrigan diff --git a/Misc/NEWS.d/next/Library/2018-02-01-01-34-47.bpo-32734.gCV9AD.rst b/Misc/NEWS.d/next/Library/2018-02-01-01-34-47.bpo-32734.gCV9AD.rst new file mode 100644 index 000000000000..14d4bbdade75 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-01-01-34-47.bpo-32734.gCV9AD.rst @@ -0,0 +1,2 @@ +Fixed ``asyncio.Lock()`` safety issue which allowed acquiring and locking +the same lock multiple times, without it being free. Patch by Bar Harel. From webhook-mailer at python.org Fri Feb 2 23:21:17 2018 From: webhook-mailer at python.org (Barry Warsaw) Date: Sat, 03 Feb 2018 04:21:17 -0000 Subject: [Python-checkins] [3.6] bpo-32303 - Consistency fixes for namespace loaders (GH-5481) (#5504) Message-ID: https://github.com/python/cpython/commit/a71397fb6603d0fe673acd7765c74699cd28fe7b commit: a71397fb6603d0fe673acd7765c74699cd28fe7b branch: 3.6 author: Barry Warsaw committer: GitHub date: 2018-02-02T23:21:14-05:00 summary: [3.6] bpo-32303 - Consistency fixes for namespace loaders (GH-5481) (#5504) * Make sure ``__spec__.loader`` matches ``__loader__`` for namespace packages. * Make sure ``__spec__.origin` matches ``__file__`` for namespace packages. https://bugs.python.org/issue32303 https://bugs.python.org/issue32305. (cherry picked from commit bbbcf8693b876daae4469765aa62f8924f39a7d2) Co-authored-by: Barry Warsaw files: A Misc/NEWS.d/next/Core and Builtins/2018-02-01-10-16-28.bpo-32303.VsvhSl.rst A Misc/NEWS.d/next/Core and Builtins/2018-02-01-10-56-41.bpo-32305.dkU9Qa.rst M Doc/library/importlib.rst M Lib/importlib/_bootstrap.py M Lib/importlib/_bootstrap_external.py M Lib/test/test_importlib/test_api.py M Lib/test/test_importlib/test_namespace_pkgs.py M Python/importlib.h M Python/importlib_external.h diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst index d194362fb003..34156135715f 100644 --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -1077,7 +1077,7 @@ find and load modules. Name of the place from which the module is loaded, e.g. "builtin" for built-in modules and the filename for modules loaded from source. Normally "origin" should be set, but it may be ``None`` (the default) - which indicates it is unspecified. + which indicates it is unspecified (e.g. for namespace packages). .. attribute:: submodule_search_locations diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py index e2343dd43080..dfcdb99463cf 100644 --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -522,6 +522,18 @@ def _init_module_attrs(spec, module, *, override=False): loader = _NamespaceLoader.__new__(_NamespaceLoader) loader._path = spec.submodule_search_locations + spec.loader = loader + # While the docs say that module.__file__ is not set for + # built-in modules, and the code below will avoid setting it if + # spec.has_location is false, this is incorrect for namespace + # packages. Namespace packages have no location, but their + # __spec__.origin is None, and thus their module.__file__ + # should also be None for consistency. While a bit of a hack, + # this is the best place to ensure this consistency. + # + # See # https://docs.python.org/3/library/importlib.html#importlib.abc.Loader.load_module + # and bpo-32305 + module.__file__ = None try: module.__loader__ = loader except AttributeError: diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index 9feec50842c7..62da085f876e 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -1160,9 +1160,9 @@ def find_spec(cls, fullname, path=None, target=None): elif spec.loader is None: namespace_path = spec.submodule_search_locations if namespace_path: - # We found at least one namespace path. Return a - # spec which can create the namespace package. - spec.origin = 'namespace' + # We found at least one namespace path. Return a spec which + # can create the namespace package. + spec.origin = None spec.submodule_search_locations = _NamespacePath(fullname, namespace_path, cls._get_spec) return spec else: diff --git a/Lib/test/test_importlib/test_api.py b/Lib/test/test_importlib/test_api.py index b0a94aaff5b3..446ed6c6fbb1 100644 --- a/Lib/test/test_importlib/test_api.py +++ b/Lib/test/test_importlib/test_api.py @@ -307,6 +307,7 @@ def test_reload_namespace_changed(self): expected = {'__name__': name, '__package__': name, '__doc__': None, + '__file__': None, } os.mkdir(name) with open(bad_path, 'w') as init_file: @@ -318,8 +319,9 @@ def test_reload_namespace_changed(self): spec = ns.pop('__spec__') ns.pop('__builtins__', None) # An implementation detail. self.assertEqual(spec.name, name) - self.assertIs(spec.loader, None) - self.assertIsNot(loader, None) + self.assertIsNotNone(spec.loader) + self.assertIsNotNone(loader) + self.assertEqual(spec.loader, loader) self.assertEqual(set(path), set([os.path.dirname(bad_path)])) with self.assertRaises(AttributeError): diff --git a/Lib/test/test_importlib/test_namespace_pkgs.py b/Lib/test/test_importlib/test_namespace_pkgs.py index e37d8a18f4ac..8e4b5d66fecc 100644 --- a/Lib/test/test_importlib/test_namespace_pkgs.py +++ b/Lib/test/test_importlib/test_namespace_pkgs.py @@ -317,5 +317,21 @@ def test_dynamic_path(self): self.assertEqual(foo.two.attr, 'portion2 foo two') +class LoaderTests(NamespacePackageTest): + paths = ['portion1'] + + def test_namespace_loader_consistency(self): + # bpo-32303 + import foo + self.assertEqual(foo.__loader__, foo.__spec__.loader) + self.assertIsNotNone(foo.__loader__) + + def test_namespace_origin_consistency(self): + # bpo-32305 + import foo + self.assertIsNone(foo.__spec__.origin) + self.assertIsNone(foo.__file__) + + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-02-01-10-16-28.bpo-32303.VsvhSl.rst b/Misc/NEWS.d/next/Core and Builtins/2018-02-01-10-16-28.bpo-32303.VsvhSl.rst new file mode 100644 index 000000000000..b84448fb25a1 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-02-01-10-16-28.bpo-32303.VsvhSl.rst @@ -0,0 +1 @@ +Make sure ``__spec__.loader`` matches ``__loader__`` for namespace packages. diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-02-01-10-56-41.bpo-32305.dkU9Qa.rst b/Misc/NEWS.d/next/Core and Builtins/2018-02-01-10-56-41.bpo-32305.dkU9Qa.rst new file mode 100644 index 000000000000..204d74a49754 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-02-01-10-56-41.bpo-32305.dkU9Qa.rst @@ -0,0 +1,2 @@ +For namespace packages, ensure that both ``__file__`` and +``__spec__.origin`` are set to None. diff --git a/Python/importlib.h b/Python/importlib.h index 191197b83852..2996b624fd69 100644 --- a/Python/importlib.h +++ b/Python/importlib.h @@ -863,960 +863,961 @@ const unsigned char _Py_M__importlib[] = { 14,1,20,1,6,1,6,1,114,129,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,59,0,0,0,67,0,0,0,115, - 212,1,0,0,124,2,115,20,116,0,124,1,100,1,100,0, + 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,166,124,0, - 106,4,125,3,124,3,100,0,107,8,114,134,124,0,106,5, - 100,0,107,9,114,134,116,6,100,0,107,8,114,110,116,7, + 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,106,9,124,4,131,1, - 125,3,124,0,106,5,124,3,95,10,121,10,124,3,124,1, - 95,11,87,0,110,20,4,0,116,3,107,10,114,164,1,0, - 1,0,1,0,89,0,110,2,88,0,124,2,115,186,116,0, - 124,1,100,3,100,0,131,3,100,0,107,8,114,220,121,12, - 124,0,106,12,124,1,95,13,87,0,110,20,4,0,116,3, - 107,10,114,218,1,0,1,0,1,0,89,0,110,2,88,0, - 121,10,124,0,124,1,95,14,87,0,110,20,4,0,116,3, - 107,10,114,250,1,0,1,0,1,0,89,0,110,2,88,0, - 124,2,144,1,115,20,116,0,124,1,100,4,100,0,131,3, - 100,0,107,8,144,1,114,68,124,0,106,5,100,0,107,9, - 144,1,114,68,121,12,124,0,106,5,124,1,95,15,87,0, - 110,22,4,0,116,3,107,10,144,1,114,66,1,0,1,0, - 1,0,89,0,110,2,88,0,124,0,106,16,144,1,114,208, - 124,2,144,1,115,100,116,0,124,1,100,5,100,0,131,3, - 100,0,107,8,144,1,114,136,121,12,124,0,106,17,124,1, - 95,18,87,0,110,22,4,0,116,3,107,10,144,1,114,134, - 1,0,1,0,1,0,89,0,110,2,88,0,124,2,144,1, - 115,160,116,0,124,1,100,6,100,0,131,3,100,0,107,8, - 144,1,114,208,124,0,106,19,100,0,107,9,144,1,114,208, - 121,12,124,0,106,19,124,1,95,20,87,0,110,22,4,0, - 116,3,107,10,144,1,114,206,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,86,0,0,0,218,11,95,95,112,97,99,107,97,103,101, - 95,95,114,128,0,0,0,114,93,0,0,0,114,126,0,0, - 0,41,21,114,6,0,0,0,114,15,0,0,0,114,1,0, - 0,0,114,91,0,0,0,114,94,0,0,0,114,107,0,0, - 0,114,116,0,0,0,114,117,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,86,0, - 0,0,114,120,0,0,0,114,131,0,0,0,114,90,0,0, - 0,114,128,0,0,0,114,114,0,0,0,114,104,0,0,0, - 114,93,0,0,0,114,113,0,0,0,114,126,0,0,0,41, - 5,114,83,0,0,0,114,84,0,0,0,114,130,0,0,0, - 114,94,0,0,0,114,132,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,92,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,2,1,10,1,14,1,6,2,20,1,2,1, - 12,1,14,1,6,2,2,1,10,1,14,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,134,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,106,2,124,0,131,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,94,0,0,0,114, - 135,0,0,0,114,71,0,0,0,114,16,0,0,0,114,15, - 0,0,0,114,134,0,0,0,41,2,114,83,0,0,0,114, - 84,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,52,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,137,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,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,106,3,124,1,131,1,83, - 0,100,4,106,3,124,1,124,0,106,2,131,2,83,0,110, - 36,124,0,106,4,114,86,100,5,106,3,124,1,124,0,106, - 1,131,2,83,0,100,6,106,3,124,0,106,0,124,0,106, - 1,131,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,88,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,104,0,0,0,114,94,0,0,0,114,38,0,0, - 0,114,114,0,0,0,41,2,114,83,0,0,0,114,15,0, + 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,86, + 0,0,0,218,11,95,95,112,97,99,107,97,103,101,95,95, + 114,128,0,0,0,114,93,0,0,0,114,126,0,0,0,41, + 21,114,6,0,0,0,114,15,0,0,0,114,1,0,0,0, + 114,91,0,0,0,114,94,0,0,0,114,107,0,0,0,114, + 116,0,0,0,114,117,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,93,0,0,0, + 114,86,0,0,0,114,120,0,0,0,114,131,0,0,0,114, + 90,0,0,0,114,128,0,0,0,114,114,0,0,0,114,104, + 0,0,0,114,113,0,0,0,114,126,0,0,0,41,5,114, + 83,0,0,0,114,84,0,0,0,114,130,0,0,0,114,94, + 0,0,0,114,132,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,134,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,106,2,124,0,131,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,94,0,0, + 0,114,135,0,0,0,114,71,0,0,0,114,16,0,0,0, + 114,15,0,0,0,114,134,0,0,0,41,2,114,83,0,0, + 0,114,84,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,137,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,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,106,3,124,1,131, + 1,83,0,100,4,106,3,124,1,124,0,106,2,131,2,83, + 0,110,36,124,0,106,4,114,86,100,5,106,3,124,1,124, + 0,106,1,131,2,83,0,100,6,106,3,124,0,106,0,124, + 0,106,1,131,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,88,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,104,0,0,0,114,94,0,0,0,114,38, + 0,0,0,114,114,0,0,0,41,2,114,83,0,0,0,114, + 15,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, + 0,0,0,114,92,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,92,0,0,0,99,2,0,0,0,0,0,0,0,4, + 0,0,0,12,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,106,4,124,2,131,1,124,1,107,9,114,54, + 100,1,106,5,124,2,131,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,106,11,124,2,131,1,1,0, + 110,12,124,0,106,7,106,12,124,1,131,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,130,0,0,0,114,136,0,0, + 0,41,13,114,15,0,0,0,114,42,0,0,0,114,14,0, + 0,0,114,80,0,0,0,114,30,0,0,0,114,38,0,0, + 0,114,71,0,0,0,114,94,0,0,0,114,107,0,0,0, + 114,134,0,0,0,114,4,0,0,0,218,11,108,111,97,100, + 95,109,111,100,117,108,101,114,136,0,0,0,41,4,114,83, + 0,0,0,114,84,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,81,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,81,0, + 0,0,99,1,0,0,0,0,0,0,0,2,0,0,0,27, + 0,0,0,67,0,0,0,115,206,0,0,0,124,0,106,0, + 106,1,124,0,106,2,131,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, + 106,11,100,4,131,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,86,0, + 0,0,114,131,0,0,0,114,128,0,0,0,114,118,0,0, + 0,114,19,0,0,0,114,90,0,0,0,41,13,114,94,0, + 0,0,114,138,0,0,0,114,15,0,0,0,114,14,0,0, + 0,114,80,0,0,0,114,6,0,0,0,114,86,0,0,0, + 114,91,0,0,0,114,1,0,0,0,114,131,0,0,0,114, + 4,0,0,0,114,119,0,0,0,114,90,0,0,0,41,2, + 114,83,0,0,0,114,84,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,140,0,0,0,99,1,0,0,0,0, + 0,0,0,2,0,0,0,11,0,0,0,67,0,0,0,115, + 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,106,8,124,1, + 131,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,136,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,94,0,0,0, + 114,4,0,0,0,114,140,0,0,0,114,137,0,0,0,114, + 97,0,0,0,114,107,0,0,0,114,71,0,0,0,114,15, + 0,0,0,114,136,0,0,0,114,14,0,0,0,114,80,0, + 0,0,41,2,114,83,0,0,0,114,84,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,141,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,141,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,82,0,0,0,174,2,0,0,115,4,0,0,0, + 0,9,12,1,114,82,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,2,0,0, + 0,67,0,0,0,115,12,0,0,0,100,1,106,0,124,0, + 106,1,131,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,84,0,0,0,114,10,0,0,0,114, + 10,0,0,0,114,11,0,0,0,114,87,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,106, + 1,124,1,131,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,104,0,0, + 0,41,3,114,49,0,0,0,90,10,105,115,95,98,117,105, + 108,116,105,110,114,79,0,0,0,41,4,218,3,99,108,115, + 114,72,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,3,0,0,0,67,0,0,0, + 115,30,0,0,0,124,0,106,0,124,1,124,2,131,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,146,0,0,0,114,94, + 0,0,0,41,4,114,143,0,0,0,114,72,0,0,0,114, + 144,0,0,0,114,83,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,106,4,124,1,106,0,131, + 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,70,0,0,0,114,71,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,83,0,0,0,114,10,0,0,0,114, + 10,0,0,0,114,11,0,0,0,114,135,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,84,0,0,0,114,10,0,0,0,114,10, + 0,0,0,114,11,0,0,0,114,136,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,143,0,0,0,114,72,0, 0,0,114,10,0,0,0,114,10,0,0,0,114,11,0,0, - 0,114,92,0,0,0,69,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, - 92,0,0,0,99,2,0,0,0,0,0,0,0,4,0,0, - 0,12,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,106,4,124,2,131,1,124,1,107,9,114,54,100,1, - 106,5,124,2,131,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,106,11,124,2,131,1,1,0,110,12, - 124,0,106,7,106,12,124,1,131,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,130,0,0,0,114,136,0,0,0,41, - 13,114,15,0,0,0,114,42,0,0,0,114,14,0,0,0, - 114,80,0,0,0,114,30,0,0,0,114,38,0,0,0,114, - 71,0,0,0,114,94,0,0,0,114,107,0,0,0,114,134, - 0,0,0,114,4,0,0,0,218,11,108,111,97,100,95,109, - 111,100,117,108,101,114,136,0,0,0,41,4,114,83,0,0, - 0,114,84,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, - 81,0,0,0,86,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,81,0,0,0, - 99,1,0,0,0,0,0,0,0,2,0,0,0,27,0,0, - 0,67,0,0,0,115,206,0,0,0,124,0,106,0,106,1, - 124,0,106,2,131,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,106,11, - 100,4,131,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,86,0,0,0, - 114,131,0,0,0,114,128,0,0,0,114,118,0,0,0,114, - 19,0,0,0,114,90,0,0,0,41,13,114,94,0,0,0, - 114,138,0,0,0,114,15,0,0,0,114,14,0,0,0,114, - 80,0,0,0,114,6,0,0,0,114,86,0,0,0,114,91, - 0,0,0,114,1,0,0,0,114,131,0,0,0,114,4,0, - 0,0,114,119,0,0,0,114,90,0,0,0,41,2,114,83, - 0,0,0,114,84,0,0,0,114,10,0,0,0,114,10,0, - 0,0,114,11,0,0,0,218,25,95,108,111,97,100,95,98, - 97,99,107,119,97,114,100,95,99,111,109,112,97,116,105,98, - 108,101,110,2,0,0,115,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,140,0,0,0,99,1,0,0,0,0,0,0, - 0,2,0,0,0,11,0,0,0,67,0,0,0,115,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,106,8,124,1,131,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,136,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,94,0,0,0,114,4, - 0,0,0,114,140,0,0,0,114,137,0,0,0,114,97,0, - 0,0,114,107,0,0,0,114,71,0,0,0,114,15,0,0, - 0,114,136,0,0,0,114,14,0,0,0,114,80,0,0,0, - 41,2,114,83,0,0,0,114,84,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,139,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,141,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,141,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,82,0,0,0,162,2,0,0,115,4,0,0,0,0,9, - 12,1,114,82,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,2,0,0,0,67, - 0,0,0,115,12,0,0,0,100,1,106,0,124,0,106,1, - 131,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,84,0,0,0,114,10,0,0,0,114,10,0, - 0,0,114,11,0,0,0,114,87,0,0,0,186,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,106,1,124, - 1,131,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,104,0,0,0,41, - 3,114,49,0,0,0,90,10,105,115,95,98,117,105,108,116, - 105,110,114,79,0,0,0,41,4,218,3,99,108,115,114,72, - 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,195,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,3,0,0,0,67,0,0,0,115,30, - 0,0,0,124,0,106,0,124,1,124,2,131,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,146,0,0,0,114,94,0,0, - 0,41,4,114,143,0,0,0,114,72,0,0,0,114,144,0, - 0,0,114,83,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,204,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,106,4,124,1,106,0,131,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, + 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, - 41,1,114,15,0,0,0,41,8,114,15,0,0,0,114,14, - 0,0,0,114,70,0,0,0,114,71,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,83,0,0,0,114,10,0,0,0,114,10,0, - 0,0,114,11,0,0,0,114,135,0,0,0,216,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,84,0,0,0,114,10,0,0,0,114,10,0,0, - 0,114,11,0,0,0,114,136,0,0,0,224,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,143,0,0,0,114,72,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,229,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, + 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,143,0,0,0,114,72,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,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,143,0,0,0,114,72,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,235,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,143,0,0,0,114, - 72,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, - 0,0,0,114,106,0,0,0,241,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,87,0,0,0,218, - 11,99,108,97,115,115,109,101,116,104,111,100,114,146,0,0, - 0,114,147,0,0,0,114,135,0,0,0,114,136,0,0,0, - 114,75,0,0,0,114,148,0,0,0,114,149,0,0,0,114, - 106,0,0,0,114,85,0,0,0,114,138,0,0,0,114,10, - 0,0,0,114,10,0,0,0,114,10,0,0,0,114,11,0, - 0,0,114,142,0,0,0,177,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,142, - 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,2,0,0,0,67,0,0,0, - 115,12,0,0,0,100,1,106,0,124,0,106,1,131,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,87,0,0,0,3,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,106,1,124,1,131,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,104,0,0,0,41,3,114,49,0,0,0, - 114,76,0,0,0,114,79,0,0,0,41,4,114,143,0,0, - 0,114,72,0,0,0,114,144,0,0,0,114,145,0,0,0, - 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,114, - 146,0,0,0,12,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,2,0,0,0,67,0, - 0,0,115,18,0,0,0,116,0,106,1,124,1,131,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,76,0,0,0,41,3,114,143,0,0,0,114,72, - 0,0,0,114,144,0,0,0,114,10,0,0,0,114,10,0, - 0,0,114,11,0,0,0,114,147,0,0,0,19,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,143,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,28,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, - 106,3,124,1,131,1,115,36,116,4,100,1,106,5,124,1, - 131,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, - 90,0,0,0,114,15,0,0,0,114,49,0,0,0,114,76, - 0,0,0,114,71,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,84,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,136,0,0,0,32,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, + 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,143,0,0, + 0,114,72,0,0,0,114,10,0,0,0,114,10,0,0,0, + 114,11,0,0,0,114,106,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,87,0,0, + 0,218,11,99,108,97,115,115,109,101,116,104,111,100,114,146, + 0,0,0,114,147,0,0,0,114,135,0,0,0,114,136,0, + 0,0,114,75,0,0,0,114,148,0,0,0,114,149,0,0, + 0,114,106,0,0,0,114,85,0,0,0,114,138,0,0,0, + 114,10,0,0,0,114,10,0,0,0,114,10,0,0,0,114, + 11,0,0,0,114,142,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,142,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,2,0,0,0,67,0, + 0,0,115,12,0,0,0,100,1,106,0,124,0,106,1,131, + 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,87,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,106,1,124,1,131, + 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,104,0,0,0,41,3,114,49,0, + 0,0,114,76,0,0,0,114,79,0,0,0,41,4,114,143, + 0,0,0,114,72,0,0,0,114,144,0,0,0,114,145,0, + 0,0,114,10,0,0,0,114,10,0,0,0,114,11,0,0, + 0,114,146,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,2,0,0,0, + 67,0,0,0,115,18,0,0,0,116,0,106,1,124,1,131, + 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,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,85,0,0,0,41,2,114,143,0,0,0,114,72,0,0, - 0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, - 114,138,0,0,0,41,3,0,0,115,2,0,0,0,0,7, - 122,26,70,114,111,122,101,110,73,109,112,111,114,116,101,114, - 46,108,111,97,100,95,109,111,100,117,108,101,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,116,0,106,1,124,1,131,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,154,0,0,0,41,2,114, - 143,0,0,0,114,72,0,0,0,114,10,0,0,0,114,10, - 0,0,0,114,11,0,0,0,114,148,0,0,0,50,3,0, - 0,115,2,0,0,0,0,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, + 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,76,0,0,0,41,3,114,143,0,0,0, + 114,72,0,0,0,114,144,0,0,0,114,10,0,0,0,114, + 10,0,0,0,114,11,0,0,0,114,147,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,143,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,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,106,3,124,1,131,1,115,36,116,4,100,1,106,5, + 124,1,131,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,90,0,0,0,114,15,0,0,0,114,49,0,0,0, + 114,76,0,0,0,114,71,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,84,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,136,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,85,0,0,0,41,2,114,143,0,0,0,114,72, + 0,0,0,114,10,0,0,0,114,10,0,0,0,114,11,0, + 0,0,114,138,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,2,0,0,0,67, + 0,0,0,115,10,0,0,0,116,0,106,1,124,1,131,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,154,0,0,0,41, 2,114,143,0,0,0,114,72,0,0,0,114,10,0,0,0, - 114,10,0,0,0,114,11,0,0,0,114,149,0,0,0,56, - 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,2,0,0,0,67,0,0,0,115,10,0,0,0,116, - 0,106,1,124,1,131,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,143,0,0,0,114,72,0,0, - 0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, - 114,106,0,0,0,62,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,150,0,0,0,114,87,0, - 0,0,114,151,0,0,0,114,146,0,0,0,114,147,0,0, - 0,114,135,0,0,0,114,136,0,0,0,114,138,0,0,0, - 114,78,0,0,0,114,148,0,0,0,114,149,0,0,0,114, - 106,0,0,0,114,10,0,0,0,114,10,0,0,0,114,10, - 0,0,0,114,11,0,0,0,114,152,0,0,0,250,2,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,152,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,1,0,0,0, - 67,0,0,0,115,12,0,0,0,116,0,106,1,131,0,1, - 0,100,1,83,0,41,2,122,24,65,99,113,117,105,114,101, + 114,10,0,0,0,114,11,0,0,0,114,148,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,143,0,0,0,114,72,0,0,0,114,10,0, + 0,0,114,10,0,0,0,114,11,0,0,0,114,149,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,2,0,0,0,67,0,0,0,115,10,0,0, + 0,116,0,106,1,124,1,131,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,143,0,0,0,114,72, + 0,0,0,114,10,0,0,0,114,10,0,0,0,114,11,0, + 0,0,114,106,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,150,0,0,0,114, + 87,0,0,0,114,151,0,0,0,114,146,0,0,0,114,147, + 0,0,0,114,135,0,0,0,114,136,0,0,0,114,138,0, + 0,0,114,78,0,0,0,114,148,0,0,0,114,149,0,0, + 0,114,106,0,0,0,114,10,0,0,0,114,10,0,0,0, + 114,10,0,0,0,114,11,0,0,0,114,152,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,152,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,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,75,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,1, - 0,0,0,67,0,0,0,115,12,0,0,0,116,0,106,1, - 131,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,79,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,157,0,0,0,71,3,0,0,115,6,0,0,0,8, - 2,4,2,8,4,114,157,0,0,0,99,3,0,0,0,0, - 0,0,0,5,0,0,0,4,0,0,0,67,0,0,0,115, - 64,0,0,0,124,1,106,0,100,1,124,2,100,2,24,0, - 131,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,106,3,124,4,124,0,131,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,118,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,84,3,0,0,115,10,0,0,0,0,2, - 16,1,12,1,8,1,8,1,114,163,0,0,0,99,3,0, - 0,0,0,0,0,0,4,0,0,0,3,0,0,0,67,0, - 0,0,115,34,0,0,0,124,0,106,0,124,1,124,2,131, - 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,147, - 0,0,0,114,79,0,0,0,41,4,218,6,102,105,110,100, - 101,114,114,15,0,0,0,114,144,0,0,0,114,94,0,0, - 0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, - 218,17,95,102,105,110,100,95,115,112,101,99,95,108,101,103, - 97,99,121,93,3,0,0,115,8,0,0,0,0,3,12,1, - 8,1,4,1,114,165,0,0,0,99,3,0,0,0,0,0, - 0,0,10,0,0,0,27,0,0,0,67,0,0,0,115,242, - 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,106, - 4,100,3,116,5,131,2,1,0,124,0,116,0,106,6,107, - 6,125,4,120,188,124,3,68,0,93,176,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,12,0,114,226,124, - 0,116,0,106,6,107,6,114,226,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,206,1,0,1,0,1,0,124,7,83, - 0,88,0,124,9,100,1,107,8,114,220,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,71,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,80,0,0,0,114,157,0,0,0,114, - 146,0,0,0,114,91,0,0,0,114,165,0,0,0,114,90, - 0,0,0,41,10,114,15,0,0,0,114,144,0,0,0,114, - 145,0,0,0,114,166,0,0,0,90,9,105,115,95,114,101, - 108,111,97,100,114,164,0,0,0,114,146,0,0,0,114,83, - 0,0,0,114,84,0,0,0,114,90,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,102,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,16,1,10,1,2,1,10,1,14,4,6,2,8, - 1,4,2,6,2,8,2,114,170,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,110,0,0,0,116,0,124,0,116,1,131,2,115,28, - 116,2,100,1,106,3,116,4,124,0,131,1,131,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,12,0,114,106, - 124,2,100,2,107,2,114,106,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,160,0,0,0,114,71,0,0,0,41,3,114, - 15,0,0,0,114,161,0,0,0,114,162,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,149,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,14,1,114,174,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,12,0,0,0,67,0,0,0,115,220,0, - 0,0,100,0,125,2,124,0,106,0,100,1,131,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,106,7,124,0,124,3, - 131,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,106,7, - 124,0,131,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,106,0,100,1,131,1, - 100,5,25,0,124,7,131,3,1,0,124,7,83,0,41,6, - 78,114,118,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,119,0,0,0,114,14,0,0,0,114,80,0,0, - 0,114,59,0,0,0,114,128,0,0,0,114,91,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,170,0,0,0,114,141,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,144,0,0,0,114,120,0,0,0,90,13,112, - 97,114,101,110,116,95,109,111,100,117,108,101,114,139,0,0, - 0,114,83,0,0,0,114,84,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,168,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,179,0,0,0,99,2,0,0,0, - 0,0,0,0,4,0,0,0,11,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,106,3,124,0,116,4,131,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,106,6,124,0,131,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,80, - 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,179,0,0,0,114,38,0, - 0,0,114,177,0,0,0,114,57,0,0,0,41,4,114,15, - 0,0,0,114,178,0,0,0,114,84,0,0,0,114,68,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,198,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,181, - 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,174,0,0, - 0,114,163,0,0,0,114,181,0,0,0,218,11,95,103,99, - 100,95,105,109,112,111,114,116,41,3,114,15,0,0,0,114, - 161,0,0,0,114,162,0,0,0,114,10,0,0,0,114,10, - 0,0,0,114,11,0,0,0,114,182,0,0,0,214,3,0, - 0,115,8,0,0,0,0,9,12,1,8,1,12,1,114,182, - 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,17,0,0, - 0,67,0,0,0,115,236,0,0,0,116,0,124,0,100,1, - 131,2,114,232,120,220,124,1,68,0,93,212,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,122, - 124,3,12,0,114,228,116,0,124,0,100,7,131,2,114,228, - 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, - 106,8,124,0,106,3,124,4,131,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,226,1,0,125,7,1,0,122,38,124,7,106,11, - 124,6,107,2,114,208,116,12,106,13,106,14,124,6,116,15, - 131,2,100,11,107,9,114,208,119,16,130,0,87,0,89,0, - 100,11,100,11,125,7,126,7,88,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,128,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,183,0,0,0,122,5,123,125,46,123,125,78, - 41,16,114,4,0,0,0,114,171,0,0,0,114,172,0,0, - 0,114,1,0,0,0,114,173,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,185,0,0,0,114,38,0,0,0,114,59,0,0, - 0,114,177,0,0,0,114,15,0,0,0,114,14,0,0,0, - 114,80,0,0,0,114,30,0,0,0,114,180,0,0,0,41, - 8,114,84,0,0,0,218,8,102,114,111,109,108,105,115,116, - 114,178,0,0,0,114,183,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,186,0,0,0,229,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,16,1,10,1,10,1,10,1,14,1,2,1,14, - 1,16,4,10,1,18,1,2,1,24,1,114,186,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,106,0,100,1, - 131,1,125,1,124,0,106,0,100,2,131,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,106,5,100,12, - 131,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,131,0,0,0,114,90,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,128,0,0,0,114,118,0,0,0,114,19,0,0,0,41, - 6,114,30,0,0,0,114,120,0,0,0,114,167,0,0,0, - 114,168,0,0,0,114,169,0,0,0,114,119,0,0,0,41, - 3,218,7,103,108,111,98,97,108,115,114,161,0,0,0,114, - 83,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,11,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,192,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,106,2,100,3,131,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,106,2,100,3,131,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,118,0,0,0,41,8,114,182,0, - 0,0,114,192,0,0,0,218,9,112,97,114,116,105,116,105, - 111,110,114,159,0,0,0,114,14,0,0,0,114,80,0,0, - 0,114,1,0,0,0,114,186,0,0,0,41,9,114,15,0, - 0,0,114,191,0,0,0,218,6,108,111,99,97,108,115,114, - 187,0,0,0,114,162,0,0,0,114,84,0,0,0,90,8, - 103,108,111,98,97,108,115,95,114,161,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,38,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,195,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,106,1,124,0,131,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,142,0,0,0,114,146, - 0,0,0,114,71,0,0,0,114,141,0,0,0,41,2,114, - 15,0,0,0,114,83,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,73,4,0,0, - 115,8,0,0,0,0,1,10,1,8,1,12,1,114,196,0, - 0,0,99,2,0,0,0,0,0,0,0,12,0,0,0,12, - 0,0,0,67,0,0,0,115,244,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,106,4,131,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,106,8,124,3, - 131,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,5,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,121,12,116,13,100,2,131,1,125,10, - 87,0,110,24,4,0,116,15,107,10,114,206,1,0,1,0, - 1,0,100,3,125,10,89,0,110,2,88,0,116,14,124,7, - 100,2,124,10,131,3,1,0,116,13,100,4,131,1,125,11, - 116,14,124,7,100,4,124,11,131,3,1,0,100,3,83,0, - 41,6,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,114,167, - 0,0,0,114,20,0,0,0,78,114,56,0,0,0,41,1, - 114,167,0,0,0,41,16,114,49,0,0,0,114,14,0,0, - 0,114,13,0,0,0,114,80,0,0,0,218,5,105,116,101, - 109,115,114,171,0,0,0,114,70,0,0,0,114,142,0,0, - 0,114,76,0,0,0,114,152,0,0,0,114,129,0,0,0, - 114,134,0,0,0,114,1,0,0,0,114,196,0,0,0,114, - 5,0,0,0,114,71,0,0,0,41,12,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,84,0,0,0,114,94,0,0,0, - 114,83,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, - 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,114, - 10,0,0,0,114,10,0,0,0,114,11,0,0,0,218,6, - 95,115,101,116,117,112,80,4,0,0,115,50,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,16,3,2,1,12,1,14,2,10,1,12,3,8, - 1,114,200,0,0,0,99,2,0,0,0,0,0,0,0,3, - 0,0,0,3,0,0,0,67,0,0,0,115,66,0,0,0, - 116,0,124,0,124,1,131,2,1,0,116,1,106,2,106,3, - 116,4,131,1,1,0,116,1,106,2,106,3,116,5,131,1, - 1,0,100,1,100,2,108,6,125,2,124,2,97,7,124,2, - 106,8,116,1,106,9,116,10,25,0,131,1,1,0,100,2, - 83,0,41,3,122,50,73,110,115,116,97,108,108,32,105,109, - 112,111,114,116,108,105,98,32,97,115,32,116,104,101,32,105, - 109,112,108,101,109,101,110,116,97,116,105,111,110,32,111,102, - 32,105,109,112,111,114,116,46,114,19,0,0,0,78,41,11, - 114,200,0,0,0,114,14,0,0,0,114,166,0,0,0,114, - 110,0,0,0,114,142,0,0,0,114,152,0,0,0,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,116,0,0,0,218, - 8,95,105,110,115,116,97,108,108,114,80,0,0,0,114,1, - 0,0,0,41,3,114,198,0,0,0,114,199,0,0,0,114, - 201,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, - 0,0,0,114,202,0,0,0,127,4,0,0,115,12,0,0, - 0,0,2,10,2,12,1,12,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,50,114,3,0,0,0,114,116,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,69,0,0,0,114,75, - 0,0,0,114,78,0,0,0,114,85,0,0,0,114,96,0, - 0,0,114,97,0,0,0,114,103,0,0,0,114,79,0,0, - 0,114,129,0,0,0,114,134,0,0,0,114,137,0,0,0, - 114,92,0,0,0,114,81,0,0,0,114,140,0,0,0,114, - 141,0,0,0,114,82,0,0,0,114,142,0,0,0,114,152, - 0,0,0,114,157,0,0,0,114,163,0,0,0,114,165,0, - 0,0,114,170,0,0,0,114,174,0,0,0,90,15,95,69, - 82,82,95,77,83,71,95,80,82,69,70,73,88,114,176,0, - 0,0,114,179,0,0,0,218,6,111,98,106,101,99,116,114, - 180,0,0,0,114,181,0,0,0,114,182,0,0,0,114,186, - 0,0,0,114,192,0,0,0,114,195,0,0,0,114,196,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,94, - 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, - 60,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,18,35,8,7,8, - 47, + 46,99,1,0,0,0,0,0,0,0,1,0,0,0,1,0, + 0,0,67,0,0,0,115,12,0,0,0,116,0,106,1,131, + 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,1,0,0,0,67,0,0,0,115,12,0,0,0,116,0, + 106,1,131,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,157,0,0,0,83,3,0,0,115,6,0,0, + 0,8,2,4,2,8,4,114,157,0,0,0,99,3,0,0, + 0,0,0,0,0,5,0,0,0,4,0,0,0,67,0,0, + 0,115,64,0,0,0,124,1,106,0,100,1,124,2,100,2, + 24,0,131,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,106,3,124,4,124,0,131,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,118,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,163,0,0,0,99, + 3,0,0,0,0,0,0,0,4,0,0,0,3,0,0,0, + 67,0,0,0,115,34,0,0,0,124,0,106,0,124,1,124, + 2,131,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,147,0,0,0,114,79,0,0,0,41,4,218,6,102,105, + 110,100,101,114,114,15,0,0,0,114,144,0,0,0,114,94, + 0,0,0,114,10,0,0,0,114,10,0,0,0,114,11,0, + 0,0,218,17,95,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,165,0,0,0,99,3,0,0,0, + 0,0,0,0,10,0,0,0,27,0,0,0,67,0,0,0, + 115,242,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,106,4,100,3,116,5,131,2,1,0,124,0,116,0,106, + 6,107,6,125,4,120,188,124,3,68,0,93,176,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,12,0,114, + 226,124,0,116,0,106,6,107,6,114,226,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,206,1,0,1,0,1,0,124, + 7,83,0,88,0,124,9,100,1,107,8,114,220,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,71,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,80,0,0,0,114,157,0,0, + 0,114,146,0,0,0,114,91,0,0,0,114,165,0,0,0, + 114,90,0,0,0,41,10,114,15,0,0,0,114,144,0,0, + 0,114,145,0,0,0,114,166,0,0,0,90,9,105,115,95, + 114,101,108,111,97,100,114,164,0,0,0,114,146,0,0,0, + 114,83,0,0,0,114,84,0,0,0,114,90,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,16,1,10,1,2,1,10,1,14,4,6, + 2,8,1,4,2,6,2,8,2,114,170,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,110,0,0,0,116,0,124,0,116,1,131,2, + 115,28,116,2,100,1,106,3,116,4,124,0,131,1,131,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,12,0, + 114,106,124,2,100,2,107,2,114,106,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,160,0,0,0,114,71,0,0,0,41, + 3,114,15,0,0,0,114,161,0,0,0,114,162,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,14,1,114,174,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,12,0,0,0,67,0,0,0,115, + 220,0,0,0,100,0,125,2,124,0,106,0,100,1,131,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,106,7,124,0, + 124,3,131,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, + 106,7,124,0,131,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,106,0,100,1, + 131,1,100,5,25,0,124,7,131,3,1,0,124,7,83,0, + 41,6,78,114,118,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,119,0,0,0,114,14,0,0,0,114,80, + 0,0,0,114,59,0,0,0,114,128,0,0,0,114,91,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,170,0,0,0,114,141,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,144,0,0,0,114,120,0,0,0,90, + 13,112,97,114,101,110,116,95,109,111,100,117,108,101,114,139, + 0,0,0,114,83,0,0,0,114,84,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,179,0,0,0,99,2,0, + 0,0,0,0,0,0,4,0,0,0,11,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,106,3,124,0,116,4,131,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,106,6,124,0,131,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,80,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,179,0,0,0,114, + 38,0,0,0,114,177,0,0,0,114,57,0,0,0,41,4, + 114,15,0,0,0,114,178,0,0,0,114,84,0,0,0,114, + 68,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,181,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,174, + 0,0,0,114,163,0,0,0,114,181,0,0,0,218,11,95, + 103,99,100,95,105,109,112,111,114,116,41,3,114,15,0,0, + 0,114,161,0,0,0,114,162,0,0,0,114,10,0,0,0, + 114,10,0,0,0,114,11,0,0,0,114,182,0,0,0,226, + 3,0,0,115,8,0,0,0,0,9,12,1,8,1,12,1, + 114,182,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,17, + 0,0,0,67,0,0,0,115,236,0,0,0,116,0,124,0, + 100,1,131,2,114,232,120,220,124,1,68,0,93,212,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,122,124,3,12,0,114,228,116,0,124,0,100,7,131,2, + 114,228,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,106,8,124,0,106,3,124,4,131,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,226,1,0,125,7,1,0,122,38,124,7, + 106,11,124,6,107,2,114,208,116,12,106,13,106,14,124,6, + 116,15,131,2,100,11,107,9,114,208,119,16,130,0,87,0, + 89,0,100,11,100,11,125,7,126,7,88,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,128,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,183,0,0,0,122,5,123,125,46,123, + 125,78,41,16,114,4,0,0,0,114,171,0,0,0,114,172, + 0,0,0,114,1,0,0,0,114,173,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,185,0,0,0,114,38,0,0,0,114,59, + 0,0,0,114,177,0,0,0,114,15,0,0,0,114,14,0, + 0,0,114,80,0,0,0,114,30,0,0,0,114,180,0,0, + 0,41,8,114,84,0,0,0,218,8,102,114,111,109,108,105, + 115,116,114,178,0,0,0,114,183,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,186,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,16,1,10,1,10,1,10,1,14,1,2, + 1,14,1,16,4,10,1,18,1,2,1,24,1,114,186,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,106,0, + 100,1,131,1,125,1,124,0,106,0,100,2,131,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,106,5, + 100,12,131,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,131,0,0,0,114,90, + 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,128,0,0,0,114,118,0,0,0,114,19,0,0, + 0,41,6,114,30,0,0,0,114,120,0,0,0,114,167,0, + 0,0,114,168,0,0,0,114,169,0,0,0,114,119,0,0, + 0,41,3,218,7,103,108,111,98,97,108,115,114,161,0,0, + 0,114,83,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, + 192,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,106,2,100,3,131,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,106,2,100,3,131,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,118,0,0,0,41,8,114, + 182,0,0,0,114,192,0,0,0,218,9,112,97,114,116,105, + 116,105,111,110,114,159,0,0,0,114,14,0,0,0,114,80, + 0,0,0,114,1,0,0,0,114,186,0,0,0,41,9,114, + 15,0,0,0,114,191,0,0,0,218,6,108,111,99,97,108, + 115,114,187,0,0,0,114,162,0,0,0,114,84,0,0,0, + 90,8,103,108,111,98,97,108,115,95,114,161,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,195,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,106,1,124,0,131,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,142,0,0,0, + 114,146,0,0,0,114,71,0,0,0,114,141,0,0,0,41, + 2,114,15,0,0,0,114,83,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, + 196,0,0,0,99,2,0,0,0,0,0,0,0,12,0,0, + 0,12,0,0,0,67,0,0,0,115,244,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,106,4,131,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,106,8, + 124,3,131,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,5,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,121,12,116,13,100,2,131,1, + 125,10,87,0,110,24,4,0,116,15,107,10,114,206,1,0, + 1,0,1,0,100,3,125,10,89,0,110,2,88,0,116,14, + 124,7,100,2,124,10,131,3,1,0,116,13,100,4,131,1, + 125,11,116,14,124,7,100,4,124,11,131,3,1,0,100,3, + 83,0,41,6,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, + 114,167,0,0,0,114,20,0,0,0,78,114,56,0,0,0, + 41,1,114,167,0,0,0,41,16,114,49,0,0,0,114,14, + 0,0,0,114,13,0,0,0,114,80,0,0,0,218,5,105, + 116,101,109,115,114,171,0,0,0,114,70,0,0,0,114,142, + 0,0,0,114,76,0,0,0,114,152,0,0,0,114,129,0, + 0,0,114,134,0,0,0,114,1,0,0,0,114,196,0,0, + 0,114,5,0,0,0,114,71,0,0,0,41,12,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,84,0,0,0,114,94,0, + 0,0,114,83,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,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,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,50,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,16,3,2,1,12,1,14,2,10,1,12, + 3,8,1,114,200,0,0,0,99,2,0,0,0,0,0,0, + 0,3,0,0,0,3,0,0,0,67,0,0,0,115,66,0, + 0,0,116,0,124,0,124,1,131,2,1,0,116,1,106,2, + 106,3,116,4,131,1,1,0,116,1,106,2,106,3,116,5, + 131,1,1,0,100,1,100,2,108,6,125,2,124,2,97,7, + 124,2,106,8,116,1,106,9,116,10,25,0,131,1,1,0, + 100,2,83,0,41,3,122,50,73,110,115,116,97,108,108,32, + 105,109,112,111,114,116,108,105,98,32,97,115,32,116,104,101, + 32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32, + 111,102,32,105,109,112,111,114,116,46,114,19,0,0,0,78, + 41,11,114,200,0,0,0,114,14,0,0,0,114,166,0,0, + 0,114,110,0,0,0,114,142,0,0,0,114,152,0,0,0, + 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,116,0,0, + 0,218,8,95,105,110,115,116,97,108,108,114,80,0,0,0, + 114,1,0,0,0,41,3,114,198,0,0,0,114,199,0,0, + 0,114,201,0,0,0,114,10,0,0,0,114,10,0,0,0, + 114,11,0,0,0,114,202,0,0,0,139,4,0,0,115,12, + 0,0,0,0,2,10,2,12,1,12,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,50,114,3,0,0,0,114,116,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,69,0,0,0, + 114,75,0,0,0,114,78,0,0,0,114,85,0,0,0,114, + 96,0,0,0,114,97,0,0,0,114,103,0,0,0,114,79, + 0,0,0,114,129,0,0,0,114,134,0,0,0,114,137,0, + 0,0,114,92,0,0,0,114,81,0,0,0,114,140,0,0, + 0,114,141,0,0,0,114,82,0,0,0,114,142,0,0,0, + 114,152,0,0,0,114,157,0,0,0,114,163,0,0,0,114, + 165,0,0,0,114,170,0,0,0,114,174,0,0,0,90,15, + 95,69,82,82,95,77,83,71,95,80,82,69,70,73,88,114, + 176,0,0,0,114,179,0,0,0,218,6,111,98,106,101,99, + 116,114,180,0,0,0,114,181,0,0,0,114,182,0,0,0, + 114,186,0,0,0,114,192,0,0,0,114,195,0,0,0,114, + 196,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,94,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,18,35,8, + 7,8,47, }; diff --git a/Python/importlib_external.h b/Python/importlib_external.h index 886aa68009ec..a4a20c8efc7c 100644 --- a/Python/importlib_external.h +++ b/Python/importlib_external.h @@ -1931,9 +1931,9 @@ const unsigned char _Py_M__importlib_external[] = { 114,14,116,0,106,1,125,2,124,0,106,2,124,1,124,2, 124,3,131,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,2,124,4,95,5,116,6,124,1, + 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,3, + 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, @@ -1943,491 +1943,491 @@ const unsigned char _Py_M__importlib_external[] = { 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, - 90,9,110,97,109,101,115,112,97,99,101,41,7,114,8,0, - 0,0,114,37,0,0,0,114,4,1,0,0,114,124,0,0, - 0,114,154,0,0,0,114,156,0,0,0,114,227,0,0,0, - 41,6,114,168,0,0,0,114,123,0,0,0,114,37,0,0, - 0,114,177,0,0,0,114,162,0,0,0,114,3,1,0,0, - 114,4,0,0,0,114,4,0,0,0,114,6,0,0,0,114, - 178,0,0,0,125,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,3,0,0,0,67,0, - 0,0,115,30,0,0,0,124,0,106,0,124,1,124,2,131, - 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,178,0,0,0,114,124,0,0,0, - 41,4,114,168,0,0,0,114,123,0,0,0,114,37,0,0, - 0,114,162,0,0,0,114,4,0,0,0,114,4,0,0,0, - 114,6,0,0,0,114,179,0,0,0,149,4,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, - 109,0,0,0,114,108,0,0,0,114,110,0,0,0,114,111, - 0,0,0,114,180,0,0,0,114,249,0,0,0,114,254,0, - 0,0,114,0,1,0,0,114,1,1,0,0,114,4,1,0, - 0,114,178,0,0,0,114,179,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,4,0,0,0,114,6,0,0,0,114, - 248,0,0,0,31,4,0,0,115,22,0,0,0,8,2,4, - 2,12,8,12,13,12,22,12,15,2,1,12,31,2,1,12, - 23,2,1,114,248,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,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,5,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,106,0,135,0,102,1,100,1,100,2, - 132,8,124,4,68,0,131,1,131,1,1,0,113,10,87,0, - 124,3,124,0,95,1,124,1,112,58,100,3,124,0,95,2, - 100,6,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,7,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,4,0,0,0, - 41,2,114,24,0,0,0,114,222,0,0,0,41,1,114,124, - 0,0,0,114,4,0,0,0,114,6,0,0,0,114,224,0, - 0,0,178,4,0,0,115,2,0,0,0,4,0,122,38,70, + 41,7,114,8,0,0,0,114,37,0,0,0,114,4,1,0, + 0,114,124,0,0,0,114,154,0,0,0,114,156,0,0,0, + 114,227,0,0,0,41,6,114,168,0,0,0,114,123,0,0, + 0,114,37,0,0,0,114,177,0,0,0,114,162,0,0,0, + 114,3,1,0,0,114,4,0,0,0,114,4,0,0,0,114, + 6,0,0,0,114,178,0,0,0,125,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,3, + 0,0,0,67,0,0,0,115,30,0,0,0,124,0,106,0, + 124,1,124,2,131,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,178,0,0,0, + 114,124,0,0,0,41,4,114,168,0,0,0,114,123,0,0, + 0,114,37,0,0,0,114,162,0,0,0,114,4,0,0,0, + 114,4,0,0,0,114,6,0,0,0,114,179,0,0,0,149, + 4,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,109,0,0,0,114,108,0,0,0,114,110, + 0,0,0,114,111,0,0,0,114,180,0,0,0,114,249,0, + 0,0,114,254,0,0,0,114,0,1,0,0,114,1,1,0, + 0,114,4,1,0,0,114,178,0,0,0,114,179,0,0,0, + 114,4,0,0,0,114,4,0,0,0,114,4,0,0,0,114, + 6,0,0,0,114,248,0,0,0,31,4,0,0,115,22,0, + 0,0,8,2,4,2,12,8,12,13,12,22,12,15,2,1, + 12,31,2,1,12,23,2,1,114,248,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,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,5,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,106,0,135,0,102, + 1,100,1,100,2,132,8,124,4,68,0,131,1,131,1,1, + 0,113,10,87,0,124,3,124,0,95,1,124,1,112,58,100, + 3,124,0,95,2,100,6,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, + 7,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,4,0,0,0,41,2,114,24,0,0,0,114,222,0,0, + 0,41,1,114,124,0,0,0,114,4,0,0,0,114,6,0, + 0,0,114,224,0,0,0,178,4,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,61,0,0,0,114, + 31,0,0,0,78,114,91,0,0,0,41,7,114,147,0,0, + 0,218,8,95,108,111,97,100,101,114,115,114,37,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,104,0,0,0,114,37,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,164,0,0,0,114,4, + 0,0,0,41,1,114,124,0,0,0,114,6,0,0,0,114, + 182,0,0,0,172,4,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,46,60,108,111,99,97,108,115,62,46,60,103,101,110, - 101,120,112,114,62,114,61,0,0,0,114,31,0,0,0,78, - 114,91,0,0,0,41,7,114,147,0,0,0,218,8,95,108, - 111,97,100,101,114,115,114,37,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,104,0,0,0,114,37,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,164,0,0,0,114,4,0,0,0,41,1, - 114,124,0,0,0,114,6,0,0,0,114,182,0,0,0,172, - 4,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,3,124,0,95,0,100,2,83, - 0,41,4,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,31,0,0,0,78,114,91,0,0,0,41, - 1,114,7,1,0,0,41,1,114,104,0,0,0,114,4,0, - 0,0,114,4,0,0,0,114,6,0,0,0,114,249,0,0, - 0,186,4,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,2,0,0,0,67,0,0,0,115, - 42,0,0,0,124,0,106,0,124,1,131,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,178,0,0,0,114, - 124,0,0,0,114,154,0,0,0,41,3,114,104,0,0,0, - 114,123,0,0,0,114,162,0,0,0,114,4,0,0,0,114, - 4,0,0,0,114,6,0,0,0,114,121,0,0,0,192,4, - 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,124,0,0,0,114,154,0,0,0,41,1,114,165,0,0, - 0,41,7,114,104,0,0,0,114,163,0,0,0,114,123,0, - 0,0,114,37,0,0,0,90,4,115,109,115,108,114,177,0, - 0,0,114,124,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,6,0,0,0,114,4,1,0,0,204,4,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,15,0, - 0,0,67,0,0,0,115,98,1,0,0,100,1,125,3,124, - 1,106,0,100,2,131,1,100,3,25,0,125,4,121,24,116, - 1,124,0,106,2,112,34,116,3,106,4,131,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,10,125,5,89,0,110,2,88,0,124, - 5,124,0,106,7,107,3,114,92,124,0,106,8,131,0,1, - 0,124,5,124,0,95,7,116,9,131,0,114,114,124,0,106, - 10,125,6,124,4,106,11,131,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,106,16,124,10,124,1,124,12,124, - 8,103,1,124,2,131,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,106,16,124,10,124, - 1,124,12,100,8,124,2,131,5,83,0,113,226,87,0,124, - 3,144,1,114,94,116,18,106,19,100,9,124,8,131,2,1, - 0,116,18,106,20,124,1,100,8,131,2,125,13,124,8,103, - 1,124,13,95,21,124,13,83,0,100,8,83,0,41,11,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,61,0,0,0,114,59,0,0,0,114,31,0,0,0, - 114,182,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,114,91,0,0,0,41,22, - 114,34,0,0,0,114,41,0,0,0,114,37,0,0,0,114, - 3,0,0,0,114,47,0,0,0,114,216,0,0,0,114,42, - 0,0,0,114,7,1,0,0,218,11,95,102,105,108,108,95, - 99,97,99,104,101,114,7,0,0,0,114,10,1,0,0,114, - 92,0,0,0,114,9,1,0,0,114,30,0,0,0,114,6, - 1,0,0,114,46,0,0,0,114,4,1,0,0,114,48,0, - 0,0,114,118,0,0,0,114,133,0,0,0,114,158,0,0, - 0,114,154,0,0,0,41,14,114,104,0,0,0,114,123,0, - 0,0,114,177,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,130,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,222,0,0,0,114,163,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,162,0,0,0, - 114,4,0,0,0,114,4,0,0,0,114,6,0,0,0,114, - 178,0,0,0,209,4,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,13,0,0,0,67,0,0,0,115,194, - 0,0,0,124,0,106,0,125,1,121,22,116,1,106,2,124, - 1,112,22,116,1,106,3,131,0,131,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,106,9,100,1,131,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,106,12,100,2,131,1,92, - 3,125,5,125,6,125,7,124,6,114,138,100,3,106,13,124, - 5,124,7,106,14,131,0,131,2,125,8,110,4,124,5,125, - 8,124,3,106,15,124,8,131,1,1,0,113,96,87,0,124, - 3,124,0,95,11,116,7,106,8,106,9,116,16,131,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,61,0,0,0,122,5,123,125,46,123,125,99,1, - 0,0,0,0,0,0,0,2,0,0,0,3,0,0,0,83, - 0,0,0,115,20,0,0,0,104,0,124,0,93,12,125,1, - 124,1,106,0,131,0,146,2,113,4,83,0,114,4,0,0, - 0,41,1,114,92,0,0,0,41,2,114,24,0,0,0,90, - 2,102,110,114,4,0,0,0,114,4,0,0,0,114,6,0, - 0,0,250,9,60,115,101,116,99,111,109,112,62,30,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,37,0,0,0,114,3,0,0,0, - 90,7,108,105,115,116,100,105,114,114,47,0,0,0,114,255, - 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,8,0,0,0,114,9,0, - 0,0,114,10,0,0,0,114,8,1,0,0,114,9,1,0, - 0,114,87,0,0,0,114,50,0,0,0,114,92,0,0,0, - 218,3,97,100,100,114,11,0,0,0,114,10,1,0,0,41, - 9,114,104,0,0,0,114,37,0,0,0,90,8,99,111,110, - 116,101,110,116,115,90,21,108,111,119,101,114,95,115,117,102, - 102,105,120,95,99,111,110,116,101,110,116,115,114,244,0,0, - 0,114,102,0,0,0,114,234,0,0,0,114,222,0,0,0, - 90,8,110,101,119,95,110,97,109,101,114,4,0,0,0,114, - 4,0,0,0,114,6,0,0,0,114,12,1,0,0,1,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,37,0,0,0,41,2,114,48, - 0,0,0,114,103,0,0,0,41,1,114,37,0,0,0,41, - 2,114,168,0,0,0,114,11,1,0,0,114,4,0,0,0, - 114,6,0,0,0,218,24,112,97,116,104,95,104,111,111,107, - 95,102,111,114,95,70,105,108,101,70,105,110,100,101,114,42, - 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,4,0,0,0,41,3,114,168,0, - 0,0,114,11,1,0,0,114,17,1,0,0,114,4,0,0, - 0,41,2,114,168,0,0,0,114,11,1,0,0,114,6,0, - 0,0,218,9,112,97,116,104,95,104,111,111,107,32,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,2,0,0, - 0,67,0,0,0,115,12,0,0,0,100,1,106,0,124,0, - 106,1,131,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,50,0, - 0,0,114,37,0,0,0,41,1,114,104,0,0,0,114,4, - 0,0,0,114,4,0,0,0,114,6,0,0,0,114,243,0, - 0,0,50,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,109,0,0,0,114,108,0,0, - 0,114,110,0,0,0,114,111,0,0,0,114,182,0,0,0, - 114,249,0,0,0,114,127,0,0,0,114,179,0,0,0,114, - 121,0,0,0,114,4,1,0,0,114,178,0,0,0,114,12, - 1,0,0,114,180,0,0,0,114,18,1,0,0,114,243,0, - 0,0,114,4,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,6,0,0,0,114,5,1,0,0,163,4,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,5,1,0,0,99,4,0, - 0,0,0,0,0,0,6,0,0,0,11,0,0,0,67,0, - 0,0,115,146,0,0,0,124,0,106,0,100,1,131,1,125, - 4,124,0,106,0,100,2,131,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,124,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,124,0,0,0,114,220,0,0,0, - 114,215,0,0,0,114,165,0,0,0,218,9,69,120,99,101, - 112,116,105,111,110,41,6,90,2,110,115,114,102,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,124,0,0,0,114,162,0,0,0,114, - 4,0,0,0,114,4,0,0,0,114,6,0,0,0,218,14, - 95,102,105,120,95,117,112,95,109,111,100,117,108,101,56,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,23,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,106,2,131,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,221,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,215,0,0,0,114,88,0,0,0,114,220,0,0,0, - 114,78,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,4,0,0,0,114,4,0,0,0,114, - 6,0,0,0,114,159,0,0,0,79,5,0,0,115,8,0, - 0,0,0,5,12,1,8,1,8,1,114,159,0,0,0,99, - 1,0,0,0,0,0,0,0,12,0,0,0,12,0,0,0, - 67,0,0,0,115,188,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,26,68,0,93,48,125,2,124,2,116, - 1,106,3,107,7,114,58,116,0,106,5,124,2,131,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,5,100, - 6,103,1,102,2,100,7,100,8,100,6,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,9,100,10,132,0,124,6,68,0,131,1,131, - 1,115,142,116,8,130,1,124,6,100,11,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,106,5,124,5,131, - 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,12,131,1,130,1,116,6,124,1,100, - 13,124,8,131,3,1,0,116,6,124,1,100,14,124,7,131, - 3,1,0,116,6,124,1,100,15,100,16,106,10,124,6,131, - 1,131,3,1,0,121,14,116,0,106,5,100,17,131,1,125, - 9,87,0,110,26,4,0,116,9,107,10,144,1,114,52,1, - 0,1,0,1,0,100,18,125,9,89,0,110,2,88,0,116, - 6,124,1,100,17,124,9,131,3,1,0,116,0,106,5,100, - 19,131,1,125,10,116,6,124,1,100,19,124,10,131,3,1, - 0,124,5,100,7,107,2,144,1,114,120,116,0,106,5,100, - 20,131,1,125,11,116,6,124,1,100,21,124,11,131,3,1, - 0,116,6,124,1,100,22,116,11,131,0,131,3,1,0,116, - 12,106,13,116,2,106,14,131,0,131,1,1,0,124,5,100, - 7,107,2,144,1,114,184,116,15,106,16,100,23,131,1,1, - 0,100,24,116,12,107,6,144,1,114,184,100,25,116,17,95, - 18,100,18,83,0,41,27,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,114,52,0,0,0,114,63,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,31,0,0,0,78,41,1,114,33, - 0,0,0,41,2,114,24,0,0,0,114,81,0,0,0,114, - 4,0,0,0,114,4,0,0,0,114,6,0,0,0,114,224, - 0,0,0,115,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,62,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,3, - 0,0,0,114,27,0,0,0,114,23,0,0,0,114,32,0, - 0,0,90,7,95,116,104,114,101,97,100,78,90,8,95,119, - 101,97,107,114,101,102,90,6,119,105,110,114,101,103,114,167, - 0,0,0,114,7,0,0,0,122,4,46,112,121,119,122,6, - 95,100,46,112,121,100,84,41,4,114,52,0,0,0,114,63, - 0,0,0,114,25,1,0,0,114,140,0,0,0,41,19,114, - 118,0,0,0,114,8,0,0,0,114,143,0,0,0,114,236, - 0,0,0,114,109,0,0,0,90,18,95,98,117,105,108,116, - 105,110,95,102,114,111,109,95,110,97,109,101,114,113,0,0, - 0,218,3,97,108,108,218,14,65,115,115,101,114,116,105,111, - 110,69,114,114,111,114,114,103,0,0,0,114,28,0,0,0, - 114,13,0,0,0,114,226,0,0,0,114,147,0,0,0,114, - 24,1,0,0,114,88,0,0,0,114,161,0,0,0,114,166, - 0,0,0,114,170,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,23,0,0,0,114,27,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,4,0,0,0,114,4,0,0,0,114,6,0, - 0,0,218,6,95,115,101,116,117,112,90,5,0,0,115,82, - 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,2,1,14,1,16,2,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,31,1,0,0,99,1,0,0,0,0, - 0,0,0,2,0,0,0,3,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,106,4,116,5,106,6,124,1,142,0, - 103,1,131,1,1,0,116,2,106,7,106,8,116,9,131,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,31,1,0,0,114,159,0,0,0, - 114,8,0,0,0,114,253,0,0,0,114,147,0,0,0,114, - 5,1,0,0,114,18,1,0,0,218,9,109,101,116,97,95, - 112,97,116,104,114,161,0,0,0,114,248,0,0,0,41,2, - 114,30,1,0,0,90,17,115,117,112,112,111,114,116,101,100, - 95,108,111,97,100,101,114,115,114,4,0,0,0,114,4,0, - 0,0,114,6,0,0,0,218,8,95,105,110,115,116,97,108, - 108,158,5,0,0,115,8,0,0,0,0,2,8,1,6,1, - 20,1,114,33,1,0,0,41,1,114,0,0,0,0,41,2, - 114,1,0,0,0,114,2,0,0,0,41,1,114,49,0,0, - 0,41,1,78,41,3,78,78,78,41,3,78,78,78,41,2, - 114,62,0,0,0,114,62,0,0,0,41,1,78,41,1,78, - 41,58,114,111,0,0,0,114,12,0,0,0,90,37,95,67, - 65,83,69,95,73,78,83,69,78,83,73,84,73,86,69,95, - 80,76,65,84,70,79,82,77,83,95,66,89,84,69,83,95, - 75,69,89,114,11,0,0,0,114,13,0,0,0,114,19,0, - 0,0,114,21,0,0,0,114,30,0,0,0,114,40,0,0, - 0,114,41,0,0,0,114,45,0,0,0,114,46,0,0,0, - 114,48,0,0,0,114,58,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, - 17,0,0,0,114,132,0,0,0,114,16,0,0,0,114,20, - 0,0,0,90,17,95,82,65,87,95,77,65,71,73,67,95, - 78,85,77,66,69,82,114,77,0,0,0,114,76,0,0,0, - 114,88,0,0,0,114,78,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,83,0,0,0,114,89,0,0,0,114,95,0,0,0,114, - 99,0,0,0,114,101,0,0,0,114,120,0,0,0,114,127, - 0,0,0,114,139,0,0,0,114,145,0,0,0,114,148,0, - 0,0,114,153,0,0,0,218,6,111,98,106,101,99,116,114, - 160,0,0,0,114,165,0,0,0,114,166,0,0,0,114,181, - 0,0,0,114,191,0,0,0,114,207,0,0,0,114,215,0, - 0,0,114,220,0,0,0,114,226,0,0,0,114,221,0,0, - 0,114,227,0,0,0,114,246,0,0,0,114,248,0,0,0, - 114,5,1,0,0,114,23,1,0,0,114,159,0,0,0,114, - 31,1,0,0,114,33,1,0,0,114,4,0,0,0,114,4, - 0,0,0,114,4,0,0,0,114,6,0,0,0,218,8,60, - 109,111,100,117,108,101,62,8,0,0,0,115,108,0,0,0, - 4,16,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,123, - 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,10,55,10,12, - 10,10,8,14,6,3,4,1,14,67,14,64,14,29,16,110, - 14,41,18,45,18,16,4,3,18,53,14,60,14,42,14,127, - 0,5,14,127,0,22,10,23,8,11,8,68, + 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,3,124,0, + 95,0,100,2,83,0,41,4,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,31,0,0,0,78,114, + 91,0,0,0,41,1,114,7,1,0,0,41,1,114,104,0, + 0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,0, + 0,114,249,0,0,0,186,4,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,2,0,0,0, + 67,0,0,0,115,42,0,0,0,124,0,106,0,124,1,131, + 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, + 178,0,0,0,114,124,0,0,0,114,154,0,0,0,41,3, + 114,104,0,0,0,114,123,0,0,0,114,162,0,0,0,114, + 4,0,0,0,114,4,0,0,0,114,6,0,0,0,114,121, + 0,0,0,192,4,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,124,0,0,0,114,154,0,0,0,41, + 1,114,165,0,0,0,41,7,114,104,0,0,0,114,163,0, + 0,0,114,123,0,0,0,114,37,0,0,0,90,4,115,109, + 115,108,114,177,0,0,0,114,124,0,0,0,114,4,0,0, + 0,114,4,0,0,0,114,6,0,0,0,114,4,1,0,0, + 204,4,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,15,0,0,0,67,0,0,0,115,98,1,0,0, + 100,1,125,3,124,1,106,0,100,2,131,1,100,3,25,0, + 125,4,121,24,116,1,124,0,106,2,112,34,116,3,106,4, + 131,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,10,125,5,89,0, + 110,2,88,0,124,5,124,0,106,7,107,3,114,92,124,0, + 106,8,131,0,1,0,124,5,124,0,95,7,116,9,131,0, + 114,114,124,0,106,10,125,6,124,4,106,11,131,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,106,16,124,10, + 124,1,124,12,124,8,103,1,124,2,131,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, + 106,16,124,10,124,1,124,12,100,8,124,2,131,5,83,0, + 113,226,87,0,124,3,144,1,114,94,116,18,106,19,100,9, + 124,8,131,2,1,0,116,18,106,20,124,1,100,8,131,2, + 125,13,124,8,103,1,124,13,95,21,124,13,83,0,100,8, + 83,0,41,11,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,61,0,0,0,114,59,0,0,0, + 114,31,0,0,0,114,182,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,114,91, + 0,0,0,41,22,114,34,0,0,0,114,41,0,0,0,114, + 37,0,0,0,114,3,0,0,0,114,47,0,0,0,114,216, + 0,0,0,114,42,0,0,0,114,7,1,0,0,218,11,95, + 102,105,108,108,95,99,97,99,104,101,114,7,0,0,0,114, + 10,1,0,0,114,92,0,0,0,114,9,1,0,0,114,30, + 0,0,0,114,6,1,0,0,114,46,0,0,0,114,4,1, + 0,0,114,48,0,0,0,114,118,0,0,0,114,133,0,0, + 0,114,158,0,0,0,114,154,0,0,0,41,14,114,104,0, + 0,0,114,123,0,0,0,114,177,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,130,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,222,0,0, + 0,114,163,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,162,0,0,0,114,4,0,0,0,114,4,0,0,0,114, + 6,0,0,0,114,178,0,0,0,209,4,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,13,0,0,0,67, + 0,0,0,115,194,0,0,0,124,0,106,0,125,1,121,22, + 116,1,106,2,124,1,112,22,116,1,106,3,131,0,131,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,106,9,100,1,131,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,106,12, + 100,2,131,1,92,3,125,5,125,6,125,7,124,6,114,138, + 100,3,106,13,124,5,124,7,106,14,131,0,131,2,125,8, + 110,4,124,5,125,8,124,3,106,15,124,8,131,1,1,0, + 113,96,87,0,124,3,124,0,95,11,116,7,106,8,106,9, + 116,16,131,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,61,0,0,0,122,5,123,125, + 46,123,125,99,1,0,0,0,0,0,0,0,2,0,0,0, + 3,0,0,0,83,0,0,0,115,20,0,0,0,104,0,124, + 0,93,12,125,1,124,1,106,0,131,0,146,2,113,4,83, + 0,114,4,0,0,0,41,1,114,92,0,0,0,41,2,114, + 24,0,0,0,90,2,102,110,114,4,0,0,0,114,4,0, + 0,0,114,6,0,0,0,250,9,60,115,101,116,99,111,109, + 112,62,30,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,37,0,0,0, + 114,3,0,0,0,90,7,108,105,115,116,100,105,114,114,47, + 0,0,0,114,255,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,8,0, + 0,0,114,9,0,0,0,114,10,0,0,0,114,8,1,0, + 0,114,9,1,0,0,114,87,0,0,0,114,50,0,0,0, + 114,92,0,0,0,218,3,97,100,100,114,11,0,0,0,114, + 10,1,0,0,41,9,114,104,0,0,0,114,37,0,0,0, + 90,8,99,111,110,116,101,110,116,115,90,21,108,111,119,101, + 114,95,115,117,102,102,105,120,95,99,111,110,116,101,110,116, + 115,114,244,0,0,0,114,102,0,0,0,114,234,0,0,0, + 114,222,0,0,0,90,8,110,101,119,95,110,97,109,101,114, + 4,0,0,0,114,4,0,0,0,114,6,0,0,0,114,12, + 1,0,0,1,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,37,0,0, + 0,41,2,114,48,0,0,0,114,103,0,0,0,41,1,114, + 37,0,0,0,41,2,114,168,0,0,0,114,11,1,0,0, + 114,4,0,0,0,114,6,0,0,0,218,24,112,97,116,104, + 95,104,111,111,107,95,102,111,114,95,70,105,108,101,70,105, + 110,100,101,114,42,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,4,0,0,0, + 41,3,114,168,0,0,0,114,11,1,0,0,114,17,1,0, + 0,114,4,0,0,0,41,2,114,168,0,0,0,114,11,1, + 0,0,114,6,0,0,0,218,9,112,97,116,104,95,104,111, + 111,107,32,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,2,0,0,0,67,0,0,0,115,12,0,0,0,100, + 1,106,0,124,0,106,1,131,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,50,0,0,0,114,37,0,0,0,41,1,114,104, + 0,0,0,114,4,0,0,0,114,4,0,0,0,114,6,0, + 0,0,114,243,0,0,0,50,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,109,0,0, + 0,114,108,0,0,0,114,110,0,0,0,114,111,0,0,0, + 114,182,0,0,0,114,249,0,0,0,114,127,0,0,0,114, + 179,0,0,0,114,121,0,0,0,114,4,1,0,0,114,178, + 0,0,0,114,12,1,0,0,114,180,0,0,0,114,18,1, + 0,0,114,243,0,0,0,114,4,0,0,0,114,4,0,0, + 0,114,4,0,0,0,114,6,0,0,0,114,5,1,0,0, + 163,4,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,5,1, + 0,0,99,4,0,0,0,0,0,0,0,6,0,0,0,11, + 0,0,0,67,0,0,0,115,146,0,0,0,124,0,106,0, + 100,1,131,1,125,4,124,0,106,0,100,2,131,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,124,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,124,0,0,0, + 114,220,0,0,0,114,215,0,0,0,114,165,0,0,0,218, + 9,69,120,99,101,112,116,105,111,110,41,6,90,2,110,115, + 114,102,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,124,0,0,0,114, + 162,0,0,0,114,4,0,0,0,114,4,0,0,0,114,6, + 0,0,0,218,14,95,102,105,120,95,117,112,95,109,111,100, + 117,108,101,56,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,23, + 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,106,2,131,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,221,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,215,0,0,0,114,88,0,0,0, + 114,220,0,0,0,114,78,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,4,0,0,0,114, + 4,0,0,0,114,6,0,0,0,114,159,0,0,0,79,5, + 0,0,115,8,0,0,0,0,5,12,1,8,1,8,1,114, + 159,0,0,0,99,1,0,0,0,0,0,0,0,12,0,0, + 0,12,0,0,0,67,0,0,0,115,188,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,26,68,0,93,48, + 125,2,124,2,116,1,106,3,107,7,114,58,116,0,106,5, + 124,2,131,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,5,100,6,103,1,102,2,100,7,100,8,100,6, + 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,9,100,10,132,0,124,6, + 68,0,131,1,131,1,115,142,116,8,130,1,124,6,100,11, + 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, + 106,5,124,5,131,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,12,131,1,130,1, + 116,6,124,1,100,13,124,8,131,3,1,0,116,6,124,1, + 100,14,124,7,131,3,1,0,116,6,124,1,100,15,100,16, + 106,10,124,6,131,1,131,3,1,0,121,14,116,0,106,5, + 100,17,131,1,125,9,87,0,110,26,4,0,116,9,107,10, + 144,1,114,52,1,0,1,0,1,0,100,18,125,9,89,0, + 110,2,88,0,116,6,124,1,100,17,124,9,131,3,1,0, + 116,0,106,5,100,19,131,1,125,10,116,6,124,1,100,19, + 124,10,131,3,1,0,124,5,100,7,107,2,144,1,114,120, + 116,0,106,5,100,20,131,1,125,11,116,6,124,1,100,21, + 124,11,131,3,1,0,116,6,124,1,100,22,116,11,131,0, + 131,3,1,0,116,12,106,13,116,2,106,14,131,0,131,1, + 1,0,124,5,100,7,107,2,144,1,114,184,116,15,106,16, + 100,23,131,1,1,0,100,24,116,12,107,6,144,1,114,184, + 100,25,116,17,95,18,100,18,83,0,41,27,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,114,52,0,0,0, + 114,63,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,31,0,0,0, + 78,41,1,114,33,0,0,0,41,2,114,24,0,0,0,114, + 81,0,0,0,114,4,0,0,0,114,4,0,0,0,114,6, + 0,0,0,114,224,0,0,0,115,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,62, + 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,3,0,0,0,114,27,0,0,0,114,23,0, + 0,0,114,32,0,0,0,90,7,95,116,104,114,101,97,100, + 78,90,8,95,119,101,97,107,114,101,102,90,6,119,105,110, + 114,101,103,114,167,0,0,0,114,7,0,0,0,122,4,46, + 112,121,119,122,6,95,100,46,112,121,100,84,41,4,114,52, + 0,0,0,114,63,0,0,0,114,25,1,0,0,114,140,0, + 0,0,41,19,114,118,0,0,0,114,8,0,0,0,114,143, + 0,0,0,114,236,0,0,0,114,109,0,0,0,90,18,95, + 98,117,105,108,116,105,110,95,102,114,111,109,95,110,97,109, + 101,114,113,0,0,0,218,3,97,108,108,218,14,65,115,115, + 101,114,116,105,111,110,69,114,114,111,114,114,103,0,0,0, + 114,28,0,0,0,114,13,0,0,0,114,226,0,0,0,114, + 147,0,0,0,114,24,1,0,0,114,88,0,0,0,114,161, + 0,0,0,114,166,0,0,0,114,170,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,23,0,0,0,114,27,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,4,0,0,0,114,4,0, + 0,0,114,6,0,0,0,218,6,95,115,101,116,117,112,90, + 5,0,0,115,82,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,2,1,14,1, + 16,2,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,31,1,0,0,99, + 1,0,0,0,0,0,0,0,2,0,0,0,3,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,106,4,116,5,106, + 6,124,1,142,0,103,1,131,1,1,0,116,2,106,7,106, + 8,116,9,131,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,31,1,0,0, + 114,159,0,0,0,114,8,0,0,0,114,253,0,0,0,114, + 147,0,0,0,114,5,1,0,0,114,18,1,0,0,218,9, + 109,101,116,97,95,112,97,116,104,114,161,0,0,0,114,248, + 0,0,0,41,2,114,30,1,0,0,90,17,115,117,112,112, + 111,114,116,101,100,95,108,111,97,100,101,114,115,114,4,0, + 0,0,114,4,0,0,0,114,6,0,0,0,218,8,95,105, + 110,115,116,97,108,108,158,5,0,0,115,8,0,0,0,0, + 2,8,1,6,1,20,1,114,33,1,0,0,41,1,114,0, + 0,0,0,41,2,114,1,0,0,0,114,2,0,0,0,41, + 1,114,49,0,0,0,41,1,78,41,3,78,78,78,41,3, + 78,78,78,41,2,114,62,0,0,0,114,62,0,0,0,41, + 1,78,41,1,78,41,58,114,111,0,0,0,114,12,0,0, + 0,90,37,95,67,65,83,69,95,73,78,83,69,78,83,73, + 84,73,86,69,95,80,76,65,84,70,79,82,77,83,95,66, + 89,84,69,83,95,75,69,89,114,11,0,0,0,114,13,0, + 0,0,114,19,0,0,0,114,21,0,0,0,114,30,0,0, + 0,114,40,0,0,0,114,41,0,0,0,114,45,0,0,0, + 114,46,0,0,0,114,48,0,0,0,114,58,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,17,0,0,0,114,132,0,0,0,114,16, + 0,0,0,114,20,0,0,0,90,17,95,82,65,87,95,77, + 65,71,73,67,95,78,85,77,66,69,82,114,77,0,0,0, + 114,76,0,0,0,114,88,0,0,0,114,78,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,83,0,0,0,114,89,0,0,0,114, + 95,0,0,0,114,99,0,0,0,114,101,0,0,0,114,120, + 0,0,0,114,127,0,0,0,114,139,0,0,0,114,145,0, + 0,0,114,148,0,0,0,114,153,0,0,0,218,6,111,98, + 106,101,99,116,114,160,0,0,0,114,165,0,0,0,114,166, + 0,0,0,114,181,0,0,0,114,191,0,0,0,114,207,0, + 0,0,114,215,0,0,0,114,220,0,0,0,114,226,0,0, + 0,114,221,0,0,0,114,227,0,0,0,114,246,0,0,0, + 114,248,0,0,0,114,5,1,0,0,114,23,1,0,0,114, + 159,0,0,0,114,31,1,0,0,114,33,1,0,0,114,4, + 0,0,0,114,4,0,0,0,114,4,0,0,0,114,6,0, + 0,0,218,8,60,109,111,100,117,108,101,62,8,0,0,0, + 115,108,0,0,0,4,16,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,123,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,10,55,10,12,10,10,8,14,6,3,4,1,14,67,14, + 64,14,29,16,110,14,41,18,45,18,16,4,3,18,53,14, + 60,14,42,14,127,0,5,14,127,0,22,10,23,8,11,8, + 68, }; From webhook-mailer at python.org Fri Feb 2 23:49:52 2018 From: webhook-mailer at python.org (Eric Snow) Date: Sat, 03 Feb 2018 04:49:52 -0000 Subject: [Python-checkins] bpo-32604: Fix memory leaks in the new _xxsubinterpreters module. (#5507) Message-ID: https://github.com/python/cpython/commit/4e9da0d163731caa79811c723c703ee416c31826 commit: 4e9da0d163731caa79811c723c703ee416c31826 branch: master author: Eric Snow committer: GitHub date: 2018-02-02T21:49:49-07:00 summary: bpo-32604: Fix memory leaks in the new _xxsubinterpreters module. (#5507) 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 2b170443a3b6..8d72ca200214 100644 --- a/Lib/test/test__xxsubinterpreters.py +++ b/Lib/test/test__xxsubinterpreters.py @@ -362,13 +362,15 @@ def test_bad_id(self): def test_from_current(self): main, = interpreters.list_all() id = interpreters.create() - script = dedent(""" + script = dedent(f""" import _xxsubinterpreters as _interpreters - _interpreters.destroy({}) - """).format(id) + try: + _interpreters.destroy({id}) + except RuntimeError: + pass + """) - with self.assertRaises(RuntimeError): - interpreters.run_string(id, script) + interpreters.run_string(id, script) self.assertEqual(set(interpreters.list_all()), {main, id}) def test_from_sibling(self): @@ -761,12 +763,12 @@ def __int__(self): self.assertEqual(int(cid), 10) def test_bad_id(self): - ids = [-1, 2**64, "spam"] - for cid in ids: + 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()) diff --git a/Modules/_xxsubinterpretersmodule.c b/Modules/_xxsubinterpretersmodule.c index d2b5f26fae1d..7829b4cd9511 100644 --- a/Modules/_xxsubinterpretersmodule.c +++ b/Modules/_xxsubinterpretersmodule.c @@ -7,6 +7,22 @@ #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) { @@ -31,10 +47,13 @@ _coerce_id(PyObject *id) } return -1; } - long long cid = PyLong_AsLongLong(id); + int64_t cid = PyLong_AsLongLong(id); + Py_DECREF(id); if (cid == -1 && PyErr_Occurred() != NULL) { - PyErr_SetString(PyExc_ValueError, - "'id' must be a non-negative int"); + if (!PyErr_ExceptionMatches(PyExc_OverflowError)) { + PyErr_SetString(PyExc_ValueError, + "'id' must be a non-negative int"); + } return -1; } if (cid < 0) { @@ -42,92 +61,131 @@ _coerce_id(PyObject *id) "'id' must be a non-negative int"); return -1; } - if (cid > INT64_MAX) { - PyErr_SetString(PyExc_ValueError, - "'id' too large (must be 64-bit int)"); - return -1; - } return cid; } + /* data-sharing-specific code ***********************************************/ -typedef struct _shareditem { - Py_UNICODE *name; - Py_ssize_t namelen; +struct _sharednsitem { + char *name; _PyCrossInterpreterData data; -} _shareditem; +}; + +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; +} -void -_sharedns_clear(_shareditem *shared) +static void +_sharedns_free(_sharedns *shared) { - for (_shareditem *item=shared; item->name != NULL; item += 1) { - _PyCrossInterpreterData_Release(&item->data); + for (Py_ssize_t i=0; i < shared->len; i++) { + _sharednsitem_clear(&shared->items[i]); } + PyMem_Free(shared->items); + PyMem_Free(shared); } -static _shareditem * -_get_shared_ns(PyObject *shareable, Py_ssize_t *lenp) +static _sharedns * +_get_shared_ns(PyObject *shareable) { if (shareable == NULL || shareable == Py_None) { - *lenp = 0; return NULL; } Py_ssize_t len = PyDict_Size(shareable); - *lenp = len; if (len == 0) { return NULL; } - _shareditem *shared = PyMem_NEW(_shareditem, len+1); + _sharedns *shared = _sharedns_new(len); if (shared == NULL) { return NULL; } - for (Py_ssize_t i=0; i < len; i++) { - *(shared + i) = (_shareditem){0}; - } 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; } - _shareditem *item = shared + i; - - if (_PyObject_GetCrossInterpreterData(value, &item->data) != 0) { + if (_sharednsitem_init(&shared->items[i], key, value) != 0) { break; } - item->name = PyUnicode_AsUnicodeAndSize(key, &item->namelen); - if (item->name == NULL) { - _PyCrossInterpreterData_Release(&item->data); - break; - } - (item + 1)->name = NULL; // Mark the next one as the last. } if (PyErr_Occurred()) { - _sharedns_clear(shared); - PyMem_Free(shared); + _sharedns_free(shared); return NULL; } return shared; } static int -_shareditem_apply(_shareditem *item, PyObject *ns) +_sharedns_apply(_sharedns *shared, PyObject *ns) { - PyObject *name = PyUnicode_FromUnicode(item->name, item->namelen); - if (name == NULL) { - return 1; - } - PyObject *value = _PyCrossInterpreterData_NewObject(&item->data); - if (value == NULL) { - Py_DECREF(name); - return 1; + for (Py_ssize_t i=0; i < shared->len; i++) { + if (_sharednsitem_apply(&shared->items[i], ns) != 0) { + return -1; + } } - int res = PyDict_SetItem(ns, name, value); - Py_DECREF(name); - Py_DECREF(value); - return res; + return 0; } // Ultimately we'd like to preserve enough information about the @@ -136,65 +194,117 @@ _shareditem_apply(_shareditem *item, PyObject *ns) // of the exception in the calling interpreter. typedef struct _sharedexception { + char *name; char *msg; } _sharedexception; static _sharedexception * -_get_shared_exception(void) +_sharedexception_new(void) { _sharedexception *err = PyMem_NEW(_sharedexception, 1); if (err == NULL) { + PyErr_NoMemory(); return NULL; } - PyObject *exc; - PyObject *value; - PyObject *tb; - PyErr_Fetch(&exc, &value, &tb); - PyObject *msg; - if (value == NULL) { - msg = PyUnicode_FromFormat("%S", exc); - } - else { - msg = PyUnicode_FromFormat("%S: %S", exc, value); - } - if (msg == NULL) { - err->msg = "unable to format exception"; - return err; + err->name = NULL; + err->msg = NULL; + return err; +} + +static void +_sharedexception_clear(_sharedexception *exc) +{ + if (exc->name != NULL) { + PyMem_Free(exc->name); } - err->msg = (char *)PyUnicode_AsUTF8(msg); - if (err->msg == NULL) { - err->msg = "unable to encode exception"; + if (exc->msg != NULL) { + PyMem_Free(exc->msg); } - return err; } -static PyObject * RunFailedError; +static void +_sharedexception_free(_sharedexception *exc) +{ + _sharedexception_clear(exc); + PyMem_Free(exc); +} -static int -interp_exceptions_init(PyObject *ns) +static _sharedexception * +_sharedexception_bind(PyObject *exctype, PyObject *exc, PyObject *tb) { - // XXX Move the exceptions into per-module memory? + assert(exctype != NULL); + char *failure = NULL; - // An uncaught exception came out of interp_run_string(). - RunFailedError = PyErr_NewException("_xxsubinterpreters.RunFailedError", - PyExc_RuntimeError, NULL); - if (RunFailedError == NULL) { - return -1; + _sharedexception *err = _sharedexception_new(); + if (err == NULL) { + goto finally; } - if (PyDict_SetItemString(ns, "RunFailedError", RunFailedError) != 0) { - return -1; + + 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; } - return 0; + 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 -_apply_shared_exception(_sharedexception *exc) +_sharedexception_apply(_sharedexception *exc, PyObject *wrapperclass) { - PyErr_SetString(RunFailedError, exc->msg); + 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 */ + +/* channel-specific code ****************************************************/ static PyObject *ChannelError; static PyObject *ChannelNotFoundError; @@ -249,6 +359,139 @@ channel_exceptions_init(PyObject *ns) 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 { @@ -262,23 +505,28 @@ _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_all(_channelend *end) { +_channelend_free(_channelend *end) +{ + PyMem_Free(end); +} + +static void +_channelend_free_all(_channelend *end) +{ while (end != NULL) { _channelend *last = end; end = end->next; - PyMem_Free(last); + _channelend_free(last); } } @@ -300,24 +548,7 @@ _channelend_find(_channelend *first, int64_t interp, _channelend **pprev) return end; } -struct _channelitem; - -typedef struct _channelitem { - _PyCrossInterpreterData *data; - struct _channelitem *next; -} _channelitem; - -struct _channel; - -typedef struct _channel { - PyThread_type_lock mutex; - - int open; - - int64_t count; - _channelitem *first; - _channelitem *last; - +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 @@ -326,39 +557,43 @@ typedef struct _channel { int64_t numrecvopen; _channelend *send; _channelend *recv; -} _PyChannelState; +} _channelends; -static _PyChannelState * -_channel_new(void) +static _channelends * +_channelends_new(void) { - _PyChannelState *chan = PyMem_NEW(_PyChannelState, 1); - if (chan == NULL) { + _channelends *ends = PyMem_NEW(_channelends, 1); + if (ends== 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->open = 1; + ends->numsendopen = 0; + ends->numrecvopen = 0; + ends->send = NULL; + ends->recv = NULL; + return ends; +} - chan->count = 0; - chan->first = NULL; - chan->last = NULL; +static void +_channelends_clear(_channelends *ends) +{ + _channelend_free_all(ends->send); + ends->send = NULL; + ends->numsendopen = 0; - chan->numsendopen = 0; - chan->numrecvopen = 0; - chan->send = NULL; - chan->recv = NULL; + _channelend_free_all(ends->recv); + ends->recv = NULL; + ends->numrecvopen = 0; +} - return chan; +static void +_channelends_free(_channelends *ends) +{ + _channelends_clear(ends); + PyMem_Free(ends); } static _channelend * -_channel_add_end(_PyChannelState *chan, _channelend *prev, int64_t interp, +_channelends_add(_channelends *ends, _channelend *prev, int64_t interp, int send) { _channelend *end = _channelend_new(interp); @@ -368,137 +603,163 @@ _channel_add_end(_PyChannelState *chan, _channelend *prev, int64_t interp, if (prev == NULL) { if (send) { - chan->send = end; + ends->send = end; } else { - chan->recv = end; + ends->recv = end; } } else { prev->next = end; } if (send) { - chan->numsendopen += 1; + ends->numsendopen += 1; } else { - chan->numrecvopen += 1; + ends->numrecvopen += 1; } return end; } -static _channelend * -_channel_associate_end(_PyChannelState *chan, int64_t interp, int send) +static int +_channelends_associate(_channelends *ends, int64_t interp, int send) { - if (!chan->open) { - PyErr_SetString(ChannelClosedError, "channel closed"); - return NULL; - } - _channelend *prev; - _channelend *end = _channelend_find(send ? chan->send : chan->recv, + _channelend *end = _channelend_find(send ? ends->send : ends->recv, interp, &prev); if (end != NULL) { if (!end->open) { PyErr_SetString(ChannelClosedError, "channel already closed"); - return NULL; + return -1; } // already associated - return end; + return 0; + } + if (_channelends_add(ends, prev, interp, send) == NULL) { + return -1; } - return _channel_add_end(chan, prev, interp, send); + 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 -_channel_close_channelend(_PyChannelState *chan, _channelend *end, int send) +_channelends_close_end(_channelends *ends, _channelend *end, int send) { end->open = 0; if (send) { - chan->numsendopen -= 1; + ends->numsendopen -= 1; } else { - chan->numrecvopen -= 1; + ends->numrecvopen -= 1; } } static int -_channel_close_interpreter(_PyChannelState *chan, int64_t interp, int which) +_channelends_close_interpreter(_channelends *ends, 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; - } - _channelend *prev; _channelend *end; if (which >= 0) { // send/both - end = _channelend_find(chan->send, interp, &prev); + end = _channelend_find(ends->send, interp, &prev); if (end == NULL) { // never associated so add it - end = _channel_add_end(chan, prev, interp, 1); + end = _channelends_add(ends, prev, interp, 1); if (end == NULL) { - goto done; + return -1; } } - _channel_close_channelend(chan, end, 1); + _channelends_close_end(ends, end, 1); } if (which <= 0) { // recv/both - end = _channelend_find(chan->recv, interp, &prev); + end = _channelend_find(ends->recv, interp, &prev); if (end == NULL) { // never associated so add it - end = _channel_add_end(chan, prev, interp, 0); + end = _channelends_add(ends, prev, interp, 0); if (end == NULL) { - goto done; + return -1; } } - _channel_close_channelend(chan, end, 0); - } - - if (chan->numsendopen == 0 && chan->numrecvopen == 0) { - if (chan->send != NULL || chan->recv != NULL) { - chan->open = 0; - } + _channelends_close_end(ends, end, 0); } - - res = 0; -done: - PyThread_release_lock(chan->mutex); - return res; + return 0; } -static int -_channel_close_all(_PyChannelState *chan) +static void +_channelends_close_all(_channelends *ends) { - int res = -1; - PyThread_acquire_lock(chan->mutex, WAIT_LOCK); + // 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); + } - if (!chan->open) { - PyErr_SetString(ChannelClosedError, "channel already closed"); - goto done; + // Ensure all the "recv"-associated interpreters are closed. + for (end = ends->recv; end != NULL; end = end->next) { + _channelends_close_end(ends, end, 0); } +} - chan->open = 0; +/* channels */ - // We *could* also just leave these in place, since we've marked - // the channel as closed already. +struct _channel; - // Ensure all the "send"-associated interpreters are closed. - _channelend *end; - for (end = chan->send; end != NULL; end = end->next) { - _channel_close_channelend(chan, end, 1); - } +typedef struct _channel { + PyThread_type_lock mutex; + _channelqueue *queue; + _channelends *ends; + int open; +} _PyChannelState; - // Ensure all the "recv"-associated interpreters are closed. - for (end = chan->recv; end != NULL; end = end->next) { - _channel_close_channelend(chan, end, 0); +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; +} - res = 0; -done: +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); - return res; + + PyThread_free_lock(chan->mutex); + PyMem_Free(chan); } static int @@ -506,24 +767,19 @@ _channel_add(_PyChannelState *chan, int64_t interp, _PyCrossInterpreterData *data) { int res = -1; - PyThread_acquire_lock(chan->mutex, WAIT_LOCK); - if (_channel_associate_end(chan, interp, 1) == NULL) { + + if (!chan->open) { + PyErr_SetString(ChannelClosedError, "channel closed"); goto done; } - - _channelitem *item = PyMem_NEW(_channelitem, 1); - if (item == NULL) { + if (_channelends_associate(chan->ends, interp, 1) != 0) { goto done; } - item->data = data; - item->next = NULL; - chan->count += 1; - if (chan->first == NULL) { - chan->first = item; + if (_channelqueue_put(chan->queue, data) != 0) { + goto done; } - chan->last = item; res = 0; done: @@ -536,56 +792,68 @@ _channel_next(_PyChannelState *chan, int64_t interp) { _PyCrossInterpreterData *data = NULL; PyThread_acquire_lock(chan->mutex, WAIT_LOCK); - if (_channel_associate_end(chan, interp, 0) == NULL) { - goto done; - } - _channelitem *item = chan->first; - if (item == NULL) { + if (!chan->open) { + PyErr_SetString(ChannelClosedError, "channel closed"); goto done; } - chan->first = item->next; - if (chan->last == item) { - chan->last = NULL; + if (_channelends_associate(chan->ends, interp, 0) != 0) { + goto done; } - chan->count -= 1; - - data = item->data; - PyMem_Free(item); + data = _channelqueue_get(chan->queue); done: PyThread_release_lock(chan->mutex); return data; } -static void -_channel_clear(_PyChannelState *chan) +static int +_channel_close_interpreter(_PyChannelState *chan, int64_t interp, int which) { - _channelitem *item = chan->first; - while (item != NULL) { - _PyCrossInterpreterData_Release(item->data); - PyMem_Free(item->data); - _channelitem *last = item; - item = item->next; - PyMem_Free(last); + PyThread_acquire_lock(chan->mutex, WAIT_LOCK); + + int res = -1; + if (!chan->open) { + PyErr_SetString(ChannelClosedError, "channel already closed"); + goto done; } - chan->first = NULL; - chan->last = NULL; + + 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 void -_channel_free(_PyChannelState *chan) +static int +_channel_close_all(_PyChannelState *chan) { + int res = -1; PyThread_acquire_lock(chan->mutex, WAIT_LOCK); - _channel_clear(chan); - _channelend_free_all(chan->send); - _channelend_free_all(chan->recv); - PyThread_release_lock(chan->mutex); - PyThread_free_lock(chan->mutex); - PyMem_Free(chan); + 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 { @@ -609,6 +877,22 @@ _channelref_new(int64_t id, _PyChannelState *chan) 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) { @@ -640,7 +924,6 @@ _channels_init(_channels *channels) if (channels->mutex == NULL) { channels->mutex = PyThread_allocate_lock(); if (channels->mutex == NULL) { - PyMem_Free(channels); PyErr_SetString(ChannelError, "can't initialize mutex for channel management"); return -1; @@ -752,6 +1035,9 @@ _channels_close(_channels *channels, int64_t cid, _PyChannelState **pchan) if (pchan != NULL) { *pchan = ref->chan; } + else { + _channel_free(ref->chan); + } ref->chan = NULL; } @@ -776,7 +1062,7 @@ _channels_remove_ref(_channels *channels, _channelref *ref, _channelref *prev, if (pchan != NULL) { *pchan = ref->chan; } - PyMem_Free(ref); + _channelref_free(ref); } static int @@ -974,6 +1260,7 @@ _channel_recv(_channels *channels, int64_t id) return NULL; } _PyCrossInterpreterData_Release(data); + PyMem_Free(data); return obj; } @@ -995,7 +1282,7 @@ _channel_drop(_channels *channels, int64_t id, int send, int recv) // 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); + int res = _channel_close_interpreter(chan, interp->id, send-recv); PyThread_release_lock(mutex); return res; } @@ -1078,6 +1365,7 @@ channelid_new(PyTypeObject *cls, PyObject *args, PyObject *kwds) "'send' and 'recv' cannot both be False"); return NULL; } + int end = 0; if (send == 1) { if (recv == 0 || recv == -1) { @@ -1176,7 +1464,9 @@ channelid_hash(PyObject *self) if (id == NULL) { return -1; } - return PyObject_Hash(id); + Py_hash_t hash = PyObject_Hash(id); + Py_DECREF(id); + return hash; } static PyObject * @@ -1208,11 +1498,11 @@ channelid_richcompare(PyObject *self, PyObject *other, int op) Py_RETURN_NOTIMPLEMENTED; } int64_t othercid = PyLong_AsLongLong(other); - // XXX decref other here? + Py_DECREF(other); if (othercid == -1 && PyErr_Occurred() != NULL) { return NULL; } - if (othercid < 0 || othercid > INT64_MAX) { + if (othercid < 0) { equal = 0; } else { @@ -1338,7 +1628,30 @@ static PyTypeObject ChannelIDtype = { NULL, /* tp_new */ }; -/* interpreter-specific functions *******************************************/ + +/* 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 PyInterpreterState * _look_up(PyObject *requested_id) @@ -1396,10 +1709,12 @@ _ensure_not_running(PyInterpreterState *interp) static int _run_script(PyInterpreterState *interp, const char *codestr, - _shareditem *shared, Py_ssize_t num_shared, - _sharedexception **exc) + _sharedns *shared, _sharedexception **exc) { - assert(num_shared >= 0); + PyObject *exctype = NULL; + PyObject *excval = NULL; + PyObject *tb = NULL; + PyObject *main_mod = PyMapping_GetItemString(interp->modules, "__main__"); if (main_mod == NULL) { goto error; @@ -1413,12 +1728,9 @@ _run_script(PyInterpreterState *interp, const char *codestr, // Apply the cross-interpreter data. if (shared != NULL) { - for (Py_ssize_t i=0; i < num_shared; i++) { - _shareditem *item = &shared[i]; - if (_shareditem_apply(item, ns) != 0) { - Py_DECREF(ns); - goto error; - } + if (_sharedns_apply(shared, ns) != 0) { + Py_DECREF(ns); + goto error; } } @@ -1432,11 +1744,25 @@ _run_script(PyInterpreterState *interp, const char *codestr, Py_DECREF(result); // We throw away the result. } + *exc = NULL; return 0; error: - *exc = _get_shared_exception(); - PyErr_Clear(); + 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; } @@ -1448,8 +1774,7 @@ _run_script_in_interpreter(PyInterpreterState *interp, const char *codestr, return -1; } - Py_ssize_t num_shared = -1; - _shareditem *shared = _get_shared_ns(shareables, &num_shared); + _sharedns *shared = _get_shared_ns(shareables); if (shared == NULL && PyErr_Occurred()) { return -1; } @@ -1460,7 +1785,7 @@ _run_script_in_interpreter(PyInterpreterState *interp, const char *codestr, // Run the script. _sharedexception *exc = NULL; - int result = _run_script(interp, codestr, shared, num_shared, &exc); + int result = _run_script(interp, codestr, shared, &exc); // Switch back. if (save_tstate != NULL) { @@ -1469,8 +1794,8 @@ _run_script_in_interpreter(PyInterpreterState *interp, const char *codestr, // Propagate any exception out to the caller. if (exc != NULL) { - _apply_shared_exception(exc); - PyMem_Free(exc); + _sharedexception_apply(exc, RunFailedError); + _sharedexception_free(exc); } else if (result != 0) { // We were unable to allocate a shared exception. @@ -1478,8 +1803,7 @@ _run_script_in_interpreter(PyInterpreterState *interp, const char *codestr, } if (shared != NULL) { - _sharedns_clear(shared); - PyMem_Free(shared); + _sharedns_free(shared); } return result; @@ -1612,7 +1936,9 @@ interp_list_all(PyObject *self) return NULL; } // insert at front of list - if (PyList_Insert(ids, 0, id) < 0) { + int res = PyList_Insert(ids, 0, id); + Py_DECREF(id); + if (res < 0) { Py_DECREF(ids); return NULL; } @@ -1822,11 +2148,11 @@ channel_list_all(PyObject *self) } PyObject *ids = PyList_New((Py_ssize_t)count); if (ids == NULL) { - // XXX free cids - return NULL; + goto finally; } - for (int64_t i=0; i < count; cids++, i++) { - PyObject *id = (PyObject *)newchannelid(&ChannelIDtype, *cids, 0, + 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); @@ -1835,7 +2161,9 @@ channel_list_all(PyObject *self) } PyList_SET_ITEM(ids, i, id); } - // XXX free cids + +finally: + PyMem_Free(cids); return ids; } diff --git a/Python/pystate.c b/Python/pystate.c index a474549a8c73..8dbda73de701 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -1242,6 +1242,7 @@ _PyCrossInterpreterData_Lookup(PyObject *obj) break; } } + Py_DECREF(cls); PyThread_release_lock(_PyRuntime.xidregistry.mutex); return getdata; } From webhook-mailer at python.org Sat Feb 3 00:52:37 2018 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Sat, 03 Feb 2018 05:52:37 -0000 Subject: [Python-checkins] [3.6] bpo-30928: prepare idlelib/NEWS.txt for 3.6.5 entries. (#5508) Message-ID: https://github.com/python/cpython/commit/72584d23a54855ef5843d7475b7c5a904e3ef713 commit: 72584d23a54855ef5843d7475b7c5a904e3ef713 branch: 3.6 author: Terry Jan Reedy committer: GitHub date: 2018-02-03T00:52:34-05:00 summary: [3.6] bpo-30928: prepare idlelib/NEWS.txt for 3.6.5 entries. (#5508) Add 3.6.4 and 3.6.5 headers; move 3.6.3 header below 3.6.4 entries; fix dates. files: M Lib/idlelib/NEWS.txt diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index 5b9d2abaca07..14d2dddcae2f 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -1,8 +1,13 @@ -What's New in IDLE 3.6.3 -Released on 2017-09-25? +What's New in IDLE 3.6.5 +Released on 2017-03-26? ======================== + +What's New in IDLE 3.6.4 +Released on 2017-12-19 +======================== + bpo-32207: Improve tk event exception tracebacks in IDLE. When tk event handling is driven by IDLE's run loop, a confusing and distracting queue.EMPTY traceback context is no longer added @@ -40,6 +45,11 @@ 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. Patch by Terry Jan Reedy + +What's New in IDLE 3.6.3 +Released on 2017-10-03 +======================== + bpo-31460: Simplify the API of IDLE's Module Browser. Passing a widget instead of an flist with a root widget opens the option of creating a browser frame that is only part of a window. @@ -268,7 +278,7 @@ bpo-24813: Add icon to help_about and make other changes. What's New in IDLE 3.6.2 -Released on 2017-07-11 +Released on 2017-07-17 ======================== bpo-15786: Fix several problems with IDLE's autocompletion box. From webhook-mailer at python.org Sat Feb 3 01:40:16 2018 From: webhook-mailer at python.org (Nick Coghlan) Date: Sat, 03 Feb 2018 06:40:16 -0000 Subject: [Python-checkins] bpo-32691: Use mod_spec.parent when running modules with pdb (GH-5474) Message-ID: https://github.com/python/cpython/commit/38bfa8418f5d39bcc7478b8f7aef4a632c26172e commit: 38bfa8418f5d39bcc7478b8f7aef4a632c26172e branch: master author: Mario Corchero committer: Nick Coghlan date: 2018-02-03T16:40:11+10:00 summary: bpo-32691: Use mod_spec.parent when running modules with pdb (GH-5474) Previously the module name was used, which broke relative imports when pdb was run against a plain module or submodule. files: A Misc/NEWS.d/next/Library/2018-02-01-15-53-35.bpo-32691.VLWVTq.rst M Lib/pdb.py M Lib/test/test_pdb.py diff --git a/Lib/pdb.py b/Lib/pdb.py index 366a85b31960..60bdb7675c81 100755 --- a/Lib/pdb.py +++ b/Lib/pdb.py @@ -1532,7 +1532,7 @@ def _runmodule(self, module_name): __main__.__dict__.update({ "__name__": "__main__", "__file__": self.mainpyfile, - "__package__": module_name, + "__package__": mod_spec.parent, "__loader__": mod_spec.loader, "__spec__": mod_spec, "__builtins__": __builtins__, diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index 70d8d1d32613..9aa38e08dd6e 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -1447,10 +1447,41 @@ def test_relative_imports(self): quit """ stdout, _ = self._run_pdb(['-m', self.module_name], commands) - self.assertTrue(any("VAR from module" in l for l in stdout.splitlines())) + self.assertTrue(any("VAR from module" in l for l in stdout.splitlines()), stdout) self.assertTrue(any("VAR from top" in l for l in stdout.splitlines())) self.assertTrue(any("second var" in l for l in stdout.splitlines())) + def test_relative_imports_on_plain_module(self): + # Validates running a plain module. See bpo32691 + self.module_name = 't_main' + support.rmtree(self.module_name) + main_file = self.module_name + '/runme.py' + init_file = self.module_name + '/__init__.py' + module_file = self.module_name + '/module.py' + self.addCleanup(support.rmtree, self.module_name) + os.mkdir(self.module_name) + with open(init_file, 'w') as f: + f.write(textwrap.dedent(""" + top_var = "VAR from top" + """)) + with open(main_file, 'w') as f: + f.write(textwrap.dedent(""" + from . import module + pass # We'll stop here and print the vars + """)) + with open(module_file, 'w') as f: + f.write(textwrap.dedent(""" + var = "VAR from module" + """)) + commands = """ + b 3 + c + p module.var + quit + """ + stdout, _ = self._run_pdb(['-m', self.module_name + '.runme'], commands) + self.assertTrue(any("VAR from module" in l for l in stdout.splitlines()), stdout) + def load_tests(*args): from test import test_pdb diff --git a/Misc/NEWS.d/next/Library/2018-02-01-15-53-35.bpo-32691.VLWVTq.rst b/Misc/NEWS.d/next/Library/2018-02-01-15-53-35.bpo-32691.VLWVTq.rst new file mode 100644 index 000000000000..93f898e9c689 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-01-15-53-35.bpo-32691.VLWVTq.rst @@ -0,0 +1 @@ +Use mod_spec.parent when running modules with pdb From solipsis at pitrou.net Sat Feb 3 04:11:25 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 03 Feb 2018 09:11:25 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=5 Message-ID: <20180203091125.1.729C1649E80E9ED3@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_forkserver leaked [2, -1, 0] memory blocks, sum=1 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflog_R4QcB', '--timeout', '7200'] From webhook-mailer at python.org Sat Feb 3 11:46:36 2018 From: webhook-mailer at python.org (Raymond Hettinger) Date: Sat, 03 Feb 2018 16:46:36 -0000 Subject: [Python-checkins] bpo-32739: Show default value for rotate() (GH-5485) Message-ID: https://github.com/python/cpython/commit/589c718a8e3bde017350f248f7f1c009240eb52b commit: 589c718a8e3bde017350f248f7f1c009240eb52b branch: master author: Raymond Hettinger committer: GitHub date: 2018-02-03T08:46:28-08:00 summary: bpo-32739: Show default value for rotate() (GH-5485) files: M Doc/library/collections.rst diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst index 772ff60fe983..256bf02da47c 100644 --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -509,11 +509,14 @@ or subtracting from an empty counter. .. versionadded:: 3.2 - .. method:: rotate(n) + .. method:: rotate(n=1) - Rotate the deque *n* steps to the right. If *n* is negative, rotate to - the left. Rotating one step to the right is equivalent to: - ``d.appendleft(d.pop())``. + Rotate the deque *n* steps to the right. If *n* is negative, rotate + to the left. + + When the deque is empty, rotating one step to the right is equivalent + to ``d.appendleft(d.pop())``, and rotating one step to the left is + equivalent to ``d.append(d.popleft())``. Deque objects also provide one read-only attribute: From webhook-mailer at python.org Sat Feb 3 13:27:42 2018 From: webhook-mailer at python.org (Raymond Hettinger) Date: Sat, 03 Feb 2018 18:27:42 -0000 Subject: [Python-checkins] bpo-32739: Show default value for rotate() (GH-5485) (GH-5515) Message-ID: https://github.com/python/cpython/commit/7eb3d1e7da42112ba879a5f8602891fa17963f9e commit: 7eb3d1e7da42112ba879a5f8602891fa17963f9e branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Raymond Hettinger date: 2018-02-03T10:27:40-08:00 summary: bpo-32739: Show default value for rotate() (GH-5485) (GH-5515) (cherry picked from commit 589c718a8e3bde017350f248f7f1c009240eb52b) Co-authored-by: Raymond Hettinger files: M Doc/library/collections.rst diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst index d6d2056dfc49..97f513533ed8 100644 --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -509,11 +509,14 @@ or subtracting from an empty counter. .. versionadded:: 3.2 - .. method:: rotate(n) + .. method:: rotate(n=1) - Rotate the deque *n* steps to the right. If *n* is negative, rotate to - the left. Rotating one step to the right is equivalent to: - ``d.appendleft(d.pop())``. + Rotate the deque *n* steps to the right. If *n* is negative, rotate + to the left. + + When the deque is empty, rotating one step to the right is equivalent + to ``d.appendleft(d.pop())``, and rotating one step to the left is + equivalent to ``d.append(d.popleft())``. Deque objects also provide one read-only attribute: From webhook-mailer at python.org Sat Feb 3 16:33:51 2018 From: webhook-mailer at python.org (Ned Deily) Date: Sat, 03 Feb 2018 21:33:51 -0000 Subject: [Python-checkins] Update Doc build for split off of 3.7 branch Message-ID: https://github.com/python/cpython/commit/2357cd71b0a58e51b873a5322e83053f3dbac38d commit: 2357cd71b0a58e51b873a5322e83053f3dbac38d branch: 2.7 author: Ned Deily committer: Ned Deily date: 2018-02-03T16:31:41-05:00 summary: Update Doc build for split off of 3.7 branch files: M Doc/tools/static/switchers.js M Doc/tools/templates/indexsidebar.html diff --git a/Doc/tools/static/switchers.js b/Doc/tools/static/switchers.js index c450f5eafffc..8e0c5ea0092a 100644 --- a/Doc/tools/static/switchers.js +++ b/Doc/tools/static/switchers.js @@ -10,7 +10,8 @@ '(?:release/\\d.\\d[\\x\\d\\.]*)']; var all_versions = { - '3.7': 'dev (3.7)', + '3.8': 'dev (3.8)', + '3.7': 'pre (3.7)', '3.6': '3.6', '3.5': '3.5', '2.7': '2.7', diff --git a/Doc/tools/templates/indexsidebar.html b/Doc/tools/templates/indexsidebar.html index 7ad6a0767345..ddd8d75432ce 100644 --- a/Doc/tools/templates/indexsidebar.html +++ b/Doc/tools/templates/indexsidebar.html @@ -2,7 +2,8 @@

{% trans %}Download{% endtrans %}

{% trans %}Download these documents{% endtrans %}

{% trans %}Docs for other versions{% endtrans %}

    -
  • {% trans %}Python 3.7 (in development){% endtrans %}
  • +
  • {% trans %}Python 3.8 (in development){% endtrans %}
  • +
  • {% trans %}Python 3.7 (pre-release){% endtrans %}
  • {% trans %}Python 3.6 (stable){% endtrans %}
  • {% trans %}Python 3.5 (stable){% endtrans %}
  • {% trans %}Old versions{% endtrans %}
  • From webhook-mailer at python.org Sat Feb 3 16:34:35 2018 From: webhook-mailer at python.org (Ned Deily) Date: Sat, 03 Feb 2018 21:34:35 -0000 Subject: [Python-checkins] Update Doc build for split off of 3.7 branch Message-ID: https://github.com/python/cpython/commit/0cb82eb7e58989693f9bec3596bbbec0256a3fca commit: 0cb82eb7e58989693f9bec3596bbbec0256a3fca branch: 3.6 author: Ned Deily committer: Ned Deily date: 2018-02-03T16:28:44-05:00 summary: Update Doc build for split off of 3.7 branch files: M Doc/tools/static/switchers.js M Doc/tools/templates/indexsidebar.html diff --git a/Doc/tools/static/switchers.js b/Doc/tools/static/switchers.js index c450f5eafffc..8e0c5ea0092a 100644 --- a/Doc/tools/static/switchers.js +++ b/Doc/tools/static/switchers.js @@ -10,7 +10,8 @@ '(?:release/\\d.\\d[\\x\\d\\.]*)']; var all_versions = { - '3.7': 'dev (3.7)', + '3.8': 'dev (3.8)', + '3.7': 'pre (3.7)', '3.6': '3.6', '3.5': '3.5', '2.7': '2.7', diff --git a/Doc/tools/templates/indexsidebar.html b/Doc/tools/templates/indexsidebar.html index c73c406426a2..20e66e0c265c 100644 --- a/Doc/tools/templates/indexsidebar.html +++ b/Doc/tools/templates/indexsidebar.html @@ -2,7 +2,8 @@

    {% trans %}Download{% endtrans %}

    {% trans %}Download these documents{% endtrans %}

    {% trans %}Docs for other versions{% endtrans %}

      -
    • {% trans %}Python 3.7 (in development){% endtrans %}
    • +
    • {% trans %}Python 3.8 (in development){% endtrans %}
    • +
    • {% trans %}Python 3.7 (pre-release){% endtrans %}
    • {% trans %}Python 3.5 (stable){% endtrans %}
    • {% trans %}Python 2.7 (stable){% endtrans %}
    • {% trans %}Old versions{% endtrans %}
    • From webhook-mailer at python.org Sat Feb 3 16:57:05 2018 From: webhook-mailer at python.org (Raymond Hettinger) Date: Sat, 03 Feb 2018 21:57:05 -0000 Subject: [Python-checkins] bpo-32739: Show default value for rotate() (GH-5517) Message-ID: https://github.com/python/cpython/commit/42e8ea9f69c133a4bbb9e496f68a05926b99c2da commit: 42e8ea9f69c133a4bbb9e496f68a05926b99c2da branch: 2.7 author: Raymond Hettinger committer: GitHub date: 2018-02-03T13:57:02-08:00 summary: bpo-32739: Show default value for rotate() (GH-5517) Manual backport of GH-5485 files: M Doc/library/collections.rst diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst index 25e5e22fa37f..a517a2eecfa9 100644 --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -311,11 +311,14 @@ counts, but the output will exclude results with counts of zero or less. .. versionadded:: 2.7 - .. method:: rotate(n) + .. method:: rotate(n=1) Rotate the deque *n* steps to the right. If *n* is negative, rotate to - the left. Rotating one step to the right is equivalent to: - ``d.appendleft(d.pop())``. + the left. + + When the deque is empty, rotating one step to the right is equivalent to + ``d.appendleft(d.pop())``, and rotating one step to the left is + equivalent to ``d.append(d.popleft())``. Deque objects also provide one read-only attribute: From webhook-mailer at python.org Sat Feb 3 19:36:14 2018 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Sun, 04 Feb 2018 00:36:14 -0000 Subject: [Python-checkins] bpo-32746: Fix multiple typos (GH-5144) Message-ID: https://github.com/python/cpython/commit/c3d9508ff22ece9a96892b628dd5813e2fb0cd80 commit: c3d9508ff22ece9a96892b628dd5813e2fb0cd80 branch: master author: Leo Arias committer: Terry Jan Reedy date: 2018-02-03T19:36:10-05:00 summary: bpo-32746: Fix multiple typos (GH-5144) Fix typos found by codespell in docs, docstrings, and comments. files: M Doc/library/optparse.rst M Doc/library/ossaudiodev.rst M Lib/ctypes/_aix.py M Lib/email/_header_value_parser.py M Lib/idlelib/configdialog.py M Lib/opcode.py M Lib/test/datetimetester.py M Lib/test/test_cmd.py M Lib/test/test_concurrent_futures.py M Lib/test/test_generators.py M Lib/test/test_weakref.py M Lib/unittest/test/test_discovery.py M Modules/_asynciomodule.c M Modules/_datetimemodule.c M Modules/_hashopenssl.c M Modules/_pickle.c M Modules/md5module.c M Modules/socketmodule.c M Objects/obmalloc.c M Objects/tupleobject.c M Objects/typeobject.c M Python/getargs.c diff --git a/Doc/library/optparse.rst b/Doc/library/optparse.rst index 2ef187db2dcb..337c7c299416 100644 --- a/Doc/library/optparse.rst +++ b/Doc/library/optparse.rst @@ -567,7 +567,7 @@ An option group is obtained using the class :class:`OptionGroup`: where - * parser is the :class:`OptionParser` instance the group will be insterted in + * parser is the :class:`OptionParser` instance the group will be inserted in to * title is the group title * description, optional, is a long description of the group diff --git a/Doc/library/ossaudiodev.rst b/Doc/library/ossaudiodev.rst index ec40c0b93abf..522bb7e09242 100644 --- a/Doc/library/ossaudiodev.rst +++ b/Doc/library/ossaudiodev.rst @@ -14,7 +14,7 @@ the standard audio interface for Linux and recent versions of FreeBSD. .. Things will get more complicated for future Linux versions, since ALSA is in the standard kernel as of 2.5.x. Presumably if you use ALSA, you'll have to make sure its OSS compatibility layer - is active to use ossaudiodev, but you're gonna need it for the vast + is active to use ossaudiodev, but you're going to need it for the vast majority of Linux audio apps anyway. Sounds like things are also complicated for other BSDs. In response @@ -447,4 +447,3 @@ The remaining methods are specific to audio mixing: microphone input:: mixer.setrecsrc (1 << ossaudiodev.SOUND_MIXER_MIC) - diff --git a/Lib/ctypes/_aix.py b/Lib/ctypes/_aix.py index 61af9423ac54..463f60a2849f 100644 --- a/Lib/ctypes/_aix.py +++ b/Lib/ctypes/_aix.py @@ -32,7 +32,7 @@ In documentation the archive is also referred to as the "base" and the shared library object is referred to as the "member". -For dlopen() on AIX (read initAndLoad()) the calls are similiar. +For dlopen() on AIX (read initAndLoad()) the calls are similar. Default activity occurs when no path information is provided. When path information is provided dlopen() does not search any other directories. @@ -90,7 +90,7 @@ def get_ld_header_info(p): if re.match("[0-9]", line): info.append(line) else: - # blank line (seperator), consume line and end for loop + # blank line (separator), consume line and end for loop break return info diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py index d2d1f5cb5f3d..d8becee19892 100644 --- a/Lib/email/_header_value_parser.py +++ b/Lib/email/_header_value_parser.py @@ -2745,8 +2745,8 @@ def _fold_mime_parameters(part, lines, maxlen, encoding): Using the decoded list of parameters and values, format them according to the RFC rules, including using RFC2231 encoding if the value cannot be - expressed in 'encoding' and/or the paramter+value is too long to fit within - 'maxlen'. + expressed in 'encoding' and/or the parameter+value is too long to fit + within 'maxlen'. """ # Special case for RFC2231 encoding: start from decoded values and use diff --git a/Lib/idlelib/configdialog.py b/Lib/idlelib/configdialog.py index 4e8394be9281..231e14e55d47 100644 --- a/Lib/idlelib/configdialog.py +++ b/Lib/idlelib/configdialog.py @@ -495,7 +495,7 @@ def create_page_font_tab(self): Changing any of the font vars invokes var_changed_font, which adds all 3 font options to changes and calls set_samples. Set_samples applies a new font constructed from the font vars to - font_sample and to highlight_sample on the hightlight page. + font_sample and to highlight_sample on the highlight page. Tabs: Enable users to change spaces entered for indent tabs. Changing indent_scale value with the mouse sets Var space_num, @@ -646,7 +646,7 @@ def set_samples(self, event=None): Called on font initialization and change events. Accesses font_name, font_size, and font_bold Variables. - Updates font_sample and hightlight page highlight_sample. + Updates font_sample and highlight page highlight_sample. """ font_name = self.font_name.get() font_weight = tkFont.BOLD if self.font_bold.get() else tkFont.NORMAL diff --git a/Lib/opcode.py b/Lib/opcode.py index 8f45f0a666f1..368472d98116 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -142,7 +142,7 @@ def jabs_op(name, op): def_op('BUILD_TUPLE', 102) # Number of tuple items def_op('BUILD_LIST', 103) # Number of list items def_op('BUILD_SET', 104) # Number of set items -def_op('BUILD_MAP', 105) # Number of dict entries (upto 255) +def_op('BUILD_MAP', 105) # Number of dict entries name_op('LOAD_ATTR', 106) # Index in name list def_op('COMPARE_OP', 107) # Comparison operator hascompare.append(107) diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index a0883b9f421d..8f9ebddff5a9 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -1861,7 +1861,7 @@ def test_tz_independent_comparing(self): # Make sure comparison doesn't forget microseconds, and isn't done # via comparing a float timestamp (an IEEE double doesn't have enough - # precision to span microsecond resolution across years 1 thru 9999, + # precision to span microsecond resolution across years 1 through 9999, # so comparing via timestamp necessarily calls some distinct values # equal). dt1 = self.theclass(MAXYEAR, 12, 31, 23, 59, 59, 999998) diff --git a/Lib/test/test_cmd.py b/Lib/test/test_cmd.py index 99a483be43b0..96e0c30da328 100644 --- a/Lib/test/test_cmd.py +++ b/Lib/test/test_cmd.py @@ -51,7 +51,7 @@ class samplecmdclass(cmd.Cmd): Test for the function completedefault(): >>> mycmd.completedefault() - This is the completedefault methode + This is the completedefault method >>> mycmd.completenames("a") ['add'] @@ -140,7 +140,7 @@ def postloop(self): print("Hello from postloop") def completedefault(self, *ignored): - print("This is the completedefault methode") + print("This is the completedefault method") def complete_command(self): print("complete command") diff --git a/Lib/test/test_concurrent_futures.py b/Lib/test/test_concurrent_futures.py index 675cd7ae05e5..18d0265f3f61 100644 --- a/Lib/test/test_concurrent_futures.py +++ b/Lib/test/test_concurrent_futures.py @@ -398,7 +398,7 @@ def test_del_shutdown(self): queue_management_thread = executor._queue_management_thread del executor - # Make sure that all the executor ressources were properly cleaned by + # Make sure that all the executor resources were properly cleaned by # the shutdown process queue_management_thread.join() for p in processes.values(): @@ -886,24 +886,24 @@ def test_crash(self): # extensive testing for deadlock caused by crashes in a pool. self.executor.shutdown(wait=True) crash_cases = [ - # Check problem occuring while pickling a task in + # Check problem occurring while pickling a task in # the task_handler thread (id, (ErrorAtPickle(),), PicklingError, "error at task pickle"), - # Check problem occuring while unpickling a task on workers + # Check problem occurring while unpickling a task on workers (id, (ExitAtUnpickle(),), BrokenProcessPool, "exit at task unpickle"), (id, (ErrorAtUnpickle(),), BrokenProcessPool, "error at task unpickle"), (id, (CrashAtUnpickle(),), BrokenProcessPool, "crash at task unpickle"), - # Check problem occuring during func execution on workers + # Check problem occurring during func execution on workers (_crash, (), BrokenProcessPool, "crash during func execution on worker"), (_exit, (), SystemExit, "exit during func execution on worker"), (_raise_error, (RuntimeError, ), RuntimeError, "error during func execution on worker"), - # Check problem occuring while pickling a task result + # Check problem occurring while pickling a task result # on workers (_return_instance, (CrashAtPickle,), BrokenProcessPool, "crash during result pickle on worker"), @@ -911,7 +911,7 @@ def test_crash(self): "exit during result pickle on worker"), (_return_instance, (ErrorAtPickle,), PicklingError, "error during result pickle on worker"), - # Check problem occuring while unpickling a task in + # Check problem occurring while unpickling a task in # the result_handler thread (_return_instance, (ErrorAtUnpickle,), BrokenProcessPool, "error during result unpickle in result_handler"), diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py index 3461f203deea..7360b34023d3 100644 --- a/Lib/test/test_generators.py +++ b/Lib/test/test_generators.py @@ -1500,7 +1500,7 @@ def second(): succs[final].remove(corner) add_to_successors(this) - # Generate moves 3 thru m*n-1. + # Generate moves 3 through m*n-1. def advance(len=len): # If some successor has only one exit, must take it. # Else favor successors with fewer exits. @@ -1522,7 +1522,7 @@ def advance(len=len): yield i add_to_successors(i) - # Generate moves 3 thru m*n-1. Alternative version using a + # Generate moves 3 through m*n-1. Alternative version using a # stronger (but more expensive) heuristic to order successors. # Since the # of backtracking levels is m*n, a poor move early on # can take eons to undo. Smallest square board for which this diff --git a/Lib/test/test_weakref.py b/Lib/test/test_weakref.py index 0384a9fdf014..9fa0bbd78087 100644 --- a/Lib/test/test_weakref.py +++ b/Lib/test/test_weakref.py @@ -1637,7 +1637,7 @@ def __eq__(self, other): # has to keep looping to find the first object we delete. objs.reverse() - # Turn on mutation in C.__eq__. The first time thru the loop, + # Turn on mutation in C.__eq__. The first time through the loop, # under the iterkeys() business the first comparison will delete # the last item iterkeys() would see, and that causes a # RuntimeError: dictionary changed size during iteration diff --git a/Lib/unittest/test/test_discovery.py b/Lib/unittest/test/test_discovery.py index 48d8fe95bce2..227b44a47026 100644 --- a/Lib/unittest/test/test_discovery.py +++ b/Lib/unittest/test/test_discovery.py @@ -199,8 +199,8 @@ def loadTestsFromModule(module, pattern=None): ['a_directory', 'test_directory', 'test_directory2']) # load_tests should have been called once with loader, tests and pattern - # (but there are no tests in our stub module itself, so thats [] at the - # time of call. + # (but there are no tests in our stub module itself, so that is [] at + # the time of call). self.assertEqual(Module.load_tests_args, [(loader, [], 'test*')]) diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index a5cf687d8893..e82425bf2fd7 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -187,7 +187,7 @@ is_coroutine(PyObject *coro) return _is_coroutine(coro); } - /* either an error has occured or + /* either an error has occurred or type(coro) is in iscoroutine_typecache */ return has_it; diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index 4a33f2d89642..b69fcdffcc92 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -3420,7 +3420,7 @@ tzinfo_fromutc(PyDateTime_TZInfo *self, PyObject *dt) PyErr_SetString(PyExc_ValueError, "fromutc: tz.dst() gave" "inconsistent results; cannot convert"); - /* fall thru to failure */ + /* fall through to failure */ Fail: Py_XDECREF(off); Py_XDECREF(dst); diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c index 50fe9d5a10b6..44d3f634fe4a 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -962,7 +962,7 @@ generate_hash_name_list(void) * This macro generates constructor function definitions for specific * hash algorithms. These constructors are much faster than calling * the generic one passing it a python string and are noticeably - * faster than calling a python new() wrapper. Thats important for + * faster than calling a python new() wrapper. That is important for * code that wants to make hashes of a bunch of small strings. * The first call will lazy-initialize, which reports an exception * if initialization fails. diff --git a/Modules/_pickle.c b/Modules/_pickle.c index 05f9a023d922..9525ad6d9661 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -1015,7 +1015,7 @@ _Pickler_OpcodeBoundary(PicklerObject *self) if(_Pickler_CommitFrame(self)) { return -1; } - /* Flush the content of the commited frame to the underlying + /* Flush the content of the committed frame to the underlying * file and reuse the pickler buffer for the next frame so as * to limit memory usage when dumping large complex objects to * a file. diff --git a/Modules/md5module.c b/Modules/md5module.c index 6b11f0bc0e3d..b019f8287684 100644 --- a/Modules/md5module.c +++ b/Modules/md5module.c @@ -293,7 +293,7 @@ md5_done(struct md5_state *md5, unsigned char *out) md5->curlen = 0; } - /* pad upto 56 bytes of zeroes */ + /* pad up to 56 bytes of zeroes */ while (md5->curlen < 56) { md5->buf[md5->curlen++] = (unsigned char)0; } diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index ab3465a95f09..13936aa1558e 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -6156,7 +6156,7 @@ socket_getaddrinfo(PyObject *self, PyObject *args, PyObject* kwargs) } #if defined(__APPLE__) && defined(AI_NUMERICSERV) if ((flags & AI_NUMERICSERV) && (pptr == NULL || (pptr[0] == '0' && pptr[1] == 0))) { - /* On OSX upto at least OSX 10.8 getaddrinfo crashes + /* On OSX up to at least OSX 10.8 getaddrinfo crashes * if AI_NUMERICSERV is set and the servname is NULL or "0". * This workaround avoids a segfault in libsystem. */ diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c index 0b8816cc54f2..0e485d62114d 100644 --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -2469,7 +2469,7 @@ pool_is_in_list(const poolp target, poolp list) * checks. * * Return 0 if the memory debug hooks are not installed or no statistics was - * writen into out, return 1 otherwise. + * written into out, return 1 otherwise. */ int _PyObject_DebugMallocStats(FILE *out) diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index 3a6094612513..39d43dd04a59 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -335,7 +335,7 @@ tuplerepr(PyTupleObject *v) /* The addend 82520, was selected from the range(0, 1000000) for generating the greatest number of prime multipliers for tuples - upto length eight: + up to length eight: 1082527, 1165049, 1082531, 1165057, 1247581, 1330103, 1082533, 1330111, 1412633, 1165069, 1247599, 1495177, 1577699 diff --git a/Objects/typeobject.c b/Objects/typeobject.c index a22173878e87..1dd534866b4d 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -5112,7 +5112,7 @@ PyType_Ready(PyTypeObject *type) /* PyType_Ready is the closest thing we have to a choke point * for type objects, so is the best place I can think of to try * to get type objects into the doubly-linked list of all objects. - * Still, not all type objects go thru PyType_Ready. + * Still, not all type objects go through PyType_Ready. */ _Py_AddToAllObjects((PyObject *)type, 0); #endif diff --git a/Python/getargs.c b/Python/getargs.c index 56e60f6d207b..97c1fe8f4c9d 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1784,7 +1784,7 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format, } } - /* We are into optional args, skip thru to any remaining + /* We are into optional args, skip through to any remaining * keyword args */ msg = skipitem(&format, p_va, flags); if (msg) { @@ -2176,7 +2176,7 @@ vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs, return cleanreturn(1, &freelist); } - /* We are into optional args, skip thru to any remaining + /* We are into optional args, skip through to any remaining * keyword args */ msg = skipitem(&format, p_va, flags); assert(msg == NULL); From webhook-mailer at python.org Sat Feb 3 21:00:27 2018 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Sun, 04 Feb 2018 02:00:27 -0000 Subject: [Python-checkins] [3.6] bpo-32746: Fix multiple typos (GH-5144) (GH-5522) Message-ID: https://github.com/python/cpython/commit/c90a5dec03fbef3a26479c800d5d6d15c44d5afb commit: c90a5dec03fbef3a26479c800d5d6d15c44d5afb branch: 3.6 author: Terry Jan Reedy committer: GitHub date: 2018-02-03T21:00:24-05:00 summary: [3.6] bpo-32746: Fix multiple typos (GH-5144) (GH-5522) Fix typos found by codespell in docs, docstrings, and comments. Fixes for the following files were in post-3.6 code and not backported: Lib/ctypes/_aix.py (new), Lib/test/test_concurrent_futures.py, Modules/_asynciomodule.c, Modules/_pickle.c, Objects/obmalloc.c. (cherry picked from commit c3d9508ff22ece9a96892b628dd5813e2fb0cd80) files: M Doc/library/optparse.rst M Doc/library/ossaudiodev.rst M Lib/email/_header_value_parser.py M Lib/idlelib/configdialog.py M Lib/opcode.py M Lib/test/datetimetester.py M Lib/test/test_cmd.py M Lib/test/test_generators.py M Lib/test/test_weakref.py M Lib/unittest/test/test_discovery.py M Modules/_datetimemodule.c M Modules/_hashopenssl.c M Modules/md5module.c M Modules/socketmodule.c M Objects/tupleobject.c M Objects/typeobject.c M Python/getargs.c diff --git a/Doc/library/optparse.rst b/Doc/library/optparse.rst index 2ef187db2dcb..337c7c299416 100644 --- a/Doc/library/optparse.rst +++ b/Doc/library/optparse.rst @@ -567,7 +567,7 @@ An option group is obtained using the class :class:`OptionGroup`: where - * parser is the :class:`OptionParser` instance the group will be insterted in + * parser is the :class:`OptionParser` instance the group will be inserted in to * title is the group title * description, optional, is a long description of the group diff --git a/Doc/library/ossaudiodev.rst b/Doc/library/ossaudiodev.rst index ec40c0b93abf..522bb7e09242 100644 --- a/Doc/library/ossaudiodev.rst +++ b/Doc/library/ossaudiodev.rst @@ -14,7 +14,7 @@ the standard audio interface for Linux and recent versions of FreeBSD. .. Things will get more complicated for future Linux versions, since ALSA is in the standard kernel as of 2.5.x. Presumably if you use ALSA, you'll have to make sure its OSS compatibility layer - is active to use ossaudiodev, but you're gonna need it for the vast + is active to use ossaudiodev, but you're going to need it for the vast majority of Linux audio apps anyway. Sounds like things are also complicated for other BSDs. In response @@ -447,4 +447,3 @@ The remaining methods are specific to audio mixing: microphone input:: mixer.setrecsrc (1 << ossaudiodev.SOUND_MIXER_MIC) - diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py index b23c897e97bb..14ffd30ca471 100644 --- a/Lib/email/_header_value_parser.py +++ b/Lib/email/_header_value_parser.py @@ -2746,8 +2746,8 @@ def _fold_mime_parameters(part, lines, maxlen, encoding): Using the decoded list of parameters and values, format them according to the RFC rules, including using RFC2231 encoding if the value cannot be - expressed in 'encoding' and/or the paramter+value is too long to fit within - 'maxlen'. + expressed in 'encoding' and/or the parameter+value is too long to fit + within 'maxlen'. """ # Special case for RFC2231 encoding: start from decoded values and use diff --git a/Lib/idlelib/configdialog.py b/Lib/idlelib/configdialog.py index 4e8394be9281..231e14e55d47 100644 --- a/Lib/idlelib/configdialog.py +++ b/Lib/idlelib/configdialog.py @@ -495,7 +495,7 @@ def create_page_font_tab(self): Changing any of the font vars invokes var_changed_font, which adds all 3 font options to changes and calls set_samples. Set_samples applies a new font constructed from the font vars to - font_sample and to highlight_sample on the hightlight page. + font_sample and to highlight_sample on the highlight page. Tabs: Enable users to change spaces entered for indent tabs. Changing indent_scale value with the mouse sets Var space_num, @@ -646,7 +646,7 @@ def set_samples(self, event=None): Called on font initialization and change events. Accesses font_name, font_size, and font_bold Variables. - Updates font_sample and hightlight page highlight_sample. + Updates font_sample and highlight page highlight_sample. """ font_name = self.font_name.get() font_weight = tkFont.BOLD if self.font_bold.get() else tkFont.NORMAL diff --git a/Lib/opcode.py b/Lib/opcode.py index b5916b6619eb..eb6bb8e6dd04 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -142,7 +142,7 @@ def jabs_op(name, op): def_op('BUILD_TUPLE', 102) # Number of tuple items def_op('BUILD_LIST', 103) # Number of list items def_op('BUILD_SET', 104) # Number of set items -def_op('BUILD_MAP', 105) # Number of dict entries (upto 255) +def_op('BUILD_MAP', 105) # Number of dict entries name_op('LOAD_ATTR', 106) # Index in name list def_op('COMPARE_OP', 107) # Comparison operator hascompare.append(107) diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index f23a5305e451..96120c337d99 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -1709,7 +1709,7 @@ def test_tz_independent_comparing(self): # Make sure comparison doesn't forget microseconds, and isn't done # via comparing a float timestamp (an IEEE double doesn't have enough - # precision to span microsecond resolution across years 1 thru 9999, + # precision to span microsecond resolution across years 1 through 9999, # so comparing via timestamp necessarily calls some distinct values # equal). dt1 = self.theclass(MAXYEAR, 12, 31, 23, 59, 59, 999998) diff --git a/Lib/test/test_cmd.py b/Lib/test/test_cmd.py index dd8981f8935b..bdcbb98d9d52 100644 --- a/Lib/test/test_cmd.py +++ b/Lib/test/test_cmd.py @@ -52,7 +52,7 @@ class samplecmdclass(cmd.Cmd): Test for the function completedefault(): >>> mycmd.completedefault() - This is the completedefault methode + This is the completedefault method >>> mycmd.completenames("a") ['add'] @@ -141,7 +141,7 @@ def postloop(self): print("Hello from postloop") def completedefault(self, *ignored): - print("This is the completedefault methode") + print("This is the completedefault method") def complete_command(self): print("complete command") diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py index b8d5bbe3b05d..d9ceeb54038c 100644 --- a/Lib/test/test_generators.py +++ b/Lib/test/test_generators.py @@ -1517,7 +1517,7 @@ def second(): succs[final].remove(corner) add_to_successors(this) - # Generate moves 3 thru m*n-1. + # Generate moves 3 through m*n-1. def advance(len=len): # If some successor has only one exit, must take it. # Else favor successors with fewer exits. @@ -1539,7 +1539,7 @@ def advance(len=len): yield i add_to_successors(i) - # Generate moves 3 thru m*n-1. Alternative version using a + # Generate moves 3 through m*n-1. Alternative version using a # stronger (but more expensive) heuristic to order successors. # Since the # of backtracking levels is m*n, a poor move early on # can take eons to undo. Smallest square board for which this diff --git a/Lib/test/test_weakref.py b/Lib/test/test_weakref.py index 43cf2c0fc2ed..ec0f1d4ab434 100644 --- a/Lib/test/test_weakref.py +++ b/Lib/test/test_weakref.py @@ -1637,7 +1637,7 @@ def __eq__(self, other): # has to keep looping to find the first object we delete. objs.reverse() - # Turn on mutation in C.__eq__. The first time thru the loop, + # Turn on mutation in C.__eq__. The first time through the loop, # under the iterkeys() business the first comparison will delete # the last item iterkeys() would see, and that causes a # RuntimeError: dictionary changed size during iteration diff --git a/Lib/unittest/test/test_discovery.py b/Lib/unittest/test/test_discovery.py index 48d8fe95bce2..227b44a47026 100644 --- a/Lib/unittest/test/test_discovery.py +++ b/Lib/unittest/test/test_discovery.py @@ -199,8 +199,8 @@ def loadTestsFromModule(module, pattern=None): ['a_directory', 'test_directory', 'test_directory2']) # load_tests should have been called once with loader, tests and pattern - # (but there are no tests in our stub module itself, so thats [] at the - # time of call. + # (but there are no tests in our stub module itself, so that is [] at + # the time of call). self.assertEqual(Module.load_tests_args, [(loader, [], 'test*')]) diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index fe92b93cb4e8..7403e958dc15 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -3157,7 +3157,7 @@ tzinfo_fromutc(PyDateTime_TZInfo *self, PyObject *dt) PyErr_SetString(PyExc_ValueError, "fromutc: tz.dst() gave" "inconsistent results; cannot convert"); - /* fall thru to failure */ + /* fall through to failure */ Fail: Py_XDECREF(off); Py_XDECREF(dst); diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c index 5a86376aa8bc..8670fbd4572d 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -918,7 +918,7 @@ generate_hash_name_list(void) * This macro generates constructor function definitions for specific * hash algorithms. These constructors are much faster than calling * the generic one passing it a python string and are noticeably - * faster than calling a python new() wrapper. Thats important for + * faster than calling a python new() wrapper. That is important for * code that wants to make hashes of a bunch of small strings. * The first call will lazy-initialize, which reports an exception * if initialization fails. diff --git a/Modules/md5module.c b/Modules/md5module.c index 04bc06e4b785..fe9da7d3af2d 100644 --- a/Modules/md5module.c +++ b/Modules/md5module.c @@ -293,7 +293,7 @@ md5_done(struct md5_state *md5, unsigned char *out) md5->curlen = 0; } - /* pad upto 56 bytes of zeroes */ + /* pad up to 56 bytes of zeroes */ while (md5->curlen < 56) { md5->buf[md5->curlen++] = (unsigned char)0; } diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 968dad07cd84..8d9915a42f5b 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -5977,7 +5977,7 @@ socket_getaddrinfo(PyObject *self, PyObject *args, PyObject* kwargs) } #if defined(__APPLE__) && defined(AI_NUMERICSERV) if ((flags & AI_NUMERICSERV) && (pptr == NULL || (pptr[0] == '0' && pptr[1] == 0))) { - /* On OSX upto at least OSX 10.8 getaddrinfo crashes + /* On OSX up to at least OSX 10.8 getaddrinfo crashes * if AI_NUMERICSERV is set and the servname is NULL or "0". * This workaround avoids a segfault in libsystem. */ diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index 047926f969b7..b9628fd94fba 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -332,7 +332,7 @@ tuplerepr(PyTupleObject *v) /* The addend 82520, was selected from the range(0, 1000000) for generating the greatest number of prime multipliers for tuples - upto length eight: + up to length eight: 1082527, 1165049, 1082531, 1165057, 1247581, 1330103, 1082533, 1330111, 1412633, 1165069, 1247599, 1495177, 1577699 diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 5a231c81d4e9..e843204f10a6 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -4929,7 +4929,7 @@ PyType_Ready(PyTypeObject *type) /* PyType_Ready is the closest thing we have to a choke point * for type objects, so is the best place I can think of to try * to get type objects into the doubly-linked list of all objects. - * Still, not all type objects go thru PyType_Ready. + * Still, not all type objects go through PyType_Ready. */ _Py_AddToAllObjects((PyObject *)type, 0); #endif diff --git a/Python/getargs.c b/Python/getargs.c index ed6b8152de45..4d27418a84ba 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1771,7 +1771,7 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format, } } - /* We are into optional args, skip thru to any remaining + /* We are into optional args, skip through to any remaining * keyword args */ msg = skipitem(&format, p_va, flags); if (msg) { @@ -2130,7 +2130,7 @@ vgetargskeywordsfast_impl(PyObject **args, Py_ssize_t nargs, return cleanreturn(1, &freelist); } - /* We are into optional args, skip thru to any remaining + /* We are into optional args, skip through to any remaining * keyword args */ msg = skipitem(&format, p_va, flags); assert(msg == NULL); From webhook-mailer at python.org Sun Feb 4 01:26:20 2018 From: webhook-mailer at python.org (Mariatta) Date: Sun, 04 Feb 2018 06:26:20 -0000 Subject: [Python-checkins] bpo-32720: Fixed the definition for width and precision in format mini-language doc (GH-5482) (GH-5525) Message-ID: https://github.com/python/cpython/commit/3bd749b2122c17b835dc438cdaef63bfdfd61344 commit: 3bd749b2122c17b835dc438cdaef63bfdfd61344 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Mariatta date: 2018-02-04T01:26:16-05:00 summary: bpo-32720: Fixed the definition for width and precision in format mini-language doc (GH-5482) (GH-5525) Changed the definition of width and precision from "integer" to "digit+" in format mini-language doc. (cherry picked from commit 8b5fa289fdb04b6b919cf95fa99246aa872e47a8) Co-authored-by: nathankerr96 files: M Doc/library/string.rst diff --git a/Doc/library/string.rst b/Doc/library/string.rst index 7a9fcc38bbde..dbafb48a8054 100644 --- a/Doc/library/string.rst +++ b/Doc/library/string.rst @@ -304,9 +304,9 @@ The general form of a *standard format specifier* is: fill: align: "<" | ">" | "=" | "^" sign: "+" | "-" | " " - width: `integer` + width: `digit`+ grouping_option: "_" | "," - precision: `integer` + precision: `digit`+ type: "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%" If a valid *align* value is specified, it can be preceded by a *fill* From webhook-mailer at python.org Sun Feb 4 03:53:54 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sun, 04 Feb 2018 08:53:54 -0000 Subject: [Python-checkins] bpo-10544: Disallow "yield" in comprehensions and generator expressions. (GH-4564) Message-ID: https://github.com/python/cpython/commit/07ca9afaa8768b44baf816b4998d209ed3e0088f commit: 07ca9afaa8768b44baf816b4998d209ed3e0088f branch: master author: Serhiy Storchaka committer: GitHub date: 2018-02-04T10:53:48+02:00 summary: bpo-10544: Disallow "yield" in comprehensions and generator expressions. (GH-4564) files: A Misc/NEWS.d/next/Core and Builtins/2017-11-26-00-59-22.bpo-10544.fHOM3V.rst M Doc/reference/expressions.rst M Doc/whatsnew/3.8.rst M Lib/test/support/__init__.py M Lib/test/test_grammar.py M Python/symtable.c diff --git a/Doc/reference/expressions.rst b/Doc/reference/expressions.rst index fb92ad0f07c2..151062ba1753 100644 --- a/Doc/reference/expressions.rst +++ b/Doc/reference/expressions.rst @@ -196,8 +196,7 @@ they may depend on the values obtained from the leftmost iterable. For example: To ensure the comprehension always results in a container of the appropriate type, ``yield`` and ``yield from`` expressions are prohibited in the implicitly -nested scope (in Python 3.7, such expressions emit :exc:`DeprecationWarning` -when compiled, in Python 3.8+ they will emit :exc:`SyntaxError`). +nested scope. Since Python 3.6, in an :keyword:`async def` function, an :keyword:`async for` clause may be used to iterate over a :term:`asynchronous iterator`. @@ -214,8 +213,8 @@ See also :pep:`530`. .. versionadded:: 3.6 Asynchronous comprehensions were introduced. -.. deprecated:: 3.7 - ``yield`` and ``yield from`` deprecated in the implicitly nested scope. +.. versionchanged:: 3.8 + ``yield`` and ``yield from`` prohibited in the implicitly nested scope. .. _lists: @@ -350,9 +349,7 @@ The parentheses can be omitted on calls with only one argument. See section To avoid interfering with the expected operation of the generator expression itself, ``yield`` and ``yield from`` expressions are prohibited in the -implicitly defined generator (in Python 3.7, such expressions emit -:exc:`DeprecationWarning` when compiled, in Python 3.8+ they will emit -:exc:`SyntaxError`). +implicitly defined generator. If a generator expression contains either :keyword:`async for` clauses or :keyword:`await` expressions it is called an @@ -368,8 +365,8 @@ which is an asynchronous iterator (see :ref:`async-iterators`). only appear in :keyword:`async def` coroutines. Starting with 3.7, any function can use asynchronous generator expressions. -.. deprecated:: 3.7 - ``yield`` and ``yield from`` deprecated in the implicitly nested scope. +.. versionchanged:: 3.8 + ``yield`` and ``yield from`` prohibited in the implicitly nested scope. .. _yieldexpr: @@ -401,12 +398,10 @@ coroutine function to be an asynchronous generator. For example:: Due to their side effects on the containing scope, ``yield`` expressions are not permitted as part of the implicitly defined scopes used to -implement comprehensions and generator expressions (in Python 3.7, such -expressions emit :exc:`DeprecationWarning` when compiled, in Python 3.8+ -they will emit :exc:`SyntaxError`).. +implement comprehensions and generator expressions. -.. deprecated:: 3.7 - Yield expressions deprecated in the implicitly nested scopes used to +.. versionchanged:: 3.8 + Yield expressions prohibited in the implicitly nested scopes used to implement comprehensions and generator expressions. Generator functions are described below, while asynchronous generator diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 8a3f9b0f7014..c4063ad76744 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -113,6 +113,15 @@ This section lists previously described changes and other bugfixes that may require changes to your code. +Changes in Python behavior +-------------------------- + +* Yield expressions (both ``yield`` and ``yield from`` clauses) are now disallowed + in comprehensions and generator expressions (aside from the iterable expression + in the leftmost :keyword:`for` clause). + (Contributed by Serhiy Storchaka in :issue:`10544`.) + + Changes in the Python API ------------------------- diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 22868d4ba1a3..6c9e31a22c10 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -1061,8 +1061,8 @@ def make_bad_fd(): file.close() unlink(TESTFN) -def check_syntax_error(testcase, statement, *, lineno=None, offset=None): - with testcase.assertRaises(SyntaxError) as cm: +def check_syntax_error(testcase, statement, errtext='', *, lineno=None, offset=None): + with testcase.assertRaisesRegex(SyntaxError, errtext) as cm: compile(statement, '', 'exec') err = cm.exception testcase.assertIsNotNone(err.lineno) diff --git a/Lib/test/test_grammar.py b/Lib/test/test_grammar.py index 88c22b89d444..d89bfdc06335 100644 --- a/Lib/test/test_grammar.py +++ b/Lib/test/test_grammar.py @@ -251,6 +251,8 @@ def __getitem__(self, item): class GrammarTests(unittest.TestCase): + check_syntax_error = check_syntax_error + # single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE # XXX can't test in a script -- this rule is only used when interactive @@ -920,15 +922,7 @@ def test_yield_in_comprehensions(self): def g(): [x for x in [(yield 1)]] def g(): [x for x in [(yield from ())]] - def check(code, warntext): - with self.assertWarnsRegex(DeprecationWarning, warntext): - compile(code, '', 'exec') - import warnings - with warnings.catch_warnings(): - warnings.filterwarnings('error', category=DeprecationWarning) - with self.assertRaisesRegex(SyntaxError, warntext): - compile(code, '', 'exec') - + check = self.check_syntax_error check("def g(): [(yield x) for x in ()]", "'yield' inside list comprehension") check("def g(): [x for x in () if not (yield x)]", diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-11-26-00-59-22.bpo-10544.fHOM3V.rst b/Misc/NEWS.d/next/Core and Builtins/2017-11-26-00-59-22.bpo-10544.fHOM3V.rst new file mode 100644 index 000000000000..404f12cbbb31 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-11-26-00-59-22.bpo-10544.fHOM3V.rst @@ -0,0 +1,2 @@ +Yield expressions are now disallowed in comprehensions and generator +expressions except the expression for the outermost iterable. diff --git a/Python/symtable.c b/Python/symtable.c index bbac25cf3767..ac14058fefd2 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -1754,35 +1754,18 @@ symtable_handle_comprehension(struct symtable *st, expr_ty e, VISIT(st, expr, value); VISIT(st, expr, elt); if (st->st_cur->ste_generator) { - PyObject *msg = PyUnicode_FromString( + PyErr_SetString(PyExc_SyntaxError, (e->kind == ListComp_kind) ? "'yield' inside list comprehension" : (e->kind == SetComp_kind) ? "'yield' inside set comprehension" : (e->kind == DictComp_kind) ? "'yield' inside dict comprehension" : "'yield' inside generator expression"); - if (msg == NULL) { - symtable_exit_block(st, (void *)e); - return 0; - } - if (PyErr_WarnExplicitObject(PyExc_DeprecationWarning, - msg, st->st_filename, st->st_cur->ste_lineno, - NULL, NULL) == -1) - { - if (PyErr_ExceptionMatches(PyExc_DeprecationWarning)) { - /* Replace the DeprecationWarning exception with a SyntaxError - to get a more accurate error report */ - PyErr_Clear(); - PyErr_SetObject(PyExc_SyntaxError, msg); - PyErr_SyntaxLocationObject(st->st_filename, - st->st_cur->ste_lineno, - st->st_cur->ste_col_offset); - } - Py_DECREF(msg); - symtable_exit_block(st, (void *)e); - return 0; - } - Py_DECREF(msg); + PyErr_SyntaxLocationObject(st->st_filename, + st->st_cur->ste_lineno, + st->st_cur->ste_col_offset); + symtable_exit_block(st, (void *)e); + return 0; } - st->st_cur->ste_generator |= is_generator; + st->st_cur->ste_generator = is_generator; return symtable_exit_block(st, (void *)e); } From solipsis at pitrou.net Sun Feb 4 04:10:37 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 04 Feb 2018 09:10:37 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=71 Message-ID: <20180204091037.1.8D4B3FA4792C9517@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_spawn leaked [0, 0, 44] references, sum=44 test_multiprocessing_spawn leaked [0, 0, 21] memory blocks, sum=21 test_multiprocessing_spawn leaked [0, 0, 2] file descriptors, sum=2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogSDuldx', '--timeout', '7200'] From webhook-mailer at python.org Sun Feb 4 11:14:50 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sun, 04 Feb 2018 16:14:50 -0000 Subject: [Python-checkins] Use assertTrue() instead of deprecated assert_(). (#5526) Message-ID: https://github.com/python/cpython/commit/95c3262762f7d0da97ad633f40bed7cd2df9814c commit: 95c3262762f7d0da97ad633f40bed7cd2df9814c branch: master author: Serhiy Storchaka committer: GitHub date: 2018-02-04T18:14:47+02:00 summary: Use assertTrue() instead of deprecated assert_(). (#5526) files: M Lib/test/test_site.py diff --git a/Lib/test/test_site.py b/Lib/test/test_site.py index b6648d67ca68..e3c9deebf08c 100644 --- a/Lib/test/test_site.py +++ b/Lib/test/test_site.py @@ -548,7 +548,7 @@ def test_underpth_nosite_file(self): 'import sys; print("\\n".join(sys.path) if sys.flags.no_site else "")' ], env=env, encoding='ansi') actual_sys_path = output.rstrip().split('\n') - self.assert_(actual_sys_path, "sys.flags.no_site was False") + self.assertTrue(actual_sys_path, "sys.flags.no_site was False") self.assertEqual( actual_sys_path, sys_path, From webhook-mailer at python.org Sun Feb 4 12:15:04 2018 From: webhook-mailer at python.org (Raymond Hettinger) Date: Sun, 04 Feb 2018 17:15:04 -0000 Subject: [Python-checkins] Fix typo -- missing "not" (GH-5528) Message-ID: https://github.com/python/cpython/commit/ca6c125f10a39ef59d6949cc793a6eeb7d02d1f6 commit: ca6c125f10a39ef59d6949cc793a6eeb7d02d1f6 branch: master author: Raymond Hettinger committer: GitHub date: 2018-02-04T09:15:01-08:00 summary: Fix typo -- missing "not" (GH-5528) files: M Doc/library/collections.rst diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst index 256bf02da47c..96475b9f490c 100644 --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -514,7 +514,7 @@ or subtracting from an empty counter. Rotate the deque *n* steps to the right. If *n* is negative, rotate to the left. - When the deque is empty, rotating one step to the right is equivalent + When the deque is not empty, rotating one step to the right is equivalent to ``d.appendleft(d.pop())``, and rotating one step to the left is equivalent to ``d.append(d.popleft())``. From webhook-mailer at python.org Sun Feb 4 13:16:36 2018 From: webhook-mailer at python.org (Raymond Hettinger) Date: Sun, 04 Feb 2018 18:16:36 -0000 Subject: [Python-checkins] Fix typo -- missing "not" (GH-5528) (GH-5531) Message-ID: https://github.com/python/cpython/commit/231fa23f3fe83ca3738727d45009916926d31216 commit: 231fa23f3fe83ca3738727d45009916926d31216 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Raymond Hettinger date: 2018-02-04T10:16:33-08:00 summary: Fix typo -- missing "not" (GH-5528) (GH-5531) files: M Doc/library/collections.rst diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst index 97f513533ed8..82ba05737413 100644 --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -514,7 +514,7 @@ or subtracting from an empty counter. Rotate the deque *n* steps to the right. If *n* is negative, rotate to the left. - When the deque is empty, rotating one step to the right is equivalent + When the deque is not empty, rotating one step to the right is equivalent to ``d.appendleft(d.pop())``, and rotating one step to the left is equivalent to ``d.append(d.popleft())``. From webhook-mailer at python.org Sun Feb 4 13:34:32 2018 From: webhook-mailer at python.org (Raymond Hettinger) Date: Sun, 04 Feb 2018 18:34:32 -0000 Subject: [Python-checkins] Fix typo -- missing "not" (GH-5532) Message-ID: https://github.com/python/cpython/commit/2a4e2ea112822c9ce10481984d291e00d8a920d7 commit: 2a4e2ea112822c9ce10481984d291e00d8a920d7 branch: 2.7 author: Raymond Hettinger committer: GitHub date: 2018-02-04T10:34:29-08:00 summary: Fix typo -- missing "not" (GH-5532) files: M Doc/library/collections.rst diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst index a517a2eecfa9..679931e089f2 100644 --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -316,7 +316,7 @@ counts, but the output will exclude results with counts of zero or less. Rotate the deque *n* steps to the right. If *n* is negative, rotate to the left. - When the deque is empty, rotating one step to the right is equivalent to + When the deque is not empty, rotating one step to the right is equivalent to ``d.appendleft(d.pop())``, and rotating one step to the left is equivalent to ``d.append(d.popleft())``. From webhook-mailer at python.org Sun Feb 4 15:09:32 2018 From: webhook-mailer at python.org (Zachary Ware) Date: Sun, 04 Feb 2018 20:09:32 -0000 Subject: [Python-checkins] Fix version in AppVeyor (GH-5535) Message-ID: https://github.com/python/cpython/commit/7de25b1124954eb333f63f0b3942eeef6f51acb7 commit: 7de25b1124954eb333f63f0b3942eeef6f51acb7 branch: master author: Zachary Ware committer: GitHub date: 2018-02-04T14:09:29-06:00 summary: Fix version in AppVeyor (GH-5535) files: M .github/appveyor.yml diff --git a/.github/appveyor.yml b/.github/appveyor.yml index b7d407873189..06247e1337d4 100644 --- a/.github/appveyor.yml +++ b/.github/appveyor.yml @@ -1,4 +1,4 @@ -version: 3.7build{build} +version: 3.8build{build} clone_depth: 5 branches: only: From webhook-mailer at python.org Sun Feb 4 15:36:46 2018 From: webhook-mailer at python.org (Zachary Ware) Date: Sun, 04 Feb 2018 20:36:46 -0000 Subject: [Python-checkins] Try to fix the AppVeyor cache mechanism (GH-5536) Message-ID: https://github.com/python/cpython/commit/685045060e63783146a1d2ce78011453bbc0e111 commit: 685045060e63783146a1d2ce78011453bbc0e111 branch: master author: Zachary Ware committer: GitHub date: 2018-02-04T14:36:43-06:00 summary: Try to fix the AppVeyor cache mechanism (GH-5536) files: M .github/appveyor.yml diff --git a/.github/appveyor.yml b/.github/appveyor.yml index 06247e1337d4..129c119df61f 100644 --- a/.github/appveyor.yml +++ b/.github/appveyor.yml @@ -6,7 +6,7 @@ branches: - /\d\.\d/ - buildbot-custom cache: - - externals -> PCbuild\* + - externals -> PCbuild build_script: - cmd: PCbuild\build.bat -e - cmd: PCbuild\win32\python.exe -m test.pythoninfo From webhook-mailer at python.org Sun Feb 4 18:15:24 2018 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Sun, 04 Feb 2018 23:15:24 -0000 Subject: [Python-checkins] bpo-32765: Update configdialog General tab create page docstring (GH-5529) Message-ID: https://github.com/python/cpython/commit/845d86485e35a26478aedb3dc127d632fdc65759 commit: 845d86485e35a26478aedb3dc127d632fdc65759 branch: master author: Cheryl Sabella committer: Terry Jan Reedy date: 2018-02-04T18:15:21-05:00 summary: bpo-32765: Update configdialog General tab create page docstring (GH-5529) Add new entries to the widget list. files: A Misc/NEWS.d/next/IDLE/2018-02-04-17-52-54.bpo-32765.qm0eCu.rst M Lib/idlelib/configdialog.py diff --git a/Lib/idlelib/configdialog.py b/Lib/idlelib/configdialog.py index 231e14e55d47..36ac4a23a52d 100644 --- a/Lib/idlelib/configdialog.py +++ b/Lib/idlelib/configdialog.py @@ -1792,11 +1792,27 @@ def create_page_general(self): (*)win_width_int: Entry - win_width win_height_title: Label (*)win_height_int: Entry - win_height + frame_autocomplete: Frame + auto_wait_title: Label + (*)auto_wait_int: Entry - autocomplete_wait + frame_paren1: Frame + paren_style_title: Label + (*)paren_style_type: OptionMenu - paren_style + frame_paren2: Frame + paren_time_title: Label + (*)paren_flash_time: Entry - flash_delay + (*)bell_on: Checkbutton - paren_bell frame_editor: LabelFrame frame_save: Frame run_save_title: Label (*)save_ask_on: Radiobutton - autosave (*)save_auto_on: Radiobutton - autosave + frame_format: Frame + format_width_title: Label + (*)format_width_int: Entry - format_width + frame_context: Frame + context_title: Label + (*)context_int: Entry - context_lines frame_help: LabelFrame frame_helplist: Frame frame_helplist_buttons: Frame diff --git a/Misc/NEWS.d/next/IDLE/2018-02-04-17-52-54.bpo-32765.qm0eCu.rst b/Misc/NEWS.d/next/IDLE/2018-02-04-17-52-54.bpo-32765.qm0eCu.rst new file mode 100644 index 000000000000..1bd6b094ca5d --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2018-02-04-17-52-54.bpo-32765.qm0eCu.rst @@ -0,0 +1 @@ +Update configdialog General tab docstring to add new widgets to the widget list. From webhook-mailer at python.org Sun Feb 4 19:05:26 2018 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Mon, 05 Feb 2018 00:05:26 -0000 Subject: [Python-checkins] bpo-32765: Update configdialog General tab create page docstring (GH-5529) (GH-5538) Message-ID: https://github.com/python/cpython/commit/1c2b138671656abf8563a0cd7ef27c8c2e0be4e6 commit: 1c2b138671656abf8563a0cd7ef27c8c2e0be4e6 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Terry Jan Reedy date: 2018-02-04T19:05:23-05:00 summary: bpo-32765: Update configdialog General tab create page docstring (GH-5529) (GH-5538) Add new entries to the widget list. (cherry picked from commit 845d86485e35a26478aedb3dc127d632fdc65759) Co-authored-by: Cheryl Sabella files: A Misc/NEWS.d/next/IDLE/2018-02-04-17-52-54.bpo-32765.qm0eCu.rst M Lib/idlelib/configdialog.py diff --git a/Lib/idlelib/configdialog.py b/Lib/idlelib/configdialog.py index 231e14e55d47..36ac4a23a52d 100644 --- a/Lib/idlelib/configdialog.py +++ b/Lib/idlelib/configdialog.py @@ -1792,11 +1792,27 @@ def create_page_general(self): (*)win_width_int: Entry - win_width win_height_title: Label (*)win_height_int: Entry - win_height + frame_autocomplete: Frame + auto_wait_title: Label + (*)auto_wait_int: Entry - autocomplete_wait + frame_paren1: Frame + paren_style_title: Label + (*)paren_style_type: OptionMenu - paren_style + frame_paren2: Frame + paren_time_title: Label + (*)paren_flash_time: Entry - flash_delay + (*)bell_on: Checkbutton - paren_bell frame_editor: LabelFrame frame_save: Frame run_save_title: Label (*)save_ask_on: Radiobutton - autosave (*)save_auto_on: Radiobutton - autosave + frame_format: Frame + format_width_title: Label + (*)format_width_int: Entry - format_width + frame_context: Frame + context_title: Label + (*)context_int: Entry - context_lines frame_help: LabelFrame frame_helplist: Frame frame_helplist_buttons: Frame diff --git a/Misc/NEWS.d/next/IDLE/2018-02-04-17-52-54.bpo-32765.qm0eCu.rst b/Misc/NEWS.d/next/IDLE/2018-02-04-17-52-54.bpo-32765.qm0eCu.rst new file mode 100644 index 000000000000..1bd6b094ca5d --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2018-02-04-17-52-54.bpo-32765.qm0eCu.rst @@ -0,0 +1 @@ +Update configdialog General tab docstring to add new widgets to the widget list. From webhook-mailer at python.org Sun Feb 4 19:07:19 2018 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Mon, 05 Feb 2018 00:07:19 -0000 Subject: [Python-checkins] Add entry for uniform lower context; add 'since' to be explicit. (GH-5539) Message-ID: https://github.com/python/cpython/commit/05e806767b857b1eab838e712828e3a7d57cabf1 commit: 05e806767b857b1eab838e712828e3a7d57cabf1 branch: master author: Terry Jan Reedy committer: GitHub date: 2018-02-04T19:07:16-05:00 summary: Add entry for uniform lower context; add 'since' to be explicit. (GH-5539) files: M Lib/idlelib/NEWS.txt diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index 9784c46b1c57..d616a740d5f5 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -1,8 +1,11 @@ -What's New in IDLE 3.7.0 +What's New in IDLE 3.7.0 (since 3.6.0) Released on 2018-06-18? -======================== +====================================== +bpo-32765: Update configdialog General tab create page docstring. +Add new widgets to the widget list. + bpo-32207: Improve tk event exception tracebacks in IDLE. When tk event handling is driven by IDLE's run loop, a confusing and distracting queue.EMPTY traceback context is no longer added @@ -294,9 +297,9 @@ Issue #28572: Add 10% to coverage of IDLE's test_configdialog. Update and augment description of the configuration system. -What's New in IDLE 3.6.0 +What's New in IDLE 3.6.0 (since 3.5.0) Released on 2016-12-23 -======================== +====================================== - Issue #15308: Add 'interrupt execution' (^C) to Shell menu. Patch by Roger Serwy, updated by Bayard Randel. From webhook-mailer at python.org Sun Feb 4 19:39:58 2018 From: webhook-mailer at python.org (Larry Hastings) Date: Mon, 05 Feb 2018 00:39:58 -0000 Subject: [Python-checkins] Finalize blurb archive for 3.5.5 (no new blurbs). Message-ID: https://github.com/python/cpython/commit/8201a1eb20bfe590888479b13d21b0cad9d88844 commit: 8201a1eb20bfe590888479b13d21b0cad9d88844 branch: 3.5 author: Larry Hastings committer: Larry Hastings date: 2018-02-04T15:39:04-08:00 summary: Finalize blurb archive for 3.5.5 (no new blurbs). files: A Misc/NEWS.d/3.5.5.rst diff --git a/Misc/NEWS.d/3.5.5.rst b/Misc/NEWS.d/3.5.5.rst new file mode 100644 index 000000000000..9d739259e86b --- /dev/null +++ b/Misc/NEWS.d/3.5.5.rst @@ -0,0 +1,8 @@ +.. bpo: 0 +.. date: 2018-02-04 +.. no changes: True +.. nonce: G9yme3 +.. release date: 2018-02-04 +.. section: Library + +There were no new changes in version 3.5.5. From webhook-mailer at python.org Sun Feb 4 21:03:25 2018 From: webhook-mailer at python.org (Nick Coghlan) Date: Mon, 05 Feb 2018 02:03:25 -0000 Subject: [Python-checkins] bpo-8722: Document __getattr__ behavior with AttributeError in property (GH-4754) Message-ID: https://github.com/python/cpython/commit/d1f318105b8781b01f3507d5cb0fd841b977d5f2 commit: d1f318105b8781b01f3507d5cb0fd841b977d5f2 branch: master author: Cheryl Sabella committer: Nick Coghlan date: 2018-02-05T12:03:22+10:00 summary: bpo-8722: Document __getattr__ behavior with AttributeError in property (GH-4754) When `__getattr__` is implemented, attribute lookup will always fall back to that, even if the initial failure comes from `__getattribute__` or a descriptor's `__get__` method (including property methods). files: A Misc/NEWS.d/next/Documentation/2018-02-03-06-11-37.bpo-8722.MPyVyj.rst M Doc/reference/datamodel.rst diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 25b95c115438..8420fb60bff3 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1463,10 +1463,12 @@ access (use of, assignment to, or deletion of ``x.name``) for class instances. .. method:: object.__getattr__(self, name) - Called when an attribute lookup has not found the attribute in the usual places - (i.e. it is not an instance attribute nor is it found in the class tree for - ``self``). ``name`` is the attribute name. This method should return the - (computed) attribute value or raise an :exc:`AttributeError` exception. + Called when the default attribute access fails with an :exc:`AttributeError` + (either :meth:`__getattribute__` raises an :exc:`AttributeError` because + *name* is not an instance attribute or an attribute in the class tree + for ``self``; or :meth:`__get__` of a *name* property raises + :exc:`AttributeError`). This method should either return the (computed) + attribute value or raise an :exc:`AttributeError` exception. Note that if the attribute is found through the normal mechanism, :meth:`__getattr__` is not called. (This is an intentional asymmetry between diff --git a/Misc/NEWS.d/next/Documentation/2018-02-03-06-11-37.bpo-8722.MPyVyj.rst b/Misc/NEWS.d/next/Documentation/2018-02-03-06-11-37.bpo-8722.MPyVyj.rst new file mode 100644 index 000000000000..36e6ff7db3ce --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2018-02-03-06-11-37.bpo-8722.MPyVyj.rst @@ -0,0 +1,2 @@ +Document :meth:`__getattr__` behavior when property :meth:`get` method +raises :exc:`AttributeError`. From webhook-mailer at python.org Sun Feb 4 22:10:03 2018 From: webhook-mailer at python.org (Nick Coghlan) Date: Mon, 05 Feb 2018 03:10:03 -0000 Subject: [Python-checkins] [3.6] bpo-8722: Document __getattr__ behavior with AttributeError in property (GH-5542) Message-ID: https://github.com/python/cpython/commit/a8c25d1c7f0d395861cc3e10dd01989150891c95 commit: a8c25d1c7f0d395861cc3e10dd01989150891c95 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Nick Coghlan date: 2018-02-05T13:10:00+10:00 summary: [3.6] bpo-8722: Document __getattr__ behavior with AttributeError in property (GH-5542) When `__getattr__` is implemented, attribute lookup will always fall back to that, even if the initial failure comes from `__getattribute__` or a descriptor's `__get__` method (including property methods). (cherry picked from commit d1f318105b8781b01f3507d5cb0fd841b977d5f2) Co-authored-by: Cheryl Sabella files: A Misc/NEWS.d/next/Documentation/2018-02-03-06-11-37.bpo-8722.MPyVyj.rst M Doc/reference/datamodel.rst diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 9752494972ff..773eeb233540 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1443,10 +1443,12 @@ access (use of, assignment to, or deletion of ``x.name``) for class instances. .. method:: object.__getattr__(self, name) - Called when an attribute lookup has not found the attribute in the usual places - (i.e. it is not an instance attribute nor is it found in the class tree for - ``self``). ``name`` is the attribute name. This method should return the - (computed) attribute value or raise an :exc:`AttributeError` exception. + Called when the default attribute access fails with an :exc:`AttributeError` + (either :meth:`__getattribute__` raises an :exc:`AttributeError` because + *name* is not an instance attribute or an attribute in the class tree + for ``self``; or :meth:`__get__` of a *name* property raises + :exc:`AttributeError`). This method should either return the (computed) + attribute value or raise an :exc:`AttributeError` exception. Note that if the attribute is found through the normal mechanism, :meth:`__getattr__` is not called. (This is an intentional asymmetry between diff --git a/Misc/NEWS.d/next/Documentation/2018-02-03-06-11-37.bpo-8722.MPyVyj.rst b/Misc/NEWS.d/next/Documentation/2018-02-03-06-11-37.bpo-8722.MPyVyj.rst new file mode 100644 index 000000000000..36e6ff7db3ce --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2018-02-03-06-11-37.bpo-8722.MPyVyj.rst @@ -0,0 +1,2 @@ +Document :meth:`__getattr__` behavior when property :meth:`get` method +raises :exc:`AttributeError`. From webhook-mailer at python.org Mon Feb 5 03:14:18 2018 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Mon, 05 Feb 2018 08:14:18 -0000 Subject: [Python-checkins] bpo-30928: IDLE - update NEWS.txt [GH-5539] (GH-5545) Message-ID: https://github.com/python/cpython/commit/7bd5a75bbe28219d3fc18a239c2c554d1850abcb commit: 7bd5a75bbe28219d3fc18a239c2c554d1850abcb branch: 3.6 author: Terry Jan Reedy committer: GitHub date: 2018-02-05T03:14:15-05:00 summary: bpo-30928: IDLE - update NEWS.txt [GH-5539] (GH-5545) Add entry for uniform lower context; add 'since' to be explicit. (cherry picked from commit 05e806767b857b1eab838e712828e3a7d57cabf1) files: M Lib/idlelib/NEWS.txt diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index 14d2dddcae2f..d82fde26f28f 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -1,7 +1,10 @@ What's New in IDLE 3.6.5 Released on 2017-03-26? -======================== +====================================== + +bpo-32765: Update configdialog General tab create page docstring. +Add new widgets to the widget list. What's New in IDLE 3.6.4 @@ -314,9 +317,9 @@ Issue #28572: Add 10% to coverage of IDLE's test_configdialog. Update and augment description of the configuration system. -What's New in IDLE 3.6.0 +What's New in IDLE 3.6.0 (since 3.5.0) Released on 2016-12-23 -======================== +====================================== - Issue #15308: Add 'interrupt execution' (^C) to Shell menu. Patch by Roger Serwy, updated by Bayard Randel. From webhook-mailer at python.org Mon Feb 5 04:29:10 2018 From: webhook-mailer at python.org (Mariatta) Date: Mon, 05 Feb 2018 09:29:10 -0000 Subject: [Python-checkins] bpo-32720: Fixed the replacement field grammar documentation. (GH-5544) Message-ID: https://github.com/python/cpython/commit/7a561afd2c79f63a6008843b83733911d07f0119 commit: 7a561afd2c79f63a6008843b83733911d07f0119 branch: master author: Mariatta committer: GitHub date: 2018-02-05T04:29:02-05:00 summary: bpo-32720: Fixed the replacement field grammar documentation. (GH-5544) `arg_name` and `element_index` are defined as `digit`+ instead of `integer`. files: M Doc/library/string.rst diff --git a/Doc/library/string.rst b/Doc/library/string.rst index 9b30f8fe1299..ee8ea857da4b 100644 --- a/Doc/library/string.rst +++ b/Doc/library/string.rst @@ -202,9 +202,9 @@ The grammar for a replacement field is as follows: .. productionlist:: sf replacement_field: "{" [`field_name`] ["!" `conversion`] [":" `format_spec`] "}" field_name: arg_name ("." `attribute_name` | "[" `element_index` "]")* - arg_name: [`identifier` | `integer`] + arg_name: [`identifier` | `digit`+] attribute_name: `identifier` - element_index: `integer` | `index_string` + element_index: `digit`+ | `index_string` index_string: + conversion: "r" | "s" | "a" format_spec: From webhook-mailer at python.org Mon Feb 5 09:39:38 2018 From: webhook-mailer at python.org (Mariatta) Date: Mon, 05 Feb 2018 14:39:38 -0000 Subject: [Python-checkins] Fix typo in whatsnew/3.7.rst (GH-5551) Message-ID: https://github.com/python/cpython/commit/c309bcfb9fb295e70a235c461d9edcaa54c821d0 commit: c309bcfb9fb295e70a235c461d9edcaa54c821d0 branch: master author: Dag Heyman committer: Mariatta date: 2018-02-05T09:39:33-05:00 summary: Fix typo in whatsnew/3.7.rst (GH-5551) now longer -> no longer files: M Doc/whatsnew/3.7.rst diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 4fdbb9182bbd..7b17c62e2562 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -496,7 +496,7 @@ therefore included in source distributions. and ``platforms`` fields are not specified as a list or a string. (Contributed by Berker Peksag in :issue:`19610`.) -The ``upload`` command now longer tries to change CR end-of-line characters +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`.) From webhook-mailer at python.org Mon Feb 5 15:47:50 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Mon, 05 Feb 2018 20:47:50 -0000 Subject: [Python-checkins] bpo-32749: Make dbm.dumb databases more cosistent with other dbm databases. (#5497) Message-ID: https://github.com/python/cpython/commit/6c85efa5a66d7b254aa22a39d47f36c040d7a04e commit: 6c85efa5a66d7b254aa22a39d47f36c040d7a04e branch: master author: Serhiy Storchaka committer: GitHub date: 2018-02-05T22:47:31+02:00 summary: bpo-32749: Make dbm.dumb databases more cosistent with other dbm databases. (#5497) files: A Misc/NEWS.d/next/Library/2018-02-02-17-21-24.bpo-32749.u5scIn.rst M Doc/library/dbm.rst M Doc/whatsnew/3.8.rst M Lib/dbm/dumb.py M Lib/test/test_dbm_dumb.py diff --git a/Doc/library/dbm.rst b/Doc/library/dbm.rst index 32e80b2cf6ed..1abc36c04a74 100644 --- a/Doc/library/dbm.rst +++ b/Doc/library/dbm.rst @@ -339,9 +339,23 @@ The module defines the following: dumbdbm database is created, files with :file:`.dat` and :file:`.dir` extensions are created. - The optional *flag* argument supports only the semantics of ``'c'`` - and ``'n'`` values. Other values will default to database being always - opened for update, and will be created if it does not exist. + The optional *flag* argument can be: + + +---------+-------------------------------------------+ + | Value | Meaning | + +=========+===========================================+ + | ``'r'`` | Open existing database for reading only | + | | (default) | + +---------+-------------------------------------------+ + | ``'w'`` | Open existing database for reading and | + | | writing | + +---------+-------------------------------------------+ + | ``'c'`` | Open database for reading and writing, | + | | creating it if it doesn't exist | + +---------+-------------------------------------------+ + | ``'n'`` | Always create a new, empty database, open | + | | for reading and writing | + +---------+-------------------------------------------+ The optional *mode* argument is the Unix mode of the file, used only when the database has to be created. It defaults to octal ``0o666`` (and will be modified @@ -351,9 +365,10 @@ The module defines the following: :func:`.open` always creates a new database when the flag has the value ``'n'``. - .. deprecated-removed:: 3.6 3.8 - Creating database in ``'r'`` and ``'w'`` modes. Modifying database in - ``'r'`` mode. + .. versionchanged:: 3.8 + A database opened with flags ``'r'`` is now read-only. Opening with + flags ``'r'`` and ``'w'`` no longer creates a database if it does not + exist. In addition to the methods provided by the :class:`collections.abc.MutableMapping` class, :class:`dumbdbm` objects diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index c4063ad76744..60f54a0561e5 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -130,3 +130,8 @@ Changes in the Python API arguments for changing the selection was deprecated in Python 3.6. Use specialized methods like :meth:`~tkinter.ttk.Treeview.selection_set` for changing the selection. (Contributed by Serhiy Storchaka in :issue:`31508`.) + +* A :mod:`dbm.dumb` database opened with flags ``'r'`` is now read-only. + :func:`dbm.dumb.open` with flags ``'r'`` and ``'w'`` no longer creates + a database if it does not exist. + (Contributed by Serhiy Storchaka in :issue:`32749`.) diff --git a/Lib/dbm/dumb.py b/Lib/dbm/dumb.py index 5064668c77ea..e5c17f5ae2ed 100644 --- a/Lib/dbm/dumb.py +++ b/Lib/dbm/dumb.py @@ -82,10 +82,7 @@ def _create(self, flag): f = _io.open(self._datfile, 'r', encoding="Latin-1") except OSError: if flag not in ('c', 'n'): - import warnings - warnings.warn("The database file is missing, the " - "semantics of the 'c' flag will be used.", - DeprecationWarning, stacklevel=4) + raise with _io.open(self._datfile, 'w', encoding="Latin-1") as f: self._chmod(self._datfile) else: @@ -93,18 +90,15 @@ def _create(self, flag): # Read directory file into the in-memory index dict. def _update(self, flag): + self._modified = False self._index = {} try: f = _io.open(self._dirfile, 'r', encoding="Latin-1") except OSError: - self._modified = not self._readonly if flag not in ('c', 'n'): - import warnings - warnings.warn("The index file is missing, the " - "semantics of the 'c' flag will be used.", - DeprecationWarning, stacklevel=4) + raise + self._modified = True else: - self._modified = False with f: for line in f: line = line.rstrip() @@ -191,9 +185,7 @@ def _addkey(self, key, pos_and_siz_pair): def __setitem__(self, key, val): if self._readonly: - import warnings - warnings.warn('The database is opened for reading only', - DeprecationWarning, stacklevel=2) + raise ValueError('The database is opened for reading only') if isinstance(key, str): key = key.encode('utf-8') elif not isinstance(key, (bytes, bytearray)): @@ -230,9 +222,7 @@ def __setitem__(self, key, val): def __delitem__(self, key): if self._readonly: - import warnings - warnings.warn('The database is opened for reading only', - DeprecationWarning, stacklevel=2) + raise ValueError('The database is opened for reading only') if isinstance(key, str): key = key.encode('utf-8') self._verify_open() @@ -323,7 +313,5 @@ def open(file, flag='c', mode=0o666): # Turn off any bits that are set in the umask mode = mode & (~um) if flag not in ('r', 'w', 'c', 'n'): - import warnings - warnings.warn("Flag must be one of 'r', 'w', 'c', or 'n'", - DeprecationWarning, stacklevel=2) + raise ValueError("Flag must be one of 'r', 'w', 'c', or 'n'") return _Database(file, mode, flag=flag) diff --git a/Lib/test/test_dbm_dumb.py b/Lib/test/test_dbm_dumb.py index 73f2a32a7b49..21f29af05d28 100644 --- a/Lib/test/test_dbm_dumb.py +++ b/Lib/test/test_dbm_dumb.py @@ -79,10 +79,10 @@ def test_dumbdbm_read(self): self.init_db() f = dumbdbm.open(_fname, 'r') self.read_helper(f) - with self.assertWarnsRegex(DeprecationWarning, + with self.assertRaisesRegex(ValueError, 'The database is opened for reading only'): f[b'g'] = b'x' - with self.assertWarnsRegex(DeprecationWarning, + with self.assertRaisesRegex(ValueError, 'The database is opened for reading only'): del f[b'a'] f.close() @@ -241,37 +241,30 @@ def test_eval(self): pass self.assertEqual(stdout.getvalue(), '') - def test_warn_on_ignored_flags(self): + def test_missing_data(self): for value in ('r', 'w'): _delete_files() - with self.assertWarnsRegex(DeprecationWarning, - "The database file is missing, the " - "semantics of the 'c' flag will " - "be used."): - f = dumbdbm.open(_fname, value) - f.close() + with self.assertRaises(FileNotFoundError): + dumbdbm.open(_fname, value) + self.assertFalse(os.path.exists(_fname + '.dir')) + self.assertFalse(os.path.exists(_fname + '.bak')) def test_missing_index(self): with dumbdbm.open(_fname, 'n') as f: pass os.unlink(_fname + '.dir') for value in ('r', 'w'): - with self.assertWarnsRegex(DeprecationWarning, - "The index file is missing, the " - "semantics of the 'c' flag will " - "be used."): - f = dumbdbm.open(_fname, value) - f.close() - self.assertEqual(os.path.exists(_fname + '.dir'), value == 'w') + with self.assertRaises(FileNotFoundError): + dumbdbm.open(_fname, value) + self.assertFalse(os.path.exists(_fname + '.dir')) self.assertFalse(os.path.exists(_fname + '.bak')) def test_invalid_flag(self): for flag in ('x', 'rf', None): - with self.assertWarnsRegex(DeprecationWarning, - "Flag must be one of " - "'r', 'w', 'c', or 'n'"): - f = dumbdbm.open(_fname, flag) - f.close() + with self.assertRaisesRegex(ValueError, + "Flag must be one of " + "'r', 'w', 'c', or 'n'"): + dumbdbm.open(_fname, flag) @unittest.skipUnless(hasattr(os, 'chmod'), 'test needs os.chmod()') def test_readonly_files(self): diff --git a/Misc/NEWS.d/next/Library/2018-02-02-17-21-24.bpo-32749.u5scIn.rst b/Misc/NEWS.d/next/Library/2018-02-02-17-21-24.bpo-32749.u5scIn.rst new file mode 100644 index 000000000000..9665ff1f8ec8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-02-17-21-24.bpo-32749.u5scIn.rst @@ -0,0 +1,3 @@ +A :mod:`dbm.dumb` database opened with flags 'r' is now read-only. +:func:`dbm.dumb.open` with flags 'r' and 'w' no longer creates a database if +it does not exist. From webhook-mailer at python.org Mon Feb 5 21:28:50 2018 From: webhook-mailer at python.org (Alexander Belopolsky) Date: Tue, 06 Feb 2018 02:28:50 -0000 Subject: [Python-checkins] Add What's new entry for datetime.fromisoformat (#5559) Message-ID: https://github.com/python/cpython/commit/22864bc8e4a076bbac748ccda6c27f1ec41b53e7 commit: 22864bc8e4a076bbac748ccda6c27f1ec41b53e7 branch: master author: Paul Ganssle committer: Alexander Belopolsky date: 2018-02-05T21:28:46-05:00 summary: Add What's new entry for datetime.fromisoformat (#5559) Documents bpo-15873 files: M Doc/whatsnew/3.7.rst diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 7b17c62e2562..8d4772f973fb 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -477,6 +477,14 @@ Added support for the Blowfish method. The :func:`~crypt.mksalt` function now allows to specify the number of rounds for hashing. (Contributed by Serhiy Storchaka in :issue:`31702`.) +datetime +-------- + +Added the :func:`datetime.datetime.fromisoformat` method, which constructs a +:class:`datetime.datetime` object from a string in one of the formats output +by :func:`datetime.datetime.isoformat`. (Contributed by Paul Ganssle in +:issue:`15873`.) + dis --- From webhook-mailer at python.org Tue Feb 6 01:09:37 2018 From: webhook-mailer at python.org (Gregory P. Smith) Date: Tue, 06 Feb 2018 06:09:37 -0000 Subject: [Python-checkins] bpo-32777: Fix _Py_set_inheritable async-safety in subprocess (GH-5560) Message-ID: https://github.com/python/cpython/commit/c1e46e94de38a92f98736af9a42d89c3975a9919 commit: c1e46e94de38a92f98736af9a42d89c3975a9919 branch: master author: Alexey Izbyshev committer: Gregory P. Smith date: 2018-02-05T22:09:34-08:00 summary: bpo-32777: Fix _Py_set_inheritable async-safety in subprocess (GH-5560) Fix a rare but potential pre-exec child process deadlock in subprocess on POSIX systems when marking file descriptors inheritable on exec in the child process. This bug appears to have been introduced in 3.4 with the inheritable file descriptors support. This also changes Python/fileutils.c `set_inheritable` to use the "slow" two `fcntl` syscall path instead of the "fast" single `ioctl` syscall path when asked to be async signal safe (by way of being asked not to raise exceptions). `ioctl` is not a POSIX async-signal-safe approved function. ref: http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html files: A Misc/NEWS.d/next/Library/2018-02-05-21-28-28.bpo-32777.C-wIXF.rst M Include/fileutils.h M Modules/_posixsubprocess.c M Python/fileutils.c diff --git a/Include/fileutils.h b/Include/fileutils.h index 21eefdef87a2..e4bf6d4db95d 100644 --- a/Include/fileutils.h +++ b/Include/fileutils.h @@ -152,6 +152,9 @@ PyAPI_FUNC(int) _Py_get_inheritable(int fd); PyAPI_FUNC(int) _Py_set_inheritable(int fd, int inheritable, int *atomic_flag_works); +PyAPI_FUNC(int) _Py_set_inheritable_async_safe(int fd, int inheritable, + int *atomic_flag_works); + PyAPI_FUNC(int) _Py_dup(int fd); #ifndef MS_WINDOWS diff --git a/Misc/NEWS.d/next/Library/2018-02-05-21-28-28.bpo-32777.C-wIXF.rst b/Misc/NEWS.d/next/Library/2018-02-05-21-28-28.bpo-32777.C-wIXF.rst new file mode 100644 index 000000000000..d5d7d7b27dc7 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-05-21-28-28.bpo-32777.C-wIXF.rst @@ -0,0 +1,3 @@ +Fix a rare but potential pre-exec child process deadlock in subprocess on +POSIX systems when marking file descriptors inheritable on exec in the child +process. This bug appears to have been introduced in 3.4. diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c index ea7a3d6c18be..dc43ffc2e19d 100644 --- a/Modules/_posixsubprocess.c +++ b/Modules/_posixsubprocess.c @@ -169,7 +169,7 @@ make_inheritable(PyObject *py_fds_to_keep, int errpipe_write) called. */ continue; } - if (_Py_set_inheritable((int)fd, 1, NULL) < 0) + if (_Py_set_inheritable_async_safe((int)fd, 1, NULL) < 0) return -1; } return 0; @@ -431,21 +431,21 @@ child_exec(char *const exec_array[], dup2() removes the CLOEXEC flag but we must do it ourselves if dup2() would be a no-op (issue #10806). */ if (p2cread == 0) { - if (_Py_set_inheritable(p2cread, 1, NULL) < 0) + if (_Py_set_inheritable_async_safe(p2cread, 1, NULL) < 0) goto error; } else if (p2cread != -1) POSIX_CALL(dup2(p2cread, 0)); /* stdin */ if (c2pwrite == 1) { - if (_Py_set_inheritable(c2pwrite, 1, NULL) < 0) + if (_Py_set_inheritable_async_safe(c2pwrite, 1, NULL) < 0) goto error; } else if (c2pwrite != -1) POSIX_CALL(dup2(c2pwrite, 1)); /* stdout */ if (errwrite == 2) { - if (_Py_set_inheritable(errwrite, 1, NULL) < 0) + if (_Py_set_inheritable_async_safe(errwrite, 1, NULL) < 0) goto error; } else if (errwrite != -1) diff --git a/Python/fileutils.c b/Python/fileutils.c index d610639688ea..3cf8b7a8b69d 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -913,6 +913,7 @@ _Py_stat(PyObject *path, struct stat *statbuf) } +/* This function MUST be kept async-signal-safe on POSIX when raise=0. */ static int get_inheritable(int fd, int raise) { @@ -958,6 +959,8 @@ _Py_get_inheritable(int fd) return get_inheritable(fd, 1); } + +/* This function MUST be kept async-signal-safe on POSIX when raise=0. */ static int set_inheritable(int fd, int inheritable, int raise, int *atomic_flag_works) { @@ -1014,8 +1017,10 @@ set_inheritable(int fd, int inheritable, int raise, int *atomic_flag_works) #else #if defined(HAVE_SYS_IOCTL_H) && defined(FIOCLEX) && defined(FIONCLEX) - if (ioctl_works != 0) { + if (ioctl_works != 0 && raise != 0) { /* fast-path: ioctl() only requires one syscall */ + /* caveat: raise=0 is an indicator that we must be async-signal-safe + * thus avoid using ioctl() so we skip the fast-path. */ if (inheritable) request = FIONCLEX; else @@ -1086,8 +1091,7 @@ make_non_inheritable(int fd) } /* Set the inheritable flag of the specified file descriptor. - On success: return 0, on error: raise an exception if raise is nonzero - and return -1. + On success: return 0, on error: raise an exception and return -1. If atomic_flag_works is not NULL: @@ -1108,6 +1112,15 @@ _Py_set_inheritable(int fd, int inheritable, int *atomic_flag_works) return set_inheritable(fd, inheritable, 1, atomic_flag_works); } +/* Same as _Py_set_inheritable() but on error, set errno and + don't raise an exception. + This function is async-signal-safe. */ +int +_Py_set_inheritable_async_safe(int fd, int inheritable, int *atomic_flag_works) +{ + return set_inheritable(fd, inheritable, 0, atomic_flag_works); +} + static int _Py_open_impl(const char *pathname, int flags, int gil_held) { From webhook-mailer at python.org Tue Feb 6 01:51:12 2018 From: webhook-mailer at python.org (Gregory P. Smith) Date: Tue, 06 Feb 2018 06:51:12 -0000 Subject: [Python-checkins] bpo-32777: Fix _Py_set_inheritable async-safety in subprocess (GH-5560) (GH-5563) Message-ID: https://github.com/python/cpython/commit/b90c68586e1f2c45c736dd38880f182be267e2ef commit: b90c68586e1f2c45c736dd38880f182be267e2ef branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Gregory P. Smith date: 2018-02-05T22:51:10-08:00 summary: bpo-32777: Fix _Py_set_inheritable async-safety in subprocess (GH-5560) (GH-5563) Fix a rare but potential pre-exec child process deadlock in subprocess on POSIX systems when marking file descriptors inheritable on exec in the child process. This bug appears to have been introduced in 3.4 with the inheritable file descriptors support. This also changes Python/fileutils.c `set_inheritable` to use the "slow" two `fcntl` syscall path instead of the "fast" single `ioctl` syscall path when asked to be async signal safe (by way of being asked not to raise exceptions). `ioctl` is not a POSIX async-signal-safe approved function. ref: http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html (cherry picked from commit c1e46e94de38a92f98736af9a42d89c3975a9919) Co-authored-by: Alexey Izbyshev files: A Misc/NEWS.d/next/Library/2018-02-05-21-28-28.bpo-32777.C-wIXF.rst M Include/fileutils.h M Modules/_posixsubprocess.c M Python/fileutils.c diff --git a/Include/fileutils.h b/Include/fileutils.h index 8fa70baa21cf..9fce7d23cf0e 100644 --- a/Include/fileutils.h +++ b/Include/fileutils.h @@ -121,6 +121,9 @@ PyAPI_FUNC(int) _Py_get_inheritable(int fd); PyAPI_FUNC(int) _Py_set_inheritable(int fd, int inheritable, int *atomic_flag_works); +PyAPI_FUNC(int) _Py_set_inheritable_async_safe(int fd, int inheritable, + int *atomic_flag_works); + PyAPI_FUNC(int) _Py_dup(int fd); #ifndef MS_WINDOWS diff --git a/Misc/NEWS.d/next/Library/2018-02-05-21-28-28.bpo-32777.C-wIXF.rst b/Misc/NEWS.d/next/Library/2018-02-05-21-28-28.bpo-32777.C-wIXF.rst new file mode 100644 index 000000000000..d5d7d7b27dc7 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-05-21-28-28.bpo-32777.C-wIXF.rst @@ -0,0 +1,3 @@ +Fix a rare but potential pre-exec child process deadlock in subprocess on +POSIX systems when marking file descriptors inheritable on exec in the child +process. This bug appears to have been introduced in 3.4. diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c index d1434d59f818..05a08eb87765 100644 --- a/Modules/_posixsubprocess.c +++ b/Modules/_posixsubprocess.c @@ -169,7 +169,7 @@ make_inheritable(PyObject *py_fds_to_keep, int errpipe_write) called. */ continue; } - if (_Py_set_inheritable((int)fd, 1, NULL) < 0) + if (_Py_set_inheritable_async_safe((int)fd, 1, NULL) < 0) return -1; } return 0; @@ -431,21 +431,21 @@ child_exec(char *const exec_array[], dup2() removes the CLOEXEC flag but we must do it ourselves if dup2() would be a no-op (issue #10806). */ if (p2cread == 0) { - if (_Py_set_inheritable(p2cread, 1, NULL) < 0) + if (_Py_set_inheritable_async_safe(p2cread, 1, NULL) < 0) goto error; } else if (p2cread != -1) POSIX_CALL(dup2(p2cread, 0)); /* stdin */ if (c2pwrite == 1) { - if (_Py_set_inheritable(c2pwrite, 1, NULL) < 0) + if (_Py_set_inheritable_async_safe(c2pwrite, 1, NULL) < 0) goto error; } else if (c2pwrite != -1) POSIX_CALL(dup2(c2pwrite, 1)); /* stdout */ if (errwrite == 2) { - if (_Py_set_inheritable(errwrite, 1, NULL) < 0) + if (_Py_set_inheritable_async_safe(errwrite, 1, NULL) < 0) goto error; } else if (errwrite != -1) diff --git a/Python/fileutils.c b/Python/fileutils.c index 7b87b72f73c8..899ea8aecac0 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -806,6 +806,7 @@ _Py_stat(PyObject *path, struct stat *statbuf) } +/* This function MUST be kept async-signal-safe on POSIX when raise=0. */ static int get_inheritable(int fd, int raise) { @@ -851,6 +852,8 @@ _Py_get_inheritable(int fd) return get_inheritable(fd, 1); } + +/* This function MUST be kept async-signal-safe on POSIX when raise=0. */ static int set_inheritable(int fd, int inheritable, int raise, int *atomic_flag_works) { @@ -907,8 +910,10 @@ set_inheritable(int fd, int inheritable, int raise, int *atomic_flag_works) #else #if defined(HAVE_SYS_IOCTL_H) && defined(FIOCLEX) && defined(FIONCLEX) - if (ioctl_works != 0) { + if (ioctl_works != 0 && raise != 0) { /* fast-path: ioctl() only requires one syscall */ + /* caveat: raise=0 is an indicator that we must be async-signal-safe + * thus avoid using ioctl() so we skip the fast-path. */ if (inheritable) request = FIONCLEX; else @@ -979,8 +984,7 @@ make_non_inheritable(int fd) } /* Set the inheritable flag of the specified file descriptor. - On success: return 0, on error: raise an exception if raise is nonzero - and return -1. + On success: return 0, on error: raise an exception and return -1. If atomic_flag_works is not NULL: @@ -1001,6 +1005,15 @@ _Py_set_inheritable(int fd, int inheritable, int *atomic_flag_works) return set_inheritable(fd, inheritable, 1, atomic_flag_works); } +/* Same as _Py_set_inheritable() but on error, set errno and + don't raise an exception. + This function is async-signal-safe. */ +int +_Py_set_inheritable_async_safe(int fd, int inheritable, int *atomic_flag_works) +{ + return set_inheritable(fd, inheritable, 0, atomic_flag_works); +} + static int _Py_open_impl(const char *pathname, int flags, int gil_held) { From solipsis at pitrou.net Tue Feb 6 04:10:29 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Tue, 06 Feb 2018 09:10:29 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=6 Message-ID: <20180206091029.1.C1BF8366A0BB79BB@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_spawn leaked [2, 0, 0] memory blocks, sum=2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogDjKgQs', '--timeout', '7200'] From webhook-mailer at python.org Tue Feb 6 12:29:24 2018 From: webhook-mailer at python.org (Benjamin Peterson) Date: Tue, 06 Feb 2018 17:29:24 -0000 Subject: [Python-checkins] allow the test suite to pass if the strop module doesn't exist (GH-5566) Message-ID: https://github.com/python/cpython/commit/0a18422b31e0d7549da5ddbf62194f8c583c2091 commit: 0a18422b31e0d7549da5ddbf62194f8c583c2091 branch: 2.7 author: Benjamin Peterson committer: GitHub date: 2018-02-06T09:29:21-08:00 summary: allow the test suite to pass if the strop module doesn't exist (GH-5566) strop is highly legacy and can be safely compiled out in most installations. Let's not fail the test suite for its absence. files: M Lib/test/test_strop.py diff --git a/Lib/test/test_strop.py b/Lib/test/test_strop.py index 81d078ed8d39..50b8f6ebc3d8 100644 --- a/Lib/test/test_strop.py +++ b/Lib/test/test_strop.py @@ -2,11 +2,12 @@ warnings.filterwarnings("ignore", "strop functions are obsolete;", DeprecationWarning, r'test.test_strop|unittest') -import strop import unittest import sys from test import test_support +strop = test_support.import_module("strop") + class StropFunctionTestCase(unittest.TestCase): From webhook-mailer at python.org Tue Feb 6 13:08:59 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Tue, 06 Feb 2018 18:08:59 -0000 Subject: [Python-checkins] bpo-30693: Fix tarfile test cleanup on MSWindows (#5557) Message-ID: https://github.com/python/cpython/commit/4ad703b7ca463d1183539277dde90ffb1c808487 commit: 4ad703b7ca463d1183539277dde90ffb1c808487 branch: master author: Bernhard M. Wiedemann committer: Serhiy Storchaka date: 2018-02-06T20:08:53+02:00 summary: bpo-30693: Fix tarfile test cleanup on MSWindows (#5557) it was using our mocked listdir to check when the files were gone. files: M Lib/test/test_tarfile.py diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py index 8ef4294921b2..b868326d5c74 100644 --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -1131,17 +1131,17 @@ def test_directory_size(self): # mock the following: # os.listdir: so we know that files are in the wrong order - @unittest.mock.patch('os.listdir') - def test_ordered_recursion(self, mock_listdir): + def test_ordered_recursion(self): path = os.path.join(TEMPDIR, "directory") os.mkdir(path) open(os.path.join(path, "1"), "a").close() open(os.path.join(path, "2"), "a").close() - mock_listdir.return_value = ["2", "1"] try: tar = tarfile.open(tmpname, self.mode) try: - tar.add(path) + with unittest.mock.patch('os.listdir') as mock_listdir: + mock_listdir.return_value = ["2", "1"] + tar.add(path) paths = [] for m in tar.getmembers(): paths.append(os.path.split(m.name)[-1]) From webhook-mailer at python.org Tue Feb 6 13:33:30 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Tue, 06 Feb 2018 18:33:30 -0000 Subject: [Python-checkins] bpo-30693: Fix tarfile test cleanup on MSWindows (GH-5557) (GH-5567) Message-ID: https://github.com/python/cpython/commit/2c6f6682768f401c297c584ef106d48c78697f67 commit: 2c6f6682768f401c297c584ef106d48c78697f67 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Serhiy Storchaka date: 2018-02-06T20:33:27+02:00 summary: bpo-30693: Fix tarfile test cleanup on MSWindows (GH-5557) (GH-5567) it was using our mocked listdir to check when the files were gone. (cherry picked from commit 4ad703b7ca463d1183539277dde90ffb1c808487) Co-authored-by: Bernhard M. Wiedemann files: M Lib/test/test_tarfile.py diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py index 8ef4294921b2..b868326d5c74 100644 --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -1131,17 +1131,17 @@ def test_directory_size(self): # mock the following: # os.listdir: so we know that files are in the wrong order - @unittest.mock.patch('os.listdir') - def test_ordered_recursion(self, mock_listdir): + def test_ordered_recursion(self): path = os.path.join(TEMPDIR, "directory") os.mkdir(path) open(os.path.join(path, "1"), "a").close() open(os.path.join(path, "2"), "a").close() - mock_listdir.return_value = ["2", "1"] try: tar = tarfile.open(tmpname, self.mode) try: - tar.add(path) + with unittest.mock.patch('os.listdir') as mock_listdir: + mock_listdir.return_value = ["2", "1"] + tar.add(path) paths = [] for m in tar.getmembers(): paths.append(os.path.split(m.name)[-1]) From webhook-mailer at python.org Tue Feb 6 18:07:38 2018 From: webhook-mailer at python.org (Mariatta) Date: Tue, 06 Feb 2018 23:07:38 -0000 Subject: [Python-checkins] Fix typo in Include/objimpl.h, the word "has" was missing (GH-5568) Message-ID: https://github.com/python/cpython/commit/517da1e58f4c489d4b31579852cde5f7113da08e commit: 517da1e58f4c489d4b31579852cde5f7113da08e branch: master author: Alexey committer: Mariatta date: 2018-02-06T16:07:30-07:00 summary: Fix typo in Include/objimpl.h, the word "has" was missing (GH-5568) It now reads: ...be aware that Python has no control over... files: M Include/objimpl.h diff --git a/Include/objimpl.h b/Include/objimpl.h index ed9e7a968066..057bb50cbda9 100644 --- a/Include/objimpl.h +++ b/Include/objimpl.h @@ -56,7 +56,7 @@ must use the platform malloc heap(s), or shared memory, or C++ local storage or operator new), you must first allocate the object with your custom allocator, then pass its pointer to PyObject_{Init, InitVar} for filling in its Python- specific fields: reference count, type pointer, possibly others. You should -be aware that Python no control over these objects because they don't +be aware that Python has no control over these objects because they don't cooperate with the Python memory manager. Such objects may not be eligible for automatic garbage collection and you have to make sure that they are released accordingly whenever their destructor gets called (cf. the specific From webhook-mailer at python.org Tue Feb 6 19:46:34 2018 From: webhook-mailer at python.org (Gregory P. Smith) Date: Wed, 07 Feb 2018 00:46:34 -0000 Subject: [Python-checkins] bpo-6135: Fix subprocess.check_output doc to mention changes in 3.6 (GH-5564) Message-ID: https://github.com/python/cpython/commit/fc1ce810f1da593648b4d19e7d582a235ec1dd37 commit: fc1ce810f1da593648b4d19e7d582a235ec1dd37 branch: master author: Brice Gros committer: Gregory P. Smith date: 2018-02-06T16:46:29-08:00 summary: bpo-6135: Fix subprocess.check_output doc to mention changes in 3.6 (GH-5564) Fixes the documentation for `subprocess.check_output()` not mentioning that the encoding and errors parameters were added in 3.6. files: M Doc/library/subprocess.rst diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst index 27d4288f67b3..8673c4b18d8c 100644 --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -1087,6 +1087,9 @@ calls these functions. .. versionchanged:: 3.4 Support for the *input* keyword argument was added. + .. versionchanged:: 3.6 + *encoding* and *errors* were added. See :func:`run` for details. + .. _subprocess-replacements: Replacing Older Functions with the :mod:`subprocess` Module From webhook-mailer at python.org Tue Feb 6 20:12:12 2018 From: webhook-mailer at python.org (Gregory P. Smith) Date: Wed, 07 Feb 2018 01:12:12 -0000 Subject: [Python-checkins] bpo-6135: Fix subprocess.check_output doc to mention changes in 3.6 (GH-5564) (GH-5572) Message-ID: https://github.com/python/cpython/commit/4e7a964aaf4374fa2f6b45cf5161fa6cd53aec19 commit: 4e7a964aaf4374fa2f6b45cf5161fa6cd53aec19 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Gregory P. Smith date: 2018-02-06T17:12:06-08:00 summary: bpo-6135: Fix subprocess.check_output doc to mention changes in 3.6 (GH-5564) (GH-5572) Fixes the documentation for `subprocess.check_output()` not mentioning that the encoding and errors parameters were added in 3.6. (cherry picked from commit fc1ce810f1da593648b4d19e7d582a235ec1dd37) Co-authored-by: Brice Gros files: M Doc/library/subprocess.rst diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst index 27d4288f67b3..8673c4b18d8c 100644 --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -1087,6 +1087,9 @@ calls these functions. .. versionchanged:: 3.4 Support for the *input* keyword argument was added. + .. versionchanged:: 3.6 + *encoding* and *errors* were added. See :func:`run` for details. + .. _subprocess-replacements: Replacing Older Functions with the :mod:`subprocess` Module From webhook-mailer at python.org Tue Feb 6 20:13:50 2018 From: webhook-mailer at python.org (Mariatta) Date: Wed, 07 Feb 2018 01:13:50 -0000 Subject: [Python-checkins] Fix typo in whatsnew/3.7.rst (GH-5551) (GH-5553) Message-ID: https://github.com/python/cpython/commit/a702f6b44256817c28e7b3c6c4a99cb2af81151e commit: a702f6b44256817c28e7b3c6c4a99cb2af81151e branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Mariatta date: 2018-02-06T18:13:47-07:00 summary: Fix typo in whatsnew/3.7.rst (GH-5551) (GH-5553) now longer -> no longer (cherry picked from commit c309bcfb9fb295e70a235c461d9edcaa54c821d0) Co-authored-by: Dag Heyman files: M Doc/whatsnew/3.7.rst diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 4fdbb9182bbd..7b17c62e2562 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -496,7 +496,7 @@ therefore included in source distributions. and ``platforms`` fields are not specified as a list or a string. (Contributed by Berker Peksag in :issue:`19610`.) -The ``upload`` command now longer tries to change CR end-of-line characters +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`.) From webhook-mailer at python.org Tue Feb 6 20:14:23 2018 From: webhook-mailer at python.org (Mariatta) Date: Wed, 07 Feb 2018 01:14:23 -0000 Subject: [Python-checkins] bpo-32720: Fixed the replacement field grammar documentation. (GH-5544) (GH-5546) Message-ID: https://github.com/python/cpython/commit/a747cf6d9b87ea8c7ce3a42d09e5b966c8e83fa0 commit: a747cf6d9b87ea8c7ce3a42d09e5b966c8e83fa0 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Mariatta date: 2018-02-06T18:14:20-07:00 summary: bpo-32720: Fixed the replacement field grammar documentation. (GH-5544) (GH-5546) `arg_name` and `element_index` are defined as `digit`+ instead of `integer`. (cherry picked from commit 7a561afd2c79f63a6008843b83733911d07f0119) Co-authored-by: Mariatta files: M Doc/library/string.rst diff --git a/Doc/library/string.rst b/Doc/library/string.rst index 9b30f8fe1299..ee8ea857da4b 100644 --- a/Doc/library/string.rst +++ b/Doc/library/string.rst @@ -202,9 +202,9 @@ The grammar for a replacement field is as follows: .. productionlist:: sf replacement_field: "{" [`field_name`] ["!" `conversion`] [":" `format_spec`] "}" field_name: arg_name ("." `attribute_name` | "[" `element_index` "]")* - arg_name: [`identifier` | `integer`] + arg_name: [`identifier` | `digit`+] attribute_name: `identifier` - element_index: `integer` | `index_string` + element_index: `digit`+ | `index_string` index_string: + conversion: "r" | "s" | "a" format_spec: From webhook-mailer at python.org Tue Feb 6 21:11:34 2018 From: webhook-mailer at python.org (Gregory P. Smith) Date: Wed, 07 Feb 2018 02:11:34 -0000 Subject: [Python-checkins] bpo-6135: Fix subprocess.check_output doc to mention changes in 3.6 (GH-5564) (GH-5573) Message-ID: https://github.com/python/cpython/commit/7f95c8c319c1ee593b130d0eb1d4947d9d7e008a commit: 7f95c8c319c1ee593b130d0eb1d4947d9d7e008a branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Gregory P. Smith date: 2018-02-06T18:11:26-08:00 summary: bpo-6135: Fix subprocess.check_output doc to mention changes in 3.6 (GH-5564) (GH-5573) Fixes the documentation for `subprocess.check_output()` not mentioning that the encoding and errors parameters were added in 3.6. (cherry picked from commit fc1ce810f1da593648b4d19e7d582a235ec1dd37) Co-authored-by: Brice Gros files: M Doc/library/subprocess.rst diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst index ea7e664f578b..6a5f276073b2 100644 --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -956,6 +956,9 @@ calls these functions. .. versionchanged:: 3.4 Support for the *input* keyword argument was added. + .. versionchanged:: 3.6 + *encoding* and *errors* were added. See :func:`run` for details. + .. _subprocess-replacements: Replacing Older Functions with the :mod:`subprocess` Module From solipsis at pitrou.net Wed Feb 7 04:12:06 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 07 Feb 2018 09:12:06 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=-1 Message-ID: <20180207091206.1.65ADC7F3C1A93D44@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_fork leaked [0, -1, 2] memory blocks, sum=1 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/refloglJQrjE', '--timeout', '7200'] From webhook-mailer at python.org Wed Feb 7 05:09:40 2018 From: webhook-mailer at python.org (INADA Naoki) Date: Wed, 07 Feb 2018 10:09:40 -0000 Subject: [Python-checkins] bpo-32616: Disable computed gotos by default for clang < 5 (GH-5574) Message-ID: https://github.com/python/cpython/commit/2942b909d9a428e6683d90b3436cfa4a81bd5d8a commit: 2942b909d9a428e6683d90b3436cfa4a81bd5d8a branch: 2.7 author: INADA Naoki committer: GitHub date: 2018-02-07T19:09:36+09:00 summary: bpo-32616: Disable computed gotos by default for clang < 5 (GH-5574) files: A Misc/NEWS.d/next/Build/2018-02-07-11-24-38.bpo-32616.o7mFJ3.rst M Python/ceval.c diff --git a/Misc/NEWS.d/next/Build/2018-02-07-11-24-38.bpo-32616.o7mFJ3.rst b/Misc/NEWS.d/next/Build/2018-02-07-11-24-38.bpo-32616.o7mFJ3.rst new file mode 100644 index 000000000000..cdddc2f2d909 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2018-02-07-11-24-38.bpo-32616.o7mFJ3.rst @@ -0,0 +1,2 @@ +Disable computed gotos by default for clang < 5.0. It caused significant +performance regression. diff --git a/Python/ceval.c b/Python/ceval.c index 4e4adc2d63dc..bae158dc1402 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -689,11 +689,19 @@ PyObject * PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) { #ifdef DYNAMIC_EXECUTION_PROFILE - #undef USE_COMPUTED_GOTOS + #undef USE_COMPUTED_GOTOS #endif #ifdef HAVE_COMPUTED_GOTOS #ifndef USE_COMPUTED_GOTOS - #define USE_COMPUTED_GOTOS 1 + #if defined(__clang__) && (__clang_major__ < 5) + /* Computed gotos caused significant performance regression + * with clang < 5.0. + * https://bugs.python.org/issue32616 + */ + #define USE_COMPUTED_GOTOS 0 + #else + #define USE_COMPUTED_GOTOS 1 + #endif #endif #else #if defined(USE_COMPUTED_GOTOS) && USE_COMPUTED_GOTOS From webhook-mailer at python.org Wed Feb 7 11:05:43 2018 From: webhook-mailer at python.org (Mariatta) Date: Wed, 07 Feb 2018 16:05:43 -0000 Subject: [Python-checkins] bpo-32784: Wrong argument name for csv.DictReader in documentation (GH-5575) Message-ID: https://github.com/python/cpython/commit/672fd7d8162f76aff8423fa5c7bfd2b1e91faf57 commit: 672fd7d8162f76aff8423fa5c7bfd2b1e91faf57 branch: 2.7 author: St?phane Wirtel committer: Mariatta date: 2018-02-07T08:05:35-08:00 summary: bpo-32784: Wrong argument name for csv.DictReader in documentation (GH-5575) Use `f` as the name of the first parameter of `csv.DictReader` and `csv.DictWriter` classes. files: M Doc/library/csv.rst diff --git a/Doc/library/csv.rst b/Doc/library/csv.rst index dbef60f0a6b6..fedd370cf1cf 100644 --- a/Doc/library/csv.rst +++ b/Doc/library/csv.rst @@ -165,7 +165,7 @@ The :mod:`csv` module defines the following functions: The :mod:`csv` module defines the following classes: -.. class:: DictReader(csvfile, fieldnames=None, restkey=None, restval=None, \ +.. class:: DictReader(f, fieldnames=None, restkey=None, restval=None, \ dialect='excel', *args, **kwds) Create an object which operates like a regular reader but maps the @@ -174,7 +174,7 @@ The :mod:`csv` module defines the following classes: ` whose elements are associated with the fields of the input data in order. These elements become the keys of the resulting dictionary. If the *fieldnames* parameter is omitted, the values - in the first row of the *csvfile* will be used as the fieldnames. If the + in the first row of the file *f* will be used as the fieldnames. If the row read has more fields than the fieldnames sequence, the remaining data is added as a sequence keyed by the value of *restkey*. If the row read has fewer fields than the fieldnames sequence, the remaining keys take the value @@ -194,14 +194,14 @@ The :mod:`csv` module defines the following classes: Wonderful Spam -.. class:: DictWriter(csvfile, fieldnames, restval='', extrasaction='raise', \ +.. class:: DictWriter(f, fieldnames, restval='', extrasaction='raise', \ dialect='excel', *args, **kwds) Create an object which operates like a regular writer but maps dictionaries onto output rows. The *fieldnames* parameter is a :ref:`sequence ` of keys that identify the order in which values in the dictionary passed to the :meth:`writerow` method are - written to the *csvfile*. The optional *restval* parameter specifies the + written to the file *f*. The optional *restval* parameter specifies the value to be written if the dictionary is missing a key in *fieldnames*. If the dictionary passed to the :meth:`writerow` method contains a key not found in *fieldnames*, the optional *extrasaction* parameter indicates what @@ -213,7 +213,7 @@ The :mod:`csv` module defines the following classes: Note that unlike the :class:`DictReader` class, the *fieldnames* parameter of the :class:`DictWriter` is not optional. Since Python's :class:`dict` objects are not ordered, there is not enough information available to deduce - the order in which the row should be written to the *csvfile*. + the order in which the row should be written to the file *f*. A short usage example:: From solipsis at pitrou.net Thu Feb 8 04:12:55 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 08 Feb 2018 09:12:55 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=9 Message-ID: <20180208091255.1.68AF71C4852A266F@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_fork leaked [0, 0, -2] memory blocks, sum=-2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/refloge3EGi3', '--timeout', '7200'] From webhook-mailer at python.org Thu Feb 8 14:15:02 2018 From: webhook-mailer at python.org (Mariatta) Date: Thu, 08 Feb 2018 19:15:02 -0000 Subject: [Python-checkins] bpo-32802: Fix Travis build (GH-5589) Message-ID: https://github.com/python/cpython/commit/32921f90821ab54ffb757b7e996e5b7a71fac25e commit: 32921f90821ab54ffb757b7e996e5b7a71fac25e branch: master author: St?phane Wirtel committer: Mariatta date: 2018-02-08T11:14:59-08:00 summary: bpo-32802: Fix Travis build (GH-5589) Fix bug in travis configuration where it did not run the tests when a change includes both code and doc changes. files: M .travis.yml diff --git a/.travis.yml b/.travis.yml index d7387e5f9831..98d6b9a97b9b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -97,7 +97,7 @@ before_script: echo "Files changed: " echo $files_changed - if ! echo $files_changed | grep -qvE '(\.rst$)|(^Doc)|(^Misc)' + if ! echo "$files_changed" | grep -qvE '(\.rst$)|(^Doc)|(^Misc)' then echo "Only docs were updated, stopping build process." exit From webhook-mailer at python.org Thu Feb 8 14:42:49 2018 From: webhook-mailer at python.org (Mariatta) Date: Thu, 08 Feb 2018 19:42:49 -0000 Subject: [Python-checkins] bpo-32802: Fix Travis build (GH-5589) (GH-5590) Message-ID: https://github.com/python/cpython/commit/ad3997c592ee9b75fdcd44a0eaa51d748a2e2394 commit: ad3997c592ee9b75fdcd44a0eaa51d748a2e2394 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Mariatta date: 2018-02-08T11:42:46-08:00 summary: bpo-32802: Fix Travis build (GH-5589) (GH-5590) Fix bug in travis configuration where it did not run the tests when a change includes both code and doc changes. (cherry picked from commit 32921f90821ab54ffb757b7e996e5b7a71fac25e) Co-authored-by: St?phane Wirtel files: M .travis.yml diff --git a/.travis.yml b/.travis.yml index d7387e5f9831..98d6b9a97b9b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -97,7 +97,7 @@ before_script: echo "Files changed: " echo $files_changed - if ! echo $files_changed | grep -qvE '(\.rst$)|(^Doc)|(^Misc)' + if ! echo "$files_changed" | grep -qvE '(\.rst$)|(^Doc)|(^Misc)' then echo "Only docs were updated, stopping build process." exit From webhook-mailer at python.org Thu Feb 8 15:01:27 2018 From: webhook-mailer at python.org (Mariatta) Date: Thu, 08 Feb 2018 20:01:27 -0000 Subject: [Python-checkins] bpo-32802: Fix Travis build (GH-5589) (GH-5591) Message-ID: https://github.com/python/cpython/commit/fe92c441519d0c4fc93bb98fc1bb4e225dea44c4 commit: fe92c441519d0c4fc93bb98fc1bb4e225dea44c4 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Mariatta date: 2018-02-08T12:01:23-08:00 summary: bpo-32802: Fix Travis build (GH-5589) (GH-5591) Fix bug in travis configuration where it did not run the tests when a change includes both code and doc changes. (cherry picked from commit 32921f90821ab54ffb757b7e996e5b7a71fac25e) Co-authored-by: St?phane Wirtel files: M .travis.yml diff --git a/.travis.yml b/.travis.yml index d568534929ad..222d6f80be4a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -80,7 +80,7 @@ before_script: echo "Files changed: " echo $files_changed - if ! echo $files_changed | grep -qvE '(\.rst$)|(^Doc)|(^Misc)' + if ! echo "$files_changed" | grep -qvE '(\.rst$)|(^Doc)|(^Misc)' then echo "Only docs were updated, stopping build process." exit From webhook-mailer at python.org Thu Feb 8 19:03:58 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Fri, 09 Feb 2018 00:03:58 -0000 Subject: [Python-checkins] bpo-32585: Add tkinter.ttk.Spinbox. (#5221) Message-ID: https://github.com/python/cpython/commit/a48e78a0b7761dd74f1d03fc69e0f6caa6f02fe6 commit: a48e78a0b7761dd74f1d03fc69e0f6caa6f02fe6 branch: master author: Alan D Moore committer: Serhiy Storchaka date: 2018-02-09T02:03:55+02:00 summary: bpo-32585: Add tkinter.ttk.Spinbox. (#5221) files: A Misc/NEWS.d/next/Library/2018-01-18-13-09-00.bpo-32585.qpeijr.rst M Doc/library/tkinter.ttk.rst M Doc/whatsnew/3.7.rst M Lib/tkinter/test/test_ttk/test_widgets.py M Lib/tkinter/ttk.py M Misc/ACKS diff --git a/Doc/library/tkinter.ttk.rst b/Doc/library/tkinter.ttk.rst index 9c0c4cde3471..5ba31feae144 100644 --- a/Doc/library/tkinter.ttk.rst +++ b/Doc/library/tkinter.ttk.rst @@ -66,13 +66,13 @@ for improved styling effects. Ttk Widgets ----------- -Ttk comes with 17 widgets, eleven of which already existed in tkinter: +Ttk comes with 18 widgets, twelve of which already existed in tkinter: :class:`Button`, :class:`Checkbutton`, :class:`Entry`, :class:`Frame`, :class:`Label`, :class:`LabelFrame`, :class:`Menubutton`, :class:`PanedWindow`, -:class:`Radiobutton`, :class:`Scale` and :class:`Scrollbar`. The other six are -new: :class:`Combobox`, :class:`Notebook`, :class:`Progressbar`, -:class:`Separator`, :class:`Sizegrip` and :class:`Treeview`. And all them are -subclasses of :class:`Widget`. +:class:`Radiobutton`, :class:`Scale`, :class:`Scrollbar`, and :class:`Spinbox`. +The other six are new: :class:`Combobox`, :class:`Notebook`, +:class:`Progressbar`, :class:`Separator`, :class:`Sizegrip` and +:class:`Treeview`. And all them are subclasses of :class:`Widget`. Using the Ttk widgets gives the application an improved look and feel. As discussed above, there are differences in how the styling is coded. @@ -381,6 +381,87 @@ ttk.Combobox Sets the value of the combobox to *value*. +Spinbox +------- +The :class:`ttk.Spinbox` widget is a :class:`ttk.Entry` enhanced with increment +and decrement arrows. It can be used for numbers or lists of string values. +This widget is a subclass of :class:`Entry`. + +Besides the methods inherited from :class:`Widget`: :meth:`Widget.cget`, +:meth:`Widget.configure`, :meth:`Widget.identify`, :meth:`Widget.instate` +and :meth:`Widget.state`, and the following inherited from :class:`Entry`: +:meth:`Entry.bbox`, :meth:`Entry.delete`, :meth:`Entry.icursor`, +:meth:`Entry.index`, :meth:`Entry.insert`, :meth:`Entry.xview`, +it has some other methods, described at :class:`ttk.Spinbox`. + +Options +^^^^^^^ + +This widget accepts the following specific options: + + .. tabularcolumns:: |l|L| + ++----------------------+------------------------------------------------------+ +| Option | Description | ++======================+======================================================+ +| from | Float value. If set, this is the minimum value to | +| | which the decrement button will decrement. Must be | +| | spelled as ``from_`` when used as an argument, since | +| | ``from`` is a Python keyword. | ++----------------------+------------------------------------------------------+ +| to | Float value. If set, this is the maximum value to | +| | which the increment button will increment. | ++----------------------+------------------------------------------------------+ +| increment | Float value. Specifies the amount which the | +| | increment/decrement buttons change the | +| | value. Defaults to 1.0. | ++----------------------+------------------------------------------------------+ +| values | Sequence of string or float values. If specified, | +| | the increment/decrement buttons will cycle through | +| | the items in this sequence rather than incrementing | +| | or decrementing numbers. | +| | | ++----------------------+------------------------------------------------------+ +| wrap | Boolean value. If ``True``, increment and decrement | +| | buttons will cycle from the ``to`` value to the | +| | ``from`` value or the ``from`` value to the ``to`` | +| | value, respectively. | ++----------------------+------------------------------------------------------+ +| format | String value. This specifies the format of numbers | +| | set by the increment/decrement buttons. It must be | +| | in the form "%W.Pf", where W is the padded width of | +| | the value, P is the precision, and '%' and 'f' are | +| | literal. | ++----------------------+------------------------------------------------------+ +| command | Python callable. Will be called with no arguments | +| | whenever either of the increment or decrement buttons| +| | are pressed. | +| | | ++----------------------+------------------------------------------------------+ + + +Virtual events +^^^^^^^^^^^^^^ + +The spinbox widget generates an **<>** virtual event when the +user presses , and a **<>** virtual event when the user +presses . + +ttk.Spinbox +^^^^^^^^^^^^ + +.. class:: Spinbox + + .. method:: get() + + Returns the current value of the spinbox. + + + .. method:: set(value) + + Sets the value of the spinbox to *value*. + + Notebook -------- diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 8d4772f973fb..3b4ba6e41975 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -663,6 +663,12 @@ Added :attr:`sys.flags.dev_mode` flag for the new development mode. Deprecated :func:`sys.set_coroutine_wrapper` and :func:`sys.get_coroutine_wrapper`. + +tkinter +------- + +Added :class:`tkinter.ttk.Spinbox`. + time ---- diff --git a/Lib/tkinter/test/test_ttk/test_widgets.py b/Lib/tkinter/test/test_ttk/test_widgets.py index 08f5fc36fc19..bbc508d35810 100644 --- a/Lib/tkinter/test/test_ttk/test_widgets.py +++ b/Lib/tkinter/test/test_ttk/test_widgets.py @@ -1105,6 +1105,183 @@ def test_traversal(self): 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() + @add_standard_options(StandardTtkOptionsTests) class TreeviewTest(AbstractWidgetTest, unittest.TestCase): @@ -1679,7 +1856,7 @@ def create(self, **kwargs): FrameTest, LabelFrameTest, LabelTest, MenubuttonTest, NotebookTest, PanedWindowTest, ProgressbarTest, RadiobuttonTest, ScaleTest, ScrollbarTest, SeparatorTest, - SizegripTest, TreeviewTest, WidgetTest, + SizegripTest, SpinboxTest, TreeviewTest, WidgetTest, ) if __name__ == "__main__": diff --git a/Lib/tkinter/ttk.py b/Lib/tkinter/ttk.py index 2ab5b59aa9ed..490b502a65f1 100644 --- a/Lib/tkinter/ttk.py +++ b/Lib/tkinter/ttk.py @@ -19,7 +19,7 @@ __all__ = ["Button", "Checkbutton", "Combobox", "Entry", "Frame", "Label", "Labelframe", "LabelFrame", "Menubutton", "Notebook", "Panedwindow", "PanedWindow", "Progressbar", "Radiobutton", "Scale", "Scrollbar", - "Separator", "Sizegrip", "Style", "Treeview", + "Separator", "Sizegrip", "Spinbox", "Style", "Treeview", # Extensions "LabeledScale", "OptionMenu", # functions @@ -1149,6 +1149,33 @@ def __init__(self, master=None, **kw): 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. diff --git a/Misc/ACKS b/Misc/ACKS index c5eadc5ba017..4c8b86ac45d4 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1073,6 +1073,7 @@ The Dragon De Monsyne Bastien Montagne Skip Montanaro Peter Moody +Alan D. Moore Paul Moore Ross Moore Ben Morgan diff --git a/Misc/NEWS.d/next/Library/2018-01-18-13-09-00.bpo-32585.qpeijr.rst b/Misc/NEWS.d/next/Library/2018-01-18-13-09-00.bpo-32585.qpeijr.rst new file mode 100644 index 000000000000..c504e8b1e538 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-01-18-13-09-00.bpo-32585.qpeijr.rst @@ -0,0 +1 @@ +Add Ttk spinbox widget to to tkinter.ttk. Patch by Alan D Moore. From solipsis at pitrou.net Fri Feb 9 04:12:38 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 09 Feb 2018 09:12:38 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=3 Message-ID: <20180209091238.1.A04182734A414644@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 [0, 0, -2] memory blocks, sum=-2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflog5Sgzdh', '--timeout', '7200'] From webhook-mailer at python.org Fri Feb 9 04:59:25 2018 From: webhook-mailer at python.org (INADA Naoki) Date: Fri, 09 Feb 2018 09:59:25 -0000 Subject: [Python-checkins] Cleanup inspect Message-ID: https://github.com/python/cpython/commit/feaefc7f60cd3be7bf4ecc2b73e77d2bfe048403 commit: feaefc7f60cd3be7bf4ecc2b73e77d2bfe048403 branch: master author: Srinivas Reddy Thatiparthy (?????????? ?????? ?????????) committer: INADA Naoki date: 2018-02-09T18:59:19+09:00 summary: Cleanup inspect * use isinstance(..) instead of type(..) * use '.. not in ..' instead of 'not .. in .. ' files: M Lib/inspect.py diff --git a/Lib/inspect.py b/Lib/inspect.py index bc97efe179ca..109efc06b268 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -993,7 +993,7 @@ def getclasstree(classes, unique=False): for c in classes: if c.__bases__: for parent in c.__bases__: - if not parent in children: + if parent not in children: children[parent] = [] if c not in children[parent]: children[parent].append(c) @@ -1538,7 +1538,7 @@ def _shadowed_dict(klass): except KeyError: pass else: - if not (type(class_dict) is types.GetSetDescriptorType and + if not (isinstance(class_dict, types.GetSetDescriptorType) and class_dict.__name__ == "__dict__" and class_dict.__objclass__ is entry): return class_dict @@ -1560,7 +1560,7 @@ def getattr_static(obj, attr, default=_sentinel): klass = type(obj) dict_attr = _shadowed_dict(klass) if (dict_attr is _sentinel or - type(dict_attr) is types.MemberDescriptorType): + isinstance(dict_attr, types.MemberDescriptorType)): instance_result = _check_instance(obj, attr) else: klass = obj @@ -1975,7 +1975,7 @@ def _signature_fromstr(cls, obj, s, skip_bound_arg=True): def parse_name(node): assert isinstance(node, ast.arg) - if node.annotation != None: + if node.annotation is not None: raise ValueError("Annotations are not currently supported") return node.arg From webhook-mailer at python.org Fri Feb 9 06:30:23 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Fri, 09 Feb 2018 11:30:23 -0000 Subject: [Python-checkins] bpo-32775: Fix regular expression warnings in fnmatch. (#5583) Message-ID: https://github.com/python/cpython/commit/23cdbfa744f0ec0e9e7575d378df4cb758691cd3 commit: 23cdbfa744f0ec0e9e7575d378df4cb758691cd3 branch: master author: Serhiy Storchaka committer: GitHub date: 2018-02-09T13:30:19+02:00 summary: bpo-32775: Fix regular expression warnings in fnmatch. (#5583) fnmatch.translate() no longer produces patterns which contain set operations. Sets starting with '[' or containing '--', '&&', '~~' or '||' will be interpreted differently in regular expressions in future versions. Currently they emit warnings. fnmatch.translate() now avoids producing patterns containing such sets by accident. files: A Misc/NEWS.d/next/Library/2018-02-07-19-12-10.bpo-32775.-T77_c.rst M Lib/fnmatch.py M Lib/test/test_fnmatch.py diff --git a/Lib/fnmatch.py b/Lib/fnmatch.py index fd3b5142e348..b98e6413295e 100644 --- a/Lib/fnmatch.py +++ b/Lib/fnmatch.py @@ -97,11 +97,30 @@ def translate(pat): if j >= n: res = res + '\\[' else: - stuff = pat[i:j].replace('\\','\\\\') + stuff = pat[i:j] + if '--' not in stuff: + stuff = stuff.replace('\\', r'\\') + else: + chunks = [] + k = i+2 if pat[i] == '!' else i+1 + while True: + k = pat.find('-', k, j) + if k < 0: + break + chunks.append(pat[i:k]) + i = k+1 + k = k+3 + chunks.append(pat[i:j]) + # Escape backslashes and hyphens for set difference (--). + # Hyphens that create ranges shouldn't be escaped. + stuff = '-'.join(s.replace('\\', r'\\').replace('-', r'\-') + for s in chunks) + # Escape set operations (&&, ~~ and ||). + stuff = re.sub(r'([&~|])', r'\\\1', stuff) i = j+1 if stuff[0] == '!': stuff = '^' + stuff[1:] - elif stuff[0] == '^': + elif stuff[0] in ('^', '['): stuff = '\\' + stuff res = '%s[%s]' % (res, stuff) else: diff --git a/Lib/test/test_fnmatch.py b/Lib/test/test_fnmatch.py index 78245c3ab1a1..55f9f0d3a542 100644 --- a/Lib/test/test_fnmatch.py +++ b/Lib/test/test_fnmatch.py @@ -2,6 +2,7 @@ import unittest import os +import warnings from fnmatch import fnmatch, fnmatchcase, translate, filter @@ -83,6 +84,17 @@ def test_sep(self): check('usr/bin', 'usr\\bin', normsep) check('usr\\bin', 'usr\\bin') + def test_warnings(self): + with warnings.catch_warnings(): + warnings.simplefilter('error', Warning) + check = self.check_match + check('[', '[[]') + check('&', '[a&&b]') + check('|', '[a||b]') + check('~', '[a~~b]') + check(',', '[a-z+--A-Z]') + check('.', '[a-z--/A-Z]') + class TranslateTestCase(unittest.TestCase): diff --git a/Misc/NEWS.d/next/Library/2018-02-07-19-12-10.bpo-32775.-T77_c.rst b/Misc/NEWS.d/next/Library/2018-02-07-19-12-10.bpo-32775.-T77_c.rst new file mode 100644 index 000000000000..ed563c17fdc8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-07-19-12-10.bpo-32775.-T77_c.rst @@ -0,0 +1,5 @@ +:func:`fnmatch.translate()` no longer produces patterns which contain set +operations. Sets starting with '[' or containing '--', '&&', '~~' or '||' +will be interpreted differently in regular expressions in future versions. +Currently they emit warnings. fnmatch.translate() now avoids producing +patterns containing such sets by accident. From webhook-mailer at python.org Fri Feb 9 06:31:22 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Fri, 09 Feb 2018 11:31:22 -0000 Subject: [Python-checkins] Make formatting of some return codes conforming to the general style. (#5587) Message-ID: https://github.com/python/cpython/commit/5bb0005f9ff768ac443924b4bb26c3818ce8dc5a commit: 5bb0005f9ff768ac443924b4bb26c3818ce8dc5a branch: master author: Serhiy Storchaka committer: GitHub date: 2018-02-09T13:31:19+02:00 summary: Make formatting of some return codes conforming to the general style. (#5587) files: M Doc/c-api/init.rst M Doc/c-api/long.rst M Doc/c-api/memory.rst M Doc/extending/newtypes.rst M Doc/faq/extending.rst M Doc/whatsnew/3.3.rst diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst index bae49d5ba812..f2564c441472 100644 --- a/Doc/c-api/init.rst +++ b/Doc/c-api/init.rst @@ -273,8 +273,8 @@ Initializing and finalizing the interpreter the last call to :c:func:`Py_Initialize`. Ideally, this frees all memory allocated by the Python interpreter. This is a no-op when called for a second time (without calling :c:func:`Py_Initialize` again first). Normally the - return value is 0. If there were errors during finalization - (flushing buffered data), -1 is returned. + return value is ``0``. If there were errors during finalization + (flushing buffered data), ``-1`` is returned. This function is provided for a number of reasons. An embedding application might want to restart Python without having to restart the application itself. @@ -1018,7 +1018,7 @@ All of the following functions must be called after :c:func:`Py_Initialize`. .. c:function:: PY_INT64_T PyInterpreterState_GetID(PyInterpreterState *interp) Return the interpreter's unique ID. If there was any error in doing - so then -1 is returned and an error is set. + so then ``-1`` is returned and an error is set. .. versionadded:: 3.7 diff --git a/Doc/c-api/long.rst b/Doc/c-api/long.rst index 4f16b578eb59..5b1f386fb7e5 100644 --- a/Doc/c-api/long.rst +++ b/Doc/c-api/long.rst @@ -137,7 +137,7 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate. Raise :exc:`OverflowError` if the value of *obj* is out of range for a :c:type:`long`. - Returns -1 on error. Use :c:func:`PyErr_Occurred` to disambiguate. + Returns ``-1`` on error. Use :c:func:`PyErr_Occurred` to disambiguate. .. c:function:: long PyLong_AsLongAndOverflow(PyObject *obj, int *overflow) @@ -151,7 +151,7 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate. return ``-1``; otherwise, set *\*overflow* to ``0``. If any other exception occurs set *\*overflow* to ``0`` and return ``-1`` as usual. - Returns -1 on error. Use :c:func:`PyErr_Occurred` to disambiguate. + Returns ``-1`` on error. Use :c:func:`PyErr_Occurred` to disambiguate. .. c:function:: long long PyLong_AsLongLong(PyObject *obj) @@ -166,7 +166,7 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate. Raise :exc:`OverflowError` if the value of *obj* is out of range for a :c:type:`long`. - Returns -1 on error. Use :c:func:`PyErr_Occurred` to disambiguate. + Returns ``-1`` on error. Use :c:func:`PyErr_Occurred` to disambiguate. .. c:function:: long long PyLong_AsLongLongAndOverflow(PyObject *obj, int *overflow) @@ -180,7 +180,7 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate. and return ``-1``; otherwise, set *\*overflow* to ``0``. If any other exception occurs set *\*overflow* to ``0`` and return ``-1`` as usual. - Returns -1 on error. Use :c:func:`PyErr_Occurred` to disambiguate. + Returns ``-1`` on error. Use :c:func:`PyErr_Occurred` to disambiguate. .. versionadded:: 3.2 @@ -197,7 +197,7 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate. Raise :exc:`OverflowError` if the value of *pylong* is out of range for a :c:type:`Py_ssize_t`. - Returns -1 on error. Use :c:func:`PyErr_Occurred` to disambiguate. + Returns ``-1`` on error. Use :c:func:`PyErr_Occurred` to disambiguate. .. c:function:: unsigned long PyLong_AsUnsignedLong(PyObject *pylong) @@ -259,7 +259,7 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate. If the value of *obj* is out of range for an :c:type:`unsigned long`, return the reduction of that value modulo ``ULONG_MAX + 1``. - Returns -1 on error. Use :c:func:`PyErr_Occurred` to disambiguate. + Returns ``-1`` on error. Use :c:func:`PyErr_Occurred` to disambiguate. .. c:function:: unsigned long long PyLong_AsUnsignedLongLongMask(PyObject *obj) @@ -271,7 +271,7 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate. If the value of *obj* is out of range for an :c:type:`unsigned long long`, return the reduction of that value modulo ``PY_ULLONG_MAX + 1``. - Returns -1 on error. Use :c:func:`PyErr_Occurred` to disambiguate. + Returns ``-1`` on error. Use :c:func:`PyErr_Occurred` to disambiguate. .. c:function:: double PyLong_AsDouble(PyObject *pylong) @@ -282,7 +282,7 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate. Raise :exc:`OverflowError` if the value of *pylong* is out of range for a :c:type:`double`. - Returns -1.0 on error. Use :c:func:`PyErr_Occurred` to disambiguate. + Returns ``-1.0`` on error. Use :c:func:`PyErr_Occurred` to disambiguate. .. c:function:: void* PyLong_AsVoidPtr(PyObject *pylong) @@ -292,4 +292,4 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate. is only assured to produce a usable :c:type:`void` pointer for values created with :c:func:`PyLong_FromVoidPtr`. - Returns NULL on error. Use :c:func:`PyErr_Occurred` to disambiguate. + Returns *NULL* on error. Use :c:func:`PyErr_Occurred` to disambiguate. diff --git a/Doc/c-api/memory.rst b/Doc/c-api/memory.rst index 2af0c46d451f..73ae6db498cf 100644 --- a/Doc/c-api/memory.rst +++ b/Doc/c-api/memory.rst @@ -530,7 +530,7 @@ tracemalloc C API Track an allocated memory block in the :mod:`tracemalloc` module. - Return 0 on success, return ``-1`` on error (failed to allocate memory to + Return ``0`` on success, return ``-1`` on error (failed to allocate memory to store the trace). Return ``-2`` if tracemalloc is disabled. If memory block is already tracked, update the existing trace. diff --git a/Doc/extending/newtypes.rst b/Doc/extending/newtypes.rst index 62fbdb87a530..d5eb7fb7c8b8 100644 --- a/Doc/extending/newtypes.rst +++ b/Doc/extending/newtypes.rst @@ -384,8 +384,8 @@ is used to initialize an object after it's created. Unlike the new method, we can't guarantee that the initializer is called. The initializer isn't called when unpickling objects and it can be overridden. Our initializer accepts arguments to provide initial values for our instance. Initializers always accept -positional and keyword arguments. Initializers should return either 0 on -success or -1 on error. +positional and keyword arguments. Initializers should return either ``0`` on +success or ``-1`` on error. Initializers can be called multiple times. Anyone can call the :meth:`__init__` method on our objects. For this reason, we have to be extra careful when diff --git a/Doc/faq/extending.rst b/Doc/faq/extending.rst index 88996e48035b..fd04a83df33c 100644 --- a/Doc/faq/extending.rst +++ b/Doc/faq/extending.rst @@ -62,7 +62,7 @@ How can I execute arbitrary Python statements from C? The highest-level function to do this is :c:func:`PyRun_SimpleString` which takes a single string argument to be executed in the context of the module -``__main__`` and returns 0 for success and -1 when an exception occurred +``__main__`` and returns ``0`` for success and ``-1`` when an exception occurred (including ``SyntaxError``). If you want more control, use :c:func:`PyRun_String`; see the source for :c:func:`PyRun_SimpleString` in ``Python/pythonrun.c``. diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst index b82227d50037..7e5133dbb720 100644 --- a/Doc/whatsnew/3.3.rst +++ b/Doc/whatsnew/3.3.rst @@ -2480,12 +2480,12 @@ Porting C code :c:func:`PyUnicode_FromFormat()`, your code will automatically take advantage of the new unicode representations. -* :c:func:`PyImport_GetMagicNumber` now returns -1 upon failure. +* :c:func:`PyImport_GetMagicNumber` now returns ``-1`` upon failure. * As a negative value for the *level* argument to :func:`__import__` is no longer valid, the same now holds for :c:func:`PyImport_ImportModuleLevel`. This also means that the value of *level* used by - :c:func:`PyImport_ImportModuleEx` is now 0 instead of -1. + :c:func:`PyImport_ImportModuleEx` is now ``0`` instead of ``-1``. Building C extensions From webhook-mailer at python.org Fri Feb 9 06:40:17 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Fri, 09 Feb 2018 11:40:17 -0000 Subject: [Python-checkins] bpo-32585: Add tkinter.ttk.Spinbox. (GH-5221) (GH-5592) Message-ID: https://github.com/python/cpython/commit/105fcbfd6a91abea0ecd71e53651f39ad6f6039b commit: 105fcbfd6a91abea0ecd71e53651f39ad6f6039b branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Serhiy Storchaka date: 2018-02-09T13:40:14+02:00 summary: bpo-32585: Add tkinter.ttk.Spinbox. (GH-5221) (GH-5592) (cherry picked from commit a48e78a0b7761dd74f1d03fc69e0f6caa6f02fe6) Co-authored-by: Alan D Moore files: A Misc/NEWS.d/next/Library/2018-01-18-13-09-00.bpo-32585.qpeijr.rst M Doc/library/tkinter.ttk.rst M Doc/whatsnew/3.7.rst M Lib/tkinter/test/test_ttk/test_widgets.py M Lib/tkinter/ttk.py M Misc/ACKS diff --git a/Doc/library/tkinter.ttk.rst b/Doc/library/tkinter.ttk.rst index debbc81ce1a3..76ecfcce4977 100644 --- a/Doc/library/tkinter.ttk.rst +++ b/Doc/library/tkinter.ttk.rst @@ -66,13 +66,13 @@ for improved styling effects. Ttk Widgets ----------- -Ttk comes with 17 widgets, eleven of which already existed in tkinter: +Ttk comes with 18 widgets, twelve of which already existed in tkinter: :class:`Button`, :class:`Checkbutton`, :class:`Entry`, :class:`Frame`, :class:`Label`, :class:`LabelFrame`, :class:`Menubutton`, :class:`PanedWindow`, -:class:`Radiobutton`, :class:`Scale` and :class:`Scrollbar`. The other six are -new: :class:`Combobox`, :class:`Notebook`, :class:`Progressbar`, -:class:`Separator`, :class:`Sizegrip` and :class:`Treeview`. And all them are -subclasses of :class:`Widget`. +:class:`Radiobutton`, :class:`Scale`, :class:`Scrollbar`, and :class:`Spinbox`. +The other six are new: :class:`Combobox`, :class:`Notebook`, +:class:`Progressbar`, :class:`Separator`, :class:`Sizegrip` and +:class:`Treeview`. And all them are subclasses of :class:`Widget`. Using the Ttk widgets gives the application an improved look and feel. As discussed above, there are differences in how the styling is coded. @@ -381,6 +381,87 @@ ttk.Combobox Sets the value of the combobox to *value*. +Spinbox +------- +The :class:`ttk.Spinbox` widget is a :class:`ttk.Entry` enhanced with increment +and decrement arrows. It can be used for numbers or lists of string values. +This widget is a subclass of :class:`Entry`. + +Besides the methods inherited from :class:`Widget`: :meth:`Widget.cget`, +:meth:`Widget.configure`, :meth:`Widget.identify`, :meth:`Widget.instate` +and :meth:`Widget.state`, and the following inherited from :class:`Entry`: +:meth:`Entry.bbox`, :meth:`Entry.delete`, :meth:`Entry.icursor`, +:meth:`Entry.index`, :meth:`Entry.insert`, :meth:`Entry.xview`, +it has some other methods, described at :class:`ttk.Spinbox`. + +Options +^^^^^^^ + +This widget accepts the following specific options: + + .. tabularcolumns:: |l|L| + ++----------------------+------------------------------------------------------+ +| Option | Description | ++======================+======================================================+ +| from | Float value. If set, this is the minimum value to | +| | which the decrement button will decrement. Must be | +| | spelled as ``from_`` when used as an argument, since | +| | ``from`` is a Python keyword. | ++----------------------+------------------------------------------------------+ +| to | Float value. If set, this is the maximum value to | +| | which the increment button will increment. | ++----------------------+------------------------------------------------------+ +| increment | Float value. Specifies the amount which the | +| | increment/decrement buttons change the | +| | value. Defaults to 1.0. | ++----------------------+------------------------------------------------------+ +| values | Sequence of string or float values. If specified, | +| | the increment/decrement buttons will cycle through | +| | the items in this sequence rather than incrementing | +| | or decrementing numbers. | +| | | ++----------------------+------------------------------------------------------+ +| wrap | Boolean value. If ``True``, increment and decrement | +| | buttons will cycle from the ``to`` value to the | +| | ``from`` value or the ``from`` value to the ``to`` | +| | value, respectively. | ++----------------------+------------------------------------------------------+ +| format | String value. This specifies the format of numbers | +| | set by the increment/decrement buttons. It must be | +| | in the form "%W.Pf", where W is the padded width of | +| | the value, P is the precision, and '%' and 'f' are | +| | literal. | ++----------------------+------------------------------------------------------+ +| command | Python callable. Will be called with no arguments | +| | whenever either of the increment or decrement buttons| +| | are pressed. | +| | | ++----------------------+------------------------------------------------------+ + + +Virtual events +^^^^^^^^^^^^^^ + +The spinbox widget generates an **<>** virtual event when the +user presses , and a **<>** virtual event when the user +presses . + +ttk.Spinbox +^^^^^^^^^^^^ + +.. class:: Spinbox + + .. method:: get() + + Returns the current value of the spinbox. + + + .. method:: set(value) + + Sets the value of the spinbox to *value*. + + Notebook -------- diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 7b17c62e2562..fcd5188e7be2 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -655,6 +655,12 @@ Added :attr:`sys.flags.dev_mode` flag for the new development mode. Deprecated :func:`sys.set_coroutine_wrapper` and :func:`sys.get_coroutine_wrapper`. + +tkinter +------- + +Added :class:`tkinter.ttk.Spinbox`. + time ---- diff --git a/Lib/tkinter/test/test_ttk/test_widgets.py b/Lib/tkinter/test/test_ttk/test_widgets.py index ab0db2878e13..5325e36b5212 100644 --- a/Lib/tkinter/test/test_ttk/test_widgets.py +++ b/Lib/tkinter/test/test_ttk/test_widgets.py @@ -1105,6 +1105,183 @@ def test_traversal(self): 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() + @add_standard_options(StandardTtkOptionsTests) class TreeviewTest(AbstractWidgetTest, unittest.TestCase): @@ -1700,7 +1877,7 @@ def create(self, **kwargs): FrameTest, LabelFrameTest, LabelTest, MenubuttonTest, NotebookTest, PanedWindowTest, ProgressbarTest, RadiobuttonTest, ScaleTest, ScrollbarTest, SeparatorTest, - SizegripTest, TreeviewTest, WidgetTest, + SizegripTest, SpinboxTest, TreeviewTest, WidgetTest, ) if __name__ == "__main__": diff --git a/Lib/tkinter/ttk.py b/Lib/tkinter/ttk.py index e6c90cef7bb1..c1651159b703 100644 --- a/Lib/tkinter/ttk.py +++ b/Lib/tkinter/ttk.py @@ -19,7 +19,7 @@ __all__ = ["Button", "Checkbutton", "Combobox", "Entry", "Frame", "Label", "Labelframe", "LabelFrame", "Menubutton", "Notebook", "Panedwindow", "PanedWindow", "Progressbar", "Radiobutton", "Scale", "Scrollbar", - "Separator", "Sizegrip", "Style", "Treeview", + "Separator", "Sizegrip", "Spinbox", "Style", "Treeview", # Extensions "LabeledScale", "OptionMenu", # functions @@ -1151,6 +1151,33 @@ def __init__(self, master=None, **kw): 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. diff --git a/Misc/ACKS b/Misc/ACKS index c5eadc5ba017..4c8b86ac45d4 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1073,6 +1073,7 @@ The Dragon De Monsyne Bastien Montagne Skip Montanaro Peter Moody +Alan D. Moore Paul Moore Ross Moore Ben Morgan diff --git a/Misc/NEWS.d/next/Library/2018-01-18-13-09-00.bpo-32585.qpeijr.rst b/Misc/NEWS.d/next/Library/2018-01-18-13-09-00.bpo-32585.qpeijr.rst new file mode 100644 index 000000000000..c504e8b1e538 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-01-18-13-09-00.bpo-32585.qpeijr.rst @@ -0,0 +1 @@ +Add Ttk spinbox widget to to tkinter.ttk. Patch by Alan D Moore. From webhook-mailer at python.org Fri Feb 9 06:56:55 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Fri, 09 Feb 2018 11:56:55 -0000 Subject: [Python-checkins] bpo-32775: Fix regular expression warnings in fnmatch. (GH-5583) (GH-5596) Message-ID: https://github.com/python/cpython/commit/0e361730b0954f7560640dd932f00f507e328c45 commit: 0e361730b0954f7560640dd932f00f507e328c45 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Serhiy Storchaka date: 2018-02-09T13:56:50+02:00 summary: bpo-32775: Fix regular expression warnings in fnmatch. (GH-5583) (GH-5596) fnmatch.translate() no longer produces patterns which contain set operations. Sets starting with '[' or containing '--', '&&', '~~' or '||' will be interpreted differently in regular expressions in future versions. Currently they emit warnings. fnmatch.translate() now avoids producing patterns containing such sets by accident. (cherry picked from commit 23cdbfa744f0ec0e9e7575d378df4cb758691cd3) Co-authored-by: Serhiy Storchaka files: A Misc/NEWS.d/next/Library/2018-02-07-19-12-10.bpo-32775.-T77_c.rst M Lib/fnmatch.py M Lib/test/test_fnmatch.py diff --git a/Lib/fnmatch.py b/Lib/fnmatch.py index fd3b5142e348..b98e6413295e 100644 --- a/Lib/fnmatch.py +++ b/Lib/fnmatch.py @@ -97,11 +97,30 @@ def translate(pat): if j >= n: res = res + '\\[' else: - stuff = pat[i:j].replace('\\','\\\\') + stuff = pat[i:j] + if '--' not in stuff: + stuff = stuff.replace('\\', r'\\') + else: + chunks = [] + k = i+2 if pat[i] == '!' else i+1 + while True: + k = pat.find('-', k, j) + if k < 0: + break + chunks.append(pat[i:k]) + i = k+1 + k = k+3 + chunks.append(pat[i:j]) + # Escape backslashes and hyphens for set difference (--). + # Hyphens that create ranges shouldn't be escaped. + stuff = '-'.join(s.replace('\\', r'\\').replace('-', r'\-') + for s in chunks) + # Escape set operations (&&, ~~ and ||). + stuff = re.sub(r'([&~|])', r'\\\1', stuff) i = j+1 if stuff[0] == '!': stuff = '^' + stuff[1:] - elif stuff[0] == '^': + elif stuff[0] in ('^', '['): stuff = '\\' + stuff res = '%s[%s]' % (res, stuff) else: diff --git a/Lib/test/test_fnmatch.py b/Lib/test/test_fnmatch.py index 78245c3ab1a1..55f9f0d3a542 100644 --- a/Lib/test/test_fnmatch.py +++ b/Lib/test/test_fnmatch.py @@ -2,6 +2,7 @@ import unittest import os +import warnings from fnmatch import fnmatch, fnmatchcase, translate, filter @@ -83,6 +84,17 @@ def test_sep(self): check('usr/bin', 'usr\\bin', normsep) check('usr\\bin', 'usr\\bin') + def test_warnings(self): + with warnings.catch_warnings(): + warnings.simplefilter('error', Warning) + check = self.check_match + check('[', '[[]') + check('&', '[a&&b]') + check('|', '[a||b]') + check('~', '[a~~b]') + check(',', '[a-z+--A-Z]') + check('.', '[a-z--/A-Z]') + class TranslateTestCase(unittest.TestCase): diff --git a/Misc/NEWS.d/next/Library/2018-02-07-19-12-10.bpo-32775.-T77_c.rst b/Misc/NEWS.d/next/Library/2018-02-07-19-12-10.bpo-32775.-T77_c.rst new file mode 100644 index 000000000000..ed563c17fdc8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-07-19-12-10.bpo-32775.-T77_c.rst @@ -0,0 +1,5 @@ +:func:`fnmatch.translate()` no longer produces patterns which contain set +operations. Sets starting with '[' or containing '--', '&&', '~~' or '||' +will be interpreted differently in regular expressions in future versions. +Currently they emit warnings. fnmatch.translate() now avoids producing +patterns containing such sets by accident. From webhook-mailer at python.org Fri Feb 9 07:08:07 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Fri, 09 Feb 2018 12:08:07 -0000 Subject: [Python-checkins] Make formatting of some return codes conforming to the general style. (GH-5587) (GH-5597) Message-ID: https://github.com/python/cpython/commit/3a047a781a82e0a55c5dae1758e91f1f1ca76026 commit: 3a047a781a82e0a55c5dae1758e91f1f1ca76026 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Serhiy Storchaka date: 2018-02-09T14:08:04+02:00 summary: Make formatting of some return codes conforming to the general style. (GH-5587) (GH-5597) (cherry picked from commit 5bb0005f9ff768ac443924b4bb26c3818ce8dc5a) Co-authored-by: Serhiy Storchaka files: M Doc/c-api/init.rst M Doc/c-api/long.rst M Doc/c-api/memory.rst M Doc/extending/newtypes.rst M Doc/faq/extending.rst M Doc/whatsnew/3.3.rst diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst index bae49d5ba812..f2564c441472 100644 --- a/Doc/c-api/init.rst +++ b/Doc/c-api/init.rst @@ -273,8 +273,8 @@ Initializing and finalizing the interpreter the last call to :c:func:`Py_Initialize`. Ideally, this frees all memory allocated by the Python interpreter. This is a no-op when called for a second time (without calling :c:func:`Py_Initialize` again first). Normally the - return value is 0. If there were errors during finalization - (flushing buffered data), -1 is returned. + return value is ``0``. If there were errors during finalization + (flushing buffered data), ``-1`` is returned. This function is provided for a number of reasons. An embedding application might want to restart Python without having to restart the application itself. @@ -1018,7 +1018,7 @@ All of the following functions must be called after :c:func:`Py_Initialize`. .. c:function:: PY_INT64_T PyInterpreterState_GetID(PyInterpreterState *interp) Return the interpreter's unique ID. If there was any error in doing - so then -1 is returned and an error is set. + so then ``-1`` is returned and an error is set. .. versionadded:: 3.7 diff --git a/Doc/c-api/long.rst b/Doc/c-api/long.rst index 4f16b578eb59..5b1f386fb7e5 100644 --- a/Doc/c-api/long.rst +++ b/Doc/c-api/long.rst @@ -137,7 +137,7 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate. Raise :exc:`OverflowError` if the value of *obj* is out of range for a :c:type:`long`. - Returns -1 on error. Use :c:func:`PyErr_Occurred` to disambiguate. + Returns ``-1`` on error. Use :c:func:`PyErr_Occurred` to disambiguate. .. c:function:: long PyLong_AsLongAndOverflow(PyObject *obj, int *overflow) @@ -151,7 +151,7 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate. return ``-1``; otherwise, set *\*overflow* to ``0``. If any other exception occurs set *\*overflow* to ``0`` and return ``-1`` as usual. - Returns -1 on error. Use :c:func:`PyErr_Occurred` to disambiguate. + Returns ``-1`` on error. Use :c:func:`PyErr_Occurred` to disambiguate. .. c:function:: long long PyLong_AsLongLong(PyObject *obj) @@ -166,7 +166,7 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate. Raise :exc:`OverflowError` if the value of *obj* is out of range for a :c:type:`long`. - Returns -1 on error. Use :c:func:`PyErr_Occurred` to disambiguate. + Returns ``-1`` on error. Use :c:func:`PyErr_Occurred` to disambiguate. .. c:function:: long long PyLong_AsLongLongAndOverflow(PyObject *obj, int *overflow) @@ -180,7 +180,7 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate. and return ``-1``; otherwise, set *\*overflow* to ``0``. If any other exception occurs set *\*overflow* to ``0`` and return ``-1`` as usual. - Returns -1 on error. Use :c:func:`PyErr_Occurred` to disambiguate. + Returns ``-1`` on error. Use :c:func:`PyErr_Occurred` to disambiguate. .. versionadded:: 3.2 @@ -197,7 +197,7 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate. Raise :exc:`OverflowError` if the value of *pylong* is out of range for a :c:type:`Py_ssize_t`. - Returns -1 on error. Use :c:func:`PyErr_Occurred` to disambiguate. + Returns ``-1`` on error. Use :c:func:`PyErr_Occurred` to disambiguate. .. c:function:: unsigned long PyLong_AsUnsignedLong(PyObject *pylong) @@ -259,7 +259,7 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate. If the value of *obj* is out of range for an :c:type:`unsigned long`, return the reduction of that value modulo ``ULONG_MAX + 1``. - Returns -1 on error. Use :c:func:`PyErr_Occurred` to disambiguate. + Returns ``-1`` on error. Use :c:func:`PyErr_Occurred` to disambiguate. .. c:function:: unsigned long long PyLong_AsUnsignedLongLongMask(PyObject *obj) @@ -271,7 +271,7 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate. If the value of *obj* is out of range for an :c:type:`unsigned long long`, return the reduction of that value modulo ``PY_ULLONG_MAX + 1``. - Returns -1 on error. Use :c:func:`PyErr_Occurred` to disambiguate. + Returns ``-1`` on error. Use :c:func:`PyErr_Occurred` to disambiguate. .. c:function:: double PyLong_AsDouble(PyObject *pylong) @@ -282,7 +282,7 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate. Raise :exc:`OverflowError` if the value of *pylong* is out of range for a :c:type:`double`. - Returns -1.0 on error. Use :c:func:`PyErr_Occurred` to disambiguate. + Returns ``-1.0`` on error. Use :c:func:`PyErr_Occurred` to disambiguate. .. c:function:: void* PyLong_AsVoidPtr(PyObject *pylong) @@ -292,4 +292,4 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate. is only assured to produce a usable :c:type:`void` pointer for values created with :c:func:`PyLong_FromVoidPtr`. - Returns NULL on error. Use :c:func:`PyErr_Occurred` to disambiguate. + Returns *NULL* on error. Use :c:func:`PyErr_Occurred` to disambiguate. diff --git a/Doc/c-api/memory.rst b/Doc/c-api/memory.rst index 2af0c46d451f..73ae6db498cf 100644 --- a/Doc/c-api/memory.rst +++ b/Doc/c-api/memory.rst @@ -530,7 +530,7 @@ tracemalloc C API Track an allocated memory block in the :mod:`tracemalloc` module. - Return 0 on success, return ``-1`` on error (failed to allocate memory to + Return ``0`` on success, return ``-1`` on error (failed to allocate memory to store the trace). Return ``-2`` if tracemalloc is disabled. If memory block is already tracked, update the existing trace. diff --git a/Doc/extending/newtypes.rst b/Doc/extending/newtypes.rst index 62fbdb87a530..d5eb7fb7c8b8 100644 --- a/Doc/extending/newtypes.rst +++ b/Doc/extending/newtypes.rst @@ -384,8 +384,8 @@ is used to initialize an object after it's created. Unlike the new method, we can't guarantee that the initializer is called. The initializer isn't called when unpickling objects and it can be overridden. Our initializer accepts arguments to provide initial values for our instance. Initializers always accept -positional and keyword arguments. Initializers should return either 0 on -success or -1 on error. +positional and keyword arguments. Initializers should return either ``0`` on +success or ``-1`` on error. Initializers can be called multiple times. Anyone can call the :meth:`__init__` method on our objects. For this reason, we have to be extra careful when diff --git a/Doc/faq/extending.rst b/Doc/faq/extending.rst index 88996e48035b..fd04a83df33c 100644 --- a/Doc/faq/extending.rst +++ b/Doc/faq/extending.rst @@ -62,7 +62,7 @@ How can I execute arbitrary Python statements from C? The highest-level function to do this is :c:func:`PyRun_SimpleString` which takes a single string argument to be executed in the context of the module -``__main__`` and returns 0 for success and -1 when an exception occurred +``__main__`` and returns ``0`` for success and ``-1`` when an exception occurred (including ``SyntaxError``). If you want more control, use :c:func:`PyRun_String`; see the source for :c:func:`PyRun_SimpleString` in ``Python/pythonrun.c``. diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst index b82227d50037..7e5133dbb720 100644 --- a/Doc/whatsnew/3.3.rst +++ b/Doc/whatsnew/3.3.rst @@ -2480,12 +2480,12 @@ Porting C code :c:func:`PyUnicode_FromFormat()`, your code will automatically take advantage of the new unicode representations. -* :c:func:`PyImport_GetMagicNumber` now returns -1 upon failure. +* :c:func:`PyImport_GetMagicNumber` now returns ``-1`` upon failure. * As a negative value for the *level* argument to :func:`__import__` is no longer valid, the same now holds for :c:func:`PyImport_ImportModuleLevel`. This also means that the value of *level* used by - :c:func:`PyImport_ImportModuleEx` is now 0 instead of -1. + :c:func:`PyImport_ImportModuleEx` is now ``0`` instead of ``-1``. Building C extensions From webhook-mailer at python.org Fri Feb 9 07:48:34 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Fri, 09 Feb 2018 12:48:34 -0000 Subject: [Python-checkins] [3.6] Make formatting of some return codes conforming to the general style. (GH-5587). (GH-5598) Message-ID: https://github.com/python/cpython/commit/3d4a174c0e3ca793d6bc827acbfd1e920c01a8d1 commit: 3d4a174c0e3ca793d6bc827acbfd1e920c01a8d1 branch: 3.6 author: Serhiy Storchaka committer: GitHub date: 2018-02-09T14:48:31+02:00 summary: [3.6] Make formatting of some return codes conforming to the general style. (GH-5587). (GH-5598) (cherry picked from commit 5bb0005f9ff768ac443924b4bb26c3818ce8dc5a) Co-authored-by: Serhiy Storchaka files: M Doc/c-api/init.rst M Doc/c-api/long.rst M Doc/extending/newtypes.rst M Doc/faq/extending.rst M Doc/whatsnew/3.3.rst diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst index c8d429de51bb..f60147621141 100644 --- a/Doc/c-api/init.rst +++ b/Doc/c-api/init.rst @@ -64,8 +64,8 @@ Initializing and finalizing the interpreter the last call to :c:func:`Py_Initialize`. Ideally, this frees all memory allocated by the Python interpreter. This is a no-op when called for a second time (without calling :c:func:`Py_Initialize` again first). Normally the - return value is 0. If there were errors during finalization - (flushing buffered data), -1 is returned. + return value is ``0``. If there were errors during finalization + (flushing buffered data), ``-1`` is returned. This function is provided for a number of reasons. An embedding application might want to restart Python without having to restart the application itself. diff --git a/Doc/c-api/long.rst b/Doc/c-api/long.rst index 4f16b578eb59..5b1f386fb7e5 100644 --- a/Doc/c-api/long.rst +++ b/Doc/c-api/long.rst @@ -137,7 +137,7 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate. Raise :exc:`OverflowError` if the value of *obj* is out of range for a :c:type:`long`. - Returns -1 on error. Use :c:func:`PyErr_Occurred` to disambiguate. + Returns ``-1`` on error. Use :c:func:`PyErr_Occurred` to disambiguate. .. c:function:: long PyLong_AsLongAndOverflow(PyObject *obj, int *overflow) @@ -151,7 +151,7 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate. return ``-1``; otherwise, set *\*overflow* to ``0``. If any other exception occurs set *\*overflow* to ``0`` and return ``-1`` as usual. - Returns -1 on error. Use :c:func:`PyErr_Occurred` to disambiguate. + Returns ``-1`` on error. Use :c:func:`PyErr_Occurred` to disambiguate. .. c:function:: long long PyLong_AsLongLong(PyObject *obj) @@ -166,7 +166,7 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate. Raise :exc:`OverflowError` if the value of *obj* is out of range for a :c:type:`long`. - Returns -1 on error. Use :c:func:`PyErr_Occurred` to disambiguate. + Returns ``-1`` on error. Use :c:func:`PyErr_Occurred` to disambiguate. .. c:function:: long long PyLong_AsLongLongAndOverflow(PyObject *obj, int *overflow) @@ -180,7 +180,7 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate. and return ``-1``; otherwise, set *\*overflow* to ``0``. If any other exception occurs set *\*overflow* to ``0`` and return ``-1`` as usual. - Returns -1 on error. Use :c:func:`PyErr_Occurred` to disambiguate. + Returns ``-1`` on error. Use :c:func:`PyErr_Occurred` to disambiguate. .. versionadded:: 3.2 @@ -197,7 +197,7 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate. Raise :exc:`OverflowError` if the value of *pylong* is out of range for a :c:type:`Py_ssize_t`. - Returns -1 on error. Use :c:func:`PyErr_Occurred` to disambiguate. + Returns ``-1`` on error. Use :c:func:`PyErr_Occurred` to disambiguate. .. c:function:: unsigned long PyLong_AsUnsignedLong(PyObject *pylong) @@ -259,7 +259,7 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate. If the value of *obj* is out of range for an :c:type:`unsigned long`, return the reduction of that value modulo ``ULONG_MAX + 1``. - Returns -1 on error. Use :c:func:`PyErr_Occurred` to disambiguate. + Returns ``-1`` on error. Use :c:func:`PyErr_Occurred` to disambiguate. .. c:function:: unsigned long long PyLong_AsUnsignedLongLongMask(PyObject *obj) @@ -271,7 +271,7 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate. If the value of *obj* is out of range for an :c:type:`unsigned long long`, return the reduction of that value modulo ``PY_ULLONG_MAX + 1``. - Returns -1 on error. Use :c:func:`PyErr_Occurred` to disambiguate. + Returns ``-1`` on error. Use :c:func:`PyErr_Occurred` to disambiguate. .. c:function:: double PyLong_AsDouble(PyObject *pylong) @@ -282,7 +282,7 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate. Raise :exc:`OverflowError` if the value of *pylong* is out of range for a :c:type:`double`. - Returns -1.0 on error. Use :c:func:`PyErr_Occurred` to disambiguate. + Returns ``-1.0`` on error. Use :c:func:`PyErr_Occurred` to disambiguate. .. c:function:: void* PyLong_AsVoidPtr(PyObject *pylong) @@ -292,4 +292,4 @@ distinguished from a number. Use :c:func:`PyErr_Occurred` to disambiguate. is only assured to produce a usable :c:type:`void` pointer for values created with :c:func:`PyLong_FromVoidPtr`. - Returns NULL on error. Use :c:func:`PyErr_Occurred` to disambiguate. + Returns *NULL* on error. Use :c:func:`PyErr_Occurred` to disambiguate. diff --git a/Doc/extending/newtypes.rst b/Doc/extending/newtypes.rst index d28d224c2930..edba57e4a3e8 100644 --- a/Doc/extending/newtypes.rst +++ b/Doc/extending/newtypes.rst @@ -391,8 +391,8 @@ is used to initialize an object after it's created. Unlike the new method, we can't guarantee that the initializer is called. The initializer isn't called when unpickling objects and it can be overridden. Our initializer accepts arguments to provide initial values for our instance. Initializers always accept -positional and keyword arguments. Initializers should return either 0 on -success or -1 on error. +positional and keyword arguments. Initializers should return either ``0`` on +success or ``-1`` on error. Initializers can be called multiple times. Anyone can call the :meth:`__init__` method on our objects. For this reason, we have to be extra careful when diff --git a/Doc/faq/extending.rst b/Doc/faq/extending.rst index 88996e48035b..fd04a83df33c 100644 --- a/Doc/faq/extending.rst +++ b/Doc/faq/extending.rst @@ -62,7 +62,7 @@ How can I execute arbitrary Python statements from C? The highest-level function to do this is :c:func:`PyRun_SimpleString` which takes a single string argument to be executed in the context of the module -``__main__`` and returns 0 for success and -1 when an exception occurred +``__main__`` and returns ``0`` for success and ``-1`` when an exception occurred (including ``SyntaxError``). If you want more control, use :c:func:`PyRun_String`; see the source for :c:func:`PyRun_SimpleString` in ``Python/pythonrun.c``. diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst index 93b297cf6532..b091507a19d5 100644 --- a/Doc/whatsnew/3.3.rst +++ b/Doc/whatsnew/3.3.rst @@ -2480,12 +2480,12 @@ Porting C code :c:func:`PyUnicode_FromFormat()`, your code will automatically take advantage of the new unicode representations. -* :c:func:`PyImport_GetMagicNumber` now returns -1 upon failure. +* :c:func:`PyImport_GetMagicNumber` now returns ``-1`` upon failure. * As a negative value for the *level* argument to :func:`__import__` is no longer valid, the same now holds for :c:func:`PyImport_ImportModuleLevel`. This also means that the value of *level* used by - :c:func:`PyImport_ImportModuleEx` is now 0 instead of -1. + :c:func:`PyImport_ImportModuleEx` is now ``0`` instead of ``-1``. Building C extensions From webhook-mailer at python.org Fri Feb 9 10:31:31 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Fri, 09 Feb 2018 15:31:31 -0000 Subject: [Python-checkins] Fix some warnings produced by different compilers. (#5593) Message-ID: https://github.com/python/cpython/commit/bfe4fd5f2e96e72eecb5b8a0c7df0ac1689f3b7e commit: bfe4fd5f2e96e72eecb5b8a0c7df0ac1689f3b7e branch: master author: Serhiy Storchaka committer: GitHub date: 2018-02-09T17:31:26+02:00 summary: Fix some warnings produced by different compilers. (#5593) files: M Modules/_decimal/libmpdec/mpdecimal.c M Modules/socketmodule.c M Modules/timemodule.c M Python/context.c M Python/hamt.c M Python/pyhash.c diff --git a/Modules/_decimal/libmpdec/mpdecimal.c b/Modules/_decimal/libmpdec/mpdecimal.c index 328ab9224628..bfa8bb343e60 100644 --- a/Modules/_decimal/libmpdec/mpdecimal.c +++ b/Modules/_decimal/libmpdec/mpdecimal.c @@ -53,6 +53,12 @@ #endif +/* Disable warning that is part of -Wextra since gcc 7.0. */ +#if defined(__GNUC__) && !defined(__INTEL_COMPILER) && __GNUC__ >= 7 + #pragma GCC diagnostic ignored "-Wimplicit-fallthrough" +#endif + + #if defined(_MSC_VER) #define ALWAYS_INLINE __forceinline #elif defined(LEGACY_COMPILER) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 13936aa1558e..23061bec5b7e 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -4867,7 +4867,9 @@ sock_initobj(PyObject *self, PyObject *args, PyObject *kwds) if (type == -1) { int tmp; socklen_t slen = sizeof(tmp); - if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &tmp, &slen) == 0) { + if (getsockopt(fd, SOL_SOCKET, SO_TYPE, + (void *)&tmp, &slen) == 0) + { type = tmp; } else { #ifdef MS_WINDOWS @@ -4885,7 +4887,9 @@ sock_initobj(PyObject *self, PyObject *args, PyObject *kwds) if (proto == -1) { int tmp; socklen_t slen = sizeof(tmp); - if (getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, &tmp, &slen) == 0) { + if (getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, + (void *)&tmp, &slen) == 0) + { proto = tmp; } else { #ifdef MS_WINDOWS diff --git a/Modules/timemodule.c b/Modules/timemodule.c index b17ab5ae824b..998216cc8fdb 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -1192,11 +1192,13 @@ _PyTime_GetProcessTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) if (freq != -1) { /* check that _PyTime_MulDiv(t, SEC_TO_NS, ticks_per_second) cannot overflow below */ +#if LONG_MAX > _PyTime_MAX / SEC_TO_NS if ((_PyTime_t)freq > _PyTime_MAX / SEC_TO_NS) { PyErr_SetString(PyExc_OverflowError, "_SC_CLK_TCK is too large"); return -1; } +#endif ticks_per_second = freq; } diff --git a/Python/context.c b/Python/context.c index 2034a2041215..b727748ee739 100644 --- a/Python/context.c +++ b/Python/context.c @@ -8,7 +8,7 @@ #define CONTEXT_FREELIST_MAXLEN 255 static PyContext *ctx_freelist = NULL; -static Py_ssize_t ctx_freelist_len = 0; +static int ctx_freelist_len = 0; #include "clinic/context.c.h" @@ -1177,7 +1177,7 @@ get_token_missing(void) int PyContext_ClearFreeList(void) { - Py_ssize_t size = ctx_freelist_len; + int size = ctx_freelist_len; while (ctx_freelist_len) { PyContext *ctx = ctx_freelist; ctx_freelist = (PyContext *)ctx->ctx_weakreflist; diff --git a/Python/hamt.c b/Python/hamt.c index c9acbbcc5acc..e54d3a4c55f9 100644 --- a/Python/hamt.c +++ b/Python/hamt.c @@ -729,7 +729,7 @@ hamt_node_bitmap_assoc(PyHamtNode_Bitmap *self, uint32_t key_idx = 2 * idx; uint32_t val_idx = key_idx + 1; - assert(val_idx < Py_SIZE(self)); + assert(val_idx < (size_t)Py_SIZE(self)); PyObject *key_or_null = self->b_array[key_idx]; PyObject *val_or_node = self->b_array[val_idx]; @@ -1123,7 +1123,7 @@ hamt_node_bitmap_find(PyHamtNode_Bitmap *self, key_idx = idx * 2; val_idx = key_idx + 1; - assert(val_idx < Py_SIZE(self)); + assert(val_idx < (size_t)Py_SIZE(self)); key_or_null = self->b_array[key_idx]; val_or_node = self->b_array[val_idx]; diff --git a/Python/pyhash.c b/Python/pyhash.c index a0850d066b31..9e6e594f441a 100644 --- a/Python/pyhash.c +++ b/Python/pyhash.c @@ -17,7 +17,7 @@ extern "C" { #endif -_Py_HashSecret_t _Py_HashSecret = {0}; +_Py_HashSecret_t _Py_HashSecret = {{0}}; #if Py_HASH_ALGORITHM == Py_HASH_EXTERNAL extern PyHash_FuncDef PyHash_Func; From webhook-mailer at python.org Fri Feb 9 10:56:37 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Fri, 09 Feb 2018 15:56:37 -0000 Subject: [Python-checkins] Fix some warnings produced by different compilers. (GH-5593) (GH-5600) Message-ID: https://github.com/python/cpython/commit/7df80492fc91cb5f344ef53a1ccce9a5bd3f4855 commit: 7df80492fc91cb5f344ef53a1ccce9a5bd3f4855 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Serhiy Storchaka date: 2018-02-09T17:56:34+02:00 summary: Fix some warnings produced by different compilers. (GH-5593) (GH-5600) (cherry picked from commit bfe4fd5f2e96e72eecb5b8a0c7df0ac1689f3b7e) Co-authored-by: Serhiy Storchaka files: M Modules/_decimal/libmpdec/mpdecimal.c M Modules/socketmodule.c M Modules/timemodule.c M Python/context.c M Python/hamt.c M Python/pyhash.c diff --git a/Modules/_decimal/libmpdec/mpdecimal.c b/Modules/_decimal/libmpdec/mpdecimal.c index 328ab9224628..bfa8bb343e60 100644 --- a/Modules/_decimal/libmpdec/mpdecimal.c +++ b/Modules/_decimal/libmpdec/mpdecimal.c @@ -53,6 +53,12 @@ #endif +/* Disable warning that is part of -Wextra since gcc 7.0. */ +#if defined(__GNUC__) && !defined(__INTEL_COMPILER) && __GNUC__ >= 7 + #pragma GCC diagnostic ignored "-Wimplicit-fallthrough" +#endif + + #if defined(_MSC_VER) #define ALWAYS_INLINE __forceinline #elif defined(LEGACY_COMPILER) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 474c1c94a0c8..7fc3d877bba5 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -4867,7 +4867,9 @@ sock_initobj(PyObject *self, PyObject *args, PyObject *kwds) if (type == -1) { int tmp; socklen_t slen = sizeof(tmp); - if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &tmp, &slen) == 0) { + if (getsockopt(fd, SOL_SOCKET, SO_TYPE, + (void *)&tmp, &slen) == 0) + { type = tmp; } else { #ifdef MS_WINDOWS @@ -4885,7 +4887,9 @@ sock_initobj(PyObject *self, PyObject *args, PyObject *kwds) if (proto == -1) { int tmp; socklen_t slen = sizeof(tmp); - if (getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, &tmp, &slen) == 0) { + if (getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, + (void *)&tmp, &slen) == 0) + { proto = tmp; } else { #ifdef MS_WINDOWS diff --git a/Modules/timemodule.c b/Modules/timemodule.c index b17ab5ae824b..998216cc8fdb 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -1192,11 +1192,13 @@ _PyTime_GetProcessTimeWithInfo(_PyTime_t *tp, _Py_clock_info_t *info) if (freq != -1) { /* check that _PyTime_MulDiv(t, SEC_TO_NS, ticks_per_second) cannot overflow below */ +#if LONG_MAX > _PyTime_MAX / SEC_TO_NS if ((_PyTime_t)freq > _PyTime_MAX / SEC_TO_NS) { PyErr_SetString(PyExc_OverflowError, "_SC_CLK_TCK is too large"); return -1; } +#endif ticks_per_second = freq; } diff --git a/Python/context.c b/Python/context.c index 2034a2041215..b727748ee739 100644 --- a/Python/context.c +++ b/Python/context.c @@ -8,7 +8,7 @@ #define CONTEXT_FREELIST_MAXLEN 255 static PyContext *ctx_freelist = NULL; -static Py_ssize_t ctx_freelist_len = 0; +static int ctx_freelist_len = 0; #include "clinic/context.c.h" @@ -1177,7 +1177,7 @@ get_token_missing(void) int PyContext_ClearFreeList(void) { - Py_ssize_t size = ctx_freelist_len; + int size = ctx_freelist_len; while (ctx_freelist_len) { PyContext *ctx = ctx_freelist; ctx_freelist = (PyContext *)ctx->ctx_weakreflist; diff --git a/Python/hamt.c b/Python/hamt.c index c9acbbcc5acc..e54d3a4c55f9 100644 --- a/Python/hamt.c +++ b/Python/hamt.c @@ -729,7 +729,7 @@ hamt_node_bitmap_assoc(PyHamtNode_Bitmap *self, uint32_t key_idx = 2 * idx; uint32_t val_idx = key_idx + 1; - assert(val_idx < Py_SIZE(self)); + assert(val_idx < (size_t)Py_SIZE(self)); PyObject *key_or_null = self->b_array[key_idx]; PyObject *val_or_node = self->b_array[val_idx]; @@ -1123,7 +1123,7 @@ hamt_node_bitmap_find(PyHamtNode_Bitmap *self, key_idx = idx * 2; val_idx = key_idx + 1; - assert(val_idx < Py_SIZE(self)); + assert(val_idx < (size_t)Py_SIZE(self)); key_or_null = self->b_array[key_idx]; val_or_node = self->b_array[val_idx]; diff --git a/Python/pyhash.c b/Python/pyhash.c index a0850d066b31..9e6e594f441a 100644 --- a/Python/pyhash.c +++ b/Python/pyhash.c @@ -17,7 +17,7 @@ extern "C" { #endif -_Py_HashSecret_t _Py_HashSecret = {0}; +_Py_HashSecret_t _Py_HashSecret = {{0}}; #if Py_HASH_ALGORITHM == Py_HASH_EXTERNAL extern PyHash_FuncDef PyHash_Func; From webhook-mailer at python.org Fri Feb 9 13:00:51 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Fri, 09 Feb 2018 18:00:51 -0000 Subject: [Python-checkins] bpo-30157: Fix csv.Sniffer.sniff() regex pattern. (GH-5601) Message-ID: https://github.com/python/cpython/commit/2411292ba8155327125d8a1da8a4c9fa003d5909 commit: 2411292ba8155327125d8a1da8a4c9fa003d5909 branch: master author: Serhiy Storchaka committer: GitHub date: 2018-02-09T20:00:49+02:00 summary: bpo-30157: Fix csv.Sniffer.sniff() regex pattern. (GH-5601) Co-authored-by: Jake Davis files: A Misc/NEWS.d/next/Library/2018-02-09-14-44-43.bpo-30157.lEiiAK.rst M Lib/csv.py M Lib/test/test_csv.py M Misc/ACKS diff --git a/Lib/csv.py b/Lib/csv.py index 6a8587674fe0..58624af90534 100644 --- a/Lib/csv.py +++ b/Lib/csv.py @@ -217,7 +217,7 @@ def _guess_quote_and_delimiter(self, data, delimiters): matches = [] for restr in (r'(?P[^\w\n"\'])(?P ?)(?P["\']).*?(?P=quote)(?P=delim)', # ,".*?", r'(?:^|\n)(?P["\']).*?(?P=quote)(?P[^\w\n"\'])(?P ?)', # ".*?", - r'(?P>[^\w\n"\'])(?P ?)(?P["\']).*?(?P=quote)(?:$|\n)', # ,".*?" + r'(?P[^\w\n"\'])(?P ?)(?P["\']).*?(?P=quote)(?:$|\n)', # ,".*?" r'(?:^|\n)(?P["\']).*?(?P=quote)(?:$|\n)'): # ".*?" (no delim, no space) regexp = re.compile(restr, re.DOTALL | re.MULTILINE) matches = regexp.findall(data) diff --git a/Lib/test/test_csv.py b/Lib/test/test_csv.py index fe248019a0f6..b65cbf6a50e3 100644 --- a/Lib/test/test_csv.py +++ b/Lib/test/test_csv.py @@ -986,6 +986,16 @@ def test_has_header_regex_special_delimiter(self): self.assertEqual(sniffer.has_header(self.header2 + self.sample8), True) + def test_guess_quote_and_delimiter(self): + sniffer = csv.Sniffer() + for header in (";'123;4';", "'123;4';", ";'123;4'", "'123;4'"): + with self.subTest(header): + dialect = sniffer.sniff(header, ",;") + self.assertEqual(dialect.delimiter, ';') + self.assertEqual(dialect.quotechar, "'") + self.assertIs(dialect.doublequote, False) + self.assertIs(dialect.skipinitialspace, False) + def test_sniff(self): sniffer = csv.Sniffer() dialect = sniffer.sniff(self.sample1) diff --git a/Misc/ACKS b/Misc/ACKS index 4c8b86ac45d4..b31190ca5283 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -355,6 +355,7 @@ Kushal Das Jonathan Dasteel Pierre-Yves David A. Jesse Jiryu Davis +Jake Davis Ratnadeep Debnath Merlijn van Deen John DeGood diff --git a/Misc/NEWS.d/next/Library/2018-02-09-14-44-43.bpo-30157.lEiiAK.rst b/Misc/NEWS.d/next/Library/2018-02-09-14-44-43.bpo-30157.lEiiAK.rst new file mode 100644 index 000000000000..9f651930ac2b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-09-14-44-43.bpo-30157.lEiiAK.rst @@ -0,0 +1,2 @@ +Fixed guessing quote and delimiter in csv.Sniffer.sniff() when only the last +field is quoted. Patch by Jake Davis. From webhook-mailer at python.org Fri Feb 9 17:00:56 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Fri, 09 Feb 2018 22:00:56 -0000 Subject: [Python-checkins] bpo-30157: Fix csv.Sniffer.sniff() regex pattern. (GH-5601) (GH-5602) Message-ID: https://github.com/python/cpython/commit/2ef69a1d45de8aa41c45d32d9ee1ff227bb1a566 commit: 2ef69a1d45de8aa41c45d32d9ee1ff227bb1a566 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Serhiy Storchaka date: 2018-02-10T00:00:48+02:00 summary: bpo-30157: Fix csv.Sniffer.sniff() regex pattern. (GH-5601) (GH-5602) Co-authored-by: Jake Davis (cherry picked from commit 2411292ba8155327125d8a1da8a4c9fa003d5909) files: A Misc/NEWS.d/next/Library/2018-02-09-14-44-43.bpo-30157.lEiiAK.rst M Lib/csv.py M Lib/test/test_csv.py M Misc/ACKS diff --git a/Lib/csv.py b/Lib/csv.py index 6a8587674fe0..58624af90534 100644 --- a/Lib/csv.py +++ b/Lib/csv.py @@ -217,7 +217,7 @@ def _guess_quote_and_delimiter(self, data, delimiters): matches = [] for restr in (r'(?P[^\w\n"\'])(?P ?)(?P["\']).*?(?P=quote)(?P=delim)', # ,".*?", r'(?:^|\n)(?P["\']).*?(?P=quote)(?P[^\w\n"\'])(?P ?)', # ".*?", - r'(?P>[^\w\n"\'])(?P ?)(?P["\']).*?(?P=quote)(?:$|\n)', # ,".*?" + r'(?P[^\w\n"\'])(?P ?)(?P["\']).*?(?P=quote)(?:$|\n)', # ,".*?" r'(?:^|\n)(?P["\']).*?(?P=quote)(?:$|\n)'): # ".*?" (no delim, no space) regexp = re.compile(restr, re.DOTALL | re.MULTILINE) matches = regexp.findall(data) diff --git a/Lib/test/test_csv.py b/Lib/test/test_csv.py index fe248019a0f6..b65cbf6a50e3 100644 --- a/Lib/test/test_csv.py +++ b/Lib/test/test_csv.py @@ -986,6 +986,16 @@ def test_has_header_regex_special_delimiter(self): self.assertEqual(sniffer.has_header(self.header2 + self.sample8), True) + def test_guess_quote_and_delimiter(self): + sniffer = csv.Sniffer() + for header in (";'123;4';", "'123;4';", ";'123;4'", "'123;4'"): + with self.subTest(header): + dialect = sniffer.sniff(header, ",;") + self.assertEqual(dialect.delimiter, ';') + self.assertEqual(dialect.quotechar, "'") + self.assertIs(dialect.doublequote, False) + self.assertIs(dialect.skipinitialspace, False) + def test_sniff(self): sniffer = csv.Sniffer() dialect = sniffer.sniff(self.sample1) diff --git a/Misc/ACKS b/Misc/ACKS index 4c8b86ac45d4..b31190ca5283 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -355,6 +355,7 @@ Kushal Das Jonathan Dasteel Pierre-Yves David A. Jesse Jiryu Davis +Jake Davis Ratnadeep Debnath Merlijn van Deen John DeGood diff --git a/Misc/NEWS.d/next/Library/2018-02-09-14-44-43.bpo-30157.lEiiAK.rst b/Misc/NEWS.d/next/Library/2018-02-09-14-44-43.bpo-30157.lEiiAK.rst new file mode 100644 index 000000000000..9f651930ac2b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-09-14-44-43.bpo-30157.lEiiAK.rst @@ -0,0 +1,2 @@ +Fixed guessing quote and delimiter in csv.Sniffer.sniff() when only the last +field is quoted. Patch by Jake Davis. From webhook-mailer at python.org Fri Feb 9 17:01:43 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Fri, 09 Feb 2018 22:01:43 -0000 Subject: [Python-checkins] [3.6] bpo-30157: Fix csv.Sniffer.sniff() regex pattern. (GH-5601) (GH-5603) Message-ID: https://github.com/python/cpython/commit/504f19145ca5738162d6a720fa45b364ac8c0384 commit: 504f19145ca5738162d6a720fa45b364ac8c0384 branch: 3.6 author: Serhiy Storchaka committer: GitHub date: 2018-02-10T00:01:40+02:00 summary: [3.6] bpo-30157: Fix csv.Sniffer.sniff() regex pattern. (GH-5601) (GH-5603) Co-authored-by: Jake Davis . (cherry picked from commit 2411292ba8155327125d8a1da8a4c9fa003d5909) files: A Misc/NEWS.d/next/Library/2018-02-09-14-44-43.bpo-30157.lEiiAK.rst M Lib/csv.py M Lib/test/test_csv.py M Misc/ACKS diff --git a/Lib/csv.py b/Lib/csv.py index 0349e0bd1162..a05c8da1b2c8 100644 --- a/Lib/csv.py +++ b/Lib/csv.py @@ -217,7 +217,7 @@ def _guess_quote_and_delimiter(self, data, delimiters): matches = [] for restr in (r'(?P[^\w\n"\'])(?P ?)(?P["\']).*?(?P=quote)(?P=delim)', # ,".*?", r'(?:^|\n)(?P["\']).*?(?P=quote)(?P[^\w\n"\'])(?P ?)', # ".*?", - r'(?P>[^\w\n"\'])(?P ?)(?P["\']).*?(?P=quote)(?:$|\n)', # ,".*?" + r'(?P[^\w\n"\'])(?P ?)(?P["\']).*?(?P=quote)(?:$|\n)', # ,".*?" r'(?:^|\n)(?P["\']).*?(?P=quote)(?:$|\n)'): # ".*?" (no delim, no space) regexp = re.compile(restr, re.DOTALL | re.MULTILINE) matches = regexp.findall(data) diff --git a/Lib/test/test_csv.py b/Lib/test/test_csv.py index fe248019a0f6..b65cbf6a50e3 100644 --- a/Lib/test/test_csv.py +++ b/Lib/test/test_csv.py @@ -986,6 +986,16 @@ def test_has_header_regex_special_delimiter(self): self.assertEqual(sniffer.has_header(self.header2 + self.sample8), True) + def test_guess_quote_and_delimiter(self): + sniffer = csv.Sniffer() + for header in (";'123;4';", "'123;4';", ";'123;4'", "'123;4'"): + with self.subTest(header): + dialect = sniffer.sniff(header, ",;") + self.assertEqual(dialect.delimiter, ';') + self.assertEqual(dialect.quotechar, "'") + self.assertIs(dialect.doublequote, False) + self.assertIs(dialect.skipinitialspace, False) + def test_sniff(self): sniffer = csv.Sniffer() dialect = sniffer.sniff(self.sample1) diff --git a/Misc/ACKS b/Misc/ACKS index ac1345938cb4..0e64609df64e 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -350,6 +350,7 @@ Kushal Das Jonathan Dasteel Pierre-Yves David A. Jesse Jiryu Davis +Jake Davis Merlijn van Deen John DeGood Ned Deily diff --git a/Misc/NEWS.d/next/Library/2018-02-09-14-44-43.bpo-30157.lEiiAK.rst b/Misc/NEWS.d/next/Library/2018-02-09-14-44-43.bpo-30157.lEiiAK.rst new file mode 100644 index 000000000000..9f651930ac2b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-09-14-44-43.bpo-30157.lEiiAK.rst @@ -0,0 +1,2 @@ +Fixed guessing quote and delimiter in csv.Sniffer.sniff() when only the last +field is quoted. Patch by Jake Davis. From webhook-mailer at python.org Fri Feb 9 17:02:07 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Fri, 09 Feb 2018 22:02:07 -0000 Subject: [Python-checkins] [2.7] bpo-30157: Fix csv.Sniffer.sniff() regex pattern. (GH-5601) (GH-5604) Message-ID: https://github.com/python/cpython/commit/e7197936c987bdf31b6b7b1dab275d1a762e03b3 commit: e7197936c987bdf31b6b7b1dab275d1a762e03b3 branch: 2.7 author: Serhiy Storchaka committer: GitHub date: 2018-02-10T00:02:04+02:00 summary: [2.7] bpo-30157: Fix csv.Sniffer.sniff() regex pattern. (GH-5601) (GH-5604) Co-authored-by: Jake Davis . (cherry picked from commit 2411292ba8155327125d8a1da8a4c9fa003d5909) files: A Misc/NEWS.d/next/Library/2018-02-09-14-44-43.bpo-30157.lEiiAK.rst M Lib/csv.py M Lib/test/test_csv.py M Misc/ACKS diff --git a/Lib/csv.py b/Lib/csv.py index c155ada794a6..70c53ae7791e 100644 --- a/Lib/csv.py +++ b/Lib/csv.py @@ -217,7 +217,7 @@ def _guess_quote_and_delimiter(self, data, delimiters): matches = [] for restr in ('(?P[^\w\n"\'])(?P ?)(?P["\']).*?(?P=quote)(?P=delim)', # ,".*?", '(?:^|\n)(?P["\']).*?(?P=quote)(?P[^\w\n"\'])(?P ?)', # ".*?", - '(?P>[^\w\n"\'])(?P ?)(?P["\']).*?(?P=quote)(?:$|\n)', # ,".*?" + '(?P[^\w\n"\'])(?P ?)(?P["\']).*?(?P=quote)(?:$|\n)', # ,".*?" '(?:^|\n)(?P["\']).*?(?P=quote)(?:$|\n)'): # ".*?" (no delim, no space) regexp = re.compile(restr, re.DOTALL | re.MULTILINE) matches = regexp.findall(data) diff --git a/Lib/test/test_csv.py b/Lib/test/test_csv.py index d4567590cb1d..88d5af7c130d 100644 --- a/Lib/test/test_csv.py +++ b/Lib/test/test_csv.py @@ -1036,6 +1036,15 @@ def test_has_header_regex_special_delimiter(self): self.assertEqual(sniffer.has_header(self.header2 + self.sample8), True) + def test_guess_quote_and_delimiter(self): + sniffer = csv.Sniffer() + for header in (";'123;4';", "'123;4';", ";'123;4'", "'123;4'"): + dialect = sniffer.sniff(header, ",;") + self.assertEqual(dialect.delimiter, ';') + self.assertEqual(dialect.quotechar, "'") + self.assertIs(dialect.doublequote, False) + self.assertIs(dialect.skipinitialspace, False) + def test_sniff(self): sniffer = csv.Sniffer() dialect = sniffer.sniff(self.sample1) diff --git a/Misc/ACKS b/Misc/ACKS index dc64293b6965..f0a115d5d555 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -317,6 +317,7 @@ Kushal Das Jonathan Dasteel Pierre-Yves David A. Jesse Jiryu Davis +Jake Davis Merlijn van Deen John DeGood Ned Deily diff --git a/Misc/NEWS.d/next/Library/2018-02-09-14-44-43.bpo-30157.lEiiAK.rst b/Misc/NEWS.d/next/Library/2018-02-09-14-44-43.bpo-30157.lEiiAK.rst new file mode 100644 index 000000000000..9f651930ac2b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-09-14-44-43.bpo-30157.lEiiAK.rst @@ -0,0 +1,2 @@ +Fixed guessing quote and delimiter in csv.Sniffer.sniff() when only the last +field is quoted. Patch by Jake Davis. From webhook-mailer at python.org Fri Feb 9 17:08:20 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Fri, 09 Feb 2018 22:08:20 -0000 Subject: [Python-checkins] bpo-30688: Support \N{name} escapes in re patterns. (GH-5588) Message-ID: https://github.com/python/cpython/commit/a445feb72902e4a3c5ae712f0c289309e1580d52 commit: a445feb72902e4a3c5ae712f0c289309e1580d52 branch: master author: Serhiy Storchaka committer: GitHub date: 2018-02-10T00:08:17+02:00 summary: bpo-30688: Support \N{name} escapes in re patterns. (GH-5588) Co-authored-by: Jonathan Eunice files: A Misc/NEWS.d/next/Library/2018-02-08-18-59-11.bpo-30688.zBh4TH.rst M Doc/library/re.rst M Doc/whatsnew/3.8.rst M Lib/sre_parse.py M Lib/test/test_re.py M Misc/ACKS diff --git a/Doc/library/re.rst b/Doc/library/re.rst index 83ebe7db01ad..475a8d285550 100644 --- a/Doc/library/re.rst +++ b/Doc/library/re.rst @@ -468,13 +468,13 @@ Most of the standard escapes supported by Python string literals are also accepted by the regular expression parser:: \a \b \f \n - \r \t \u \U - \v \x \\ + \N \r \t \u + \U \v \x \\ (Note that ``\b`` is used to represent word boundaries, and means "backspace" only inside character classes.) -``'\u'`` and ``'\U'`` escape sequences are only recognized in Unicode +``'\u'``, ``'\U'``, and ``'\N'`` escape sequences are only recognized in Unicode patterns. In bytes patterns they are errors. Octal escapes are included in a limited form. If the first digit is a 0, or if @@ -488,6 +488,9 @@ three digits in length. .. versionchanged:: 3.6 Unknown escapes consisting of ``'\'`` and an ASCII letter now are errors. +.. versionchanged:: 3.8 + The ``'\N{name}'`` escape sequence has been added. As in string literals, + it expands to the named Unicode character (e.g. ``'\N{EM DASH}'``). .. seealso:: diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 60f54a0561e5..41819815e399 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -75,6 +75,8 @@ New Features Other Language Changes ====================== +* Added support of ``\N{name}`` escapes in :mod:`regular expressions `. + (Contributed by Jonathan Eunice and Serhiy Storchaka in :issue:`30688`.) New Modules diff --git a/Lib/sre_parse.py b/Lib/sre_parse.py index a53735b07ded..db01e844b432 100644 --- a/Lib/sre_parse.py +++ b/Lib/sre_parse.py @@ -13,6 +13,7 @@ # XXX: show string offset and offending character for all errors from sre_constants import * +import unicodedata SPECIAL_CHARS = ".\\[{()*+?^$|" REPEAT_CHARS = "*+?{" @@ -264,19 +265,19 @@ def getwhile(self, n, charset): result += c self.__next() return result - def getuntil(self, terminator): + def getuntil(self, terminator, name): result = '' while True: c = self.next self.__next() if c is None: if not result: - raise self.error("missing group name") + raise self.error("missing " + name) raise self.error("missing %s, unterminated name" % terminator, len(result)) if c == terminator: if not result: - raise self.error("missing group name", 1) + raise self.error("missing " + name, 1) break result += c return result @@ -322,6 +323,17 @@ def _class_escape(source, escape): c = int(escape[2:], 16) chr(c) # raise ValueError for invalid code return LITERAL, c + elif c == "N" and source.istext: + # named unicode escape e.g. \N{EM DASH} + if not source.match('{'): + raise source.error("missing {") + charname = source.getuntil('}', 'character name') + try: + c = ord(unicodedata.lookup(charname)) + except KeyError: + raise source.error("undefined character name %r" % charname, + len(charname) + len(r'\N{}')) + return LITERAL, c elif c in OCTDIGITS: # octal escape (up to three digits) escape += source.getwhile(2, OCTDIGITS) @@ -370,6 +382,17 @@ def _escape(source, escape, state): c = int(escape[2:], 16) chr(c) # raise ValueError for invalid code return LITERAL, c + elif c == "N" and source.istext: + # named unicode escape e.g. \N{EM DASH} + if not source.match('{'): + raise source.error("missing {") + charname = source.getuntil('}', 'character name') + try: + c = ord(unicodedata.lookup(charname)) + except KeyError: + raise source.error("undefined character name %r" % charname, + len(charname) + len(r'\N{}')) + return LITERAL, c elif c == "0": # octal escape escape += source.getwhile(2, OCTDIGITS) @@ -679,13 +702,13 @@ def _parse(source, state, verbose, nested, first=False): # python extensions if sourcematch("<"): # named group: skip forward to end of name - name = source.getuntil(">") + name = source.getuntil(">", "group name") if not name.isidentifier(): msg = "bad character in group name %r" % name raise source.error(msg, len(name) + 1) elif sourcematch("="): # named backreference - name = source.getuntil(")") + name = source.getuntil(")", "group name") if not name.isidentifier(): msg = "bad character in group name %r" % name raise source.error(msg, len(name) + 1) @@ -748,7 +771,7 @@ def _parse(source, state, verbose, nested, first=False): elif char == "(": # conditional backreference group - condname = source.getuntil(")") + condname = source.getuntil(")", "group name") if condname.isidentifier(): condgroup = state.groupdict.get(condname) if condgroup is None: @@ -977,7 +1000,7 @@ def addgroup(index, pos): name = "" if not s.match("<"): raise s.error("missing <") - name = s.getuntil(">") + name = s.getuntil(">", "group name") if name.isidentifier(): try: index = groupindex[name] diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py index 9fed4bef8809..ab1d985d59f8 100644 --- a/Lib/test/test_re.py +++ b/Lib/test/test_re.py @@ -694,6 +694,42 @@ def test_other_escapes(self): with self.subTest(c): self.assertRaises(re.error, re.compile, '[\\%c]' % c) + def test_named_unicode_escapes(self): + # test individual Unicode named escapes + self.assertTrue(re.match(r'\N{LESS-THAN SIGN}', '<')) + self.assertTrue(re.match(r'\N{less-than sign}', '<')) + self.assertIsNone(re.match(r'\N{LESS-THAN SIGN}', '>')) + self.assertTrue(re.match(r'\N{SNAKE}', '\U0001f40d')) + self.assertTrue(re.match(r'\N{ARABIC LIGATURE UIGHUR KIRGHIZ YEH WITH ' + r'HAMZA ABOVE WITH ALEF MAKSURA ISOLATED FORM}', + '\ufbf9')) + self.assertTrue(re.match(r'[\N{LESS-THAN SIGN}-\N{GREATER-THAN SIGN}]', + '=')) + self.assertIsNone(re.match(r'[\N{LESS-THAN SIGN}-\N{GREATER-THAN SIGN}]', + ';')) + + # test errors in \N{name} handling - only valid names should pass + self.checkPatternError(r'\N', 'missing {', 2) + self.checkPatternError(r'[\N]', 'missing {', 3) + self.checkPatternError(r'\N{', 'missing character name', 3) + self.checkPatternError(r'[\N{', 'missing character name', 4) + self.checkPatternError(r'\N{}', 'missing character name', 3) + self.checkPatternError(r'[\N{}]', 'missing character name', 4) + self.checkPatternError(r'\NSNAKE}', 'missing {', 2) + self.checkPatternError(r'[\NSNAKE}]', 'missing {', 3) + self.checkPatternError(r'\N{SNAKE', + 'missing }, unterminated name', 3) + self.checkPatternError(r'[\N{SNAKE]', + 'missing }, unterminated name', 4) + self.checkPatternError(r'[\N{SNAKE]}', + "undefined character name 'SNAKE]'", 1) + self.checkPatternError(r'\N{SPAM}', + "undefined character name 'SPAM'", 0) + self.checkPatternError(r'[\N{SPAM}]', + "undefined character name 'SPAM'", 1) + self.checkPatternError(br'\N{LESS-THAN SIGN}', r'bad escape \N', 0) + self.checkPatternError(br'[\N{LESS-THAN SIGN}]', r'bad escape \N', 1) + def test_string_boundaries(self): # See http://bugs.python.org/issue10713 self.assertEqual(re.search(r"\b(abc)\b", "abc").group(1), diff --git a/Misc/ACKS b/Misc/ACKS index b31190ca5283..ea1d9418870a 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -441,6 +441,7 @@ Andy Eskilsson Andr? Espaze Stefan Esser Nicolas Estibals +Jonathan Eunice Carey Evans Stephen D Evans Tim Everett diff --git a/Misc/NEWS.d/next/Library/2018-02-08-18-59-11.bpo-30688.zBh4TH.rst b/Misc/NEWS.d/next/Library/2018-02-08-18-59-11.bpo-30688.zBh4TH.rst new file mode 100644 index 000000000000..7d31680d651a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-08-18-59-11.bpo-30688.zBh4TH.rst @@ -0,0 +1,2 @@ +Added support of ``\N{name}`` escapes in regular expressions. Based on +patch by Jonathan Eunice. From webhook-mailer at python.org Sat Feb 10 01:59:33 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sat, 10 Feb 2018 06:59:33 -0000 Subject: [Python-checkins] bpo-30688: Import unicodedata only when needed. (GH-5606) Message-ID: https://github.com/python/cpython/commit/5df5286abda57a0b3865d4fc3e25aaf1a820ef49 commit: 5df5286abda57a0b3865d4fc3e25aaf1a820ef49 branch: master author: Zhou Fangyi committer: Serhiy Storchaka date: 2018-02-10T08:59:29+02:00 summary: bpo-30688: Import unicodedata only when needed. (GH-5606) Importing unicodedata in sre_parse leads to failure in compilation. unicodedata is unused during compilation, and is not compiled when this file is imported. The error occurs when generating posix variables, pprint is required. The dependency chain goes on like this: sysconfig -> pprint -> re -> sre_compile -> sre_parse (this file) This commits fixes compilation issues introduced by 2272cec13b53c405d86c45d404f035f201c0baef. (Issue 30688, GH-5588) files: M Lib/sre_parse.py diff --git a/Lib/sre_parse.py b/Lib/sre_parse.py index db01e844b432..7a172ff2fb14 100644 --- a/Lib/sre_parse.py +++ b/Lib/sre_parse.py @@ -13,7 +13,6 @@ # XXX: show string offset and offending character for all errors from sre_constants import * -import unicodedata SPECIAL_CHARS = ".\\[{()*+?^$|" REPEAT_CHARS = "*+?{" @@ -324,6 +323,7 @@ def _class_escape(source, escape): chr(c) # raise ValueError for invalid code return LITERAL, c elif c == "N" and source.istext: + import unicodedata # named unicode escape e.g. \N{EM DASH} if not source.match('{'): raise source.error("missing {") @@ -383,6 +383,7 @@ def _escape(source, escape, state): chr(c) # raise ValueError for invalid code return LITERAL, c elif c == "N" and source.istext: + import unicodedata # named unicode escape e.g. \N{EM DASH} if not source.match('{'): raise source.error("missing {") From solipsis at pitrou.net Sat Feb 10 04:09:07 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 10 Feb 2018 09:09:07 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=6 Message-ID: <20180210090907.1.7AFFA49FA127D755@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_asyncio leaked [0, 0, 3] memory blocks, sum=3 test_functools leaked [0, 3, 1] memory blocks, sum=4 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/reflogYfdBe5', '--timeout', '7200'] From webhook-mailer at python.org Sat Feb 10 06:35:25 2018 From: webhook-mailer at python.org (INADA Naoki) Date: Sat, 10 Feb 2018 11:35:25 -0000 Subject: [Python-checkins] travis: Use -O3 option (GH-5599) Message-ID: https://github.com/python/cpython/commit/8ff53564730f7ba503f5ad94418c309c48e8516d commit: 8ff53564730f7ba503f5ad94418c309c48e8516d branch: master author: INADA Naoki committer: GitHub date: 2018-02-10T20:35:17+09:00 summary: travis: Use -O3 option (GH-5599) We don't use debugger on Travis. files: M .travis.yml diff --git a/.travis.yml b/.travis.yml index 98d6b9a97b9b..dd0688717c08 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,8 @@ env: - OPENSSL=1.1.0g - OPENSSL_DIR="$HOME/multissl/openssl/${OPENSSL}" - PATH="${OPENSSL_DIR}/bin:$PATH" - - CFLAGS="-I${OPENSSL_DIR}/include" + # Use -O3 because we don't use debugger on Travis-CI + - CFLAGS="-I${OPENSSL_DIR}/include -O3" - LDFLAGS="-L${OPENSSL_DIR}/lib" # Set rpath with env var instead of -Wl,-rpath linker flag # OpenSSL ignores LDFLAGS when linking bin/openssl From webhook-mailer at python.org Sat Feb 10 06:56:25 2018 From: webhook-mailer at python.org (INADA Naoki) Date: Sat, 10 Feb 2018 11:56:25 -0000 Subject: [Python-checkins] travis: Use -O3 option (GH-5599) Message-ID: https://github.com/python/cpython/commit/e39429ab907df039a4bb6dbfece4c0ef32abeae0 commit: e39429ab907df039a4bb6dbfece4c0ef32abeae0 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: INADA Naoki date: 2018-02-10T20:56:22+09:00 summary: travis: Use -O3 option (GH-5599) We don't use debugger on Travis. (cherry picked from commit 8ff53564730f7ba503f5ad94418c309c48e8516d) Co-authored-by: INADA Naoki files: M .travis.yml diff --git a/.travis.yml b/.travis.yml index 98d6b9a97b9b..dd0688717c08 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,8 @@ env: - OPENSSL=1.1.0g - OPENSSL_DIR="$HOME/multissl/openssl/${OPENSSL}" - PATH="${OPENSSL_DIR}/bin:$PATH" - - CFLAGS="-I${OPENSSL_DIR}/include" + # Use -O3 because we don't use debugger on Travis-CI + - CFLAGS="-I${OPENSSL_DIR}/include -O3" - LDFLAGS="-L${OPENSSL_DIR}/lib" # Set rpath with env var instead of -Wl,-rpath linker flag # OpenSSL ignores LDFLAGS when linking bin/openssl From webhook-mailer at python.org Sat Feb 10 17:39:46 2018 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Sat, 10 Feb 2018 22:39:46 -0000 Subject: [Python-checkins] bpo-32800: Update link to w3c doc for xml default namespaces (GH-5609) Message-ID: https://github.com/python/cpython/commit/8d1f2f40389c476d9240ec87a33da0373597c6af commit: 8d1f2f40389c476d9240ec87a33da0373597c6af branch: master author: sblondon committer: Terry Jan Reedy date: 2018-02-10T17:39:43-05:00 summary: bpo-32800: Update link to w3c doc for xml default namespaces (GH-5609) The new link is given in a red box on the old page. files: A Misc/NEWS.d/next/Documentation/2018-02-10-15-16-04.bpo-32800.FyrqCk.rst M Doc/library/xml.etree.elementtree.rst diff --git a/Doc/library/xml.etree.elementtree.rst b/Doc/library/xml.etree.elementtree.rst index 61808596a555..6298f1396ae2 100644 --- a/Doc/library/xml.etree.elementtree.rst +++ b/Doc/library/xml.etree.elementtree.rst @@ -297,7 +297,7 @@ If the XML input has `namespaces with prefixes in the form ``prefix:sometag`` get expanded to ``{uri}sometag`` where the *prefix* is replaced by the full *URI*. Also, if there is a `default namespace -`__, +`__, that full URI gets prepended to all of the non-prefixed tags. Here is an XML example that incorporates two namespaces, one with the diff --git a/Misc/NEWS.d/next/Documentation/2018-02-10-15-16-04.bpo-32800.FyrqCk.rst b/Misc/NEWS.d/next/Documentation/2018-02-10-15-16-04.bpo-32800.FyrqCk.rst new file mode 100644 index 000000000000..eac1107bba76 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2018-02-10-15-16-04.bpo-32800.FyrqCk.rst @@ -0,0 +1 @@ +Update link to w3c doc for xml default namespaces. From webhook-mailer at python.org Sat Feb 10 18:08:36 2018 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Sat, 10 Feb 2018 23:08:36 -0000 Subject: [Python-checkins] bpo-32800: Update link to w3c doc for xml default namespaces (GH-5609) (GH-5611) Message-ID: https://github.com/python/cpython/commit/e6033209754c5b01870791645044a791da1fa73f commit: e6033209754c5b01870791645044a791da1fa73f branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Terry Jan Reedy date: 2018-02-10T18:08:34-05:00 summary: bpo-32800: Update link to w3c doc for xml default namespaces (GH-5609) (GH-5611) The new link is given in a red box on the old page. (cherry picked from commit 8d1f2f40389c476d9240ec87a33da0373597c6af) Co-authored-by: sblondon files: A Misc/NEWS.d/next/Documentation/2018-02-10-15-16-04.bpo-32800.FyrqCk.rst M Doc/library/xml.etree.elementtree.rst diff --git a/Doc/library/xml.etree.elementtree.rst b/Doc/library/xml.etree.elementtree.rst index 61808596a555..6298f1396ae2 100644 --- a/Doc/library/xml.etree.elementtree.rst +++ b/Doc/library/xml.etree.elementtree.rst @@ -297,7 +297,7 @@ If the XML input has `namespaces with prefixes in the form ``prefix:sometag`` get expanded to ``{uri}sometag`` where the *prefix* is replaced by the full *URI*. Also, if there is a `default namespace -`__, +`__, that full URI gets prepended to all of the non-prefixed tags. Here is an XML example that incorporates two namespaces, one with the diff --git a/Misc/NEWS.d/next/Documentation/2018-02-10-15-16-04.bpo-32800.FyrqCk.rst b/Misc/NEWS.d/next/Documentation/2018-02-10-15-16-04.bpo-32800.FyrqCk.rst new file mode 100644 index 000000000000..eac1107bba76 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2018-02-10-15-16-04.bpo-32800.FyrqCk.rst @@ -0,0 +1 @@ +Update link to w3c doc for xml default namespaces. From webhook-mailer at python.org Sat Feb 10 19:42:24 2018 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Sun, 11 Feb 2018 00:42:24 -0000 Subject: [Python-checkins] bpo-32800: Update link to w3c doc for xml default namespaces (GH-5609) GH-5612) Message-ID: https://github.com/python/cpython/commit/9d8c24b79162711551394c8f8e6002342554791b commit: 9d8c24b79162711551394c8f8e6002342554791b branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Terry Jan Reedy date: 2018-02-10T19:42:22-05:00 summary: bpo-32800: Update link to w3c doc for xml default namespaces (GH-5609) GH-5612) The new link is given in a red box on the old page. (cherry picked from commit 8d1f2f40389c476d9240ec87a33da0373597c6af) Co-authored-by: sblondon files: A Misc/NEWS.d/next/Documentation/2018-02-10-15-16-04.bpo-32800.FyrqCk.rst M Doc/library/xml.etree.elementtree.rst diff --git a/Doc/library/xml.etree.elementtree.rst b/Doc/library/xml.etree.elementtree.rst index 7d814ad406eb..80505ea64ac7 100644 --- a/Doc/library/xml.etree.elementtree.rst +++ b/Doc/library/xml.etree.elementtree.rst @@ -297,7 +297,7 @@ If the XML input has `namespaces with prefixes in the form ``prefix:sometag`` get expanded to ``{uri}sometag`` where the *prefix* is replaced by the full *URI*. Also, if there is a `default namespace -`__, +`__, that full URI gets prepended to all of the non-prefixed tags. Here is an XML example that incorporates two namespaces, one with the diff --git a/Misc/NEWS.d/next/Documentation/2018-02-10-15-16-04.bpo-32800.FyrqCk.rst b/Misc/NEWS.d/next/Documentation/2018-02-10-15-16-04.bpo-32800.FyrqCk.rst new file mode 100644 index 000000000000..eac1107bba76 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2018-02-10-15-16-04.bpo-32800.FyrqCk.rst @@ -0,0 +1 @@ +Update link to w3c doc for xml default namespaces. From webhook-mailer at python.org Sat Feb 10 19:42:44 2018 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Sun, 11 Feb 2018 00:42:44 -0000 Subject: [Python-checkins] bpo-32800: Update link to w3c doc for xml default namespaces (GH-5609) (GH-5613) Message-ID: https://github.com/python/cpython/commit/ea6e6444bdf983c99d9175a22dd054bf02ee22b4 commit: ea6e6444bdf983c99d9175a22dd054bf02ee22b4 branch: 2.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Terry Jan Reedy date: 2018-02-10T19:42:42-05:00 summary: bpo-32800: Update link to w3c doc for xml default namespaces (GH-5609) (GH-5613) The new link is given in a red box on the old page. (cherry picked from commit 8d1f2f40389c476d9240ec87a33da0373597c6af) Co-authored-by: sblondon files: A Misc/NEWS.d/next/Documentation/2018-02-10-15-16-04.bpo-32800.FyrqCk.rst M Doc/library/xml.etree.elementtree.rst diff --git a/Doc/library/xml.etree.elementtree.rst b/Doc/library/xml.etree.elementtree.rst index 39d811be6d7f..e13da105cf51 100644 --- a/Doc/library/xml.etree.elementtree.rst +++ b/Doc/library/xml.etree.elementtree.rst @@ -274,7 +274,7 @@ If the XML input has `namespaces with prefixes in the form ``prefix:sometag`` get expanded to ``{uri}sometag`` where the *prefix* is replaced by the full *URI*. Also, if there is a `default namespace -`__, +`__, that full URI gets prepended to all of the non-prefixed tags. Here is an XML example that incorporates two namespaces, one with the diff --git a/Misc/NEWS.d/next/Documentation/2018-02-10-15-16-04.bpo-32800.FyrqCk.rst b/Misc/NEWS.d/next/Documentation/2018-02-10-15-16-04.bpo-32800.FyrqCk.rst new file mode 100644 index 000000000000..eac1107bba76 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2018-02-10-15-16-04.bpo-32800.FyrqCk.rst @@ -0,0 +1 @@ +Update link to w3c doc for xml default namespaces. From webhook-mailer at python.org Sun Feb 11 03:30:34 2018 From: webhook-mailer at python.org (Raymond Hettinger) Date: Sun, 11 Feb 2018 08:30:34 -0000 Subject: [Python-checkins] bpo-32792: Preserve mapping order in ChainMap() (GH-5586) Message-ID: https://github.com/python/cpython/commit/3793f95f98c3112ce447288a5bf9899eb9e35423 commit: 3793f95f98c3112ce447288a5bf9899eb9e35423 branch: master author: Raymond Hettinger committer: GitHub date: 2018-02-11T00:30:31-08:00 summary: bpo-32792: Preserve mapping order in ChainMap() (GH-5586) files: A Misc/NEWS.d/next/Library/2018-02-08-00-47-07.bpo-32792.NtyDb4.rst M Lib/collections/__init__.py M Lib/test/test_collections.py diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py index f0b41fd9d10d..9a753db71cae 100644 --- a/Lib/collections/__init__.py +++ b/Lib/collections/__init__.py @@ -920,7 +920,10 @@ def __len__(self): return len(set().union(*self.maps)) # reuses stored hash values if possible def __iter__(self): - return iter(set().union(*self.maps)) + d = {} + for mapping in reversed(self.maps): + d.update(mapping) # reuses stored hash values if possible + return iter(d) def __contains__(self, key): return any(key in m for m in self.maps) diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py index a55239e57302..2099d236d0c4 100644 --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -141,6 +141,23 @@ def __missing__(self, key): with self.assertRaises(KeyError): d.popitem() + def test_order_preservation(self): + d = ChainMap( + OrderedDict(j=0, h=88888), + OrderedDict(), + OrderedDict(i=9999, d=4444, c=3333), + OrderedDict(f=666, b=222, g=777, c=333, h=888), + OrderedDict(), + OrderedDict(e=55, b=22), + OrderedDict(a=1, b=2, c=3, d=4, e=5), + OrderedDict(), + ) + self.assertEqual(''.join(d), 'abcdefghij') + self.assertEqual(list(d.items()), + [('a', 1), ('b', 222), ('c', 3333), ('d', 4444), + ('e', 55), ('f', 666), ('g', 777), ('h', 88888), + ('i', 9999), ('j', 0)]) + def test_dict_coercion(self): d = ChainMap(dict(a=1, b=2), dict(b=20, c=30)) self.assertEqual(dict(d), dict(a=1, b=2, c=30)) diff --git a/Misc/NEWS.d/next/Library/2018-02-08-00-47-07.bpo-32792.NtyDb4.rst b/Misc/NEWS.d/next/Library/2018-02-08-00-47-07.bpo-32792.NtyDb4.rst new file mode 100644 index 000000000000..1f7df62cc3e1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-08-00-47-07.bpo-32792.NtyDb4.rst @@ -0,0 +1 @@ +collections.ChainMap() preserves the order of the underlying mappings. From webhook-mailer at python.org Sun Feb 11 04:10:00 2018 From: webhook-mailer at python.org (Raymond Hettinger) Date: Sun, 11 Feb 2018 09:10:00 -0000 Subject: [Python-checkins] bpo-32792: Preserve mapping order in ChainMap() (GH-5586) (#GH-5617) Message-ID: https://github.com/python/cpython/commit/170b3f79506480f78275a801822c9ff1283e16f2 commit: 170b3f79506480f78275a801822c9ff1283e16f2 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Raymond Hettinger date: 2018-02-11T01:09:52-08:00 summary: bpo-32792: Preserve mapping order in ChainMap() (GH-5586) (#GH-5617) (cherry picked from commit 3793f95f98c3112ce447288a5bf9899eb9e35423) Co-authored-by: Raymond Hettinger files: A Misc/NEWS.d/next/Library/2018-02-08-00-47-07.bpo-32792.NtyDb4.rst M Lib/collections/__init__.py M Lib/test/test_collections.py diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py index 8aeee359cd62..c481fe2f2012 100644 --- a/Lib/collections/__init__.py +++ b/Lib/collections/__init__.py @@ -914,7 +914,10 @@ def __len__(self): return len(set().union(*self.maps)) # reuses stored hash values if possible def __iter__(self): - return iter(set().union(*self.maps)) + d = {} + for mapping in reversed(self.maps): + d.update(mapping) # reuses stored hash values if possible + return iter(d) def __contains__(self, key): return any(key in m for m in self.maps) diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py index a55239e57302..2099d236d0c4 100644 --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -141,6 +141,23 @@ def __missing__(self, key): with self.assertRaises(KeyError): d.popitem() + def test_order_preservation(self): + d = ChainMap( + OrderedDict(j=0, h=88888), + OrderedDict(), + OrderedDict(i=9999, d=4444, c=3333), + OrderedDict(f=666, b=222, g=777, c=333, h=888), + OrderedDict(), + OrderedDict(e=55, b=22), + OrderedDict(a=1, b=2, c=3, d=4, e=5), + OrderedDict(), + ) + self.assertEqual(''.join(d), 'abcdefghij') + self.assertEqual(list(d.items()), + [('a', 1), ('b', 222), ('c', 3333), ('d', 4444), + ('e', 55), ('f', 666), ('g', 777), ('h', 88888), + ('i', 9999), ('j', 0)]) + def test_dict_coercion(self): d = ChainMap(dict(a=1, b=2), dict(b=20, c=30)) self.assertEqual(dict(d), dict(a=1, b=2, c=30)) diff --git a/Misc/NEWS.d/next/Library/2018-02-08-00-47-07.bpo-32792.NtyDb4.rst b/Misc/NEWS.d/next/Library/2018-02-08-00-47-07.bpo-32792.NtyDb4.rst new file mode 100644 index 000000000000..1f7df62cc3e1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-08-00-47-07.bpo-32792.NtyDb4.rst @@ -0,0 +1 @@ +collections.ChainMap() preserves the order of the underlying mappings. From solipsis at pitrou.net Sun Feb 11 04:10:43 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 11 Feb 2018 09:10:43 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=11 Message-ID: <20180211091043.1.E5DC0B6A98BFC394@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 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogKLI10C', '--timeout', '7200'] From webhook-mailer at python.org Sun Feb 11 08:10:49 2018 From: webhook-mailer at python.org (Nick Coghlan) Date: Sun, 11 Feb 2018 13:10:49 -0000 Subject: [Python-checkins] bpo-11015: Update test.support documentation (GH-5610) Message-ID: https://github.com/python/cpython/commit/988fb28431d3a3fc5dc6eb657c8a4baacc04d9ce commit: 988fb28431d3a3fc5dc6eb657c8a4baacc04d9ce branch: master author: Cheryl Sabella committer: Nick Coghlan date: 2018-02-11T23:10:42+10:00 summary: bpo-11015: Update test.support documentation (GH-5610) files: A Misc/NEWS.d/next/Documentation/2018-02-10-12-48-38.bpo-11015.-gUf34.rst M Doc/library/test.rst diff --git a/Doc/library/test.rst b/Doc/library/test.rst index 01ba1ec7062c..a366fe2556b5 100644 --- a/Doc/library/test.rst +++ b/Doc/library/test.rst @@ -237,12 +237,127 @@ The :mod:`test.support` module defines the following constants: ``True`` if the running interpreter is Jython. +.. data:: is_android + + ``True`` if the system is Android. + + +.. data:: unix_shell + + Path for shell if not on Windows; otherwise ``None``. + + +.. data:: FS_NONASCII + + A non-ASCII character encodable by :func:`os.fsencode`. + + .. data:: TESTFN Set to a name that is safe to use as the name of a temporary file. Any temporary file that is created should be closed and unlinked (removed). +.. data:: TESTFN_UNICODE + + Set to a non-ASCII name for a temporary file. + + +.. data:: TESTFN_ENCODING + + Set to :func:`sys.getfilesystemencoding`. + + +.. data:: TESTFN_UNENCODABLE + + Set to a filename (str type) that should not be able to be encoded by file + system encoding in strict mode. It may be ``None`` if it's not possible to + generate such a filename. + + +.. data:: TESTFN_UNDECODABLE + + Set to a filename (bytes type) that should not be able to be decoded by + file system encoding in strict mode. It may be ``None`` if it's not + possible to generate such a filename. + + +.. data:: TESTFN_NONASCII + + Set to a filename containing the :data:`FS_NONASCII` character. + + +.. data:: IPV6_ENABLED + + Set to ``True`` if IPV6 is enabled on this host, ``False`` otherwise. + + +.. data:: SAVEDCWD + + Set to :func:`os.getcwd`. + + +.. data:: PGO + + Set when tests can be skipped when they are not useful for PGO. + + +.. data:: PIPE_MAX_SIZE + + A constant that is likely larger than the underlying OS pipe buffer size, + to make writes blocking. + + +.. data:: SOCK_MAX_SIZE + + A constant that is likely larger than the underlying OS socket buffer size, + to make writes blocking. + + +.. data:: TEST_SUPPORT_DIR + + Set to the top level directory that contains :mod:`test.support`. + + +.. data:: TEST_HOME_DIR + + Set to the top level directory for the test package. + + +.. data:: TEST_DATA_DIR + + Set to the ``data`` directory within the test package. + + +.. data:: MAX_Py_ssize_t + + Set to :data:`sys.maxsize` for big memory tests. + + +.. data:: max_memuse + + Set by :func:`set_memlimit` as the memory limit for big memory tests. + Limited by :data:`MAX_Py_ssize_t`. + + +.. data:: real_max_memuse + + Set by :func:`set_memlimit` as the memory limit for big memory tests. Not + limited by :data:`MAX_Py_ssize_t`. + + +.. data:: MISSING_C_DOCSTRINGS + + Return ``True`` if running on CPython, not on Windows, and configuration + not set with ``WITH_DOC_STRINGS``. + + +.. data:: HAVE_DOCSTRINGS + + Check for presence of docstrings. + + + The :mod:`test.support` module defines the following functions: .. function:: forget(module_name) @@ -251,6 +366,38 @@ The :mod:`test.support` module defines the following functions: byte-compiled files of the module. +.. function:: unload(name) + + Delete *name* from ``sys.modules``. + + +.. function:: unlink(filename) + + Call :func:`os.unlink` on *filename*. On Windows platforms, this is + wrapped with a wait loop that checks for the existence fo the file. + + +.. function:: rmdir(filename) + + Call :func:`os.rmdir` on *filename*. On Windows platforms, this is + wrapped with a wait loop that checks for the existence of the file. + + +.. function:: rmtree(path) + + Call :func:`shutil.rmtree` on *path* or call :func:`os.lstat` and + :func:`os.rmdir` to remove a path and its contents. On Windows platforms, + this is wrapped with a wait loop that checks for the existence of the files. + + +.. function:: make_legacy_pyc(source) + + Move a PEP 3147/488 pyc file to its legacy pyc location and return the file + system path to the legacy pyc file. The *source* value is the file system + path to the source file. It does not need to exist, however the PEP + 3147/488 pyc file must exist. + + .. function:: is_resource_enabled(resource) Return ``True`` if *resource* is enabled and available. The list of @@ -258,6 +405,16 @@ The :mod:`test.support` module defines the following functions: tests. +.. function:: python_is_optimized() + + Return ``True`` if Python was not built with ``-O0`` or ``-Og``. + + +.. function:: with_pymalloc() + + Return :data:`_testcapi.WITH_PYMALLOC`. + + .. function:: requires(resource, msg=None) Raise :exc:`ResourceDenied` if *resource* is not available. *msg* is the @@ -266,14 +423,44 @@ The :mod:`test.support` module defines the following functions: Used when tests are executed by :mod:`test.regrtest`. +.. function:: system_must_validate_cert(f) + + Raise :exc:`unittest.SkipTest` on TLS certification validation failures. + + +.. function:: sortdict(dict) + + Return a repr of *dict* with keys sorted. + + .. function:: findfile(filename, subdir=None) Return the path to the file named *filename*. If no match is found *filename* is returned. This does not equal a failure since it could be the path to the file. - Setting *subdir* indicates a relative path to use to find the file - rather than looking directly in the path directories. + Setting *subdir* indicates a relative path to use to find the file + rather than looking directly in the path directories. + + +.. function:: create_empty_file(filename) + + Create an empty file with *filename*. If it already exists, truncate it. + + +.. function:: fd_count() + + Count the number of open file descriptors. + + +.. function:: match_test(test) + + Match *test* to patterns set in :func:`set_match_tests`. + + +.. function:: set_match_tests(patterns) + + Define match test with regular expression *patterns*. .. function:: run_unittest(\*classes) @@ -293,14 +480,32 @@ The :mod:`test.support` module defines the following functions: This will run all tests defined in the named module. -.. function:: run_doctest(module, verbosity=None) +.. function:: run_doctest(module, verbosity=None, optionflags=0) Run :func:`doctest.testmod` on the given *module*. Return ``(failure_count, test_count)``. If *verbosity* is ``None``, :func:`doctest.testmod` is run with verbosity set to :data:`verbose`. Otherwise, it is run with verbosity set to - ``None``. + ``None``. *optionflags* is passed as ``optionflags`` to + :func:`doctest.testmod`. + + +.. function:: setswitchinterval(interval) + + Set the :func:`sys.setswitchinterval` to the given *interval*. Defines + a minimum interval for Android systems to prevent the system from hanging. + + +.. function:: check_impl_detail(**guards) + + Use this check to guard CPython's implementation-specific tests or to + run them only on the implementations guarded by the arguments:: + + check_impl_detail() # Only on CPython (default). + check_impl_detail(jython=True) # Only on Jython. + check_impl_detail(cpython=False) # Everywhere except CPython. + .. function:: check_warnings(\*filters, quiet=True) @@ -368,6 +573,50 @@ The :mod:`test.support` module defines the following functions: New optional arguments *filters* and *quiet*. +.. function:: check_no_resource_warning(testcase) + + Context manager to check that no :exc:`ResourceWarning` was raised. You + must remove the object which may emit :exc:`ResourceWarning` before the + end of the context manager. + + +.. function:: set_memlimit(limit) + + Set the values for :data:`max_memuse` and :data:`real_max_memuse` for big + memory tests. + + +.. function:: record_original_stdout(stdout) + + Store the value from *stdout*. It is meant to hold the stdout at the + time the regrtest began. + + +.. function:: get_original_stdout + + Return the original stdout set by :func:`record_original_stdout` or + ``sys.stdout`` if it's not set. + + +.. function:: strip_python_strerr(stderr) + + Strip the *stderr* of a Python process from potential debug output + emitted by the interpreter. This will typically be run on the result of + :meth:`subprocess.Popen.communicate`. + + +.. function:: args_from_interpreter_flags() + + Return a list of command line arguments reproducing the current settings + in ``sys.flags`` and ``sys.warnoptions``. + + +.. function:: optim_args_from_interpreter_flags() + + Return a list of command line arguments reproducing the current + optimization settings in ``sys.flags``. + + .. function:: captured_stdin() captured_stdout() captured_stderr() @@ -434,17 +683,125 @@ The :mod:`test.support` module defines the following functions: A context manager that temporarily sets the process umask. +.. function:: transient_internet(resource_name, *, timeout=30.0, errnos=()) + + A context manager that raises :exc:`ResourceDenied` when various issues + with the internet connection manifest themselves as exceptions. + + +.. function:: disable_faulthandler() + + A context manager that replaces ``sys.stderr`` with ``sys.__stderr__``. + + +.. function:: gc_collect() + + Force as many objects as possible to be collected. This is needed because + timely deallocation is not guaranteed by the garbage collector. This means + that ``__del__`` methods may be called later than expected and weakrefs + may remain alive for longer than expected. + + +.. function:: disable_gc() + + A context manager that disables the garbage collector upon entry and + reenables it upon exit. + + +.. function:: swap_attr(obj, attr, new_val) + + Context manager to swap out an attribute with a new object. + + Usage:: + + with swap_attr(obj, "attr", 5): + ... + + This will set ``obj.attr`` to 5 for the duration of the ``with`` block, + restoring the old value at the end of the block. If ``attr`` doesn't + exist on ``obj``, it will be created and then deleted at the end of the + block. + + The old value (or ``None`` if it doesn't exist) will be assigned to the + target of the "as" clause, if there is one. + + +.. function:: swap_item(obj, attr, new_val) + + Context manager to swap out an item with a new object. + + Usage:: + + with swap_item(obj, "item", 5): + ... + + This will set ``obj["item"]`` to 5 for the duration of the ``with`` block, + restoring the old value at the end of the block. If ``item`` doesn't + exist on ``obj``, it will be created and then deleted at the end of the + block. + + The old value (or ``None`` if it doesn't exist) will be assigned to the + target of the "as" clause, if there is one. + + +.. function:: wait_threads_exit(timeout=60.0) + + Context manager to wait until all threads created in the ``with`` statment + exit. + + +.. function:: start_threads(threads, unlock=None) + + Context manager to start *threads*. It attempts to join the threads upon + exit. + + +.. function:: calcobjsize(fmt) + + Return :func:`struct.calcsize` for ``nP{fmt}0n`` or, if ``gettotalrefcount`` + exists, ``2PnP{fmt}0P``. + + +.. function:: calcvobjsize(fmt) + + Return :func:`struct.calcsize` for ``nPn{fmt}0n`` or, if ``gettotalrefcount`` + exists, ``2PnPn{fmt}0P``. + + +.. function:: checksizeof(test, o, size) + + For testcase *test*, assert that the ``sys.getsizeof`` for *o* plus the GC + header size equals *size*. + + .. function:: can_symlink() Return ``True`` if the OS supports symbolic links, ``False`` otherwise. +.. function:: can_xattr() + + Return ``True`` if the OS supports xattr, ``False`` + otherwise. + + .. decorator:: skip_unless_symlink A decorator for running tests that require support for symbolic links. +.. decorator:: skip_unless_xattr + + A decorator for running tests that require support for xattr. + + +.. decorator:: skip_unless_bind_unix_socket + + A decorator for running tests that require a functional bind() for Unix + sockets. + + .. decorator:: anticipate_failure(condition) A decorator to conditionally mark tests with @@ -460,20 +817,145 @@ The :mod:`test.support` module defines the following functions: sequentially, and the first valid locale will be used. +.. decorator:: run_with_tz(tz) + + A decorator for running a function in a specific timezone, correctly + resetting it after it has finished. + + +.. decorator:: requires_freebsd_version(*min_version) + + Decorator for the minimum version when running test on FreeBSD. If the + FreeBSD version is less than the minimum, raise :exc:`unittest.SkipTest`. + + +.. decorator:: requires_linux_version(*min_version) + + Decorator for the minimum version when running test on Linux. If the + Linux version is less than the minimum, raise :exc:`unittest.SkipTest`. + + +.. decorator:: requires_mac_version(*min_version) + + Decorator for the minimum version when running test on Mac OS X. If the + MAC OS X version is less than the minimum, raise :exc:`unittest.SkipTest`. + + +.. decorator:: requires_IEEE_754 + + Decorator for skipping tests on non-IEEE 754 platforms. + + +.. decorator:: requires_zlib + + Decorator for skipping tests if :mod:`zlib` doesn't exist. + + +.. decorator:: requires_gzip + + Decorator for skipping tests if :mod:`gzip` doesn't exist. + + +.. decorator:: requires_bz2 + + Decorator for skipping tests if :mod:`bz2` doesn't exist. + + +.. decorator:: requires_lzma + + Decorator for skipping tests if :mod:`lzma` doesn't exist. + + +.. decorator:: requires_resource(resource) + + Decorator for skipping tests if *resource* is not available. + + +.. decorator:: requires_docstrings + + Decorator for only running the test if :data:`HAVE_DOCSTRINGS`. + + +.. decorator:: cpython_only(test) + + Decorator for tests only applicable to CPython. + + +.. decorator:: impl_detail(msg=None, **guards) + + Decorator for invoking :func:`check_impl_detail` on *guards*. If that + returns ``False``, then uses *msg* as the reason for skipping the test. + + +.. decorator:: no_tracing(func) + + Decorator to temporarily turn off tracing for the duration of the test. + + +.. decorator:: refcount_test(test) + + Decorator for tests which involve reference counting. The decorator does + not run the test if it is not run by CPython. Any trace function is unset + for the duration of the test to prevent unexpected refcounts caused by + the trace function. + + +.. decorator:: reap_threads(func) + + Decorator to ensure the threads are cleaned up even if the test fails. + + +.. decorator:: bigmemtest(size, memuse, dry_run=True) + + Decorator for bigmem tests. + + *size* is a requested size for the test (in arbitrary, test-interpreted + units.) *memuse* is the number of bytes per unit for the test, or a good + estimate of it. For example, a test that needs two byte buffers, of 4 GiB + each, could be decorated with ``@bigmemtest(size=_4G, memuse=2)``. + + The *size* argument is normally passed to the decorated test method as an + extra argument. If *dry_run* is ``True``, the value passed to the test + method may be less than the requested value. If *dry_run* is ``False``, it + means the test doesn't support dummy runs when ``-M`` is not specified. + + +.. decorator:: bigaddrspacetest(f) + + Decorator for tests that fill the address space. *f* is the function to + wrap. + + .. function:: make_bad_fd() Create an invalid file descriptor by opening and closing a temporary file, and returning its descriptor. -.. function:: import_module(name, deprecated=False) +.. function:: check_syntax_error(testcase, statement, errtext='', *, lineno=None, offset=None) + + Test for syntax errors in *statement* by attempting to compile *statement*. + *testcase* is the :mod:`unittest` instance for the test. *errtext* is the + text of the error raised by :exc:`SyntaxError`. If *lineno* is not None, + compares to the line of the :exc:`SyntaxError`. If *offset* is not None, + compares to the offset of the :exc:`SyntaxError`. + + +.. function:: open_urlresource(url, *args, **kw) + + Open *url*. If open fails, raises :exc:`TestFailed`. + + +.. function:: import_module(name, deprecated=False, *, required_on()) This function imports and returns the named module. Unlike a normal import, this function raises :exc:`unittest.SkipTest` if the module cannot be imported. Module and package deprecation messages are suppressed during this import - if *deprecated* is ``True``. + if *deprecated* is ``True``. If a module is required on a platform but + optional for others, set *required_on* to an iterable of platform prefixes + which will be compared against :data:`sys.platform`. .. versionadded:: 3.1 @@ -514,6 +996,47 @@ The :mod:`test.support` module defines the following functions: .. versionadded:: 3.1 +.. function:: modules_setup() + + Return a copy of :data:`sys.modules`. + + +.. function:: modules_cleanup(oldmodules) + + Remove modules except for *oldmodules* and ``encodings`` in order to + preserve internal cache. + + +.. function:: threading_setup() + + Return current thread count and copy of dangling threads. + + +.. function:: threading_cleanup(*original_values) + + Cleanup up threads not specified in *original_values*. Designed to emit + a warning if a test leaves running threads in the background. + + +.. function:: join_thread(thread, timeout=30.0) + + Join a *thread* within *timeout*. Raise an :exc:`AssertionError` if thread + is still alive after *timeout* seconds. + + +.. function:: reap_children() + + Use this at the end of ``test_main`` whenever sub-processes are started. + This will help ensure that no extra children (zombies) stick around to + hog resources and create problems when looking for refleaks. + + +.. function:: get_attribute(obj, name) + + Get an attribute, raising :exc:`unittest.SkipTest` if :exc:`AttributeError` + is raised. + + .. function:: bind_port(sock, host=HOST) Bind the socket to a free port and return the port number. Relies on @@ -533,6 +1056,12 @@ The :mod:`test.support` module defines the following functions: test. +.. function:: bind_unix_socket(sock, addr) + + Bind a unix socket, raising :exc:`unittest.SkipTest` if + :exc:`PermissionError` is raised. + + .. function:: find_unused_port(family=socket.AF_INET, socktype=socket.SOCK_STREAM) Returns an unused port that should be suitable for binding. This is @@ -571,6 +1100,11 @@ The :mod:`test.support` module defines the following functions: return load_package_tests(os.path.dirname(__file__), *args) +.. function:: fs_is_case_insensitive(directory) + + Return ``True`` if the file system for *directory* is case-insensitive. + + .. function:: detect_api_mismatch(ref_api, other_api, *, ignore=()) Returns the set of attributes, functions or methods of *ref_api* not @@ -583,6 +1117,33 @@ The :mod:`test.support` module defines the following functions: .. versionadded:: 3.5 +.. function:: patch(test_instance, object_to_patch, attr_name, new_value) + + Override *object_to_patch.attr_name* with *new_value*. Also add + cleanup procedure to *test_instance* to restore *object_to_patch* for + *attr_name*. The *attr_name* should be a valid attribute for + *object_to_patch*. + + +.. function:: run_in_subinterp(code) + + Run *code* in subinterpreter. Raise :exc:`unittest.SkipTest` if + :mod:`tracemalloc` is enabled. + + +.. function:: check_free_after_iterating(test, iter, cls, args=()) + + Assert that *iter* is deallocated after iterating. + + +.. function:: missing_compiler_executable(cmd_names=[]) + + Check for the existence of the compiler executables whose names are listed + in *cmd_names* or all the compiler executables when *cmd_names* is empty + and return the first missing executable or ``None`` when none is found + missing. + + .. function:: check__all__(test_case, module, name_of_module=None, extra=(), blacklist=()) Assert that the ``__all__`` variable of *module* contains all public names. @@ -673,7 +1234,162 @@ The :mod:`test.support` module defines the following classes: On both platforms, the old value is restored by :meth:`__exit__`. +.. class:: CleanImport(*module_names) + + A context manager to force import to return a new module reference. This + is useful for testing module-level behaviors, such as the emission of a + DeprecationWarning on import. Example usage:: + + with CleanImport('foo'): + importlib.import_module('foo') # New reference. + + +.. class:: DirsOnSysPath(*paths) + + A context manager to temporarily add directories to sys.path. + + This makes a copy of :data:`sys.path`, appends any directories given + as positional arguments, then reverts :data:`sys.path` to the copied + settings when the context ends. + + Note that *all* :data:`sys.path` modifications in the body of the + context manager, including replacement of the object, + will be reverted at the end of the block. + + +.. class:: SaveSignals() + + Class to save and restore signal handlers registered by the Python signal + handler. + + +.. class:: Matcher() + + .. method:: matches(self, d, **kwargs) + + Try to match a single dict with the supplied arguments. + + + .. method:: match_value(self, k, dv, v) + + Try to match a single stored value (*dv*) with a supplied value (*v*). + + .. class:: WarningsRecorder() Class used to record warnings for unit tests. See documentation of :func:`check_warnings` above for more details. + + +.. class:: BasicTestRunner() + + .. method:: run(test) + + Run *test* and return the result. + + +.. class:: TestHandler(logging.handlers.BufferingHandler) + + Class for logging support. + + +:mod:`test.support.script_helper` --- Utilities for the Python execution tests +============================================================================== + +.. module:: test.support.script_helper + :synopsis: Support for Python's script execution tests. + + +The :mod:`test.support.script_helper` module provides support for Python's +script execution tests. + +.. function:: interpreter_requires_environment() + + Return ``True`` if ``sys.executable interpreter`` requires environment + variables in order to be able to run at all. + + This is designed to be used with ``@unittest.skipIf()`` to annotate tests + that need to use an ``assert_python*()`` function to launch an isolated + mode (``-I``) or no environment mode (``-E``) sub-interpreter process. + + A normal build & test does not run into this situation but it can happen + when trying to run the standard library test suite from an interpreter that + doesn't have an obvious home with Python's current home finding logic. + + Setting :envvar:`PYTHONHOME` is one way to get most of the testsuite to run + in that situation. :envvar:`PYTHONPATH` or :envvar:`PYTHONUSERSITE` are + other common environment variables that might impact whether or not the + interpreter can start. + + +.. function:: run_python_until_end(*args, **env_vars) + + Set up the environment based on *env_vars* for running the interpreter + in a subprocess. The values can include ``__isolated``, ``__cleavenv``, + and ``TERM``. + + +.. function:: assert_python_ok(*args, **env_vars) + + Assert that running the interpreter with *args* and optional environment + variables *env_vars* succeeds (``rc == 0``) and return a ``(return code, + stdout, stderr)`` tuple. + + If the ``__cleanenv`` keyword is set, *env_vars* is used as a fresh + environment. + + Python is started in isolated mode (command line option ``-I``), + except if the ``__isolated`` keyword is set to ``False``. + + +.. function:: assert_python_failure(*args, **env_vars) + + Assert that running the interpreter with *args* and optional environment + variables *env_vars* fails (``rc != 0``) and return a ``(return code, + stdout, stderr)`` tuple. + + See :func:`assert_python_ok` for more options. + + +.. function:: spawn_python(*args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, **kw) + + Run a Python subprocess with the given arguments. + + *kw* is extra keyword args to pass to :func:`subprocess.Popen`. Returns a + :class:`subprocess.Popen` object. + + +.. function:: kill_python(p) + + Run the given :class:`subprocess.Popen` process until completion and return + stdout. + + +.. function:: make_script(script_dir, script_basename, source, omit_suffix=False) + + Create script containing *source* in path *script_dir* and *script_basename*. + If *omit_suffix* is ``False``, append ``.py`` to the name. Return the full + script path. + + +.. function:: make_zip_script(zip_dir, zip_basename, script_name, name_in_zip=None) + + Create zip file at *zip_dir* and *zip_basename* with extension ``zip`` which + contains the files in *script_name*. *name_in_zip* is the archive name. + Return a tuple containing ``(full path, full path of archive name)``. + + +.. function:: make_pkg(pkg_dir, init_source='') + + Create a directory named *pkg_dir* containing an ``__init__`` file with + *init_source* as its contents. + + +.. function:: make_zip_pkg(zip_dir, zip_basename, pkg_name, script_basename, \ + source, depth=1, compiled=False) + + Create a zip package directory with a path of *zip_dir* and *zip_basename* + containing an empty ``__init__`` file and a file *script_basename* + containing the *source*. If *compiled* is ``True``, both source files will + be compiled and added to the zip package. Return a tuple of the full zip + path and the archive name for the zip file. diff --git a/Misc/NEWS.d/next/Documentation/2018-02-10-12-48-38.bpo-11015.-gUf34.rst b/Misc/NEWS.d/next/Documentation/2018-02-10-12-48-38.bpo-11015.-gUf34.rst new file mode 100644 index 000000000000..73612dab69e5 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2018-02-10-12-48-38.bpo-11015.-gUf34.rst @@ -0,0 +1 @@ +Update :mod:`test.support` documentation. From webhook-mailer at python.org Sun Feb 11 11:00:14 2018 From: webhook-mailer at python.org (Raymond Hettinger) Date: Sun, 11 Feb 2018 16:00:14 -0000 Subject: [Python-checkins] Code beautification using f-strings (#5618) Message-ID: https://github.com/python/cpython/commit/136c8e07955392676680c8e29ab96017127b6672 commit: 136c8e07955392676680c8e29ab96017127b6672 branch: master author: Raymond Hettinger committer: GitHub date: 2018-02-11T08:00:11-08:00 summary: Code beautification using f-strings (#5618) files: M Lib/collections/__init__.py diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py index 9a753db71cae..3109054e20c1 100644 --- a/Lib/collections/__init__.py +++ b/Lib/collections/__init__.py @@ -933,8 +933,7 @@ def __bool__(self): @_recursive_repr() def __repr__(self): - return '{0.__class__.__name__}({1})'.format( - self, ', '.join(map(repr, self.maps))) + return f'{self.__class__.__name__}({", ".join(map(repr, self.maps))})' @classmethod def fromkeys(cls, iterable, *args): From webhook-mailer at python.org Sun Feb 11 11:34:30 2018 From: webhook-mailer at python.org (Nick Coghlan) Date: Sun, 11 Feb 2018 16:34:30 -0000 Subject: [Python-checkins] bpo-11015: Update test.support documentation (GH-5619) Message-ID: https://github.com/python/cpython/commit/a0b998df314370f00502efe7ad84206f5bb782ff commit: a0b998df314370f00502efe7ad84206f5bb782ff branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Nick Coghlan date: 2018-02-12T02:34:28+10:00 summary: bpo-11015: Update test.support documentation (GH-5619) (cherry picked from commit 988fb28431d3a3fc5dc6eb657c8a4baacc04d9ce) Co-authored-by: Cheryl Sabella files: A Misc/NEWS.d/next/Documentation/2018-02-10-12-48-38.bpo-11015.-gUf34.rst M Doc/library/test.rst diff --git a/Doc/library/test.rst b/Doc/library/test.rst index 01ba1ec7062c..a366fe2556b5 100644 --- a/Doc/library/test.rst +++ b/Doc/library/test.rst @@ -237,12 +237,127 @@ The :mod:`test.support` module defines the following constants: ``True`` if the running interpreter is Jython. +.. data:: is_android + + ``True`` if the system is Android. + + +.. data:: unix_shell + + Path for shell if not on Windows; otherwise ``None``. + + +.. data:: FS_NONASCII + + A non-ASCII character encodable by :func:`os.fsencode`. + + .. data:: TESTFN Set to a name that is safe to use as the name of a temporary file. Any temporary file that is created should be closed and unlinked (removed). +.. data:: TESTFN_UNICODE + + Set to a non-ASCII name for a temporary file. + + +.. data:: TESTFN_ENCODING + + Set to :func:`sys.getfilesystemencoding`. + + +.. data:: TESTFN_UNENCODABLE + + Set to a filename (str type) that should not be able to be encoded by file + system encoding in strict mode. It may be ``None`` if it's not possible to + generate such a filename. + + +.. data:: TESTFN_UNDECODABLE + + Set to a filename (bytes type) that should not be able to be decoded by + file system encoding in strict mode. It may be ``None`` if it's not + possible to generate such a filename. + + +.. data:: TESTFN_NONASCII + + Set to a filename containing the :data:`FS_NONASCII` character. + + +.. data:: IPV6_ENABLED + + Set to ``True`` if IPV6 is enabled on this host, ``False`` otherwise. + + +.. data:: SAVEDCWD + + Set to :func:`os.getcwd`. + + +.. data:: PGO + + Set when tests can be skipped when they are not useful for PGO. + + +.. data:: PIPE_MAX_SIZE + + A constant that is likely larger than the underlying OS pipe buffer size, + to make writes blocking. + + +.. data:: SOCK_MAX_SIZE + + A constant that is likely larger than the underlying OS socket buffer size, + to make writes blocking. + + +.. data:: TEST_SUPPORT_DIR + + Set to the top level directory that contains :mod:`test.support`. + + +.. data:: TEST_HOME_DIR + + Set to the top level directory for the test package. + + +.. data:: TEST_DATA_DIR + + Set to the ``data`` directory within the test package. + + +.. data:: MAX_Py_ssize_t + + Set to :data:`sys.maxsize` for big memory tests. + + +.. data:: max_memuse + + Set by :func:`set_memlimit` as the memory limit for big memory tests. + Limited by :data:`MAX_Py_ssize_t`. + + +.. data:: real_max_memuse + + Set by :func:`set_memlimit` as the memory limit for big memory tests. Not + limited by :data:`MAX_Py_ssize_t`. + + +.. data:: MISSING_C_DOCSTRINGS + + Return ``True`` if running on CPython, not on Windows, and configuration + not set with ``WITH_DOC_STRINGS``. + + +.. data:: HAVE_DOCSTRINGS + + Check for presence of docstrings. + + + The :mod:`test.support` module defines the following functions: .. function:: forget(module_name) @@ -251,6 +366,38 @@ The :mod:`test.support` module defines the following functions: byte-compiled files of the module. +.. function:: unload(name) + + Delete *name* from ``sys.modules``. + + +.. function:: unlink(filename) + + Call :func:`os.unlink` on *filename*. On Windows platforms, this is + wrapped with a wait loop that checks for the existence fo the file. + + +.. function:: rmdir(filename) + + Call :func:`os.rmdir` on *filename*. On Windows platforms, this is + wrapped with a wait loop that checks for the existence of the file. + + +.. function:: rmtree(path) + + Call :func:`shutil.rmtree` on *path* or call :func:`os.lstat` and + :func:`os.rmdir` to remove a path and its contents. On Windows platforms, + this is wrapped with a wait loop that checks for the existence of the files. + + +.. function:: make_legacy_pyc(source) + + Move a PEP 3147/488 pyc file to its legacy pyc location and return the file + system path to the legacy pyc file. The *source* value is the file system + path to the source file. It does not need to exist, however the PEP + 3147/488 pyc file must exist. + + .. function:: is_resource_enabled(resource) Return ``True`` if *resource* is enabled and available. The list of @@ -258,6 +405,16 @@ The :mod:`test.support` module defines the following functions: tests. +.. function:: python_is_optimized() + + Return ``True`` if Python was not built with ``-O0`` or ``-Og``. + + +.. function:: with_pymalloc() + + Return :data:`_testcapi.WITH_PYMALLOC`. + + .. function:: requires(resource, msg=None) Raise :exc:`ResourceDenied` if *resource* is not available. *msg* is the @@ -266,14 +423,44 @@ The :mod:`test.support` module defines the following functions: Used when tests are executed by :mod:`test.regrtest`. +.. function:: system_must_validate_cert(f) + + Raise :exc:`unittest.SkipTest` on TLS certification validation failures. + + +.. function:: sortdict(dict) + + Return a repr of *dict* with keys sorted. + + .. function:: findfile(filename, subdir=None) Return the path to the file named *filename*. If no match is found *filename* is returned. This does not equal a failure since it could be the path to the file. - Setting *subdir* indicates a relative path to use to find the file - rather than looking directly in the path directories. + Setting *subdir* indicates a relative path to use to find the file + rather than looking directly in the path directories. + + +.. function:: create_empty_file(filename) + + Create an empty file with *filename*. If it already exists, truncate it. + + +.. function:: fd_count() + + Count the number of open file descriptors. + + +.. function:: match_test(test) + + Match *test* to patterns set in :func:`set_match_tests`. + + +.. function:: set_match_tests(patterns) + + Define match test with regular expression *patterns*. .. function:: run_unittest(\*classes) @@ -293,14 +480,32 @@ The :mod:`test.support` module defines the following functions: This will run all tests defined in the named module. -.. function:: run_doctest(module, verbosity=None) +.. function:: run_doctest(module, verbosity=None, optionflags=0) Run :func:`doctest.testmod` on the given *module*. Return ``(failure_count, test_count)``. If *verbosity* is ``None``, :func:`doctest.testmod` is run with verbosity set to :data:`verbose`. Otherwise, it is run with verbosity set to - ``None``. + ``None``. *optionflags* is passed as ``optionflags`` to + :func:`doctest.testmod`. + + +.. function:: setswitchinterval(interval) + + Set the :func:`sys.setswitchinterval` to the given *interval*. Defines + a minimum interval for Android systems to prevent the system from hanging. + + +.. function:: check_impl_detail(**guards) + + Use this check to guard CPython's implementation-specific tests or to + run them only on the implementations guarded by the arguments:: + + check_impl_detail() # Only on CPython (default). + check_impl_detail(jython=True) # Only on Jython. + check_impl_detail(cpython=False) # Everywhere except CPython. + .. function:: check_warnings(\*filters, quiet=True) @@ -368,6 +573,50 @@ The :mod:`test.support` module defines the following functions: New optional arguments *filters* and *quiet*. +.. function:: check_no_resource_warning(testcase) + + Context manager to check that no :exc:`ResourceWarning` was raised. You + must remove the object which may emit :exc:`ResourceWarning` before the + end of the context manager. + + +.. function:: set_memlimit(limit) + + Set the values for :data:`max_memuse` and :data:`real_max_memuse` for big + memory tests. + + +.. function:: record_original_stdout(stdout) + + Store the value from *stdout*. It is meant to hold the stdout at the + time the regrtest began. + + +.. function:: get_original_stdout + + Return the original stdout set by :func:`record_original_stdout` or + ``sys.stdout`` if it's not set. + + +.. function:: strip_python_strerr(stderr) + + Strip the *stderr* of a Python process from potential debug output + emitted by the interpreter. This will typically be run on the result of + :meth:`subprocess.Popen.communicate`. + + +.. function:: args_from_interpreter_flags() + + Return a list of command line arguments reproducing the current settings + in ``sys.flags`` and ``sys.warnoptions``. + + +.. function:: optim_args_from_interpreter_flags() + + Return a list of command line arguments reproducing the current + optimization settings in ``sys.flags``. + + .. function:: captured_stdin() captured_stdout() captured_stderr() @@ -434,17 +683,125 @@ The :mod:`test.support` module defines the following functions: A context manager that temporarily sets the process umask. +.. function:: transient_internet(resource_name, *, timeout=30.0, errnos=()) + + A context manager that raises :exc:`ResourceDenied` when various issues + with the internet connection manifest themselves as exceptions. + + +.. function:: disable_faulthandler() + + A context manager that replaces ``sys.stderr`` with ``sys.__stderr__``. + + +.. function:: gc_collect() + + Force as many objects as possible to be collected. This is needed because + timely deallocation is not guaranteed by the garbage collector. This means + that ``__del__`` methods may be called later than expected and weakrefs + may remain alive for longer than expected. + + +.. function:: disable_gc() + + A context manager that disables the garbage collector upon entry and + reenables it upon exit. + + +.. function:: swap_attr(obj, attr, new_val) + + Context manager to swap out an attribute with a new object. + + Usage:: + + with swap_attr(obj, "attr", 5): + ... + + This will set ``obj.attr`` to 5 for the duration of the ``with`` block, + restoring the old value at the end of the block. If ``attr`` doesn't + exist on ``obj``, it will be created and then deleted at the end of the + block. + + The old value (or ``None`` if it doesn't exist) will be assigned to the + target of the "as" clause, if there is one. + + +.. function:: swap_item(obj, attr, new_val) + + Context manager to swap out an item with a new object. + + Usage:: + + with swap_item(obj, "item", 5): + ... + + This will set ``obj["item"]`` to 5 for the duration of the ``with`` block, + restoring the old value at the end of the block. If ``item`` doesn't + exist on ``obj``, it will be created and then deleted at the end of the + block. + + The old value (or ``None`` if it doesn't exist) will be assigned to the + target of the "as" clause, if there is one. + + +.. function:: wait_threads_exit(timeout=60.0) + + Context manager to wait until all threads created in the ``with`` statment + exit. + + +.. function:: start_threads(threads, unlock=None) + + Context manager to start *threads*. It attempts to join the threads upon + exit. + + +.. function:: calcobjsize(fmt) + + Return :func:`struct.calcsize` for ``nP{fmt}0n`` or, if ``gettotalrefcount`` + exists, ``2PnP{fmt}0P``. + + +.. function:: calcvobjsize(fmt) + + Return :func:`struct.calcsize` for ``nPn{fmt}0n`` or, if ``gettotalrefcount`` + exists, ``2PnPn{fmt}0P``. + + +.. function:: checksizeof(test, o, size) + + For testcase *test*, assert that the ``sys.getsizeof`` for *o* plus the GC + header size equals *size*. + + .. function:: can_symlink() Return ``True`` if the OS supports symbolic links, ``False`` otherwise. +.. function:: can_xattr() + + Return ``True`` if the OS supports xattr, ``False`` + otherwise. + + .. decorator:: skip_unless_symlink A decorator for running tests that require support for symbolic links. +.. decorator:: skip_unless_xattr + + A decorator for running tests that require support for xattr. + + +.. decorator:: skip_unless_bind_unix_socket + + A decorator for running tests that require a functional bind() for Unix + sockets. + + .. decorator:: anticipate_failure(condition) A decorator to conditionally mark tests with @@ -460,20 +817,145 @@ The :mod:`test.support` module defines the following functions: sequentially, and the first valid locale will be used. +.. decorator:: run_with_tz(tz) + + A decorator for running a function in a specific timezone, correctly + resetting it after it has finished. + + +.. decorator:: requires_freebsd_version(*min_version) + + Decorator for the minimum version when running test on FreeBSD. If the + FreeBSD version is less than the minimum, raise :exc:`unittest.SkipTest`. + + +.. decorator:: requires_linux_version(*min_version) + + Decorator for the minimum version when running test on Linux. If the + Linux version is less than the minimum, raise :exc:`unittest.SkipTest`. + + +.. decorator:: requires_mac_version(*min_version) + + Decorator for the minimum version when running test on Mac OS X. If the + MAC OS X version is less than the minimum, raise :exc:`unittest.SkipTest`. + + +.. decorator:: requires_IEEE_754 + + Decorator for skipping tests on non-IEEE 754 platforms. + + +.. decorator:: requires_zlib + + Decorator for skipping tests if :mod:`zlib` doesn't exist. + + +.. decorator:: requires_gzip + + Decorator for skipping tests if :mod:`gzip` doesn't exist. + + +.. decorator:: requires_bz2 + + Decorator for skipping tests if :mod:`bz2` doesn't exist. + + +.. decorator:: requires_lzma + + Decorator for skipping tests if :mod:`lzma` doesn't exist. + + +.. decorator:: requires_resource(resource) + + Decorator for skipping tests if *resource* is not available. + + +.. decorator:: requires_docstrings + + Decorator for only running the test if :data:`HAVE_DOCSTRINGS`. + + +.. decorator:: cpython_only(test) + + Decorator for tests only applicable to CPython. + + +.. decorator:: impl_detail(msg=None, **guards) + + Decorator for invoking :func:`check_impl_detail` on *guards*. If that + returns ``False``, then uses *msg* as the reason for skipping the test. + + +.. decorator:: no_tracing(func) + + Decorator to temporarily turn off tracing for the duration of the test. + + +.. decorator:: refcount_test(test) + + Decorator for tests which involve reference counting. The decorator does + not run the test if it is not run by CPython. Any trace function is unset + for the duration of the test to prevent unexpected refcounts caused by + the trace function. + + +.. decorator:: reap_threads(func) + + Decorator to ensure the threads are cleaned up even if the test fails. + + +.. decorator:: bigmemtest(size, memuse, dry_run=True) + + Decorator for bigmem tests. + + *size* is a requested size for the test (in arbitrary, test-interpreted + units.) *memuse* is the number of bytes per unit for the test, or a good + estimate of it. For example, a test that needs two byte buffers, of 4 GiB + each, could be decorated with ``@bigmemtest(size=_4G, memuse=2)``. + + The *size* argument is normally passed to the decorated test method as an + extra argument. If *dry_run* is ``True``, the value passed to the test + method may be less than the requested value. If *dry_run* is ``False``, it + means the test doesn't support dummy runs when ``-M`` is not specified. + + +.. decorator:: bigaddrspacetest(f) + + Decorator for tests that fill the address space. *f* is the function to + wrap. + + .. function:: make_bad_fd() Create an invalid file descriptor by opening and closing a temporary file, and returning its descriptor. -.. function:: import_module(name, deprecated=False) +.. function:: check_syntax_error(testcase, statement, errtext='', *, lineno=None, offset=None) + + Test for syntax errors in *statement* by attempting to compile *statement*. + *testcase* is the :mod:`unittest` instance for the test. *errtext* is the + text of the error raised by :exc:`SyntaxError`. If *lineno* is not None, + compares to the line of the :exc:`SyntaxError`. If *offset* is not None, + compares to the offset of the :exc:`SyntaxError`. + + +.. function:: open_urlresource(url, *args, **kw) + + Open *url*. If open fails, raises :exc:`TestFailed`. + + +.. function:: import_module(name, deprecated=False, *, required_on()) This function imports and returns the named module. Unlike a normal import, this function raises :exc:`unittest.SkipTest` if the module cannot be imported. Module and package deprecation messages are suppressed during this import - if *deprecated* is ``True``. + if *deprecated* is ``True``. If a module is required on a platform but + optional for others, set *required_on* to an iterable of platform prefixes + which will be compared against :data:`sys.platform`. .. versionadded:: 3.1 @@ -514,6 +996,47 @@ The :mod:`test.support` module defines the following functions: .. versionadded:: 3.1 +.. function:: modules_setup() + + Return a copy of :data:`sys.modules`. + + +.. function:: modules_cleanup(oldmodules) + + Remove modules except for *oldmodules* and ``encodings`` in order to + preserve internal cache. + + +.. function:: threading_setup() + + Return current thread count and copy of dangling threads. + + +.. function:: threading_cleanup(*original_values) + + Cleanup up threads not specified in *original_values*. Designed to emit + a warning if a test leaves running threads in the background. + + +.. function:: join_thread(thread, timeout=30.0) + + Join a *thread* within *timeout*. Raise an :exc:`AssertionError` if thread + is still alive after *timeout* seconds. + + +.. function:: reap_children() + + Use this at the end of ``test_main`` whenever sub-processes are started. + This will help ensure that no extra children (zombies) stick around to + hog resources and create problems when looking for refleaks. + + +.. function:: get_attribute(obj, name) + + Get an attribute, raising :exc:`unittest.SkipTest` if :exc:`AttributeError` + is raised. + + .. function:: bind_port(sock, host=HOST) Bind the socket to a free port and return the port number. Relies on @@ -533,6 +1056,12 @@ The :mod:`test.support` module defines the following functions: test. +.. function:: bind_unix_socket(sock, addr) + + Bind a unix socket, raising :exc:`unittest.SkipTest` if + :exc:`PermissionError` is raised. + + .. function:: find_unused_port(family=socket.AF_INET, socktype=socket.SOCK_STREAM) Returns an unused port that should be suitable for binding. This is @@ -571,6 +1100,11 @@ The :mod:`test.support` module defines the following functions: return load_package_tests(os.path.dirname(__file__), *args) +.. function:: fs_is_case_insensitive(directory) + + Return ``True`` if the file system for *directory* is case-insensitive. + + .. function:: detect_api_mismatch(ref_api, other_api, *, ignore=()) Returns the set of attributes, functions or methods of *ref_api* not @@ -583,6 +1117,33 @@ The :mod:`test.support` module defines the following functions: .. versionadded:: 3.5 +.. function:: patch(test_instance, object_to_patch, attr_name, new_value) + + Override *object_to_patch.attr_name* with *new_value*. Also add + cleanup procedure to *test_instance* to restore *object_to_patch* for + *attr_name*. The *attr_name* should be a valid attribute for + *object_to_patch*. + + +.. function:: run_in_subinterp(code) + + Run *code* in subinterpreter. Raise :exc:`unittest.SkipTest` if + :mod:`tracemalloc` is enabled. + + +.. function:: check_free_after_iterating(test, iter, cls, args=()) + + Assert that *iter* is deallocated after iterating. + + +.. function:: missing_compiler_executable(cmd_names=[]) + + Check for the existence of the compiler executables whose names are listed + in *cmd_names* or all the compiler executables when *cmd_names* is empty + and return the first missing executable or ``None`` when none is found + missing. + + .. function:: check__all__(test_case, module, name_of_module=None, extra=(), blacklist=()) Assert that the ``__all__`` variable of *module* contains all public names. @@ -673,7 +1234,162 @@ The :mod:`test.support` module defines the following classes: On both platforms, the old value is restored by :meth:`__exit__`. +.. class:: CleanImport(*module_names) + + A context manager to force import to return a new module reference. This + is useful for testing module-level behaviors, such as the emission of a + DeprecationWarning on import. Example usage:: + + with CleanImport('foo'): + importlib.import_module('foo') # New reference. + + +.. class:: DirsOnSysPath(*paths) + + A context manager to temporarily add directories to sys.path. + + This makes a copy of :data:`sys.path`, appends any directories given + as positional arguments, then reverts :data:`sys.path` to the copied + settings when the context ends. + + Note that *all* :data:`sys.path` modifications in the body of the + context manager, including replacement of the object, + will be reverted at the end of the block. + + +.. class:: SaveSignals() + + Class to save and restore signal handlers registered by the Python signal + handler. + + +.. class:: Matcher() + + .. method:: matches(self, d, **kwargs) + + Try to match a single dict with the supplied arguments. + + + .. method:: match_value(self, k, dv, v) + + Try to match a single stored value (*dv*) with a supplied value (*v*). + + .. class:: WarningsRecorder() Class used to record warnings for unit tests. See documentation of :func:`check_warnings` above for more details. + + +.. class:: BasicTestRunner() + + .. method:: run(test) + + Run *test* and return the result. + + +.. class:: TestHandler(logging.handlers.BufferingHandler) + + Class for logging support. + + +:mod:`test.support.script_helper` --- Utilities for the Python execution tests +============================================================================== + +.. module:: test.support.script_helper + :synopsis: Support for Python's script execution tests. + + +The :mod:`test.support.script_helper` module provides support for Python's +script execution tests. + +.. function:: interpreter_requires_environment() + + Return ``True`` if ``sys.executable interpreter`` requires environment + variables in order to be able to run at all. + + This is designed to be used with ``@unittest.skipIf()`` to annotate tests + that need to use an ``assert_python*()`` function to launch an isolated + mode (``-I``) or no environment mode (``-E``) sub-interpreter process. + + A normal build & test does not run into this situation but it can happen + when trying to run the standard library test suite from an interpreter that + doesn't have an obvious home with Python's current home finding logic. + + Setting :envvar:`PYTHONHOME` is one way to get most of the testsuite to run + in that situation. :envvar:`PYTHONPATH` or :envvar:`PYTHONUSERSITE` are + other common environment variables that might impact whether or not the + interpreter can start. + + +.. function:: run_python_until_end(*args, **env_vars) + + Set up the environment based on *env_vars* for running the interpreter + in a subprocess. The values can include ``__isolated``, ``__cleavenv``, + and ``TERM``. + + +.. function:: assert_python_ok(*args, **env_vars) + + Assert that running the interpreter with *args* and optional environment + variables *env_vars* succeeds (``rc == 0``) and return a ``(return code, + stdout, stderr)`` tuple. + + If the ``__cleanenv`` keyword is set, *env_vars* is used as a fresh + environment. + + Python is started in isolated mode (command line option ``-I``), + except if the ``__isolated`` keyword is set to ``False``. + + +.. function:: assert_python_failure(*args, **env_vars) + + Assert that running the interpreter with *args* and optional environment + variables *env_vars* fails (``rc != 0``) and return a ``(return code, + stdout, stderr)`` tuple. + + See :func:`assert_python_ok` for more options. + + +.. function:: spawn_python(*args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, **kw) + + Run a Python subprocess with the given arguments. + + *kw* is extra keyword args to pass to :func:`subprocess.Popen`. Returns a + :class:`subprocess.Popen` object. + + +.. function:: kill_python(p) + + Run the given :class:`subprocess.Popen` process until completion and return + stdout. + + +.. function:: make_script(script_dir, script_basename, source, omit_suffix=False) + + Create script containing *source* in path *script_dir* and *script_basename*. + If *omit_suffix* is ``False``, append ``.py`` to the name. Return the full + script path. + + +.. function:: make_zip_script(zip_dir, zip_basename, script_name, name_in_zip=None) + + Create zip file at *zip_dir* and *zip_basename* with extension ``zip`` which + contains the files in *script_name*. *name_in_zip* is the archive name. + Return a tuple containing ``(full path, full path of archive name)``. + + +.. function:: make_pkg(pkg_dir, init_source='') + + Create a directory named *pkg_dir* containing an ``__init__`` file with + *init_source* as its contents. + + +.. function:: make_zip_pkg(zip_dir, zip_basename, pkg_name, script_basename, \ + source, depth=1, compiled=False) + + Create a zip package directory with a path of *zip_dir* and *zip_basename* + containing an empty ``__init__`` file and a file *script_basename* + containing the *source*. If *compiled* is ``True``, both source files will + be compiled and added to the zip package. Return a tuple of the full zip + path and the archive name for the zip file. diff --git a/Misc/NEWS.d/next/Documentation/2018-02-10-12-48-38.bpo-11015.-gUf34.rst b/Misc/NEWS.d/next/Documentation/2018-02-10-12-48-38.bpo-11015.-gUf34.rst new file mode 100644 index 000000000000..73612dab69e5 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2018-02-10-12-48-38.bpo-11015.-gUf34.rst @@ -0,0 +1 @@ +Update :mod:`test.support` documentation. From webhook-mailer at python.org Sun Feb 11 11:43:51 2018 From: webhook-mailer at python.org (Zachary Ware) Date: Sun, 11 Feb 2018 16:43:51 -0000 Subject: [Python-checkins] bpo-32604: Make _xxsubinterpreters build on Windows (GH-5516) Message-ID: https://github.com/python/cpython/commit/310b05289b5d9550040f469e60b5e8e77f1022b6 commit: 310b05289b5d9550040f469e60b5e8e77f1022b6 branch: master author: Zachary Ware committer: GitHub date: 2018-02-11T10:43:48-06:00 summary: bpo-32604: Make _xxsubinterpreters build on Windows (GH-5516) This is not the ideal solution; this means that a test module is now always included in the main python3x.dll. However, we're already including xxsubtype, so why not? files: M PC/config.c M PCbuild/pythoncore.vcxproj diff --git a/PC/config.c b/PC/config.c index 6209d7e284f3..0c08bfeaa0dc 100644 --- a/PC/config.c +++ b/PC/config.c @@ -31,7 +31,9 @@ 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. */ 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); @@ -126,6 +128,7 @@ 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 f30945508698..bf4131e91b0a 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -279,6 +279,7 @@ + From webhook-mailer at python.org Sun Feb 11 12:16:07 2018 From: webhook-mailer at python.org (Zachary Ware) Date: Sun, 11 Feb 2018 17:16:07 -0000 Subject: [Python-checkins] bpo-32604: Make _xxsubinterpreters build on Windows (GH-5624) Message-ID: https://github.com/python/cpython/commit/fe61e8d8c7cd1f6fb0ce7e9b8f0460b47b5f29a5 commit: fe61e8d8c7cd1f6fb0ce7e9b8f0460b47b5f29a5 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Zachary Ware date: 2018-02-11T11:16:04-06:00 summary: bpo-32604: Make _xxsubinterpreters build on Windows (GH-5624) This is not the ideal solution; this means that a test module is now always included in the main python3x.dll. However, we're already including xxsubtype, so why not? (cherry picked from commit 310b05289b5d9550040f469e60b5e8e77f1022b6) Co-authored-by: Zachary Ware files: M PC/config.c M PCbuild/pythoncore.vcxproj diff --git a/PC/config.c b/PC/config.c index 6209d7e284f3..0c08bfeaa0dc 100644 --- a/PC/config.c +++ b/PC/config.c @@ -31,7 +31,9 @@ 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. */ 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); @@ -126,6 +128,7 @@ 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 f30945508698..bf4131e91b0a 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -279,6 +279,7 @@ + From webhook-mailer at python.org Sun Feb 11 12:19:54 2018 From: webhook-mailer at python.org (Zachary Ware) Date: Sun, 11 Feb 2018 17:19:54 -0000 Subject: [Python-checkins] Add short-circuit for doc changes to AppVeyor (GH-5519) Message-ID: https://github.com/python/cpython/commit/28607e0dd9417ce44a109980ffd60697c1afdea0 commit: 28607e0dd9417ce44a109980ffd60697c1afdea0 branch: master author: Zachary Ware committer: GitHub date: 2018-02-11T11:19:51-06:00 summary: Add short-circuit for doc changes to AppVeyor (GH-5519) files: M .github/appveyor.yml diff --git a/.github/appveyor.yml b/.github/appveyor.yml index 129c119df61f..5239d6ccc17c 100644 --- a/.github/appveyor.yml +++ b/.github/appveyor.yml @@ -7,11 +7,27 @@ branches: - buildbot-custom cache: - externals -> PCbuild +before_build: + - ps: |+ + if ($env:APPVEYOR_RE_BUILD) { + echo 'Doing full build due to re-build request.' + } elseif (!$env:APPVEYOR_PULL_REQUEST_HEAD_COMMIT) { + echo 'Not a PR, doing full build.' + } else { + $mergebase = git merge-base $env:APPVEYOR_PULL_REQUEST_HEAD_COMMIT $env:APPVEYOR_REPO_BRANCH + $changes = git diff --name-only HEAD $mergebase | grep -vE '(\.rst$)|(^Doc)|(^Misc)' + If (!$changes) { + echo 'Only docs were updated, stopping build process.' + Exit-AppveyorBuild + } + } + + build_script: -- cmd: PCbuild\build.bat -e -- cmd: PCbuild\win32\python.exe -m test.pythoninfo + - cmd: PCbuild\build.bat -e + - cmd: PCbuild\win32\python.exe -m test.pythoninfo test_script: -- cmd: PCbuild\rt.bat -q -uall -u-cpu -rwW --slowest --timeout=1200 --fail-env-changed -j0 + - cmd: PCbuild\rt.bat -q -uall -u-cpu -rwW --slowest --timeout=1200 --fail-env-changed -j0 environment: HOST_PYTHON: C:\Python36\python.exe image: From webhook-mailer at python.org Sun Feb 11 12:55:35 2018 From: webhook-mailer at python.org (Zachary Ware) Date: Sun, 11 Feb 2018 17:55:35 -0000 Subject: [Python-checkins] [3.7] Add short-circuit for doc changes to AppVeyor (GH-5626) Message-ID: https://github.com/python/cpython/commit/40f7d9a06e7c2034714f71bb2ecd77d6499fbf62 commit: 40f7d9a06e7c2034714f71bb2ecd77d6499fbf62 branch: 3.7 author: Zachary Ware committer: GitHub date: 2018-02-11T11:55:32-06:00 summary: [3.7] Add short-circuit for doc changes to AppVeyor (GH-5626) (cherry picked from commit 28607e0dd9417ce44a109980ffd60697c1afdea0) files: M .github/appveyor.yml diff --git a/.github/appveyor.yml b/.github/appveyor.yml index b7d407873189..a4c11df2795e 100644 --- a/.github/appveyor.yml +++ b/.github/appveyor.yml @@ -7,11 +7,27 @@ branches: - buildbot-custom cache: - externals -> PCbuild\* +before_build: + - ps: |+ + if ($env:APPVEYOR_RE_BUILD) { + echo 'Doing full build due to re-build request.' + } elseif (!$env:APPVEYOR_PULL_REQUEST_HEAD_COMMIT) { + echo 'Not a PR, doing full build.' + } else { + $mergebase = git merge-base $env:APPVEYOR_PULL_REQUEST_HEAD_COMMIT $env:APPVEYOR_REPO_BRANCH + $changes = git diff --name-only HEAD $mergebase | grep -vE '(\.rst$)|(^Doc)|(^Misc)' + If (!$changes) { + echo 'Only docs were updated, stopping build process.' + Exit-AppveyorBuild + } + } + + build_script: -- cmd: PCbuild\build.bat -e -- cmd: PCbuild\win32\python.exe -m test.pythoninfo + - cmd: PCbuild\build.bat -e + - cmd: PCbuild\win32\python.exe -m test.pythoninfo test_script: -- cmd: PCbuild\rt.bat -q -uall -u-cpu -rwW --slowest --timeout=1200 --fail-env-changed -j0 + - cmd: PCbuild\rt.bat -q -uall -u-cpu -rwW --slowest --timeout=1200 --fail-env-changed -j0 environment: HOST_PYTHON: C:\Python36\python.exe image: From webhook-mailer at python.org Sun Feb 11 14:57:00 2018 From: webhook-mailer at python.org (Zachary Ware) Date: Sun, 11 Feb 2018 19:57:00 -0000 Subject: [Python-checkins] [3.6] Add short-circuit for doc changes to AppVeyor (GH-5628) Message-ID: https://github.com/python/cpython/commit/7574a1a8916639075dce3534aae8a54e977e06e9 commit: 7574a1a8916639075dce3534aae8a54e977e06e9 branch: 3.6 author: Zachary Ware committer: GitHub date: 2018-02-11T13:56:57-06:00 summary: [3.6] Add short-circuit for doc changes to AppVeyor (GH-5628) (cherry picked from commit 28607e0dd9417ce44a109980ffd60697c1afdea0) files: M .github/appveyor.yml diff --git a/.github/appveyor.yml b/.github/appveyor.yml index 162a7d8a701c..6e6a078a1032 100644 --- a/.github/appveyor.yml +++ b/.github/appveyor.yml @@ -7,13 +7,29 @@ branches: - buildbot-custom cache: - externals -> PCbuild\* +before_build: + - ps: |+ + if ($env:APPVEYOR_RE_BUILD) { + echo 'Doing full build due to re-build request.' + } elseif (!$env:APPVEYOR_PULL_REQUEST_HEAD_COMMIT) { + echo 'Not a PR, doing full build.' + } else { + $mergebase = git merge-base $env:APPVEYOR_PULL_REQUEST_HEAD_COMMIT $env:APPVEYOR_REPO_BRANCH + $changes = git diff --name-only HEAD $mergebase | grep -vE '(\.rst$)|(^Doc)|(^Misc)' + If (!$changes) { + echo 'Only docs were updated, stopping build process.' + Exit-AppveyorBuild + } + } + + build_script: -- cmd: PCbuild\build.bat -e -- cmd: PCbuild\win32\python.exe -m test.pythoninfo + - cmd: PCbuild\build.bat -e + - cmd: PCbuild\win32\python.exe -m test.pythoninfo test_script: -- cmd: PCbuild\rt.bat -q -uall -u-cpu -rwW --slowest --timeout=1200 -j0 + - cmd: PCbuild\rt.bat -q -uall -u-cpu -rwW --slowest --timeout=1200 -j0 environment: HOST_PYTHON: C:\Python36\python.exe image: -- Visual Studio 2015 -- Visual Studio 2017 + - Visual Studio 2015 + - Visual Studio 2017 From webhook-mailer at python.org Sun Feb 11 14:57:14 2018 From: webhook-mailer at python.org (Zachary Ware) Date: Sun, 11 Feb 2018 19:57:14 -0000 Subject: [Python-checkins] [2.7] Add short-circuit for doc changes to AppVeyor (GH-5629) Message-ID: https://github.com/python/cpython/commit/239e13b3b8af05fe860427c62982f390613086d5 commit: 239e13b3b8af05fe860427c62982f390613086d5 branch: 2.7 author: Zachary Ware committer: GitHub date: 2018-02-11T13:57:11-06:00 summary: [2.7] Add short-circuit for doc changes to AppVeyor (GH-5629) (cherry picked from commit 28607e0dd9417ce44a109980ffd60697c1afdea0) files: M .github/appveyor.yml diff --git a/.github/appveyor.yml b/.github/appveyor.yml index ddd5b15c5aa8..fa614dbf9b87 100644 --- a/.github/appveyor.yml +++ b/.github/appveyor.yml @@ -7,10 +7,26 @@ branches: - buildbot-custom cache: - externals -> PCbuild\* +before_build: + - ps: |+ + if ($env:APPVEYOR_RE_BUILD) { + echo 'Doing full build due to re-build request.' + } elseif (!$env:APPVEYOR_PULL_REQUEST_HEAD_COMMIT) { + echo 'Not a PR, doing full build.' + } else { + $mergebase = git merge-base $env:APPVEYOR_PULL_REQUEST_HEAD_COMMIT $env:APPVEYOR_REPO_BRANCH + $changes = git diff --name-only HEAD $mergebase | grep -vE '(\.rst$)|(^Doc)|(^Misc)' + If (!$changes) { + echo 'Only docs were updated, stopping build process.' + Exit-AppveyorBuild + } + } + + build_script: -- cmd: PCbuild\build.bat -e -- cmd: PCbuild\python.exe -m test.pythoninfo + - cmd: PCbuild\build.bat -e + - cmd: PCbuild\python.exe -m test.pythoninfo test_script: -- cmd: PCbuild\rt.bat -q -uall -u-cpu -rwW --slowest -j2 + - cmd: PCbuild\rt.bat -q -uall -u-cpu -rwW --slowest -j2 environment: HOST_PYTHON: C:\Python36\python.exe From webhook-mailer at python.org Sun Feb 11 15:58:25 2018 From: webhook-mailer at python.org (Gregory P. Smith) Date: Sun, 11 Feb 2018 20:58:25 -0000 Subject: [Python-checkins] bpo-32815: Improve docs on the subprocess API *text* parameter (GH-5622) Message-ID: https://github.com/python/cpython/commit/e14c01037877768a3fe766e50d14993bd5d8a67e commit: e14c01037877768a3fe766e50d14993bd5d8a67e branch: master author: Pablo Galindo committer: Gregory P. Smith date: 2018-02-11T12:58:23-08:00 summary: bpo-32815: Improve docs on the subprocess API *text* parameter (GH-5622) Describe *text* as an alias for *universal_newlines* in more places that people are likely to be referred to. files: M Doc/library/subprocess.rst diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst index 8673c4b18d8c..a22afe041850 100644 --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -39,7 +39,7 @@ compatibility with older versions, see the :ref:`call-function-trio` section. .. function:: run(args, *, stdin=None, input=None, stdout=None, stderr=None,\ shell=False, cwd=None, timeout=None, check=False, \ - encoding=None, errors=None) + encoding=None, errors=None, text=None) Run the command described by *args*. Wait for command to complete, then return a :class:`CompletedProcess` instance. @@ -267,7 +267,8 @@ default values. The arguments that are most commonly needed are: .. index:: single: universal newlines; subprocess module - If *encoding* or *errors* are specified, or *universal_newlines* is true, + If *encoding* or *errors* are specified, or *text* (also known as + *universal_newlines*) is true, the file objects *stdin*, *stdout* and *stderr* will be opened in text mode using the *encoding* and *errors* specified in the call or the defaults for :class:`io.TextIOWrapper`. @@ -284,6 +285,9 @@ default values. The arguments that are most commonly needed are: .. versionadded:: 3.6 Added *encoding* and *errors* parameters. + .. versionadded:: 3.7 + Added the *text* parameter as an alias for *universal_newlines*. + .. note:: The newlines attribute of the file objects :attr:`Popen.stdin`, @@ -328,7 +332,7 @@ functions. cwd=None, env=None, universal_newlines=False, \ startupinfo=None, creationflags=0, restore_signals=True, \ start_new_session=False, pass_fds=(), *, \ - encoding=None, errors=None) + encoding=None, errors=None, text=None) Execute a child program in a new process. On POSIX, the class uses :meth:`os.execvp`-like behavior to execute the child program. On Windows, @@ -511,15 +515,18 @@ functions. .. _side-by-side assembly: https://en.wikipedia.org/wiki/Side-by-Side_Assembly - If *encoding* or *errors* are specified, the file objects *stdin*, *stdout* - and *stderr* are opened in text mode with the specified encoding and - *errors*, as described above in :ref:`frequently-used-arguments`. If - *universal_newlines* is ``True``, they are opened in text mode with default - encoding. Otherwise, they are opened as binary streams. + If *encoding* or *errors* are specified, or *text* is true, the file objects + *stdin*, *stdout* and *stderr* are opened in text mode with the specified + encoding and *errors*, as described above in :ref:`frequently-used-arguments`. + The *universal_newlines* argument is equivalent to *text* and is provided + for backwards compatibility. By default, file objects are opened in binary mode. .. versionadded:: 3.6 *encoding* and *errors* were added. + .. versionadded:: 3.7 + *text* was added as a more readable alias for *universal_newlines*. + If given, *startupinfo* will be a :class:`STARTUPINFO` object, which is passed to the underlying ``CreateProcess`` function. *creationflags*, if given, can be one or more of the following flags: From webhook-mailer at python.org Sun Feb 11 16:35:12 2018 From: webhook-mailer at python.org (Zachary Ware) Date: Sun, 11 Feb 2018 21:35:12 -0000 Subject: [Python-checkins] Fix AppVeyor doc short-circuit (GH-5632) Message-ID: https://github.com/python/cpython/commit/6ea20fc719dcaf102d2cefa1786f0421514f7a58 commit: 6ea20fc719dcaf102d2cefa1786f0421514f7a58 branch: master author: Zachary Ware committer: GitHub date: 2018-02-11T15:35:09-06:00 summary: Fix AppVeyor doc short-circuit (GH-5632) files: M .github/appveyor.yml diff --git a/.github/appveyor.yml b/.github/appveyor.yml index 5239d6ccc17c..b87beda75e08 100644 --- a/.github/appveyor.yml +++ b/.github/appveyor.yml @@ -14,12 +14,15 @@ before_build: } elseif (!$env:APPVEYOR_PULL_REQUEST_HEAD_COMMIT) { echo 'Not a PR, doing full build.' } else { - $mergebase = git merge-base $env:APPVEYOR_PULL_REQUEST_HEAD_COMMIT $env:APPVEYOR_REPO_BRANCH + git fetch -q origin +refs/heads/$env:APPVEYOR_REPO_BRANCH + $mergebase = git merge-base HEAD FETCH_HEAD $changes = git diff --name-only HEAD $mergebase | grep -vE '(\.rst$)|(^Doc)|(^Misc)' If (!$changes) { echo 'Only docs were updated, stopping build process.' Exit-AppveyorBuild } + echo 'Doing full build due to non-doc changes in these files:' + echo $changes } From webhook-mailer at python.org Sun Feb 11 17:14:48 2018 From: webhook-mailer at python.org (Zachary Ware) Date: Sun, 11 Feb 2018 22:14:48 -0000 Subject: [Python-checkins] Fix AppVeyor doc short-circuit (GH-5633) Message-ID: https://github.com/python/cpython/commit/09df4b761f6365e315be26c89d2af70a4fda6985 commit: 09df4b761f6365e315be26c89d2af70a4fda6985 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Zachary Ware date: 2018-02-11T16:14:45-06:00 summary: Fix AppVeyor doc short-circuit (GH-5633) (cherry picked from commit 6ea20fc719dcaf102d2cefa1786f0421514f7a58) files: M .github/appveyor.yml diff --git a/.github/appveyor.yml b/.github/appveyor.yml index a4c11df2795e..9d47c9975e5a 100644 --- a/.github/appveyor.yml +++ b/.github/appveyor.yml @@ -14,12 +14,15 @@ before_build: } elseif (!$env:APPVEYOR_PULL_REQUEST_HEAD_COMMIT) { echo 'Not a PR, doing full build.' } else { - $mergebase = git merge-base $env:APPVEYOR_PULL_REQUEST_HEAD_COMMIT $env:APPVEYOR_REPO_BRANCH + git fetch -q origin +refs/heads/$env:APPVEYOR_REPO_BRANCH + $mergebase = git merge-base HEAD FETCH_HEAD $changes = git diff --name-only HEAD $mergebase | grep -vE '(\.rst$)|(^Doc)|(^Misc)' If (!$changes) { echo 'Only docs were updated, stopping build process.' Exit-AppveyorBuild } + echo 'Doing full build due to non-doc changes in these files:' + echo $changes } From webhook-mailer at python.org Sun Feb 11 17:21:35 2018 From: webhook-mailer at python.org (Zachary Ware) Date: Sun, 11 Feb 2018 22:21:35 -0000 Subject: [Python-checkins] Fix AppVeyor doc short-circuit (GH-5634) Message-ID: https://github.com/python/cpython/commit/db1de759a9caed5f77b9b550ce0085833a1eb05b commit: db1de759a9caed5f77b9b550ce0085833a1eb05b branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Zachary Ware date: 2018-02-11T16:21:32-06:00 summary: Fix AppVeyor doc short-circuit (GH-5634) (cherry picked from commit 6ea20fc719dcaf102d2cefa1786f0421514f7a58) files: M .github/appveyor.yml diff --git a/.github/appveyor.yml b/.github/appveyor.yml index 6e6a078a1032..e26969664ec2 100644 --- a/.github/appveyor.yml +++ b/.github/appveyor.yml @@ -14,12 +14,15 @@ before_build: } elseif (!$env:APPVEYOR_PULL_REQUEST_HEAD_COMMIT) { echo 'Not a PR, doing full build.' } else { - $mergebase = git merge-base $env:APPVEYOR_PULL_REQUEST_HEAD_COMMIT $env:APPVEYOR_REPO_BRANCH + git fetch -q origin +refs/heads/$env:APPVEYOR_REPO_BRANCH + $mergebase = git merge-base HEAD FETCH_HEAD $changes = git diff --name-only HEAD $mergebase | grep -vE '(\.rst$)|(^Doc)|(^Misc)' If (!$changes) { echo 'Only docs were updated, stopping build process.' Exit-AppveyorBuild } + echo 'Doing full build due to non-doc changes in these files:' + echo $changes } From webhook-mailer at python.org Sun Feb 11 17:29:13 2018 From: webhook-mailer at python.org (Zachary Ware) Date: Sun, 11 Feb 2018 22:29:13 -0000 Subject: [Python-checkins] Fix AppVeyor doc short-circuit (GH-5635) Message-ID: https://github.com/python/cpython/commit/2cf880498ac1d817914d4f87fe14d1a3cd6aaa0f commit: 2cf880498ac1d817914d4f87fe14d1a3cd6aaa0f branch: 2.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Zachary Ware date: 2018-02-11T16:29:11-06:00 summary: Fix AppVeyor doc short-circuit (GH-5635) (cherry picked from commit 6ea20fc719dcaf102d2cefa1786f0421514f7a58) files: M .github/appveyor.yml diff --git a/.github/appveyor.yml b/.github/appveyor.yml index fa614dbf9b87..c69e0ad2c4f2 100644 --- a/.github/appveyor.yml +++ b/.github/appveyor.yml @@ -14,12 +14,15 @@ before_build: } elseif (!$env:APPVEYOR_PULL_REQUEST_HEAD_COMMIT) { echo 'Not a PR, doing full build.' } else { - $mergebase = git merge-base $env:APPVEYOR_PULL_REQUEST_HEAD_COMMIT $env:APPVEYOR_REPO_BRANCH + git fetch -q origin +refs/heads/$env:APPVEYOR_REPO_BRANCH + $mergebase = git merge-base HEAD FETCH_HEAD $changes = git diff --name-only HEAD $mergebase | grep -vE '(\.rst$)|(^Doc)|(^Misc)' If (!$changes) { echo 'Only docs were updated, stopping build process.' Exit-AppveyorBuild } + echo 'Doing full build due to non-doc changes in these files:' + echo $changes } From webhook-mailer at python.org Sun Feb 11 18:21:04 2018 From: webhook-mailer at python.org (Gregory P. Smith) Date: Sun, 11 Feb 2018 23:21:04 -0000 Subject: [Python-checkins] bpo-32815: Improve docs on the subprocess API *text* parameter (GH-5622) (GH-5631) Message-ID: https://github.com/python/cpython/commit/ba4f218657efcba856d00eb320418355cce8309a commit: ba4f218657efcba856d00eb320418355cce8309a branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Gregory P. Smith date: 2018-02-11T15:21:02-08:00 summary: bpo-32815: Improve docs on the subprocess API *text* parameter (GH-5622) (GH-5631) Describe *text* as an alias for *universal_newlines* in more places that people are likely to be referred to. (cherry picked from commit e14c01037877768a3fe766e50d14993bd5d8a67e) Co-authored-by: Pablo Galindo files: M Doc/library/subprocess.rst diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst index 8673c4b18d8c..a22afe041850 100644 --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -39,7 +39,7 @@ compatibility with older versions, see the :ref:`call-function-trio` section. .. function:: run(args, *, stdin=None, input=None, stdout=None, stderr=None,\ shell=False, cwd=None, timeout=None, check=False, \ - encoding=None, errors=None) + encoding=None, errors=None, text=None) Run the command described by *args*. Wait for command to complete, then return a :class:`CompletedProcess` instance. @@ -267,7 +267,8 @@ default values. The arguments that are most commonly needed are: .. index:: single: universal newlines; subprocess module - If *encoding* or *errors* are specified, or *universal_newlines* is true, + If *encoding* or *errors* are specified, or *text* (also known as + *universal_newlines*) is true, the file objects *stdin*, *stdout* and *stderr* will be opened in text mode using the *encoding* and *errors* specified in the call or the defaults for :class:`io.TextIOWrapper`. @@ -284,6 +285,9 @@ default values. The arguments that are most commonly needed are: .. versionadded:: 3.6 Added *encoding* and *errors* parameters. + .. versionadded:: 3.7 + Added the *text* parameter as an alias for *universal_newlines*. + .. note:: The newlines attribute of the file objects :attr:`Popen.stdin`, @@ -328,7 +332,7 @@ functions. cwd=None, env=None, universal_newlines=False, \ startupinfo=None, creationflags=0, restore_signals=True, \ start_new_session=False, pass_fds=(), *, \ - encoding=None, errors=None) + encoding=None, errors=None, text=None) Execute a child program in a new process. On POSIX, the class uses :meth:`os.execvp`-like behavior to execute the child program. On Windows, @@ -511,15 +515,18 @@ functions. .. _side-by-side assembly: https://en.wikipedia.org/wiki/Side-by-Side_Assembly - If *encoding* or *errors* are specified, the file objects *stdin*, *stdout* - and *stderr* are opened in text mode with the specified encoding and - *errors*, as described above in :ref:`frequently-used-arguments`. If - *universal_newlines* is ``True``, they are opened in text mode with default - encoding. Otherwise, they are opened as binary streams. + If *encoding* or *errors* are specified, or *text* is true, the file objects + *stdin*, *stdout* and *stderr* are opened in text mode with the specified + encoding and *errors*, as described above in :ref:`frequently-used-arguments`. + The *universal_newlines* argument is equivalent to *text* and is provided + for backwards compatibility. By default, file objects are opened in binary mode. .. versionadded:: 3.6 *encoding* and *errors* were added. + .. versionadded:: 3.7 + *text* was added as a more readable alias for *universal_newlines*. + If given, *startupinfo* will be a :class:`STARTUPINFO` object, which is passed to the underlying ``CreateProcess`` function. *creationflags*, if given, can be one or more of the following flags: From webhook-mailer at python.org Mon Feb 12 02:33:20 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 12 Feb 2018 07:33:20 -0000 Subject: [Python-checkins] Fix typo in Include/objimpl.h, the word "has" was missing (GH-5568) (GH-5569) Message-ID: https://github.com/python/cpython/commit/972edd91cf630ee5139fee0161a3bcbea0ceaf48 commit: 972edd91cf630ee5139fee0161a3bcbea0ceaf48 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-11T23:33:11-08:00 summary: Fix typo in Include/objimpl.h, the word "has" was missing (GH-5568) (GH-5569) It now reads: ...be aware that Python has no control over... (cherry picked from commit 517da1e58f4c489d4b31579852cde5f7113da08e) Co-authored-by: Alexey files: M Include/objimpl.h diff --git a/Include/objimpl.h b/Include/objimpl.h index ed9e7a968066..057bb50cbda9 100644 --- a/Include/objimpl.h +++ b/Include/objimpl.h @@ -56,7 +56,7 @@ must use the platform malloc heap(s), or shared memory, or C++ local storage or operator new), you must first allocate the object with your custom allocator, then pass its pointer to PyObject_{Init, InitVar} for filling in its Python- specific fields: reference count, type pointer, possibly others. You should -be aware that Python no control over these objects because they don't +be aware that Python has no control over these objects because they don't cooperate with the Python memory manager. Such objects may not be eligible for automatic garbage collection and you have to make sure that they are released accordingly whenever their destructor gets called (cf. the specific From webhook-mailer at python.org Mon Feb 12 02:35:59 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 12 Feb 2018 07:35:59 -0000 Subject: [Python-checkins] Fix typo in Include/objimpl.h, the word "has" was missing (GH-5568) (GH-5570) Message-ID: https://github.com/python/cpython/commit/743b6c07e8c79ffee38ab77f1284b542d865ce6e commit: 743b6c07e8c79ffee38ab77f1284b542d865ce6e branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-11T23:35:56-08:00 summary: Fix typo in Include/objimpl.h, the word "has" was missing (GH-5568) (GH-5570) It now reads: ...be aware that Python has no control over... (cherry picked from commit 517da1e58f4c489d4b31579852cde5f7113da08e) Co-authored-by: Alexey files: M Include/objimpl.h diff --git a/Include/objimpl.h b/Include/objimpl.h index 746f9c921344..e7a3696d7a1b 100644 --- a/Include/objimpl.h +++ b/Include/objimpl.h @@ -56,7 +56,7 @@ must use the platform malloc heap(s), or shared memory, or C++ local storage or operator new), you must first allocate the object with your custom allocator, then pass its pointer to PyObject_{Init, InitVar} for filling in its Python- specific fields: reference count, type pointer, possibly others. You should -be aware that Python no control over these objects because they don't +be aware that Python has no control over these objects because they don't cooperate with the Python memory manager. Such objects may not be eligible for automatic garbage collection and you have to make sure that they are released accordingly whenever their destructor gets called (cf. the specific From webhook-mailer at python.org Mon Feb 12 03:06:51 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 12 Feb 2018 08:06:51 -0000 Subject: [Python-checkins] Fix typo in Include/objimpl.h, the word "has" was missing (GH-5568) (GH-5571) Message-ID: https://github.com/python/cpython/commit/40290647167d96752b924ff109cc527aca729872 commit: 40290647167d96752b924ff109cc527aca729872 branch: 2.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-12T00:06:48-08:00 summary: Fix typo in Include/objimpl.h, the word "has" was missing (GH-5568) (GH-5571) It now reads: ...be aware that Python has no control over... (cherry picked from commit 517da1e58f4c489d4b31579852cde5f7113da08e) Co-authored-by: Alexey files: M Include/objimpl.h diff --git a/Include/objimpl.h b/Include/objimpl.h index 55e83eced6a2..5f2868332955 100644 --- a/Include/objimpl.h +++ b/Include/objimpl.h @@ -56,7 +56,7 @@ must use the platform malloc heap(s), or shared memory, or C++ local storage or operator new), you must first allocate the object with your custom allocator, then pass its pointer to PyObject_{Init, InitVar} for filling in its Python- specific fields: reference count, type pointer, possibly others. You should -be aware that Python no control over these objects because they don't +be aware that Python has no control over these objects because they don't cooperate with the Python memory manager. Such objects may not be eligible for automatic garbage collection and you have to make sure that they are released accordingly whenever their destructor gets called (cf. the specific From webhook-mailer at python.org Mon Feb 12 03:07:57 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 12 Feb 2018 08:07:57 -0000 Subject: [Python-checkins] bpo-32720: Fixed the replacement field grammar documentation. (GH-5544) (GH-5547) Message-ID: https://github.com/python/cpython/commit/6708be744d032aeffab3e2cf0b064a41a719d8a1 commit: 6708be744d032aeffab3e2cf0b064a41a719d8a1 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-12T00:07:55-08:00 summary: bpo-32720: Fixed the replacement field grammar documentation. (GH-5544) (GH-5547) `arg_name` and `element_index` are defined as `digit`+ instead of `integer`. (cherry picked from commit 7a561afd2c79f63a6008843b83733911d07f0119) Co-authored-by: Mariatta files: M Doc/library/string.rst diff --git a/Doc/library/string.rst b/Doc/library/string.rst index dbafb48a8054..706d5e1fff3f 100644 --- a/Doc/library/string.rst +++ b/Doc/library/string.rst @@ -202,9 +202,9 @@ The grammar for a replacement field is as follows: .. productionlist:: sf replacement_field: "{" [`field_name`] ["!" `conversion`] [":" `format_spec`] "}" field_name: arg_name ("." `attribute_name` | "[" `element_index` "]")* - arg_name: [`identifier` | `integer`] + arg_name: [`identifier` | `digit`+] attribute_name: `identifier` - element_index: `integer` | `index_string` + element_index: `digit`+ | `index_string` index_string: + conversion: "r" | "s" | "a" format_spec: From solipsis at pitrou.net Mon Feb 12 04:09:28 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Mon, 12 Feb 2018 09:09:28 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=7 Message-ID: <20180212090928.1.110222B04947BA44@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_fork leaked [2, 0, 1] memory blocks, sum=3 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogAl1qeV', '--timeout', '7200'] From webhook-mailer at python.org Mon Feb 12 13:14:12 2018 From: webhook-mailer at python.org (Berker Peksag) Date: Mon, 12 Feb 2018 18:14:12 -0000 Subject: [Python-checkins] bpo-29248: Fix os.readlink() on Windows (GH-5577) Message-ID: https://github.com/python/cpython/commit/a1d33f742515dc70ae99bc3ea1c851729522afc3 commit: a1d33f742515dc70ae99bc3ea1c851729522afc3 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Berker Peksag date: 2018-02-12T21:14:08+03:00 summary: bpo-29248: Fix os.readlink() on Windows (GH-5577) The PrintNameOffset field of the reparse data buffer was treated as a number of characters instead of bytes. (cherry picked from commit 3c34aad4e7a95913ec7db8e5e948a8fc69047bf7) Co-authored-by: SSE4 files: A Misc/NEWS.d/next/Windows/2018-02-07-17-50-48.bpo-29248.Xzwj-6.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 b65ccb71591d..033e544ffed5 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -2171,6 +2171,21 @@ def test_12084(self): finally: os.chdir(orig_dir) + @unittest.skipUnless(os.path.lexists(r'C:\Users\All Users') + and os.path.exists(r'C:\ProgramData'), + 'Test directories not found') + def test_29248(self): + # os.symlink() calls CreateSymbolicLink, which creates + # the reparse data buffer with the print name stored + # first, so the offset is always 0. CreateSymbolicLink + # stores the "PrintName" DOS path (e.g. "C:\") first, + # with an offset of 0, followed by the "SubstituteName" + # NT path (e.g. "\??\C:\"). The "All Users" link, on + # the other hand, seems to have been created manually + # with an inverted order. + target = os.readlink(r'C:\Users\All Users') + self.assertTrue(os.path.samefile(target, r'C:\ProgramData')) + @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") class Win32JunctionTests(unittest.TestCase): diff --git a/Misc/NEWS.d/next/Windows/2018-02-07-17-50-48.bpo-29248.Xzwj-6.rst b/Misc/NEWS.d/next/Windows/2018-02-07-17-50-48.bpo-29248.Xzwj-6.rst new file mode 100644 index 000000000000..3030ef6958de --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2018-02-07-17-50-48.bpo-29248.Xzwj-6.rst @@ -0,0 +1,3 @@ +Fix :func:`os.readlink` on Windows, which was mistakenly treating the +``PrintNameOffset`` field of the reparse data buffer as a number of +characters instead of bytes. Patch by Craig Holmquist and SSE4. diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index e30d3c13bb2c..80b1fbdfd253 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -7127,11 +7127,11 @@ win_readlink(PyObject *self, PyObject *args, PyObject *kwargs) "not a symbolic link"); return NULL; } - print_name = rdb->SymbolicLinkReparseBuffer.PathBuffer + - rdb->SymbolicLinkReparseBuffer.PrintNameOffset; + print_name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer + + rdb->SymbolicLinkReparseBuffer.PrintNameOffset); result = PyUnicode_FromWideChar(print_name, - rdb->SymbolicLinkReparseBuffer.PrintNameLength/2); + rdb->SymbolicLinkReparseBuffer.PrintNameLength / sizeof(wchar_t)); return result; } From webhook-mailer at python.org Mon Feb 12 13:16:46 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Mon, 12 Feb 2018 18:16:46 -0000 Subject: [Python-checkins] bpo-30109: Fix reindent.py for non-ASCII files. (#5637) Message-ID: https://github.com/python/cpython/commit/17cec70a38b297779b8fd3f081fb041d45ae1dff commit: 17cec70a38b297779b8fd3f081fb041d45ae1dff branch: 2.7 author: Serhiy Storchaka committer: GitHub date: 2018-02-12T20:16:42+02:00 summary: bpo-30109: Fix reindent.py for non-ASCII files. (#5637) It now processes files as binary streams. This also fixes "make reindent". files: A Misc/NEWS.d/next/Tools-Demos/2018-02-12-14-27-01.bpo-30109.lIYlaf.rst M Lib/email/utils.py M Tools/scripts/reindent.py diff --git a/Lib/email/utils.py b/Lib/email/utils.py index a74db42286e7..5b22521e5814 100644 --- a/Lib/email/utils.py +++ b/Lib/email/utils.py @@ -213,7 +213,7 @@ def parsedate_tz(data): def parseaddr(addr): """ Parse addr into its constituent realname and email address parts. - + Return a tuple of realname and email address, unless the parse fails, in which case return a 2-tuple of ('', ''). """ diff --git a/Misc/NEWS.d/next/Tools-Demos/2018-02-12-14-27-01.bpo-30109.lIYlaf.rst b/Misc/NEWS.d/next/Tools-Demos/2018-02-12-14-27-01.bpo-30109.lIYlaf.rst new file mode 100644 index 000000000000..89249e171879 --- /dev/null +++ b/Misc/NEWS.d/next/Tools-Demos/2018-02-12-14-27-01.bpo-30109.lIYlaf.rst @@ -0,0 +1,2 @@ +Fixed Tools/scripts/reindent.py for non-ASCII files. It now processes files +as binary streams. This also fixes "make reindent". diff --git a/Tools/scripts/reindent.py b/Tools/scripts/reindent.py index df15edbc8d65..540901ba7d70 100755 --- a/Tools/scripts/reindent.py +++ b/Tools/scripts/reindent.py @@ -109,7 +109,7 @@ def check(file): if verbose: print "checking", file, "...", try: - f = io.open(file) + f = open(file, "rb") except IOError, msg: errprint("%s: I/O Error: %s" % (file, str(msg))) return @@ -133,7 +133,7 @@ def check(file): shutil.copyfile(file, bak) if verbose: print "backed up", file, "to", bak - f = io.open(file, "w", newline=newline) + f = open(file, "wb") r.write(f) f.close() if verbose: @@ -144,7 +144,21 @@ def check(file): print "unchanged." return False -def _rstrip(line, JUNK='\n \t'): +def _detect_newlines(lines): + newlines = {'\r\n' if line[-2:] == '\r\n' else + '\n' if line[-1:] == '\n' else + '\r' if line[-1:] == '\r' else + '' + for line in lines} + newlines.discard('') + newlines = tuple(sorted(newlines)) + if not newlines: + return '\n' + if len(newlines) == 1: + return newlines[0] + return newlines + +def _rstrip(line, JUNK='\r\n \t'): """Return line stripped of trailing spaces, tabs, newlines. Note that line.rstrip() instead also strips sundry control characters, @@ -166,10 +180,18 @@ def __init__(self, f): # Raw file lines. self.raw = f.readlines() + # Save the newlines found in the file so they can be used to + # create output without mutating the newlines. + self.newlines = _detect_newlines(self.raw) + if isinstance(self.newlines, tuple): + self.newline = self.newlines[0] + else: + self.newline = self.newlines + # File lines, rstripped & tab-expanded. Dummy at start is so # that we can use tokenize's 1-based line numbering easily. - # Note that a line is all-blank iff it's "\n". - self.lines = [_rstrip(line).expandtabs() + "\n" + # Note that a line is all-blank iff it's newline. + self.lines = [_rstrip(line).expandtabs() + self.newline for line in self.raw] self.lines.insert(0, None) self.index = 1 # index into self.lines of next line @@ -180,15 +202,11 @@ def __init__(self, f): # indeed, they're our headache! self.stats = [] - # Save the newlines found in the file so they can be used to - # create output without mutating the newlines. - self.newlines = f.newlines - def run(self): tokenize.tokenize(self.getline, self.tokeneater) # Remove trailing empty lines. lines = self.lines - while lines and lines[-1] == "\n": + while lines and lines[-1] == self.newline: lines.pop() # Sentinel. stats = self.stats @@ -244,7 +262,7 @@ def run(self): else: for line in lines[thisstmt:nextstmt]: if diff > 0: - if line == "\n": + if line == self.newline: after.append(line) else: after.append(" " * diff + line) From webhook-mailer at python.org Mon Feb 12 14:47:51 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Mon, 12 Feb 2018 19:47:51 -0000 Subject: [Python-checkins] bpo-32221: makeipaddr(): remove interface part + speedup (GH-5449) (#5449) Message-ID: https://github.com/python/cpython/commit/7766b96ab80b04509bbac708ee5ecf3c1c5934fc commit: 7766b96ab80b04509bbac708ee5ecf3c1c5934fc branch: master author: ????????? ???? committer: Yury Selivanov date: 2018-02-12T14:47:42-05:00 summary: bpo-32221: makeipaddr(): remove interface part + speedup (GH-5449) (#5449) files: A Misc/NEWS.d/next/Library/2017-12-06-10-10-10.bpo-32221.ideco_.rst M Doc/library/socket.rst M Lib/test/test_socket.py M Modules/socketmodule.c diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst index 7f0d4ede7ccf..04042ffdf1ac 100644 --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -77,6 +77,11 @@ created. Socket addresses are represented as follows: backward compatibility. Note, however, omission of *scopeid* can cause problems in manipulating scoped IPv6 addresses. + .. versionchanged:: 3.7 + For multicast addresses (with *scopeid* meaningful) *address* may not contain + ``%scope`` (or ``zone id``) part. This information is superfluous and may + be safely omitted (recommended). + - :const:`AF_NETLINK` sockets are represented as pairs ``(pid, groups)``. - Linux-only support for TIPC is available using the :const:`AF_TIPC` @@ -635,6 +640,10 @@ The :mod:`socket` module also offers various network-related services: .. versionchanged:: 3.2 parameters can now be passed using keyword arguments. + .. versionchanged:: 3.7 + for IPv6 multicast addresses, string representing an address will not + contain ``%scope`` part. + .. function:: getfqdn([name]) Return a fully qualified domain name for *name*. If *name* is omitted or empty, @@ -693,6 +702,8 @@ The :mod:`socket` module also offers various network-related services: or numeric address representation in *host*. Similarly, *port* can contain a string port name or a numeric port number. + For IPv6 addresses, ``%scope`` is appended to the host part if *sockaddr* + contains meaningful *scopeid*. Usually this happens for multicast addresses. .. function:: getprotobyname(protocolname) @@ -1193,6 +1204,10 @@ to sockets. an exception, the method now retries the system call instead of raising an :exc:`InterruptedError` exception (see :pep:`475` for the rationale). + .. versionchanged:: 3.7 + For multicast IPv6 address, first item of *address* does not contain + ``%scope`` part anymore. In order to get full IPv6 address use + :func:`getnameinfo`. .. method:: socket.recvmsg(bufsize[, ancbufsize[, flags]]) diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index 2851922bd0c5..b0e1b7471ee2 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -1594,6 +1594,72 @@ def test_flowinfo(self): with socket.socket(socket.AF_INET6, socket.SOCK_STREAM) as s: self.assertRaises(OverflowError, s.bind, (support.HOSTv6, 0, -10)) + @unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 required for this test.') + def test_getaddrinfo_ipv6_basic(self): + ((*_, sockaddr),) = socket.getaddrinfo( + 'ff02::1de:c0:face:8D', # Note capital letter `D`. + 1234, socket.AF_INET6, + socket.SOCK_DGRAM, + socket.IPPROTO_UDP + ) + self.assertEqual(sockaddr, ('ff02::1de:c0:face:8d', 1234, 0, 0)) + + @unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 required for this test.') + @unittest.skipUnless( + hasattr(socket, 'if_nameindex'), + 'if_nameindex is not supported') + def test_getaddrinfo_ipv6_scopeid_symbolic(self): + # Just pick up any network interface (Linux, Mac OS X) + (ifindex, test_interface) = socket.if_nameindex()[0] + ((*_, sockaddr),) = socket.getaddrinfo( + 'ff02::1de:c0:face:8D%' + test_interface, + 1234, socket.AF_INET6, + socket.SOCK_DGRAM, + socket.IPPROTO_UDP + ) + # Note missing interface name part in IPv6 address + self.assertEqual(sockaddr, ('ff02::1de:c0:face:8d', 1234, 0, ifindex)) + + @unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 required for this test.') + @unittest.skipUnless( + sys.platform == 'win32', + 'Numeric scope id does not work or undocumented') + def test_getaddrinfo_ipv6_scopeid_numeric(self): + # Also works on Linux and Mac OS X, but is not documented (?) + # Windows, Linux and Max OS X allow nonexistent interface numbers here. + ifindex = 42 + ((*_, sockaddr),) = socket.getaddrinfo( + 'ff02::1de:c0:face:8D%' + str(ifindex), + 1234, socket.AF_INET6, + socket.SOCK_DGRAM, + socket.IPPROTO_UDP + ) + # Note missing interface name part in IPv6 address + self.assertEqual(sockaddr, ('ff02::1de:c0:face:8d', 1234, 0, ifindex)) + + @unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 required for this test.') + @unittest.skipUnless( + hasattr(socket, 'if_nameindex'), + 'if_nameindex is not supported') + def test_getnameinfo_ipv6_scopeid_symbolic(self): + # Just pick up any network interface. + (ifindex, test_interface) = socket.if_nameindex()[0] + sockaddr = ('ff02::1de:c0:face:8D', 1234, 0, ifindex) # Note capital letter `D`. + nameinfo = socket.getnameinfo(sockaddr, socket.NI_NUMERICHOST | socket.NI_NUMERICSERV) + self.assertEqual(nameinfo, ('ff02::1de:c0:face:8d%' + test_interface, '1234')) + + @unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 required for this test.') + @unittest.skipUnless( + sys.platform == 'win32', + 'Numeric scope id does not work or undocumented') + def test_getnameinfo_ipv6_scopeid_numeric(self): + # Also works on Linux (undocumented), but does not work on Mac OS X + # Windows and Linux allow nonexistent interface numbers here. + ifindex = 42 + sockaddr = ('ff02::1de:c0:face:8D', 1234, 0, ifindex) # Note capital letter `D`. + nameinfo = socket.getnameinfo(sockaddr, socket.NI_NUMERICHOST | socket.NI_NUMERICSERV) + self.assertEqual(nameinfo, ('ff02::1de:c0:face:8d%' + str(ifindex), '1234')) + def test_str_for_enums(self): # Make sure that the AF_* and SOCK_* constants have enum-like string # reprs. diff --git a/Misc/NEWS.d/next/Library/2017-12-06-10-10-10.bpo-32221.ideco_.rst b/Misc/NEWS.d/next/Library/2017-12-06-10-10-10.bpo-32221.ideco_.rst new file mode 100644 index 000000000000..a88dcf48e02b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-06-10-10-10.bpo-32221.ideco_.rst @@ -0,0 +1,4 @@ +Various functions returning tuple containig IPv6 addresses now omit ``%scope`` +part since the same information is already encoded in *scopeid* tuple item. +Especially this speeds up :func:`socket.recvfrom` when it receives multicast +packet since useless resolving of network interface name is omitted. diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 23061bec5b7e..aa715bf95d76 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -1099,25 +1099,33 @@ setipaddr(const char *name, struct sockaddr *addr_ret, size_t addr_ret_size, int } -/* Create a string object representing an IP address. - This is always a string of the form 'dd.dd.dd.dd' (with variable - size numbers). */ +/* Convert IPv4 sockaddr to a Python str. */ static PyObject * -makeipaddr(struct sockaddr *addr, int addrlen) +make_ipv4_addr(const struct sockaddr_in *addr) { - char buf[NI_MAXHOST]; - int error; - - error = getnameinfo(addr, addrlen, buf, sizeof(buf), NULL, 0, - NI_NUMERICHOST); - if (error) { - set_gaierror(error); + char buf[INET_ADDRSTRLEN]; + if (inet_ntop(AF_INET, &addr->sin_addr, buf, sizeof(buf)) == NULL) { + PyErr_SetFromErrno(PyExc_OSError); return NULL; } return PyUnicode_FromString(buf); } +#ifdef ENABLE_IPV6 +/* Convert IPv6 sockaddr to a Python str. */ + +static PyObject * +make_ipv6_addr(const struct sockaddr_in6 *addr) +{ + char buf[INET6_ADDRSTRLEN]; + if (inet_ntop(AF_INET6, &addr->sin6_addr, buf, sizeof(buf)) == NULL) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + return PyUnicode_FromString(buf); +} +#endif #ifdef USE_BLUETOOTH /* Convert a string representation of a Bluetooth address into a numeric @@ -1182,11 +1190,10 @@ makesockaddr(SOCKET_T sockfd, struct sockaddr *addr, size_t addrlen, int proto) case AF_INET: { - struct sockaddr_in *a; - PyObject *addrobj = makeipaddr(addr, sizeof(*a)); + const struct sockaddr_in *a = (const struct sockaddr_in *)addr; + PyObject *addrobj = make_ipv4_addr(a); PyObject *ret = NULL; if (addrobj) { - a = (struct sockaddr_in *)addr; ret = Py_BuildValue("Oi", addrobj, ntohs(a->sin_port)); Py_DECREF(addrobj); } @@ -1230,11 +1237,10 @@ makesockaddr(SOCKET_T sockfd, struct sockaddr *addr, size_t addrlen, int proto) #ifdef ENABLE_IPV6 case AF_INET6: { - struct sockaddr_in6 *a; - PyObject *addrobj = makeipaddr(addr, sizeof(*a)); + const struct sockaddr_in6 *a = (const struct sockaddr_in6 *)addr; + PyObject *addrobj = make_ipv6_addr(a); PyObject *ret = NULL; if (addrobj) { - a = (struct sockaddr_in6 *)addr; ret = Py_BuildValue("OiII", addrobj, ntohs(a->sin6_port), @@ -5154,14 +5160,14 @@ static PyObject * socket_gethostbyname(PyObject *self, PyObject *args) { char *name; - sock_addr_t addrbuf; + struct sockaddr_in addrbuf; PyObject *ret = NULL; if (!PyArg_ParseTuple(args, "et:gethostbyname", "idna", &name)) return NULL; - if (setipaddr(name, SAS2SA(&addrbuf), sizeof(addrbuf), AF_INET) < 0) + if (setipaddr(name, (struct sockaddr *)&addrbuf, sizeof(addrbuf), AF_INET) < 0) goto finally; - ret = makeipaddr(SAS2SA(&addrbuf), sizeof(struct sockaddr_in)); + ret = make_ipv4_addr(&addrbuf); finally: PyMem_Free(name); return ret; @@ -5263,7 +5269,7 @@ gethost_common(struct hostent *h, struct sockaddr *addr, size_t alen, int af) sin.sin_len = sizeof(sin); #endif memcpy(&sin.sin_addr, *pch, sizeof(sin.sin_addr)); - tmp = makeipaddr((struct sockaddr *)&sin, sizeof(sin)); + tmp = make_ipv4_addr(&sin); if (pch == h->h_addr_list && alen >= sizeof(sin)) memcpy((char *) addr, &sin, sizeof(sin)); @@ -5280,8 +5286,7 @@ gethost_common(struct hostent *h, struct sockaddr *addr, size_t alen, int af) sin6.sin6_len = sizeof(sin6); #endif memcpy(&sin6.sin6_addr, *pch, sizeof(sin6.sin6_addr)); - tmp = makeipaddr((struct sockaddr *)&sin6, - sizeof(sin6)); + tmp = make_ipv6_addr(&sin6); if (pch == h->h_addr_list && alen >= sizeof(sin6)) memcpy((char *) addr, &sin6, sizeof(sin6)); @@ -6052,14 +6057,11 @@ socket_inet_ntop(PyObject *self, PyObject *args) Py_buffer packed_ip; const char* retval; #ifdef ENABLE_IPV6 - char ip[Py_MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN) + 1]; + char ip[Py_MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)]; #else - char ip[INET_ADDRSTRLEN + 1]; + char ip[INET_ADDRSTRLEN]; #endif - /* Guarantee NUL-termination for PyUnicode_FromString() below */ - memset((void *) &ip[0], '\0', sizeof(ip)); - if (!PyArg_ParseTuple(args, "iy*:inet_ntop", &af, &packed_ip)) { return NULL; } @@ -6087,6 +6089,7 @@ socket_inet_ntop(PyObject *self, PyObject *args) return NULL; } + /* inet_ntop guarantee NUL-termination of resulting string. */ retval = inet_ntop(af, packed_ip.buf, ip, sizeof(ip)); PyBuffer_Release(&packed_ip); if (!retval) { From webhook-mailer at python.org Mon Feb 12 14:58:32 2018 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Mon, 12 Feb 2018 19:58:32 -0000 Subject: [Python-checkins] bpo-32826: Add "encoding=utf-8" to open() in idle_test/test_help_about. (GH-5639) Message-ID: https://github.com/python/cpython/commit/f34e03ec0ea6a4cef8d966087c77e616c4a5893b commit: f34e03ec0ea6a4cef8d966087c77e616c4a5893b branch: master author: Terry Jan Reedy committer: GitHub date: 2018-02-12T14:58:26-05:00 summary: bpo-32826: Add "encoding=utf-8" to open() in idle_test/test_help_about. (GH-5639) GUI test test_file_buttons() only looks at initial ascii-only lines, but failed on systems where open() defaults to 'ascii' because readline() internally reads and decodes far enough ahead to encounter a non-ascii character in CREDITS.txt. files: A Misc/NEWS.d/next/IDLE/2018-02-12-11-05-22.bpo-32826.IxNZrk.rst M Lib/idlelib/idle_test/test_help_about.py diff --git a/Lib/idlelib/idle_test/test_help_about.py b/Lib/idlelib/idle_test/test_help_about.py index 1f67aaddb3b4..9c6a834a461b 100644 --- a/Lib/idlelib/idle_test/test_help_about.py +++ b/Lib/idlelib/idle_test/test_help_about.py @@ -50,35 +50,37 @@ def test_dialog_logo(self): def test_printer_buttons(self): """Test buttons whose commands use printer function.""" dialog = self.dialog - button_sources = [(dialog.py_license, license), - (dialog.py_copyright, copyright), - (dialog.py_credits, credits)] - - for button, printer in button_sources: - printer._Printer__setup() - button.invoke() - get = dialog._current_textview.viewframe.textframe.text.get - self.assertEqual(printer._Printer__lines[0], get('1.0', '1.end')) - self.assertEqual( - printer._Printer__lines[1], get('2.0', '2.end')) - dialog._current_textview.destroy() + button_sources = [(dialog.py_license, license, 'license'), + (dialog.py_copyright, copyright, 'copyright'), + (dialog.py_credits, credits, 'credits')] + + for button, printer, name in button_sources: + with self.subTest(name=name): + printer._Printer__setup() + button.invoke() + get = dialog._current_textview.viewframe.textframe.text.get + lines = printer._Printer__lines + self.assertEqual(lines[0], get('1.0', '1.end')) + self.assertEqual(lines[1], get('2.0', '2.end')) + dialog._current_textview.destroy() def test_file_buttons(self): """Test buttons that display files.""" dialog = self.dialog - button_sources = [(self.dialog.readme, 'README.txt'), - (self.dialog.idle_news, 'NEWS.txt'), - (self.dialog.idle_credits, 'CREDITS.txt')] - - for button, filename in button_sources: - button.invoke() - fn = findfile(filename, subdir='idlelib') - get = dialog._current_textview.viewframe.textframe.text.get - with open(fn) as f: - self.assertEqual(f.readline().strip(), get('1.0', '1.end')) - f.readline() - self.assertEqual(f.readline().strip(), get('3.0', '3.end')) - dialog._current_textview.destroy() + button_sources = [(self.dialog.readme, 'README.txt', 'readme'), + (self.dialog.idle_news, 'NEWS.txt', 'news'), + (self.dialog.idle_credits, 'CREDITS.txt', 'credits')] + + for button, filename, name in button_sources: + with self.subTest(name=name): + button.invoke() + fn = findfile(filename, subdir='idlelib') + get = dialog._current_textview.viewframe.textframe.text.get + with open(fn, encoding='utf-8') as f: + self.assertEqual(f.readline().strip(), get('1.0', '1.end')) + f.readline() + self.assertEqual(f.readline().strip(), get('3.0', '3.end')) + dialog._current_textview.destroy() class DefaultTitleTest(unittest.TestCase): diff --git a/Misc/NEWS.d/next/IDLE/2018-02-12-11-05-22.bpo-32826.IxNZrk.rst b/Misc/NEWS.d/next/IDLE/2018-02-12-11-05-22.bpo-32826.IxNZrk.rst new file mode 100644 index 000000000000..4310ed2e721a --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2018-02-12-11-05-22.bpo-32826.IxNZrk.rst @@ -0,0 +1,5 @@ +Add "encoding=utf-8" to open() in IDLE's test_help_about. +GUI test test_file_buttons() only looks at initial ascii-only lines, +but failed on systems where open() defaults to 'ascii' because +readline() internally reads and decodes far enough ahead to encounter +a non-ascii character in CREDITS.txt. From webhook-mailer at python.org Mon Feb 12 15:12:26 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Mon, 12 Feb 2018 20:12:26 -0000 Subject: [Python-checkins] bpo-32221: makeipaddr(): remove interface part + speedup (GH-5449) (GH-5449) (#5641) Message-ID: https://github.com/python/cpython/commit/0442599961f966a3dc7f3fe6a3c0d5765fcf2082 commit: 0442599961f966a3dc7f3fe6a3c0d5765fcf2082 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Yury Selivanov date: 2018-02-12T15:12:24-05:00 summary: bpo-32221: makeipaddr(): remove interface part + speedup (GH-5449) (GH-5449) (#5641) (cherry picked from commit 7766b96ab80b04509bbac708ee5ecf3c1c5934fc) Co-authored-by: ????????? ???? files: A Misc/NEWS.d/next/Library/2017-12-06-10-10-10.bpo-32221.ideco_.rst M Doc/library/socket.rst M Lib/test/test_socket.py M Modules/socketmodule.c diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst index 7f0d4ede7ccf..04042ffdf1ac 100644 --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -77,6 +77,11 @@ created. Socket addresses are represented as follows: backward compatibility. Note, however, omission of *scopeid* can cause problems in manipulating scoped IPv6 addresses. + .. versionchanged:: 3.7 + For multicast addresses (with *scopeid* meaningful) *address* may not contain + ``%scope`` (or ``zone id``) part. This information is superfluous and may + be safely omitted (recommended). + - :const:`AF_NETLINK` sockets are represented as pairs ``(pid, groups)``. - Linux-only support for TIPC is available using the :const:`AF_TIPC` @@ -635,6 +640,10 @@ The :mod:`socket` module also offers various network-related services: .. versionchanged:: 3.2 parameters can now be passed using keyword arguments. + .. versionchanged:: 3.7 + for IPv6 multicast addresses, string representing an address will not + contain ``%scope`` part. + .. function:: getfqdn([name]) Return a fully qualified domain name for *name*. If *name* is omitted or empty, @@ -693,6 +702,8 @@ The :mod:`socket` module also offers various network-related services: or numeric address representation in *host*. Similarly, *port* can contain a string port name or a numeric port number. + For IPv6 addresses, ``%scope`` is appended to the host part if *sockaddr* + contains meaningful *scopeid*. Usually this happens for multicast addresses. .. function:: getprotobyname(protocolname) @@ -1193,6 +1204,10 @@ to sockets. an exception, the method now retries the system call instead of raising an :exc:`InterruptedError` exception (see :pep:`475` for the rationale). + .. versionchanged:: 3.7 + For multicast IPv6 address, first item of *address* does not contain + ``%scope`` part anymore. In order to get full IPv6 address use + :func:`getnameinfo`. .. method:: socket.recvmsg(bufsize[, ancbufsize[, flags]]) diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index 2851922bd0c5..b0e1b7471ee2 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -1594,6 +1594,72 @@ def test_flowinfo(self): with socket.socket(socket.AF_INET6, socket.SOCK_STREAM) as s: self.assertRaises(OverflowError, s.bind, (support.HOSTv6, 0, -10)) + @unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 required for this test.') + def test_getaddrinfo_ipv6_basic(self): + ((*_, sockaddr),) = socket.getaddrinfo( + 'ff02::1de:c0:face:8D', # Note capital letter `D`. + 1234, socket.AF_INET6, + socket.SOCK_DGRAM, + socket.IPPROTO_UDP + ) + self.assertEqual(sockaddr, ('ff02::1de:c0:face:8d', 1234, 0, 0)) + + @unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 required for this test.') + @unittest.skipUnless( + hasattr(socket, 'if_nameindex'), + 'if_nameindex is not supported') + def test_getaddrinfo_ipv6_scopeid_symbolic(self): + # Just pick up any network interface (Linux, Mac OS X) + (ifindex, test_interface) = socket.if_nameindex()[0] + ((*_, sockaddr),) = socket.getaddrinfo( + 'ff02::1de:c0:face:8D%' + test_interface, + 1234, socket.AF_INET6, + socket.SOCK_DGRAM, + socket.IPPROTO_UDP + ) + # Note missing interface name part in IPv6 address + self.assertEqual(sockaddr, ('ff02::1de:c0:face:8d', 1234, 0, ifindex)) + + @unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 required for this test.') + @unittest.skipUnless( + sys.platform == 'win32', + 'Numeric scope id does not work or undocumented') + def test_getaddrinfo_ipv6_scopeid_numeric(self): + # Also works on Linux and Mac OS X, but is not documented (?) + # Windows, Linux and Max OS X allow nonexistent interface numbers here. + ifindex = 42 + ((*_, sockaddr),) = socket.getaddrinfo( + 'ff02::1de:c0:face:8D%' + str(ifindex), + 1234, socket.AF_INET6, + socket.SOCK_DGRAM, + socket.IPPROTO_UDP + ) + # Note missing interface name part in IPv6 address + self.assertEqual(sockaddr, ('ff02::1de:c0:face:8d', 1234, 0, ifindex)) + + @unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 required for this test.') + @unittest.skipUnless( + hasattr(socket, 'if_nameindex'), + 'if_nameindex is not supported') + def test_getnameinfo_ipv6_scopeid_symbolic(self): + # Just pick up any network interface. + (ifindex, test_interface) = socket.if_nameindex()[0] + sockaddr = ('ff02::1de:c0:face:8D', 1234, 0, ifindex) # Note capital letter `D`. + nameinfo = socket.getnameinfo(sockaddr, socket.NI_NUMERICHOST | socket.NI_NUMERICSERV) + self.assertEqual(nameinfo, ('ff02::1de:c0:face:8d%' + test_interface, '1234')) + + @unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 required for this test.') + @unittest.skipUnless( + sys.platform == 'win32', + 'Numeric scope id does not work or undocumented') + def test_getnameinfo_ipv6_scopeid_numeric(self): + # Also works on Linux (undocumented), but does not work on Mac OS X + # Windows and Linux allow nonexistent interface numbers here. + ifindex = 42 + sockaddr = ('ff02::1de:c0:face:8D', 1234, 0, ifindex) # Note capital letter `D`. + nameinfo = socket.getnameinfo(sockaddr, socket.NI_NUMERICHOST | socket.NI_NUMERICSERV) + self.assertEqual(nameinfo, ('ff02::1de:c0:face:8d%' + str(ifindex), '1234')) + def test_str_for_enums(self): # Make sure that the AF_* and SOCK_* constants have enum-like string # reprs. diff --git a/Misc/NEWS.d/next/Library/2017-12-06-10-10-10.bpo-32221.ideco_.rst b/Misc/NEWS.d/next/Library/2017-12-06-10-10-10.bpo-32221.ideco_.rst new file mode 100644 index 000000000000..a88dcf48e02b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-06-10-10-10.bpo-32221.ideco_.rst @@ -0,0 +1,4 @@ +Various functions returning tuple containig IPv6 addresses now omit ``%scope`` +part since the same information is already encoded in *scopeid* tuple item. +Especially this speeds up :func:`socket.recvfrom` when it receives multicast +packet since useless resolving of network interface name is omitted. diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 7fc3d877bba5..c1b24c153e2b 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -1099,25 +1099,33 @@ setipaddr(const char *name, struct sockaddr *addr_ret, size_t addr_ret_size, int } -/* Create a string object representing an IP address. - This is always a string of the form 'dd.dd.dd.dd' (with variable - size numbers). */ +/* Convert IPv4 sockaddr to a Python str. */ static PyObject * -makeipaddr(struct sockaddr *addr, int addrlen) +make_ipv4_addr(const struct sockaddr_in *addr) { - char buf[NI_MAXHOST]; - int error; - - error = getnameinfo(addr, addrlen, buf, sizeof(buf), NULL, 0, - NI_NUMERICHOST); - if (error) { - set_gaierror(error); + char buf[INET_ADDRSTRLEN]; + if (inet_ntop(AF_INET, &addr->sin_addr, buf, sizeof(buf)) == NULL) { + PyErr_SetFromErrno(PyExc_OSError); return NULL; } return PyUnicode_FromString(buf); } +#ifdef ENABLE_IPV6 +/* Convert IPv6 sockaddr to a Python str. */ + +static PyObject * +make_ipv6_addr(const struct sockaddr_in6 *addr) +{ + char buf[INET6_ADDRSTRLEN]; + if (inet_ntop(AF_INET6, &addr->sin6_addr, buf, sizeof(buf)) == NULL) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + return PyUnicode_FromString(buf); +} +#endif #ifdef USE_BLUETOOTH /* Convert a string representation of a Bluetooth address into a numeric @@ -1182,11 +1190,10 @@ makesockaddr(SOCKET_T sockfd, struct sockaddr *addr, size_t addrlen, int proto) case AF_INET: { - struct sockaddr_in *a; - PyObject *addrobj = makeipaddr(addr, sizeof(*a)); + const struct sockaddr_in *a = (const struct sockaddr_in *)addr; + PyObject *addrobj = make_ipv4_addr(a); PyObject *ret = NULL; if (addrobj) { - a = (struct sockaddr_in *)addr; ret = Py_BuildValue("Oi", addrobj, ntohs(a->sin_port)); Py_DECREF(addrobj); } @@ -1230,11 +1237,10 @@ makesockaddr(SOCKET_T sockfd, struct sockaddr *addr, size_t addrlen, int proto) #ifdef ENABLE_IPV6 case AF_INET6: { - struct sockaddr_in6 *a; - PyObject *addrobj = makeipaddr(addr, sizeof(*a)); + const struct sockaddr_in6 *a = (const struct sockaddr_in6 *)addr; + PyObject *addrobj = make_ipv6_addr(a); PyObject *ret = NULL; if (addrobj) { - a = (struct sockaddr_in6 *)addr; ret = Py_BuildValue("OiII", addrobj, ntohs(a->sin6_port), @@ -5154,14 +5160,14 @@ static PyObject * socket_gethostbyname(PyObject *self, PyObject *args) { char *name; - sock_addr_t addrbuf; + struct sockaddr_in addrbuf; PyObject *ret = NULL; if (!PyArg_ParseTuple(args, "et:gethostbyname", "idna", &name)) return NULL; - if (setipaddr(name, SAS2SA(&addrbuf), sizeof(addrbuf), AF_INET) < 0) + if (setipaddr(name, (struct sockaddr *)&addrbuf, sizeof(addrbuf), AF_INET) < 0) goto finally; - ret = makeipaddr(SAS2SA(&addrbuf), sizeof(struct sockaddr_in)); + ret = make_ipv4_addr(&addrbuf); finally: PyMem_Free(name); return ret; @@ -5263,7 +5269,7 @@ gethost_common(struct hostent *h, struct sockaddr *addr, size_t alen, int af) sin.sin_len = sizeof(sin); #endif memcpy(&sin.sin_addr, *pch, sizeof(sin.sin_addr)); - tmp = makeipaddr((struct sockaddr *)&sin, sizeof(sin)); + tmp = make_ipv4_addr(&sin); if (pch == h->h_addr_list && alen >= sizeof(sin)) memcpy((char *) addr, &sin, sizeof(sin)); @@ -5280,8 +5286,7 @@ gethost_common(struct hostent *h, struct sockaddr *addr, size_t alen, int af) sin6.sin6_len = sizeof(sin6); #endif memcpy(&sin6.sin6_addr, *pch, sizeof(sin6.sin6_addr)); - tmp = makeipaddr((struct sockaddr *)&sin6, - sizeof(sin6)); + tmp = make_ipv6_addr(&sin6); if (pch == h->h_addr_list && alen >= sizeof(sin6)) memcpy((char *) addr, &sin6, sizeof(sin6)); @@ -6052,14 +6057,11 @@ socket_inet_ntop(PyObject *self, PyObject *args) Py_buffer packed_ip; const char* retval; #ifdef ENABLE_IPV6 - char ip[Py_MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN) + 1]; + char ip[Py_MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)]; #else - char ip[INET_ADDRSTRLEN + 1]; + char ip[INET_ADDRSTRLEN]; #endif - /* Guarantee NUL-termination for PyUnicode_FromString() below */ - memset((void *) &ip[0], '\0', sizeof(ip)); - if (!PyArg_ParseTuple(args, "iy*:inet_ntop", &af, &packed_ip)) { return NULL; } @@ -6087,6 +6089,7 @@ socket_inet_ntop(PyObject *self, PyObject *args) return NULL; } + /* inet_ntop guarantee NUL-termination of resulting string. */ retval = inet_ntop(af, packed_ip.buf, ip, sizeof(ip)); PyBuffer_Release(&packed_ip); if (!retval) { From webhook-mailer at python.org Mon Feb 12 15:35:01 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 12 Feb 2018 20:35:01 -0000 Subject: [Python-checkins] bpo-32826: Add "encoding=utf-8" to open() in idle_test/test_help_about. (GH-5639) Message-ID: https://github.com/python/cpython/commit/38b4dd7f83fbdce6fe970088cd89b80f074a13f6 commit: 38b4dd7f83fbdce6fe970088cd89b80f074a13f6 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-12T12:34:52-08:00 summary: bpo-32826: Add "encoding=utf-8" to open() in idle_test/test_help_about. (GH-5639) GUI test test_file_buttons() only looks at initial ascii-only lines, but failed on systems where open() defaults to 'ascii' because readline() internally reads and decodes far enough ahead to encounter a non-ascii character in CREDITS.txt. (cherry picked from commit f34e03ec0ea6a4cef8d966087c77e616c4a5893b) Co-authored-by: Terry Jan Reedy files: A Misc/NEWS.d/next/IDLE/2018-02-12-11-05-22.bpo-32826.IxNZrk.rst M Lib/idlelib/idle_test/test_help_about.py diff --git a/Lib/idlelib/idle_test/test_help_about.py b/Lib/idlelib/idle_test/test_help_about.py index 1f67aaddb3b4..9c6a834a461b 100644 --- a/Lib/idlelib/idle_test/test_help_about.py +++ b/Lib/idlelib/idle_test/test_help_about.py @@ -50,35 +50,37 @@ def test_dialog_logo(self): def test_printer_buttons(self): """Test buttons whose commands use printer function.""" dialog = self.dialog - button_sources = [(dialog.py_license, license), - (dialog.py_copyright, copyright), - (dialog.py_credits, credits)] - - for button, printer in button_sources: - printer._Printer__setup() - button.invoke() - get = dialog._current_textview.viewframe.textframe.text.get - self.assertEqual(printer._Printer__lines[0], get('1.0', '1.end')) - self.assertEqual( - printer._Printer__lines[1], get('2.0', '2.end')) - dialog._current_textview.destroy() + button_sources = [(dialog.py_license, license, 'license'), + (dialog.py_copyright, copyright, 'copyright'), + (dialog.py_credits, credits, 'credits')] + + for button, printer, name in button_sources: + with self.subTest(name=name): + printer._Printer__setup() + button.invoke() + get = dialog._current_textview.viewframe.textframe.text.get + lines = printer._Printer__lines + self.assertEqual(lines[0], get('1.0', '1.end')) + self.assertEqual(lines[1], get('2.0', '2.end')) + dialog._current_textview.destroy() def test_file_buttons(self): """Test buttons that display files.""" dialog = self.dialog - button_sources = [(self.dialog.readme, 'README.txt'), - (self.dialog.idle_news, 'NEWS.txt'), - (self.dialog.idle_credits, 'CREDITS.txt')] - - for button, filename in button_sources: - button.invoke() - fn = findfile(filename, subdir='idlelib') - get = dialog._current_textview.viewframe.textframe.text.get - with open(fn) as f: - self.assertEqual(f.readline().strip(), get('1.0', '1.end')) - f.readline() - self.assertEqual(f.readline().strip(), get('3.0', '3.end')) - dialog._current_textview.destroy() + button_sources = [(self.dialog.readme, 'README.txt', 'readme'), + (self.dialog.idle_news, 'NEWS.txt', 'news'), + (self.dialog.idle_credits, 'CREDITS.txt', 'credits')] + + for button, filename, name in button_sources: + with self.subTest(name=name): + button.invoke() + fn = findfile(filename, subdir='idlelib') + get = dialog._current_textview.viewframe.textframe.text.get + with open(fn, encoding='utf-8') as f: + self.assertEqual(f.readline().strip(), get('1.0', '1.end')) + f.readline() + self.assertEqual(f.readline().strip(), get('3.0', '3.end')) + dialog._current_textview.destroy() class DefaultTitleTest(unittest.TestCase): diff --git a/Misc/NEWS.d/next/IDLE/2018-02-12-11-05-22.bpo-32826.IxNZrk.rst b/Misc/NEWS.d/next/IDLE/2018-02-12-11-05-22.bpo-32826.IxNZrk.rst new file mode 100644 index 000000000000..4310ed2e721a --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2018-02-12-11-05-22.bpo-32826.IxNZrk.rst @@ -0,0 +1,5 @@ +Add "encoding=utf-8" to open() in IDLE's test_help_about. +GUI test test_file_buttons() only looks at initial ascii-only lines, +but failed on systems where open() defaults to 'ascii' because +readline() internally reads and decodes far enough ahead to encounter +a non-ascii character in CREDITS.txt. From webhook-mailer at python.org Mon Feb 12 16:39:48 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 12 Feb 2018 21:39:48 -0000 Subject: [Python-checkins] bpo-29248: Fix os.readlink() on Windows (GH-5577) Message-ID: https://github.com/python/cpython/commit/74ebbaeb566dc10031756430ec5c896e56d0e491 commit: 74ebbaeb566dc10031756430ec5c896e56d0e491 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-12T13:39:42-08:00 summary: bpo-29248: Fix os.readlink() on Windows (GH-5577) The PrintNameOffset field of the reparse data buffer was treated as a number of characters instead of bytes. (cherry picked from commit 3c34aad4e7a95913ec7db8e5e948a8fc69047bf7) Co-authored-by: SSE4 files: A Misc/NEWS.d/next/Windows/2018-02-07-17-50-48.bpo-29248.Xzwj-6.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 02611d223b76..77e4a008ae61 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -2165,6 +2165,21 @@ def test_12084(self): finally: os.chdir(orig_dir) + @unittest.skipUnless(os.path.lexists(r'C:\Users\All Users') + and os.path.exists(r'C:\ProgramData'), + 'Test directories not found') + def test_29248(self): + # os.symlink() calls CreateSymbolicLink, which creates + # the reparse data buffer with the print name stored + # first, so the offset is always 0. CreateSymbolicLink + # stores the "PrintName" DOS path (e.g. "C:\") first, + # with an offset of 0, followed by the "SubstituteName" + # NT path (e.g. "\??\C:\"). The "All Users" link, on + # the other hand, seems to have been created manually + # with an inverted order. + target = os.readlink(r'C:\Users\All Users') + self.assertTrue(os.path.samefile(target, r'C:\ProgramData')) + @unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") class Win32JunctionTests(unittest.TestCase): diff --git a/Misc/NEWS.d/next/Windows/2018-02-07-17-50-48.bpo-29248.Xzwj-6.rst b/Misc/NEWS.d/next/Windows/2018-02-07-17-50-48.bpo-29248.Xzwj-6.rst new file mode 100644 index 000000000000..3030ef6958de --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2018-02-07-17-50-48.bpo-29248.Xzwj-6.rst @@ -0,0 +1,3 @@ +Fix :func:`os.readlink` on Windows, which was mistakenly treating the +``PrintNameOffset`` field of the reparse data buffer as a number of +characters instead of bytes. Patch by Craig Holmquist and SSE4. diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 4a1c9f398a07..63f5b2a38896 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -7439,11 +7439,11 @@ win_readlink(PyObject *self, PyObject *args, PyObject *kwargs) "not a symbolic link"); return NULL; } - print_name = rdb->SymbolicLinkReparseBuffer.PathBuffer + - rdb->SymbolicLinkReparseBuffer.PrintNameOffset; + print_name = (wchar_t *)((char*)rdb->SymbolicLinkReparseBuffer.PathBuffer + + rdb->SymbolicLinkReparseBuffer.PrintNameOffset); result = PyUnicode_FromWideChar(print_name, - rdb->SymbolicLinkReparseBuffer.PrintNameLength/2); + rdb->SymbolicLinkReparseBuffer.PrintNameLength / sizeof(wchar_t)); return result; } From webhook-mailer at python.org Mon Feb 12 17:43:00 2018 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Mon, 12 Feb 2018 22:43:00 -0000 Subject: [Python-checkins] bpo-32837: IDLE - require encoding argument for textview.view_file. (GH-5646) Message-ID: https://github.com/python/cpython/commit/688722cedd6437910ff185ecf94fb3b749ad37f2 commit: 688722cedd6437910ff185ecf94fb3b749ad37f2 branch: master author: Terry Jan Reedy committer: GitHub date: 2018-02-12T17:42:41-05:00 summary: bpo-32837: IDLE - require encoding argument for textview.view_file. (GH-5646) Using the system and place-dependent default encoding for open() is a bad idea for IDLE's system and location-independent files. files: A Misc/NEWS.d/next/IDLE/2018-02-12-17-22-48.bpo-32837.-33QPl.rst M Lib/idlelib/idle_test/test_textview.py M Lib/idlelib/textview.py diff --git a/Lib/idlelib/idle_test/test_textview.py b/Lib/idlelib/idle_test/test_textview.py index c129c2f0819a..dfd4063eb08d 100644 --- a/Lib/idlelib/idle_test/test_textview.py +++ b/Lib/idlelib/idle_test/test_textview.py @@ -112,7 +112,7 @@ def test_view_text(self): view.ok() def test_view_file(self): - view = tv.view_file(root, 'Title', __file__, modal=False) + view = tv.view_file(root, 'Title', __file__, 'ascii', modal=False) self.assertIsInstance(view, tv.ViewWindow) self.assertIsInstance(view.viewframe, tv.ViewFrame) get = view.viewframe.textframe.text.get @@ -121,7 +121,7 @@ def test_view_file(self): def test_bad_file(self): # Mock showerror will be used; view_file will return None. - view = tv.view_file(root, 'Title', 'abc.xyz', modal=False) + view = tv.view_file(root, 'Title', 'abc.xyz', 'ascii', modal=False) self.assertIsNone(view) self.assertEqual(tv.showerror.title, 'File Load Error') @@ -161,7 +161,8 @@ def _command(): def test_view_file_bind_with_button(self): def _command(): self.called = True - self.view = tv.view_file(root, 'TITLE_FILE', __file__, _utest=True) + self.view = tv.view_file(root, 'TITLE_FILE', __file__, + encoding='ascii', _utest=True) button = Button(root, text='BUTTON', command=_command) button.invoke() self.addCleanup(button.destroy) diff --git a/Lib/idlelib/textview.py b/Lib/idlelib/textview.py index e3b55065c6d9..662013440610 100644 --- a/Lib/idlelib/textview.py +++ b/Lib/idlelib/textview.py @@ -107,7 +107,7 @@ def view_text(parent, title, text, modal=True, _utest=False): return ViewWindow(parent, title, text, modal, _utest=_utest) -def view_file(parent, title, filename, encoding=None, modal=True, _utest=False): +def view_file(parent, title, filename, encoding, modal=True, _utest=False): """Create text viewer for text in filename. Return error message if file cannot be read. Otherwise calls view_text diff --git a/Misc/NEWS.d/next/IDLE/2018-02-12-17-22-48.bpo-32837.-33QPl.rst b/Misc/NEWS.d/next/IDLE/2018-02-12-17-22-48.bpo-32837.-33QPl.rst new file mode 100644 index 000000000000..258536a1cd0c --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2018-02-12-17-22-48.bpo-32837.-33QPl.rst @@ -0,0 +1,2 @@ +Using the system and place-dependent default encoding for open() is a bad +idea for IDLE's system and location-independent files. From webhook-mailer at python.org Mon Feb 12 18:15:05 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 12 Feb 2018 23:15:05 -0000 Subject: [Python-checkins] bpo-32837: IDLE - require encoding argument for textview.view_file. (GH-5646) Message-ID: https://github.com/python/cpython/commit/65c32bbe85862ab5eb52a0d4340e844e13d0f7ee commit: 65c32bbe85862ab5eb52a0d4340e844e13d0f7ee branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-12T15:15:01-08:00 summary: bpo-32837: IDLE - require encoding argument for textview.view_file. (GH-5646) Using the system and place-dependent default encoding for open() is a bad idea for IDLE's system and location-independent files. (cherry picked from commit 688722cedd6437910ff185ecf94fb3b749ad37f2) Co-authored-by: Terry Jan Reedy files: A Misc/NEWS.d/next/IDLE/2018-02-12-17-22-48.bpo-32837.-33QPl.rst M Lib/idlelib/idle_test/test_textview.py M Lib/idlelib/textview.py diff --git a/Lib/idlelib/idle_test/test_textview.py b/Lib/idlelib/idle_test/test_textview.py index c129c2f0819a..dfd4063eb08d 100644 --- a/Lib/idlelib/idle_test/test_textview.py +++ b/Lib/idlelib/idle_test/test_textview.py @@ -112,7 +112,7 @@ def test_view_text(self): view.ok() def test_view_file(self): - view = tv.view_file(root, 'Title', __file__, modal=False) + view = tv.view_file(root, 'Title', __file__, 'ascii', modal=False) self.assertIsInstance(view, tv.ViewWindow) self.assertIsInstance(view.viewframe, tv.ViewFrame) get = view.viewframe.textframe.text.get @@ -121,7 +121,7 @@ def test_view_file(self): def test_bad_file(self): # Mock showerror will be used; view_file will return None. - view = tv.view_file(root, 'Title', 'abc.xyz', modal=False) + view = tv.view_file(root, 'Title', 'abc.xyz', 'ascii', modal=False) self.assertIsNone(view) self.assertEqual(tv.showerror.title, 'File Load Error') @@ -161,7 +161,8 @@ def _command(): def test_view_file_bind_with_button(self): def _command(): self.called = True - self.view = tv.view_file(root, 'TITLE_FILE', __file__, _utest=True) + self.view = tv.view_file(root, 'TITLE_FILE', __file__, + encoding='ascii', _utest=True) button = Button(root, text='BUTTON', command=_command) button.invoke() self.addCleanup(button.destroy) diff --git a/Lib/idlelib/textview.py b/Lib/idlelib/textview.py index e3b55065c6d9..662013440610 100644 --- a/Lib/idlelib/textview.py +++ b/Lib/idlelib/textview.py @@ -107,7 +107,7 @@ def view_text(parent, title, text, modal=True, _utest=False): return ViewWindow(parent, title, text, modal, _utest=_utest) -def view_file(parent, title, filename, encoding=None, modal=True, _utest=False): +def view_file(parent, title, filename, encoding, modal=True, _utest=False): """Create text viewer for text in filename. Return error message if file cannot be read. Otherwise calls view_text diff --git a/Misc/NEWS.d/next/IDLE/2018-02-12-17-22-48.bpo-32837.-33QPl.rst b/Misc/NEWS.d/next/IDLE/2018-02-12-17-22-48.bpo-32837.-33QPl.rst new file mode 100644 index 000000000000..258536a1cd0c --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2018-02-12-17-22-48.bpo-32837.-33QPl.rst @@ -0,0 +1,2 @@ +Using the system and place-dependent default encoding for open() is a bad +idea for IDLE's system and location-independent files. From webhook-mailer at python.org Mon Feb 12 18:40:15 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 12 Feb 2018 23:40:15 -0000 Subject: [Python-checkins] bpo-32837: IDLE - require encoding argument for textview.view_file. (GH-5646) Message-ID: https://github.com/python/cpython/commit/9fad857444d90b9c6c36c31f5f07e57f390a70f2 commit: 9fad857444d90b9c6c36c31f5f07e57f390a70f2 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-12T15:40:12-08:00 summary: bpo-32837: IDLE - require encoding argument for textview.view_file. (GH-5646) Using the system and place-dependent default encoding for open() is a bad idea for IDLE's system and location-independent files. (cherry picked from commit 688722cedd6437910ff185ecf94fb3b749ad37f2) Co-authored-by: Terry Jan Reedy files: A Misc/NEWS.d/next/IDLE/2018-02-12-17-22-48.bpo-32837.-33QPl.rst M Lib/idlelib/idle_test/test_textview.py M Lib/idlelib/textview.py diff --git a/Lib/idlelib/idle_test/test_textview.py b/Lib/idlelib/idle_test/test_textview.py index c129c2f0819a..dfd4063eb08d 100644 --- a/Lib/idlelib/idle_test/test_textview.py +++ b/Lib/idlelib/idle_test/test_textview.py @@ -112,7 +112,7 @@ def test_view_text(self): view.ok() def test_view_file(self): - view = tv.view_file(root, 'Title', __file__, modal=False) + view = tv.view_file(root, 'Title', __file__, 'ascii', modal=False) self.assertIsInstance(view, tv.ViewWindow) self.assertIsInstance(view.viewframe, tv.ViewFrame) get = view.viewframe.textframe.text.get @@ -121,7 +121,7 @@ def test_view_file(self): def test_bad_file(self): # Mock showerror will be used; view_file will return None. - view = tv.view_file(root, 'Title', 'abc.xyz', modal=False) + view = tv.view_file(root, 'Title', 'abc.xyz', 'ascii', modal=False) self.assertIsNone(view) self.assertEqual(tv.showerror.title, 'File Load Error') @@ -161,7 +161,8 @@ def _command(): def test_view_file_bind_with_button(self): def _command(): self.called = True - self.view = tv.view_file(root, 'TITLE_FILE', __file__, _utest=True) + self.view = tv.view_file(root, 'TITLE_FILE', __file__, + encoding='ascii', _utest=True) button = Button(root, text='BUTTON', command=_command) button.invoke() self.addCleanup(button.destroy) diff --git a/Lib/idlelib/textview.py b/Lib/idlelib/textview.py index e3b55065c6d9..662013440610 100644 --- a/Lib/idlelib/textview.py +++ b/Lib/idlelib/textview.py @@ -107,7 +107,7 @@ def view_text(parent, title, text, modal=True, _utest=False): return ViewWindow(parent, title, text, modal, _utest=_utest) -def view_file(parent, title, filename, encoding=None, modal=True, _utest=False): +def view_file(parent, title, filename, encoding, modal=True, _utest=False): """Create text viewer for text in filename. Return error message if file cannot be read. Otherwise calls view_text diff --git a/Misc/NEWS.d/next/IDLE/2018-02-12-17-22-48.bpo-32837.-33QPl.rst b/Misc/NEWS.d/next/IDLE/2018-02-12-17-22-48.bpo-32837.-33QPl.rst new file mode 100644 index 000000000000..258536a1cd0c --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2018-02-12-17-22-48.bpo-32837.-33QPl.rst @@ -0,0 +1,2 @@ +Using the system and place-dependent default encoding for open() is a bad +idea for IDLE's system and location-independent files. From tjreedy at udel.edu Mon Feb 12 18:46:10 2018 From: tjreedy at udel.edu (Terry Reedy) Date: Mon, 12 Feb 2018 18:46:10 -0500 Subject: [Python-checkins] bpo-32837: IDLE - require encoding argument for textview.view_file. (GH-5646) In-Reply-To: <3zgMc06yM1zFr4v@mail.python.org> References: <3zgMc06yM1zFr4v@mail.python.org> Message-ID: On 2/12/2018 6:40 PM, Miss Islington (bot) wrote: > https://github.com/python/cpython/commit/9fad857444d90b9c6c36c31f5f07e57f390a70f2 > commit: 9fad857444d90b9c6c36c31f5f07e57f390a70f2 > branch: 3.6 > author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> > committer: GitHub > date: 2018-02-12T15:40:12-08:00 > summary: > > bpo-32837: IDLE - require encoding argument for textview.view_file. (GH-5646) This is my second PR today that was automerged by Miss Islington after I approved the 3.7 and 3.6 autobackports. Really nice. Thank you Mariatta. From webhook-mailer at python.org Tue Feb 13 01:27:36 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Tue, 13 Feb 2018 06:27:36 -0000 Subject: [Python-checkins] bpo-32827: Fix usage of _PyUnicodeWriter_Prepare() in decoding errors handler. (GH-5636) Message-ID: https://github.com/python/cpython/commit/b7e2d67f7c035f09c921ca4e7a36529cd502ccf7 commit: b7e2d67f7c035f09c921ca4e7a36529cd502ccf7 branch: master author: Serhiy Storchaka committer: GitHub date: 2018-02-13T08:27:33+02:00 summary: bpo-32827: Fix usage of _PyUnicodeWriter_Prepare() in decoding errors handler. (GH-5636) files: M Objects/unicodeobject.c diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index f5e4ab62a333..02334382cabe 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -4256,7 +4256,7 @@ unicode_decode_call_errorhandler_writer( } if (need_to_grow) { writer->overallocate = 1; - if (_PyUnicodeWriter_Prepare(writer, writer->min_length, + if (_PyUnicodeWriter_Prepare(writer, writer->min_length - writer->pos, PyUnicode_MAX_CHAR_VALUE(repunicode)) == -1) goto onError; } @@ -6085,9 +6085,7 @@ _PyUnicode_DecodeUnicodeEscape(const char *s, &writer)) { goto onError; } - if (_PyUnicodeWriter_Prepare(&writer, writer.min_length, 127) < 0) { - goto onError; - } + assert(end - s <= writer.size - writer.pos); #undef WRITE_ASCII_CHAR #undef WRITE_CHAR @@ -6364,9 +6362,7 @@ PyUnicode_DecodeRawUnicodeEscape(const char *s, &writer)) { goto onError; } - if (_PyUnicodeWriter_Prepare(&writer, writer.min_length, 127) < 0) { - goto onError; - } + assert(end - s <= writer.size - writer.pos); #undef WRITE_CHAR } From webhook-mailer at python.org Tue Feb 13 01:29:58 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Tue, 13 Feb 2018 06:29:58 -0000 Subject: [Python-checkins] bpo-32370: Use the correct encoding for ipconfig output in the uuid module. (GH-5608) Message-ID: https://github.com/python/cpython/commit/da6c3da6c33c6bf794f741e348b9c6d86cc43ec5 commit: da6c3da6c33c6bf794f741e348b9c6d86cc43ec5 branch: master author: Segev Finer committer: Serhiy Storchaka date: 2018-02-13T08:29:54+02:00 summary: bpo-32370: Use the correct encoding for ipconfig output in the uuid module. (GH-5608) files: A Misc/NEWS.d/next/Windows/2018-02-10-15-38-19.bpo-32370.kcKuct.rst M Lib/uuid.py diff --git a/Lib/uuid.py b/Lib/uuid.py index ef7b3b59241f..9cb73e877181 100644 --- a/Lib/uuid.py +++ b/Lib/uuid.py @@ -468,7 +468,7 @@ def _netstat_getnode(): def _ipconfig_getnode(): """Get the hardware address on Windows by running ipconfig.exe.""" - import os, re + import os, re, subprocess first_local_mac = None dirs = ['', r'c:\windows\system32', r'c:\winnt\system32'] try: @@ -480,11 +480,13 @@ def _ipconfig_getnode(): pass for dir in dirs: try: - pipe = os.popen(os.path.join(dir, 'ipconfig') + ' /all') + proc = subprocess.Popen([os.path.join(dir, 'ipconfig'), '/all'], + stdout=subprocess.PIPE, + encoding="oem") except OSError: continue - with pipe: - for line in pipe: + 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): mac = int(value.replace('-', ''), 16) diff --git a/Misc/NEWS.d/next/Windows/2018-02-10-15-38-19.bpo-32370.kcKuct.rst b/Misc/NEWS.d/next/Windows/2018-02-10-15-38-19.bpo-32370.kcKuct.rst new file mode 100644 index 000000000000..7f076d45bef9 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2018-02-10-15-38-19.bpo-32370.kcKuct.rst @@ -0,0 +1,2 @@ +Use the correct encoding for ipconfig output in the uuid module. +Patch by Segev Finer. From webhook-mailer at python.org Tue Feb 13 02:16:00 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Tue, 13 Feb 2018 07:16:00 -0000 Subject: [Python-checkins] bpo-32827: Fix usage of _PyUnicodeWriter_Prepare() in decoding errors handler. (GH-5636) (GH-5650) Message-ID: https://github.com/python/cpython/commit/09819ef05a9a1b13321b56c09f48ca45b46e8656 commit: 09819ef05a9a1b13321b56c09f48ca45b46e8656 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Serhiy Storchaka date: 2018-02-13T09:15:57+02:00 summary: bpo-32827: Fix usage of _PyUnicodeWriter_Prepare() in decoding errors handler. (GH-5636) (GH-5650) (cherry picked from commit b7e2d67f7c035f09c921ca4e7a36529cd502ccf7) Co-authored-by: Serhiy Storchaka files: M Objects/unicodeobject.c diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 3d9e09d7fab1..d5e7d10b1759 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -4256,7 +4256,7 @@ unicode_decode_call_errorhandler_writer( } if (need_to_grow) { writer->overallocate = 1; - if (_PyUnicodeWriter_Prepare(writer, writer->min_length, + if (_PyUnicodeWriter_Prepare(writer, writer->min_length - writer->pos, PyUnicode_MAX_CHAR_VALUE(repunicode)) == -1) goto onError; } @@ -6085,9 +6085,7 @@ _PyUnicode_DecodeUnicodeEscape(const char *s, &writer)) { goto onError; } - if (_PyUnicodeWriter_Prepare(&writer, writer.min_length, 127) < 0) { - goto onError; - } + assert(end - s <= writer.size - writer.pos); #undef WRITE_ASCII_CHAR #undef WRITE_CHAR @@ -6364,9 +6362,7 @@ PyUnicode_DecodeRawUnicodeEscape(const char *s, &writer)) { goto onError; } - if (_PyUnicodeWriter_Prepare(&writer, writer.min_length, 127) < 0) { - goto onError; - } + assert(end - s <= writer.size - writer.pos); #undef WRITE_CHAR } From webhook-mailer at python.org Tue Feb 13 03:11:02 2018 From: webhook-mailer at python.org (Nick Coghlan) Date: Tue, 13 Feb 2018 08:11:02 -0000 Subject: [Python-checkins] bpo-30579: Docs for dynamic traceback creation (GH-5653) Message-ID: https://github.com/python/cpython/commit/aec7532ed3ccbd29d3429a3f375e25f956c44003 commit: aec7532ed3ccbd29d3429a3f375e25f956c44003 branch: master author: Nick Coghlan committer: GitHub date: 2018-02-13T18:10:58+10:00 summary: bpo-30579: Docs for dynamic traceback creation (GH-5653) 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 bbc1d1301d2c..67cd4d702ad4 100644 --- a/Doc/library/types.rst +++ b/Doc/library/types.rst @@ -198,16 +198,23 @@ Standard names are defined for the following types: Defaults to ``None``. Previously the attribute was optional. -.. data:: TracebackType +.. class:: TracebackType(tb_next, tb_frame, tb_lasti, tb_lineno) The type of traceback objects such as found in ``sys.exc_info()[2]``. + See :ref:`the language reference ` for details of the + available attributes and operations, and guidance on creating tracebacks + dynamically. + .. data:: FrameType The type of frame objects such as found in ``tb.tb_frame`` if ``tb`` is a traceback object. + See :ref:`the language reference ` for details of the + available attributes and operations. + .. data:: GetSetDescriptorType diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 8420fb60bff3..8b127a0b7e81 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -950,7 +950,7 @@ Internal types .. index:: object: frame Frame objects represent execution frames. They may occur in traceback objects - (see below). + (see below), and are also passed to registered trace functions. .. index:: single: f_back (frame attribute) @@ -1003,6 +1003,8 @@ Internal types .. versionadded:: 3.4 + .. _traceback-objects: + Traceback objects .. index:: object: traceback @@ -1015,31 +1017,51 @@ Internal types single: sys.last_traceback Traceback objects represent a stack trace of an exception. A traceback object - is created when an exception occurs. When the search for an exception handler + is implicitly created when an exception occurs, and may also be explicitly + created by calling :class:`types.TracebackType`. + + For implicitly created tracebacks, when the search for an exception handler unwinds the execution stack, at each unwound level a traceback object is inserted in front of the current traceback. When an exception handler is entered, the stack trace is made available to the program. (See section :ref:`try`.) It is accessible as the third item of the - tuple returned by ``sys.exc_info()``. When the program contains no suitable + tuple returned by ``sys.exc_info()``, and as the ``__traceback__`` attribute + of the caught exception. + + When the program contains no suitable handler, the stack trace is written (nicely formatted) to the standard error stream; if the interpreter is interactive, it is also made available to the user as ``sys.last_traceback``. + For explicitly created tracebacks, it is up to the creator of the traceback + to determine how the ``tb_next`` attributes should be linked to form a + full stack trace. + .. index:: - single: tb_next (traceback attribute) single: tb_frame (traceback attribute) single: tb_lineno (traceback attribute) single: tb_lasti (traceback attribute) statement: try - Special read-only attributes: :attr:`tb_next` is the next level in the stack - trace (towards the frame where the exception occurred), or ``None`` if there is - no next level; :attr:`tb_frame` points to the execution frame of the current - level; :attr:`tb_lineno` gives the line number where the exception occurred; - :attr:`tb_lasti` indicates the precise instruction. The line number and last - instruction in the traceback may differ from the line number of its frame object - if the exception occurred in a :keyword:`try` statement with no matching except - clause or with a finally clause. + Special read-only attributes: + :attr:`tb_frame` points to the execution frame of the current level; + :attr:`tb_lineno` gives the line number where the exception occurred; + :attr:`tb_lasti` indicates the precise instruction. + The line number and last instruction in the traceback may differ from the + line number of its frame object if the exception occurred in a + :keyword:`try` statement with no matching except clause or with a + finally clause. + + .. index:: + single: tb_next (traceback attribute) + + Special writable attribute: :attr:`tb_next` is the next level in the stack + trace (towards the frame where the exception occurred), or ``None`` if + there is no next level. + + .. versionchanged:: 3.7 + Traceback objects can now be explicitly instantiated from Python code, + and the ``tb_next`` attribute of existing instances can be updated. Slice objects .. index:: builtin: slice diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 3b4ba6e41975..c3761c565322 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -398,6 +398,12 @@ Other Language Changes ``format(str(self), '')``. (Contributed by Serhiy Storchaka in :issue:`28974`.) +* In order to better support dynamic creation of stack traces, + :class:`types.TracebackType` can now be instantiated from Python code, and + the ``tb_next`` attribute on :ref:`tracebacks ` is now + writable. + (Contributed by Nathaniel J. Smith in :issue:`30579`.) + New Modules =========== From webhook-mailer at python.org Tue Feb 13 03:53:46 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 13 Feb 2018 08:53:46 -0000 Subject: [Python-checkins] bpo-30579: Docs for dynamic traceback creation (GH-5653) Message-ID: https://github.com/python/cpython/commit/53374cc57f33f1afb22924da3a76ec6cf9e4afc1 commit: 53374cc57f33f1afb22924da3a76ec6cf9e4afc1 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-13T00:53:37-08:00 summary: bpo-30579: Docs for dynamic traceback creation (GH-5653) (cherry picked from commit aec7532ed3ccbd29d3429a3f375e25f956c44003) Co-authored-by: Nick Coghlan 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 bbc1d1301d2c..67cd4d702ad4 100644 --- a/Doc/library/types.rst +++ b/Doc/library/types.rst @@ -198,16 +198,23 @@ Standard names are defined for the following types: Defaults to ``None``. Previously the attribute was optional. -.. data:: TracebackType +.. class:: TracebackType(tb_next, tb_frame, tb_lasti, tb_lineno) The type of traceback objects such as found in ``sys.exc_info()[2]``. + See :ref:`the language reference ` for details of the + available attributes and operations, and guidance on creating tracebacks + dynamically. + .. data:: FrameType The type of frame objects such as found in ``tb.tb_frame`` if ``tb`` is a traceback object. + See :ref:`the language reference ` for details of the + available attributes and operations. + .. data:: GetSetDescriptorType diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 8420fb60bff3..8b127a0b7e81 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -950,7 +950,7 @@ Internal types .. index:: object: frame Frame objects represent execution frames. They may occur in traceback objects - (see below). + (see below), and are also passed to registered trace functions. .. index:: single: f_back (frame attribute) @@ -1003,6 +1003,8 @@ Internal types .. versionadded:: 3.4 + .. _traceback-objects: + Traceback objects .. index:: object: traceback @@ -1015,31 +1017,51 @@ Internal types single: sys.last_traceback Traceback objects represent a stack trace of an exception. A traceback object - is created when an exception occurs. When the search for an exception handler + is implicitly created when an exception occurs, and may also be explicitly + created by calling :class:`types.TracebackType`. + + For implicitly created tracebacks, when the search for an exception handler unwinds the execution stack, at each unwound level a traceback object is inserted in front of the current traceback. When an exception handler is entered, the stack trace is made available to the program. (See section :ref:`try`.) It is accessible as the third item of the - tuple returned by ``sys.exc_info()``. When the program contains no suitable + tuple returned by ``sys.exc_info()``, and as the ``__traceback__`` attribute + of the caught exception. + + When the program contains no suitable handler, the stack trace is written (nicely formatted) to the standard error stream; if the interpreter is interactive, it is also made available to the user as ``sys.last_traceback``. + For explicitly created tracebacks, it is up to the creator of the traceback + to determine how the ``tb_next`` attributes should be linked to form a + full stack trace. + .. index:: - single: tb_next (traceback attribute) single: tb_frame (traceback attribute) single: tb_lineno (traceback attribute) single: tb_lasti (traceback attribute) statement: try - Special read-only attributes: :attr:`tb_next` is the next level in the stack - trace (towards the frame where the exception occurred), or ``None`` if there is - no next level; :attr:`tb_frame` points to the execution frame of the current - level; :attr:`tb_lineno` gives the line number where the exception occurred; - :attr:`tb_lasti` indicates the precise instruction. The line number and last - instruction in the traceback may differ from the line number of its frame object - if the exception occurred in a :keyword:`try` statement with no matching except - clause or with a finally clause. + Special read-only attributes: + :attr:`tb_frame` points to the execution frame of the current level; + :attr:`tb_lineno` gives the line number where the exception occurred; + :attr:`tb_lasti` indicates the precise instruction. + The line number and last instruction in the traceback may differ from the + line number of its frame object if the exception occurred in a + :keyword:`try` statement with no matching except clause or with a + finally clause. + + .. index:: + single: tb_next (traceback attribute) + + Special writable attribute: :attr:`tb_next` is the next level in the stack + trace (towards the frame where the exception occurred), or ``None`` if + there is no next level. + + .. versionchanged:: 3.7 + Traceback objects can now be explicitly instantiated from Python code, + and the ``tb_next`` attribute of existing instances can be updated. Slice objects .. index:: builtin: slice diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index fcd5188e7be2..aaf4dcfa3050 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -398,6 +398,12 @@ Other Language Changes ``format(str(self), '')``. (Contributed by Serhiy Storchaka in :issue:`28974`.) +* In order to better support dynamic creation of stack traces, + :class:`types.TracebackType` can now be instantiated from Python code, and + the ``tb_next`` attribute on :ref:`tracebacks ` is now + writable. + (Contributed by Nathaniel J. Smith in :issue:`30579`.) + New Modules =========== From webhook-mailer at python.org Tue Feb 13 03:58:30 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 13 Feb 2018 08:58:30 -0000 Subject: [Python-checkins] bpo-32370: Use the correct encoding for ipconfig output in the uuid module. (GH-5608) Message-ID: https://github.com/python/cpython/commit/9b5a90b975ef32b261d60b8ec06504f4ffd00d63 commit: 9b5a90b975ef32b261d60b8ec06504f4ffd00d63 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-13T00:58:28-08:00 summary: bpo-32370: Use the correct encoding for ipconfig output in the uuid module. (GH-5608) (cherry picked from commit da6c3da6c33c6bf794f741e348b9c6d86cc43ec5) Co-authored-by: Segev Finer files: A Misc/NEWS.d/next/Windows/2018-02-10-15-38-19.bpo-32370.kcKuct.rst M Lib/uuid.py diff --git a/Lib/uuid.py b/Lib/uuid.py index ef7b3b59241f..9cb73e877181 100644 --- a/Lib/uuid.py +++ b/Lib/uuid.py @@ -468,7 +468,7 @@ def _netstat_getnode(): def _ipconfig_getnode(): """Get the hardware address on Windows by running ipconfig.exe.""" - import os, re + import os, re, subprocess first_local_mac = None dirs = ['', r'c:\windows\system32', r'c:\winnt\system32'] try: @@ -480,11 +480,13 @@ def _ipconfig_getnode(): pass for dir in dirs: try: - pipe = os.popen(os.path.join(dir, 'ipconfig') + ' /all') + proc = subprocess.Popen([os.path.join(dir, 'ipconfig'), '/all'], + stdout=subprocess.PIPE, + encoding="oem") except OSError: continue - with pipe: - for line in pipe: + 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): mac = int(value.replace('-', ''), 16) diff --git a/Misc/NEWS.d/next/Windows/2018-02-10-15-38-19.bpo-32370.kcKuct.rst b/Misc/NEWS.d/next/Windows/2018-02-10-15-38-19.bpo-32370.kcKuct.rst new file mode 100644 index 000000000000..7f076d45bef9 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2018-02-10-15-38-19.bpo-32370.kcKuct.rst @@ -0,0 +1,2 @@ +Use the correct encoding for ipconfig output in the uuid module. +Patch by Segev Finer. From solipsis at pitrou.net Tue Feb 13 04:14:57 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Tue, 13 Feb 2018 09:14:57 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=11 Message-ID: <20180213091457.1.D9B8F49497A5E4D0@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 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogZzvz18', '--timeout', '7200'] From webhook-mailer at python.org Tue Feb 13 04:15:26 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Tue, 13 Feb 2018 09:15:26 -0000 Subject: [Python-checkins] [3.6] bpo-32370: Use the correct encoding for ipconfig output in the uuid module. (GH-5608). (#5654) Message-ID: https://github.com/python/cpython/commit/c3f9d7e0ea30e94c901d13e1d43ff0be1e5dbcb7 commit: c3f9d7e0ea30e94c901d13e1d43ff0be1e5dbcb7 branch: 3.6 author: Serhiy Storchaka committer: GitHub date: 2018-02-13T11:15:21+02:00 summary: [3.6] bpo-32370: Use the correct encoding for ipconfig output in the uuid module. (GH-5608). (#5654) (cherry picked from commit da6c3da6c33c6bf794f741e348b9c6d86cc43ec5) Co-authored-by: Segev Finer files: A Misc/NEWS.d/next/Windows/2018-02-10-15-38-19.bpo-32370.kcKuct.rst M Lib/uuid.py diff --git a/Lib/uuid.py b/Lib/uuid.py index 3cd67fcfd093..32a48eaeacff 100644 --- a/Lib/uuid.py +++ b/Lib/uuid.py @@ -419,7 +419,7 @@ def _netstat_getnode(): def _ipconfig_getnode(): """Get the hardware address on Windows by running ipconfig.exe.""" - import os, re + import os, re, subprocess dirs = ['', r'c:\windows\system32', r'c:\winnt\system32'] try: import ctypes @@ -430,11 +430,13 @@ def _ipconfig_getnode(): pass for dir in dirs: try: - pipe = os.popen(os.path.join(dir, 'ipconfig') + ' /all') + proc = subprocess.Popen([os.path.join(dir, 'ipconfig'), '/all'], + stdout=subprocess.PIPE, + encoding="oem") except OSError: continue - with pipe: - for line in pipe: + 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): return int(value.replace('-', ''), 16) diff --git a/Misc/NEWS.d/next/Windows/2018-02-10-15-38-19.bpo-32370.kcKuct.rst b/Misc/NEWS.d/next/Windows/2018-02-10-15-38-19.bpo-32370.kcKuct.rst new file mode 100644 index 000000000000..7f076d45bef9 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2018-02-10-15-38-19.bpo-32370.kcKuct.rst @@ -0,0 +1,2 @@ +Use the correct encoding for ipconfig output in the uuid module. +Patch by Segev Finer. From webhook-mailer at python.org Tue Feb 13 04:32:54 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 13 Feb 2018 09:32:54 -0000 Subject: [Python-checkins] bpo-32827: Fix usage of _PyUnicodeWriter_Prepare() in decoding errors handler. (GH-5636) Message-ID: https://github.com/python/cpython/commit/310b424c476e3de3370990e5b9a10acc64ed17f8 commit: 310b424c476e3de3370990e5b9a10acc64ed17f8 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-13T01:32:46-08:00 summary: bpo-32827: Fix usage of _PyUnicodeWriter_Prepare() in decoding errors handler. (GH-5636) (cherry picked from commit b7e2d67f7c035f09c921ca4e7a36529cd502ccf7) Co-authored-by: Serhiy Storchaka files: M Objects/unicodeobject.c diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index a246756d9412..bed7d419b070 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -4500,7 +4500,7 @@ unicode_decode_call_errorhandler_writer( } if (need_to_grow) { writer->overallocate = 1; - if (_PyUnicodeWriter_Prepare(writer, writer->min_length, + if (_PyUnicodeWriter_Prepare(writer, writer->min_length - writer->pos, PyUnicode_MAX_CHAR_VALUE(repunicode)) == -1) goto onError; } @@ -6176,9 +6176,7 @@ _PyUnicode_DecodeUnicodeEscape(const char *s, &writer)) { goto onError; } - if (_PyUnicodeWriter_Prepare(&writer, writer.min_length, 127) < 0) { - goto onError; - } + assert(end - s <= writer.size - writer.pos); #undef WRITE_ASCII_CHAR #undef WRITE_CHAR @@ -6455,9 +6453,7 @@ PyUnicode_DecodeRawUnicodeEscape(const char *s, &writer)) { goto onError; } - if (_PyUnicodeWriter_Prepare(&writer, writer.min_length, 127) < 0) { - goto onError; - } + assert(end - s <= writer.size - writer.pos); #undef WRITE_CHAR } From webhook-mailer at python.org Tue Feb 13 05:28:41 2018 From: webhook-mailer at python.org (INADA Naoki) Date: Tue, 13 Feb 2018 10:28:41 -0000 Subject: [Python-checkins] bpo-31787: Prevent refleaks when calling __init__() more than once (GH-3995) Message-ID: https://github.com/python/cpython/commit/d019bc8319ea35e93bf4baa38098ff1b57cd3ee5 commit: d019bc8319ea35e93bf4baa38098ff1b57cd3ee5 branch: master author: Oren Milman committer: INADA Naoki date: 2018-02-13T19:28:33+09:00 summary: bpo-31787: Prevent refleaks when calling __init__() more than once (GH-3995) files: A Misc/NEWS.d/next/Library/2018-02-09-21-41-56.bpo-31787.owSZ2t.rst M Lib/test/test_asyncio/test_tasks.py M Lib/test/test_bz2.py M Lib/test/test_descr.py M Lib/test/test_hashlib.py M Lib/test/test_lzma.py M Lib/test/test_property.py M Modules/_asynciomodule.c M Modules/_bz2module.c M Modules/_hashopenssl.c M Modules/_lzmamodule.c M Objects/descrobject.c M Objects/funcobject.c diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index 19cf1e667fc4..e5334c6ff914 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -2373,6 +2373,20 @@ class CTask_CFuture_Tests(BaseTaskTests, SetMethodsTest, Task = getattr(tasks, '_CTask', None) Future = getattr(futures, '_CFuture', None) + @support.refcount_test + def test_refleaks_in_task___init__(self): + gettotalrefcount = support.get_attribute(sys, 'gettotalrefcount') + @asyncio.coroutine + def coro(): + pass + task = self.new_task(self.loop, coro()) + self.loop.run_until_complete(task) + refs_before = gettotalrefcount() + for i in range(100): + task.__init__(coro(), loop=self.loop) + self.loop.run_until_complete(task) + self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10) + @unittest.skipUnless(hasattr(futures, '_CFuture') and hasattr(tasks, '_CTask'), diff --git a/Lib/test/test_bz2.py b/Lib/test/test_bz2.py index 58abdc1a0668..003497f28b16 100644 --- a/Lib/test/test_bz2.py +++ b/Lib/test/test_bz2.py @@ -13,6 +13,7 @@ import threading from test.support import unlink import _compression +import sys # Skip tests if the bz2 module doesn't exist. @@ -816,6 +817,16 @@ def test_failure(self): # Previously, a second call could crash due to internal inconsistency self.assertRaises(Exception, bzd.decompress, self.BAD_DATA * 30) + @support.refcount_test + def test_refleaks_in___init__(self): + gettotalrefcount = support.get_attribute(sys, 'gettotalrefcount') + bzd = BZ2Decompressor() + refs_before = gettotalrefcount() + for i in range(100): + bzd.__init__() + self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10) + + class CompressDecompressTest(BaseTest): def testCompress(self): data = bz2.compress(self.TEXT) diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index d24d005ccfaa..0e7728ebf2d7 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -1559,6 +1559,15 @@ def f(cls, arg): return (cls, arg) del cm.x self.assertNotHasAttr(cm, "x") + @support.refcount_test + def test_refleaks_in_classmethod___init__(self): + gettotalrefcount = support.get_attribute(sys, 'gettotalrefcount') + cm = classmethod(None) + refs_before = gettotalrefcount() + for i in range(100): + cm.__init__(None) + self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10) + @support.impl_detail("the module 'xxsubtype' is internal") def test_classmethods_in_c(self): # Testing C-based class methods... @@ -1614,6 +1623,15 @@ class D(C): del sm.x self.assertNotHasAttr(sm, "x") + @support.refcount_test + def test_refleaks_in_staticmethod___init__(self): + gettotalrefcount = support.get_attribute(sys, 'gettotalrefcount') + sm = staticmethod(None) + refs_before = gettotalrefcount() + for i in range(100): + sm.__init__(None) + self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10) + @support.impl_detail("the module 'xxsubtype' is internal") def test_staticmethods_in_c(self): # Testing C-based static methods... diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py index 751f74813d35..f7df872793c2 100644 --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py @@ -162,6 +162,15 @@ def hash_constructors(self): constructors = self.constructors_to_test.values() return itertools.chain.from_iterable(constructors) + @support.refcount_test + def test_refleaks_in_hash___init__(self): + gettotalrefcount = support.get_attribute(sys, 'gettotalrefcount') + sha1_hash = c_hashlib.new('sha1') + refs_before = gettotalrefcount() + for i in range(100): + sha1_hash.__init__('sha1') + self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10) + def test_hash_array(self): a = array.array("b", range(10)) for cons in self.hash_constructors: diff --git a/Lib/test/test_lzma.py b/Lib/test/test_lzma.py index d7a8576d5123..3dc2c1e7e3b7 100644 --- a/Lib/test/test_lzma.py +++ b/Lib/test/test_lzma.py @@ -4,6 +4,8 @@ import pathlib import pickle import random +import sys +from test import support import unittest from test.support import ( @@ -364,6 +366,15 @@ def test_pickle(self): with self.assertRaises(TypeError): pickle.dumps(LZMADecompressor(), proto) + @support.refcount_test + def test_refleaks_in_decompressor___init__(self): + gettotalrefcount = support.get_attribute(sys, 'gettotalrefcount') + lzd = LZMADecompressor() + refs_before = gettotalrefcount() + for i in range(100): + lzd.__init__() + self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10) + class CompressDecompressFunctionTestCase(unittest.TestCase): diff --git a/Lib/test/test_property.py b/Lib/test/test_property.py index 26b7d5283a22..f6f8f5ed0e45 100644 --- a/Lib/test/test_property.py +++ b/Lib/test/test_property.py @@ -3,6 +3,7 @@ import sys import unittest +from test import support class PropertyBase(Exception): pass @@ -173,6 +174,16 @@ def spam(self): sub.__class__.spam.__doc__ = 'Spam' self.assertEqual(sub.__class__.spam.__doc__, 'Spam') + @support.refcount_test + def test_refleaks_in___init__(self): + gettotalrefcount = support.get_attribute(sys, 'gettotalrefcount') + fake_prop = property('fget', 'fset', 'fdel', 'doc') + refs_before = gettotalrefcount() + for i in range(100): + fake_prop.__init__('fget', 'fset', 'fdel', 'doc') + self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10) + + # Issue 5890: subclasses of property do not preserve method __doc__ strings class PropertySub(property): """This is a subclass of property""" diff --git a/Misc/NEWS.d/next/Library/2018-02-09-21-41-56.bpo-31787.owSZ2t.rst b/Misc/NEWS.d/next/Library/2018-02-09-21-41-56.bpo-31787.owSZ2t.rst new file mode 100644 index 000000000000..f0cde59d740f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-09-21-41-56.bpo-31787.owSZ2t.rst @@ -0,0 +1,2 @@ +Fixed refleaks of ``__init__()`` methods in various modules. +(Contributed by Oren Milman) diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index e82425bf2fd7..d66cc4cf0a5f 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -458,6 +458,7 @@ future_schedule_callbacks(FutureObj *fut) return 0; } + static int future_init(FutureObj *fut, PyObject *loop) { @@ -465,6 +466,19 @@ future_init(FutureObj *fut, PyObject *loop) int is_true; _Py_IDENTIFIER(get_debug); + // Same to FutureObj_clear() but not clearing fut->dict + Py_CLEAR(fut->fut_loop); + Py_CLEAR(fut->fut_callback0); + Py_CLEAR(fut->fut_context0); + Py_CLEAR(fut->fut_callbacks); + Py_CLEAR(fut->fut_result); + Py_CLEAR(fut->fut_exception); + Py_CLEAR(fut->fut_source_tb); + + fut->fut_state = STATE_PENDING; + fut->fut_log_tb = 0; + fut->fut_blocking = 0; + if (loop == Py_None) { loop = get_event_loop(); if (loop == NULL) { @@ -474,7 +488,7 @@ future_init(FutureObj *fut, PyObject *loop) else { Py_INCREF(loop); } - Py_XSETREF(fut->fut_loop, loop); + fut->fut_loop = loop; res = _PyObject_CallMethodId(fut->fut_loop, &PyId_get_debug, NULL); if (res == NULL) { @@ -486,16 +500,12 @@ future_init(FutureObj *fut, PyObject *loop) return -1; } if (is_true) { - Py_XSETREF(fut->fut_source_tb, _PyObject_CallNoArg(traceback_extract_stack)); + fut->fut_source_tb = _PyObject_CallNoArg(traceback_extract_stack); if (fut->fut_source_tb == NULL) { return -1; } } - fut->fut_callback0 = NULL; - fut->fut_context0 = NULL; - fut->fut_callbacks = NULL; - return 0; } @@ -1938,16 +1948,16 @@ _asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop) return -1; } - self->task_context = PyContext_CopyCurrent(); + Py_XSETREF(self->task_context, PyContext_CopyCurrent()); if (self->task_context == NULL) { return -1; } - self->task_fut_waiter = NULL; + Py_CLEAR(self->task_fut_waiter); self->task_must_cancel = 0; self->task_log_destroy_pending = 1; Py_INCREF(coro); - self->task_coro = coro; + Py_XSETREF(self->task_coro, coro); if (task_call_step_soon(self, NULL)) { return -1; diff --git a/Modules/_bz2module.c b/Modules/_bz2module.c index dba0e19384ab..0789b6179e52 100644 --- a/Modules/_bz2module.c +++ b/Modules/_bz2module.c @@ -644,7 +644,7 @@ _bz2_BZ2Decompressor___init___impl(BZ2Decompressor *self) self->bzs_avail_in_real = 0; self->input_buffer = NULL; self->input_buffer_size = 0; - self->unused_data = PyBytes_FromStringAndSize(NULL, 0); + Py_XSETREF(self->unused_data, PyBytes_FromStringAndSize(NULL, 0)); if (self->unused_data == NULL) goto error; diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c index 44d3f634fe4a..b6dcc0699233 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -369,8 +369,8 @@ EVP_tp_init(EVPobject *self, PyObject *args, PyObject *kwds) return -1; } - self->name = name_obj; - Py_INCREF(self->name); + Py_INCREF(name_obj); + Py_XSETREF(self->name, name_obj); if (data_obj) { if (view.len >= HASHLIB_GIL_MINSIZE) { diff --git a/Modules/_lzmamodule.c b/Modules/_lzmamodule.c index fd3bbb80bce1..5bcd088d7721 100644 --- a/Modules/_lzmamodule.c +++ b/Modules/_lzmamodule.c @@ -1173,7 +1173,7 @@ _lzma_LZMADecompressor___init___impl(Decompressor *self, int format, self->needs_input = 1; self->input_buffer = NULL; self->input_buffer_size = 0; - self->unused_data = PyBytes_FromStringAndSize(NULL, 0); + Py_XSETREF(self->unused_data, PyBytes_FromStringAndSize(NULL, 0)); if (self->unused_data == NULL) goto error; diff --git a/Objects/descrobject.c b/Objects/descrobject.c index a2530184cd3d..601403940299 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -1490,10 +1490,10 @@ property_init_impl(propertyobject *self, PyObject *fget, PyObject *fset, Py_XINCREF(fdel); Py_XINCREF(doc); - self->prop_get = fget; - self->prop_set = fset; - self->prop_del = fdel; - self->prop_doc = doc; + Py_XSETREF(self->prop_get, fget); + Py_XSETREF(self->prop_set, fset); + Py_XSETREF(self->prop_del, fdel); + Py_XSETREF(self->prop_doc, doc); self->getter_doc = 0; /* if no docstring given and the getter has one, use that one */ diff --git a/Objects/funcobject.c b/Objects/funcobject.c index d376f9cab90b..241685d5b7bb 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -709,7 +709,7 @@ cm_init(PyObject *self, PyObject *args, PyObject *kwds) if (!PyArg_UnpackTuple(args, "classmethod", 1, 1, &callable)) return -1; Py_INCREF(callable); - cm->cm_callable = callable; + Py_XSETREF(cm->cm_callable, callable); return 0; } @@ -890,7 +890,7 @@ sm_init(PyObject *self, PyObject *args, PyObject *kwds) if (!PyArg_UnpackTuple(args, "staticmethod", 1, 1, &callable)) return -1; Py_INCREF(callable); - sm->sm_callable = callable; + Py_XSETREF(sm->sm_callable, callable); return 0; } From webhook-mailer at python.org Tue Feb 13 05:33:35 2018 From: webhook-mailer at python.org (Xiang Zhang) Date: Tue, 13 Feb 2018 10:33:35 -0000 Subject: [Python-checkins] bpo-29803: remove a redandunt op and fix a comment in unicodeobject.c (#660) Message-ID: https://github.com/python/cpython/commit/2b77a921e6a4dee236047ac8d69cf9f915916fdc commit: 2b77a921e6a4dee236047ac8d69cf9f915916fdc branch: master author: Xiang Zhang committer: GitHub date: 2018-02-13T18:33:32+08:00 summary: bpo-29803: remove a redandunt op and fix a comment in unicodeobject.c (#660) files: M Objects/unicodeobject.c diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 02334382cabe..1ae2f5e018fe 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -3727,10 +3727,6 @@ PyUnicode_FSDecoder(PyObject* arg, void* addr) } if (PyUnicode_Check(path)) { - if (PyUnicode_READY(path) == -1) { - Py_DECREF(path); - return 0; - } output = path; } else if (PyBytes_Check(path) || is_buffer) { @@ -6426,7 +6422,7 @@ PyUnicode_AsRawUnicodeEscapeString(PyObject *unicode) if (ch < 0x100) { *p++ = (char) ch; } - /* U+0000-U+00ff range: Map 16-bit characters to '\uHHHH' */ + /* U+0100-U+ffff range: Map 16-bit characters to '\uHHHH' */ else if (ch < 0x10000) { *p++ = '\\'; *p++ = 'u'; From webhook-mailer at python.org Tue Feb 13 06:32:22 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 13 Feb 2018 11:32:22 -0000 Subject: [Python-checkins] bpo-31787: Prevent refleaks when calling __init__() more than once (GH-3995) Message-ID: https://github.com/python/cpython/commit/ef20abed7f2ae0ba54b1d287f5fe601be80c1128 commit: ef20abed7f2ae0ba54b1d287f5fe601be80c1128 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-13T03:32:18-08:00 summary: bpo-31787: Prevent refleaks when calling __init__() more than once (GH-3995) (cherry picked from commit d019bc8319ea35e93bf4baa38098ff1b57cd3ee5) Co-authored-by: Oren Milman files: A Misc/NEWS.d/next/Library/2018-02-09-21-41-56.bpo-31787.owSZ2t.rst M Lib/test/test_asyncio/test_tasks.py M Lib/test/test_bz2.py M Lib/test/test_descr.py M Lib/test/test_hashlib.py M Lib/test/test_lzma.py M Lib/test/test_property.py M Modules/_asynciomodule.c M Modules/_bz2module.c M Modules/_hashopenssl.c M Modules/_lzmamodule.c M Objects/descrobject.c M Objects/funcobject.c diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index 19cf1e667fc4..e5334c6ff914 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -2373,6 +2373,20 @@ class CTask_CFuture_Tests(BaseTaskTests, SetMethodsTest, Task = getattr(tasks, '_CTask', None) Future = getattr(futures, '_CFuture', None) + @support.refcount_test + def test_refleaks_in_task___init__(self): + gettotalrefcount = support.get_attribute(sys, 'gettotalrefcount') + @asyncio.coroutine + def coro(): + pass + task = self.new_task(self.loop, coro()) + self.loop.run_until_complete(task) + refs_before = gettotalrefcount() + for i in range(100): + task.__init__(coro(), loop=self.loop) + self.loop.run_until_complete(task) + self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10) + @unittest.skipUnless(hasattr(futures, '_CFuture') and hasattr(tasks, '_CTask'), diff --git a/Lib/test/test_bz2.py b/Lib/test/test_bz2.py index 58abdc1a0668..003497f28b16 100644 --- a/Lib/test/test_bz2.py +++ b/Lib/test/test_bz2.py @@ -13,6 +13,7 @@ import threading from test.support import unlink import _compression +import sys # Skip tests if the bz2 module doesn't exist. @@ -816,6 +817,16 @@ def test_failure(self): # Previously, a second call could crash due to internal inconsistency self.assertRaises(Exception, bzd.decompress, self.BAD_DATA * 30) + @support.refcount_test + def test_refleaks_in___init__(self): + gettotalrefcount = support.get_attribute(sys, 'gettotalrefcount') + bzd = BZ2Decompressor() + refs_before = gettotalrefcount() + for i in range(100): + bzd.__init__() + self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10) + + class CompressDecompressTest(BaseTest): def testCompress(self): data = bz2.compress(self.TEXT) diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index d24d005ccfaa..0e7728ebf2d7 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -1559,6 +1559,15 @@ def f(cls, arg): return (cls, arg) del cm.x self.assertNotHasAttr(cm, "x") + @support.refcount_test + def test_refleaks_in_classmethod___init__(self): + gettotalrefcount = support.get_attribute(sys, 'gettotalrefcount') + cm = classmethod(None) + refs_before = gettotalrefcount() + for i in range(100): + cm.__init__(None) + self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10) + @support.impl_detail("the module 'xxsubtype' is internal") def test_classmethods_in_c(self): # Testing C-based class methods... @@ -1614,6 +1623,15 @@ class D(C): del sm.x self.assertNotHasAttr(sm, "x") + @support.refcount_test + def test_refleaks_in_staticmethod___init__(self): + gettotalrefcount = support.get_attribute(sys, 'gettotalrefcount') + sm = staticmethod(None) + refs_before = gettotalrefcount() + for i in range(100): + sm.__init__(None) + self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10) + @support.impl_detail("the module 'xxsubtype' is internal") def test_staticmethods_in_c(self): # Testing C-based static methods... diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py index 751f74813d35..f7df872793c2 100644 --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py @@ -162,6 +162,15 @@ def hash_constructors(self): constructors = self.constructors_to_test.values() return itertools.chain.from_iterable(constructors) + @support.refcount_test + def test_refleaks_in_hash___init__(self): + gettotalrefcount = support.get_attribute(sys, 'gettotalrefcount') + sha1_hash = c_hashlib.new('sha1') + refs_before = gettotalrefcount() + for i in range(100): + sha1_hash.__init__('sha1') + self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10) + def test_hash_array(self): a = array.array("b", range(10)) for cons in self.hash_constructors: diff --git a/Lib/test/test_lzma.py b/Lib/test/test_lzma.py index d7a8576d5123..3dc2c1e7e3b7 100644 --- a/Lib/test/test_lzma.py +++ b/Lib/test/test_lzma.py @@ -4,6 +4,8 @@ import pathlib import pickle import random +import sys +from test import support import unittest from test.support import ( @@ -364,6 +366,15 @@ def test_pickle(self): with self.assertRaises(TypeError): pickle.dumps(LZMADecompressor(), proto) + @support.refcount_test + def test_refleaks_in_decompressor___init__(self): + gettotalrefcount = support.get_attribute(sys, 'gettotalrefcount') + lzd = LZMADecompressor() + refs_before = gettotalrefcount() + for i in range(100): + lzd.__init__() + self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10) + class CompressDecompressFunctionTestCase(unittest.TestCase): diff --git a/Lib/test/test_property.py b/Lib/test/test_property.py index 26b7d5283a22..f6f8f5ed0e45 100644 --- a/Lib/test/test_property.py +++ b/Lib/test/test_property.py @@ -3,6 +3,7 @@ import sys import unittest +from test import support class PropertyBase(Exception): pass @@ -173,6 +174,16 @@ def spam(self): sub.__class__.spam.__doc__ = 'Spam' self.assertEqual(sub.__class__.spam.__doc__, 'Spam') + @support.refcount_test + def test_refleaks_in___init__(self): + gettotalrefcount = support.get_attribute(sys, 'gettotalrefcount') + fake_prop = property('fget', 'fset', 'fdel', 'doc') + refs_before = gettotalrefcount() + for i in range(100): + fake_prop.__init__('fget', 'fset', 'fdel', 'doc') + self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10) + + # Issue 5890: subclasses of property do not preserve method __doc__ strings class PropertySub(property): """This is a subclass of property""" diff --git a/Misc/NEWS.d/next/Library/2018-02-09-21-41-56.bpo-31787.owSZ2t.rst b/Misc/NEWS.d/next/Library/2018-02-09-21-41-56.bpo-31787.owSZ2t.rst new file mode 100644 index 000000000000..f0cde59d740f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-09-21-41-56.bpo-31787.owSZ2t.rst @@ -0,0 +1,2 @@ +Fixed refleaks of ``__init__()`` methods in various modules. +(Contributed by Oren Milman) diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index e82425bf2fd7..d66cc4cf0a5f 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -458,6 +458,7 @@ future_schedule_callbacks(FutureObj *fut) return 0; } + static int future_init(FutureObj *fut, PyObject *loop) { @@ -465,6 +466,19 @@ future_init(FutureObj *fut, PyObject *loop) int is_true; _Py_IDENTIFIER(get_debug); + // Same to FutureObj_clear() but not clearing fut->dict + Py_CLEAR(fut->fut_loop); + Py_CLEAR(fut->fut_callback0); + Py_CLEAR(fut->fut_context0); + Py_CLEAR(fut->fut_callbacks); + Py_CLEAR(fut->fut_result); + Py_CLEAR(fut->fut_exception); + Py_CLEAR(fut->fut_source_tb); + + fut->fut_state = STATE_PENDING; + fut->fut_log_tb = 0; + fut->fut_blocking = 0; + if (loop == Py_None) { loop = get_event_loop(); if (loop == NULL) { @@ -474,7 +488,7 @@ future_init(FutureObj *fut, PyObject *loop) else { Py_INCREF(loop); } - Py_XSETREF(fut->fut_loop, loop); + fut->fut_loop = loop; res = _PyObject_CallMethodId(fut->fut_loop, &PyId_get_debug, NULL); if (res == NULL) { @@ -486,16 +500,12 @@ future_init(FutureObj *fut, PyObject *loop) return -1; } if (is_true) { - Py_XSETREF(fut->fut_source_tb, _PyObject_CallNoArg(traceback_extract_stack)); + fut->fut_source_tb = _PyObject_CallNoArg(traceback_extract_stack); if (fut->fut_source_tb == NULL) { return -1; } } - fut->fut_callback0 = NULL; - fut->fut_context0 = NULL; - fut->fut_callbacks = NULL; - return 0; } @@ -1938,16 +1948,16 @@ _asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop) return -1; } - self->task_context = PyContext_CopyCurrent(); + Py_XSETREF(self->task_context, PyContext_CopyCurrent()); if (self->task_context == NULL) { return -1; } - self->task_fut_waiter = NULL; + Py_CLEAR(self->task_fut_waiter); self->task_must_cancel = 0; self->task_log_destroy_pending = 1; Py_INCREF(coro); - self->task_coro = coro; + Py_XSETREF(self->task_coro, coro); if (task_call_step_soon(self, NULL)) { return -1; diff --git a/Modules/_bz2module.c b/Modules/_bz2module.c index dba0e19384ab..0789b6179e52 100644 --- a/Modules/_bz2module.c +++ b/Modules/_bz2module.c @@ -644,7 +644,7 @@ _bz2_BZ2Decompressor___init___impl(BZ2Decompressor *self) self->bzs_avail_in_real = 0; self->input_buffer = NULL; self->input_buffer_size = 0; - self->unused_data = PyBytes_FromStringAndSize(NULL, 0); + Py_XSETREF(self->unused_data, PyBytes_FromStringAndSize(NULL, 0)); if (self->unused_data == NULL) goto error; diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c index 44d3f634fe4a..b6dcc0699233 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -369,8 +369,8 @@ EVP_tp_init(EVPobject *self, PyObject *args, PyObject *kwds) return -1; } - self->name = name_obj; - Py_INCREF(self->name); + Py_INCREF(name_obj); + Py_XSETREF(self->name, name_obj); if (data_obj) { if (view.len >= HASHLIB_GIL_MINSIZE) { diff --git a/Modules/_lzmamodule.c b/Modules/_lzmamodule.c index fd3bbb80bce1..5bcd088d7721 100644 --- a/Modules/_lzmamodule.c +++ b/Modules/_lzmamodule.c @@ -1173,7 +1173,7 @@ _lzma_LZMADecompressor___init___impl(Decompressor *self, int format, self->needs_input = 1; self->input_buffer = NULL; self->input_buffer_size = 0; - self->unused_data = PyBytes_FromStringAndSize(NULL, 0); + Py_XSETREF(self->unused_data, PyBytes_FromStringAndSize(NULL, 0)); if (self->unused_data == NULL) goto error; diff --git a/Objects/descrobject.c b/Objects/descrobject.c index a2530184cd3d..601403940299 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -1490,10 +1490,10 @@ property_init_impl(propertyobject *self, PyObject *fget, PyObject *fset, Py_XINCREF(fdel); Py_XINCREF(doc); - self->prop_get = fget; - self->prop_set = fset; - self->prop_del = fdel; - self->prop_doc = doc; + Py_XSETREF(self->prop_get, fget); + Py_XSETREF(self->prop_set, fset); + Py_XSETREF(self->prop_del, fdel); + Py_XSETREF(self->prop_doc, doc); self->getter_doc = 0; /* if no docstring given and the getter has one, use that one */ diff --git a/Objects/funcobject.c b/Objects/funcobject.c index d376f9cab90b..241685d5b7bb 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -709,7 +709,7 @@ cm_init(PyObject *self, PyObject *args, PyObject *kwds) if (!PyArg_UnpackTuple(args, "classmethod", 1, 1, &callable)) return -1; Py_INCREF(callable); - cm->cm_callable = callable; + Py_XSETREF(cm->cm_callable, callable); return 0; } @@ -890,7 +890,7 @@ sm_init(PyObject *self, PyObject *args, PyObject *kwds) if (!PyArg_UnpackTuple(args, "staticmethod", 1, 1, &callable)) return -1; Py_INCREF(callable); - sm->sm_callable = callable; + Py_XSETREF(sm->sm_callable, callable); return 0; } From webhook-mailer at python.org Tue Feb 13 08:15:29 2018 From: webhook-mailer at python.org (INADA Naoki) Date: Tue, 13 Feb 2018 13:15:29 -0000 Subject: [Python-checkins] bpo-31787: Prevent refleaks when calling __init__() more than once (GH-3995) Message-ID: https://github.com/python/cpython/commit/47316342417146f62653bc3c3dd505bfacc5e956 commit: 47316342417146f62653bc3c3dd505bfacc5e956 branch: 3.6 author: INADA Naoki committer: GitHub date: 2018-02-13T22:15:24+09:00 summary: bpo-31787: Prevent refleaks when calling __init__() more than once (GH-3995) (cherry picked from commit d019bc8319ea35e93bf4baa38098ff1b57cd3ee5) files: A Misc/NEWS.d/next/Library/2018-02-09-21-41-56.bpo-31787.owSZ2t.rst M Lib/test/test_asyncio/test_tasks.py M Lib/test/test_bz2.py M Lib/test/test_descr.py M Lib/test/test_hashlib.py M Lib/test/test_lzma.py M Lib/test/test_property.py M Modules/_asynciomodule.c M Modules/_bz2module.c M Modules/_hashopenssl.c M Modules/_lzmamodule.c M Objects/descrobject.c M Objects/funcobject.c diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py index 42da1fa19548..f41160ba3222 100644 --- a/Lib/test/test_asyncio/test_tasks.py +++ b/Lib/test/test_asyncio/test_tasks.py @@ -2133,6 +2133,20 @@ class CTask_CFuture_Tests(BaseTaskTests, test_utils.TestCase): Task = getattr(tasks, '_CTask', None) Future = getattr(futures, '_CFuture', None) + @support.refcount_test + def test_refleaks_in_task___init__(self): + gettotalrefcount = support.get_attribute(sys, 'gettotalrefcount') + @asyncio.coroutine + def coro(): + pass + task = self.new_task(self.loop, coro()) + self.loop.run_until_complete(task) + refs_before = gettotalrefcount() + for i in range(100): + task.__init__(coro(), loop=self.loop) + self.loop.run_until_complete(task) + self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10) + @unittest.skipUnless(hasattr(futures, '_CFuture'), 'requires the C _asyncio module') diff --git a/Lib/test/test_bz2.py b/Lib/test/test_bz2.py index eaa472a6ccda..f340f2330c3d 100644 --- a/Lib/test/test_bz2.py +++ b/Lib/test/test_bz2.py @@ -13,6 +13,7 @@ import sys from test.support import unlink import _compression +import sys try: import threading @@ -828,6 +829,16 @@ def test_failure(self): # Previously, a second call could crash due to internal inconsistency self.assertRaises(Exception, bzd.decompress, self.BAD_DATA * 30) + @support.refcount_test + def test_refleaks_in___init__(self): + gettotalrefcount = support.get_attribute(sys, 'gettotalrefcount') + bzd = BZ2Decompressor() + refs_before = gettotalrefcount() + for i in range(100): + bzd.__init__() + self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10) + + class CompressDecompressTest(BaseTest): def testCompress(self): data = bz2.compress(self.TEXT) diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index c5bff7718dc7..0d33e9179308 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -1519,6 +1519,15 @@ def f(cls, arg): return (cls, arg) del cm.x self.assertNotHasAttr(cm, "x") + @support.refcount_test + def test_refleaks_in_classmethod___init__(self): + gettotalrefcount = support.get_attribute(sys, 'gettotalrefcount') + cm = classmethod(None) + refs_before = gettotalrefcount() + for i in range(100): + cm.__init__(None) + self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10) + @support.impl_detail("the module 'xxsubtype' is internal") def test_classmethods_in_c(self): # Testing C-based class methods... @@ -1574,6 +1583,15 @@ class D(C): del sm.x self.assertNotHasAttr(sm, "x") + @support.refcount_test + def test_refleaks_in_staticmethod___init__(self): + gettotalrefcount = support.get_attribute(sys, 'gettotalrefcount') + sm = staticmethod(None) + refs_before = gettotalrefcount() + for i in range(100): + sm.__init__(None) + self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10) + @support.impl_detail("the module 'xxsubtype' is internal") def test_staticmethods_in_c(self): # Testing C-based static methods... diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py index 177143e01dc7..751a713b3e8b 100644 --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py @@ -165,6 +165,15 @@ def hash_constructors(self): constructors = self.constructors_to_test.values() return itertools.chain.from_iterable(constructors) + @support.refcount_test + def test_refleaks_in_hash___init__(self): + gettotalrefcount = support.get_attribute(sys, 'gettotalrefcount') + sha1_hash = c_hashlib.new('sha1') + refs_before = gettotalrefcount() + for i in range(100): + sha1_hash.__init__('sha1') + self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10) + def test_hash_array(self): a = array.array("b", range(10)) for cons in self.hash_constructors: diff --git a/Lib/test/test_lzma.py b/Lib/test/test_lzma.py index d7a8576d5123..3dc2c1e7e3b7 100644 --- a/Lib/test/test_lzma.py +++ b/Lib/test/test_lzma.py @@ -4,6 +4,8 @@ import pathlib import pickle import random +import sys +from test import support import unittest from test.support import ( @@ -364,6 +366,15 @@ def test_pickle(self): with self.assertRaises(TypeError): pickle.dumps(LZMADecompressor(), proto) + @support.refcount_test + def test_refleaks_in_decompressor___init__(self): + gettotalrefcount = support.get_attribute(sys, 'gettotalrefcount') + lzd = LZMADecompressor() + refs_before = gettotalrefcount() + for i in range(100): + lzd.__init__() + self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10) + class CompressDecompressFunctionTestCase(unittest.TestCase): diff --git a/Lib/test/test_property.py b/Lib/test/test_property.py index 26b7d5283a22..f6f8f5ed0e45 100644 --- a/Lib/test/test_property.py +++ b/Lib/test/test_property.py @@ -3,6 +3,7 @@ import sys import unittest +from test import support class PropertyBase(Exception): pass @@ -173,6 +174,16 @@ def spam(self): sub.__class__.spam.__doc__ = 'Spam' self.assertEqual(sub.__class__.spam.__doc__, 'Spam') + @support.refcount_test + def test_refleaks_in___init__(self): + gettotalrefcount = support.get_attribute(sys, 'gettotalrefcount') + fake_prop = property('fget', 'fset', 'fdel', 'doc') + refs_before = gettotalrefcount() + for i in range(100): + fake_prop.__init__('fget', 'fset', 'fdel', 'doc') + self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10) + + # Issue 5890: subclasses of property do not preserve method __doc__ strings class PropertySub(property): """This is a subclass of property""" diff --git a/Misc/NEWS.d/next/Library/2018-02-09-21-41-56.bpo-31787.owSZ2t.rst b/Misc/NEWS.d/next/Library/2018-02-09-21-41-56.bpo-31787.owSZ2t.rst new file mode 100644 index 000000000000..f0cde59d740f --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-09-21-41-56.bpo-31787.owSZ2t.rst @@ -0,0 +1,2 @@ +Fixed refleaks of ``__init__()`` methods in various modules. +(Contributed by Oren Milman) diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 35632a6e6faa..f53387115e73 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -132,6 +132,7 @@ future_schedule_callbacks(FutureObj *fut) return 0; } + static int future_init(FutureObj *fut, PyObject *loop) { @@ -139,6 +140,17 @@ future_init(FutureObj *fut, PyObject *loop) int is_true; _Py_IDENTIFIER(get_debug); + // Same to FutureObj_clear() but not clearing fut->dict + Py_CLEAR(fut->fut_loop); + Py_CLEAR(fut->fut_callbacks); + Py_CLEAR(fut->fut_result); + Py_CLEAR(fut->fut_exception); + Py_CLEAR(fut->fut_source_tb); + + fut->fut_state = STATE_PENDING; + fut->fut_log_tb = 0; + fut->fut_blocking = 0; + if (loop == Py_None) { loop = _PyObject_CallNoArg(asyncio_get_event_loop); if (loop == NULL) { @@ -148,7 +160,7 @@ future_init(FutureObj *fut, PyObject *loop) else { Py_INCREF(loop); } - Py_XSETREF(fut->fut_loop, loop); + fut->fut_loop = loop; res = _PyObject_CallMethodId(fut->fut_loop, &PyId_get_debug, NULL); if (res == NULL) { @@ -160,13 +172,13 @@ future_init(FutureObj *fut, PyObject *loop) return -1; } if (is_true) { - Py_XSETREF(fut->fut_source_tb, _PyObject_CallNoArg(traceback_extract_stack)); + fut->fut_source_tb = _PyObject_CallNoArg(traceback_extract_stack); if (fut->fut_source_tb == NULL) { return -1; } } - Py_XSETREF(fut->fut_callbacks, PyList_New(0)); + fut->fut_callbacks = PyList_New(0); if (fut->fut_callbacks == NULL) { return -1; } @@ -1336,12 +1348,12 @@ _asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop) return -1; } - self->task_fut_waiter = NULL; + Py_CLEAR(self->task_fut_waiter); self->task_must_cancel = 0; self->task_log_destroy_pending = 1; Py_INCREF(coro); - self->task_coro = coro; + Py_XSETREF(self->task_coro, coro); if (task_call_step_soon(self, NULL)) { return -1; diff --git a/Modules/_bz2module.c b/Modules/_bz2module.c index 5cea42cc6b2f..9c5a631eff45 100644 --- a/Modules/_bz2module.c +++ b/Modules/_bz2module.c @@ -663,7 +663,7 @@ _bz2_BZ2Decompressor___init___impl(BZ2Decompressor *self) self->bzs_avail_in_real = 0; self->input_buffer = NULL; self->input_buffer_size = 0; - self->unused_data = PyBytes_FromStringAndSize(NULL, 0); + Py_XSETREF(self->unused_data, PyBytes_FromStringAndSize(NULL, 0)); if (self->unused_data == NULL) goto error; diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c index 8670fbd4572d..8f6185ccb73b 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -378,8 +378,8 @@ EVP_tp_init(EVPobject *self, PyObject *args, PyObject *kwds) return -1; } - self->name = name_obj; - Py_INCREF(self->name); + Py_INCREF(name_obj); + Py_XSETREF(self->name, name_obj); if (data_obj) { if (view.len >= HASHLIB_GIL_MINSIZE) { diff --git a/Modules/_lzmamodule.c b/Modules/_lzmamodule.c index bb77552b67b1..b25faff5ac49 100644 --- a/Modules/_lzmamodule.c +++ b/Modules/_lzmamodule.c @@ -1192,7 +1192,7 @@ _lzma_LZMADecompressor___init___impl(Decompressor *self, int format, self->needs_input = 1; self->input_buffer = NULL; self->input_buffer_size = 0; - self->unused_data = PyBytes_FromStringAndSize(NULL, 0); + Py_XSETREF(self->unused_data, PyBytes_FromStringAndSize(NULL, 0)); if (self->unused_data == NULL) goto error; diff --git a/Objects/descrobject.c b/Objects/descrobject.c index 076e74148148..9020ccd32547 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -1483,10 +1483,10 @@ property_init(PyObject *self, PyObject *args, PyObject *kwds) Py_XINCREF(del); Py_XINCREF(doc); - prop->prop_get = get; - prop->prop_set = set; - prop->prop_del = del; - prop->prop_doc = doc; + Py_XSETREF(prop->prop_get, get); + Py_XSETREF(prop->prop_set, set); + Py_XSETREF(prop->prop_del, del); + Py_XSETREF(prop->prop_doc, doc); prop->getter_doc = 0; /* if no docstring given and the getter has one, use that one */ diff --git a/Objects/funcobject.c b/Objects/funcobject.c index 69cd973384b2..6ce0cb43e5e9 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -745,7 +745,7 @@ cm_init(PyObject *self, PyObject *args, PyObject *kwds) if (!_PyArg_NoKeywords("classmethod", kwds)) return -1; Py_INCREF(callable); - cm->cm_callable = callable; + Py_XSETREF(cm->cm_callable, callable); return 0; } @@ -926,7 +926,7 @@ sm_init(PyObject *self, PyObject *args, PyObject *kwds) if (!_PyArg_NoKeywords("staticmethod", kwds)) return -1; Py_INCREF(callable); - sm->sm_callable = callable; + Py_XSETREF(sm->sm_callable, callable); return 0; } From webhook-mailer at python.org Tue Feb 13 09:41:24 2018 From: webhook-mailer at python.org (INADA Naoki) Date: Tue, 13 Feb 2018 14:41:24 -0000 Subject: [Python-checkins] bpo-31787: Skip refleak check when _hashlib is not available (GH-5660) Message-ID: https://github.com/python/cpython/commit/f0bc645dfede8118c84844bad319cd952c4d1905 commit: f0bc645dfede8118c84844bad319cd952c4d1905 branch: master author: INADA Naoki committer: GitHub date: 2018-02-13T23:41:19+09:00 summary: bpo-31787: Skip refleak check when _hashlib is not available (GH-5660) files: M Lib/test/test_hashlib.py diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py index f7df872793c2..5b0218b08567 100644 --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py @@ -163,6 +163,7 @@ def hash_constructors(self): return itertools.chain.from_iterable(constructors) @support.refcount_test + @unittest.skipIf(c_hashlib is None, 'Require _hashlib module') def test_refleaks_in_hash___init__(self): gettotalrefcount = support.get_attribute(sys, 'gettotalrefcount') sha1_hash = c_hashlib.new('sha1') From webhook-mailer at python.org Tue Feb 13 10:07:40 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 13 Feb 2018 15:07:40 -0000 Subject: [Python-checkins] bpo-31787: Skip refleak check when _hashlib is not available (GH-5660) Message-ID: https://github.com/python/cpython/commit/e81a6c86c89da02a0da719926198ab72edab2e05 commit: e81a6c86c89da02a0da719926198ab72edab2e05 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-13T07:07:34-08:00 summary: bpo-31787: Skip refleak check when _hashlib is not available (GH-5660) (cherry picked from commit f0bc645dfede8118c84844bad319cd952c4d1905) Co-authored-by: INADA Naoki files: M Lib/test/test_hashlib.py diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py index f7df872793c2..5b0218b08567 100644 --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py @@ -163,6 +163,7 @@ def hash_constructors(self): return itertools.chain.from_iterable(constructors) @support.refcount_test + @unittest.skipIf(c_hashlib is None, 'Require _hashlib module') def test_refleaks_in_hash___init__(self): gettotalrefcount = support.get_attribute(sys, 'gettotalrefcount') sha1_hash = c_hashlib.new('sha1') From webhook-mailer at python.org Tue Feb 13 10:33:53 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 13 Feb 2018 15:33:53 -0000 Subject: [Python-checkins] bpo-31787: Skip refleak check when _hashlib is not available (GH-5660) Message-ID: https://github.com/python/cpython/commit/5d0d0eaf3ccee4349a5bed6e7741d09d56f2ab50 commit: 5d0d0eaf3ccee4349a5bed6e7741d09d56f2ab50 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-13T07:33:50-08:00 summary: bpo-31787: Skip refleak check when _hashlib is not available (GH-5660) (cherry picked from commit f0bc645dfede8118c84844bad319cd952c4d1905) Co-authored-by: INADA Naoki files: M Lib/test/test_hashlib.py diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py index 751a713b3e8b..220b5febc2fe 100644 --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py @@ -166,6 +166,7 @@ def hash_constructors(self): return itertools.chain.from_iterable(constructors) @support.refcount_test + @unittest.skipIf(c_hashlib is None, 'Require _hashlib module') def test_refleaks_in_hash___init__(self): gettotalrefcount = support.get_attribute(sys, 'gettotalrefcount') sha1_hash = c_hashlib.new('sha1') From webhook-mailer at python.org Tue Feb 13 19:08:57 2018 From: webhook-mailer at python.org (Berker Peksag) Date: Wed, 14 Feb 2018 00:08:57 -0000 Subject: [Python-checkins] bpo-27846: Delete incorrect note in base64 docs (GH-5666) Message-ID: https://github.com/python/cpython/commit/88c38a4049ded0e1f197fec3e76be7c0c0e83d7a commit: 88c38a4049ded0e1f197fec3e76be7c0c0e83d7a branch: master author: Zackery Spytz committer: Berker Peksag date: 2018-02-14T03:08:54+03:00 summary: bpo-27846: Delete incorrect note in base64 docs (GH-5666) This note incorrectly stated that "Base64 has an expansion factor of 6 to 4" (it is actually 4 to 3). It was decided to remove the note. files: M Doc/library/base64.rst diff --git a/Doc/library/base64.rst b/Doc/library/base64.rst index ceecf17cba23..ad9f5f58bee2 100644 --- a/Doc/library/base64.rst +++ b/Doc/library/base64.rst @@ -218,14 +218,6 @@ The modern interface provides: .. versionadded:: 3.4 -.. note:: - Both Base85 and Ascii85 have an expansion factor of 5 to 4 (5 Base85 or - Ascii85 characters can encode 4 binary bytes), while the better-known - Base64 has an expansion factor of 6 to 4. They are therefore more - efficient when space expensive. They differ by details such as the - character map used for encoding. - - The legacy interface: .. function:: decode(input, output) From webhook-mailer at python.org Tue Feb 13 19:48:03 2018 From: webhook-mailer at python.org (Berker Peksag) Date: Wed, 14 Feb 2018 00:48:03 -0000 Subject: [Python-checkins] bpo-27846: Delete incorrect note in base64 docs (GH-5666) Message-ID: https://github.com/python/cpython/commit/2e8d9003ed7a97955c36fa19a9ce7c43d9ec83e1 commit: 2e8d9003ed7a97955c36fa19a9ce7c43d9ec83e1 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Berker Peksag date: 2018-02-14T03:48:00+03:00 summary: bpo-27846: Delete incorrect note in base64 docs (GH-5666) This note incorrectly stated that "Base64 has an expansion factor of 6 to 4" (it is actually 4 to 3). It was decided to remove the note. (cherry picked from commit 88c38a4049ded0e1f197fec3e76be7c0c0e83d7a) Co-authored-by: Zackery Spytz files: M Doc/library/base64.rst diff --git a/Doc/library/base64.rst b/Doc/library/base64.rst index ceecf17cba23..ad9f5f58bee2 100644 --- a/Doc/library/base64.rst +++ b/Doc/library/base64.rst @@ -218,14 +218,6 @@ The modern interface provides: .. versionadded:: 3.4 -.. note:: - Both Base85 and Ascii85 have an expansion factor of 5 to 4 (5 Base85 or - Ascii85 characters can encode 4 binary bytes), while the better-known - Base64 has an expansion factor of 6 to 4. They are therefore more - efficient when space expensive. They differ by details such as the - character map used for encoding. - - The legacy interface: .. function:: decode(input, output) From webhook-mailer at python.org Tue Feb 13 19:48:32 2018 From: webhook-mailer at python.org (Berker Peksag) Date: Wed, 14 Feb 2018 00:48:32 -0000 Subject: [Python-checkins] bpo-27846: Delete incorrect note in base64 docs (GH-5666) Message-ID: https://github.com/python/cpython/commit/b93a52b136fd2285f2891eef91c50e3d36ea6f36 commit: b93a52b136fd2285f2891eef91c50e3d36ea6f36 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Berker Peksag date: 2018-02-14T03:48:28+03:00 summary: bpo-27846: Delete incorrect note in base64 docs (GH-5666) This note incorrectly stated that "Base64 has an expansion factor of 6 to 4" (it is actually 4 to 3). It was decided to remove the note. (cherry picked from commit 88c38a4049ded0e1f197fec3e76be7c0c0e83d7a) Co-authored-by: Zackery Spytz files: M Doc/library/base64.rst diff --git a/Doc/library/base64.rst b/Doc/library/base64.rst index ceecf17cba23..ad9f5f58bee2 100644 --- a/Doc/library/base64.rst +++ b/Doc/library/base64.rst @@ -218,14 +218,6 @@ The modern interface provides: .. versionadded:: 3.4 -.. note:: - Both Base85 and Ascii85 have an expansion factor of 5 to 4 (5 Base85 or - Ascii85 characters can encode 4 binary bytes), while the better-known - Base64 has an expansion factor of 6 to 4. They are therefore more - efficient when space expensive. They differ by details such as the - character map used for encoding. - - The legacy interface: .. function:: decode(input, output) From webhook-mailer at python.org Tue Feb 13 21:11:37 2018 From: webhook-mailer at python.org (Benjamin Peterson) Date: Wed, 14 Feb 2018 02:11:37 -0000 Subject: [Python-checkins] remove mercurial dot files (GH-5558) Message-ID: https://github.com/python/cpython/commit/2b86f4cb2cd339f545804a9abb8c4d4cc28d9488 commit: 2b86f4cb2cd339f545804a9abb8c4d4cc28d9488 branch: master author: Benjamin Peterson committer: GitHub date: 2018-02-13T18:11:34-08:00 summary: remove mercurial dot files (GH-5558) files: D .hgeol D .hgignore D .hgtags diff --git a/.hgeol b/.hgeol deleted file mode 100644 index eb19a6c88d28..000000000000 --- a/.hgeol +++ /dev/null @@ -1,58 +0,0 @@ -[patterns] - -# Non human-editable files are binary - -**.dsp = BIN -**.dsw = BIN -**.mk = BIN -**.sln = BIN -**.vcproj = BIN -**.vsprops = BIN - -**.aif = BIN -**.aifc = BIN -**.aiff = BIN -**.au = BIN -**.bmp = BIN -**.db = BIN -**.exe = BIN -**.icns = BIN -**.gif = BIN -**.ico = BIN -**.info = BIN -**.jpg = BIN -**.pck = BIN -**.png = BIN -**.psd = BIN -**.tar = BIN -**.wav = BIN -**.whl = BIN -**.xar = BIN -**.zip = BIN - -Lib/test/cjkencodings/* = BIN -Lib/test/decimaltestdata/*.decTest = BIN -Lib/test/sndhdrdata/sndhdr.* = BIN -Lib/test/test_email/data/msg_26.txt = BIN -Lib/test/xmltestdata/* = BIN - -Lib/venv/scripts/nt/* = BIN - -Lib/test/coding20731.py = BIN - -# Windows only zlib upstream file -Modules/zlib/zlib.map = CRLF - -# Windows batch files work best with CRLF, there can be subtle problems with LF -**.bat = CRLF - -# The Windows readme is likely to be read in Notepad, so make it readable -PCbuild/readme.txt = CRLF - -# All other files (which presumably are human-editable) are "native". -# This must be the last rule! - -** = native - -[repository] -native = LF diff --git a/.hgignore b/.hgignore deleted file mode 100644 index 68c607f2e8d4..000000000000 --- a/.hgignore +++ /dev/null @@ -1,106 +0,0 @@ -.gdb_history -.purify -.svn/ -^.idea/ -^.vscode/ -.DS_Store -Makefile$ -Makefile.pre$ -TAGS$ -autom4te.cache$ -^build/ -^Doc/build/ -^Doc/venv/ -buildno$ -config.cache -config.log -config.status -config.status.lineno -db_home -platform$ -pyconfig.h$ -python$ -python.bat$ -python.exe$ -python-config$ -python-config.py$ -reflog.txt$ -tags$ -Misc/python.pc -Misc/python-config.sh$ -Modules/Setup$ -Modules/Setup.config -Modules/Setup.local -Modules/config.c -Modules/ld_so_aix$ -^lcov-report/ -^core -^python-gdb.py -^python.exe-gdb.py -^pybuilddir.txt - -syntax: glob -libpython*.a -libpython*.so* -libpython*.dylib -libpython*.dll -*.swp -*.o -*.pyc -*.pyo -*.pyd -*.cover -*~ -*.gc?? -*.profclang? -*.profraw -*.dyn -Include/pydtrace_probes.h -Lib/distutils/command/*.pdb -Lib/lib2to3/*.pickle -Lib/test/data/* -Misc/*.wpu -PC/python_nt*.h -PC/pythonnt_rc*.h -PC/*/*.exe -PC/*/*.exp -PC/*/*.lib -PC/*/*.bsc -PC/*/*.dll -PC/*/*.pdb -PC/*/*.user -PC/*/*.ncb -PC/*/*.suo -PC/*/Win32-temp-* -PC/*/x64-temp-* -PC/*/amd64 -PCbuild/*.user -PCbuild/*.suo -PCbuild/*.*sdf -PCbuild/*-pgi -PCbuild/*-pgo -PCbuild/.vs -PCbuild/amd64 -PCbuild/obj -PCbuild/win32 -Tools/unicode/build/ -Tools/unicode/MAPPINGS/ -BuildLog.htm -__pycache__ -Parser/pgen{,.exe} -Programs/_freeze_importlib{,.exe} -Programs/_testembed{,.exe} -.coverage -coverage/ -externals/ -htmlcov/ -*.gcda -*.gcno -*.gcov -ipch/ -coverage.info -Tools/msi/obj -Tools/ssl/amd64 -Tools/ssl/win32 -.vs/ -.vscode/ diff --git a/.hgtags b/.hgtags deleted file mode 100644 index 8f51c2ced49a..000000000000 --- a/.hgtags +++ /dev/null @@ -1,182 +0,0 @@ -64cc5439e10a6fdf984effaf0141e94fa4cc1004 v0.9.8 -78a7ed6953025e7ecdde9585099b01a6ae40b76a v0.9.9 -b15b8cc9b8d10e0352a0b8b7e8d51fa309db6df3 v1.0.1 -0326b5d61445ee3a8d3de28119f9652cb72d2e3f v1.0.2 -832615ec07646e310c85316b8ba6bc9b17ad3547 v1.1 -9895475d18c7b5f32adaf78f71886ae041e4d10c v1.1.1 -16eb4c51ee97169046340998e850a63c65225b0a v1.2b1 -b45c688756d04fb84d4a0d518fc3d7e3cb25fa8d v1.2b2 -9e82daf7605bad7976a9abc997cb5e0abe434078 v1.2b3 -065e31cf5862e27521cf5725b003aed211f091b2 v1.2b4 -e72257e655454d569468da8b1189e0ec336f3536 v1.2 -e63d83f8275853aaaa3d1972cb86564505e65583 v1.3b1 -7d743c865a9aa6bde8b603e32e0542031bba3c33 v1.3 -4fc85c82cc222554ae6b9c0b87776ed5f2b70c6e v1.4b1 -129f1299d4e97e884bbbbdd00baf101d178973e6 v1.4b2 -44a82ac654a4175569deed8e8a94b0cc8edee08d v1.4b3 -db49494c93dc73de06d5721c74eab533a947a92c v1.4 -062aed8a4ce2c91c81b80e29f02faff1cf5a761b v1.5a1 -c9498ac988372575cf7028b86395b900c9b0a840 v1.5a2 -dc5c968ec992aab3d40a7189df0c443d1c7a1a68 v1.5a3 -746654a0af680c7d9b814b210a026eb91bec9533 v1.5a4 -8ff58b5730f06be08fbbdc2bf592226f7a736201 v1.5b1 -eb78658d819fb0af09a8e6f9bedcb670805ed5f6 v1.5b2 -84461011a1a0ab402e352f06748f29fb5b5559e5 v1.5 -44aba4d26b01fbae0403efe654f9fd0347606732 v1.5.1 -fed63ccbe6dc3ac663bfe97a2f7006b1b28568f9 v1.5.2a1 -21d71f2e27248a0f4e393d0fc321ecf9b89321d2 v1.5.2a2 -f08c7a2a56f80741f5f192fd0ebe0b0967a203cf v1.5.2b1 -8fe7ec4b4fc1518fcac89e6bf674fbbce16150a9 v1.5.2b2 -39fb0dcc83dc375c1565ba65dbce0ed59b1359c9 v1.5.2c1 -61c91c7f101bab3149adfcd5646ae40e048de712 v1.5.2 -605eb9326ffe1fd1e43f40e2338d6652ab449fdf v1.6a1 -011bee8fd9f7f4da457ec71596484fb0882c0614 v1.6a2 -35c4fc1414a59888614b9be784a25f233ba67984 v2.0b1 -55bba197d4870cdae62aeca00e20240a756b84f8 v2.0b2 -e276329cce036a5f9e9d3451256dca5984e543dc v2.0c1 -2fa4e35083e02342ca014bf5bfba46aecb816c31 v2.0 -b60831eeab5a06dd3c5e8297a99e39297aa8794b v2.1a1 -b382f1f07ec6b2c95551658b30c6139eeb32077a v2.1a2 -d0c830db5e68edd4aaa3401216e610c9ff145826 v2.1b1 -b59a536ae1ef3774fd85c17f623e8926b7b6c095 v2.1b2 -d611276e9ad53b5d32d1e8065e1d811c32f7d96f v2.1c1 -ff065e674af6c9ab895bd9eff7d9e9039a376c7d v2.1c2 -020e95d8180d7943fe54701e1db0a7d7d87e2b1e v2.1 -08796a137f1ada2462f7a3177306df5f67a767e1 v2.2a3 -d054c29647f90bccb8345bd779bca1eecf2dd7f2 v2.3c1 -fce5c9e9abc722394cb2e909b7e2a39080d4448e v2.3c2 -92ca658fd420095b6284c9ce6e9082a80285ec9c v2.4a1 -055fc6955f3c6522bfeb7ed4c671c97d5baaaac2 v2.4a2 -186b72550e53533ef6175f6411f932c1298193d7 v2.4a3 -53cff04283855adf88ed0c0fd3698827ca843637 v2.4b1 -7e387a9dcc79954a77695adef8b593da35be1214 v2.4b2 -ff80d8bbef6e13426c8a85d7f9d837b8f8f89834 v2.4c1 -f31e18d313c7a4fc66914b2d27e130a0f72c0b69 v2.4 -cd3f783cd08a16781e236c0b9cb5717d1d995fa9 v3.0a1 -65e82140e281bf26f2e22eda05a7f9956c420f8b v3.0a2 -df15827f34881b9af0936350813ced5c123c8230 v3.0a3 -15f773f7300e372c56a21d59fe49ca26955a6477 v3.0a4 -e35935475153377d6727d64e6c52f72c3b84015b v3.0a5 -a335c4d643b1cfe14197a9ef195c9b2804f608fc v3.0b1 -16ec4bb14a68ea428acf09ebf0c92981da2646f3 v3.0b2 -509e30a7968e01be329ec121540b3e755fc4e566 v3.0b3 -507ede9c7f7f475dfafbd4a52c22d767d10a2bc0 v3.0rc1 -8fae465a39627b590385462e6095eb63af45240a v3.0rc2 -e83a60c69d53f5551a306e77a6d38e9b11485496 v3.0rc3 -bc1ce368986e45b1faf96f93995df46bcd75e7b8 v3.1a1 -ee430e5075db2adf8124e6b94916a89ca41d3171 v3.1a2 -b63020797f9678adaf4d2c3e26574a9eef2ef028 v3.1b1 -4353fd0843cb31b356adc50f93d220e2e7255ef2 v3.1rc1 -0b87e438e1b53e3f812cad963a7fdb65d198ba2f v3.1rc2 -a69a031ac1402dede8b1ef80096436bca6d371f3 v3.1 -35efb1054ec6ceca72017a587263cb6a9257340b v3.1.1rc1 -8b9c0f573ab29c41c6c5fdcca82a1fe0ff5355af v3.1.1 -149b8b87514d10416b598884db5f74651f625b38 v3.1.2rc1 -960efa327c5d9c18df995437b0ac550cb89c9f85 v3.1.2 -d18e9d71f369d8211f6ac87252c6d3211f9bd09f v3.1.3rc1 -a4f75773c0060cee38b0bb651a7aba6f56b0e996 v3.1.3 -32fcb9e94985cb19ce37ba9543f091c0dbe9d7dd v3.1.4rc1 -c918ec9f3a76d6afedfbb5d455004de880443a3d v3.1.4 -ee26aca3219cf4bb0b93352e83edcc9cb28c7802 v3.1.5rc1 -75db2bc69fc9a3e4801e94e3e19801cb096208d8 v3.1.5rc2 -7395330e495ec3316862ca1f6ce0aaf7bdf6785b v3.1.5 -b37b7834757492d009b99cf0ca4d42d2153d7fac v3.2a1 -56d4373cecb73c8b45126ba7b045b3c7b3f94b0b v3.2a2 -da012d9a2c23d144e399d2e01a55b8a83ad94573 v3.2a3 -d92a5b850f5e56808bedc01723906ed64c5e6e2e v3.2a4 -b635cea94195780c8716e236479af319bcc26253 v3.2b1 -e3af5f3a7904c0d5343ec9633ea66e7acfd23a66 v3.2b2 -865d5b24bf28ca41b536befc326407c03e74a4d5 v3.2rc1 -acf3e24dd0d0dfd1e20c907d696d3da965a8f56f v3.2rc2 -18c1f52896501c7ee13b038454a39acb45a87979 v3.2rc3 -a222a015e28d8ae9af3899258dc6c15c3d40add0 v3.2 -8ffac2337a3323323d02153ac919fd1483176652 v3.2.1b1 -cfa9364997c7f2e67b9cbb45c3a5fa3bba4e4999 v3.2.1rc1 -5df549718fb4841ff521fe051f6b54f290fad5d8 v3.2.1rc2 -ac1f7e5c05104d557d5acd922e95625ba5d1fe10 v3.2.1 -c860feaa348d663e598986894ee4680480577e15 v3.2.2rc1 -137e45f15c0bd262c9ad4c032d97425bc0589456 v3.2.2 -7085403daf439adb3f9e70ef13f6bedb1c447376 v3.2.3rc1 -428f05cb7277e1d42bb9dd8d1af6b6270ebc6112 v3.2.3rc2 -3d0686d90f55a78f96d9403da2c52dc2411419d0 v3.2.3 -b2cb7bc1edb8493c0a78f9331eae3e8fba6a881d v3.2.4rc1 -1e10bdeabe3de02f038a63c001911561ac1d13a7 v3.2.4 -cef745775b6583446572cffad704100983db2bea v3.2.5 -51382a5598ec96119cb84594572901c9c964dc3c v3.2.6rc1 -0bd5f4f14de965ca8e44c6e3965fee106176cfc4 v3.2.6 -f1a9a6505731714f0e157453ff850e3b71615c45 v3.3.0a1 -2f69db52d6de306cdaef0a0cc00cc823fb350b01 v3.3.0a2 -0b53b70a40a00013505eb35e3660057b62be77be v3.3.0a3 -7c51388a3aa7ce76a8541bbbdfc05d2d259a162c v3.3.0a4 -e15c554cd43eb23bc0a528a4e8741da9bbec9607 v3.3.0b1 -4972a8f1b2aa3d7cdd64dc96aa7fa112fe1ea343 v3.3.0b2 -8bb5c7bc46ba43804480f3e328e1fa956672c885 v3.3.0rc1 -88a0792e8ba3e4916b24c7e7a522c277d326d66e v3.3.0rc2 -c191d21cefafb3832c45570e84854e309aa62eaa v3.3.0rc3 -bd8afb90ebf28ba4edc901d4a235f75e7bbc79fd v3.3.0 -92c2cfb924055ce68c4f78f836dcfe688437ceb8 v3.3.1rc1 -d9893d13c6289aa03d33559ec67f97dcbf5c9e3c v3.3.1 -d047928ae3f6314a13b6137051315453d0ae89b6 v3.3.2 -fd53c500f8b80f54f3ecedec9da2e8c7e52a6888 v3.3.3rc1 -d32442c0e60dfbd71234e807d3d1dedd227495a9 v3.3.3rc2 -c3896275c0f61b2510a6c7e6c458a750359a91b8 v3.3.3 -fa92f5f940c6c0d839d7f0611e4b717606504a3c v3.3.4rc1 -7ff62415e4263c432c8acf6e424224209211eadb v3.3.4 -9ec811df548ed154a9bf9815383a916d6df31b98 v3.3.5rc1 -ca5635efe090f78806188ac2758f9948596aa8b2 v3.3.5rc2 -62cf4e77f78564714e7ea3d4bf1479ca1fbd0758 v3.3.5 -51317c9786f54267975abf2e9c502e6aaaa4a249 v3.3.6rc1 -971fec30da1fc5bf2b9fb28e09812a5127014211 v3.3.6 -46535f65e7f3bcdcf176f36d34bc1fed719ffd2b v3.4.0a1 -9265a2168e2cb2a84785d8717792acc661e6b692 v3.4.0a2 -dd9cdf90a5073510877e9dd5112f8e6cf20d5e89 v3.4.0a3 -e245b0d7209bb6d0e19316e1e2af1aa9c2139104 v3.4.0a4 -3405dc9a6afaa0a06dd1f6f182ec5c998dce6f5f v3.4.0b1 -ba32913eb13ec545a46dd0ce18035b6c416f0d78 v3.4.0b2 -a97ce3ecc96af79bd2e1ac66ce48d9138e0ca749 v3.4.0b3 -5e088cea8660677969113741c1313d570d977e02 v3.4.0rc1 -a300712ed38c9a242b736c44e806caea25a6dc05 v3.4.0rc2 -8a81cdab3e9d521daaef989fade94b16455fc3b8 v3.4.0rc3 -04f714765c13824c3bc2835d7b008908862e083a v3.4.0 -c67a19e11a7191baf30f313bf55e2e0b6c6f574e v3.4.1rc1 -c0e311e010fcb5bae8d87ca22051cd0845ea0ca0 v3.4.1 -8711a09513848cfc48c689d983495ee64f4668ca v3.4.2rc1 -ab2c023a9432f16652e89c404bbc84aa91bf55af v3.4.2 -69dd528ca6255a66c37cc5cf680e8357d108b036 v3.4.3rc1 -b4cbecbc0781e89a309d03b60a1f75f8499250e6 v3.4.3 -04f3f725896c6961212c3a12e8ac25be6958f4fa v3.4.4rc1 -737efcadf5a678b184e0fa431aae11276bf06648 v3.4.4 -3631bb4a2490292ebf81d3e947ae36da145da564 v3.4.5rc1 -619b61e505d0e2ccc8516b366e4ddd1971b46a6f v3.4.5 -e199a272ccdac5a8c073d4690f60c13e0b6d86b0 v3.4.6rc1 -b662f47769213f23325144b80782c05764d0f053 v3.4.6 -5d4b6a57d5fd7564bf73f3db0e46fe5eeb00bcd8 v3.5.0a1 -0337bd7ebcb6559d69679bc7025059ad1ce4f432 v3.5.0a2 -82656e28b5e5c4ae48d8dd8b5f0d7968908a82b6 v3.5.0a3 -413e0e0004f4f954331cb8122aa55fe208984955 v3.5.0a4 -071fefbb5e3db770c6c19fba9994699f121b1cea v3.5.0b1 -7a088af5615bf04024e9912068f4bd8f43ed3917 v3.5.0b2 -0035fcd9b9243ae52c2e830204fd9c1f7d528534 v3.5.0b3 -c0d64105463581f85d0e368e8d6e59b7fd8f12b1 v3.5.0b4 -1a58b1227501e046eee13d90f113417b60843301 v3.5.0rc1 -cc15d736d860303b9da90d43cd32db39bab048df v3.5.0rc2 -66ed52375df802f9d0a34480daaa8ce79fc41313 v3.5.0rc3 -2d033fedfa7f1e325fd14ccdaa9cb42155da206f v3.5.0rc4 -374f501f4567b7595f2ad7798aa09afa2456bb28 v3.5.0 -948ef16a69513ba1ff15c9d7d0b012b949df4c80 v3.5.1rc1 -37a07cee5969e6d3672583187a73cf636ff28e1b v3.5.1 -68feec6488b26327a85a634605dd28eca4daa5f1 v3.5.2rc1 -4def2a2901a5618ea45bcc8f2a1411ef33af18ad v3.5.2 -de530d7f21c0398bb2a2b67716e0638e5fadf727 v3.5.3rc1 -1880cb95a742cd001c67677de5c4efeab169416c v3.5.3 -5896da372fb044e38595fb74495de1e1e7c8fb3c v3.6.0a1 -37889342355223e2fc1438de3dc7ffcd625c60f7 v3.6.0a2 -f3edf13dc339b8942ae6b309771ab197dd8ce6fa v3.6.0a3 -017cf260936b444788c9b671d195b7bfd83dbd25 v3.6.0a4 -5b0ca4ed5e2f0669d76ece7ef975c544580f12b4 v3.6.0b1 -b9fadc7d1c3f9c3c77f32f35afbe1a1cc38070e6 v3.6.0b2 -8345e066c0ed713c3e510cbc8fafc1c38d6d306b v3.6.0b3 -18496abdb3d5c2730a659b747a89261b2219fecf v3.6.0b4 -29a273eee9a523ee178f6a66c4ac9d317c8fc84f v3.6.0rc1 -800a67f7806de45a7abd5273359e704bf147c079 v3.6.0rc2 -41df79263a11f2429d1dd0cfe12553de3dcb5508 v3.6.0 From webhook-mailer at python.org Tue Feb 13 21:44:04 2018 From: webhook-mailer at python.org (Mariatta) Date: Wed, 14 Feb 2018 02:44:04 -0000 Subject: [Python-checkins] Fix installation instructions for *nix (GH-5605) Message-ID: https://github.com/python/cpython/commit/3384d38d51a2c3450e742175db5d6d638fa5d2eb commit: 3384d38d51a2c3450e742175db5d6d638fa5d2eb branch: master author: Eitan Adler committer: Mariatta date: 2018-02-13T18:44:01-08:00 summary: Fix installation instructions for *nix (GH-5605) Remove pkg_add -r python from FreeBSD installation section. Moved to OpenBSD. files: M Doc/using/unix.rst diff --git a/Doc/using/unix.rst b/Doc/using/unix.rst index ccdf84dcfa5e..ac99b699868f 100644 --- a/Doc/using/unix.rst +++ b/Doc/using/unix.rst @@ -41,9 +41,11 @@ On FreeBSD and OpenBSD * FreeBSD users, to add the package use:: - pkg_add -r python + pkg install python3 + +* OpenBSD users, to add the package use:: -* OpenBSD users use:: + pkg_add -r python pkg_add ftp://ftp.openbsd.org/pub/OpenBSD/4.2/packages//python-.tgz From webhook-mailer at python.org Tue Feb 13 21:49:59 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 14 Feb 2018 02:49:59 -0000 Subject: [Python-checkins] remove mercurial dot files (GH-5558) Message-ID: https://github.com/python/cpython/commit/deab193e6f18732cf30d54df0bc551210c463d15 commit: deab193e6f18732cf30d54df0bc551210c463d15 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-13T18:49:56-08:00 summary: remove mercurial dot files (GH-5558) (cherry picked from commit 2b86f4cb2cd339f545804a9abb8c4d4cc28d9488) Co-authored-by: Benjamin Peterson files: D .hgeol D .hgignore D .hgtags diff --git a/.hgeol b/.hgeol deleted file mode 100644 index eb19a6c88d28..000000000000 --- a/.hgeol +++ /dev/null @@ -1,58 +0,0 @@ -[patterns] - -# Non human-editable files are binary - -**.dsp = BIN -**.dsw = BIN -**.mk = BIN -**.sln = BIN -**.vcproj = BIN -**.vsprops = BIN - -**.aif = BIN -**.aifc = BIN -**.aiff = BIN -**.au = BIN -**.bmp = BIN -**.db = BIN -**.exe = BIN -**.icns = BIN -**.gif = BIN -**.ico = BIN -**.info = BIN -**.jpg = BIN -**.pck = BIN -**.png = BIN -**.psd = BIN -**.tar = BIN -**.wav = BIN -**.whl = BIN -**.xar = BIN -**.zip = BIN - -Lib/test/cjkencodings/* = BIN -Lib/test/decimaltestdata/*.decTest = BIN -Lib/test/sndhdrdata/sndhdr.* = BIN -Lib/test/test_email/data/msg_26.txt = BIN -Lib/test/xmltestdata/* = BIN - -Lib/venv/scripts/nt/* = BIN - -Lib/test/coding20731.py = BIN - -# Windows only zlib upstream file -Modules/zlib/zlib.map = CRLF - -# Windows batch files work best with CRLF, there can be subtle problems with LF -**.bat = CRLF - -# The Windows readme is likely to be read in Notepad, so make it readable -PCbuild/readme.txt = CRLF - -# All other files (which presumably are human-editable) are "native". -# This must be the last rule! - -** = native - -[repository] -native = LF diff --git a/.hgignore b/.hgignore deleted file mode 100644 index 68c607f2e8d4..000000000000 --- a/.hgignore +++ /dev/null @@ -1,106 +0,0 @@ -.gdb_history -.purify -.svn/ -^.idea/ -^.vscode/ -.DS_Store -Makefile$ -Makefile.pre$ -TAGS$ -autom4te.cache$ -^build/ -^Doc/build/ -^Doc/venv/ -buildno$ -config.cache -config.log -config.status -config.status.lineno -db_home -platform$ -pyconfig.h$ -python$ -python.bat$ -python.exe$ -python-config$ -python-config.py$ -reflog.txt$ -tags$ -Misc/python.pc -Misc/python-config.sh$ -Modules/Setup$ -Modules/Setup.config -Modules/Setup.local -Modules/config.c -Modules/ld_so_aix$ -^lcov-report/ -^core -^python-gdb.py -^python.exe-gdb.py -^pybuilddir.txt - -syntax: glob -libpython*.a -libpython*.so* -libpython*.dylib -libpython*.dll -*.swp -*.o -*.pyc -*.pyo -*.pyd -*.cover -*~ -*.gc?? -*.profclang? -*.profraw -*.dyn -Include/pydtrace_probes.h -Lib/distutils/command/*.pdb -Lib/lib2to3/*.pickle -Lib/test/data/* -Misc/*.wpu -PC/python_nt*.h -PC/pythonnt_rc*.h -PC/*/*.exe -PC/*/*.exp -PC/*/*.lib -PC/*/*.bsc -PC/*/*.dll -PC/*/*.pdb -PC/*/*.user -PC/*/*.ncb -PC/*/*.suo -PC/*/Win32-temp-* -PC/*/x64-temp-* -PC/*/amd64 -PCbuild/*.user -PCbuild/*.suo -PCbuild/*.*sdf -PCbuild/*-pgi -PCbuild/*-pgo -PCbuild/.vs -PCbuild/amd64 -PCbuild/obj -PCbuild/win32 -Tools/unicode/build/ -Tools/unicode/MAPPINGS/ -BuildLog.htm -__pycache__ -Parser/pgen{,.exe} -Programs/_freeze_importlib{,.exe} -Programs/_testembed{,.exe} -.coverage -coverage/ -externals/ -htmlcov/ -*.gcda -*.gcno -*.gcov -ipch/ -coverage.info -Tools/msi/obj -Tools/ssl/amd64 -Tools/ssl/win32 -.vs/ -.vscode/ diff --git a/.hgtags b/.hgtags deleted file mode 100644 index 8f51c2ced49a..000000000000 --- a/.hgtags +++ /dev/null @@ -1,182 +0,0 @@ -64cc5439e10a6fdf984effaf0141e94fa4cc1004 v0.9.8 -78a7ed6953025e7ecdde9585099b01a6ae40b76a v0.9.9 -b15b8cc9b8d10e0352a0b8b7e8d51fa309db6df3 v1.0.1 -0326b5d61445ee3a8d3de28119f9652cb72d2e3f v1.0.2 -832615ec07646e310c85316b8ba6bc9b17ad3547 v1.1 -9895475d18c7b5f32adaf78f71886ae041e4d10c v1.1.1 -16eb4c51ee97169046340998e850a63c65225b0a v1.2b1 -b45c688756d04fb84d4a0d518fc3d7e3cb25fa8d v1.2b2 -9e82daf7605bad7976a9abc997cb5e0abe434078 v1.2b3 -065e31cf5862e27521cf5725b003aed211f091b2 v1.2b4 -e72257e655454d569468da8b1189e0ec336f3536 v1.2 -e63d83f8275853aaaa3d1972cb86564505e65583 v1.3b1 -7d743c865a9aa6bde8b603e32e0542031bba3c33 v1.3 -4fc85c82cc222554ae6b9c0b87776ed5f2b70c6e v1.4b1 -129f1299d4e97e884bbbbdd00baf101d178973e6 v1.4b2 -44a82ac654a4175569deed8e8a94b0cc8edee08d v1.4b3 -db49494c93dc73de06d5721c74eab533a947a92c v1.4 -062aed8a4ce2c91c81b80e29f02faff1cf5a761b v1.5a1 -c9498ac988372575cf7028b86395b900c9b0a840 v1.5a2 -dc5c968ec992aab3d40a7189df0c443d1c7a1a68 v1.5a3 -746654a0af680c7d9b814b210a026eb91bec9533 v1.5a4 -8ff58b5730f06be08fbbdc2bf592226f7a736201 v1.5b1 -eb78658d819fb0af09a8e6f9bedcb670805ed5f6 v1.5b2 -84461011a1a0ab402e352f06748f29fb5b5559e5 v1.5 -44aba4d26b01fbae0403efe654f9fd0347606732 v1.5.1 -fed63ccbe6dc3ac663bfe97a2f7006b1b28568f9 v1.5.2a1 -21d71f2e27248a0f4e393d0fc321ecf9b89321d2 v1.5.2a2 -f08c7a2a56f80741f5f192fd0ebe0b0967a203cf v1.5.2b1 -8fe7ec4b4fc1518fcac89e6bf674fbbce16150a9 v1.5.2b2 -39fb0dcc83dc375c1565ba65dbce0ed59b1359c9 v1.5.2c1 -61c91c7f101bab3149adfcd5646ae40e048de712 v1.5.2 -605eb9326ffe1fd1e43f40e2338d6652ab449fdf v1.6a1 -011bee8fd9f7f4da457ec71596484fb0882c0614 v1.6a2 -35c4fc1414a59888614b9be784a25f233ba67984 v2.0b1 -55bba197d4870cdae62aeca00e20240a756b84f8 v2.0b2 -e276329cce036a5f9e9d3451256dca5984e543dc v2.0c1 -2fa4e35083e02342ca014bf5bfba46aecb816c31 v2.0 -b60831eeab5a06dd3c5e8297a99e39297aa8794b v2.1a1 -b382f1f07ec6b2c95551658b30c6139eeb32077a v2.1a2 -d0c830db5e68edd4aaa3401216e610c9ff145826 v2.1b1 -b59a536ae1ef3774fd85c17f623e8926b7b6c095 v2.1b2 -d611276e9ad53b5d32d1e8065e1d811c32f7d96f v2.1c1 -ff065e674af6c9ab895bd9eff7d9e9039a376c7d v2.1c2 -020e95d8180d7943fe54701e1db0a7d7d87e2b1e v2.1 -08796a137f1ada2462f7a3177306df5f67a767e1 v2.2a3 -d054c29647f90bccb8345bd779bca1eecf2dd7f2 v2.3c1 -fce5c9e9abc722394cb2e909b7e2a39080d4448e v2.3c2 -92ca658fd420095b6284c9ce6e9082a80285ec9c v2.4a1 -055fc6955f3c6522bfeb7ed4c671c97d5baaaac2 v2.4a2 -186b72550e53533ef6175f6411f932c1298193d7 v2.4a3 -53cff04283855adf88ed0c0fd3698827ca843637 v2.4b1 -7e387a9dcc79954a77695adef8b593da35be1214 v2.4b2 -ff80d8bbef6e13426c8a85d7f9d837b8f8f89834 v2.4c1 -f31e18d313c7a4fc66914b2d27e130a0f72c0b69 v2.4 -cd3f783cd08a16781e236c0b9cb5717d1d995fa9 v3.0a1 -65e82140e281bf26f2e22eda05a7f9956c420f8b v3.0a2 -df15827f34881b9af0936350813ced5c123c8230 v3.0a3 -15f773f7300e372c56a21d59fe49ca26955a6477 v3.0a4 -e35935475153377d6727d64e6c52f72c3b84015b v3.0a5 -a335c4d643b1cfe14197a9ef195c9b2804f608fc v3.0b1 -16ec4bb14a68ea428acf09ebf0c92981da2646f3 v3.0b2 -509e30a7968e01be329ec121540b3e755fc4e566 v3.0b3 -507ede9c7f7f475dfafbd4a52c22d767d10a2bc0 v3.0rc1 -8fae465a39627b590385462e6095eb63af45240a v3.0rc2 -e83a60c69d53f5551a306e77a6d38e9b11485496 v3.0rc3 -bc1ce368986e45b1faf96f93995df46bcd75e7b8 v3.1a1 -ee430e5075db2adf8124e6b94916a89ca41d3171 v3.1a2 -b63020797f9678adaf4d2c3e26574a9eef2ef028 v3.1b1 -4353fd0843cb31b356adc50f93d220e2e7255ef2 v3.1rc1 -0b87e438e1b53e3f812cad963a7fdb65d198ba2f v3.1rc2 -a69a031ac1402dede8b1ef80096436bca6d371f3 v3.1 -35efb1054ec6ceca72017a587263cb6a9257340b v3.1.1rc1 -8b9c0f573ab29c41c6c5fdcca82a1fe0ff5355af v3.1.1 -149b8b87514d10416b598884db5f74651f625b38 v3.1.2rc1 -960efa327c5d9c18df995437b0ac550cb89c9f85 v3.1.2 -d18e9d71f369d8211f6ac87252c6d3211f9bd09f v3.1.3rc1 -a4f75773c0060cee38b0bb651a7aba6f56b0e996 v3.1.3 -32fcb9e94985cb19ce37ba9543f091c0dbe9d7dd v3.1.4rc1 -c918ec9f3a76d6afedfbb5d455004de880443a3d v3.1.4 -ee26aca3219cf4bb0b93352e83edcc9cb28c7802 v3.1.5rc1 -75db2bc69fc9a3e4801e94e3e19801cb096208d8 v3.1.5rc2 -7395330e495ec3316862ca1f6ce0aaf7bdf6785b v3.1.5 -b37b7834757492d009b99cf0ca4d42d2153d7fac v3.2a1 -56d4373cecb73c8b45126ba7b045b3c7b3f94b0b v3.2a2 -da012d9a2c23d144e399d2e01a55b8a83ad94573 v3.2a3 -d92a5b850f5e56808bedc01723906ed64c5e6e2e v3.2a4 -b635cea94195780c8716e236479af319bcc26253 v3.2b1 -e3af5f3a7904c0d5343ec9633ea66e7acfd23a66 v3.2b2 -865d5b24bf28ca41b536befc326407c03e74a4d5 v3.2rc1 -acf3e24dd0d0dfd1e20c907d696d3da965a8f56f v3.2rc2 -18c1f52896501c7ee13b038454a39acb45a87979 v3.2rc3 -a222a015e28d8ae9af3899258dc6c15c3d40add0 v3.2 -8ffac2337a3323323d02153ac919fd1483176652 v3.2.1b1 -cfa9364997c7f2e67b9cbb45c3a5fa3bba4e4999 v3.2.1rc1 -5df549718fb4841ff521fe051f6b54f290fad5d8 v3.2.1rc2 -ac1f7e5c05104d557d5acd922e95625ba5d1fe10 v3.2.1 -c860feaa348d663e598986894ee4680480577e15 v3.2.2rc1 -137e45f15c0bd262c9ad4c032d97425bc0589456 v3.2.2 -7085403daf439adb3f9e70ef13f6bedb1c447376 v3.2.3rc1 -428f05cb7277e1d42bb9dd8d1af6b6270ebc6112 v3.2.3rc2 -3d0686d90f55a78f96d9403da2c52dc2411419d0 v3.2.3 -b2cb7bc1edb8493c0a78f9331eae3e8fba6a881d v3.2.4rc1 -1e10bdeabe3de02f038a63c001911561ac1d13a7 v3.2.4 -cef745775b6583446572cffad704100983db2bea v3.2.5 -51382a5598ec96119cb84594572901c9c964dc3c v3.2.6rc1 -0bd5f4f14de965ca8e44c6e3965fee106176cfc4 v3.2.6 -f1a9a6505731714f0e157453ff850e3b71615c45 v3.3.0a1 -2f69db52d6de306cdaef0a0cc00cc823fb350b01 v3.3.0a2 -0b53b70a40a00013505eb35e3660057b62be77be v3.3.0a3 -7c51388a3aa7ce76a8541bbbdfc05d2d259a162c v3.3.0a4 -e15c554cd43eb23bc0a528a4e8741da9bbec9607 v3.3.0b1 -4972a8f1b2aa3d7cdd64dc96aa7fa112fe1ea343 v3.3.0b2 -8bb5c7bc46ba43804480f3e328e1fa956672c885 v3.3.0rc1 -88a0792e8ba3e4916b24c7e7a522c277d326d66e v3.3.0rc2 -c191d21cefafb3832c45570e84854e309aa62eaa v3.3.0rc3 -bd8afb90ebf28ba4edc901d4a235f75e7bbc79fd v3.3.0 -92c2cfb924055ce68c4f78f836dcfe688437ceb8 v3.3.1rc1 -d9893d13c6289aa03d33559ec67f97dcbf5c9e3c v3.3.1 -d047928ae3f6314a13b6137051315453d0ae89b6 v3.3.2 -fd53c500f8b80f54f3ecedec9da2e8c7e52a6888 v3.3.3rc1 -d32442c0e60dfbd71234e807d3d1dedd227495a9 v3.3.3rc2 -c3896275c0f61b2510a6c7e6c458a750359a91b8 v3.3.3 -fa92f5f940c6c0d839d7f0611e4b717606504a3c v3.3.4rc1 -7ff62415e4263c432c8acf6e424224209211eadb v3.3.4 -9ec811df548ed154a9bf9815383a916d6df31b98 v3.3.5rc1 -ca5635efe090f78806188ac2758f9948596aa8b2 v3.3.5rc2 -62cf4e77f78564714e7ea3d4bf1479ca1fbd0758 v3.3.5 -51317c9786f54267975abf2e9c502e6aaaa4a249 v3.3.6rc1 -971fec30da1fc5bf2b9fb28e09812a5127014211 v3.3.6 -46535f65e7f3bcdcf176f36d34bc1fed719ffd2b v3.4.0a1 -9265a2168e2cb2a84785d8717792acc661e6b692 v3.4.0a2 -dd9cdf90a5073510877e9dd5112f8e6cf20d5e89 v3.4.0a3 -e245b0d7209bb6d0e19316e1e2af1aa9c2139104 v3.4.0a4 -3405dc9a6afaa0a06dd1f6f182ec5c998dce6f5f v3.4.0b1 -ba32913eb13ec545a46dd0ce18035b6c416f0d78 v3.4.0b2 -a97ce3ecc96af79bd2e1ac66ce48d9138e0ca749 v3.4.0b3 -5e088cea8660677969113741c1313d570d977e02 v3.4.0rc1 -a300712ed38c9a242b736c44e806caea25a6dc05 v3.4.0rc2 -8a81cdab3e9d521daaef989fade94b16455fc3b8 v3.4.0rc3 -04f714765c13824c3bc2835d7b008908862e083a v3.4.0 -c67a19e11a7191baf30f313bf55e2e0b6c6f574e v3.4.1rc1 -c0e311e010fcb5bae8d87ca22051cd0845ea0ca0 v3.4.1 -8711a09513848cfc48c689d983495ee64f4668ca v3.4.2rc1 -ab2c023a9432f16652e89c404bbc84aa91bf55af v3.4.2 -69dd528ca6255a66c37cc5cf680e8357d108b036 v3.4.3rc1 -b4cbecbc0781e89a309d03b60a1f75f8499250e6 v3.4.3 -04f3f725896c6961212c3a12e8ac25be6958f4fa v3.4.4rc1 -737efcadf5a678b184e0fa431aae11276bf06648 v3.4.4 -3631bb4a2490292ebf81d3e947ae36da145da564 v3.4.5rc1 -619b61e505d0e2ccc8516b366e4ddd1971b46a6f v3.4.5 -e199a272ccdac5a8c073d4690f60c13e0b6d86b0 v3.4.6rc1 -b662f47769213f23325144b80782c05764d0f053 v3.4.6 -5d4b6a57d5fd7564bf73f3db0e46fe5eeb00bcd8 v3.5.0a1 -0337bd7ebcb6559d69679bc7025059ad1ce4f432 v3.5.0a2 -82656e28b5e5c4ae48d8dd8b5f0d7968908a82b6 v3.5.0a3 -413e0e0004f4f954331cb8122aa55fe208984955 v3.5.0a4 -071fefbb5e3db770c6c19fba9994699f121b1cea v3.5.0b1 -7a088af5615bf04024e9912068f4bd8f43ed3917 v3.5.0b2 -0035fcd9b9243ae52c2e830204fd9c1f7d528534 v3.5.0b3 -c0d64105463581f85d0e368e8d6e59b7fd8f12b1 v3.5.0b4 -1a58b1227501e046eee13d90f113417b60843301 v3.5.0rc1 -cc15d736d860303b9da90d43cd32db39bab048df v3.5.0rc2 -66ed52375df802f9d0a34480daaa8ce79fc41313 v3.5.0rc3 -2d033fedfa7f1e325fd14ccdaa9cb42155da206f v3.5.0rc4 -374f501f4567b7595f2ad7798aa09afa2456bb28 v3.5.0 -948ef16a69513ba1ff15c9d7d0b012b949df4c80 v3.5.1rc1 -37a07cee5969e6d3672583187a73cf636ff28e1b v3.5.1 -68feec6488b26327a85a634605dd28eca4daa5f1 v3.5.2rc1 -4def2a2901a5618ea45bcc8f2a1411ef33af18ad v3.5.2 -de530d7f21c0398bb2a2b67716e0638e5fadf727 v3.5.3rc1 -1880cb95a742cd001c67677de5c4efeab169416c v3.5.3 -5896da372fb044e38595fb74495de1e1e7c8fb3c v3.6.0a1 -37889342355223e2fc1438de3dc7ffcd625c60f7 v3.6.0a2 -f3edf13dc339b8942ae6b309771ab197dd8ce6fa v3.6.0a3 -017cf260936b444788c9b671d195b7bfd83dbd25 v3.6.0a4 -5b0ca4ed5e2f0669d76ece7ef975c544580f12b4 v3.6.0b1 -b9fadc7d1c3f9c3c77f32f35afbe1a1cc38070e6 v3.6.0b2 -8345e066c0ed713c3e510cbc8fafc1c38d6d306b v3.6.0b3 -18496abdb3d5c2730a659b747a89261b2219fecf v3.6.0b4 -29a273eee9a523ee178f6a66c4ac9d317c8fc84f v3.6.0rc1 -800a67f7806de45a7abd5273359e704bf147c079 v3.6.0rc2 -41df79263a11f2429d1dd0cfe12553de3dcb5508 v3.6.0 From webhook-mailer at python.org Tue Feb 13 22:17:12 2018 From: webhook-mailer at python.org (Benjamin Peterson) Date: Wed, 14 Feb 2018 03:17:12 -0000 Subject: [Python-checkins] [2.7] remove mercurial dot files (GH-5558). Message-ID: https://github.com/python/cpython/commit/23f0a5eabcac20e491d5c06687617e6aa799b25a commit: 23f0a5eabcac20e491d5c06687617e6aa799b25a branch: 2.7 author: Benjamin Peterson committer: GitHub date: 2018-02-13T19:17:10-08:00 summary: [2.7] remove mercurial dot files (GH-5558). (cherry picked from commit 2b86f4cb2cd339f545804a9abb8c4d4cc28d9488) files: D .hgeol D .hgignore D .hgtags diff --git a/.hgeol b/.hgeol deleted file mode 100644 index eab3645db194..000000000000 --- a/.hgeol +++ /dev/null @@ -1,55 +0,0 @@ -[patterns] - -# Non human-editable files are binary - -**.dsp = BIN -**.dsw = BIN -**.mk = BIN -**.sln = BIN -**.vcproj = BIN -**.vsprops = BIN - -**.aif = BIN -**.aifc = BIN -**.aiff = BIN -**.au = BIN -**.bmp = BIN -**.blob = BIN -**.db = BIN -**.exe = BIN -**.icns = BIN -**.gif = BIN -**.ico = BIN -**.info = BIN -**.jpg = BIN -**.pck = BIN -**.png = BIN -**.psd = BIN -**.tar = BIN -**.wav = BIN -**.whl = BIN -**.xar = BIN -**.zip = BIN - -Lib/email/test/data/msg_26.txt = BIN -Lib/test/cjkencodings/* = BIN -Lib/test/decimaltestdata/*.decTest = BIN -Lib/test/sndhdrdata/sndhdr.* = BIN - -# Windows only zlib upstream file -Modules/zlib/zlib.map = CRLF - -# Windows batch files work best with CRLF, there can be subtle problems with LF -**.bat = CRLF - -# The Windows readme is likely to be read in Notepad, so make it readable -PCbuild/readme.txt = CRLF -PC/VS9.0/readme.txt = CRLF - -# All other files (which presumably are human-editable) are "native". -# This must be the last rule! - -** = native - -[repository] -native = LF diff --git a/.hgignore b/.hgignore deleted file mode 100644 index 16662a0a284d..000000000000 --- a/.hgignore +++ /dev/null @@ -1,92 +0,0 @@ -.gdb_history -.purify -.svn/ -^.idea/ -.DS_Store -Makefile$ -Makefile.pre$ -TAGS$ -autom4te.cache$ -build/ -buildno$ -config.cache -config.log -config.status -config.status.lineno -db_home -platform$ -pyconfig.h$ -python$ -python.bat$ -python.exe$ -reflog.txt$ -tags$ -Lib/plat-mac/errors.rsrc.df.rsrc -Misc/python.pc -Modules/Setup$ -Modules/Setup.config -Modules/Setup.local -Modules/config.c -Modules/ld_so_aix$ -Parser/pgen$ -Parser/pgen.stamp$ -^lcov-report/ -^core -^python-gdb.py -^pybuilddir.txt - -syntax: glob -python.exe-gdb.py -libpython*.a -libpython*.so* -*.swp -*.o -*.pyc -*.pyo -*.pyd -*.cover -*~ -*.gc?? -*.profclang? -*.profraw -*.dyn -Lib/distutils/command/*.pdb -Lib/lib2to3/*.pickle -Lib/test/data/* -Misc/*.wpu -PC/python_nt*.h -PC/pythonnt_rc*.h -PC/*/*.exe -PC/*/*.exp -PC/*/*.lib -PC/*/*.bsc -PC/*/*.dll -PC/*/*.pdb -PC/*/*.user -PC/*/*.ncb -PC/*/*.suo -PC/*/Win32-temp-* -PC/*/x64-temp-* -PC/*/amd64 -PCbuild/*.user -PCbuild/*.suo -PCbuild/*.*sdf -PCbuild/*-pgi -PCbuild/*-pgo -PCbuild/.vs -PCbuild/*.dll -PCbuild/*.exp -PCbuild/*.exe -PCbuild/*.ilk -PCbuild/*.lib -PCbuild/*.pdb -PCbuild/amd64 -PCbuild/obj -*.gcda -*.gcno -*.gcov -coverage.info -.coverage -coverage/ -externals/ -htmlcov/ diff --git a/.hgtags b/.hgtags deleted file mode 100644 index 8f57968e8d09..000000000000 --- a/.hgtags +++ /dev/null @@ -1,178 +0,0 @@ -64cc5439e10a6fdf984effaf0141e94fa4cc1004 v0.9.8 -78a7ed6953025e7ecdde9585099b01a6ae40b76a v0.9.9 -b15b8cc9b8d10e0352a0b8b7e8d51fa309db6df3 v1.0.1 -0326b5d61445ee3a8d3de28119f9652cb72d2e3f v1.0.2 -832615ec07646e310c85316b8ba6bc9b17ad3547 v1.1 -9895475d18c7b5f32adaf78f71886ae041e4d10c v1.1.1 -16eb4c51ee97169046340998e850a63c65225b0a v1.2b1 -b45c688756d04fb84d4a0d518fc3d7e3cb25fa8d v1.2b2 -9e82daf7605bad7976a9abc997cb5e0abe434078 v1.2b3 -065e31cf5862e27521cf5725b003aed211f091b2 v1.2b4 -e72257e655454d569468da8b1189e0ec336f3536 v1.2 -e63d83f8275853aaaa3d1972cb86564505e65583 v1.3b1 -7d743c865a9aa6bde8b603e32e0542031bba3c33 v1.3 -4fc85c82cc222554ae6b9c0b87776ed5f2b70c6e v1.4b1 -129f1299d4e97e884bbbbdd00baf101d178973e6 v1.4b2 -44a82ac654a4175569deed8e8a94b0cc8edee08d v1.4b3 -db49494c93dc73de06d5721c74eab533a947a92c v1.4 -062aed8a4ce2c91c81b80e29f02faff1cf5a761b v1.5a1 -c9498ac988372575cf7028b86395b900c9b0a840 v1.5a2 -dc5c968ec992aab3d40a7189df0c443d1c7a1a68 v1.5a3 -746654a0af680c7d9b814b210a026eb91bec9533 v1.5a4 -8ff58b5730f06be08fbbdc2bf592226f7a736201 v1.5b1 -eb78658d819fb0af09a8e6f9bedcb670805ed5f6 v1.5b2 -84461011a1a0ab402e352f06748f29fb5b5559e5 v1.5 -44aba4d26b01fbae0403efe654f9fd0347606732 v1.5.1 -fed63ccbe6dc3ac663bfe97a2f7006b1b28568f9 v1.5.2a1 -21d71f2e27248a0f4e393d0fc321ecf9b89321d2 v1.5.2a2 -f08c7a2a56f80741f5f192fd0ebe0b0967a203cf v1.5.2b1 -8fe7ec4b4fc1518fcac89e6bf674fbbce16150a9 v1.5.2b2 -39fb0dcc83dc375c1565ba65dbce0ed59b1359c9 v1.5.2c1 -61c91c7f101bab3149adfcd5646ae40e048de712 v1.5.2 -605eb9326ffe1fd1e43f40e2338d6652ab449fdf v1.6a1 -011bee8fd9f7f4da457ec71596484fb0882c0614 v1.6a2 -35c4fc1414a59888614b9be784a25f233ba67984 v2.0b1 -55bba197d4870cdae62aeca00e20240a756b84f8 v2.0b2 -e276329cce036a5f9e9d3451256dca5984e543dc v2.0c1 -2fa4e35083e02342ca014bf5bfba46aecb816c31 v2.0 -83459cc191c1c9c8cc6b08ada99c02f0af6ad54f v2.0.1c1 -73de94a722d206a45c0b49d3011c629ead4d62b1 v2.0.1 -b60831eeab5a06dd3c5e8297a99e39297aa8794b v2.1a1 -b382f1f07ec6b2c95551658b30c6139eeb32077a v2.1a2 -d0c830db5e68edd4aaa3401216e610c9ff145826 v2.1b1 -b59a536ae1ef3774fd85c17f623e8926b7b6c095 v2.1b2 -d611276e9ad53b5d32d1e8065e1d811c32f7d96f v2.1c1 -ff065e674af6c9ab895bd9eff7d9e9039a376c7d v2.1c2 -020e95d8180d7943fe54701e1db0a7d7d87e2b1e v2.1 -22bed2dd1b286564dea4d9a67d4ed80dc3225193 v2.1.1c1 -572533a3038d1832c8a200fb8718112dd83758e9 v2.1.1 -f76a425b14e4ee8ade5e9239598538534b3a90a4 v2.1.2c1 -cf31b10e45b48615094cae90e3c5bd072587d8e6 v2.1.2 -7d1504c80fa072b4ba86edda13a13b0a05ae8eab v2.1.3 -08796a137f1ada2462f7a3177306df5f67a767e1 v2.2a3 -765434e7aa019c1bb82f9813b8025830867cbdc0 v2.2.1c1 -11c952c7d4be6638040764910be80bd9c3c17de6 v2.2.1c2 -4045e6e92fafabad42f6c9989b67076fbad452ca v2.2 -394790316aa380d22e4d670bc69a639e725f0300 v2.2.1 -0128313c2855d71753f00fccc60bb39ed92a0c54 v2.2.2b1 -61d531533a86224a1c26917c18013d91f592fbfb v2.2.2 -ac77b91342534d09b1e432e1dc3b70dbbec3a919 v2.2.3c1 -f4f134ad46abd0bc973d3f6094ea56e62ac5c492 v2.2.3 -d054c29647f90bccb8345bd779bca1eecf2dd7f2 v2.3c1 -fce5c9e9abc722394cb2e909b7e2a39080d4448e v2.3c2 -fa65f6527fe134aa97e03e1b2af365d443b67dc7 v2.3.1 -7d7362a71253bff4fc1b0c825c14569778db8c36 v2.3.2c1 -be2533fb10a587c8da89b18c5f381f478d720593 v2.3.2 -d21d4ba2f973467d30794a3d2ac493658180e503 v2.3.3c1 -a8f1286f217129cdb53e320ee125d2c2c80e1377 v2.3.3 -3639861d02646af1da3123c25560c4db3d7edbce v2.3.4c1 -a74f9081c6970878cabe151f969617587915400c v2.3.4 -2639b10daa985b20b3cabec45169d523cac29d68 v2.3.5c1 -d228509424172f977edad4f7860a9c747cd655c8 v2.3.5 -b21427ff26475f9c7f4a701da324e951c2b162fe v2.3.6c1 -3b6fb5439c1061a941401245076c315beafcc787 v2.3.6 -893c7bd4a92bd889a85e691f49188c37b0a72357 v2.3.7c1 -2022943ad450c41d64708fb5caca2d2672b5b8f8 v2.3.7 -92ca658fd420095b6284c9ce6e9082a80285ec9c v2.4a1 -055fc6955f3c6522bfeb7ed4c671c97d5baaaac2 v2.4a2 -186b72550e53533ef6175f6411f932c1298193d7 v2.4a3 -53cff04283855adf88ed0c0fd3698827ca843637 v2.4b1 -7e387a9dcc79954a77695adef8b593da35be1214 v2.4b2 -ff80d8bbef6e13426c8a85d7f9d837b8f8f89834 v2.4c1 -f31e18d313c7a4fc66914b2d27e130a0f72c0b69 v2.4 -1195f9ba3439097cc5b5a367e3ae1b43f157b264 v2.4.1c1 -333cf303543b680ec5e3fdf7e8c9661f9488a50e v2.4.1c2 -f9054d235870029afa33ef945bca7ece99616c10 v2.4.1 -d02d387554e200befceec999b788f4593b434b49 v2.4.2c1 -8d37276fdf077d6d23d963d3f7f95381d00f1926 v2.4.2 -7c5be7c0fdfdbbc0ac1d91c07038bc81412da412 v2.4.3c1 -8cca2492626ce408cd567110811c0692fd1d37dd v2.4.3 -baaeea722b1c97ca03179e5a02a4717e7017ba2a v2.4.4c1 -592ac93532efdfa9a40f47b96b1c1231d2eae0e5 v2.4.4 -1f7d628c70a9aefe762c2c32210876faf8d64c78 v2.4.5c1 -d8df4aa06261de5e4c0aa051e448697d4791e437 v2.4.5 -a6c3c715e2b70740c4b6b4f7dc6f47b16a7e5905 v2.4.6c1 -f3f1f1462c82536bb23796e70c85522144ee24db v2.4.6 -67192da3e69c985bb1272da932d7de6073033fad v2.5a0 -896f9fead17e720ec4a21de3ac214518da84845f v2.5a1 -26d0770f2b7ee289a39a3b55dcec1c1ee65849c5 v2.5a2 -d49b198f545cd82fbf735a22979c332b8a97eecb v2.5b1 -03b6fe57cd6df5bb34ca19f4b760b943186cc806 v2.5b2 -c0abb18299b442e1160d2f958bce18f66850caa9 v2.5b3 -2dc64d570e8d7a4498ab850108c85709c276df93 v2.5c1 -cc3cb3a8237ea545db917d84c49d8a0a5e175cc1 v2.5c2 -c10a71cf16e471425e6d7564e3f7a648f14b702e v2.5 -4777c4007b5b194423953d41b1e5e6adaaba6c5d v2.5.1c1 -490d8c09abcb814950be7bb7a25c3ff2047c7eb5 v2.5.1 -0a8aae575cdddbf3d133fcb4eed91080e3fe41f3 v2.5.2c1 -1d508bbbdb49a2b11629ee186a63928291b08694 v2.5.2 -9530d334d2624219e7ee1aecaf33532e910266bc v2.5.3c1 -3cc056d21c2f4435a534d23345bad9c0a9d9b3cb v2.5.3 -a0a6d9909312ad9c1d844af66e9c91931b93852a v2.5.4 -657f16582943739b906f66f7efad4014492c8b1c v2.5.5c1 -1dc91e9dd5c13a4bc2d3bb7d4b5896ab264f2325 v2.5.5c2 -7098a46f0b75e5aacfaf81d65d72e3613b023532 v2.5.5 -a87c7b96672b69dffef64c59b56fba5bb2059b99 v2.5.6c1 -de34c7b097e8d66b1140c211dbd61d48b31ba483 v2.5.6 -2d0bd095c420b0711000d9be66848f6cfd972b3b v2.6a1 -eec144917a189be11ed5efa35c6604d03bc62bcc v2.6a2 -48e9fb0a721799877f26edaef01ac6e6029b6812 v2.6a3 -2f2f32af8c4ee8f6598f632dc83701a20726d10a v2.6b1 -81ec8263bd6e25c9a8855cd0ce9ae881732972be v2.6b2 -c62862d73f9ec64d655494cf1f61443446f2dea2 v2.6b3 -1ebb2a8cc06c94471d72b5476c2050c4d115a1aa v2.6rc1 -525792097c6308a78a76b7b5f56bbd8a24c26acf v2.6rc2 -95fff5a6a276520b2e7e0f75fe303f49376567a5 v2.6 -cabf303e787aa5cd7209b40e3b2caba3ee75c5a5 v2.6.1 -01f1ae83631ae82bd8598a11c17e3f9b3f56c38a v2.6.2c1 -4feba09a826ba99e5b482707b3d9643eba34156f v2.6.2 -1873542c00000c4b7ce2c7992d1f2d87f866232a v2.6.3rc1 -00c3396d7a8c4ab4c2c841d61013a073ae921d0f v2.6.3 -25aa90a6865b63133962dd64626c53c7b6fd47d5 v2.6.4rc1 -ea1fdafbe4fe2458ac17287e0d6c709ed00fce5c v2.6.4rc2 -8803c3d61da275c71cabe9e9d0274dac9902e2c0 v2.6.4 -c9f68e42ab796a3bab4f8cf3cc69ce10503cb990 v2.6.5rc1 -fa4630916699046357a5ac16884f3fc47bd0eaa6 v2.6.5rc2 -99af4b44e7e490390817a597a542546d749e698e v2.6.5 -c1dc9e7986a2a8e1070ec7bee748520febef382e v2.6.6rc1 -e189dc8fd66154ef46d9cd22584d56669b544ca3 v2.6.6rc2 -9f8771e0905277f8b3c2799113a062fda4164995 v2.6.6 -caab08cd2b3eb5a6f78479b2513b65d36c754f41 v2.6.8rc1 -1d1b7b9fad48bd0dc60dc8a06cca4459ef273127 v2.6.8rc2 -c9910fd022fc842e5578e1bf5a30ba55a37239fc v2.6.8 -b4107eb00b4271fb73a9e1b736d4f23460950778 v2.7a1 -adc85ebc7271cc22e24e816782bb2b8d7fa3a6b3 v2.7a2 -4180557b7a9bb9dd5341a18af199f843f199e46e v2.7a3 -d2e1027edde84a02853fcf9790f311f10f46cf0a v2.7a4 -61550a1302b07a731436a84b2d86eb2bab3b2fb0 v2.7b1 -6bb9891d4275bd42a69b3d903d13b687543c915d v2.7b2 -381c5eeb511038d091d8e0808c4b85087ed2f684 v2.7rc1 -13e5b0b2071a2a42067fb03facc931409fa6ba50 v2.7rc2 -2145593d108de62ebf770987a4ac2a57d268c9d1 v2.7 -63d9f00fea0730c1c437a50f64a42b7792bdcbfb v2.7.1rc1 -5395f96588d4f0199d329cb79eb109648dc4ef5e v2.7.1 -f48756685406e8d0fa9d23d841fceb07e36a5656 v2.7.2rc1 -8527427914a29d895bcb30be76a465143993a793 v2.7.2 -b2c6aff96e1251a4f03cf866e7e75fb8232869f2 v2.7.3rc1 -d46c1973d3c407ecaa6a8ee16d3fad3ef506b51f v2.7.3rc2 -70274d53c1ddc60c5f9a2b8a422a49884021447c v2.7.3 -a8d18780bc2bccf16bf580587e1e3c934a98f6a7 v2.7.4rc1 -026ee0057e2d3305f90a9da41daf7c3f9eb1e814 v2.7.4 -ab05e7dd27889b93f20d97bae86170aabfe45ace v2.7.5 -a0025037f11a73df5a7dd03e5a4027adad4cb94e v2.6.9rc1 -fcb3ec2842f99454322492dd0ec2cf01322df093 v2.6.9 -4913d0e9be30666218cc4d713937e81c0e7f346a v2.7.6rc1 -3a1db0d2747ec2d47a8693ed5650f3567161a200 v2.7.6 -e32e3a9f390212463c22509d0f9aead8051cee63 v2.7.7rc1 -f89216059edf77660ef1eb2a98e88352551da1d6 v2.7.7 -ee879c0ffa11caaa34bf01537e1c4411dd948552 v2.7.8 -40eada278702349a2b2f334aa9d91fa7090ea1e3 v2.7.9rc1 -648dcafa7e5f40da31079bc7a7f0c445f1ea4ab9 v2.7.9 -80ccce248ba2657ed5da3ccf7999f35b78827f5e v2.7.10rc1 -15c95b7d81dcf821daade360741e00714667653f v2.7.10 -82dd9545bd93d6e7a9821e1dabc7b25508d0fa3a v2.7.11rc1 -6d1b6a68f775fada9877d295e62958bafa1ca11e v2.7.11 -13912cd1e7e8fc6986f42822f5439ae1f2bc0d7d v2.7.12rc1 -d33e0cf91556723fb8cebefdad1f3bce43b2244d v2.7.12 -4d6fd49eeb14bb47f700325eb90d7989fc9e4020 v2.7.13rc1 -a06454b1afa167fbcd8626e4abc144ce15461067 v2.7.13 From webhook-mailer at python.org Tue Feb 13 22:53:37 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 14 Feb 2018 03:53:37 -0000 Subject: [Python-checkins] Fix installation instructions for *nix (GH-5605) Message-ID: https://github.com/python/cpython/commit/8e29fd4b3b3c5856a481a80d12d35da8df35b72e commit: 8e29fd4b3b3c5856a481a80d12d35da8df35b72e branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-13T19:53:31-08:00 summary: Fix installation instructions for *nix (GH-5605) Remove pkg_add -r python from FreeBSD installation section. Moved to OpenBSD. (cherry picked from commit 3384d38d51a2c3450e742175db5d6d638fa5d2eb) Co-authored-by: Eitan Adler files: M Doc/using/unix.rst diff --git a/Doc/using/unix.rst b/Doc/using/unix.rst index ccdf84dcfa5e..ac99b699868f 100644 --- a/Doc/using/unix.rst +++ b/Doc/using/unix.rst @@ -41,9 +41,11 @@ On FreeBSD and OpenBSD * FreeBSD users, to add the package use:: - pkg_add -r python + pkg install python3 + +* OpenBSD users, to add the package use:: -* OpenBSD users use:: + pkg_add -r python pkg_add ftp://ftp.openbsd.org/pub/OpenBSD/4.2/packages//python-.tgz From webhook-mailer at python.org Tue Feb 13 22:55:12 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 14 Feb 2018 03:55:12 -0000 Subject: [Python-checkins] Fix installation instructions for *nix (GH-5605) Message-ID: https://github.com/python/cpython/commit/877112567ab3f11f29a3f64b4f42570310f55afe commit: 877112567ab3f11f29a3f64b4f42570310f55afe branch: 2.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-13T19:55:09-08:00 summary: Fix installation instructions for *nix (GH-5605) Remove pkg_add -r python from FreeBSD installation section. Moved to OpenBSD. (cherry picked from commit 3384d38d51a2c3450e742175db5d6d638fa5d2eb) Co-authored-by: Eitan Adler files: M Doc/using/unix.rst diff --git a/Doc/using/unix.rst b/Doc/using/unix.rst index 2da26d87a5b8..7719baa8cdeb 100644 --- a/Doc/using/unix.rst +++ b/Doc/using/unix.rst @@ -41,9 +41,11 @@ On FreeBSD and OpenBSD * FreeBSD users, to add the package use:: - pkg_add -r python + pkg install python3 + +* OpenBSD users, to add the package use:: -* OpenBSD users use:: + pkg_add -r python pkg_add ftp://ftp.openbsd.org/pub/OpenBSD/4.2/packages//python-.tgz From webhook-mailer at python.org Tue Feb 13 23:00:41 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 14 Feb 2018 04:00:41 -0000 Subject: [Python-checkins] Fix installation instructions for *nix (GH-5605) Message-ID: https://github.com/python/cpython/commit/1b9bbbcad3c08e9ea2a3e877bd86a23ca89d35b7 commit: 1b9bbbcad3c08e9ea2a3e877bd86a23ca89d35b7 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-13T20:00:38-08:00 summary: Fix installation instructions for *nix (GH-5605) Remove pkg_add -r python from FreeBSD installation section. Moved to OpenBSD. (cherry picked from commit 3384d38d51a2c3450e742175db5d6d638fa5d2eb) Co-authored-by: Eitan Adler files: M Doc/using/unix.rst diff --git a/Doc/using/unix.rst b/Doc/using/unix.rst index 8b96ebea396f..dc05e0d63dca 100644 --- a/Doc/using/unix.rst +++ b/Doc/using/unix.rst @@ -41,9 +41,11 @@ On FreeBSD and OpenBSD * FreeBSD users, to add the package use:: - pkg_add -r python + pkg install python3 + +* OpenBSD users, to add the package use:: -* OpenBSD users use:: + pkg_add -r python pkg_add ftp://ftp.openbsd.org/pub/OpenBSD/4.2/packages//python-.tgz From webhook-mailer at python.org Tue Feb 13 23:28:51 2018 From: webhook-mailer at python.org (Benjamin Peterson) Date: Wed, 14 Feb 2018 04:28:51 -0000 Subject: [Python-checkins] [3.6] remove mercurial dot files (GH-5558) Message-ID: https://github.com/python/cpython/commit/2be5435203ebdfa34b053677055a7e93c611aa8e commit: 2be5435203ebdfa34b053677055a7e93c611aa8e branch: 3.6 author: Benjamin Peterson committer: GitHub date: 2018-02-13T20:28:46-08:00 summary: [3.6] remove mercurial dot files (GH-5558) (cherry picked from commit 2b86f4cb2cd339f545804a9abb8c4d4cc28d9488) files: D .hgeol D .hgtags diff --git a/.hgeol b/.hgeol deleted file mode 100644 index eb19a6c88d28..000000000000 --- a/.hgeol +++ /dev/null @@ -1,58 +0,0 @@ -[patterns] - -# Non human-editable files are binary - -**.dsp = BIN -**.dsw = BIN -**.mk = BIN -**.sln = BIN -**.vcproj = BIN -**.vsprops = BIN - -**.aif = BIN -**.aifc = BIN -**.aiff = BIN -**.au = BIN -**.bmp = BIN -**.db = BIN -**.exe = BIN -**.icns = BIN -**.gif = BIN -**.ico = BIN -**.info = BIN -**.jpg = BIN -**.pck = BIN -**.png = BIN -**.psd = BIN -**.tar = BIN -**.wav = BIN -**.whl = BIN -**.xar = BIN -**.zip = BIN - -Lib/test/cjkencodings/* = BIN -Lib/test/decimaltestdata/*.decTest = BIN -Lib/test/sndhdrdata/sndhdr.* = BIN -Lib/test/test_email/data/msg_26.txt = BIN -Lib/test/xmltestdata/* = BIN - -Lib/venv/scripts/nt/* = BIN - -Lib/test/coding20731.py = BIN - -# Windows only zlib upstream file -Modules/zlib/zlib.map = CRLF - -# Windows batch files work best with CRLF, there can be subtle problems with LF -**.bat = CRLF - -# The Windows readme is likely to be read in Notepad, so make it readable -PCbuild/readme.txt = CRLF - -# All other files (which presumably are human-editable) are "native". -# This must be the last rule! - -** = native - -[repository] -native = LF diff --git a/.hgtags b/.hgtags deleted file mode 100644 index 8f51c2ced49a..000000000000 --- a/.hgtags +++ /dev/null @@ -1,182 +0,0 @@ -64cc5439e10a6fdf984effaf0141e94fa4cc1004 v0.9.8 -78a7ed6953025e7ecdde9585099b01a6ae40b76a v0.9.9 -b15b8cc9b8d10e0352a0b8b7e8d51fa309db6df3 v1.0.1 -0326b5d61445ee3a8d3de28119f9652cb72d2e3f v1.0.2 -832615ec07646e310c85316b8ba6bc9b17ad3547 v1.1 -9895475d18c7b5f32adaf78f71886ae041e4d10c v1.1.1 -16eb4c51ee97169046340998e850a63c65225b0a v1.2b1 -b45c688756d04fb84d4a0d518fc3d7e3cb25fa8d v1.2b2 -9e82daf7605bad7976a9abc997cb5e0abe434078 v1.2b3 -065e31cf5862e27521cf5725b003aed211f091b2 v1.2b4 -e72257e655454d569468da8b1189e0ec336f3536 v1.2 -e63d83f8275853aaaa3d1972cb86564505e65583 v1.3b1 -7d743c865a9aa6bde8b603e32e0542031bba3c33 v1.3 -4fc85c82cc222554ae6b9c0b87776ed5f2b70c6e v1.4b1 -129f1299d4e97e884bbbbdd00baf101d178973e6 v1.4b2 -44a82ac654a4175569deed8e8a94b0cc8edee08d v1.4b3 -db49494c93dc73de06d5721c74eab533a947a92c v1.4 -062aed8a4ce2c91c81b80e29f02faff1cf5a761b v1.5a1 -c9498ac988372575cf7028b86395b900c9b0a840 v1.5a2 -dc5c968ec992aab3d40a7189df0c443d1c7a1a68 v1.5a3 -746654a0af680c7d9b814b210a026eb91bec9533 v1.5a4 -8ff58b5730f06be08fbbdc2bf592226f7a736201 v1.5b1 -eb78658d819fb0af09a8e6f9bedcb670805ed5f6 v1.5b2 -84461011a1a0ab402e352f06748f29fb5b5559e5 v1.5 -44aba4d26b01fbae0403efe654f9fd0347606732 v1.5.1 -fed63ccbe6dc3ac663bfe97a2f7006b1b28568f9 v1.5.2a1 -21d71f2e27248a0f4e393d0fc321ecf9b89321d2 v1.5.2a2 -f08c7a2a56f80741f5f192fd0ebe0b0967a203cf v1.5.2b1 -8fe7ec4b4fc1518fcac89e6bf674fbbce16150a9 v1.5.2b2 -39fb0dcc83dc375c1565ba65dbce0ed59b1359c9 v1.5.2c1 -61c91c7f101bab3149adfcd5646ae40e048de712 v1.5.2 -605eb9326ffe1fd1e43f40e2338d6652ab449fdf v1.6a1 -011bee8fd9f7f4da457ec71596484fb0882c0614 v1.6a2 -35c4fc1414a59888614b9be784a25f233ba67984 v2.0b1 -55bba197d4870cdae62aeca00e20240a756b84f8 v2.0b2 -e276329cce036a5f9e9d3451256dca5984e543dc v2.0c1 -2fa4e35083e02342ca014bf5bfba46aecb816c31 v2.0 -b60831eeab5a06dd3c5e8297a99e39297aa8794b v2.1a1 -b382f1f07ec6b2c95551658b30c6139eeb32077a v2.1a2 -d0c830db5e68edd4aaa3401216e610c9ff145826 v2.1b1 -b59a536ae1ef3774fd85c17f623e8926b7b6c095 v2.1b2 -d611276e9ad53b5d32d1e8065e1d811c32f7d96f v2.1c1 -ff065e674af6c9ab895bd9eff7d9e9039a376c7d v2.1c2 -020e95d8180d7943fe54701e1db0a7d7d87e2b1e v2.1 -08796a137f1ada2462f7a3177306df5f67a767e1 v2.2a3 -d054c29647f90bccb8345bd779bca1eecf2dd7f2 v2.3c1 -fce5c9e9abc722394cb2e909b7e2a39080d4448e v2.3c2 -92ca658fd420095b6284c9ce6e9082a80285ec9c v2.4a1 -055fc6955f3c6522bfeb7ed4c671c97d5baaaac2 v2.4a2 -186b72550e53533ef6175f6411f932c1298193d7 v2.4a3 -53cff04283855adf88ed0c0fd3698827ca843637 v2.4b1 -7e387a9dcc79954a77695adef8b593da35be1214 v2.4b2 -ff80d8bbef6e13426c8a85d7f9d837b8f8f89834 v2.4c1 -f31e18d313c7a4fc66914b2d27e130a0f72c0b69 v2.4 -cd3f783cd08a16781e236c0b9cb5717d1d995fa9 v3.0a1 -65e82140e281bf26f2e22eda05a7f9956c420f8b v3.0a2 -df15827f34881b9af0936350813ced5c123c8230 v3.0a3 -15f773f7300e372c56a21d59fe49ca26955a6477 v3.0a4 -e35935475153377d6727d64e6c52f72c3b84015b v3.0a5 -a335c4d643b1cfe14197a9ef195c9b2804f608fc v3.0b1 -16ec4bb14a68ea428acf09ebf0c92981da2646f3 v3.0b2 -509e30a7968e01be329ec121540b3e755fc4e566 v3.0b3 -507ede9c7f7f475dfafbd4a52c22d767d10a2bc0 v3.0rc1 -8fae465a39627b590385462e6095eb63af45240a v3.0rc2 -e83a60c69d53f5551a306e77a6d38e9b11485496 v3.0rc3 -bc1ce368986e45b1faf96f93995df46bcd75e7b8 v3.1a1 -ee430e5075db2adf8124e6b94916a89ca41d3171 v3.1a2 -b63020797f9678adaf4d2c3e26574a9eef2ef028 v3.1b1 -4353fd0843cb31b356adc50f93d220e2e7255ef2 v3.1rc1 -0b87e438e1b53e3f812cad963a7fdb65d198ba2f v3.1rc2 -a69a031ac1402dede8b1ef80096436bca6d371f3 v3.1 -35efb1054ec6ceca72017a587263cb6a9257340b v3.1.1rc1 -8b9c0f573ab29c41c6c5fdcca82a1fe0ff5355af v3.1.1 -149b8b87514d10416b598884db5f74651f625b38 v3.1.2rc1 -960efa327c5d9c18df995437b0ac550cb89c9f85 v3.1.2 -d18e9d71f369d8211f6ac87252c6d3211f9bd09f v3.1.3rc1 -a4f75773c0060cee38b0bb651a7aba6f56b0e996 v3.1.3 -32fcb9e94985cb19ce37ba9543f091c0dbe9d7dd v3.1.4rc1 -c918ec9f3a76d6afedfbb5d455004de880443a3d v3.1.4 -ee26aca3219cf4bb0b93352e83edcc9cb28c7802 v3.1.5rc1 -75db2bc69fc9a3e4801e94e3e19801cb096208d8 v3.1.5rc2 -7395330e495ec3316862ca1f6ce0aaf7bdf6785b v3.1.5 -b37b7834757492d009b99cf0ca4d42d2153d7fac v3.2a1 -56d4373cecb73c8b45126ba7b045b3c7b3f94b0b v3.2a2 -da012d9a2c23d144e399d2e01a55b8a83ad94573 v3.2a3 -d92a5b850f5e56808bedc01723906ed64c5e6e2e v3.2a4 -b635cea94195780c8716e236479af319bcc26253 v3.2b1 -e3af5f3a7904c0d5343ec9633ea66e7acfd23a66 v3.2b2 -865d5b24bf28ca41b536befc326407c03e74a4d5 v3.2rc1 -acf3e24dd0d0dfd1e20c907d696d3da965a8f56f v3.2rc2 -18c1f52896501c7ee13b038454a39acb45a87979 v3.2rc3 -a222a015e28d8ae9af3899258dc6c15c3d40add0 v3.2 -8ffac2337a3323323d02153ac919fd1483176652 v3.2.1b1 -cfa9364997c7f2e67b9cbb45c3a5fa3bba4e4999 v3.2.1rc1 -5df549718fb4841ff521fe051f6b54f290fad5d8 v3.2.1rc2 -ac1f7e5c05104d557d5acd922e95625ba5d1fe10 v3.2.1 -c860feaa348d663e598986894ee4680480577e15 v3.2.2rc1 -137e45f15c0bd262c9ad4c032d97425bc0589456 v3.2.2 -7085403daf439adb3f9e70ef13f6bedb1c447376 v3.2.3rc1 -428f05cb7277e1d42bb9dd8d1af6b6270ebc6112 v3.2.3rc2 -3d0686d90f55a78f96d9403da2c52dc2411419d0 v3.2.3 -b2cb7bc1edb8493c0a78f9331eae3e8fba6a881d v3.2.4rc1 -1e10bdeabe3de02f038a63c001911561ac1d13a7 v3.2.4 -cef745775b6583446572cffad704100983db2bea v3.2.5 -51382a5598ec96119cb84594572901c9c964dc3c v3.2.6rc1 -0bd5f4f14de965ca8e44c6e3965fee106176cfc4 v3.2.6 -f1a9a6505731714f0e157453ff850e3b71615c45 v3.3.0a1 -2f69db52d6de306cdaef0a0cc00cc823fb350b01 v3.3.0a2 -0b53b70a40a00013505eb35e3660057b62be77be v3.3.0a3 -7c51388a3aa7ce76a8541bbbdfc05d2d259a162c v3.3.0a4 -e15c554cd43eb23bc0a528a4e8741da9bbec9607 v3.3.0b1 -4972a8f1b2aa3d7cdd64dc96aa7fa112fe1ea343 v3.3.0b2 -8bb5c7bc46ba43804480f3e328e1fa956672c885 v3.3.0rc1 -88a0792e8ba3e4916b24c7e7a522c277d326d66e v3.3.0rc2 -c191d21cefafb3832c45570e84854e309aa62eaa v3.3.0rc3 -bd8afb90ebf28ba4edc901d4a235f75e7bbc79fd v3.3.0 -92c2cfb924055ce68c4f78f836dcfe688437ceb8 v3.3.1rc1 -d9893d13c6289aa03d33559ec67f97dcbf5c9e3c v3.3.1 -d047928ae3f6314a13b6137051315453d0ae89b6 v3.3.2 -fd53c500f8b80f54f3ecedec9da2e8c7e52a6888 v3.3.3rc1 -d32442c0e60dfbd71234e807d3d1dedd227495a9 v3.3.3rc2 -c3896275c0f61b2510a6c7e6c458a750359a91b8 v3.3.3 -fa92f5f940c6c0d839d7f0611e4b717606504a3c v3.3.4rc1 -7ff62415e4263c432c8acf6e424224209211eadb v3.3.4 -9ec811df548ed154a9bf9815383a916d6df31b98 v3.3.5rc1 -ca5635efe090f78806188ac2758f9948596aa8b2 v3.3.5rc2 -62cf4e77f78564714e7ea3d4bf1479ca1fbd0758 v3.3.5 -51317c9786f54267975abf2e9c502e6aaaa4a249 v3.3.6rc1 -971fec30da1fc5bf2b9fb28e09812a5127014211 v3.3.6 -46535f65e7f3bcdcf176f36d34bc1fed719ffd2b v3.4.0a1 -9265a2168e2cb2a84785d8717792acc661e6b692 v3.4.0a2 -dd9cdf90a5073510877e9dd5112f8e6cf20d5e89 v3.4.0a3 -e245b0d7209bb6d0e19316e1e2af1aa9c2139104 v3.4.0a4 -3405dc9a6afaa0a06dd1f6f182ec5c998dce6f5f v3.4.0b1 -ba32913eb13ec545a46dd0ce18035b6c416f0d78 v3.4.0b2 -a97ce3ecc96af79bd2e1ac66ce48d9138e0ca749 v3.4.0b3 -5e088cea8660677969113741c1313d570d977e02 v3.4.0rc1 -a300712ed38c9a242b736c44e806caea25a6dc05 v3.4.0rc2 -8a81cdab3e9d521daaef989fade94b16455fc3b8 v3.4.0rc3 -04f714765c13824c3bc2835d7b008908862e083a v3.4.0 -c67a19e11a7191baf30f313bf55e2e0b6c6f574e v3.4.1rc1 -c0e311e010fcb5bae8d87ca22051cd0845ea0ca0 v3.4.1 -8711a09513848cfc48c689d983495ee64f4668ca v3.4.2rc1 -ab2c023a9432f16652e89c404bbc84aa91bf55af v3.4.2 -69dd528ca6255a66c37cc5cf680e8357d108b036 v3.4.3rc1 -b4cbecbc0781e89a309d03b60a1f75f8499250e6 v3.4.3 -04f3f725896c6961212c3a12e8ac25be6958f4fa v3.4.4rc1 -737efcadf5a678b184e0fa431aae11276bf06648 v3.4.4 -3631bb4a2490292ebf81d3e947ae36da145da564 v3.4.5rc1 -619b61e505d0e2ccc8516b366e4ddd1971b46a6f v3.4.5 -e199a272ccdac5a8c073d4690f60c13e0b6d86b0 v3.4.6rc1 -b662f47769213f23325144b80782c05764d0f053 v3.4.6 -5d4b6a57d5fd7564bf73f3db0e46fe5eeb00bcd8 v3.5.0a1 -0337bd7ebcb6559d69679bc7025059ad1ce4f432 v3.5.0a2 -82656e28b5e5c4ae48d8dd8b5f0d7968908a82b6 v3.5.0a3 -413e0e0004f4f954331cb8122aa55fe208984955 v3.5.0a4 -071fefbb5e3db770c6c19fba9994699f121b1cea v3.5.0b1 -7a088af5615bf04024e9912068f4bd8f43ed3917 v3.5.0b2 -0035fcd9b9243ae52c2e830204fd9c1f7d528534 v3.5.0b3 -c0d64105463581f85d0e368e8d6e59b7fd8f12b1 v3.5.0b4 -1a58b1227501e046eee13d90f113417b60843301 v3.5.0rc1 -cc15d736d860303b9da90d43cd32db39bab048df v3.5.0rc2 -66ed52375df802f9d0a34480daaa8ce79fc41313 v3.5.0rc3 -2d033fedfa7f1e325fd14ccdaa9cb42155da206f v3.5.0rc4 -374f501f4567b7595f2ad7798aa09afa2456bb28 v3.5.0 -948ef16a69513ba1ff15c9d7d0b012b949df4c80 v3.5.1rc1 -37a07cee5969e6d3672583187a73cf636ff28e1b v3.5.1 -68feec6488b26327a85a634605dd28eca4daa5f1 v3.5.2rc1 -4def2a2901a5618ea45bcc8f2a1411ef33af18ad v3.5.2 -de530d7f21c0398bb2a2b67716e0638e5fadf727 v3.5.3rc1 -1880cb95a742cd001c67677de5c4efeab169416c v3.5.3 -5896da372fb044e38595fb74495de1e1e7c8fb3c v3.6.0a1 -37889342355223e2fc1438de3dc7ffcd625c60f7 v3.6.0a2 -f3edf13dc339b8942ae6b309771ab197dd8ce6fa v3.6.0a3 -017cf260936b444788c9b671d195b7bfd83dbd25 v3.6.0a4 -5b0ca4ed5e2f0669d76ece7ef975c544580f12b4 v3.6.0b1 -b9fadc7d1c3f9c3c77f32f35afbe1a1cc38070e6 v3.6.0b2 -8345e066c0ed713c3e510cbc8fafc1c38d6d306b v3.6.0b3 -18496abdb3d5c2730a659b747a89261b2219fecf v3.6.0b4 -29a273eee9a523ee178f6a66c4ac9d317c8fc84f v3.6.0rc1 -800a67f7806de45a7abd5273359e704bf147c079 v3.6.0rc2 -41df79263a11f2429d1dd0cfe12553de3dcb5508 v3.6.0 From webhook-mailer at python.org Wed Feb 14 04:18:19 2018 From: webhook-mailer at python.org (Andrew Svetlov) Date: Wed, 14 Feb 2018 09:18:19 -0000 Subject: [Python-checkins] bpo-32841: Fix cancellation in awaiting asyncio.Condition (#5665) Message-ID: https://github.com/python/cpython/commit/5746510b7aef423fa4afc92b2abb919307b1dbb9 commit: 5746510b7aef423fa4afc92b2abb919307b1dbb9 branch: master author: Bar Harel committer: Andrew Svetlov date: 2018-02-14T11:18:11+02:00 summary: bpo-32841: Fix cancellation in awaiting asyncio.Condition (#5665) files: A Misc/NEWS.d/next/Library/2018-02-14-00-21-24.bpo-32841.bvHDOc.rst M Lib/asyncio/locks.py M Lib/test/test_asyncio/test_locks.py diff --git a/Lib/asyncio/locks.py b/Lib/asyncio/locks.py index 508a2142d842..91f7a01de8ad 100644 --- a/Lib/asyncio/locks.py +++ b/Lib/asyncio/locks.py @@ -358,12 +358,16 @@ def __repr__(self): finally: # Must reacquire lock even if wait is cancelled + cancelled = False while True: try: await self.acquire() break except futures.CancelledError: - pass + cancelled = True + + if cancelled: + raise futures.CancelledError async def wait_for(self, predicate): """Wait until a predicate becomes true. diff --git a/Lib/test/test_asyncio/test_locks.py b/Lib/test/test_asyncio/test_locks.py index 3e3dd799273e..8642aa86b92b 100644 --- a/Lib/test/test_asyncio/test_locks.py +++ b/Lib/test/test_asyncio/test_locks.py @@ -214,11 +214,11 @@ def test_cancel_release_race(self): call_count += 1 await lock.acquire() lock_count += 1 - + async def lockandtrigger(): await lock.acquire() self.loop.call_soon(trigger) - + def trigger(): t1.cancel() lock.release() @@ -248,8 +248,6 @@ def trigger(): test_utils.run_briefly(self.loop) self.assertTrue(t3.cancelled()) - - def test_finished_waiter_cancelled(self): lock = asyncio.Lock(loop=self.loop) @@ -576,6 +574,31 @@ def test_wait_cancel_contested(self): self.assertTrue(cond.locked()) + def test_wait_cancel_after_notify(self): + # See bpo-32841 + cond = asyncio.Condition(loop=self.loop) + waited = False + + async def wait_on_cond(): + nonlocal waited + async with cond: + waited = True # Make sure this area was reached + await cond.wait() + + waiter = asyncio.ensure_future(wait_on_cond(), loop=self.loop) + test_utils.run_briefly(self.loop) # Start waiting + + self.loop.run_until_complete(cond.acquire()) + cond.notify() + test_utils.run_briefly(self.loop) # Get to acquire() + waiter.cancel() + test_utils.run_briefly(self.loop) # Activate cancellation + cond.release() + test_utils.run_briefly(self.loop) # Cancellation should occur + + self.assertTrue(waiter.cancelled()) + self.assertTrue(waited) + def test_wait_unacquired(self): cond = asyncio.Condition(loop=self.loop) self.assertRaises( diff --git a/Misc/NEWS.d/next/Library/2018-02-14-00-21-24.bpo-32841.bvHDOc.rst b/Misc/NEWS.d/next/Library/2018-02-14-00-21-24.bpo-32841.bvHDOc.rst new file mode 100644 index 000000000000..a6d45669d027 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-14-00-21-24.bpo-32841.bvHDOc.rst @@ -0,0 +1,2 @@ +Fixed `asyncio.Condition` issue which silently ignored cancellation after +notifying and cancelling a conditional lock. Patch by Bar Harel. From webhook-mailer at python.org Wed Feb 14 04:47:38 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 14 Feb 2018 09:47:38 -0000 Subject: [Python-checkins] bpo-32841: Fix cancellation in awaiting asyncio.Condition (GH-5665) Message-ID: https://github.com/python/cpython/commit/8caee0fa572e8ced00df553a7bdca49ddaf729e8 commit: 8caee0fa572e8ced00df553a7bdca49ddaf729e8 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-14T01:47:30-08:00 summary: bpo-32841: Fix cancellation in awaiting asyncio.Condition (GH-5665) (cherry picked from commit 5746510b7aef423fa4afc92b2abb919307b1dbb9) Co-authored-by: Bar Harel files: A Misc/NEWS.d/next/Library/2018-02-14-00-21-24.bpo-32841.bvHDOc.rst M Lib/asyncio/locks.py M Lib/test/test_asyncio/test_locks.py diff --git a/Lib/asyncio/locks.py b/Lib/asyncio/locks.py index 508a2142d842..91f7a01de8ad 100644 --- a/Lib/asyncio/locks.py +++ b/Lib/asyncio/locks.py @@ -358,12 +358,16 @@ def __repr__(self): finally: # Must reacquire lock even if wait is cancelled + cancelled = False while True: try: await self.acquire() break except futures.CancelledError: - pass + cancelled = True + + if cancelled: + raise futures.CancelledError async def wait_for(self, predicate): """Wait until a predicate becomes true. diff --git a/Lib/test/test_asyncio/test_locks.py b/Lib/test/test_asyncio/test_locks.py index 3e3dd799273e..8642aa86b92b 100644 --- a/Lib/test/test_asyncio/test_locks.py +++ b/Lib/test/test_asyncio/test_locks.py @@ -214,11 +214,11 @@ def test_cancel_release_race(self): call_count += 1 await lock.acquire() lock_count += 1 - + async def lockandtrigger(): await lock.acquire() self.loop.call_soon(trigger) - + def trigger(): t1.cancel() lock.release() @@ -248,8 +248,6 @@ def trigger(): test_utils.run_briefly(self.loop) self.assertTrue(t3.cancelled()) - - def test_finished_waiter_cancelled(self): lock = asyncio.Lock(loop=self.loop) @@ -576,6 +574,31 @@ def test_wait_cancel_contested(self): self.assertTrue(cond.locked()) + def test_wait_cancel_after_notify(self): + # See bpo-32841 + cond = asyncio.Condition(loop=self.loop) + waited = False + + async def wait_on_cond(): + nonlocal waited + async with cond: + waited = True # Make sure this area was reached + await cond.wait() + + waiter = asyncio.ensure_future(wait_on_cond(), loop=self.loop) + test_utils.run_briefly(self.loop) # Start waiting + + self.loop.run_until_complete(cond.acquire()) + cond.notify() + test_utils.run_briefly(self.loop) # Get to acquire() + waiter.cancel() + test_utils.run_briefly(self.loop) # Activate cancellation + cond.release() + test_utils.run_briefly(self.loop) # Cancellation should occur + + self.assertTrue(waiter.cancelled()) + self.assertTrue(waited) + def test_wait_unacquired(self): cond = asyncio.Condition(loop=self.loop) self.assertRaises( diff --git a/Misc/NEWS.d/next/Library/2018-02-14-00-21-24.bpo-32841.bvHDOc.rst b/Misc/NEWS.d/next/Library/2018-02-14-00-21-24.bpo-32841.bvHDOc.rst new file mode 100644 index 000000000000..a6d45669d027 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-14-00-21-24.bpo-32841.bvHDOc.rst @@ -0,0 +1,2 @@ +Fixed `asyncio.Condition` issue which silently ignored cancellation after +notifying and cancelling a conditional lock. Patch by Bar Harel. From solipsis at pitrou.net Wed Feb 14 05:01:52 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 14 Feb 2018 10:01:52 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=7 Message-ID: <20180214100152.1.230C3F28F40519CE@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_asyncio leaked [0, 3, 0] memory blocks, sum=3 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, -2, 1] memory blocks, sum=-1 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogsN8tqR', '--timeout', '7200'] From webhook-mailer at python.org Wed Feb 14 05:10:25 2018 From: webhook-mailer at python.org (Andrew Svetlov) Date: Wed, 14 Feb 2018 10:10:25 -0000 Subject: [Python-checkins] bpo-32841: Fix cancellation in awaiting asyncio.Condition (GH-5665) (GH-5683) Message-ID: https://github.com/python/cpython/commit/a23eecab9a0b724bdfde83d159ac2415927f042a commit: a23eecab9a0b724bdfde83d159ac2415927f042a branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Andrew Svetlov date: 2018-02-14T12:10:18+02:00 summary: bpo-32841: Fix cancellation in awaiting asyncio.Condition (GH-5665) (GH-5683) (cherry picked from commit 5746510b7aef423fa4afc92b2abb919307b1dbb9) Co-authored-by: Bar Harel files: A Misc/NEWS.d/next/Library/2018-02-14-00-21-24.bpo-32841.bvHDOc.rst M Lib/asyncio/locks.py M Lib/test/test_asyncio/test_locks.py diff --git a/Lib/asyncio/locks.py b/Lib/asyncio/locks.py index 14d21ff4e6f7..8ee7e2ea045f 100644 --- a/Lib/asyncio/locks.py +++ b/Lib/asyncio/locks.py @@ -349,12 +349,16 @@ def wait(self): finally: # Must reacquire lock even if wait is cancelled + cancelled = False while True: try: yield from self.acquire() break except futures.CancelledError: - pass + cancelled = True + + if cancelled: + raise futures.CancelledError @coroutine def wait_for(self, predicate): diff --git a/Lib/test/test_asyncio/test_locks.py b/Lib/test/test_asyncio/test_locks.py index 835d09ffc5d2..8686395da16f 100644 --- a/Lib/test/test_asyncio/test_locks.py +++ b/Lib/test/test_asyncio/test_locks.py @@ -190,11 +190,11 @@ def test_cancel_release_race(self): call_count += 1 await lock.acquire() lock_count += 1 - + async def lockandtrigger(): await lock.acquire() self.loop.call_soon(trigger) - + def trigger(): t1.cancel() lock.release() @@ -224,8 +224,6 @@ def trigger(): test_utils.run_briefly(self.loop) self.assertTrue(t3.cancelled()) - - def test_finished_waiter_cancelled(self): lock = asyncio.Lock(loop=self.loop) @@ -557,6 +555,31 @@ def test_wait_cancel_contested(self): self.assertTrue(cond.locked()) + def test_wait_cancel_after_notify(self): + # See bpo-32841 + cond = asyncio.Condition(loop=self.loop) + waited = False + + async def wait_on_cond(): + nonlocal waited + async with cond: + waited = True # Make sure this area was reached + await cond.wait() + + waiter = asyncio.ensure_future(wait_on_cond(), loop=self.loop) + test_utils.run_briefly(self.loop) # Start waiting + + self.loop.run_until_complete(cond.acquire()) + cond.notify() + test_utils.run_briefly(self.loop) # Get to acquire() + waiter.cancel() + test_utils.run_briefly(self.loop) # Activate cancellation + cond.release() + test_utils.run_briefly(self.loop) # Cancellation should occur + + self.assertTrue(waiter.cancelled()) + self.assertTrue(waited) + def test_wait_unacquired(self): cond = asyncio.Condition(loop=self.loop) self.assertRaises( diff --git a/Misc/NEWS.d/next/Library/2018-02-14-00-21-24.bpo-32841.bvHDOc.rst b/Misc/NEWS.d/next/Library/2018-02-14-00-21-24.bpo-32841.bvHDOc.rst new file mode 100644 index 000000000000..a6d45669d027 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-14-00-21-24.bpo-32841.bvHDOc.rst @@ -0,0 +1,2 @@ +Fixed `asyncio.Condition` issue which silently ignored cancellation after +notifying and cancelling a conditional lock. Patch by Bar Harel. From webhook-mailer at python.org Wed Feb 14 14:54:37 2018 From: webhook-mailer at python.org (Mariatta) Date: Wed, 14 Feb 2018 19:54:37 -0000 Subject: [Python-checkins] Update comment in posixmodule.c (GH-5681) Message-ID: https://github.com/python/cpython/commit/7745ec4e356ac1f4eaf43b155f4482c20a907d48 commit: 7745ec4e356ac1f4eaf43b155f4482c20a907d48 branch: master author: ngie-eign <1574099+ngie-eign at users.noreply.github.com> committer: Mariatta date: 2018-02-14T11:54:28-08:00 summary: Update comment in posixmodule.c (GH-5681) A closing parentheses was missing. Signed-off-by: Ngie Cooper files: M Modules/posixmodule.c diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 72fda6a21966..d242df0b6f31 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -6102,7 +6102,7 @@ os_sched_getaffinity_impl(PyObject *module, pid_t pid) #ifdef HAVE_STROPTS_H #include #endif -#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX */ +#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX) */ #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) From webhook-mailer at python.org Wed Feb 14 15:43:20 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 14 Feb 2018 20:43:20 -0000 Subject: [Python-checkins] Update comment in posixmodule.c (GH-5681) Message-ID: https://github.com/python/cpython/commit/836b6421484cbbe3de105d9c7cec9371422d1397 commit: 836b6421484cbbe3de105d9c7cec9371422d1397 branch: 2.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-14T12:43:17-08:00 summary: Update comment in posixmodule.c (GH-5681) A closing parentheses was missing. Signed-off-by: Ngie Cooper (cherry picked from commit 7745ec4e356ac1f4eaf43b155f4482c20a907d48) Co-authored-by: ngie-eign <1574099+ngie-eign at users.noreply.github.com> files: M Modules/posixmodule.c diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index cecbb45fb4b3..f8e081ed7d61 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -3936,7 +3936,7 @@ posix_fork(PyObject *self, PyObject *noargs) #ifdef HAVE_STROPTS_H #include #endif -#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX */ +#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX) */ #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) PyDoc_STRVAR(posix_openpty__doc__, From webhook-mailer at python.org Wed Feb 14 16:06:49 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 14 Feb 2018 21:06:49 -0000 Subject: [Python-checkins] Update comment in posixmodule.c (GH-5681) Message-ID: https://github.com/python/cpython/commit/f0616ce137abecd18e9a1b1e191f657f049a4147 commit: f0616ce137abecd18e9a1b1e191f657f049a4147 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-14T13:06:46-08:00 summary: Update comment in posixmodule.c (GH-5681) A closing parentheses was missing. Signed-off-by: Ngie Cooper (cherry picked from commit 7745ec4e356ac1f4eaf43b155f4482c20a907d48) Co-authored-by: ngie-eign <1574099+ngie-eign at users.noreply.github.com> files: M Modules/posixmodule.c diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 63f5b2a38896..7304feed72df 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -6102,7 +6102,7 @@ os_sched_getaffinity_impl(PyObject *module, pid_t pid) #ifdef HAVE_STROPTS_H #include #endif -#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX */ +#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX) */ #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) From webhook-mailer at python.org Wed Feb 14 16:16:40 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 14 Feb 2018 21:16:40 -0000 Subject: [Python-checkins] Update comment in posixmodule.c (GH-5681) Message-ID: https://github.com/python/cpython/commit/f62a9d41b518cc325964d6a3f723fcada340efce commit: f62a9d41b518cc325964d6a3f723fcada340efce branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-14T13:16:36-08:00 summary: Update comment in posixmodule.c (GH-5681) A closing parentheses was missing. Signed-off-by: Ngie Cooper (cherry picked from commit 7745ec4e356ac1f4eaf43b155f4482c20a907d48) Co-authored-by: ngie-eign <1574099+ngie-eign at users.noreply.github.com> files: M Modules/posixmodule.c diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 80b1fbdfd253..85ec255fcb4f 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -5780,7 +5780,7 @@ os_sched_getaffinity_impl(PyObject *module, pid_t pid) #ifdef HAVE_STROPTS_H #include #endif -#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX */ +#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX) */ #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) From solipsis at pitrou.net Thu Feb 15 04:12:01 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 15 Feb 2018 09:12:01 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=3 Message-ID: <20180215091201.1.102AD45C8F3C71C8@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, 1, -2] memory blocks, sum=0 test_multiprocessing_spawn leaked [-2, 1, 0] memory blocks, sum=-1 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflog7ck_jo', '--timeout', '7200'] From solipsis at pitrou.net Fri Feb 16 04:14:42 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 16 Feb 2018 09:14:42 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=11 Message-ID: <20180216091442.1.E5F9E2338F718144@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_fork leaked [0, -2, 0] memory blocks, sum=-2 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/reflogSBfMqk', '--timeout', '7200'] From webhook-mailer at python.org Fri Feb 16 10:45:48 2018 From: webhook-mailer at python.org (Barry Warsaw) Date: Fri, 16 Feb 2018 15:45:48 -0000 Subject: [Python-checkins] Update and sync importlib.resources documentation (#5694) Message-ID: https://github.com/python/cpython/commit/997b8c140e768c849fa99d172245a7688af20a89 commit: 997b8c140e768c849fa99d172245a7688af20a89 branch: master author: Barry Warsaw committer: GitHub date: 2018-02-16T10:45:39-05:00 summary: Update and sync importlib.resources documentation (#5694) files: M Doc/library/importlib.rst diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst index c80f4606f3d1..db75f69a0d00 100644 --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -369,9 +369,9 @@ ABC hierarchy:: An abstract base class for a :term:`loader`. See :pep:`302` for the exact definition for a loader. - For loaders that wish to support resource reading, they should - implement a ``get_resource_reader(fullname)`` method as specified - by :class:`importlib.abc.ResourceReader`. + Loaders that wish to support resource reading should implement a + ``get_resource_reader(fullname)`` method as specified by + :class:`importlib.abc.ResourceReader`. .. versionchanged:: 3.7 Introduced the optional ``get_resource_reader()`` method. @@ -813,8 +813,25 @@ Resources are roughly akin to files inside directories, though it's important to keep in mind that this is just a metaphor. Resources and packages **do not** have to exist as physical files and directories on the file system. -Loaders can support resources by implementing the :class:`ResourceReader` -abstract base class. +.. note:: + + This module provides functionality similar to `pkg_resources + `_ `Basic + Resource Access + `_ + without the performance overhead of that package. This makes reading + resources included in packages easier, with more stable and consistent + semantics. + + The standalone backport of this module provides more information + on `using importlib.resources + `_ and + `migrating from pkg_resources to importlib.resources + `_. + +Loaders that wish to support resource reading should implement a +``get_resource_reader(fullname)`` method as specified by +:class:`importlib.abc.ResourceReader`. The following types are defined. From webhook-mailer at python.org Fri Feb 16 11:07:57 2018 From: webhook-mailer at python.org (Barry Warsaw) Date: Fri, 16 Feb 2018 16:07:57 -0000 Subject: [Python-checkins] Update and sync importlib.resources documentation (GH-5694) (#5697) Message-ID: https://github.com/python/cpython/commit/f26b0190c21b7519349605c05ac2a76091f71f7f commit: f26b0190c21b7519349605c05ac2a76091f71f7f branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Barry Warsaw date: 2018-02-16T11:07:53-05:00 summary: Update and sync importlib.resources documentation (GH-5694) (#5697) (cherry picked from commit 997b8c140e768c849fa99d172245a7688af20a89) Co-authored-by: Barry Warsaw files: M Doc/library/importlib.rst diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst index c80f4606f3d1..db75f69a0d00 100644 --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -369,9 +369,9 @@ ABC hierarchy:: An abstract base class for a :term:`loader`. See :pep:`302` for the exact definition for a loader. - For loaders that wish to support resource reading, they should - implement a ``get_resource_reader(fullname)`` method as specified - by :class:`importlib.abc.ResourceReader`. + Loaders that wish to support resource reading should implement a + ``get_resource_reader(fullname)`` method as specified by + :class:`importlib.abc.ResourceReader`. .. versionchanged:: 3.7 Introduced the optional ``get_resource_reader()`` method. @@ -813,8 +813,25 @@ Resources are roughly akin to files inside directories, though it's important to keep in mind that this is just a metaphor. Resources and packages **do not** have to exist as physical files and directories on the file system. -Loaders can support resources by implementing the :class:`ResourceReader` -abstract base class. +.. note:: + + This module provides functionality similar to `pkg_resources + `_ `Basic + Resource Access + `_ + without the performance overhead of that package. This makes reading + resources included in packages easier, with more stable and consistent + semantics. + + The standalone backport of this module provides more information + on `using importlib.resources + `_ and + `migrating from pkg_resources to importlib.resources + `_. + +Loaders that wish to support resource reading should implement a +``get_resource_reader(fullname)`` method as specified by +:class:`importlib.abc.ResourceReader`. The following types are defined. From webhook-mailer at python.org Fri Feb 16 11:46:42 2018 From: webhook-mailer at python.org (Mariatta) Date: Fri, 16 Feb 2018 16:46:42 -0000 Subject: [Python-checkins] Correct the code example in Python 3.7's What's New (GH-5696) Message-ID: https://github.com/python/cpython/commit/b65cb163d6e125606070c54dc757f421fe419b59 commit: b65cb163d6e125606070c54dc757f421fe419b59 branch: master author: xpvpc <32843902+xpvpc at users.noreply.github.com> committer: Mariatta date: 2018-02-16T08:46:39-08:00 summary: Correct the code example in Python 3.7's What's New (GH-5696) There was an extra dash in the example for re.sub(). files: M Doc/whatsnew/3.7.rst diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index c3761c565322..89ca5d75c85d 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -1146,7 +1146,7 @@ Changes in the Python API :func:`re.sub()` now replaces empty matches adjacent to a previous non-empty match. For example ``re.sub('x*', '-', 'abxd')`` returns now - ``'-a-b--d-'`` instead of ``'-a-b--d-'`` (the first minus between 'b' and + ``'-a-b--d-'`` instead of ``'-a-b-d-'`` (the first minus between 'b' and 'd' replaces 'x', and the second minus replaces an empty string between 'x' and 'd'). From webhook-mailer at python.org Fri Feb 16 11:47:56 2018 From: webhook-mailer at python.org (Yury Selivanov) Date: Fri, 16 Feb 2018 16:47:56 -0000 Subject: [Python-checkins] bpo-32436: Add docs for contextvars (#5685) Message-ID: https://github.com/python/cpython/commit/bd093355a6aaf2f4ca3ed153e195da57870a55eb commit: bd093355a6aaf2f4ca3ed153e195da57870a55eb branch: master author: Yury Selivanov committer: GitHub date: 2018-02-16T11:47:54-05:00 summary: bpo-32436: Add docs for contextvars (#5685) files: A Doc/library/contextvars.rst A Misc/NEWS.d/next/Documentation/2018-02-14-11-10-41.bpo-32436.TTJ2jb.rst M Doc/library/index.rst M Doc/whatsnew/3.7.rst diff --git a/Doc/library/contextvars.rst b/Doc/library/contextvars.rst new file mode 100644 index 000000000000..1e0987ce4d6a --- /dev/null +++ b/Doc/library/contextvars.rst @@ -0,0 +1,279 @@ +:mod:`contextvars` --- Context Variables +======================================== + +.. module:: contextvars + :synopsis: Context Variables + +.. sectionauthor:: Yury Selivanov + +-------------- + +This module provides APIs to manage, store, and access non-local +state. The :class:`~contextvars.ContextVar` class is used to declare +and work with *Context Variables*. The :func:`~contextvars.copy_context` +function and the :class:`~contextvars.Context` class should be used to +manage the current context in asynchronous frameworks. + +Context managers that have state should use Context Variables +instead of :func:`threading.local()` to prevent their state from +bleeding to other code unexpectedly, when used in concurrent code. + +See also :pep:`567` for additional details. + +.. versionadded:: 3.7 + + +Context Variables +----------------- + +.. class:: ContextVar(name, [\*, default]) + + This class is used to declare a new Context Variable, e.g.:: + + var: ContextVar[int] = ContextVar('var', default=42) + + The required *name* parameter is used for introspection and debug + purposes. + + The optional keyword-only *default* parameter is returned by + :meth:`ContextVar.get` when no value for the variable is found + in the current context. + + **Important:** Context Variables should be created at the top module + level and never in closures. :class:`Context` objects hold strong + references to context variables which prevents context variables + from being properly garbage collected. + + .. attribute:: ContextVar.name + + The name of the variable. This is a read-only property. + + .. method:: get([default]) + + Return a value for the context variable for the current context. + + If there is no value for the variable in the current context, + the method will: + + * return the value of the *default* argument of the method, + if provided; or + + * return the default value for the context variable, + if it was created with one; or + + * raise a :exc:`LookupError`. + + .. method:: set(value) + + Call to set a new value for the context variable in the current + context. + + The required *value* argument is the new value for the context + variable. + + Returns a :class:`~contextvars.Token` object that can be used + to restore the variable to its previous value via the + :meth:`ContextVar.reset` method. + + .. method:: reset(token) + + Reset the context variable to the value it had before the + :meth:`ContextVar.set` that created the *token* was used. + + For example:: + + var = ContextVar('var') + + token = var.set('new value') + # code that uses 'var'; var.get() returns 'new value'. + var.reset(token) + + # After the reset call the var has no value again, so + # var.get() would raise a LookupError. + + +.. class:: contextvars.Token + + *Token* objects are returned by the :meth:`ContextVar.set` method. + They can be passed to the :meth:`ContextVar.reset` method to revert + the value of the variable to what it was before the corresponding + *set*. + + .. attribute:: Token.var + + A read-only property. Points to the :class:`ContextVar` object + that created the token. + + .. attribute:: Token.old_value + + A read-only property. Set to the value the variable had before + the :meth:`ContextVar.set` method call that created the token. + It points to :attr:`Token.MISSING` is the variable was not set + before the call. + + .. attribute:: Token.MISSING + + A marker object used by :attr:`Token.old_value`. + + +Manual Context Management +------------------------- + +.. function:: copy_context() + + Returns a copy of the current :class:`~contextvars.Context` object. + + The following snippet gets a copy of the current context and prints + all variables and their values that are set in it:: + + ctx: Context = copy_context() + print(list(ctx.items())) + + The function has an O(1) complexity, i.e. works equally fast for + contexts with a few context variables and for contexts that have + a lot of them. + + +.. class:: Context() + + A mapping of :class:`ContextVars ` to their values. + + ``Context()`` creates an empty context with no values in it. + To get a copy of the current context use the + :func:`~contextvars.copy_context` function. + + Context implements the :class:`collections.abc.Mapping` interface. + + .. method:: run(callable, \*args, \*\*kwargs) + + Execute ``callable(*args, **kwargs)`` code in the context object + the *run* method is called on. Return the result of the execution + or propagate an exception if one occurred. + + Any changes to any context variables that *callable* makes will + be contained in the context object:: + + var = ContextVar('var') + var.set('spam') + + def main(): + # 'var' was set to 'spam' before + # calling 'copy_context()' and 'ctx.run(main)', so: + # var.get() == ctx[var] == 'spam' + + var.set('ham') + + # Now, after setting 'var' to 'ham': + # var.get() == ctx[var] == 'ham' + + ctx = copy_context() + + # Any changes that the 'main' function makes to 'var' + # will be contained in 'ctx'. + ctx.run(main) + + # The 'main()' function was run in the 'ctx' context, + # so changes to 'var' are contained in it: + # ctx[var] == 'ham' + + # However, outside of 'ctx', 'var' is still set to 'spam': + # var.get() == 'spam' + + The method raises a :exc:`RuntimeError` when called on the same + context object from more than one OS thread, or when called + recursively. + + .. method:: copy() + + Return a shallow copy of the context object. + + .. describe:: var in context + + Return ``True`` if the *context* has a value for *var* set; + return ``False`` otherwise. + + .. describe:: context[var] + + Return the value of the *var* :class:`ContextVar` variable. + If the variable is not set in the context object, a + :exc:`KeyError` is raised. + + .. method:: get(var, [default]) + + Return the value for *var* if *var* has the value in the context + object. Return *default* otherwise. If *default* is not given, + return ``None``. + + .. describe:: iter(context) + + Return an iterator over the variables stored in the context + object. + + .. describe:: len(proxy) + + Return the number of variables set in the context object. + + .. method:: keys() + + Return a list of all variables in the context object. + + .. method:: values() + + Return a list of all variables' values in the context object. + + + .. method:: items() + + Return a list of 2-tuples containing all variables and their + values in the context object. + + +asyncio support +--------------- + +Context variables are natively supported in :mod:`asyncio` and are +ready to be used without any extra configuration. For example, here +is a simple echo server, that uses a context variable to make the +address of a remote client available in the Task that handles that +client:: + + import asyncio + import contextvars + + client_addr_var = contextvars.ContextVar('client_addr') + + def render_goodbye(): + # The address of the currently handled client can be accessed + # without passing it explicitly to this function. + + client_addr = client_addr_var.get() + return f'Good bye, client @ {client_addr}\n'.encode() + + async def handle_request(reader, writer): + addr = writer.transport.get_extra_info('socket').getpeername() + client_addr_var.set(addr) + + # In any code that we call is is now possible to get + # client's address by calling 'client_addr_var.get()'. + + while True: + line = await reader.readline() + print(line) + if not line.strip(): + break + writer.write(line) + + writer.write(render_goodbye()) + writer.close() + + async def main(): + srv = await asyncio.start_server( + handle_request, '127.0.0.1', 8081) + + async with srv: + await srv.serve_forever() + + asyncio.run(main()) + + # To test it you can use telnet: + # telnet 127.0.0.1 8081 diff --git a/Doc/library/index.rst b/Doc/library/index.rst index a925e10ee498..da6a460e2c31 100644 --- a/Doc/library/index.rst +++ b/Doc/library/index.rst @@ -55,6 +55,7 @@ the `Python Package Index `_. crypto.rst allos.rst concurrency.rst + contextvars.rst ipc.rst netdata.rst markup.rst diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 89ca5d75c85d..7c98c7cfa38d 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -340,6 +340,25 @@ For example:: 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 + + New Development Mode: -X dev ---------------------------- diff --git a/Misc/NEWS.d/next/Documentation/2018-02-14-11-10-41.bpo-32436.TTJ2jb.rst b/Misc/NEWS.d/next/Documentation/2018-02-14-11-10-41.bpo-32436.TTJ2jb.rst new file mode 100644 index 000000000000..b764b45cd968 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2018-02-14-11-10-41.bpo-32436.TTJ2jb.rst @@ -0,0 +1 @@ +Add documentation for the contextvars module (PEP 567). From webhook-mailer at python.org Fri Feb 16 12:03:20 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 16 Feb 2018 17:03:20 -0000 Subject: [Python-checkins] bpo-32436: Add docs for contextvars (GH-5685) Message-ID: https://github.com/python/cpython/commit/af6eaae306dce5095a350348432cc8595efc0211 commit: af6eaae306dce5095a350348432cc8595efc0211 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-16T09:03:18-08:00 summary: bpo-32436: Add docs for contextvars (GH-5685) (cherry picked from commit bd093355a6aaf2f4ca3ed153e195da57870a55eb) Co-authored-by: Yury Selivanov files: A Doc/library/contextvars.rst A Misc/NEWS.d/next/Documentation/2018-02-14-11-10-41.bpo-32436.TTJ2jb.rst M Doc/library/index.rst M Doc/whatsnew/3.7.rst diff --git a/Doc/library/contextvars.rst b/Doc/library/contextvars.rst new file mode 100644 index 000000000000..1e0987ce4d6a --- /dev/null +++ b/Doc/library/contextvars.rst @@ -0,0 +1,279 @@ +:mod:`contextvars` --- Context Variables +======================================== + +.. module:: contextvars + :synopsis: Context Variables + +.. sectionauthor:: Yury Selivanov + +-------------- + +This module provides APIs to manage, store, and access non-local +state. The :class:`~contextvars.ContextVar` class is used to declare +and work with *Context Variables*. The :func:`~contextvars.copy_context` +function and the :class:`~contextvars.Context` class should be used to +manage the current context in asynchronous frameworks. + +Context managers that have state should use Context Variables +instead of :func:`threading.local()` to prevent their state from +bleeding to other code unexpectedly, when used in concurrent code. + +See also :pep:`567` for additional details. + +.. versionadded:: 3.7 + + +Context Variables +----------------- + +.. class:: ContextVar(name, [\*, default]) + + This class is used to declare a new Context Variable, e.g.:: + + var: ContextVar[int] = ContextVar('var', default=42) + + The required *name* parameter is used for introspection and debug + purposes. + + The optional keyword-only *default* parameter is returned by + :meth:`ContextVar.get` when no value for the variable is found + in the current context. + + **Important:** Context Variables should be created at the top module + level and never in closures. :class:`Context` objects hold strong + references to context variables which prevents context variables + from being properly garbage collected. + + .. attribute:: ContextVar.name + + The name of the variable. This is a read-only property. + + .. method:: get([default]) + + Return a value for the context variable for the current context. + + If there is no value for the variable in the current context, + the method will: + + * return the value of the *default* argument of the method, + if provided; or + + * return the default value for the context variable, + if it was created with one; or + + * raise a :exc:`LookupError`. + + .. method:: set(value) + + Call to set a new value for the context variable in the current + context. + + The required *value* argument is the new value for the context + variable. + + Returns a :class:`~contextvars.Token` object that can be used + to restore the variable to its previous value via the + :meth:`ContextVar.reset` method. + + .. method:: reset(token) + + Reset the context variable to the value it had before the + :meth:`ContextVar.set` that created the *token* was used. + + For example:: + + var = ContextVar('var') + + token = var.set('new value') + # code that uses 'var'; var.get() returns 'new value'. + var.reset(token) + + # After the reset call the var has no value again, so + # var.get() would raise a LookupError. + + +.. class:: contextvars.Token + + *Token* objects are returned by the :meth:`ContextVar.set` method. + They can be passed to the :meth:`ContextVar.reset` method to revert + the value of the variable to what it was before the corresponding + *set*. + + .. attribute:: Token.var + + A read-only property. Points to the :class:`ContextVar` object + that created the token. + + .. attribute:: Token.old_value + + A read-only property. Set to the value the variable had before + the :meth:`ContextVar.set` method call that created the token. + It points to :attr:`Token.MISSING` is the variable was not set + before the call. + + .. attribute:: Token.MISSING + + A marker object used by :attr:`Token.old_value`. + + +Manual Context Management +------------------------- + +.. function:: copy_context() + + Returns a copy of the current :class:`~contextvars.Context` object. + + The following snippet gets a copy of the current context and prints + all variables and their values that are set in it:: + + ctx: Context = copy_context() + print(list(ctx.items())) + + The function has an O(1) complexity, i.e. works equally fast for + contexts with a few context variables and for contexts that have + a lot of them. + + +.. class:: Context() + + A mapping of :class:`ContextVars ` to their values. + + ``Context()`` creates an empty context with no values in it. + To get a copy of the current context use the + :func:`~contextvars.copy_context` function. + + Context implements the :class:`collections.abc.Mapping` interface. + + .. method:: run(callable, \*args, \*\*kwargs) + + Execute ``callable(*args, **kwargs)`` code in the context object + the *run* method is called on. Return the result of the execution + or propagate an exception if one occurred. + + Any changes to any context variables that *callable* makes will + be contained in the context object:: + + var = ContextVar('var') + var.set('spam') + + def main(): + # 'var' was set to 'spam' before + # calling 'copy_context()' and 'ctx.run(main)', so: + # var.get() == ctx[var] == 'spam' + + var.set('ham') + + # Now, after setting 'var' to 'ham': + # var.get() == ctx[var] == 'ham' + + ctx = copy_context() + + # Any changes that the 'main' function makes to 'var' + # will be contained in 'ctx'. + ctx.run(main) + + # The 'main()' function was run in the 'ctx' context, + # so changes to 'var' are contained in it: + # ctx[var] == 'ham' + + # However, outside of 'ctx', 'var' is still set to 'spam': + # var.get() == 'spam' + + The method raises a :exc:`RuntimeError` when called on the same + context object from more than one OS thread, or when called + recursively. + + .. method:: copy() + + Return a shallow copy of the context object. + + .. describe:: var in context + + Return ``True`` if the *context* has a value for *var* set; + return ``False`` otherwise. + + .. describe:: context[var] + + Return the value of the *var* :class:`ContextVar` variable. + If the variable is not set in the context object, a + :exc:`KeyError` is raised. + + .. method:: get(var, [default]) + + Return the value for *var* if *var* has the value in the context + object. Return *default* otherwise. If *default* is not given, + return ``None``. + + .. describe:: iter(context) + + Return an iterator over the variables stored in the context + object. + + .. describe:: len(proxy) + + Return the number of variables set in the context object. + + .. method:: keys() + + Return a list of all variables in the context object. + + .. method:: values() + + Return a list of all variables' values in the context object. + + + .. method:: items() + + Return a list of 2-tuples containing all variables and their + values in the context object. + + +asyncio support +--------------- + +Context variables are natively supported in :mod:`asyncio` and are +ready to be used without any extra configuration. For example, here +is a simple echo server, that uses a context variable to make the +address of a remote client available in the Task that handles that +client:: + + import asyncio + import contextvars + + client_addr_var = contextvars.ContextVar('client_addr') + + def render_goodbye(): + # The address of the currently handled client can be accessed + # without passing it explicitly to this function. + + client_addr = client_addr_var.get() + return f'Good bye, client @ {client_addr}\n'.encode() + + async def handle_request(reader, writer): + addr = writer.transport.get_extra_info('socket').getpeername() + client_addr_var.set(addr) + + # In any code that we call is is now possible to get + # client's address by calling 'client_addr_var.get()'. + + while True: + line = await reader.readline() + print(line) + if not line.strip(): + break + writer.write(line) + + writer.write(render_goodbye()) + writer.close() + + async def main(): + srv = await asyncio.start_server( + handle_request, '127.0.0.1', 8081) + + async with srv: + await srv.serve_forever() + + asyncio.run(main()) + + # To test it you can use telnet: + # telnet 127.0.0.1 8081 diff --git a/Doc/library/index.rst b/Doc/library/index.rst index a925e10ee498..da6a460e2c31 100644 --- a/Doc/library/index.rst +++ b/Doc/library/index.rst @@ -55,6 +55,7 @@ the `Python Package Index `_. crypto.rst allos.rst concurrency.rst + contextvars.rst ipc.rst netdata.rst markup.rst diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index aaf4dcfa3050..efebcee942b6 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -340,6 +340,25 @@ For example:: 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 + + New Development Mode: -X dev ---------------------------- diff --git a/Misc/NEWS.d/next/Documentation/2018-02-14-11-10-41.bpo-32436.TTJ2jb.rst b/Misc/NEWS.d/next/Documentation/2018-02-14-11-10-41.bpo-32436.TTJ2jb.rst new file mode 100644 index 000000000000..b764b45cd968 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2018-02-14-11-10-41.bpo-32436.TTJ2jb.rst @@ -0,0 +1 @@ +Add documentation for the contextvars module (PEP 567). From webhook-mailer at python.org Fri Feb 16 13:28:24 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 16 Feb 2018 18:28:24 -0000 Subject: [Python-checkins] Correct the code example in Python 3.7's What's New (GH-5696) Message-ID: https://github.com/python/cpython/commit/803e1a5722302476ee079d27f26dd24ed57a1743 commit: 803e1a5722302476ee079d27f26dd24ed57a1743 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-16T10:28:18-08:00 summary: Correct the code example in Python 3.7's What's New (GH-5696) There was an extra dash in the example for re.sub(). (cherry picked from commit b65cb163d6e125606070c54dc757f421fe419b59) Co-authored-by: xpvpc <32843902+xpvpc at users.noreply.github.com> files: M Doc/whatsnew/3.7.rst diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index efebcee942b6..748189e57486 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -1157,7 +1157,7 @@ Changes in the Python API :func:`re.sub()` now replaces empty matches adjacent to a previous non-empty match. For example ``re.sub('x*', '-', 'abxd')`` returns now - ``'-a-b--d-'`` instead of ``'-a-b--d-'`` (the first minus between 'b' and + ``'-a-b--d-'`` instead of ``'-a-b-d-'`` (the first minus between 'b' and 'd' replaces 'x', and the second minus replaces an empty string between 'x' and 'd'). From webhook-mailer at python.org Fri Feb 16 20:53:49 2018 From: webhook-mailer at python.org (Eric Snow) Date: Sat, 17 Feb 2018 01:53:49 -0000 Subject: [Python-checkins] bpo-32604: Clean up created subinterpreters before runtime finalization. (gh-5709) Message-ID: https://github.com/python/cpython/commit/4c6955e2b0ccf88c705f8d1fac685a8e65f9699e commit: 4c6955e2b0ccf88c705f8d1fac685a8e65f9699e branch: master author: Eric Snow committer: GitHub date: 2018-02-16T18:53:40-07:00 summary: bpo-32604: Clean up created subinterpreters before runtime finalization. (gh-5709) files: M Include/internal/pystate.h M Include/pystate.h M Lib/test/test__xxsubinterpreters.py M Modules/_xxsubinterpretersmodule.c M Python/pystate.c diff --git a/Include/internal/pystate.h b/Include/internal/pystate.h index 2b60b25c19b1..da642c6fd007 100644 --- a/Include/internal/pystate.h +++ b/Include/internal/pystate.h @@ -69,6 +69,10 @@ PyAPI_FUNC(void) _PyPathConfig_Clear(_PyPathConfig *config); PyAPI_FUNC(PyInterpreterState *) _PyInterpreterState_LookUpID(PY_INT64_T); +PyAPI_FUNC(int) _PyInterpreterState_IDInitref(PyInterpreterState *); +PyAPI_FUNC(void) _PyInterpreterState_IDIncref(PyInterpreterState *); +PyAPI_FUNC(void) _PyInterpreterState_IDDecref(PyInterpreterState *); + /* cross-interpreter data */ diff --git a/Include/pystate.h b/Include/pystate.h index a19c1ed3b81c..29d7148bf9a3 100644 --- a/Include/pystate.h +++ b/Include/pystate.h @@ -8,6 +8,8 @@ extern "C" { #endif +#include "pythread.h" + /* This limitation is for performance and simplicity. If needed it can be removed (with effort). */ #define MAX_CO_EXTRA_USERS 255 @@ -111,6 +113,8 @@ typedef struct _is { struct _ts *tstate_head; int64_t id; + int64_t id_refcount; + PyThread_type_lock id_mutex; PyObject *modules; PyObject *modules_by_index; diff --git a/Lib/test/test__xxsubinterpreters.py b/Lib/test/test__xxsubinterpreters.py index 8d72ca200214..d280270af91b 100644 --- a/Lib/test/test__xxsubinterpreters.py +++ b/Lib/test/test__xxsubinterpreters.py @@ -152,7 +152,7 @@ def test_subinterpreter(self): interp = interpreters.create() out = _run_output(interp, dedent(""" import _xxsubinterpreters as _interpreters - print(_interpreters.get_current()) + print(int(_interpreters.get_current())) """)) cur = int(out.strip()) _, expected = interpreters.list_all() @@ -172,7 +172,7 @@ def test_from_subinterpreter(self): interp = interpreters.create() out = _run_output(interp, dedent(""" import _xxsubinterpreters as _interpreters - print(_interpreters.get_main()) + print(int(_interpreters.get_main())) """)) main = int(out.strip()) self.assertEqual(main, expected) @@ -196,7 +196,7 @@ def test_from_subinterpreter(self): interp = interpreters.create() out = _run_output(interp, dedent(f""" import _xxsubinterpreters as _interpreters - if _interpreters.is_running({interp}): + if _interpreters.is_running({int(interp)}): print(True) else: print(False) @@ -218,6 +218,63 @@ def test_bad_id(self): 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): @@ -256,7 +313,7 @@ def test_in_subinterpreter(self): out = _run_output(id1, dedent(""" import _xxsubinterpreters as _interpreters id = _interpreters.create() - print(id) + print(int(id)) """)) id2 = int(out.strip()) @@ -271,7 +328,7 @@ def f(): out = _run_output(id1, dedent(""" import _xxsubinterpreters as _interpreters id = _interpreters.create() - print(id) + print(int(id)) """)) id2 = int(out.strip()) @@ -365,7 +422,7 @@ def test_from_current(self): script = dedent(f""" import _xxsubinterpreters as _interpreters try: - _interpreters.destroy({id}) + _interpreters.destroy({int(id)}) except RuntimeError: pass """) @@ -377,10 +434,10 @@ def test_from_sibling(self): main, = interpreters.list_all() id1 = interpreters.create() id2 = interpreters.create() - script = dedent(""" + script = dedent(f""" import _xxsubinterpreters as _interpreters - _interpreters.destroy({}) - """).format(id2) + _interpreters.destroy({int(id2)}) + """) interpreters.run_string(id1, script) self.assertEqual(set(interpreters.list_all()), {main, id1}) @@ -699,11 +756,14 @@ def test_execution_namespace_is_main(self): '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 diff --git a/Modules/_xxsubinterpretersmodule.c b/Modules/_xxsubinterpretersmodule.c index 7829b4cd9511..d7588079f225 100644 --- a/Modules/_xxsubinterpretersmodule.c +++ b/Modules/_xxsubinterpretersmodule.c @@ -1653,27 +1653,6 @@ interp_exceptions_init(PyObject *ns) return 0; } -static PyInterpreterState * -_look_up(PyObject *requested_id) -{ - long long id = PyLong_AsLongLong(requested_id); - if (id == -1 && PyErr_Occurred() != NULL) { - return NULL; - } - assert(id <= INT64_MAX); - return _PyInterpreterState_LookUpID(id); -} - -static PyObject * -_get_id(PyInterpreterState *interp) -{ - PY_INT64_T id = PyInterpreterState_GetID(interp); - if (id < 0) { - return NULL; - } - return PyLong_FromLongLong(id); -} - static int _is_running(PyInterpreterState *interp) { @@ -1809,6 +1788,265 @@ _run_script_in_interpreter(PyInterpreterState *interp, const char *codestr, 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 ********************************************************/ @@ -1852,7 +2090,16 @@ interp_create(PyObject *self, PyObject *args) PyErr_SetString(PyExc_RuntimeError, "interpreter creation failed"); return NULL; } + if (_PyInterpreterState_IDInitref(tstate->interp) != 0) { + goto error; + }; return _get_id(tstate->interp); + +error: + save_tstate = PyThreadState_Swap(tstate); + Py_EndInterpreter(tstate); + PyThreadState_Swap(save_tstate); + return NULL; } PyDoc_STRVAR(create_doc, @@ -2359,6 +2606,10 @@ PyInit__xxsubinterpreters(void) 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); @@ -2380,6 +2631,10 @@ PyInit__xxsubinterpreters(void) 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; diff --git a/Python/pystate.c b/Python/pystate.c index 8dbda73de701..8cbf1fa10a59 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -125,7 +125,8 @@ PyInterpreterState_New(void) return NULL; } - + interp->id_refcount = -1; + interp->id_mutex = NULL; interp->modules = NULL; interp->modules_by_index = NULL; interp->sysdict = NULL; @@ -247,6 +248,9 @@ PyInterpreterState_Delete(PyInterpreterState *interp) Py_FatalError("PyInterpreterState_Delete: remaining subinterpreters"); } HEAD_UNLOCK(); + if (interp->id_mutex != NULL) { + PyThread_free_lock(interp->id_mutex); + } PyMem_RawFree(interp); } @@ -284,6 +288,58 @@ _PyInterpreterState_LookUpID(PY_INT64_T requested_id) return NULL; } + +int +_PyInterpreterState_IDInitref(PyInterpreterState *interp) +{ + if (interp->id_mutex != NULL) { + return 0; + } + interp->id_mutex = PyThread_allocate_lock(); + if (interp->id_mutex == NULL) { + PyErr_SetString(PyExc_RuntimeError, + "failed to create init interpreter ID mutex"); + return -1; + } + interp->id_refcount = 0; + return 0; +} + + +void +_PyInterpreterState_IDIncref(PyInterpreterState *interp) +{ + if (interp->id_mutex == NULL) { + return; + } + PyThread_acquire_lock(interp->id_mutex, WAIT_LOCK); + interp->id_refcount += 1; + PyThread_release_lock(interp->id_mutex); +} + + +void +_PyInterpreterState_IDDecref(PyInterpreterState *interp) +{ + if (interp->id_mutex == NULL) { + return; + } + PyThread_acquire_lock(interp->id_mutex, WAIT_LOCK); + assert(interp->id_refcount != 0); + interp->id_refcount -= 1; + int64_t refcount = interp->id_refcount; + PyThread_release_lock(interp->id_mutex); + + if (refcount == 0) { + PyThreadState *tstate, *save_tstate; + tstate = PyInterpreterState_ThreadHead(interp); + save_tstate = PyThreadState_Swap(tstate); + Py_EndInterpreter(tstate); + PyThreadState_Swap(save_tstate); + } +} + + /* Default implementation for _PyThreadState_GetFrame */ static struct _frame * threadstate_getframe(PyThreadState *self) From webhook-mailer at python.org Fri Feb 16 21:15:27 2018 From: webhook-mailer at python.org (Eric Snow) Date: Sat, 17 Feb 2018 02:15:27 -0000 Subject: [Python-checkins] bpo-32604: Clean up created subinterpreters before runtime finalization. (gh-5710) Message-ID: https://github.com/python/cpython/commit/3db05a3a9c109f49d54b4965852e41c657e9b117 commit: 3db05a3a9c109f49d54b4965852e41c657e9b117 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Eric Snow date: 2018-02-16T19:15:24-07:00 summary: bpo-32604: Clean up created subinterpreters before runtime finalization. (gh-5710) (cherry picked from commit 4c6955e2b0ccf88c705f8d1fac685a8e65f9699e) Co-authored-by: Eric Snow files: M Include/internal/pystate.h M Include/pystate.h M Lib/test/test__xxsubinterpreters.py M Modules/_xxsubinterpretersmodule.c M Python/pystate.c diff --git a/Include/internal/pystate.h b/Include/internal/pystate.h index 2b60b25c19b1..da642c6fd007 100644 --- a/Include/internal/pystate.h +++ b/Include/internal/pystate.h @@ -69,6 +69,10 @@ PyAPI_FUNC(void) _PyPathConfig_Clear(_PyPathConfig *config); PyAPI_FUNC(PyInterpreterState *) _PyInterpreterState_LookUpID(PY_INT64_T); +PyAPI_FUNC(int) _PyInterpreterState_IDInitref(PyInterpreterState *); +PyAPI_FUNC(void) _PyInterpreterState_IDIncref(PyInterpreterState *); +PyAPI_FUNC(void) _PyInterpreterState_IDDecref(PyInterpreterState *); + /* cross-interpreter data */ diff --git a/Include/pystate.h b/Include/pystate.h index a19c1ed3b81c..29d7148bf9a3 100644 --- a/Include/pystate.h +++ b/Include/pystate.h @@ -8,6 +8,8 @@ extern "C" { #endif +#include "pythread.h" + /* This limitation is for performance and simplicity. If needed it can be removed (with effort). */ #define MAX_CO_EXTRA_USERS 255 @@ -111,6 +113,8 @@ typedef struct _is { struct _ts *tstate_head; int64_t id; + int64_t id_refcount; + PyThread_type_lock id_mutex; PyObject *modules; PyObject *modules_by_index; diff --git a/Lib/test/test__xxsubinterpreters.py b/Lib/test/test__xxsubinterpreters.py index 8d72ca200214..d280270af91b 100644 --- a/Lib/test/test__xxsubinterpreters.py +++ b/Lib/test/test__xxsubinterpreters.py @@ -152,7 +152,7 @@ def test_subinterpreter(self): interp = interpreters.create() out = _run_output(interp, dedent(""" import _xxsubinterpreters as _interpreters - print(_interpreters.get_current()) + print(int(_interpreters.get_current())) """)) cur = int(out.strip()) _, expected = interpreters.list_all() @@ -172,7 +172,7 @@ def test_from_subinterpreter(self): interp = interpreters.create() out = _run_output(interp, dedent(""" import _xxsubinterpreters as _interpreters - print(_interpreters.get_main()) + print(int(_interpreters.get_main())) """)) main = int(out.strip()) self.assertEqual(main, expected) @@ -196,7 +196,7 @@ def test_from_subinterpreter(self): interp = interpreters.create() out = _run_output(interp, dedent(f""" import _xxsubinterpreters as _interpreters - if _interpreters.is_running({interp}): + if _interpreters.is_running({int(interp)}): print(True) else: print(False) @@ -218,6 +218,63 @@ def test_bad_id(self): 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): @@ -256,7 +313,7 @@ def test_in_subinterpreter(self): out = _run_output(id1, dedent(""" import _xxsubinterpreters as _interpreters id = _interpreters.create() - print(id) + print(int(id)) """)) id2 = int(out.strip()) @@ -271,7 +328,7 @@ def f(): out = _run_output(id1, dedent(""" import _xxsubinterpreters as _interpreters id = _interpreters.create() - print(id) + print(int(id)) """)) id2 = int(out.strip()) @@ -365,7 +422,7 @@ def test_from_current(self): script = dedent(f""" import _xxsubinterpreters as _interpreters try: - _interpreters.destroy({id}) + _interpreters.destroy({int(id)}) except RuntimeError: pass """) @@ -377,10 +434,10 @@ def test_from_sibling(self): main, = interpreters.list_all() id1 = interpreters.create() id2 = interpreters.create() - script = dedent(""" + script = dedent(f""" import _xxsubinterpreters as _interpreters - _interpreters.destroy({}) - """).format(id2) + _interpreters.destroy({int(id2)}) + """) interpreters.run_string(id1, script) self.assertEqual(set(interpreters.list_all()), {main, id1}) @@ -699,11 +756,14 @@ def test_execution_namespace_is_main(self): '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 diff --git a/Modules/_xxsubinterpretersmodule.c b/Modules/_xxsubinterpretersmodule.c index 7829b4cd9511..d7588079f225 100644 --- a/Modules/_xxsubinterpretersmodule.c +++ b/Modules/_xxsubinterpretersmodule.c @@ -1653,27 +1653,6 @@ interp_exceptions_init(PyObject *ns) return 0; } -static PyInterpreterState * -_look_up(PyObject *requested_id) -{ - long long id = PyLong_AsLongLong(requested_id); - if (id == -1 && PyErr_Occurred() != NULL) { - return NULL; - } - assert(id <= INT64_MAX); - return _PyInterpreterState_LookUpID(id); -} - -static PyObject * -_get_id(PyInterpreterState *interp) -{ - PY_INT64_T id = PyInterpreterState_GetID(interp); - if (id < 0) { - return NULL; - } - return PyLong_FromLongLong(id); -} - static int _is_running(PyInterpreterState *interp) { @@ -1809,6 +1788,265 @@ _run_script_in_interpreter(PyInterpreterState *interp, const char *codestr, 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 ********************************************************/ @@ -1852,7 +2090,16 @@ interp_create(PyObject *self, PyObject *args) PyErr_SetString(PyExc_RuntimeError, "interpreter creation failed"); return NULL; } + if (_PyInterpreterState_IDInitref(tstate->interp) != 0) { + goto error; + }; return _get_id(tstate->interp); + +error: + save_tstate = PyThreadState_Swap(tstate); + Py_EndInterpreter(tstate); + PyThreadState_Swap(save_tstate); + return NULL; } PyDoc_STRVAR(create_doc, @@ -2359,6 +2606,10 @@ PyInit__xxsubinterpreters(void) 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); @@ -2380,6 +2631,10 @@ PyInit__xxsubinterpreters(void) 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; diff --git a/Python/pystate.c b/Python/pystate.c index 8dbda73de701..8cbf1fa10a59 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -125,7 +125,8 @@ PyInterpreterState_New(void) return NULL; } - + interp->id_refcount = -1; + interp->id_mutex = NULL; interp->modules = NULL; interp->modules_by_index = NULL; interp->sysdict = NULL; @@ -247,6 +248,9 @@ PyInterpreterState_Delete(PyInterpreterState *interp) Py_FatalError("PyInterpreterState_Delete: remaining subinterpreters"); } HEAD_UNLOCK(); + if (interp->id_mutex != NULL) { + PyThread_free_lock(interp->id_mutex); + } PyMem_RawFree(interp); } @@ -284,6 +288,58 @@ _PyInterpreterState_LookUpID(PY_INT64_T requested_id) return NULL; } + +int +_PyInterpreterState_IDInitref(PyInterpreterState *interp) +{ + if (interp->id_mutex != NULL) { + return 0; + } + interp->id_mutex = PyThread_allocate_lock(); + if (interp->id_mutex == NULL) { + PyErr_SetString(PyExc_RuntimeError, + "failed to create init interpreter ID mutex"); + return -1; + } + interp->id_refcount = 0; + return 0; +} + + +void +_PyInterpreterState_IDIncref(PyInterpreterState *interp) +{ + if (interp->id_mutex == NULL) { + return; + } + PyThread_acquire_lock(interp->id_mutex, WAIT_LOCK); + interp->id_refcount += 1; + PyThread_release_lock(interp->id_mutex); +} + + +void +_PyInterpreterState_IDDecref(PyInterpreterState *interp) +{ + if (interp->id_mutex == NULL) { + return; + } + PyThread_acquire_lock(interp->id_mutex, WAIT_LOCK); + assert(interp->id_refcount != 0); + interp->id_refcount -= 1; + int64_t refcount = interp->id_refcount; + PyThread_release_lock(interp->id_mutex); + + if (refcount == 0) { + PyThreadState *tstate, *save_tstate; + tstate = PyInterpreterState_ThreadHead(interp); + save_tstate = PyThreadState_Swap(tstate); + Py_EndInterpreter(tstate); + PyThreadState_Swap(save_tstate); + } +} + + /* Default implementation for _PyThreadState_GetFrame */ static struct _frame * threadstate_getframe(PyThreadState *self) From webhook-mailer at python.org Fri Feb 16 22:39:55 2018 From: webhook-mailer at python.org (Mariatta) Date: Sat, 17 Feb 2018 03:39:55 -0000 Subject: [Python-checkins] bpo-32860: Fix a missing asterisk in the documentation for glob.iglob() (GH-5712) Message-ID: https://github.com/python/cpython/commit/6887d86e9a04b9c5718b08e5d9e1ca3cc1f53721 commit: 6887d86e9a04b9c5718b08e5d9e1ca3cc1f53721 branch: master author: Zackery Spytz committer: Mariatta date: 2018-02-16T19:39:51-08:00 summary: bpo-32860: Fix a missing asterisk in the documentation for glob.iglob() (GH-5712) files: M Doc/library/glob.rst diff --git a/Doc/library/glob.rst b/Doc/library/glob.rst index a8a5a500cbcf..25bd4b7f9a87 100644 --- a/Doc/library/glob.rst +++ b/Doc/library/glob.rst @@ -48,7 +48,7 @@ For example, ``'[?]'`` matches the character ``'?'``. Support for recursive globs using "``**``". -.. function:: iglob(pathname, recursive=False) +.. function:: iglob(pathname, *, recursive=False) Return an :term:`iterator` which yields the same values as :func:`glob` without actually storing them all simultaneously. From webhook-mailer at python.org Fri Feb 16 22:49:02 2018 From: webhook-mailer at python.org (Mariatta) Date: Sat, 17 Feb 2018 03:49:02 -0000 Subject: [Python-checkins] DOC: fix documentation for copyright and credits (GH-5706) Message-ID: https://github.com/python/cpython/commit/243d6d71265be1996a8326002deae429106a5fba commit: 243d6d71265be1996a8326002deae429106a5fba branch: master author: Gerrit Holl committer: Mariatta date: 2018-02-16T19:48:57-08:00 summary: DOC: fix documentation for copyright and credits (GH-5706) Adapt documentation for `copyright` and `credits` to reality. Previously, the documentation implied that all each of `copyright`, `credits`, and `license`, would print a message to call the object in order to see the full text. In reality, only `license` exhibits this behaviour, and `copyright` and `credit` print their full text either when printed, displayed, or called. files: M Doc/library/constants.rst diff --git a/Doc/library/constants.rst b/Doc/library/constants.rst index 469a3eed606f..78f161963698 100644 --- a/Doc/library/constants.rst +++ b/Doc/library/constants.rst @@ -86,10 +86,14 @@ should not be used in programs. specified exit code. .. data:: copyright - license credits - Objects that when printed, print a message like "Type license() to see the - full license text", and when called, display the corresponding text in a + Objects that when printed or called, print the text of copyright or + credits, respectively. + +.. data:: license + + Object that when printed, prints the message "Type license() to see the + full license text", and when called, displays the full license text in a pager-like fashion (one screen at a time). From webhook-mailer at python.org Fri Feb 16 22:51:12 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 17 Feb 2018 03:51:12 -0000 Subject: [Python-checkins] bpo-32860: Fix a missing asterisk in the documentation for glob.iglob() (GH-5712) Message-ID: https://github.com/python/cpython/commit/0f764110593b337161e9321671dc13b54ca0cf95 commit: 0f764110593b337161e9321671dc13b54ca0cf95 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-16T19:51:09-08:00 summary: bpo-32860: Fix a missing asterisk in the documentation for glob.iglob() (GH-5712) (cherry picked from commit 6887d86e9a04b9c5718b08e5d9e1ca3cc1f53721) Co-authored-by: Zackery Spytz files: M Doc/library/glob.rst diff --git a/Doc/library/glob.rst b/Doc/library/glob.rst index a8a5a500cbcf..25bd4b7f9a87 100644 --- a/Doc/library/glob.rst +++ b/Doc/library/glob.rst @@ -48,7 +48,7 @@ For example, ``'[?]'`` matches the character ``'?'``. Support for recursive globs using "``**``". -.. function:: iglob(pathname, recursive=False) +.. function:: iglob(pathname, *, recursive=False) Return an :term:`iterator` which yields the same values as :func:`glob` without actually storing them all simultaneously. From webhook-mailer at python.org Fri Feb 16 22:58:14 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 17 Feb 2018 03:58:14 -0000 Subject: [Python-checkins] bpo-32860: Fix a missing asterisk in the documentation for glob.iglob() (GH-5712) Message-ID: https://github.com/python/cpython/commit/76591bc03a26e8fde143c25cb88a98f1c96f8bc2 commit: 76591bc03a26e8fde143c25cb88a98f1c96f8bc2 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-16T19:58:11-08:00 summary: bpo-32860: Fix a missing asterisk in the documentation for glob.iglob() (GH-5712) (cherry picked from commit 6887d86e9a04b9c5718b08e5d9e1ca3cc1f53721) Co-authored-by: Zackery Spytz files: M Doc/library/glob.rst diff --git a/Doc/library/glob.rst b/Doc/library/glob.rst index a8a5a500cbcf..25bd4b7f9a87 100644 --- a/Doc/library/glob.rst +++ b/Doc/library/glob.rst @@ -48,7 +48,7 @@ For example, ``'[?]'`` matches the character ``'?'``. Support for recursive globs using "``**``". -.. function:: iglob(pathname, recursive=False) +.. function:: iglob(pathname, *, recursive=False) Return an :term:`iterator` which yields the same values as :func:`glob` without actually storing them all simultaneously. From webhook-mailer at python.org Fri Feb 16 23:09:23 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 17 Feb 2018 04:09:23 -0000 Subject: [Python-checkins] DOC: fix documentation for copyright and credits (GH-5706) Message-ID: https://github.com/python/cpython/commit/025544a855ef3f3f7f21c1b6e4f19b47dcd30933 commit: 025544a855ef3f3f7f21c1b6e4f19b47dcd30933 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-16T20:09:20-08:00 summary: DOC: fix documentation for copyright and credits (GH-5706) Adapt documentation for `copyright` and `credits` to reality. Previously, the documentation implied that all each of `copyright`, `credits`, and `license`, would print a message to call the object in order to see the full text. In reality, only `license` exhibits this behaviour, and `copyright` and `credit` print their full text either when printed, displayed, or called. (cherry picked from commit 243d6d71265be1996a8326002deae429106a5fba) Co-authored-by: Gerrit Holl files: M Doc/library/constants.rst diff --git a/Doc/library/constants.rst b/Doc/library/constants.rst index 469a3eed606f..78f161963698 100644 --- a/Doc/library/constants.rst +++ b/Doc/library/constants.rst @@ -86,10 +86,14 @@ should not be used in programs. specified exit code. .. data:: copyright - license credits - Objects that when printed, print a message like "Type license() to see the - full license text", and when called, display the corresponding text in a + Objects that when printed or called, print the text of copyright or + credits, respectively. + +.. data:: license + + Object that when printed, prints the message "Type license() to see the + full license text", and when called, displays the full license text in a pager-like fashion (one screen at a time). From webhook-mailer at python.org Fri Feb 16 23:16:55 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 17 Feb 2018 04:16:55 -0000 Subject: [Python-checkins] DOC: fix documentation for copyright and credits (GH-5706) Message-ID: https://github.com/python/cpython/commit/f2d2e6169eb31e1a223d29d5de07e80939939106 commit: f2d2e6169eb31e1a223d29d5de07e80939939106 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-16T20:16:52-08:00 summary: DOC: fix documentation for copyright and credits (GH-5706) Adapt documentation for `copyright` and `credits` to reality. Previously, the documentation implied that all each of `copyright`, `credits`, and `license`, would print a message to call the object in order to see the full text. In reality, only `license` exhibits this behaviour, and `copyright` and `credit` print their full text either when printed, displayed, or called. (cherry picked from commit 243d6d71265be1996a8326002deae429106a5fba) Co-authored-by: Gerrit Holl files: M Doc/library/constants.rst diff --git a/Doc/library/constants.rst b/Doc/library/constants.rst index 469a3eed606f..78f161963698 100644 --- a/Doc/library/constants.rst +++ b/Doc/library/constants.rst @@ -86,10 +86,14 @@ should not be used in programs. specified exit code. .. data:: copyright - license credits - Objects that when printed, print a message like "Type license() to see the - full license text", and when called, display the corresponding text in a + Objects that when printed or called, print the text of copyright or + credits, respectively. + +.. data:: license + + Object that when printed, prints the message "Type license() to see the + full license text", and when called, displays the full license text in a pager-like fashion (one screen at a time). From webhook-mailer at python.org Sat Feb 17 01:32:42 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sat, 17 Feb 2018 06:32:42 -0000 Subject: [Python-checkins] bpo-32852: Fix trace changing sys.argv to tuple. (GH-5692) Message-ID: https://github.com/python/cpython/commit/9f4223261fd129ad7b9a09b2b0d625d1bb90b22b commit: 9f4223261fd129ad7b9a09b2b0d625d1bb90b22b branch: master author: Kyle Altendorf committer: Serhiy Storchaka date: 2018-02-17T08:32:37+02:00 summary: bpo-32852: Fix trace changing sys.argv to tuple. (GH-5692) files: A Misc/NEWS.d/next/Library/2018-02-15-12-04-29.bpo-32852.HDqIxM.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 1d87aea5a3d3..e04ca01c4299 100644 --- a/Lib/test/test_trace.py +++ b/Lib/test/test_trace.py @@ -387,5 +387,15 @@ def test_listfuncs_flag_success(self): status, stdout, stderr = assert_python_ok('-m', 'trace', '-l', TESTFN) self.assertIn(b'functions called:', stdout) + def test_sys_argv_list(self): + with open(TESTFN, 'w') as fd: + self.addCleanup(unlink, TESTFN) + fd.write("import sys\n") + fd.write("print(type(sys.argv))\n") + + status, direct_stdout, stderr = assert_python_ok(TESTFN) + status, trace_stdout, stderr = assert_python_ok('-m', 'trace', '-l', TESTFN) + self.assertIn(direct_stdout.strip(), trace_stdout) + if __name__ == '__main__': unittest.main() diff --git a/Lib/trace.py b/Lib/trace.py index 48a1d1b6a914..ade76166bdd2 100755 --- a/Lib/trace.py +++ b/Lib/trace.py @@ -705,7 +705,7 @@ def parse_ignore_dir(s): if opts.filename is None: parser.error('filename is missing: required with the main options') - sys.argv = opts.filename, *opts.arguments + sys.argv = [opts.filename, *opts.arguments] sys.path[0] = os.path.dirname(opts.filename) t = Trace(opts.count, opts.trace, countfuncs=opts.listfuncs, diff --git a/Misc/NEWS.d/next/Library/2018-02-15-12-04-29.bpo-32852.HDqIxM.rst b/Misc/NEWS.d/next/Library/2018-02-15-12-04-29.bpo-32852.HDqIxM.rst new file mode 100644 index 000000000000..8eabbfaea222 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-15-12-04-29.bpo-32852.HDqIxM.rst @@ -0,0 +1 @@ +Make sure sys.argv remains as a list when running trace. From webhook-mailer at python.org Sat Feb 17 01:53:28 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 17 Feb 2018 06:53:28 -0000 Subject: [Python-checkins] bpo-32852: Fix trace changing sys.argv to tuple. (GH-5692) Message-ID: https://github.com/python/cpython/commit/afb5e5583694798793d44f35f901aa912ece278a commit: afb5e5583694798793d44f35f901aa912ece278a branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-16T22:53:24-08:00 summary: bpo-32852: Fix trace changing sys.argv to tuple. (GH-5692) (cherry picked from commit 9f4223261fd129ad7b9a09b2b0d625d1bb90b22b) Co-authored-by: Kyle Altendorf files: A Misc/NEWS.d/next/Library/2018-02-15-12-04-29.bpo-32852.HDqIxM.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 1d87aea5a3d3..e04ca01c4299 100644 --- a/Lib/test/test_trace.py +++ b/Lib/test/test_trace.py @@ -387,5 +387,15 @@ def test_listfuncs_flag_success(self): status, stdout, stderr = assert_python_ok('-m', 'trace', '-l', TESTFN) self.assertIn(b'functions called:', stdout) + def test_sys_argv_list(self): + with open(TESTFN, 'w') as fd: + self.addCleanup(unlink, TESTFN) + fd.write("import sys\n") + fd.write("print(type(sys.argv))\n") + + status, direct_stdout, stderr = assert_python_ok(TESTFN) + status, trace_stdout, stderr = assert_python_ok('-m', 'trace', '-l', TESTFN) + self.assertIn(direct_stdout.strip(), trace_stdout) + if __name__ == '__main__': unittest.main() diff --git a/Lib/trace.py b/Lib/trace.py index 48a1d1b6a914..ade76166bdd2 100755 --- a/Lib/trace.py +++ b/Lib/trace.py @@ -705,7 +705,7 @@ def parse_ignore_dir(s): if opts.filename is None: parser.error('filename is missing: required with the main options') - sys.argv = opts.filename, *opts.arguments + sys.argv = [opts.filename, *opts.arguments] sys.path[0] = os.path.dirname(opts.filename) t = Trace(opts.count, opts.trace, countfuncs=opts.listfuncs, diff --git a/Misc/NEWS.d/next/Library/2018-02-15-12-04-29.bpo-32852.HDqIxM.rst b/Misc/NEWS.d/next/Library/2018-02-15-12-04-29.bpo-32852.HDqIxM.rst new file mode 100644 index 000000000000..8eabbfaea222 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-15-12-04-29.bpo-32852.HDqIxM.rst @@ -0,0 +1 @@ +Make sure sys.argv remains as a list when running trace. From webhook-mailer at python.org Sat Feb 17 02:14:44 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 17 Feb 2018 07:14:44 -0000 Subject: [Python-checkins] bpo-32852: Fix trace changing sys.argv to tuple. (GH-5692) Message-ID: https://github.com/python/cpython/commit/dda938683c48197ab7e775144136f433a5d43103 commit: dda938683c48197ab7e775144136f433a5d43103 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-16T23:14:41-08:00 summary: bpo-32852: Fix trace changing sys.argv to tuple. (GH-5692) (cherry picked from commit 9f4223261fd129ad7b9a09b2b0d625d1bb90b22b) Co-authored-by: Kyle Altendorf files: A Misc/NEWS.d/next/Library/2018-02-15-12-04-29.bpo-32852.HDqIxM.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 1d87aea5a3d3..e04ca01c4299 100644 --- a/Lib/test/test_trace.py +++ b/Lib/test/test_trace.py @@ -387,5 +387,15 @@ def test_listfuncs_flag_success(self): status, stdout, stderr = assert_python_ok('-m', 'trace', '-l', TESTFN) self.assertIn(b'functions called:', stdout) + def test_sys_argv_list(self): + with open(TESTFN, 'w') as fd: + self.addCleanup(unlink, TESTFN) + fd.write("import sys\n") + fd.write("print(type(sys.argv))\n") + + status, direct_stdout, stderr = assert_python_ok(TESTFN) + status, trace_stdout, stderr = assert_python_ok('-m', 'trace', '-l', TESTFN) + self.assertIn(direct_stdout.strip(), trace_stdout) + if __name__ == '__main__': unittest.main() diff --git a/Lib/trace.py b/Lib/trace.py index ae154615fa3a..9ba9486bd024 100755 --- a/Lib/trace.py +++ b/Lib/trace.py @@ -710,7 +710,7 @@ def parse_ignore_dir(s): if opts.filename is None: parser.error('filename is missing: required with the main options') - sys.argv = opts.filename, *opts.arguments + sys.argv = [opts.filename, *opts.arguments] sys.path[0] = os.path.dirname(opts.filename) t = Trace(opts.count, opts.trace, countfuncs=opts.listfuncs, diff --git a/Misc/NEWS.d/next/Library/2018-02-15-12-04-29.bpo-32852.HDqIxM.rst b/Misc/NEWS.d/next/Library/2018-02-15-12-04-29.bpo-32852.HDqIxM.rst new file mode 100644 index 000000000000..8eabbfaea222 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-15-12-04-29.bpo-32852.HDqIxM.rst @@ -0,0 +1 @@ +Make sure sys.argv remains as a list when running trace. From solipsis at pitrou.net Sat Feb 17 04:14:21 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 17 Feb 2018 09:14:21 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=72 Message-ID: <20180217091421.1.9F957FFE06ED8B9B@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_functools leaked [0, 3, 1] memory blocks, sum=4 test_multiprocessing_fork leaked [0, 0, 44] references, sum=44 test_multiprocessing_fork leaked [1, 0, 21] memory blocks, sum=22 test_multiprocessing_fork leaked [0, 0, 2] file descriptors, sum=2 test_multiprocessing_forkserver leaked [2, -1, -1] memory blocks, sum=0 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogTI8OZW', '--timeout', '7200'] From webhook-mailer at python.org Sat Feb 17 12:44:39 2018 From: webhook-mailer at python.org (Andrew Svetlov) Date: Sat, 17 Feb 2018 17:44:39 -0000 Subject: [Python-checkins] Fix a typo in asyncio docs (#5721) Message-ID: https://github.com/python/cpython/commit/17ab8f0e8e2b2f66d11fbb95aa9936544a5e1a9a commit: 17ab8f0e8e2b2f66d11fbb95aa9936544a5e1a9a branch: master author: Andrew Svetlov committer: GitHub date: 2018-02-17T19:44:35+02:00 summary: Fix a typo in asyncio docs (#5721) files: M Doc/library/asyncio-eventloop.rst diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index a19c670d0f30..3ee9939192c1 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -1043,7 +1043,7 @@ Server async def main(host, port): srv = await asyncio.start_server( client_connected, host, port) - await loop.serve_forever() + await srv.serve_forever() asyncio.run(main('127.0.0.1', 0)) From webhook-mailer at python.org Sat Feb 17 13:02:49 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 17 Feb 2018 18:02:49 -0000 Subject: [Python-checkins] Fix a typo in asyncio docs (GH-5721) Message-ID: https://github.com/python/cpython/commit/aeb5d73b0d29a8c14732dc796425ab53114bd0c3 commit: aeb5d73b0d29a8c14732dc796425ab53114bd0c3 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-17T10:02:46-08:00 summary: Fix a typo in asyncio docs (GH-5721) (cherry picked from commit 17ab8f0e8e2b2f66d11fbb95aa9936544a5e1a9a) Co-authored-by: Andrew Svetlov files: M Doc/library/asyncio-eventloop.rst diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index a19c670d0f30..3ee9939192c1 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -1043,7 +1043,7 @@ Server async def main(host, port): srv = await asyncio.start_server( client_connected, host, port) - await loop.serve_forever() + await srv.serve_forever() asyncio.run(main('127.0.0.1', 0)) From webhook-mailer at python.org Sat Feb 17 18:59:01 2018 From: webhook-mailer at python.org (Zachary Ware) Date: Sat, 17 Feb 2018 23:59:01 -0000 Subject: [Python-checkins] bpo-30638: Add clinic to `make regen-all` (GH-5671) Message-ID: https://github.com/python/cpython/commit/d6ff8a7037903497eff95fa32bdac2b6adf71505 commit: d6ff8a7037903497eff95fa32bdac2b6adf71505 branch: master author: Zachary Ware committer: GitHub date: 2018-02-17T17:58:57-06:00 summary: bpo-30638: Add clinic to `make regen-all` (GH-5671) Also, use PYTHON_FOR_REGEN for clinic and blake2s_impl.c rather than PYTHON_FOR_BUILD, and update .travis.yml to make use of the change. files: M .travis.yml M Makefile.pre.in diff --git a/.travis.yml b/.travis.yml index dd0688717c08..665b266146ae 100644 --- a/.travis.yml +++ b/.travis.yml @@ -111,8 +111,7 @@ before_script: fi openssl version ./configure --with-pydebug - make -j4 - make -j4 regen-all clinic + make -j4 regen-all changes=`git status --porcelain` if ! test -z "$changes" then @@ -120,6 +119,7 @@ before_script: echo "$changes" exit 1 fi + make -j4 make pythoninfo script: diff --git a/Makefile.pre.in b/Makefile.pre.in index f58b71537887..916f03091a00 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -560,10 +560,9 @@ coverage-report: regen-grammar regen-importlib $(MAKE) coverage-lcov # Run "Argument Clinic" over all source files -# (depends on python having already been built) .PHONY=clinic -clinic: check-clean-src $(BUILDPYTHON) $(srcdir)/Modules/_blake2/blake2s_impl.c - $(RUNSHARED) $(PYTHON_FOR_BUILD) $(srcdir)/Tools/clinic/clinic.py --make --srcdir $(srcdir) +clinic: check-clean-src $(srcdir)/Modules/_blake2/blake2s_impl.c + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/clinic/clinic.py --make --srcdir $(srcdir) # Build the interpreter $(BUILDPYTHON): Programs/python.o $(LIBRARY) $(LDLIBRARY) $(PY3LIBRARY) @@ -593,9 +592,9 @@ Modules/_math.o: Modules/_math.c Modules/_math.h $(CC) -c $(CCSHARED) $(PY_CORE_CFLAGS) -o $@ $< # blake2s is auto-generated from blake2b -$(srcdir)/Modules/_blake2/blake2s_impl.c: $(BUILDPYTHON) $(srcdir)/Modules/_blake2/blake2b_impl.c $(srcdir)/Modules/_blake2/blake2b2s.py - $(RUNSHARED) $(PYTHON_FOR_BUILD) $(srcdir)/Modules/_blake2/blake2b2s.py - $(RUNSHARED) $(PYTHON_FOR_BUILD) $(srcdir)/Tools/clinic/clinic.py -f $@ +$(srcdir)/Modules/_blake2/blake2s_impl.c: $(srcdir)/Modules/_blake2/blake2b_impl.c $(srcdir)/Modules/_blake2/blake2b2s.py + $(PYTHON_FOR_REGEN) $(srcdir)/Modules/_blake2/blake2b2s.py + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/clinic/clinic.py -f $@ # Build the shared modules # Under GNU make, MAKEFLAGS are sorted and normalized; the 's' for @@ -733,7 +732,8 @@ regen-importlib: Programs/_freeze_importlib ############################################################################ # Regenerate all generated files -regen-all: regen-opcode regen-opcode-targets regen-typeslots regen-grammar regen-ast regen-importlib +regen-all: regen-opcode regen-opcode-targets regen-typeslots regen-grammar \ + regen-ast regen-importlib clinic ############################################################################ # Special rules for object files From webhook-mailer at python.org Sat Feb 17 19:24:02 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sun, 18 Feb 2018 00:24:02 -0000 Subject: [Python-checkins] bpo-30638: Add clinic to `make regen-all` (GH-5671) Message-ID: https://github.com/python/cpython/commit/d5be8e13b0ccf4473300d3a1672fc113702cf66c commit: d5be8e13b0ccf4473300d3a1672fc113702cf66c branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-17T16:23:59-08:00 summary: bpo-30638: Add clinic to `make regen-all` (GH-5671) Also, use PYTHON_FOR_REGEN for clinic and blake2s_impl.c rather than PYTHON_FOR_BUILD, and update .travis.yml to make use of the change. (cherry picked from commit d6ff8a7037903497eff95fa32bdac2b6adf71505) Co-authored-by: Zachary Ware files: M .travis.yml M Makefile.pre.in diff --git a/.travis.yml b/.travis.yml index dd0688717c08..665b266146ae 100644 --- a/.travis.yml +++ b/.travis.yml @@ -111,8 +111,7 @@ before_script: fi openssl version ./configure --with-pydebug - make -j4 - make -j4 regen-all clinic + make -j4 regen-all changes=`git status --porcelain` if ! test -z "$changes" then @@ -120,6 +119,7 @@ before_script: echo "$changes" exit 1 fi + make -j4 make pythoninfo script: diff --git a/Makefile.pre.in b/Makefile.pre.in index f58b71537887..916f03091a00 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -560,10 +560,9 @@ coverage-report: regen-grammar regen-importlib $(MAKE) coverage-lcov # Run "Argument Clinic" over all source files -# (depends on python having already been built) .PHONY=clinic -clinic: check-clean-src $(BUILDPYTHON) $(srcdir)/Modules/_blake2/blake2s_impl.c - $(RUNSHARED) $(PYTHON_FOR_BUILD) $(srcdir)/Tools/clinic/clinic.py --make --srcdir $(srcdir) +clinic: check-clean-src $(srcdir)/Modules/_blake2/blake2s_impl.c + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/clinic/clinic.py --make --srcdir $(srcdir) # Build the interpreter $(BUILDPYTHON): Programs/python.o $(LIBRARY) $(LDLIBRARY) $(PY3LIBRARY) @@ -593,9 +592,9 @@ Modules/_math.o: Modules/_math.c Modules/_math.h $(CC) -c $(CCSHARED) $(PY_CORE_CFLAGS) -o $@ $< # blake2s is auto-generated from blake2b -$(srcdir)/Modules/_blake2/blake2s_impl.c: $(BUILDPYTHON) $(srcdir)/Modules/_blake2/blake2b_impl.c $(srcdir)/Modules/_blake2/blake2b2s.py - $(RUNSHARED) $(PYTHON_FOR_BUILD) $(srcdir)/Modules/_blake2/blake2b2s.py - $(RUNSHARED) $(PYTHON_FOR_BUILD) $(srcdir)/Tools/clinic/clinic.py -f $@ +$(srcdir)/Modules/_blake2/blake2s_impl.c: $(srcdir)/Modules/_blake2/blake2b_impl.c $(srcdir)/Modules/_blake2/blake2b2s.py + $(PYTHON_FOR_REGEN) $(srcdir)/Modules/_blake2/blake2b2s.py + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/clinic/clinic.py -f $@ # Build the shared modules # Under GNU make, MAKEFLAGS are sorted and normalized; the 's' for @@ -733,7 +732,8 @@ regen-importlib: Programs/_freeze_importlib ############################################################################ # Regenerate all generated files -regen-all: regen-opcode regen-opcode-targets regen-typeslots regen-grammar regen-ast regen-importlib +regen-all: regen-opcode regen-opcode-targets regen-typeslots regen-grammar \ + regen-ast regen-importlib clinic ############################################################################ # Special rules for object files From webhook-mailer at python.org Sat Feb 17 20:27:25 2018 From: webhook-mailer at python.org (Zachary Ware) Date: Sun, 18 Feb 2018 01:27:25 -0000 Subject: [Python-checkins] [3.6] bpo-30638: Add clinic to `make regen-all` (GH-5671) Message-ID: https://github.com/python/cpython/commit/c1b8aedfbabf6e5460b09f4792d80f18051d43d3 commit: c1b8aedfbabf6e5460b09f4792d80f18051d43d3 branch: 3.6 author: Zachary Ware committer: GitHub date: 2018-02-17T19:27:22-06:00 summary: [3.6] bpo-30638: Add clinic to `make regen-all` (GH-5671) Also, use PYTHON_FOR_REGEN for clinic and blake2s_impl.c rather than PYTHON_FOR_BUILD, and update .travis.yml to make use of the change. (cherry picked from commit d6ff8a7037903497eff95fa32bdac2b6adf71505) files: M .travis.yml M Makefile.pre.in diff --git a/.travis.yml b/.travis.yml index 222d6f80be4a..2bed28103522 100644 --- a/.travis.yml +++ b/.travis.yml @@ -87,8 +87,7 @@ before_script: fi # Build in debug mode ./configure --with-pydebug PYTHON_FOR_REGEN=python3 - make -j4 - make -j4 regen-all clinic + make -j4 regen-all changes=`git status --porcelain` if ! test -z "$changes" then @@ -96,6 +95,7 @@ before_script: echo "$changes" exit 1 fi + make -j4 make pythoninfo script: diff --git a/Makefile.pre.in b/Makefile.pre.in index 5e88e3f6aa1e..1c9ffea6eed4 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -538,10 +538,9 @@ coverage-report: regen-grammar regen-importlib $(MAKE) coverage-lcov # Run "Argument Clinic" over all source files -# (depends on python having already been built) .PHONY=clinic -clinic: check-clean-src $(BUILDPYTHON) $(srcdir)/Modules/_blake2/blake2s_impl.c - $(RUNSHARED) $(PYTHON_FOR_BUILD) ./Tools/clinic/clinic.py --make +clinic: check-clean-src $(srcdir)/Modules/_blake2/blake2s_impl.c + $(PYTHON_FOR_REGEN) ./Tools/clinic/clinic.py --make # Build the interpreter $(BUILDPYTHON): Programs/python.o $(LIBRARY) $(LDLIBRARY) $(PY3LIBRARY) @@ -571,9 +570,9 @@ Modules/_math.o: Modules/_math.c Modules/_math.h $(CC) -c $(CCSHARED) $(PY_CORE_CFLAGS) -o $@ $< # blake2s is auto-generated from blake2b -$(srcdir)/Modules/_blake2/blake2s_impl.c: $(BUILDPYTHON) $(srcdir)/Modules/_blake2/blake2b_impl.c $(srcdir)/Modules/_blake2/blake2b2s.py - $(RUNSHARED) $(PYTHON_FOR_BUILD) $(srcdir)/Modules/_blake2/blake2b2s.py - $(RUNSHARED) $(PYTHON_FOR_BUILD) $(srcdir)/Tools/clinic/clinic.py -f $@ +$(srcdir)/Modules/_blake2/blake2s_impl.c: $(srcdir)/Modules/_blake2/blake2b_impl.c $(srcdir)/Modules/_blake2/blake2b2s.py + $(PYTHON_FOR_REGEN) $(srcdir)/Modules/_blake2/blake2b2s.py + $(PYTHON_FOR_REGEN) $(srcdir)/Tools/clinic/clinic.py -f $@ # Build the shared modules # Under GNU make, MAKEFLAGS are sorted and normalized; the 's' for @@ -720,7 +719,8 @@ regen-importlib: Programs/_freeze_importlib ############################################################################ # Regenerate all generated files -regen-all: regen-opcode regen-opcode-targets regen-typeslots regen-grammar regen-ast regen-importlib +regen-all: regen-opcode regen-opcode-targets regen-typeslots regen-grammar \ + regen-ast regen-importlib clinic ############################################################################ # Special rules for object files From webhook-mailer at python.org Sat Feb 17 21:59:06 2018 From: webhook-mailer at python.org (Steve Dower) Date: Sun, 18 Feb 2018 02:59:06 -0000 Subject: [Python-checkins] Improves the ability to build in CI (GH-5728) Message-ID: https://github.com/python/cpython/commit/01423cb53b5662b363d2f1a5963eadfe951ef3e8 commit: 01423cb53b5662b363d2f1a5963eadfe951ef3e8 branch: master author: Steve Dower committer: GitHub date: 2018-02-17T18:59:03-08:00 summary: Improves the ability to build in CI (GH-5728) files: M Lib/test/support/script_helper.py M Lib/test/test_cmd_line.py M PCbuild/find_python.bat M PCbuild/get_externals.bat M PCbuild/python.props diff --git a/Lib/test/support/script_helper.py b/Lib/test/support/script_helper.py index b3ac848f0825..5a81697708fd 100644 --- a/Lib/test/support/script_helper.py +++ b/Lib/test/support/script_helper.py @@ -36,6 +36,11 @@ def interpreter_requires_environment(): """ global __cached_interp_requires_environment if __cached_interp_requires_environment is None: + # If PYTHONHOME is set, assume that we need it + if 'PYTHONHOME' in os.environ: + __cached_interp_requires_environment = True + return True + # Try running an interpreter with -E to see if it works or not. try: subprocess.check_call([sys.executable, '-E', @@ -166,7 +171,9 @@ def spawn_python(*args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, **kw): kw is extra keyword args to pass to subprocess.Popen. Returns a Popen object. """ - cmd_line = [sys.executable, '-E'] + cmd_line = [sys.executable] + if not interpreter_requires_environment(): + cmd_line.append('-E') cmd_line.extend(args) # Under Fedora (?), GNU readline can output junk on stderr when initialized, # depending on the TERM setting. Setting TERM=vt100 is supposed to disable diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py index a6b663403f4f..fe89e3c0ee34 100644 --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -63,6 +63,8 @@ def test_verbose(self): rc, out, err = assert_python_ok('-vv') self.assertNotIn(b'stack overflow', err) + @unittest.skipIf(interpreter_requires_environment(), + 'Cannot run -E tests when PYTHON env vars are required.') def test_xoptions(self): def get_xoptions(*args): # use subprocess module directly because test.support.script_helper adds @@ -278,11 +280,7 @@ def test_empty_PYTHONPATH_issue16309(self): def test_displayhook_unencodable(self): for encoding in ('ascii', 'latin-1', 'utf-8'): - # We are testing a PYTHON environment variable here, so we can't - # use -E, -I, or script_helper (which uses them). So instead we do - # poor-man's isolation by deleting the PYTHON vars from env. - env = {key:value for (key,value) in os.environ.copy().items() - if not key.startswith('PYTHON')} + env = os.environ.copy() env['PYTHONIOENCODING'] = encoding p = subprocess.Popen( [sys.executable, '-i'], @@ -704,6 +702,8 @@ def test_pythondevmode_env(self): self.assertEqual(proc.returncode, 0, proc) + at unittest.skipIf(interpreter_requires_environment(), + 'Cannot run -I tests when PYTHON env vars are required.') class IgnoreEnvironmentTest(unittest.TestCase): def run_ignoring_vars(self, predicate, **env_vars): diff --git a/PCbuild/find_python.bat b/PCbuild/find_python.bat index ba3a0f5a10da..17ce7ac609c1 100644 --- a/PCbuild/find_python.bat +++ b/PCbuild/find_python.bat @@ -31,10 +31,10 @@ @if exist "%_Py_EXTERNALS_DIR%\pythonx86\tools\python.exe" (set PYTHON="%_Py_EXTERNALS_DIR%\pythonx86\tools\python.exe") & (set _Py_Python_Source=found in externals directory) & goto :found @rem If HOST_PYTHON is recent enough, use that - at if NOT "%HOST_PYTHON%"=="" @%HOST_PYTHON% -c "import sys; assert sys.version_info[:2] >= (3, 6)" >nul 2>nul && (set PYTHON="%HOST_PYTHON%") && (set _Py_Python_Source=found as HOST_PYTHON) && goto :found + at if NOT "%HOST_PYTHON%"=="" @%HOST_PYTHON% -Ec "import sys; assert sys.version_info[:2] >= (3, 6)" >nul 2>nul && (set PYTHON="%HOST_PYTHON%") && (set _Py_Python_Source=found as HOST_PYTHON) && goto :found @rem If py.exe finds a recent enough version, use that one - at py -3.6 -V >nul 2>&1 && (set PYTHON=py -3.6) && (set _Py_Python_Source=found with py.exe) && goto :found + at py -3.6 -EV >nul 2>&1 && (set PYTHON=py -3.6) && (set _Py_Python_Source=found with py.exe) && goto :found @if NOT exist "%_Py_EXTERNALS_DIR%" mkdir "%_Py_EXTERNALS_DIR%" @set _Py_NUGET=%NUGET% @@ -50,7 +50,7 @@ @rem If it fails, retry with any available copy of Python @powershell.exe -Command Invoke-WebRequest %_Py_NUGET_URL% -OutFile '%_Py_NUGET%' @if errorlevel 1 ( - @%_Py_HOST_PYTHON% "%~dp0\urlretrieve.py" "%_Py_NUGET_URL%" "%_Py_NUGET%" + @%_Py_HOST_PYTHON% -E "%~dp0\urlretrieve.py" "%_Py_NUGET_URL%" "%_Py_NUGET%" ) ) @echo Installing Python via nuget... diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat index ed9ff759a370..e696f22d579a 100644 --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -65,7 +65,7 @@ for %%e in (%libraries%) do ( git clone --depth 1 https://github.com/%ORG%/cpython-source-deps --branch %%e "%EXTERNALS_DIR%\%%e" ) else ( echo.Fetching %%e... - %PYTHON% "%PCBUILD%\get_external.py" -O %ORG% %%e + %PYTHON% -E "%PCBUILD%get_external.py" -O %ORG% -e "%EXTERNALS_DIR%" %%e ) ) @@ -84,7 +84,7 @@ for %%b in (%binaries%) do ( git clone --depth 1 https://github.com/%ORG%/cpython-bin-deps --branch %%b "%EXTERNALS_DIR%\%%b" ) else ( echo.Fetching %%b... - %PYTHON% "%PCBUILD%\get_external.py" -b -O %ORG% %%b + %PYTHON% -E "%PCBUILD%get_external.py" -b -O %ORG% -e "%EXTERNALS_DIR%" %%b ) ) diff --git a/PCbuild/python.props b/PCbuild/python.props index 39b7b8a6b6f3..f9433133a87b 100644 --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -43,7 +43,9 @@ $(BuildPath)instrumented\ - $([System.IO.Path]::GetFullPath(`$(PySourcePath)externals\`)) + $(EXTERNALS_DIR) + $([System.IO.Path]::GetFullPath(`$(PySourcePath)externals`)) + $(ExternalsDir)\ $(ExternalsDir)sqlite-3.21.0.0\ $(ExternalsDir)bzip2-1.0.6\ $(ExternalsDir)xz-5.2.2\ From webhook-mailer at python.org Sat Feb 17 22:31:40 2018 From: webhook-mailer at python.org (Steve Dower) Date: Sun, 18 Feb 2018 03:31:40 -0000 Subject: [Python-checkins] [3.7] Improves the ability to build in CI (GH-5729) Message-ID: https://github.com/python/cpython/commit/fa9a502a387a26ba116840d35ae4a30f672e78ad commit: fa9a502a387a26ba116840d35ae4a30f672e78ad branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Steve Dower date: 2018-02-17T19:31:37-08:00 summary: [3.7] Improves the ability to build in CI (GH-5729) files: M Lib/test/support/script_helper.py M Lib/test/test_cmd_line.py M PCbuild/find_python.bat M PCbuild/get_externals.bat M PCbuild/python.props diff --git a/Lib/test/support/script_helper.py b/Lib/test/support/script_helper.py index b3ac848f0825..5a81697708fd 100644 --- a/Lib/test/support/script_helper.py +++ b/Lib/test/support/script_helper.py @@ -36,6 +36,11 @@ def interpreter_requires_environment(): """ global __cached_interp_requires_environment if __cached_interp_requires_environment is None: + # If PYTHONHOME is set, assume that we need it + if 'PYTHONHOME' in os.environ: + __cached_interp_requires_environment = True + return True + # Try running an interpreter with -E to see if it works or not. try: subprocess.check_call([sys.executable, '-E', @@ -166,7 +171,9 @@ def spawn_python(*args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, **kw): kw is extra keyword args to pass to subprocess.Popen. Returns a Popen object. """ - cmd_line = [sys.executable, '-E'] + cmd_line = [sys.executable] + if not interpreter_requires_environment(): + cmd_line.append('-E') cmd_line.extend(args) # Under Fedora (?), GNU readline can output junk on stderr when initialized, # depending on the TERM setting. Setting TERM=vt100 is supposed to disable diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py index a6b663403f4f..fe89e3c0ee34 100644 --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -63,6 +63,8 @@ def test_verbose(self): rc, out, err = assert_python_ok('-vv') self.assertNotIn(b'stack overflow', err) + @unittest.skipIf(interpreter_requires_environment(), + 'Cannot run -E tests when PYTHON env vars are required.') def test_xoptions(self): def get_xoptions(*args): # use subprocess module directly because test.support.script_helper adds @@ -278,11 +280,7 @@ def test_empty_PYTHONPATH_issue16309(self): def test_displayhook_unencodable(self): for encoding in ('ascii', 'latin-1', 'utf-8'): - # We are testing a PYTHON environment variable here, so we can't - # use -E, -I, or script_helper (which uses them). So instead we do - # poor-man's isolation by deleting the PYTHON vars from env. - env = {key:value for (key,value) in os.environ.copy().items() - if not key.startswith('PYTHON')} + env = os.environ.copy() env['PYTHONIOENCODING'] = encoding p = subprocess.Popen( [sys.executable, '-i'], @@ -704,6 +702,8 @@ def test_pythondevmode_env(self): self.assertEqual(proc.returncode, 0, proc) + at unittest.skipIf(interpreter_requires_environment(), + 'Cannot run -I tests when PYTHON env vars are required.') class IgnoreEnvironmentTest(unittest.TestCase): def run_ignoring_vars(self, predicate, **env_vars): diff --git a/PCbuild/find_python.bat b/PCbuild/find_python.bat index ba3a0f5a10da..17ce7ac609c1 100644 --- a/PCbuild/find_python.bat +++ b/PCbuild/find_python.bat @@ -31,10 +31,10 @@ @if exist "%_Py_EXTERNALS_DIR%\pythonx86\tools\python.exe" (set PYTHON="%_Py_EXTERNALS_DIR%\pythonx86\tools\python.exe") & (set _Py_Python_Source=found in externals directory) & goto :found @rem If HOST_PYTHON is recent enough, use that - at if NOT "%HOST_PYTHON%"=="" @%HOST_PYTHON% -c "import sys; assert sys.version_info[:2] >= (3, 6)" >nul 2>nul && (set PYTHON="%HOST_PYTHON%") && (set _Py_Python_Source=found as HOST_PYTHON) && goto :found + at if NOT "%HOST_PYTHON%"=="" @%HOST_PYTHON% -Ec "import sys; assert sys.version_info[:2] >= (3, 6)" >nul 2>nul && (set PYTHON="%HOST_PYTHON%") && (set _Py_Python_Source=found as HOST_PYTHON) && goto :found @rem If py.exe finds a recent enough version, use that one - at py -3.6 -V >nul 2>&1 && (set PYTHON=py -3.6) && (set _Py_Python_Source=found with py.exe) && goto :found + at py -3.6 -EV >nul 2>&1 && (set PYTHON=py -3.6) && (set _Py_Python_Source=found with py.exe) && goto :found @if NOT exist "%_Py_EXTERNALS_DIR%" mkdir "%_Py_EXTERNALS_DIR%" @set _Py_NUGET=%NUGET% @@ -50,7 +50,7 @@ @rem If it fails, retry with any available copy of Python @powershell.exe -Command Invoke-WebRequest %_Py_NUGET_URL% -OutFile '%_Py_NUGET%' @if errorlevel 1 ( - @%_Py_HOST_PYTHON% "%~dp0\urlretrieve.py" "%_Py_NUGET_URL%" "%_Py_NUGET%" + @%_Py_HOST_PYTHON% -E "%~dp0\urlretrieve.py" "%_Py_NUGET_URL%" "%_Py_NUGET%" ) ) @echo Installing Python via nuget... diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat index ed9ff759a370..d2af042d4aae 100644 --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -65,7 +65,7 @@ for %%e in (%libraries%) do ( git clone --depth 1 https://github.com/%ORG%/cpython-source-deps --branch %%e "%EXTERNALS_DIR%\%%e" ) else ( echo.Fetching %%e... - %PYTHON% "%PCBUILD%\get_external.py" -O %ORG% %%e + %PYTHON% -E "%PCBUILD%\get_external.py" -O %ORG% -e "%EXTERNALS_DIR%" %%e ) ) @@ -84,7 +84,7 @@ for %%b in (%binaries%) do ( git clone --depth 1 https://github.com/%ORG%/cpython-bin-deps --branch %%b "%EXTERNALS_DIR%\%%b" ) else ( echo.Fetching %%b... - %PYTHON% "%PCBUILD%\get_external.py" -b -O %ORG% %%b + %PYTHON% -E "%PCBUILD%\get_external.py" -b -O %ORG% -e "%EXTERNALS_DIR%" %%b ) ) diff --git a/PCbuild/python.props b/PCbuild/python.props index 39b7b8a6b6f3..f9433133a87b 100644 --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -43,7 +43,9 @@ $(BuildPath)instrumented\ - $([System.IO.Path]::GetFullPath(`$(PySourcePath)externals\`)) + $(EXTERNALS_DIR) + $([System.IO.Path]::GetFullPath(`$(PySourcePath)externals`)) + $(ExternalsDir)\ $(ExternalsDir)sqlite-3.21.0.0\ $(ExternalsDir)bzip2-1.0.6\ $(ExternalsDir)xz-5.2.2\ From webhook-mailer at python.org Sat Feb 17 22:59:00 2018 From: webhook-mailer at python.org (Steve Dower) Date: Sun, 18 Feb 2018 03:59:00 -0000 Subject: [Python-checkins] Add missing backslashes to get_externals.bat (GH-5731) Message-ID: https://github.com/python/cpython/commit/667b91a5e210e20946ad41f1796c544a1becf1b6 commit: 667b91a5e210e20946ad41f1796c544a1becf1b6 branch: master author: Steve Dower committer: GitHub date: 2018-02-17T19:58:57-08:00 summary: Add missing backslashes to get_externals.bat (GH-5731) files: M PCbuild/get_externals.bat diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat index e696f22d579a..d2af042d4aae 100644 --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -65,7 +65,7 @@ for %%e in (%libraries%) do ( git clone --depth 1 https://github.com/%ORG%/cpython-source-deps --branch %%e "%EXTERNALS_DIR%\%%e" ) else ( echo.Fetching %%e... - %PYTHON% -E "%PCBUILD%get_external.py" -O %ORG% -e "%EXTERNALS_DIR%" %%e + %PYTHON% -E "%PCBUILD%\get_external.py" -O %ORG% -e "%EXTERNALS_DIR%" %%e ) ) @@ -84,7 +84,7 @@ for %%b in (%binaries%) do ( git clone --depth 1 https://github.com/%ORG%/cpython-bin-deps --branch %%b "%EXTERNALS_DIR%\%%b" ) else ( echo.Fetching %%b... - %PYTHON% -E "%PCBUILD%get_external.py" -b -O %ORG% -e "%EXTERNALS_DIR%" %%b + %PYTHON% -E "%PCBUILD%\get_external.py" -b -O %ORG% -e "%EXTERNALS_DIR%" %%b ) ) From webhook-mailer at python.org Sat Feb 17 23:35:06 2018 From: webhook-mailer at python.org (Steve Dower) Date: Sun, 18 Feb 2018 04:35:06 -0000 Subject: [Python-checkins] [3.6] Improves the ability to build in CI (GH-5730) Message-ID: https://github.com/python/cpython/commit/17ca4e193ea25f13a5f0309a0713a6b5bedaf3e4 commit: 17ca4e193ea25f13a5f0309a0713a6b5bedaf3e4 branch: 3.6 author: Steve Dower committer: GitHub date: 2018-02-17T20:35:03-08:00 summary: [3.6] Improves the ability to build in CI (GH-5730) files: M Lib/test/support/script_helper.py M Lib/test/test_cmd_line.py M PCbuild/find_python.bat M PCbuild/get_externals.bat M PCbuild/python.props diff --git a/Lib/test/support/script_helper.py b/Lib/test/support/script_helper.py index ca5f9c20dd03..507dc48848a5 100644 --- a/Lib/test/support/script_helper.py +++ b/Lib/test/support/script_helper.py @@ -39,6 +39,11 @@ def interpreter_requires_environment(): """ global __cached_interp_requires_environment if __cached_interp_requires_environment is None: + # If PYTHONHOME is set, assume that we need it + if 'PYTHONHOME' in os.environ: + __cached_interp_requires_environment = True + return True + # Try running an interpreter with -E to see if it works or not. try: subprocess.check_call([sys.executable, '-E', @@ -165,7 +170,9 @@ def spawn_python(*args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, **kw): kw is extra keyword args to pass to subprocess.Popen. Returns a Popen object. """ - cmd_line = [sys.executable, '-E'] + cmd_line = [sys.executable] + if not interpreter_requires_environment(): + cmd_line.append('-E') cmd_line.extend(args) # Under Fedora (?), GNU readline can output junk on stderr when initialized, # depending on the TERM setting. Setting TERM=vt100 is supposed to disable diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py index 98441b0f4a5d..32d2df9d6c26 100644 --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -10,7 +10,7 @@ import tempfile from test.support import script_helper, is_android from test.support.script_helper import (spawn_python, kill_python, assert_python_ok, - assert_python_failure) + assert_python_failure, interpreter_requires_environment) # XXX (ncoghlan): Move to script_helper and make consistent with run_python @@ -57,6 +57,8 @@ def test_verbose(self): rc, out, err = assert_python_ok('-vv') self.assertNotIn(b'stack overflow', err) + @unittest.skipIf(interpreter_requires_environment(), + 'Cannot run -E tests when PYTHON env vars are required.') def test_xoptions(self): def get_xoptions(*args): # use subprocess module directly because test.support.script_helper adds @@ -272,11 +274,7 @@ def test_empty_PYTHONPATH_issue16309(self): def test_displayhook_unencodable(self): for encoding in ('ascii', 'latin-1', 'utf-8'): - # We are testing a PYTHON environment variable here, so we can't - # use -E, -I, or script_helper (which uses them). So instead we do - # poor-man's isolation by deleting the PYTHON vars from env. - env = {key:value for (key,value) in os.environ.copy().items() - if not key.startswith('PYTHON')} + env = os.environ.copy() env['PYTHONIOENCODING'] = encoding p = subprocess.Popen( [sys.executable, '-i'], @@ -491,6 +489,7 @@ def test_isolatedmode(self): cwd=tmpdir) self.assertEqual(out.strip(), b"ok") + def test_main(): test.support.run_unittest(CmdLineTest) test.support.reap_children() diff --git a/PCbuild/find_python.bat b/PCbuild/find_python.bat index ba3a0f5a10da..17ce7ac609c1 100644 --- a/PCbuild/find_python.bat +++ b/PCbuild/find_python.bat @@ -31,10 +31,10 @@ @if exist "%_Py_EXTERNALS_DIR%\pythonx86\tools\python.exe" (set PYTHON="%_Py_EXTERNALS_DIR%\pythonx86\tools\python.exe") & (set _Py_Python_Source=found in externals directory) & goto :found @rem If HOST_PYTHON is recent enough, use that - at if NOT "%HOST_PYTHON%"=="" @%HOST_PYTHON% -c "import sys; assert sys.version_info[:2] >= (3, 6)" >nul 2>nul && (set PYTHON="%HOST_PYTHON%") && (set _Py_Python_Source=found as HOST_PYTHON) && goto :found + at if NOT "%HOST_PYTHON%"=="" @%HOST_PYTHON% -Ec "import sys; assert sys.version_info[:2] >= (3, 6)" >nul 2>nul && (set PYTHON="%HOST_PYTHON%") && (set _Py_Python_Source=found as HOST_PYTHON) && goto :found @rem If py.exe finds a recent enough version, use that one - at py -3.6 -V >nul 2>&1 && (set PYTHON=py -3.6) && (set _Py_Python_Source=found with py.exe) && goto :found + at py -3.6 -EV >nul 2>&1 && (set PYTHON=py -3.6) && (set _Py_Python_Source=found with py.exe) && goto :found @if NOT exist "%_Py_EXTERNALS_DIR%" mkdir "%_Py_EXTERNALS_DIR%" @set _Py_NUGET=%NUGET% @@ -50,7 +50,7 @@ @rem If it fails, retry with any available copy of Python @powershell.exe -Command Invoke-WebRequest %_Py_NUGET_URL% -OutFile '%_Py_NUGET%' @if errorlevel 1 ( - @%_Py_HOST_PYTHON% "%~dp0\urlretrieve.py" "%_Py_NUGET_URL%" "%_Py_NUGET%" + @%_Py_HOST_PYTHON% -E "%~dp0\urlretrieve.py" "%_Py_NUGET_URL%" "%_Py_NUGET%" ) ) @echo Installing Python via nuget... diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat index 58e6c5de2baa..7c1ed2750a2f 100644 --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -56,7 +56,7 @@ for %%e in (%libraries%) do ( git clone --depth 1 https://github.com/%ORG%/cpython-source-deps --branch %%e "%EXTERNALS_DIR%\%%e" ) else ( echo.Fetching %%e... - %PYTHON% "%PCBUILD%\get_external.py" -O %ORG% %%e + %PYTHON% -E "%PCBUILD%\get_external.py" -O %ORG% -e "%EXTERNALS_DIR%" %%e ) ) @@ -74,7 +74,7 @@ for %%b in (%binaries%) do ( git clone --depth 1 https://github.com/%ORG%/cpython-bin-deps --branch %%b "%EXTERNALS_DIR%\%%b" ) else ( echo.Fetching %%b... - %PYTHON% "%PCBUILD%\get_external.py" -b -O %ORG% %%b + %PYTHON% -E "%PCBUILD%\get_external.py" -b -O %ORG% -e "%EXTERNALS_DIR%" %%b ) ) diff --git a/PCbuild/python.props b/PCbuild/python.props index 16a7672315f2..6589a23c7ad7 100644 --- a/PCbuild/python.props +++ b/PCbuild/python.props @@ -43,7 +43,9 @@ $(BuildPath)instrumented\ - $([System.IO.Path]::GetFullPath(`$(PySourcePath)externals\`)) + $(EXTERNALS_DIR) + $([System.IO.Path]::GetFullPath(`$(PySourcePath)externals`)) + $(ExternalsDir)\ $(ExternalsDir)sqlite-3.21.0.0\ $(ExternalsDir)bzip2-1.0.6\ $(ExternalsDir)xz-5.2.2\ From solipsis at pitrou.net Sun Feb 18 04:09:39 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 18 Feb 2018 09:09:39 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=7 Message-ID: <20180218090939.1.C47C0327F763B233@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 [0, 0, 2] memory blocks, sum=2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogL1Z20e', '--timeout', '7200'] From webhook-mailer at python.org Sun Feb 18 07:42:05 2018 From: webhook-mailer at python.org (Ivan Levkivskyi) Date: Sun, 18 Feb 2018 12:42:05 -0000 Subject: [Python-checkins] bpo-31333: Re-implement ABCMeta in C (#5273) Message-ID: https://github.com/python/cpython/commit/03e3c340a0156891a036d6dbdb9e348108826255 commit: 03e3c340a0156891a036d6dbdb9e348108826255 branch: master author: Ivan Levkivskyi committer: GitHub date: 2018-02-18T12:41:58Z summary: bpo-31333: Re-implement ABCMeta in C (#5273) This adds C versions of methods used by ABCMeta that improve performance of various ABC operations. files: A Lib/_py_abc.py A Misc/NEWS.d/next/Library/2018-02-15-08-18-52.bpo-31333.4fF-gM.rst A Modules/_abc.c A Modules/clinic/_abc.c.h M Doc/whatsnew/3.7.rst M Lib/abc.py M Lib/test/libregrtest/refleak.py M Lib/test/test_abc.py M Lib/test/test_typing.py M Modules/Setup.dist M PC/config.c M PCbuild/pythoncore.vcxproj M PCbuild/pythoncore.vcxproj.filters M setup.py diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 7c98c7cfa38d..c35f07c0eabf 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -853,6 +853,12 @@ Optimizations * 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 rewrittent 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`) + Build and C API Changes ======================= diff --git a/Lib/_py_abc.py b/Lib/_py_abc.py new file mode 100644 index 000000000000..6f42ef32fa69 --- /dev/null +++ b/Lib/_py_abc.py @@ -0,0 +1,145 @@ +from _weakrefset import WeakSet + + +def get_cache_token(): + """Returns the current ABC cache token. + + The token is an opaque object (supporting equality testing) identifying the + current version of the ABC cache for virtual subclasses. The token changes + with every call to ``register()`` on any ABC. + """ + return ABCMeta._abc_invalidation_counter + + +class ABCMeta(type): + """Metaclass for defining Abstract Base Classes (ABCs). + + Use this metaclass to create an ABC. An ABC can be subclassed + directly, and then acts as a mix-in class. You can also register + unrelated concrete classes (even built-in classes) and unrelated + ABCs as 'virtual subclasses' -- these and their descendants will + be considered subclasses of the registering ABC by the built-in + issubclass() function, but the registering ABC won't show up in + their MRO (Method Resolution Order) nor will method + implementations defined by the registering ABC be callable (not + even via super()). + """ + + # A global counter that is incremented each time a class is + # registered as a virtual subclass of anything. It forces the + # negative cache to be cleared before its next use. + # Note: this counter is private. Use `abc.get_cache_token()` for + # external code. + _abc_invalidation_counter = 0 + + def __new__(mcls, name, bases, namespace, **kwargs): + cls = super().__new__(mcls, name, bases, namespace, **kwargs) + # Compute set of abstract method names + abstracts = {name + for name, value in namespace.items() + if getattr(value, "__isabstractmethod__", False)} + for base in bases: + for name in getattr(base, "__abstractmethods__", set()): + value = getattr(cls, name, None) + if getattr(value, "__isabstractmethod__", False): + abstracts.add(name) + cls.__abstractmethods__ = frozenset(abstracts) + # Set up inheritance registry + cls._abc_registry = WeakSet() + cls._abc_cache = WeakSet() + cls._abc_negative_cache = WeakSet() + cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter + return cls + + def register(cls, subclass): + """Register a virtual subclass of an ABC. + + Returns the subclass, to allow usage as a class decorator. + """ + if not isinstance(subclass, type): + raise TypeError("Can only register classes") + if issubclass(subclass, cls): + return subclass # Already a subclass + # Subtle: test for cycles *after* testing for "already a subclass"; + # this means we allow X.register(X) and interpret it as a no-op. + if issubclass(cls, subclass): + # This would create a cycle, which is bad for the algorithm below + raise RuntimeError("Refusing to create an inheritance cycle") + cls._abc_registry.add(subclass) + ABCMeta._abc_invalidation_counter += 1 # Invalidate negative cache + return subclass + + def _dump_registry(cls, file=None): + """Debug helper to print the ABC registry.""" + print(f"Class: {cls.__module__}.{cls.__qualname__}", file=file) + print(f"Inv. counter: {get_cache_token()}", file=file) + for name in cls.__dict__: + if name.startswith("_abc_"): + value = getattr(cls, name) + if isinstance(value, WeakSet): + value = set(value) + print(f"{name}: {value!r}", file=file) + + def _abc_registry_clear(cls): + """Clear the registry (for debugging or testing).""" + cls._abc_registry.clear() + + def _abc_caches_clear(cls): + """Clear the caches (for debugging or testing).""" + cls._abc_cache.clear() + cls._abc_negative_cache.clear() + + def __instancecheck__(cls, instance): + """Override for isinstance(instance, cls).""" + # Inline the cache checking + subclass = instance.__class__ + if subclass in cls._abc_cache: + return True + subtype = type(instance) + if subtype is subclass: + if (cls._abc_negative_cache_version == + ABCMeta._abc_invalidation_counter and + subclass in cls._abc_negative_cache): + return False + # Fall back to the subclass check. + return cls.__subclasscheck__(subclass) + return any(cls.__subclasscheck__(c) for c in (subclass, subtype)) + + def __subclasscheck__(cls, subclass): + """Override for issubclass(subclass, cls).""" + # Check cache + if subclass in cls._abc_cache: + return True + # Check negative cache; may have to invalidate + if cls._abc_negative_cache_version < ABCMeta._abc_invalidation_counter: + # Invalidate the negative cache + cls._abc_negative_cache = WeakSet() + cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter + elif subclass in cls._abc_negative_cache: + return False + # Check the subclass hook + ok = cls.__subclasshook__(subclass) + if ok is not NotImplemented: + assert isinstance(ok, bool) + if ok: + cls._abc_cache.add(subclass) + else: + cls._abc_negative_cache.add(subclass) + return ok + # Check if it's a direct subclass + if cls in getattr(subclass, '__mro__', ()): + cls._abc_cache.add(subclass) + return True + # Check if it's a subclass of a registered class (recursive) + for rcls in cls._abc_registry: + if issubclass(subclass, rcls): + cls._abc_cache.add(subclass) + return True + # Check if it's a subclass of a subclass (recursive) + for scls in cls.__subclasses__(): + if issubclass(subclass, scls): + cls._abc_cache.add(subclass) + return True + # No dice; update negative cache + cls._abc_negative_cache.add(subclass) + return False diff --git a/Lib/abc.py b/Lib/abc.py index 9bdc36dce65e..7094141277ae 100644 --- a/Lib/abc.py +++ b/Lib/abc.py @@ -3,8 +3,6 @@ """Abstract Base Classes (ABCs) according to PEP 3119.""" -from _weakrefset import WeakSet - def abstractmethod(funcobj): """A decorator indicating abstract methods. @@ -27,8 +25,7 @@ def my_abstract_method(self, ...): class abstractclassmethod(classmethod): - """ - A decorator indicating abstract classmethods. + """A decorator indicating abstract classmethods. Similar to abstractmethod. @@ -51,8 +48,7 @@ def __init__(self, callable): class abstractstaticmethod(staticmethod): - """ - A decorator indicating abstract staticmethods. + """A decorator indicating abstract staticmethods. Similar to abstractmethod. @@ -75,8 +71,7 @@ def __init__(self, callable): class abstractproperty(property): - """ - A decorator indicating abstract properties. + """A decorator indicating abstract properties. Requires that the metaclass is ABCMeta or derived from it. A class that has a metaclass derived from ABCMeta cannot be @@ -106,131 +101,66 @@ def setx(self, value): ... __isabstractmethod__ = True -class ABCMeta(type): - - """Metaclass for defining Abstract Base Classes (ABCs). - - Use this metaclass to create an ABC. An ABC can be subclassed - directly, and then acts as a mix-in class. You can also register - unrelated concrete classes (even built-in classes) and unrelated - ABCs as 'virtual subclasses' -- these and their descendants will - be considered subclasses of the registering ABC by the built-in - issubclass() function, but the registering ABC won't show up in - their MRO (Method Resolution Order) nor will method - implementations defined by the registering ABC be callable (not - even via super()). - - """ - - # A global counter that is incremented each time a class is - # registered as a virtual subclass of anything. It forces the - # negative cache to be cleared before its next use. - # Note: this counter is private. Use `abc.get_cache_token()` for - # external code. - _abc_invalidation_counter = 0 - - def __new__(mcls, name, bases, namespace, **kwargs): - cls = super().__new__(mcls, name, bases, namespace, **kwargs) - # Compute set of abstract method names - abstracts = {name - for name, value in namespace.items() - if getattr(value, "__isabstractmethod__", False)} - for base in bases: - for name in getattr(base, "__abstractmethods__", set()): - value = getattr(cls, name, None) - if getattr(value, "__isabstractmethod__", False): - abstracts.add(name) - cls.__abstractmethods__ = frozenset(abstracts) - # Set up inheritance registry - cls._abc_registry = WeakSet() - cls._abc_cache = WeakSet() - cls._abc_negative_cache = WeakSet() - cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter - return cls - - def register(cls, subclass): - """Register a virtual subclass of an ABC. - - Returns the subclass, to allow usage as a class decorator. +try: + from _abc import (get_cache_token, _abc_init, _abc_register, + _abc_instancecheck, _abc_subclasscheck, _get_dump, + _reset_registry, _reset_caches) +except ImportError: + from _py_abc import ABCMeta, get_cache_token + ABCMeta.__module__ = 'abc' +else: + class ABCMeta(type): + """Metaclass for defining Abstract Base Classes (ABCs). + + Use this metaclass to create an ABC. An ABC can be subclassed + directly, and then acts as a mix-in class. You can also register + unrelated concrete classes (even built-in classes) and unrelated + ABCs as 'virtual subclasses' -- these and their descendants will + be considered subclasses of the registering ABC by the built-in + issubclass() function, but the registering ABC won't show up in + their MRO (Method Resolution Order) nor will method + implementations defined by the registering ABC be callable (not + even via super()). """ - if not isinstance(subclass, type): - raise TypeError("Can only register classes") - if issubclass(subclass, cls): - return subclass # Already a subclass - # Subtle: test for cycles *after* testing for "already a subclass"; - # this means we allow X.register(X) and interpret it as a no-op. - if issubclass(cls, subclass): - # This would create a cycle, which is bad for the algorithm below - raise RuntimeError("Refusing to create an inheritance cycle") - cls._abc_registry.add(subclass) - ABCMeta._abc_invalidation_counter += 1 # Invalidate negative cache - return subclass - - def _dump_registry(cls, file=None): - """Debug helper to print the ABC registry.""" - print("Class: %s.%s" % (cls.__module__, cls.__qualname__), file=file) - print("Inv.counter: %s" % ABCMeta._abc_invalidation_counter, file=file) - for name in cls.__dict__: - if name.startswith("_abc_"): - value = getattr(cls, name) - if isinstance(value, WeakSet): - value = set(value) - print("%s: %r" % (name, value), file=file) - - def __instancecheck__(cls, instance): - """Override for isinstance(instance, cls).""" - # Inline the cache checking - subclass = instance.__class__ - if subclass in cls._abc_cache: - return True - subtype = type(instance) - if subtype is subclass: - if (cls._abc_negative_cache_version == - ABCMeta._abc_invalidation_counter and - subclass in cls._abc_negative_cache): - return False - # Fall back to the subclass check. - return cls.__subclasscheck__(subclass) - return any(cls.__subclasscheck__(c) for c in {subclass, subtype}) - - def __subclasscheck__(cls, subclass): - """Override for issubclass(subclass, cls).""" - # Check cache - if subclass in cls._abc_cache: - return True - # Check negative cache; may have to invalidate - if cls._abc_negative_cache_version < ABCMeta._abc_invalidation_counter: - # Invalidate the negative cache - cls._abc_negative_cache = WeakSet() - cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter - elif subclass in cls._abc_negative_cache: - return False - # Check the subclass hook - ok = cls.__subclasshook__(subclass) - if ok is not NotImplemented: - assert isinstance(ok, bool) - if ok: - cls._abc_cache.add(subclass) - else: - cls._abc_negative_cache.add(subclass) - return ok - # Check if it's a direct subclass - if cls in getattr(subclass, '__mro__', ()): - cls._abc_cache.add(subclass) - return True - # Check if it's a subclass of a registered class (recursive) - for rcls in cls._abc_registry: - if issubclass(subclass, rcls): - cls._abc_cache.add(subclass) - return True - # Check if it's a subclass of a subclass (recursive) - for scls in cls.__subclasses__(): - if issubclass(subclass, scls): - cls._abc_cache.add(subclass) - return True - # No dice; update negative cache - cls._abc_negative_cache.add(subclass) - return False + def __new__(mcls, name, bases, namespace, **kwargs): + cls = super().__new__(mcls, name, bases, namespace, **kwargs) + _abc_init(cls) + return cls + + def register(cls, subclass): + """Register a virtual subclass of an ABC. + + Returns the subclass, to allow usage as a class decorator. + """ + return _abc_register(cls, subclass) + + def __instancecheck__(cls, instance): + """Override for isinstance(instance, cls).""" + return _abc_instancecheck(cls, instance) + + def __subclasscheck__(cls, subclass): + """Override for issubclass(subclass, cls).""" + return _abc_subclasscheck(cls, subclass) + + def _dump_registry(cls, file=None): + """Debug helper to print the ABC registry.""" + print(f"Class: {cls.__module__}.{cls.__qualname__}", file=file) + print(f"Inv. counter: {get_cache_token()}", file=file) + (_abc_registry, _abc_cache, _abc_negative_cache, + _abc_negative_cache_version) = _get_dump(cls) + print(f"_abc_registry: {_abc_registry!r}", file=file) + print(f"_abc_cache: {_abc_cache!r}", file=file) + print(f"_abc_negative_cache: {_abc_negative_cache!r}", file=file) + print(f"_abc_negative_cache_version: {_abc_negative_cache_version!r}", + file=file) + + def _abc_registry_clear(cls): + """Clear the registry (for debugging or testing).""" + _reset_registry(cls) + + def _abc_caches_clear(cls): + """Clear the caches (for debugging or testing).""" + _reset_caches(cls) class ABC(metaclass=ABCMeta): @@ -238,13 +168,3 @@ class ABC(metaclass=ABCMeta): inheritance. """ __slots__ = () - - -def get_cache_token(): - """Returns the current ABC cache token. - - The token is an opaque object (supporting equality testing) identifying the - current version of the ABC cache for virtual subclasses. The token changes - with every call to ``register()`` on any ABC. - """ - return ABCMeta._abc_invalidation_counter diff --git a/Lib/test/libregrtest/refleak.py b/Lib/test/libregrtest/refleak.py index 2ca9aa87644c..6724488fcfb0 100644 --- a/Lib/test/libregrtest/refleak.py +++ b/Lib/test/libregrtest/refleak.py @@ -5,6 +5,13 @@ import warnings from inspect import isabstract from test import support +try: + from _abc import _get_dump +except ImportError: + def _get_dump(cls): + # For legacy Python version + return (cls._abc_registry, cls._abc_cache, + cls._abc_negative_cache, cls._abc_negative_cache_version) def dash_R(the_module, test, indirect_test, huntrleaks): @@ -36,7 +43,7 @@ def dash_R(the_module, test, indirect_test, huntrleaks): if not isabstract(abc): continue for obj in abc.__subclasses__() + [abc]: - abcs[obj] = obj._abc_registry.copy() + abcs[obj] = _get_dump(obj)[0] # bpo-31217: Integer pool to get a single integer object for the same # value. The pool is used to prevent false alarm when checking for memory @@ -113,7 +120,6 @@ def check_fd_deltas(deltas): def dash_R_cleanup(fs, ps, pic, zdc, abcs): import gc, copyreg import collections.abc - from weakref import WeakSet # Restore some original values. warnings.filters[:] = fs @@ -137,9 +143,10 @@ def dash_R_cleanup(fs, ps, pic, zdc, abcs): abs_classes = filter(isabstract, abs_classes) for abc in abs_classes: for obj in abc.__subclasses__() + [abc]: - obj._abc_registry = abcs.get(obj, WeakSet()).copy() - obj._abc_cache.clear() - obj._abc_negative_cache.clear() + for ref in abcs.get(obj, set()): + if ref() is not None: + obj.register(ref()) + obj._abc_caches_clear() clear_caches() diff --git a/Lib/test/test_abc.py b/Lib/test/test_abc.py index 61c2876708c2..af26c1d6b8c5 100644 --- a/Lib/test/test_abc.py +++ b/Lib/test/test_abc.py @@ -1,422 +1,445 @@ # Copyright 2007 Google, Inc. All Rights Reserved. # Licensed to PSF under a Contributor Agreement. +# Note: each test is run with Python and C versions of ABCMeta. Except for +# test_ABC_helper(), which assures that abc.ABC is an instance of abc.ABCMeta. + """Unit tests for abc.py.""" import unittest import abc +import _py_abc from inspect import isabstract +def test_factory(abc_ABCMeta, abc_get_cache_token): + class TestLegacyAPI(unittest.TestCase): -class TestLegacyAPI(unittest.TestCase): - - def test_abstractproperty_basics(self): - @abc.abstractproperty - def foo(self): pass - self.assertTrue(foo.__isabstractmethod__) - def bar(self): pass - self.assertFalse(hasattr(bar, "__isabstractmethod__")) - - class C(metaclass=abc.ABCMeta): + def test_abstractproperty_basics(self): @abc.abstractproperty - def foo(self): return 3 - self.assertRaises(TypeError, C) - class D(C): - @property - def foo(self): return super().foo - self.assertEqual(D().foo, 3) - self.assertFalse(getattr(D.foo, "__isabstractmethod__", False)) - - def test_abstractclassmethod_basics(self): - @abc.abstractclassmethod - def foo(cls): pass - self.assertTrue(foo.__isabstractmethod__) - @classmethod - def bar(cls): pass - self.assertFalse(getattr(bar, "__isabstractmethod__", False)) - - class C(metaclass=abc.ABCMeta): + def foo(self): pass + self.assertTrue(foo.__isabstractmethod__) + def bar(self): pass + self.assertFalse(hasattr(bar, "__isabstractmethod__")) + + class C(metaclass=abc_ABCMeta): + @abc.abstractproperty + def foo(self): return 3 + self.assertRaises(TypeError, C) + class D(C): + @property + def foo(self): return super().foo + self.assertEqual(D().foo, 3) + self.assertFalse(getattr(D.foo, "__isabstractmethod__", False)) + + def test_abstractclassmethod_basics(self): @abc.abstractclassmethod - def foo(cls): return cls.__name__ - self.assertRaises(TypeError, C) - class D(C): + def foo(cls): pass + self.assertTrue(foo.__isabstractmethod__) @classmethod - def foo(cls): return super().foo() - self.assertEqual(D.foo(), 'D') - self.assertEqual(D().foo(), 'D') - - def test_abstractstaticmethod_basics(self): - @abc.abstractstaticmethod - def foo(): pass - self.assertTrue(foo.__isabstractmethod__) - @staticmethod - def bar(): pass - self.assertFalse(getattr(bar, "__isabstractmethod__", False)) - - class C(metaclass=abc.ABCMeta): + def bar(cls): pass + self.assertFalse(getattr(bar, "__isabstractmethod__", False)) + + class C(metaclass=abc_ABCMeta): + @abc.abstractclassmethod + def foo(cls): return cls.__name__ + self.assertRaises(TypeError, C) + class D(C): + @classmethod + def foo(cls): return super().foo() + self.assertEqual(D.foo(), 'D') + self.assertEqual(D().foo(), 'D') + + def test_abstractstaticmethod_basics(self): @abc.abstractstaticmethod - def foo(): return 3 - self.assertRaises(TypeError, C) - class D(C): + def foo(): pass + self.assertTrue(foo.__isabstractmethod__) @staticmethod - def foo(): return 4 - self.assertEqual(D.foo(), 4) - self.assertEqual(D().foo(), 4) - + def bar(): pass + self.assertFalse(getattr(bar, "__isabstractmethod__", False)) -class TestABC(unittest.TestCase): + class C(metaclass=abc_ABCMeta): + @abc.abstractstaticmethod + def foo(): return 3 + self.assertRaises(TypeError, C) + class D(C): + @staticmethod + def foo(): return 4 + self.assertEqual(D.foo(), 4) + self.assertEqual(D().foo(), 4) + + + class TestABC(unittest.TestCase): + + def test_ABC_helper(self): + # create an ABC using the helper class and perform basic checks + class C(abc.ABC): + @classmethod + @abc.abstractmethod + def foo(cls): return cls.__name__ + self.assertEqual(type(C), abc.ABCMeta) + self.assertRaises(TypeError, C) + class D(C): + @classmethod + def foo(cls): return super().foo() + self.assertEqual(D.foo(), 'D') - def test_ABC_helper(self): - # create an ABC using the helper class and perform basic checks - class C(abc.ABC): - @classmethod + def test_abstractmethod_basics(self): @abc.abstractmethod - def foo(cls): return cls.__name__ - self.assertEqual(type(C), abc.ABCMeta) - self.assertRaises(TypeError, C) - class D(C): - @classmethod - def foo(cls): return super().foo() - self.assertEqual(D.foo(), 'D') - - def test_abstractmethod_basics(self): - @abc.abstractmethod - def foo(self): pass - self.assertTrue(foo.__isabstractmethod__) - def bar(self): pass - self.assertFalse(hasattr(bar, "__isabstractmethod__")) - - def test_abstractproperty_basics(self): - @property - @abc.abstractmethod - def foo(self): pass - self.assertTrue(foo.__isabstractmethod__) - def bar(self): pass - self.assertFalse(getattr(bar, "__isabstractmethod__", False)) - - class C(metaclass=abc.ABCMeta): + def foo(self): pass + self.assertTrue(foo.__isabstractmethod__) + def bar(self): pass + self.assertFalse(hasattr(bar, "__isabstractmethod__")) + + def test_abstractproperty_basics(self): @property @abc.abstractmethod - def foo(self): return 3 - self.assertRaises(TypeError, C) - class D(C): - @C.foo.getter - def foo(self): return super().foo - self.assertEqual(D().foo, 3) - - def test_abstractclassmethod_basics(self): - @classmethod - @abc.abstractmethod - def foo(cls): pass - self.assertTrue(foo.__isabstractmethod__) - @classmethod - def bar(cls): pass - self.assertFalse(getattr(bar, "__isabstractmethod__", False)) - - class C(metaclass=abc.ABCMeta): + def foo(self): pass + self.assertTrue(foo.__isabstractmethod__) + def bar(self): pass + self.assertFalse(getattr(bar, "__isabstractmethod__", False)) + + class C(metaclass=abc_ABCMeta): + @property + @abc.abstractmethod + def foo(self): return 3 + self.assertRaises(TypeError, C) + class D(C): + @C.foo.getter + def foo(self): return super().foo + self.assertEqual(D().foo, 3) + + def test_abstractclassmethod_basics(self): @classmethod @abc.abstractmethod - def foo(cls): return cls.__name__ - self.assertRaises(TypeError, C) - class D(C): + def foo(cls): pass + self.assertTrue(foo.__isabstractmethod__) @classmethod - def foo(cls): return super().foo() - self.assertEqual(D.foo(), 'D') - self.assertEqual(D().foo(), 'D') - - def test_abstractstaticmethod_basics(self): - @staticmethod - @abc.abstractmethod - def foo(): pass - self.assertTrue(foo.__isabstractmethod__) - @staticmethod - def bar(): pass - self.assertFalse(getattr(bar, "__isabstractmethod__", False)) - - class C(metaclass=abc.ABCMeta): + def bar(cls): pass + self.assertFalse(getattr(bar, "__isabstractmethod__", False)) + + class C(metaclass=abc_ABCMeta): + @classmethod + @abc.abstractmethod + def foo(cls): return cls.__name__ + self.assertRaises(TypeError, C) + class D(C): + @classmethod + def foo(cls): return super().foo() + self.assertEqual(D.foo(), 'D') + self.assertEqual(D().foo(), 'D') + + def test_abstractstaticmethod_basics(self): @staticmethod @abc.abstractmethod - def foo(): return 3 - self.assertRaises(TypeError, C) - class D(C): + def foo(): pass + self.assertTrue(foo.__isabstractmethod__) @staticmethod - def foo(): return 4 - self.assertEqual(D.foo(), 4) - self.assertEqual(D().foo(), 4) - - def test_abstractmethod_integration(self): - for abstractthing in [abc.abstractmethod, abc.abstractproperty, - abc.abstractclassmethod, - abc.abstractstaticmethod]: - class C(metaclass=abc.ABCMeta): - @abstractthing - def foo(self): pass # abstract - def bar(self): pass # concrete - self.assertEqual(C.__abstractmethods__, {"foo"}) - self.assertRaises(TypeError, C) # because foo is abstract - self.assertTrue(isabstract(C)) + def bar(): pass + self.assertFalse(getattr(bar, "__isabstractmethod__", False)) + + class C(metaclass=abc_ABCMeta): + @staticmethod + @abc.abstractmethod + def foo(): return 3 + self.assertRaises(TypeError, C) class D(C): - def bar(self): pass # concrete override of concrete - self.assertEqual(D.__abstractmethods__, {"foo"}) - self.assertRaises(TypeError, D) # because foo is still abstract - self.assertTrue(isabstract(D)) + @staticmethod + def foo(): return 4 + self.assertEqual(D.foo(), 4) + self.assertEqual(D().foo(), 4) + + def test_abstractmethod_integration(self): + for abstractthing in [abc.abstractmethod, abc.abstractproperty, + abc.abstractclassmethod, + abc.abstractstaticmethod]: + class C(metaclass=abc_ABCMeta): + @abstractthing + def foo(self): pass # abstract + def bar(self): pass # concrete + self.assertEqual(C.__abstractmethods__, {"foo"}) + self.assertRaises(TypeError, C) # because foo is abstract + self.assertTrue(isabstract(C)) + class D(C): + def bar(self): pass # concrete override of concrete + self.assertEqual(D.__abstractmethods__, {"foo"}) + self.assertRaises(TypeError, D) # because foo is still abstract + self.assertTrue(isabstract(D)) + class E(D): + def foo(self): pass + self.assertEqual(E.__abstractmethods__, set()) + E() # now foo is concrete, too + self.assertFalse(isabstract(E)) + class F(E): + @abstractthing + def bar(self): pass # abstract override of concrete + self.assertEqual(F.__abstractmethods__, {"bar"}) + self.assertRaises(TypeError, F) # because bar is abstract now + self.assertTrue(isabstract(F)) + + def test_descriptors_with_abstractmethod(self): + class C(metaclass=abc_ABCMeta): + @property + @abc.abstractmethod + def foo(self): return 3 + @foo.setter + @abc.abstractmethod + def foo(self, val): pass + self.assertRaises(TypeError, C) + class D(C): + @C.foo.getter + def foo(self): return super().foo + self.assertRaises(TypeError, D) class E(D): - def foo(self): pass - self.assertEqual(E.__abstractmethods__, set()) - E() # now foo is concrete, too - self.assertFalse(isabstract(E)) - class F(E): - @abstractthing - def bar(self): pass # abstract override of concrete - self.assertEqual(F.__abstractmethods__, {"bar"}) - self.assertRaises(TypeError, F) # because bar is abstract now - self.assertTrue(isabstract(F)) - - def test_descriptors_with_abstractmethod(self): - class C(metaclass=abc.ABCMeta): - @property - @abc.abstractmethod - def foo(self): return 3 - @foo.setter - @abc.abstractmethod - def foo(self, val): pass - self.assertRaises(TypeError, C) - class D(C): - @C.foo.getter - def foo(self): return super().foo - self.assertRaises(TypeError, D) - class E(D): - @D.foo.setter - def foo(self, val): pass - self.assertEqual(E().foo, 3) - # check that the property's __isabstractmethod__ descriptor does the - # right thing when presented with a value that fails truth testing: - class NotBool(object): - def __bool__(self): - raise ValueError() - __len__ = __bool__ - with self.assertRaises(ValueError): - class F(C): - def bar(self): + @D.foo.setter + def foo(self, val): pass + self.assertEqual(E().foo, 3) + # check that the property's __isabstractmethod__ descriptor does the + # right thing when presented with a value that fails truth testing: + class NotBool(object): + def __bool__(self): + raise ValueError() + __len__ = __bool__ + with self.assertRaises(ValueError): + class F(C): + def bar(self): + pass + bar.__isabstractmethod__ = NotBool() + foo = property(bar) + + + def test_customdescriptors_with_abstractmethod(self): + class Descriptor: + def __init__(self, fget, fset=None): + self._fget = fget + self._fset = fset + def getter(self, callable): + return Descriptor(callable, self._fget) + def setter(self, callable): + return Descriptor(self._fget, callable) + @property + def __isabstractmethod__(self): + return (getattr(self._fget, '__isabstractmethod__', False) + or getattr(self._fset, '__isabstractmethod__', False)) + class C(metaclass=abc_ABCMeta): + @Descriptor + @abc.abstractmethod + def foo(self): return 3 + @foo.setter + @abc.abstractmethod + def foo(self, val): pass + self.assertRaises(TypeError, C) + class D(C): + @C.foo.getter + def foo(self): return super().foo + self.assertRaises(TypeError, D) + class E(D): + @D.foo.setter + def foo(self, val): pass + self.assertFalse(E.foo.__isabstractmethod__) + + def test_metaclass_abc(self): + # Metaclasses can be ABCs, too. + class A(metaclass=abc_ABCMeta): + @abc.abstractmethod + def x(self): pass - bar.__isabstractmethod__ = NotBool() - foo = property(bar) - - - def test_customdescriptors_with_abstractmethod(self): - class Descriptor: - def __init__(self, fget, fset=None): - self._fget = fget - self._fset = fset - def getter(self, callable): - return Descriptor(callable, self._fget) - def setter(self, callable): - return Descriptor(self._fget, callable) - @property - def __isabstractmethod__(self): - return (getattr(self._fget, '__isabstractmethod__', False) - or getattr(self._fset, '__isabstractmethod__', False)) - class C(metaclass=abc.ABCMeta): - @Descriptor - @abc.abstractmethod - def foo(self): return 3 - @foo.setter - @abc.abstractmethod - def foo(self, val): pass - self.assertRaises(TypeError, C) - class D(C): - @C.foo.getter - def foo(self): return super().foo - self.assertRaises(TypeError, D) - class E(D): - @D.foo.setter - def foo(self, val): pass - self.assertFalse(E.foo.__isabstractmethod__) - - def test_metaclass_abc(self): - # Metaclasses can be ABCs, too. - class A(metaclass=abc.ABCMeta): - @abc.abstractmethod - def x(self): + self.assertEqual(A.__abstractmethods__, {"x"}) + class meta(type, A): + def x(self): + return 1 + class C(metaclass=meta): + pass + + def test_registration_basics(self): + class A(metaclass=abc_ABCMeta): + pass + class B(object): + pass + b = B() + self.assertFalse(issubclass(B, A)) + self.assertFalse(issubclass(B, (A,))) + self.assertNotIsInstance(b, A) + self.assertNotIsInstance(b, (A,)) + B1 = A.register(B) + self.assertTrue(issubclass(B, A)) + self.assertTrue(issubclass(B, (A,))) + self.assertIsInstance(b, A) + self.assertIsInstance(b, (A,)) + self.assertIs(B1, B) + class C(B): + pass + c = C() + self.assertTrue(issubclass(C, A)) + self.assertTrue(issubclass(C, (A,))) + self.assertIsInstance(c, A) + self.assertIsInstance(c, (A,)) + + def test_register_as_class_deco(self): + class A(metaclass=abc_ABCMeta): + pass + @A.register + class B(object): + pass + b = B() + self.assertTrue(issubclass(B, A)) + self.assertTrue(issubclass(B, (A,))) + self.assertIsInstance(b, A) + self.assertIsInstance(b, (A,)) + @A.register + class C(B): + pass + c = C() + self.assertTrue(issubclass(C, A)) + self.assertTrue(issubclass(C, (A,))) + self.assertIsInstance(c, A) + self.assertIsInstance(c, (A,)) + self.assertIs(C, A.register(C)) + + def test_isinstance_invalidation(self): + class A(metaclass=abc_ABCMeta): + pass + class B: + pass + b = B() + self.assertFalse(isinstance(b, A)) + self.assertFalse(isinstance(b, (A,))) + token_old = abc_get_cache_token() + A.register(B) + token_new = abc_get_cache_token() + self.assertNotEqual(token_old, token_new) + self.assertTrue(isinstance(b, A)) + self.assertTrue(isinstance(b, (A,))) + + def test_registration_builtins(self): + class A(metaclass=abc_ABCMeta): + pass + A.register(int) + self.assertIsInstance(42, A) + self.assertIsInstance(42, (A,)) + self.assertTrue(issubclass(int, A)) + self.assertTrue(issubclass(int, (A,))) + class B(A): + pass + B.register(str) + class C(str): pass + self.assertIsInstance("", A) + self.assertIsInstance("", (A,)) + self.assertTrue(issubclass(str, A)) + self.assertTrue(issubclass(str, (A,))) + self.assertTrue(issubclass(C, A)) + self.assertTrue(issubclass(C, (A,))) + + def test_registration_edge_cases(self): + class A(metaclass=abc_ABCMeta): + pass + A.register(A) # should pass silently + class A1(A): + pass + self.assertRaises(RuntimeError, A1.register, A) # cycles not allowed + class B(object): + pass + A1.register(B) # ok + A1.register(B) # should pass silently + class C(A): + pass + A.register(C) # should pass silently + self.assertRaises(RuntimeError, C.register, A) # cycles not allowed + C.register(B) # ok + + def test_register_non_class(self): + class A(metaclass=abc_ABCMeta): + pass + self.assertRaisesRegex(TypeError, "Can only register classes", + A.register, 4) + + def test_registration_transitiveness(self): + class A(metaclass=abc_ABCMeta): + pass + self.assertTrue(issubclass(A, A)) + self.assertTrue(issubclass(A, (A,))) + class B(metaclass=abc_ABCMeta): + pass + self.assertFalse(issubclass(A, B)) + self.assertFalse(issubclass(A, (B,))) + self.assertFalse(issubclass(B, A)) + self.assertFalse(issubclass(B, (A,))) + class C(metaclass=abc_ABCMeta): + pass + A.register(B) + class B1(B): + pass + self.assertTrue(issubclass(B1, A)) + self.assertTrue(issubclass(B1, (A,))) + class C1(C): + pass + B1.register(C1) + self.assertFalse(issubclass(C, B)) + self.assertFalse(issubclass(C, (B,))) + self.assertFalse(issubclass(C, B1)) + self.assertFalse(issubclass(C, (B1,))) + self.assertTrue(issubclass(C1, A)) + self.assertTrue(issubclass(C1, (A,))) + self.assertTrue(issubclass(C1, B)) + self.assertTrue(issubclass(C1, (B,))) + self.assertTrue(issubclass(C1, B1)) + self.assertTrue(issubclass(C1, (B1,))) + C1.register(int) + class MyInt(int): + pass + self.assertTrue(issubclass(MyInt, A)) + self.assertTrue(issubclass(MyInt, (A,))) + self.assertIsInstance(42, A) + self.assertIsInstance(42, (A,)) + + def test_all_new_methods_are_called(self): + class A(metaclass=abc_ABCMeta): + pass + class B(object): + counter = 0 + def __new__(cls): + B.counter += 1 + return super().__new__(cls) + class C(A, B): + pass + self.assertEqual(B.counter, 0) + C() + self.assertEqual(B.counter, 1) + + def test_ABC_has___slots__(self): + self.assertTrue(hasattr(abc.ABC, '__slots__')) + + def test_tricky_new_works(self): + def with_metaclass(meta, *bases): + class metaclass(type): + def __new__(cls, name, this_bases, d): + return meta(name, bases, d) + return type.__new__(metaclass, 'temporary_class', (), {}) + class A: ... + class B: ... + class C(with_metaclass(abc_ABCMeta, A, B)): + pass + self.assertEqual(C.__class__, abc_ABCMeta) + + + class TestABCWithInitSubclass(unittest.TestCase): + def test_works_with_init_subclass(self): + class abc_ABC(metaclass=abc_ABCMeta): + __slots__ = () + saved_kwargs = {} + class ReceivesClassKwargs: + def __init_subclass__(cls, **kwargs): + super().__init_subclass__() + saved_kwargs.update(kwargs) + class Receiver(ReceivesClassKwargs, abc_ABC, x=1, y=2, z=3): pass - self.assertEqual(A.__abstractmethods__, {"x"}) - class meta(type, A): - def x(self): - return 1 - class C(metaclass=meta): - pass - - def test_registration_basics(self): - class A(metaclass=abc.ABCMeta): - pass - class B(object): - pass - b = B() - self.assertFalse(issubclass(B, A)) - self.assertFalse(issubclass(B, (A,))) - self.assertNotIsInstance(b, A) - self.assertNotIsInstance(b, (A,)) - B1 = A.register(B) - self.assertTrue(issubclass(B, A)) - self.assertTrue(issubclass(B, (A,))) - self.assertIsInstance(b, A) - self.assertIsInstance(b, (A,)) - self.assertIs(B1, B) - class C(B): - pass - c = C() - self.assertTrue(issubclass(C, A)) - self.assertTrue(issubclass(C, (A,))) - self.assertIsInstance(c, A) - self.assertIsInstance(c, (A,)) - - def test_register_as_class_deco(self): - class A(metaclass=abc.ABCMeta): - pass - @A.register - class B(object): - pass - b = B() - self.assertTrue(issubclass(B, A)) - self.assertTrue(issubclass(B, (A,))) - self.assertIsInstance(b, A) - self.assertIsInstance(b, (A,)) - @A.register - class C(B): - pass - c = C() - self.assertTrue(issubclass(C, A)) - self.assertTrue(issubclass(C, (A,))) - self.assertIsInstance(c, A) - self.assertIsInstance(c, (A,)) - self.assertIs(C, A.register(C)) - - def test_isinstance_invalidation(self): - class A(metaclass=abc.ABCMeta): - pass - class B: - pass - b = B() - self.assertFalse(isinstance(b, A)) - self.assertFalse(isinstance(b, (A,))) - token_old = abc.get_cache_token() - A.register(B) - token_new = abc.get_cache_token() - self.assertNotEqual(token_old, token_new) - self.assertTrue(isinstance(b, A)) - self.assertTrue(isinstance(b, (A,))) - - def test_registration_builtins(self): - class A(metaclass=abc.ABCMeta): - pass - A.register(int) - self.assertIsInstance(42, A) - self.assertIsInstance(42, (A,)) - self.assertTrue(issubclass(int, A)) - self.assertTrue(issubclass(int, (A,))) - class B(A): - pass - B.register(str) - class C(str): pass - self.assertIsInstance("", A) - self.assertIsInstance("", (A,)) - self.assertTrue(issubclass(str, A)) - self.assertTrue(issubclass(str, (A,))) - self.assertTrue(issubclass(C, A)) - self.assertTrue(issubclass(C, (A,))) - - def test_registration_edge_cases(self): - class A(metaclass=abc.ABCMeta): - pass - A.register(A) # should pass silently - class A1(A): - pass - self.assertRaises(RuntimeError, A1.register, A) # cycles not allowed - class B(object): - pass - A1.register(B) # ok - A1.register(B) # should pass silently - class C(A): - pass - A.register(C) # should pass silently - self.assertRaises(RuntimeError, C.register, A) # cycles not allowed - C.register(B) # ok - - def test_register_non_class(self): - class A(metaclass=abc.ABCMeta): - pass - self.assertRaisesRegex(TypeError, "Can only register classes", - A.register, 4) - - def test_registration_transitiveness(self): - class A(metaclass=abc.ABCMeta): - pass - self.assertTrue(issubclass(A, A)) - self.assertTrue(issubclass(A, (A,))) - class B(metaclass=abc.ABCMeta): - pass - self.assertFalse(issubclass(A, B)) - self.assertFalse(issubclass(A, (B,))) - self.assertFalse(issubclass(B, A)) - self.assertFalse(issubclass(B, (A,))) - class C(metaclass=abc.ABCMeta): - pass - A.register(B) - class B1(B): - pass - self.assertTrue(issubclass(B1, A)) - self.assertTrue(issubclass(B1, (A,))) - class C1(C): - pass - B1.register(C1) - self.assertFalse(issubclass(C, B)) - self.assertFalse(issubclass(C, (B,))) - self.assertFalse(issubclass(C, B1)) - self.assertFalse(issubclass(C, (B1,))) - self.assertTrue(issubclass(C1, A)) - self.assertTrue(issubclass(C1, (A,))) - self.assertTrue(issubclass(C1, B)) - self.assertTrue(issubclass(C1, (B,))) - self.assertTrue(issubclass(C1, B1)) - self.assertTrue(issubclass(C1, (B1,))) - C1.register(int) - class MyInt(int): - pass - self.assertTrue(issubclass(MyInt, A)) - self.assertTrue(issubclass(MyInt, (A,))) - self.assertIsInstance(42, A) - self.assertIsInstance(42, (A,)) - - def test_all_new_methods_are_called(self): - class A(metaclass=abc.ABCMeta): - pass - class B(object): - counter = 0 - def __new__(cls): - B.counter += 1 - return super().__new__(cls) - class C(A, B): - pass - self.assertEqual(B.counter, 0) - C() - self.assertEqual(B.counter, 1) - - def test_ABC_has___slots__(self): - self.assertTrue(hasattr(abc.ABC, '__slots__')) - - -class TestABCWithInitSubclass(unittest.TestCase): - def test_works_with_init_subclass(self): - saved_kwargs = {} - class ReceivesClassKwargs: - def __init_subclass__(cls, **kwargs): - super().__init_subclass__() - saved_kwargs.update(kwargs) - class Receiver(ReceivesClassKwargs, abc.ABC, x=1, y=2, z=3): - pass - self.assertEqual(saved_kwargs, dict(x=1, y=2, z=3)) + self.assertEqual(saved_kwargs, dict(x=1, y=2, z=3)) + return TestLegacyAPI, TestABC, TestABCWithInitSubclass +TestLegacyAPI_Py, TestABC_Py, TestABCWithInitSubclass_Py = test_factory(abc.ABCMeta, + abc.get_cache_token) +TestLegacyAPI_C, TestABC_C, TestABCWithInitSubclass_C = test_factory(_py_abc.ABCMeta, + _py_abc.get_cache_token) if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 3f24faf37629..f56caa13a295 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -761,8 +761,8 @@ class C(collections.abc.Mapping, Generic[T]): ... self.assertIsInstance(1, C) C[int] self.assertIsInstance(1, C) - C._abc_registry.clear() - C._abc_cache.clear() # To keep refleak hunting mode clean + C._abc_registry_clear() + C._abc_caches_clear() # To keep refleak hunting mode clean def test_false_subclasses(self): class MyMapping(MutableMapping[str, str]): pass diff --git a/Misc/NEWS.d/next/Library/2018-02-15-08-18-52.bpo-31333.4fF-gM.rst b/Misc/NEWS.d/next/Library/2018-02-15-08-18-52.bpo-31333.4fF-gM.rst new file mode 100644 index 000000000000..63fc72a5c11b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-15-08-18-52.bpo-31333.4fF-gM.rst @@ -0,0 +1,10 @@ +``_abc`` module is added. It is a speedup module with C implementations for +various functions and methods in ``abc``. Creating an ABC subclass and calling +``isinstance`` or ``issubclass`` with an ABC subclass are up to 1.5x faster. +In addition, this makes Python start-up up to 10% faster. + +Note that the new implementation hides internal registry and caches, previously +accessible via private attributes ``_abc_registry``, ``_abc_cache``, and +``_abc_negative_cache``. There are three debugging helper methods that can be +used instead ``_dump_registry``, ``_abc_registry_clear``, and +``_abc_caches_clear``. diff --git a/Modules/Setup.dist b/Modules/Setup.dist index 4b463b28d672..a833774a1538 100644 --- a/Modules/Setup.dist +++ b/Modules/Setup.dist @@ -114,6 +114,7 @@ _weakref _weakref.c # weak references _functools _functoolsmodule.c # Tools for working with functions and callable objects _operator _operator.c # operator.add() and similar goodies _collections _collectionsmodule.c # Container types +_abc _abc.c # Abstract base classes itertools itertoolsmodule.c # Functions creating iterators for efficient looping atexit atexitmodule.c # Register functions to be run at interpreter-shutdown _signal signalmodule.c diff --git a/Modules/_abc.c b/Modules/_abc.c new file mode 100644 index 000000000000..504e23d9a74d --- /dev/null +++ b/Modules/_abc.c @@ -0,0 +1,822 @@ +/* ABCMeta implementation */ + +#include "Python.h" +#include "structmember.h" +#include "clinic/_abc.c.h" + +/*[clinic input] +module _abc +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=964f5328e1aefcda]*/ + +PyDoc_STRVAR(_abc__doc__, +"Module contains faster C implementation of abc.ABCMeta"); + +_Py_IDENTIFIER(__abstractmethods__); +_Py_IDENTIFIER(__class__); +_Py_IDENTIFIER(__dict__); +_Py_IDENTIFIER(__bases__); +_Py_IDENTIFIER(_abc_impl); +_Py_IDENTIFIER(__subclasscheck__); +_Py_IDENTIFIER(__subclasshook__); + +/* A global counter that is incremented each time a class is + registered as a virtual subclass of anything. It forces the + negative cache to be cleared before its next use. + Note: this counter is private. Use `abc.get_cache_token()` for + external code. */ +static unsigned long long abc_invalidation_counter = 0; + +/* This object stores internal state for ABCs. + Note that we can use normal sets for caches, + since they are never iterated over. */ +typedef struct { + PyObject_HEAD + PyObject *_abc_registry; + PyObject *_abc_cache; /* Normal set of weak references. */ + PyObject *_abc_negative_cache; /* Normal set of weak references. */ + unsigned long long _abc_negative_cache_version; +} _abc_data; + +static void +abc_data_dealloc(_abc_data *self) +{ + Py_XDECREF(self->_abc_registry); + Py_XDECREF(self->_abc_cache); + Py_XDECREF(self->_abc_negative_cache); + Py_TYPE(self)->tp_free(self); +} + +static PyObject * +abc_data_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + _abc_data *self = (_abc_data *) type->tp_alloc(type, 0); + if (self == NULL) { + return NULL; + } + + self->_abc_registry = NULL; + self->_abc_cache = NULL; + self->_abc_negative_cache = NULL; + self->_abc_negative_cache_version = abc_invalidation_counter; + return (PyObject *) self; +} + +PyDoc_STRVAR(abc_data_doc, +"Internal state held by ABC machinery."); + +static PyTypeObject _abc_data_type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "_abc_data", /*tp_name*/ + sizeof(_abc_data), /*tp_size*/ + .tp_dealloc = (destructor)abc_data_dealloc, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_alloc = PyType_GenericAlloc, + .tp_new = abc_data_new, +}; + +static _abc_data * +_get_impl(PyObject *self) +{ + PyObject *impl = _PyObject_GetAttrId(self, &PyId__abc_impl); + if (impl == NULL) { + return NULL; + } + if (Py_TYPE(impl) != &_abc_data_type) { + PyErr_SetString(PyExc_TypeError, "_abc_impl is set to a wrong type"); + Py_DECREF(impl); + return NULL; + } + return (_abc_data *)impl; +} + +static int +_in_weak_set(PyObject *set, PyObject *obj) +{ + if (set == NULL || PySet_GET_SIZE(set) == 0) { + return 0; + } + PyObject *ref = PyWeakref_NewRef(obj, NULL); + if (ref == NULL) { + if (PyErr_ExceptionMatches(PyExc_TypeError)) { + PyErr_Clear(); + return 0; + } + return -1; + } + int res = PySet_Contains(set, ref); + Py_DECREF(ref); + return res; +} + +static PyObject * +_destroy(PyObject *setweakref, PyObject *objweakref) +{ + PyObject *set; + set = PyWeakref_GET_OBJECT(setweakref); + if (set == Py_None) { + Py_RETURN_NONE; + } + Py_INCREF(set); + if (PySet_Discard(set, objweakref) < 0) { + Py_DECREF(set); + return NULL; + } + Py_DECREF(set); + Py_RETURN_NONE; +} + +static PyMethodDef _destroy_def = { + "_destroy", (PyCFunction) _destroy, METH_O +}; + +static int +_add_to_weak_set(PyObject **pset, PyObject *obj) +{ + if (*pset == NULL) { + *pset = PySet_New(NULL); + if (*pset == NULL) { + return -1; + } + } + + PyObject *set = *pset; + PyObject *ref, *wr; + PyObject *destroy_cb; + wr = PyWeakref_NewRef(set, NULL); + if (wr == NULL) { + return -1; + } + destroy_cb = PyCFunction_NewEx(&_destroy_def, wr, NULL); + if (destroy_cb == NULL) { + Py_DECREF(wr); + return -1; + } + ref = PyWeakref_NewRef(obj, destroy_cb); + Py_DECREF(destroy_cb); + if (ref == NULL) { + Py_DECREF(wr); + return -1; + } + int ret = PySet_Add(set, ref); + Py_DECREF(wr); + Py_DECREF(ref); + return ret; +} + +/*[clinic input] +_abc._reset_registry + + self: object + / + +Internal ABC helper to reset registry of a given class. + +Should be only used by refleak.py +[clinic start generated code]*/ + +static PyObject * +_abc__reset_registry(PyObject *module, PyObject *self) +/*[clinic end generated code: output=92d591a43566cc10 input=12a0b7eb339ac35c]*/ +{ + _abc_data *impl = _get_impl(self); + if (impl == NULL) { + return NULL; + } + if (impl->_abc_registry != NULL && PySet_Clear(impl->_abc_registry) < 0) { + Py_DECREF(impl); + return NULL; + } + Py_DECREF(impl); + Py_RETURN_NONE; +} + +/*[clinic input] +_abc._reset_caches + + self: object + / + +Internal ABC helper to reset both caches of a given class. + +Should be only used by refleak.py +[clinic start generated code]*/ + +static PyObject * +_abc__reset_caches(PyObject *module, PyObject *self) +/*[clinic end generated code: output=f296f0d5c513f80c input=c0ac616fd8acfb6f]*/ +{ + _abc_data *impl = _get_impl(self); + if (impl == NULL) { + return NULL; + } + if (impl->_abc_cache != NULL && PySet_Clear(impl->_abc_cache) < 0) { + Py_DECREF(impl); + return NULL; + } + /* also the second cache */ + if (impl->_abc_negative_cache != NULL && + PySet_Clear(impl->_abc_negative_cache) < 0) { + Py_DECREF(impl); + return NULL; + } + Py_DECREF(impl); + Py_RETURN_NONE; +} + +/*[clinic input] +_abc._get_dump + + self: object + / + +Internal ABC helper for cache and registry debugging. + +Return shallow copies of registry, of both caches, and +negative cache version. Don't call this function directly, +instead use ABC._dump_registry() for a nice repr. +[clinic start generated code]*/ + +static PyObject * +_abc__get_dump(PyObject *module, PyObject *self) +/*[clinic end generated code: output=9d9569a8e2c1c443 input=2c5deb1bfe9e3c79]*/ +{ + _abc_data *impl = _get_impl(self); + if (impl == NULL) { + return NULL; + } + PyObject *res = Py_BuildValue("NNNK", + PySet_New(impl->_abc_registry), + PySet_New(impl->_abc_cache), + PySet_New(impl->_abc_negative_cache), + impl->_abc_negative_cache_version); + Py_DECREF(impl); + return res; +} + +// Compute set of abstract method names. +static int +compute_abstract_methods(PyObject *self) +{ + int ret = -1; + PyObject *abstracts = PyFrozenSet_New(NULL); + if (abstracts == NULL) { + return -1; + } + + PyObject *ns = NULL, *items = NULL, *bases = NULL; // Py_XDECREF()ed on error. + + /* Stage 1: direct abstract methods. */ + ns = _PyObject_GetAttrId(self, &PyId___dict__); + if (!ns) { + goto error; + } + + // We can't use PyDict_Next(ns) even when ns is dict because + // _PyObject_IsAbstract() can mutate ns. + items = PyMapping_Items(ns); + if (!items) { + goto error; + } + assert(PyList_Check(items)); + for (Py_ssize_t pos = 0; pos < PyList_GET_SIZE(items); pos++) { + PyObject *it = PySequence_Fast( + PyList_GET_ITEM(items, pos), + "items() returned non-iterable"); + if (!it) { + goto error; + } + if (PySequence_Fast_GET_SIZE(it) != 2) { + PyErr_SetString(PyExc_TypeError, + "items() returned item which size is not 2"); + Py_DECREF(it); + goto error; + } + + // borrowed + PyObject *key = PySequence_Fast_GET_ITEM(it, 0); + PyObject *value = PySequence_Fast_GET_ITEM(it, 1); + // items or it may be cleared while accessing __abstractmethod__ + // So we need to keep strong reference for key + Py_INCREF(key); + int is_abstract = _PyObject_IsAbstract(value); + if (is_abstract < 0 || + (is_abstract && PySet_Add(abstracts, key) < 0)) { + Py_DECREF(it); + Py_DECREF(key); + goto error; + } + Py_DECREF(key); + Py_DECREF(it); + } + + /* Stage 2: inherited abstract methods. */ + bases = _PyObject_GetAttrId(self, &PyId___bases__); + if (!bases) { + goto error; + } + if (!PyTuple_Check(bases)) { + PyErr_SetString(PyExc_TypeError, "__bases__ is not tuple"); + goto error; + } + + for (Py_ssize_t pos = 0; pos < PyTuple_GET_SIZE(bases); pos++) { + PyObject *item = PyTuple_GET_ITEM(bases, pos); // borrowed + PyObject *base_abstracts, *iter; + + if (_PyObject_LookupAttrId(item, &PyId___abstractmethods__, + &base_abstracts) < 0) { + goto error; + } + if (base_abstracts == NULL) { + continue; + } + if (!(iter = PyObject_GetIter(base_abstracts))) { + Py_DECREF(base_abstracts); + goto error; + } + Py_DECREF(base_abstracts); + PyObject *key, *value; + while ((key = PyIter_Next(iter))) { + if (_PyObject_LookupAttr(self, key, &value) < 0) { + Py_DECREF(key); + Py_DECREF(iter); + goto error; + } + if (value == NULL) { + Py_DECREF(key); + continue; + } + + int is_abstract = _PyObject_IsAbstract(value); + Py_DECREF(value); + if (is_abstract < 0 || + (is_abstract && PySet_Add(abstracts, key) < 0)) + { + Py_DECREF(key); + Py_DECREF(iter); + goto error; + } + Py_DECREF(key); + } + Py_DECREF(iter); + if (PyErr_Occurred()) { + goto error; + } + } + + if (_PyObject_SetAttrId(self, &PyId___abstractmethods__, abstracts) < 0) { + goto error; + } + + ret = 0; +error: + Py_DECREF(abstracts); + Py_XDECREF(ns); + Py_XDECREF(items); + Py_XDECREF(bases); + return ret; +} + +/*[clinic input] +_abc._abc_init + + self: object + / + +Internal ABC helper for class set-up. Should be never used outside abc module. +[clinic start generated code]*/ + +static PyObject * +_abc__abc_init(PyObject *module, PyObject *self) +/*[clinic end generated code: output=594757375714cda1 input=8d7fe470ff77f029]*/ +{ + PyObject *data; + if (compute_abstract_methods(self) < 0) { + return NULL; + } + + /* Set up inheritance registry. */ + data = abc_data_new(&_abc_data_type, NULL, NULL); + if (data == NULL) { + return NULL; + } + if (_PyObject_SetAttrId(self, &PyId__abc_impl, data) < 0) { + Py_DECREF(data); + return NULL; + } + Py_DECREF(data); + Py_RETURN_NONE; +} + +/*[clinic input] +_abc._abc_register + + self: object + subclass: object + / + +Internal ABC helper for subclasss registration. Should be never used outside abc module. +[clinic start generated code]*/ + +static PyObject * +_abc__abc_register_impl(PyObject *module, PyObject *self, PyObject *subclass) +/*[clinic end generated code: output=7851e7668c963524 input=ca589f8c3080e67f]*/ +{ + if (!PyType_Check(subclass)) { + PyErr_SetString(PyExc_TypeError, "Can only register classes"); + return NULL; + } + int result = PyObject_IsSubclass(subclass, self); + if (result > 0) { + Py_INCREF(subclass); + return subclass; /* Already a subclass. */ + } + if (result < 0) { + return NULL; + } + /* Subtle: test for cycles *after* testing for "already a subclass"; + this means we allow X.register(X) and interpret it as a no-op. */ + result = PyObject_IsSubclass(self, subclass); + if (result > 0) { + /* This would create a cycle, which is bad for the algorithm below. */ + PyErr_SetString(PyExc_RuntimeError, "Refusing to create an inheritance cycle"); + return NULL; + } + if (result < 0) { + return NULL; + } + _abc_data *impl = _get_impl(self); + if (impl == NULL) { + return NULL; + } + if (_add_to_weak_set(&impl->_abc_registry, subclass) < 0) { + Py_DECREF(impl); + return NULL; + } + Py_DECREF(impl); + + /* Invalidate negative cache */ + abc_invalidation_counter++; + + Py_INCREF(subclass); + return subclass; +} + + +/*[clinic input] +_abc._abc_instancecheck + + self: object + instance: object + / + +Internal ABC helper for instance checks. Should be never used outside abc module. +[clinic start generated code]*/ + +static PyObject * +_abc__abc_instancecheck_impl(PyObject *module, PyObject *self, + PyObject *instance) +/*[clinic end generated code: output=b8b5148f63b6b56f input=a4f4525679261084]*/ +{ + PyObject *subtype, *result = NULL, *subclass = NULL; + _abc_data *impl = _get_impl(self); + if (impl == NULL) { + return NULL; + } + + subclass = _PyObject_GetAttrId(instance, &PyId___class__); + if (subclass == NULL) { + Py_DECREF(impl); + return NULL; + } + /* Inline the cache checking. */ + int incache = _in_weak_set(impl->_abc_cache, subclass); + if (incache < 0) { + goto end; + } + if (incache > 0) { + result = Py_True; + Py_INCREF(result); + goto end; + } + subtype = (PyObject *)Py_TYPE(instance); + if (subtype == subclass) { + if (impl->_abc_negative_cache_version == abc_invalidation_counter) { + incache = _in_weak_set(impl->_abc_negative_cache, subclass); + if (incache < 0) { + goto end; + } + if (incache > 0) { + result = Py_False; + Py_INCREF(result); + goto end; + } + } + /* Fall back to the subclass check. */ + result = _PyObject_CallMethodIdObjArgs(self, &PyId___subclasscheck__, + subclass, NULL); + goto end; + } + result = _PyObject_CallMethodIdObjArgs(self, &PyId___subclasscheck__, + subclass, NULL); + if (result == NULL) { + goto end; + } + + switch (PyObject_IsTrue(result)) { + case -1: + Py_DECREF(result); + result = NULL; + break; + case 0: + Py_DECREF(result); + result = _PyObject_CallMethodIdObjArgs(self, &PyId___subclasscheck__, + subtype, NULL); + break; + case 1: // Nothing to do. + break; + default: + Py_UNREACHABLE(); + } + +end: + Py_XDECREF(impl); + Py_XDECREF(subclass); + return result; +} + + +// Return -1 when exception occured. +// Return 1 when result is set. +// Return 0 otherwise. +static int subclasscheck_check_registry(_abc_data *impl, PyObject *subclass, + PyObject **result); + +/*[clinic input] +_abc._abc_subclasscheck + + self: object + subclass: object + / + +Internal ABC helper for subclasss checks. Should be never used outside abc module. +[clinic start generated code]*/ + +static PyObject * +_abc__abc_subclasscheck_impl(PyObject *module, PyObject *self, + PyObject *subclass) +/*[clinic end generated code: output=b56c9e4a530e3894 input=1d947243409d10b8]*/ +{ + PyObject *ok, *mro, *subclasses = NULL, *result = NULL; + Py_ssize_t pos; + int incache; + _abc_data *impl = _get_impl(self); + if (impl == NULL) { + return NULL; + } + + /* 1. Check cache. */ + incache = _in_weak_set(impl->_abc_cache, subclass); + if (incache < 0) { + goto end; + } + if (incache > 0) { + result = Py_True; + goto end; + } + + /* 2. Check negative cache; may have to invalidate. */ + if (impl->_abc_negative_cache_version < abc_invalidation_counter) { + /* Invalidate the negative cache. */ + if (impl->_abc_negative_cache != NULL && + PySet_Clear(impl->_abc_negative_cache) < 0) + { + goto end; + } + impl->_abc_negative_cache_version = abc_invalidation_counter; + } + else { + incache = _in_weak_set(impl->_abc_negative_cache, subclass); + if (incache < 0) { + goto end; + } + if (incache > 0) { + result = Py_False; + goto end; + } + } + + /* 3. Check the subclass hook. */ + ok = _PyObject_CallMethodIdObjArgs((PyObject *)self, &PyId___subclasshook__, + subclass, NULL); + if (ok == NULL) { + goto end; + } + if (ok == Py_True) { + Py_DECREF(ok); + if (_add_to_weak_set(&impl->_abc_cache, subclass) < 0) { + goto end; + } + result = Py_True; + goto end; + } + if (ok == Py_False) { + Py_DECREF(ok); + if (_add_to_weak_set(&impl->_abc_negative_cache, subclass) < 0) { + goto end; + } + result = Py_False; + goto end; + } + if (ok != Py_NotImplemented) { + Py_DECREF(ok); + PyErr_SetString(PyExc_AssertionError, "__subclasshook__ must return either" + " False, True, or NotImplemented"); + goto end; + } + Py_DECREF(ok); + + /* 4. Check if it's a direct subclass. */ + mro = ((PyTypeObject *)subclass)->tp_mro; + assert(PyTuple_Check(mro)); + for (pos = 0; pos < PyTuple_GET_SIZE(mro); pos++) { + PyObject *mro_item = PyTuple_GET_ITEM(mro, pos); + if (mro_item == NULL) { + goto end; + } + if ((PyObject *)self == mro_item) { + if (_add_to_weak_set(&impl->_abc_cache, subclass) < 0) { + goto end; + } + result = Py_True; + goto end; + } + } + + /* 5. Check if it's a subclass of a registered class (recursive). */ + if (subclasscheck_check_registry(impl, subclass, &result)) { + // Exception occured or result is set. + goto end; + } + + /* 6. Check if it's a subclass of a subclass (recursive). */ + subclasses = PyObject_CallMethod(self, "__subclasses__", NULL); + if (!PyList_Check(subclasses)) { + PyErr_SetString(PyExc_TypeError, "__subclasses__() must return a list"); + goto end; + } + for (pos = 0; pos < PyList_GET_SIZE(subclasses); pos++) { + PyObject *scls = PyList_GET_ITEM(subclasses, pos); + Py_INCREF(scls); + int r = PyObject_IsSubclass(subclass, scls); + Py_DECREF(scls); + if (r > 0) { + if (_add_to_weak_set(&impl->_abc_cache, subclass) < 0) { + goto end; + } + result = Py_True; + goto end; + } + if (r < 0) { + goto end; + } + } + + /* No dice; update negative cache. */ + if (_add_to_weak_set(&impl->_abc_negative_cache, subclass) < 0) { + goto end; + } + result = Py_False; + +end: + Py_XDECREF(impl); + Py_XDECREF(subclasses); + Py_XINCREF(result); + return result; +} + + +static int +subclasscheck_check_registry(_abc_data *impl, PyObject *subclass, + PyObject **result) +{ + // Fast path: check subclass is in weakref directly. + int ret = _in_weak_set(impl->_abc_registry, subclass); + if (ret < 0) { + *result = NULL; + return -1; + } + if (ret > 0) { + *result = Py_True; + return 1; + } + + if (impl->_abc_registry == NULL) { + return 0; + } + Py_ssize_t registry_size = PySet_Size(impl->_abc_registry); + if (registry_size == 0) { + return 0; + } + // Weakref callback may remove entry from set. + // So we take snapshot of registry first. + PyObject **copy = PyMem_Malloc(sizeof(PyObject*) * registry_size); + PyObject *key; + Py_ssize_t pos = 0; + Py_hash_t hash; + Py_ssize_t i = 0; + + while (_PySet_NextEntry(impl->_abc_registry, &pos, &key, &hash)) { + Py_INCREF(key); + copy[i++] = key; + } + assert(i == registry_size); + + for (i = 0; i < registry_size; i++) { + PyObject *rkey = PyWeakref_GetObject(copy[i]); + if (rkey == NULL) { + // Someone inject non-weakref type in the registry. + ret = -1; + break; + } + if (rkey == Py_None) { + continue; + } + Py_INCREF(rkey); + int r = PyObject_IsSubclass(subclass, rkey); + Py_DECREF(rkey); + if (r < 0) { + ret = -1; + break; + } + if (r > 0) { + if (_add_to_weak_set(&impl->_abc_cache, subclass) < 0) { + ret = -1; + break; + } + *result = Py_True; + ret = 1; + break; + } + } + + for (i = 0; i < registry_size; i++) { + Py_DECREF(copy[i]); + } + PyMem_Free(copy); + return ret; +} + +/*[clinic input] +_abc.get_cache_token + +Returns the current ABC cache token. + +The token is an opaque object (supporting equality testing) identifying the +current version of the ABC cache for virtual subclasses. The token changes +with every call to register() on any ABC. +[clinic start generated code]*/ + +static PyObject * +_abc_get_cache_token_impl(PyObject *module) +/*[clinic end generated code: output=c7d87841e033dacc input=70413d1c423ad9f9]*/ +{ + return PyLong_FromUnsignedLongLong(abc_invalidation_counter); +} + +static struct PyMethodDef module_functions[] = { + _ABC_GET_CACHE_TOKEN_METHODDEF + _ABC__ABC_INIT_METHODDEF + _ABC__RESET_REGISTRY_METHODDEF + _ABC__RESET_CACHES_METHODDEF + _ABC__GET_DUMP_METHODDEF + _ABC__ABC_REGISTER_METHODDEF + _ABC__ABC_INSTANCECHECK_METHODDEF + _ABC__ABC_SUBCLASSCHECK_METHODDEF + {NULL, NULL} /* sentinel */ +}; + +static struct PyModuleDef _abcmodule = { + PyModuleDef_HEAD_INIT, + "_abc", + _abc__doc__, + -1, + module_functions, + NULL, + NULL, + NULL, + NULL +}; + + +PyMODINIT_FUNC +PyInit__abc(void) +{ + if (PyType_Ready(&_abc_data_type) < 0) { + return NULL; + } + _abc_data_type.tp_doc = abc_data_doc; + + return PyModule_Create(&_abcmodule); +} diff --git a/Modules/clinic/_abc.c.h b/Modules/clinic/_abc.c.h new file mode 100644 index 000000000000..b1ec371d1551 --- /dev/null +++ b/Modules/clinic/_abc.c.h @@ -0,0 +1,162 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +PyDoc_STRVAR(_abc__reset_registry__doc__, +"_reset_registry($module, self, /)\n" +"--\n" +"\n" +"Internal ABC helper to reset registry of a given class.\n" +"\n" +"Should be only used by refleak.py"); + +#define _ABC__RESET_REGISTRY_METHODDEF \ + {"_reset_registry", (PyCFunction)_abc__reset_registry, METH_O, _abc__reset_registry__doc__}, + +PyDoc_STRVAR(_abc__reset_caches__doc__, +"_reset_caches($module, self, /)\n" +"--\n" +"\n" +"Internal ABC helper to reset both caches of a given class.\n" +"\n" +"Should be only used by refleak.py"); + +#define _ABC__RESET_CACHES_METHODDEF \ + {"_reset_caches", (PyCFunction)_abc__reset_caches, METH_O, _abc__reset_caches__doc__}, + +PyDoc_STRVAR(_abc__get_dump__doc__, +"_get_dump($module, self, /)\n" +"--\n" +"\n" +"Internal ABC helper for cache and registry debugging.\n" +"\n" +"Return shallow copies of registry, of both caches, and\n" +"negative cache version. Don\'t call this function directly,\n" +"instead use ABC._dump_registry() for a nice repr."); + +#define _ABC__GET_DUMP_METHODDEF \ + {"_get_dump", (PyCFunction)_abc__get_dump, METH_O, _abc__get_dump__doc__}, + +PyDoc_STRVAR(_abc__abc_init__doc__, +"_abc_init($module, self, /)\n" +"--\n" +"\n" +"Internal ABC helper for class set-up. Should be never used outside abc module."); + +#define _ABC__ABC_INIT_METHODDEF \ + {"_abc_init", (PyCFunction)_abc__abc_init, METH_O, _abc__abc_init__doc__}, + +PyDoc_STRVAR(_abc__abc_register__doc__, +"_abc_register($module, self, subclass, /)\n" +"--\n" +"\n" +"Internal ABC helper for subclasss registration. Should be never used outside abc module."); + +#define _ABC__ABC_REGISTER_METHODDEF \ + {"_abc_register", (PyCFunction)_abc__abc_register, METH_FASTCALL, _abc__abc_register__doc__}, + +static PyObject * +_abc__abc_register_impl(PyObject *module, PyObject *self, PyObject *subclass); + +static PyObject * +_abc__abc_register(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *self; + PyObject *subclass; + + if (!_PyArg_UnpackStack(args, nargs, "_abc_register", + 2, 2, + &self, &subclass)) { + goto exit; + } + return_value = _abc__abc_register_impl(module, self, subclass); + +exit: + return return_value; +} + +PyDoc_STRVAR(_abc__abc_instancecheck__doc__, +"_abc_instancecheck($module, self, instance, /)\n" +"--\n" +"\n" +"Internal ABC helper for instance checks. Should be never used outside abc module."); + +#define _ABC__ABC_INSTANCECHECK_METHODDEF \ + {"_abc_instancecheck", (PyCFunction)_abc__abc_instancecheck, METH_FASTCALL, _abc__abc_instancecheck__doc__}, + +static PyObject * +_abc__abc_instancecheck_impl(PyObject *module, PyObject *self, + PyObject *instance); + +static PyObject * +_abc__abc_instancecheck(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *self; + PyObject *instance; + + if (!_PyArg_UnpackStack(args, nargs, "_abc_instancecheck", + 2, 2, + &self, &instance)) { + goto exit; + } + return_value = _abc__abc_instancecheck_impl(module, self, instance); + +exit: + return return_value; +} + +PyDoc_STRVAR(_abc__abc_subclasscheck__doc__, +"_abc_subclasscheck($module, self, subclass, /)\n" +"--\n" +"\n" +"Internal ABC helper for subclasss checks. Should be never used outside abc module."); + +#define _ABC__ABC_SUBCLASSCHECK_METHODDEF \ + {"_abc_subclasscheck", (PyCFunction)_abc__abc_subclasscheck, METH_FASTCALL, _abc__abc_subclasscheck__doc__}, + +static PyObject * +_abc__abc_subclasscheck_impl(PyObject *module, PyObject *self, + PyObject *subclass); + +static PyObject * +_abc__abc_subclasscheck(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *self; + PyObject *subclass; + + if (!_PyArg_UnpackStack(args, nargs, "_abc_subclasscheck", + 2, 2, + &self, &subclass)) { + goto exit; + } + return_value = _abc__abc_subclasscheck_impl(module, self, subclass); + +exit: + return return_value; +} + +PyDoc_STRVAR(_abc_get_cache_token__doc__, +"get_cache_token($module, /)\n" +"--\n" +"\n" +"Returns the current ABC cache token.\n" +"\n" +"The token is an opaque object (supporting equality testing) identifying the\n" +"current version of the ABC cache for virtual subclasses. The token changes\n" +"with every call to register() on any ABC."); + +#define _ABC_GET_CACHE_TOKEN_METHODDEF \ + {"get_cache_token", (PyCFunction)_abc_get_cache_token, METH_NOARGS, _abc_get_cache_token__doc__}, + +static PyObject * +_abc_get_cache_token_impl(PyObject *module); + +static PyObject * +_abc_get_cache_token(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _abc_get_cache_token_impl(module); +} +/*[clinic end generated code: output=9d6f861a8f45bc6f input=a9049054013a1b77]*/ diff --git a/PC/config.c b/PC/config.c index 0c08bfeaa0dc..568a0fa9a467 100644 --- a/PC/config.c +++ b/PC/config.c @@ -5,6 +5,7 @@ #include "Python.h" +extern PyObject* PyInit__abc(void); extern PyObject* PyInit_array(void); extern PyObject* PyInit_audioop(void); extern PyObject* PyInit_binascii(void); @@ -80,6 +81,7 @@ extern PyObject* PyInit__imp(void); struct _inittab _PyImport_Inittab[] = { + {"_abc", PyInit__abc}, {"array", PyInit_array}, {"_ast", PyInit__ast}, {"audioop", PyInit_audioop}, diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index bf4131e91b0a..90330faa0cf2 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -228,6 +228,7 @@ + diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index 5f980388e5f3..b51fd54f8b4d 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -473,6 +473,9 @@ + + Modules + Modules diff --git a/setup.py b/setup.py index 6f9a39719b43..f4f6e4fdb1f0 100644 --- a/setup.py +++ b/setup.py @@ -712,6 +712,8 @@ def detect_modules(self): exts.append( Extension('_opcode', ['_opcode.c']) ) # asyncio speedups exts.append( Extension("_asyncio", ["_asynciomodule.c"]) ) + # _abc speedups + exts.append( Extension("_abc", ["_abc.c"]) ) # _queue module exts.append( Extension("_queue", ["_queuemodule.c"]) ) From webhook-mailer at python.org Sun Feb 18 11:19:40 2018 From: webhook-mailer at python.org (Zachary Ware) Date: Sun, 18 Feb 2018 16:19:40 -0000 Subject: [Python-checkins] Clean up Travis config (GH-5727) Message-ID: https://github.com/python/cpython/commit/7eb3f8226ea7b79dae4e4e8b05730cfe0d9af7c1 commit: 7eb3f8226ea7b79dae4e4e8b05730cfe0d9af7c1 branch: master author: Zachary Ware committer: GitHub date: 2018-02-18T10:19:37-06:00 summary: Clean up Travis config (GH-5727) files: M .travis.yml diff --git a/.travis.yml b/.travis.yml index 665b266146ae..ab43318975fb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,10 +5,10 @@ group: beta # To cache doc-building dependencies and C compiler output. cache: - - pip - - ccache - - directories: - - $HOME/multissl + - pip + - ccache + - directories: + - $HOME/multissl env: global: @@ -26,6 +26,7 @@ branches: only: - master - /^\d\.\d$/ + - buildbot-custom matrix: fast_finish: true @@ -56,22 +57,12 @@ matrix: compiler: gcc env: OPTIONAL=true before_script: - - | - if ! git diff --name-only $TRAVIS_COMMIT_RANGE | grep -qvE '(\.rst$)|(^Doc)|(^Misc)' - then - echo "Only docs were updated, stopping build process." - exit - fi - python3 Tools/ssl/multissltests.py --steps=library \ - --base-directory ${HOME}/multissl \ - --openssl ${OPENSSL} >/dev/null - openssl version - ./configure - make -s -j4 - # Need a venv that can parse covered code. - ./python -m venv venv - ./venv/bin/python -m pip install -U coverage - ./venv/bin/python -m test.pythoninfo + - ./configure + - make -s -j4 + # Need a venv that can parse covered code. + - ./python -m venv venv + - ./venv/bin/python -m pip install -U coverage + - ./venv/bin/python -m test.pythoninfo script: # Skip tests that re-run the entire test suite. - ./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 @@ -80,47 +71,60 @@ matrix: - source ./venv/bin/activate - bash <(curl -s https://codecov.io/bash) -# Travis provides only 2 cores, so don't overdo the parallelism and waste memory. -before_script: + +before_install: + - set -e - | - set -e - if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then - files_changed=$(git diff --name-only $TRAVIS_COMMIT_RANGE) - else - # Pull requests are slightly complicated because merging the PR commit without - # rebasing causes it to retain its old commit date. Meaning in history if any - # commits have been made on master that post-date it, they will be accidentally - # included in the diff if we use the TRAVIS_COMMIT_RANGE variable. - files_changed=$(git diff --name-only HEAD $(git merge-base HEAD $TRAVIS_BRANCH)) + # Check short-circuit conditions + if [ "${TESTING}" != "docs" ] + then + if [ "$TRAVIS_PULL_REQUEST" = "false" ] + then + echo "Not a PR, doing full build." + else + # Pull requests are slightly complicated because $TRAVIS_COMMIT_RANGE + # may include more changes than desired if the history is convoluted. + # Instead, explicitly fetch the base branch and compare against the + # merge-base commit. + git fetch -q origin +refs/heads/$TRAVIS_BRANCH + changes=$(git diff --name-only HEAD $(git merge-base HEAD FETCH_HEAD)) + echo "Files changed:" + echo "$changes" + if ! echo "$changes" | grep -qvE '(\.rst$)|(^Doc)|(^Misc)' + then + echo "Only docs were updated, stopping build process." + exit + fi + fi fi - # Prints changed files in this commit to help debug doc-only build issues. - echo "Files changed: " - echo $files_changed - - if ! echo "$files_changed" | grep -qvE '(\.rst$)|(^Doc)|(^Misc)' +install: + - | + # Install OpenSSL as necessary + if [ "${TESTING}" != "docs" ] then - echo "Only docs were updated, stopping build process." - exit - fi - if [ "${TESTING}" != "docs" ]; then # clang complains about unused-parameter a lot, redirect stderr python3 Tools/ssl/multissltests.py --steps=library \ --base-directory ${HOME}/multissl \ --openssl ${OPENSSL} >/dev/null 2>&1 fi - openssl version - ./configure --with-pydebug - make -j4 regen-all - changes=`git status --porcelain` + - openssl version + +# Travis provides only 2 cores, so don't overdo the parallelism and waste memory. +before_script: + - ./configure --with-pydebug + - make -j4 regen-all + - changes=`git status --porcelain` + - | + # Check for changes in regenerated files if ! test -z "$changes" then echo "Generated files not up to date" echo "$changes" exit 1 fi - make -j4 - make pythoninfo + - make -j4 + - make pythoninfo script: # Using the built Python as patchcheck.py is built around the idea of using @@ -128,10 +132,10 @@ script: # should be compared against. # Only run on Linux as the check only needs to be run once. - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./python Tools/scripts/patchcheck.py --travis $TRAVIS_PULL_REQUEST; fi - # `-r -w` implicitly provided through `make buildbottest`. - - make buildbottest TESTOPTS="-j4 -uall,-cpu" # Check that all symbols exported by libpython start with "Py" or "_Py" - make smelly + # `-r -w` implicitly provided through `make buildbottest`. + - make buildbottest TESTOPTS="-j4 -uall,-cpu" notifications: email: false From webhook-mailer at python.org Sun Feb 18 11:39:54 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sun, 18 Feb 2018 16:39:54 -0000 Subject: [Python-checkins] Clean up Travis config (GH-5727) Message-ID: https://github.com/python/cpython/commit/7da582d3b5c798e47f836efaef0157195c17efb8 commit: 7da582d3b5c798e47f836efaef0157195c17efb8 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-18T08:39:51-08:00 summary: Clean up Travis config (GH-5727) (cherry picked from commit 7eb3f8226ea7b79dae4e4e8b05730cfe0d9af7c1) Co-authored-by: Zachary Ware files: M .travis.yml diff --git a/.travis.yml b/.travis.yml index 665b266146ae..ab43318975fb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,10 +5,10 @@ group: beta # To cache doc-building dependencies and C compiler output. cache: - - pip - - ccache - - directories: - - $HOME/multissl + - pip + - ccache + - directories: + - $HOME/multissl env: global: @@ -26,6 +26,7 @@ branches: only: - master - /^\d\.\d$/ + - buildbot-custom matrix: fast_finish: true @@ -56,22 +57,12 @@ matrix: compiler: gcc env: OPTIONAL=true before_script: - - | - if ! git diff --name-only $TRAVIS_COMMIT_RANGE | grep -qvE '(\.rst$)|(^Doc)|(^Misc)' - then - echo "Only docs were updated, stopping build process." - exit - fi - python3 Tools/ssl/multissltests.py --steps=library \ - --base-directory ${HOME}/multissl \ - --openssl ${OPENSSL} >/dev/null - openssl version - ./configure - make -s -j4 - # Need a venv that can parse covered code. - ./python -m venv venv - ./venv/bin/python -m pip install -U coverage - ./venv/bin/python -m test.pythoninfo + - ./configure + - make -s -j4 + # Need a venv that can parse covered code. + - ./python -m venv venv + - ./venv/bin/python -m pip install -U coverage + - ./venv/bin/python -m test.pythoninfo script: # Skip tests that re-run the entire test suite. - ./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 @@ -80,47 +71,60 @@ matrix: - source ./venv/bin/activate - bash <(curl -s https://codecov.io/bash) -# Travis provides only 2 cores, so don't overdo the parallelism and waste memory. -before_script: + +before_install: + - set -e - | - set -e - if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then - files_changed=$(git diff --name-only $TRAVIS_COMMIT_RANGE) - else - # Pull requests are slightly complicated because merging the PR commit without - # rebasing causes it to retain its old commit date. Meaning in history if any - # commits have been made on master that post-date it, they will be accidentally - # included in the diff if we use the TRAVIS_COMMIT_RANGE variable. - files_changed=$(git diff --name-only HEAD $(git merge-base HEAD $TRAVIS_BRANCH)) + # Check short-circuit conditions + if [ "${TESTING}" != "docs" ] + then + if [ "$TRAVIS_PULL_REQUEST" = "false" ] + then + echo "Not a PR, doing full build." + else + # Pull requests are slightly complicated because $TRAVIS_COMMIT_RANGE + # may include more changes than desired if the history is convoluted. + # Instead, explicitly fetch the base branch and compare against the + # merge-base commit. + git fetch -q origin +refs/heads/$TRAVIS_BRANCH + changes=$(git diff --name-only HEAD $(git merge-base HEAD FETCH_HEAD)) + echo "Files changed:" + echo "$changes" + if ! echo "$changes" | grep -qvE '(\.rst$)|(^Doc)|(^Misc)' + then + echo "Only docs were updated, stopping build process." + exit + fi + fi fi - # Prints changed files in this commit to help debug doc-only build issues. - echo "Files changed: " - echo $files_changed - - if ! echo "$files_changed" | grep -qvE '(\.rst$)|(^Doc)|(^Misc)' +install: + - | + # Install OpenSSL as necessary + if [ "${TESTING}" != "docs" ] then - echo "Only docs were updated, stopping build process." - exit - fi - if [ "${TESTING}" != "docs" ]; then # clang complains about unused-parameter a lot, redirect stderr python3 Tools/ssl/multissltests.py --steps=library \ --base-directory ${HOME}/multissl \ --openssl ${OPENSSL} >/dev/null 2>&1 fi - openssl version - ./configure --with-pydebug - make -j4 regen-all - changes=`git status --porcelain` + - openssl version + +# Travis provides only 2 cores, so don't overdo the parallelism and waste memory. +before_script: + - ./configure --with-pydebug + - make -j4 regen-all + - changes=`git status --porcelain` + - | + # Check for changes in regenerated files if ! test -z "$changes" then echo "Generated files not up to date" echo "$changes" exit 1 fi - make -j4 - make pythoninfo + - make -j4 + - make pythoninfo script: # Using the built Python as patchcheck.py is built around the idea of using @@ -128,10 +132,10 @@ script: # should be compared against. # Only run on Linux as the check only needs to be run once. - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./python Tools/scripts/patchcheck.py --travis $TRAVIS_PULL_REQUEST; fi - # `-r -w` implicitly provided through `make buildbottest`. - - make buildbottest TESTOPTS="-j4 -uall,-cpu" # Check that all symbols exported by libpython start with "Py" or "_Py" - make smelly + # `-r -w` implicitly provided through `make buildbottest`. + - make buildbottest TESTOPTS="-j4 -uall,-cpu" notifications: email: false From webhook-mailer at python.org Sun Feb 18 11:52:39 2018 From: webhook-mailer at python.org (Jason R. Coombs) Date: Sun, 18 Feb 2018 16:52:39 -0000 Subject: [Python-checkins] Correct venv doc (fix #32540) (#5736) Message-ID: https://github.com/python/cpython/commit/e8eb972514cad6086b752754c1d34d703c04dd82 commit: e8eb972514cad6086b752754c1d34d703c04dd82 branch: master author: TROUVERIE Joachim committer: Jason R. Coombs date: 2018-02-18T11:52:36-05:00 summary: Correct venv doc (fix #32540) (#5736) files: M Doc/using/venv-create.inc diff --git a/Doc/using/venv-create.inc b/Doc/using/venv-create.inc index 4292592ba7a2..4c7795ad8019 100644 --- a/Doc/using/venv-create.inc +++ b/Doc/using/venv-create.inc @@ -9,7 +9,8 @@ with a ``home`` key pointing to the Python installation from which the command was run. It also creates a ``bin`` (or ``Scripts`` on Windows) subdirectory containing a copy of the ``python`` binary (or binaries, in the case of Windows). It also creates an (initially empty) ``lib/pythonX.Y/site-packages`` -subdirectory (on Windows, this is ``Lib\site-packages``). +subdirectory (on Windows, this is ``Lib\site-packages``). If an existing +directory is specified, it will be re-used. .. deprecated:: 3.6 ``pyvenv`` was the recommended tool for creating virtual environments for @@ -71,9 +72,7 @@ The command, if run with ``-h``, will show the available options:: .. versionchanged:: 3.4 In earlier versions, if the target directory already existed, an error was - raised, unless the ``--clear`` or ``--upgrade`` option was provided. Now, - if an existing directory is specified, its contents are removed and - the directory is processed as if it had been newly created. + raised, unless the ``--clear`` or ``--upgrade`` option was provided. The created ``pyvenv.cfg`` file also includes the ``include-system-site-packages`` key, set to ``true`` if ``venv`` is From webhook-mailer at python.org Sun Feb 18 12:39:46 2018 From: webhook-mailer at python.org (Ivan Levkivskyi) Date: Sun, 18 Feb 2018 17:39:46 -0000 Subject: [Python-checkins] bpo-31333: Re-implement ABCMeta in C (GH-5733) Message-ID: https://github.com/python/cpython/commit/38928992885d8a04b7188abdba3b04f350bde32d commit: 38928992885d8a04b7188abdba3b04f350bde32d branch: 3.7 author: Ivan Levkivskyi committer: GitHub date: 2018-02-18T17:39:43Z summary: bpo-31333: Re-implement ABCMeta in C (GH-5733) This adds C versions of methods used by ABCMeta that improve performance of various ABC operations. files: A Lib/_py_abc.py A Misc/NEWS.d/next/Library/2018-02-15-08-18-52.bpo-31333.4fF-gM.rst A Modules/_abc.c A Modules/clinic/_abc.c.h M Doc/whatsnew/3.7.rst M Lib/abc.py M Lib/test/libregrtest/refleak.py M Lib/test/test_abc.py M Lib/test/test_typing.py M Modules/Setup.dist M PC/config.c M PCbuild/pythoncore.vcxproj M PCbuild/pythoncore.vcxproj.filters M setup.py diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 748189e57486..80bc8fb3d951 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -845,6 +845,12 @@ Optimizations * 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 rewrittent 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`) + Build and C API Changes ======================= diff --git a/Lib/_py_abc.py b/Lib/_py_abc.py new file mode 100644 index 000000000000..6f42ef32fa69 --- /dev/null +++ b/Lib/_py_abc.py @@ -0,0 +1,145 @@ +from _weakrefset import WeakSet + + +def get_cache_token(): + """Returns the current ABC cache token. + + The token is an opaque object (supporting equality testing) identifying the + current version of the ABC cache for virtual subclasses. The token changes + with every call to ``register()`` on any ABC. + """ + return ABCMeta._abc_invalidation_counter + + +class ABCMeta(type): + """Metaclass for defining Abstract Base Classes (ABCs). + + Use this metaclass to create an ABC. An ABC can be subclassed + directly, and then acts as a mix-in class. You can also register + unrelated concrete classes (even built-in classes) and unrelated + ABCs as 'virtual subclasses' -- these and their descendants will + be considered subclasses of the registering ABC by the built-in + issubclass() function, but the registering ABC won't show up in + their MRO (Method Resolution Order) nor will method + implementations defined by the registering ABC be callable (not + even via super()). + """ + + # A global counter that is incremented each time a class is + # registered as a virtual subclass of anything. It forces the + # negative cache to be cleared before its next use. + # Note: this counter is private. Use `abc.get_cache_token()` for + # external code. + _abc_invalidation_counter = 0 + + def __new__(mcls, name, bases, namespace, **kwargs): + cls = super().__new__(mcls, name, bases, namespace, **kwargs) + # Compute set of abstract method names + abstracts = {name + for name, value in namespace.items() + if getattr(value, "__isabstractmethod__", False)} + for base in bases: + for name in getattr(base, "__abstractmethods__", set()): + value = getattr(cls, name, None) + if getattr(value, "__isabstractmethod__", False): + abstracts.add(name) + cls.__abstractmethods__ = frozenset(abstracts) + # Set up inheritance registry + cls._abc_registry = WeakSet() + cls._abc_cache = WeakSet() + cls._abc_negative_cache = WeakSet() + cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter + return cls + + def register(cls, subclass): + """Register a virtual subclass of an ABC. + + Returns the subclass, to allow usage as a class decorator. + """ + if not isinstance(subclass, type): + raise TypeError("Can only register classes") + if issubclass(subclass, cls): + return subclass # Already a subclass + # Subtle: test for cycles *after* testing for "already a subclass"; + # this means we allow X.register(X) and interpret it as a no-op. + if issubclass(cls, subclass): + # This would create a cycle, which is bad for the algorithm below + raise RuntimeError("Refusing to create an inheritance cycle") + cls._abc_registry.add(subclass) + ABCMeta._abc_invalidation_counter += 1 # Invalidate negative cache + return subclass + + def _dump_registry(cls, file=None): + """Debug helper to print the ABC registry.""" + print(f"Class: {cls.__module__}.{cls.__qualname__}", file=file) + print(f"Inv. counter: {get_cache_token()}", file=file) + for name in cls.__dict__: + if name.startswith("_abc_"): + value = getattr(cls, name) + if isinstance(value, WeakSet): + value = set(value) + print(f"{name}: {value!r}", file=file) + + def _abc_registry_clear(cls): + """Clear the registry (for debugging or testing).""" + cls._abc_registry.clear() + + def _abc_caches_clear(cls): + """Clear the caches (for debugging or testing).""" + cls._abc_cache.clear() + cls._abc_negative_cache.clear() + + def __instancecheck__(cls, instance): + """Override for isinstance(instance, cls).""" + # Inline the cache checking + subclass = instance.__class__ + if subclass in cls._abc_cache: + return True + subtype = type(instance) + if subtype is subclass: + if (cls._abc_negative_cache_version == + ABCMeta._abc_invalidation_counter and + subclass in cls._abc_negative_cache): + return False + # Fall back to the subclass check. + return cls.__subclasscheck__(subclass) + return any(cls.__subclasscheck__(c) for c in (subclass, subtype)) + + def __subclasscheck__(cls, subclass): + """Override for issubclass(subclass, cls).""" + # Check cache + if subclass in cls._abc_cache: + return True + # Check negative cache; may have to invalidate + if cls._abc_negative_cache_version < ABCMeta._abc_invalidation_counter: + # Invalidate the negative cache + cls._abc_negative_cache = WeakSet() + cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter + elif subclass in cls._abc_negative_cache: + return False + # Check the subclass hook + ok = cls.__subclasshook__(subclass) + if ok is not NotImplemented: + assert isinstance(ok, bool) + if ok: + cls._abc_cache.add(subclass) + else: + cls._abc_negative_cache.add(subclass) + return ok + # Check if it's a direct subclass + if cls in getattr(subclass, '__mro__', ()): + cls._abc_cache.add(subclass) + return True + # Check if it's a subclass of a registered class (recursive) + for rcls in cls._abc_registry: + if issubclass(subclass, rcls): + cls._abc_cache.add(subclass) + return True + # Check if it's a subclass of a subclass (recursive) + for scls in cls.__subclasses__(): + if issubclass(subclass, scls): + cls._abc_cache.add(subclass) + return True + # No dice; update negative cache + cls._abc_negative_cache.add(subclass) + return False diff --git a/Lib/abc.py b/Lib/abc.py index 9bdc36dce65e..7094141277ae 100644 --- a/Lib/abc.py +++ b/Lib/abc.py @@ -3,8 +3,6 @@ """Abstract Base Classes (ABCs) according to PEP 3119.""" -from _weakrefset import WeakSet - def abstractmethod(funcobj): """A decorator indicating abstract methods. @@ -27,8 +25,7 @@ def my_abstract_method(self, ...): class abstractclassmethod(classmethod): - """ - A decorator indicating abstract classmethods. + """A decorator indicating abstract classmethods. Similar to abstractmethod. @@ -51,8 +48,7 @@ def __init__(self, callable): class abstractstaticmethod(staticmethod): - """ - A decorator indicating abstract staticmethods. + """A decorator indicating abstract staticmethods. Similar to abstractmethod. @@ -75,8 +71,7 @@ def __init__(self, callable): class abstractproperty(property): - """ - A decorator indicating abstract properties. + """A decorator indicating abstract properties. Requires that the metaclass is ABCMeta or derived from it. A class that has a metaclass derived from ABCMeta cannot be @@ -106,131 +101,66 @@ def setx(self, value): ... __isabstractmethod__ = True -class ABCMeta(type): - - """Metaclass for defining Abstract Base Classes (ABCs). - - Use this metaclass to create an ABC. An ABC can be subclassed - directly, and then acts as a mix-in class. You can also register - unrelated concrete classes (even built-in classes) and unrelated - ABCs as 'virtual subclasses' -- these and their descendants will - be considered subclasses of the registering ABC by the built-in - issubclass() function, but the registering ABC won't show up in - their MRO (Method Resolution Order) nor will method - implementations defined by the registering ABC be callable (not - even via super()). - - """ - - # A global counter that is incremented each time a class is - # registered as a virtual subclass of anything. It forces the - # negative cache to be cleared before its next use. - # Note: this counter is private. Use `abc.get_cache_token()` for - # external code. - _abc_invalidation_counter = 0 - - def __new__(mcls, name, bases, namespace, **kwargs): - cls = super().__new__(mcls, name, bases, namespace, **kwargs) - # Compute set of abstract method names - abstracts = {name - for name, value in namespace.items() - if getattr(value, "__isabstractmethod__", False)} - for base in bases: - for name in getattr(base, "__abstractmethods__", set()): - value = getattr(cls, name, None) - if getattr(value, "__isabstractmethod__", False): - abstracts.add(name) - cls.__abstractmethods__ = frozenset(abstracts) - # Set up inheritance registry - cls._abc_registry = WeakSet() - cls._abc_cache = WeakSet() - cls._abc_negative_cache = WeakSet() - cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter - return cls - - def register(cls, subclass): - """Register a virtual subclass of an ABC. - - Returns the subclass, to allow usage as a class decorator. +try: + from _abc import (get_cache_token, _abc_init, _abc_register, + _abc_instancecheck, _abc_subclasscheck, _get_dump, + _reset_registry, _reset_caches) +except ImportError: + from _py_abc import ABCMeta, get_cache_token + ABCMeta.__module__ = 'abc' +else: + class ABCMeta(type): + """Metaclass for defining Abstract Base Classes (ABCs). + + Use this metaclass to create an ABC. An ABC can be subclassed + directly, and then acts as a mix-in class. You can also register + unrelated concrete classes (even built-in classes) and unrelated + ABCs as 'virtual subclasses' -- these and their descendants will + be considered subclasses of the registering ABC by the built-in + issubclass() function, but the registering ABC won't show up in + their MRO (Method Resolution Order) nor will method + implementations defined by the registering ABC be callable (not + even via super()). """ - if not isinstance(subclass, type): - raise TypeError("Can only register classes") - if issubclass(subclass, cls): - return subclass # Already a subclass - # Subtle: test for cycles *after* testing for "already a subclass"; - # this means we allow X.register(X) and interpret it as a no-op. - if issubclass(cls, subclass): - # This would create a cycle, which is bad for the algorithm below - raise RuntimeError("Refusing to create an inheritance cycle") - cls._abc_registry.add(subclass) - ABCMeta._abc_invalidation_counter += 1 # Invalidate negative cache - return subclass - - def _dump_registry(cls, file=None): - """Debug helper to print the ABC registry.""" - print("Class: %s.%s" % (cls.__module__, cls.__qualname__), file=file) - print("Inv.counter: %s" % ABCMeta._abc_invalidation_counter, file=file) - for name in cls.__dict__: - if name.startswith("_abc_"): - value = getattr(cls, name) - if isinstance(value, WeakSet): - value = set(value) - print("%s: %r" % (name, value), file=file) - - def __instancecheck__(cls, instance): - """Override for isinstance(instance, cls).""" - # Inline the cache checking - subclass = instance.__class__ - if subclass in cls._abc_cache: - return True - subtype = type(instance) - if subtype is subclass: - if (cls._abc_negative_cache_version == - ABCMeta._abc_invalidation_counter and - subclass in cls._abc_negative_cache): - return False - # Fall back to the subclass check. - return cls.__subclasscheck__(subclass) - return any(cls.__subclasscheck__(c) for c in {subclass, subtype}) - - def __subclasscheck__(cls, subclass): - """Override for issubclass(subclass, cls).""" - # Check cache - if subclass in cls._abc_cache: - return True - # Check negative cache; may have to invalidate - if cls._abc_negative_cache_version < ABCMeta._abc_invalidation_counter: - # Invalidate the negative cache - cls._abc_negative_cache = WeakSet() - cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter - elif subclass in cls._abc_negative_cache: - return False - # Check the subclass hook - ok = cls.__subclasshook__(subclass) - if ok is not NotImplemented: - assert isinstance(ok, bool) - if ok: - cls._abc_cache.add(subclass) - else: - cls._abc_negative_cache.add(subclass) - return ok - # Check if it's a direct subclass - if cls in getattr(subclass, '__mro__', ()): - cls._abc_cache.add(subclass) - return True - # Check if it's a subclass of a registered class (recursive) - for rcls in cls._abc_registry: - if issubclass(subclass, rcls): - cls._abc_cache.add(subclass) - return True - # Check if it's a subclass of a subclass (recursive) - for scls in cls.__subclasses__(): - if issubclass(subclass, scls): - cls._abc_cache.add(subclass) - return True - # No dice; update negative cache - cls._abc_negative_cache.add(subclass) - return False + def __new__(mcls, name, bases, namespace, **kwargs): + cls = super().__new__(mcls, name, bases, namespace, **kwargs) + _abc_init(cls) + return cls + + def register(cls, subclass): + """Register a virtual subclass of an ABC. + + Returns the subclass, to allow usage as a class decorator. + """ + return _abc_register(cls, subclass) + + def __instancecheck__(cls, instance): + """Override for isinstance(instance, cls).""" + return _abc_instancecheck(cls, instance) + + def __subclasscheck__(cls, subclass): + """Override for issubclass(subclass, cls).""" + return _abc_subclasscheck(cls, subclass) + + def _dump_registry(cls, file=None): + """Debug helper to print the ABC registry.""" + print(f"Class: {cls.__module__}.{cls.__qualname__}", file=file) + print(f"Inv. counter: {get_cache_token()}", file=file) + (_abc_registry, _abc_cache, _abc_negative_cache, + _abc_negative_cache_version) = _get_dump(cls) + print(f"_abc_registry: {_abc_registry!r}", file=file) + print(f"_abc_cache: {_abc_cache!r}", file=file) + print(f"_abc_negative_cache: {_abc_negative_cache!r}", file=file) + print(f"_abc_negative_cache_version: {_abc_negative_cache_version!r}", + file=file) + + def _abc_registry_clear(cls): + """Clear the registry (for debugging or testing).""" + _reset_registry(cls) + + def _abc_caches_clear(cls): + """Clear the caches (for debugging or testing).""" + _reset_caches(cls) class ABC(metaclass=ABCMeta): @@ -238,13 +168,3 @@ class ABC(metaclass=ABCMeta): inheritance. """ __slots__ = () - - -def get_cache_token(): - """Returns the current ABC cache token. - - The token is an opaque object (supporting equality testing) identifying the - current version of the ABC cache for virtual subclasses. The token changes - with every call to ``register()`` on any ABC. - """ - return ABCMeta._abc_invalidation_counter diff --git a/Lib/test/libregrtest/refleak.py b/Lib/test/libregrtest/refleak.py index 2ca9aa87644c..6724488fcfb0 100644 --- a/Lib/test/libregrtest/refleak.py +++ b/Lib/test/libregrtest/refleak.py @@ -5,6 +5,13 @@ import warnings from inspect import isabstract from test import support +try: + from _abc import _get_dump +except ImportError: + def _get_dump(cls): + # For legacy Python version + return (cls._abc_registry, cls._abc_cache, + cls._abc_negative_cache, cls._abc_negative_cache_version) def dash_R(the_module, test, indirect_test, huntrleaks): @@ -36,7 +43,7 @@ def dash_R(the_module, test, indirect_test, huntrleaks): if not isabstract(abc): continue for obj in abc.__subclasses__() + [abc]: - abcs[obj] = obj._abc_registry.copy() + abcs[obj] = _get_dump(obj)[0] # bpo-31217: Integer pool to get a single integer object for the same # value. The pool is used to prevent false alarm when checking for memory @@ -113,7 +120,6 @@ def check_fd_deltas(deltas): def dash_R_cleanup(fs, ps, pic, zdc, abcs): import gc, copyreg import collections.abc - from weakref import WeakSet # Restore some original values. warnings.filters[:] = fs @@ -137,9 +143,10 @@ def dash_R_cleanup(fs, ps, pic, zdc, abcs): abs_classes = filter(isabstract, abs_classes) for abc in abs_classes: for obj in abc.__subclasses__() + [abc]: - obj._abc_registry = abcs.get(obj, WeakSet()).copy() - obj._abc_cache.clear() - obj._abc_negative_cache.clear() + for ref in abcs.get(obj, set()): + if ref() is not None: + obj.register(ref()) + obj._abc_caches_clear() clear_caches() diff --git a/Lib/test/test_abc.py b/Lib/test/test_abc.py index 61c2876708c2..af26c1d6b8c5 100644 --- a/Lib/test/test_abc.py +++ b/Lib/test/test_abc.py @@ -1,422 +1,445 @@ # Copyright 2007 Google, Inc. All Rights Reserved. # Licensed to PSF under a Contributor Agreement. +# Note: each test is run with Python and C versions of ABCMeta. Except for +# test_ABC_helper(), which assures that abc.ABC is an instance of abc.ABCMeta. + """Unit tests for abc.py.""" import unittest import abc +import _py_abc from inspect import isabstract +def test_factory(abc_ABCMeta, abc_get_cache_token): + class TestLegacyAPI(unittest.TestCase): -class TestLegacyAPI(unittest.TestCase): - - def test_abstractproperty_basics(self): - @abc.abstractproperty - def foo(self): pass - self.assertTrue(foo.__isabstractmethod__) - def bar(self): pass - self.assertFalse(hasattr(bar, "__isabstractmethod__")) - - class C(metaclass=abc.ABCMeta): + def test_abstractproperty_basics(self): @abc.abstractproperty - def foo(self): return 3 - self.assertRaises(TypeError, C) - class D(C): - @property - def foo(self): return super().foo - self.assertEqual(D().foo, 3) - self.assertFalse(getattr(D.foo, "__isabstractmethod__", False)) - - def test_abstractclassmethod_basics(self): - @abc.abstractclassmethod - def foo(cls): pass - self.assertTrue(foo.__isabstractmethod__) - @classmethod - def bar(cls): pass - self.assertFalse(getattr(bar, "__isabstractmethod__", False)) - - class C(metaclass=abc.ABCMeta): + def foo(self): pass + self.assertTrue(foo.__isabstractmethod__) + def bar(self): pass + self.assertFalse(hasattr(bar, "__isabstractmethod__")) + + class C(metaclass=abc_ABCMeta): + @abc.abstractproperty + def foo(self): return 3 + self.assertRaises(TypeError, C) + class D(C): + @property + def foo(self): return super().foo + self.assertEqual(D().foo, 3) + self.assertFalse(getattr(D.foo, "__isabstractmethod__", False)) + + def test_abstractclassmethod_basics(self): @abc.abstractclassmethod - def foo(cls): return cls.__name__ - self.assertRaises(TypeError, C) - class D(C): + def foo(cls): pass + self.assertTrue(foo.__isabstractmethod__) @classmethod - def foo(cls): return super().foo() - self.assertEqual(D.foo(), 'D') - self.assertEqual(D().foo(), 'D') - - def test_abstractstaticmethod_basics(self): - @abc.abstractstaticmethod - def foo(): pass - self.assertTrue(foo.__isabstractmethod__) - @staticmethod - def bar(): pass - self.assertFalse(getattr(bar, "__isabstractmethod__", False)) - - class C(metaclass=abc.ABCMeta): + def bar(cls): pass + self.assertFalse(getattr(bar, "__isabstractmethod__", False)) + + class C(metaclass=abc_ABCMeta): + @abc.abstractclassmethod + def foo(cls): return cls.__name__ + self.assertRaises(TypeError, C) + class D(C): + @classmethod + def foo(cls): return super().foo() + self.assertEqual(D.foo(), 'D') + self.assertEqual(D().foo(), 'D') + + def test_abstractstaticmethod_basics(self): @abc.abstractstaticmethod - def foo(): return 3 - self.assertRaises(TypeError, C) - class D(C): + def foo(): pass + self.assertTrue(foo.__isabstractmethod__) @staticmethod - def foo(): return 4 - self.assertEqual(D.foo(), 4) - self.assertEqual(D().foo(), 4) - + def bar(): pass + self.assertFalse(getattr(bar, "__isabstractmethod__", False)) -class TestABC(unittest.TestCase): + class C(metaclass=abc_ABCMeta): + @abc.abstractstaticmethod + def foo(): return 3 + self.assertRaises(TypeError, C) + class D(C): + @staticmethod + def foo(): return 4 + self.assertEqual(D.foo(), 4) + self.assertEqual(D().foo(), 4) + + + class TestABC(unittest.TestCase): + + def test_ABC_helper(self): + # create an ABC using the helper class and perform basic checks + class C(abc.ABC): + @classmethod + @abc.abstractmethod + def foo(cls): return cls.__name__ + self.assertEqual(type(C), abc.ABCMeta) + self.assertRaises(TypeError, C) + class D(C): + @classmethod + def foo(cls): return super().foo() + self.assertEqual(D.foo(), 'D') - def test_ABC_helper(self): - # create an ABC using the helper class and perform basic checks - class C(abc.ABC): - @classmethod + def test_abstractmethod_basics(self): @abc.abstractmethod - def foo(cls): return cls.__name__ - self.assertEqual(type(C), abc.ABCMeta) - self.assertRaises(TypeError, C) - class D(C): - @classmethod - def foo(cls): return super().foo() - self.assertEqual(D.foo(), 'D') - - def test_abstractmethod_basics(self): - @abc.abstractmethod - def foo(self): pass - self.assertTrue(foo.__isabstractmethod__) - def bar(self): pass - self.assertFalse(hasattr(bar, "__isabstractmethod__")) - - def test_abstractproperty_basics(self): - @property - @abc.abstractmethod - def foo(self): pass - self.assertTrue(foo.__isabstractmethod__) - def bar(self): pass - self.assertFalse(getattr(bar, "__isabstractmethod__", False)) - - class C(metaclass=abc.ABCMeta): + def foo(self): pass + self.assertTrue(foo.__isabstractmethod__) + def bar(self): pass + self.assertFalse(hasattr(bar, "__isabstractmethod__")) + + def test_abstractproperty_basics(self): @property @abc.abstractmethod - def foo(self): return 3 - self.assertRaises(TypeError, C) - class D(C): - @C.foo.getter - def foo(self): return super().foo - self.assertEqual(D().foo, 3) - - def test_abstractclassmethod_basics(self): - @classmethod - @abc.abstractmethod - def foo(cls): pass - self.assertTrue(foo.__isabstractmethod__) - @classmethod - def bar(cls): pass - self.assertFalse(getattr(bar, "__isabstractmethod__", False)) - - class C(metaclass=abc.ABCMeta): + def foo(self): pass + self.assertTrue(foo.__isabstractmethod__) + def bar(self): pass + self.assertFalse(getattr(bar, "__isabstractmethod__", False)) + + class C(metaclass=abc_ABCMeta): + @property + @abc.abstractmethod + def foo(self): return 3 + self.assertRaises(TypeError, C) + class D(C): + @C.foo.getter + def foo(self): return super().foo + self.assertEqual(D().foo, 3) + + def test_abstractclassmethod_basics(self): @classmethod @abc.abstractmethod - def foo(cls): return cls.__name__ - self.assertRaises(TypeError, C) - class D(C): + def foo(cls): pass + self.assertTrue(foo.__isabstractmethod__) @classmethod - def foo(cls): return super().foo() - self.assertEqual(D.foo(), 'D') - self.assertEqual(D().foo(), 'D') - - def test_abstractstaticmethod_basics(self): - @staticmethod - @abc.abstractmethod - def foo(): pass - self.assertTrue(foo.__isabstractmethod__) - @staticmethod - def bar(): pass - self.assertFalse(getattr(bar, "__isabstractmethod__", False)) - - class C(metaclass=abc.ABCMeta): + def bar(cls): pass + self.assertFalse(getattr(bar, "__isabstractmethod__", False)) + + class C(metaclass=abc_ABCMeta): + @classmethod + @abc.abstractmethod + def foo(cls): return cls.__name__ + self.assertRaises(TypeError, C) + class D(C): + @classmethod + def foo(cls): return super().foo() + self.assertEqual(D.foo(), 'D') + self.assertEqual(D().foo(), 'D') + + def test_abstractstaticmethod_basics(self): @staticmethod @abc.abstractmethod - def foo(): return 3 - self.assertRaises(TypeError, C) - class D(C): + def foo(): pass + self.assertTrue(foo.__isabstractmethod__) @staticmethod - def foo(): return 4 - self.assertEqual(D.foo(), 4) - self.assertEqual(D().foo(), 4) - - def test_abstractmethod_integration(self): - for abstractthing in [abc.abstractmethod, abc.abstractproperty, - abc.abstractclassmethod, - abc.abstractstaticmethod]: - class C(metaclass=abc.ABCMeta): - @abstractthing - def foo(self): pass # abstract - def bar(self): pass # concrete - self.assertEqual(C.__abstractmethods__, {"foo"}) - self.assertRaises(TypeError, C) # because foo is abstract - self.assertTrue(isabstract(C)) + def bar(): pass + self.assertFalse(getattr(bar, "__isabstractmethod__", False)) + + class C(metaclass=abc_ABCMeta): + @staticmethod + @abc.abstractmethod + def foo(): return 3 + self.assertRaises(TypeError, C) class D(C): - def bar(self): pass # concrete override of concrete - self.assertEqual(D.__abstractmethods__, {"foo"}) - self.assertRaises(TypeError, D) # because foo is still abstract - self.assertTrue(isabstract(D)) + @staticmethod + def foo(): return 4 + self.assertEqual(D.foo(), 4) + self.assertEqual(D().foo(), 4) + + def test_abstractmethod_integration(self): + for abstractthing in [abc.abstractmethod, abc.abstractproperty, + abc.abstractclassmethod, + abc.abstractstaticmethod]: + class C(metaclass=abc_ABCMeta): + @abstractthing + def foo(self): pass # abstract + def bar(self): pass # concrete + self.assertEqual(C.__abstractmethods__, {"foo"}) + self.assertRaises(TypeError, C) # because foo is abstract + self.assertTrue(isabstract(C)) + class D(C): + def bar(self): pass # concrete override of concrete + self.assertEqual(D.__abstractmethods__, {"foo"}) + self.assertRaises(TypeError, D) # because foo is still abstract + self.assertTrue(isabstract(D)) + class E(D): + def foo(self): pass + self.assertEqual(E.__abstractmethods__, set()) + E() # now foo is concrete, too + self.assertFalse(isabstract(E)) + class F(E): + @abstractthing + def bar(self): pass # abstract override of concrete + self.assertEqual(F.__abstractmethods__, {"bar"}) + self.assertRaises(TypeError, F) # because bar is abstract now + self.assertTrue(isabstract(F)) + + def test_descriptors_with_abstractmethod(self): + class C(metaclass=abc_ABCMeta): + @property + @abc.abstractmethod + def foo(self): return 3 + @foo.setter + @abc.abstractmethod + def foo(self, val): pass + self.assertRaises(TypeError, C) + class D(C): + @C.foo.getter + def foo(self): return super().foo + self.assertRaises(TypeError, D) class E(D): - def foo(self): pass - self.assertEqual(E.__abstractmethods__, set()) - E() # now foo is concrete, too - self.assertFalse(isabstract(E)) - class F(E): - @abstractthing - def bar(self): pass # abstract override of concrete - self.assertEqual(F.__abstractmethods__, {"bar"}) - self.assertRaises(TypeError, F) # because bar is abstract now - self.assertTrue(isabstract(F)) - - def test_descriptors_with_abstractmethod(self): - class C(metaclass=abc.ABCMeta): - @property - @abc.abstractmethod - def foo(self): return 3 - @foo.setter - @abc.abstractmethod - def foo(self, val): pass - self.assertRaises(TypeError, C) - class D(C): - @C.foo.getter - def foo(self): return super().foo - self.assertRaises(TypeError, D) - class E(D): - @D.foo.setter - def foo(self, val): pass - self.assertEqual(E().foo, 3) - # check that the property's __isabstractmethod__ descriptor does the - # right thing when presented with a value that fails truth testing: - class NotBool(object): - def __bool__(self): - raise ValueError() - __len__ = __bool__ - with self.assertRaises(ValueError): - class F(C): - def bar(self): + @D.foo.setter + def foo(self, val): pass + self.assertEqual(E().foo, 3) + # check that the property's __isabstractmethod__ descriptor does the + # right thing when presented with a value that fails truth testing: + class NotBool(object): + def __bool__(self): + raise ValueError() + __len__ = __bool__ + with self.assertRaises(ValueError): + class F(C): + def bar(self): + pass + bar.__isabstractmethod__ = NotBool() + foo = property(bar) + + + def test_customdescriptors_with_abstractmethod(self): + class Descriptor: + def __init__(self, fget, fset=None): + self._fget = fget + self._fset = fset + def getter(self, callable): + return Descriptor(callable, self._fget) + def setter(self, callable): + return Descriptor(self._fget, callable) + @property + def __isabstractmethod__(self): + return (getattr(self._fget, '__isabstractmethod__', False) + or getattr(self._fset, '__isabstractmethod__', False)) + class C(metaclass=abc_ABCMeta): + @Descriptor + @abc.abstractmethod + def foo(self): return 3 + @foo.setter + @abc.abstractmethod + def foo(self, val): pass + self.assertRaises(TypeError, C) + class D(C): + @C.foo.getter + def foo(self): return super().foo + self.assertRaises(TypeError, D) + class E(D): + @D.foo.setter + def foo(self, val): pass + self.assertFalse(E.foo.__isabstractmethod__) + + def test_metaclass_abc(self): + # Metaclasses can be ABCs, too. + class A(metaclass=abc_ABCMeta): + @abc.abstractmethod + def x(self): pass - bar.__isabstractmethod__ = NotBool() - foo = property(bar) - - - def test_customdescriptors_with_abstractmethod(self): - class Descriptor: - def __init__(self, fget, fset=None): - self._fget = fget - self._fset = fset - def getter(self, callable): - return Descriptor(callable, self._fget) - def setter(self, callable): - return Descriptor(self._fget, callable) - @property - def __isabstractmethod__(self): - return (getattr(self._fget, '__isabstractmethod__', False) - or getattr(self._fset, '__isabstractmethod__', False)) - class C(metaclass=abc.ABCMeta): - @Descriptor - @abc.abstractmethod - def foo(self): return 3 - @foo.setter - @abc.abstractmethod - def foo(self, val): pass - self.assertRaises(TypeError, C) - class D(C): - @C.foo.getter - def foo(self): return super().foo - self.assertRaises(TypeError, D) - class E(D): - @D.foo.setter - def foo(self, val): pass - self.assertFalse(E.foo.__isabstractmethod__) - - def test_metaclass_abc(self): - # Metaclasses can be ABCs, too. - class A(metaclass=abc.ABCMeta): - @abc.abstractmethod - def x(self): + self.assertEqual(A.__abstractmethods__, {"x"}) + class meta(type, A): + def x(self): + return 1 + class C(metaclass=meta): + pass + + def test_registration_basics(self): + class A(metaclass=abc_ABCMeta): + pass + class B(object): + pass + b = B() + self.assertFalse(issubclass(B, A)) + self.assertFalse(issubclass(B, (A,))) + self.assertNotIsInstance(b, A) + self.assertNotIsInstance(b, (A,)) + B1 = A.register(B) + self.assertTrue(issubclass(B, A)) + self.assertTrue(issubclass(B, (A,))) + self.assertIsInstance(b, A) + self.assertIsInstance(b, (A,)) + self.assertIs(B1, B) + class C(B): + pass + c = C() + self.assertTrue(issubclass(C, A)) + self.assertTrue(issubclass(C, (A,))) + self.assertIsInstance(c, A) + self.assertIsInstance(c, (A,)) + + def test_register_as_class_deco(self): + class A(metaclass=abc_ABCMeta): + pass + @A.register + class B(object): + pass + b = B() + self.assertTrue(issubclass(B, A)) + self.assertTrue(issubclass(B, (A,))) + self.assertIsInstance(b, A) + self.assertIsInstance(b, (A,)) + @A.register + class C(B): + pass + c = C() + self.assertTrue(issubclass(C, A)) + self.assertTrue(issubclass(C, (A,))) + self.assertIsInstance(c, A) + self.assertIsInstance(c, (A,)) + self.assertIs(C, A.register(C)) + + def test_isinstance_invalidation(self): + class A(metaclass=abc_ABCMeta): + pass + class B: + pass + b = B() + self.assertFalse(isinstance(b, A)) + self.assertFalse(isinstance(b, (A,))) + token_old = abc_get_cache_token() + A.register(B) + token_new = abc_get_cache_token() + self.assertNotEqual(token_old, token_new) + self.assertTrue(isinstance(b, A)) + self.assertTrue(isinstance(b, (A,))) + + def test_registration_builtins(self): + class A(metaclass=abc_ABCMeta): + pass + A.register(int) + self.assertIsInstance(42, A) + self.assertIsInstance(42, (A,)) + self.assertTrue(issubclass(int, A)) + self.assertTrue(issubclass(int, (A,))) + class B(A): + pass + B.register(str) + class C(str): pass + self.assertIsInstance("", A) + self.assertIsInstance("", (A,)) + self.assertTrue(issubclass(str, A)) + self.assertTrue(issubclass(str, (A,))) + self.assertTrue(issubclass(C, A)) + self.assertTrue(issubclass(C, (A,))) + + def test_registration_edge_cases(self): + class A(metaclass=abc_ABCMeta): + pass + A.register(A) # should pass silently + class A1(A): + pass + self.assertRaises(RuntimeError, A1.register, A) # cycles not allowed + class B(object): + pass + A1.register(B) # ok + A1.register(B) # should pass silently + class C(A): + pass + A.register(C) # should pass silently + self.assertRaises(RuntimeError, C.register, A) # cycles not allowed + C.register(B) # ok + + def test_register_non_class(self): + class A(metaclass=abc_ABCMeta): + pass + self.assertRaisesRegex(TypeError, "Can only register classes", + A.register, 4) + + def test_registration_transitiveness(self): + class A(metaclass=abc_ABCMeta): + pass + self.assertTrue(issubclass(A, A)) + self.assertTrue(issubclass(A, (A,))) + class B(metaclass=abc_ABCMeta): + pass + self.assertFalse(issubclass(A, B)) + self.assertFalse(issubclass(A, (B,))) + self.assertFalse(issubclass(B, A)) + self.assertFalse(issubclass(B, (A,))) + class C(metaclass=abc_ABCMeta): + pass + A.register(B) + class B1(B): + pass + self.assertTrue(issubclass(B1, A)) + self.assertTrue(issubclass(B1, (A,))) + class C1(C): + pass + B1.register(C1) + self.assertFalse(issubclass(C, B)) + self.assertFalse(issubclass(C, (B,))) + self.assertFalse(issubclass(C, B1)) + self.assertFalse(issubclass(C, (B1,))) + self.assertTrue(issubclass(C1, A)) + self.assertTrue(issubclass(C1, (A,))) + self.assertTrue(issubclass(C1, B)) + self.assertTrue(issubclass(C1, (B,))) + self.assertTrue(issubclass(C1, B1)) + self.assertTrue(issubclass(C1, (B1,))) + C1.register(int) + class MyInt(int): + pass + self.assertTrue(issubclass(MyInt, A)) + self.assertTrue(issubclass(MyInt, (A,))) + self.assertIsInstance(42, A) + self.assertIsInstance(42, (A,)) + + def test_all_new_methods_are_called(self): + class A(metaclass=abc_ABCMeta): + pass + class B(object): + counter = 0 + def __new__(cls): + B.counter += 1 + return super().__new__(cls) + class C(A, B): + pass + self.assertEqual(B.counter, 0) + C() + self.assertEqual(B.counter, 1) + + def test_ABC_has___slots__(self): + self.assertTrue(hasattr(abc.ABC, '__slots__')) + + def test_tricky_new_works(self): + def with_metaclass(meta, *bases): + class metaclass(type): + def __new__(cls, name, this_bases, d): + return meta(name, bases, d) + return type.__new__(metaclass, 'temporary_class', (), {}) + class A: ... + class B: ... + class C(with_metaclass(abc_ABCMeta, A, B)): + pass + self.assertEqual(C.__class__, abc_ABCMeta) + + + class TestABCWithInitSubclass(unittest.TestCase): + def test_works_with_init_subclass(self): + class abc_ABC(metaclass=abc_ABCMeta): + __slots__ = () + saved_kwargs = {} + class ReceivesClassKwargs: + def __init_subclass__(cls, **kwargs): + super().__init_subclass__() + saved_kwargs.update(kwargs) + class Receiver(ReceivesClassKwargs, abc_ABC, x=1, y=2, z=3): pass - self.assertEqual(A.__abstractmethods__, {"x"}) - class meta(type, A): - def x(self): - return 1 - class C(metaclass=meta): - pass - - def test_registration_basics(self): - class A(metaclass=abc.ABCMeta): - pass - class B(object): - pass - b = B() - self.assertFalse(issubclass(B, A)) - self.assertFalse(issubclass(B, (A,))) - self.assertNotIsInstance(b, A) - self.assertNotIsInstance(b, (A,)) - B1 = A.register(B) - self.assertTrue(issubclass(B, A)) - self.assertTrue(issubclass(B, (A,))) - self.assertIsInstance(b, A) - self.assertIsInstance(b, (A,)) - self.assertIs(B1, B) - class C(B): - pass - c = C() - self.assertTrue(issubclass(C, A)) - self.assertTrue(issubclass(C, (A,))) - self.assertIsInstance(c, A) - self.assertIsInstance(c, (A,)) - - def test_register_as_class_deco(self): - class A(metaclass=abc.ABCMeta): - pass - @A.register - class B(object): - pass - b = B() - self.assertTrue(issubclass(B, A)) - self.assertTrue(issubclass(B, (A,))) - self.assertIsInstance(b, A) - self.assertIsInstance(b, (A,)) - @A.register - class C(B): - pass - c = C() - self.assertTrue(issubclass(C, A)) - self.assertTrue(issubclass(C, (A,))) - self.assertIsInstance(c, A) - self.assertIsInstance(c, (A,)) - self.assertIs(C, A.register(C)) - - def test_isinstance_invalidation(self): - class A(metaclass=abc.ABCMeta): - pass - class B: - pass - b = B() - self.assertFalse(isinstance(b, A)) - self.assertFalse(isinstance(b, (A,))) - token_old = abc.get_cache_token() - A.register(B) - token_new = abc.get_cache_token() - self.assertNotEqual(token_old, token_new) - self.assertTrue(isinstance(b, A)) - self.assertTrue(isinstance(b, (A,))) - - def test_registration_builtins(self): - class A(metaclass=abc.ABCMeta): - pass - A.register(int) - self.assertIsInstance(42, A) - self.assertIsInstance(42, (A,)) - self.assertTrue(issubclass(int, A)) - self.assertTrue(issubclass(int, (A,))) - class B(A): - pass - B.register(str) - class C(str): pass - self.assertIsInstance("", A) - self.assertIsInstance("", (A,)) - self.assertTrue(issubclass(str, A)) - self.assertTrue(issubclass(str, (A,))) - self.assertTrue(issubclass(C, A)) - self.assertTrue(issubclass(C, (A,))) - - def test_registration_edge_cases(self): - class A(metaclass=abc.ABCMeta): - pass - A.register(A) # should pass silently - class A1(A): - pass - self.assertRaises(RuntimeError, A1.register, A) # cycles not allowed - class B(object): - pass - A1.register(B) # ok - A1.register(B) # should pass silently - class C(A): - pass - A.register(C) # should pass silently - self.assertRaises(RuntimeError, C.register, A) # cycles not allowed - C.register(B) # ok - - def test_register_non_class(self): - class A(metaclass=abc.ABCMeta): - pass - self.assertRaisesRegex(TypeError, "Can only register classes", - A.register, 4) - - def test_registration_transitiveness(self): - class A(metaclass=abc.ABCMeta): - pass - self.assertTrue(issubclass(A, A)) - self.assertTrue(issubclass(A, (A,))) - class B(metaclass=abc.ABCMeta): - pass - self.assertFalse(issubclass(A, B)) - self.assertFalse(issubclass(A, (B,))) - self.assertFalse(issubclass(B, A)) - self.assertFalse(issubclass(B, (A,))) - class C(metaclass=abc.ABCMeta): - pass - A.register(B) - class B1(B): - pass - self.assertTrue(issubclass(B1, A)) - self.assertTrue(issubclass(B1, (A,))) - class C1(C): - pass - B1.register(C1) - self.assertFalse(issubclass(C, B)) - self.assertFalse(issubclass(C, (B,))) - self.assertFalse(issubclass(C, B1)) - self.assertFalse(issubclass(C, (B1,))) - self.assertTrue(issubclass(C1, A)) - self.assertTrue(issubclass(C1, (A,))) - self.assertTrue(issubclass(C1, B)) - self.assertTrue(issubclass(C1, (B,))) - self.assertTrue(issubclass(C1, B1)) - self.assertTrue(issubclass(C1, (B1,))) - C1.register(int) - class MyInt(int): - pass - self.assertTrue(issubclass(MyInt, A)) - self.assertTrue(issubclass(MyInt, (A,))) - self.assertIsInstance(42, A) - self.assertIsInstance(42, (A,)) - - def test_all_new_methods_are_called(self): - class A(metaclass=abc.ABCMeta): - pass - class B(object): - counter = 0 - def __new__(cls): - B.counter += 1 - return super().__new__(cls) - class C(A, B): - pass - self.assertEqual(B.counter, 0) - C() - self.assertEqual(B.counter, 1) - - def test_ABC_has___slots__(self): - self.assertTrue(hasattr(abc.ABC, '__slots__')) - - -class TestABCWithInitSubclass(unittest.TestCase): - def test_works_with_init_subclass(self): - saved_kwargs = {} - class ReceivesClassKwargs: - def __init_subclass__(cls, **kwargs): - super().__init_subclass__() - saved_kwargs.update(kwargs) - class Receiver(ReceivesClassKwargs, abc.ABC, x=1, y=2, z=3): - pass - self.assertEqual(saved_kwargs, dict(x=1, y=2, z=3)) + self.assertEqual(saved_kwargs, dict(x=1, y=2, z=3)) + return TestLegacyAPI, TestABC, TestABCWithInitSubclass +TestLegacyAPI_Py, TestABC_Py, TestABCWithInitSubclass_Py = test_factory(abc.ABCMeta, + abc.get_cache_token) +TestLegacyAPI_C, TestABC_C, TestABCWithInitSubclass_C = test_factory(_py_abc.ABCMeta, + _py_abc.get_cache_token) if __name__ == "__main__": unittest.main() diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 3f24faf37629..f56caa13a295 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -761,8 +761,8 @@ class C(collections.abc.Mapping, Generic[T]): ... self.assertIsInstance(1, C) C[int] self.assertIsInstance(1, C) - C._abc_registry.clear() - C._abc_cache.clear() # To keep refleak hunting mode clean + C._abc_registry_clear() + C._abc_caches_clear() # To keep refleak hunting mode clean def test_false_subclasses(self): class MyMapping(MutableMapping[str, str]): pass diff --git a/Misc/NEWS.d/next/Library/2018-02-15-08-18-52.bpo-31333.4fF-gM.rst b/Misc/NEWS.d/next/Library/2018-02-15-08-18-52.bpo-31333.4fF-gM.rst new file mode 100644 index 000000000000..63fc72a5c11b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-15-08-18-52.bpo-31333.4fF-gM.rst @@ -0,0 +1,10 @@ +``_abc`` module is added. It is a speedup module with C implementations for +various functions and methods in ``abc``. Creating an ABC subclass and calling +``isinstance`` or ``issubclass`` with an ABC subclass are up to 1.5x faster. +In addition, this makes Python start-up up to 10% faster. + +Note that the new implementation hides internal registry and caches, previously +accessible via private attributes ``_abc_registry``, ``_abc_cache``, and +``_abc_negative_cache``. There are three debugging helper methods that can be +used instead ``_dump_registry``, ``_abc_registry_clear``, and +``_abc_caches_clear``. diff --git a/Modules/Setup.dist b/Modules/Setup.dist index 4b463b28d672..a833774a1538 100644 --- a/Modules/Setup.dist +++ b/Modules/Setup.dist @@ -114,6 +114,7 @@ _weakref _weakref.c # weak references _functools _functoolsmodule.c # Tools for working with functions and callable objects _operator _operator.c # operator.add() and similar goodies _collections _collectionsmodule.c # Container types +_abc _abc.c # Abstract base classes itertools itertoolsmodule.c # Functions creating iterators for efficient looping atexit atexitmodule.c # Register functions to be run at interpreter-shutdown _signal signalmodule.c diff --git a/Modules/_abc.c b/Modules/_abc.c new file mode 100644 index 000000000000..504e23d9a74d --- /dev/null +++ b/Modules/_abc.c @@ -0,0 +1,822 @@ +/* ABCMeta implementation */ + +#include "Python.h" +#include "structmember.h" +#include "clinic/_abc.c.h" + +/*[clinic input] +module _abc +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=964f5328e1aefcda]*/ + +PyDoc_STRVAR(_abc__doc__, +"Module contains faster C implementation of abc.ABCMeta"); + +_Py_IDENTIFIER(__abstractmethods__); +_Py_IDENTIFIER(__class__); +_Py_IDENTIFIER(__dict__); +_Py_IDENTIFIER(__bases__); +_Py_IDENTIFIER(_abc_impl); +_Py_IDENTIFIER(__subclasscheck__); +_Py_IDENTIFIER(__subclasshook__); + +/* A global counter that is incremented each time a class is + registered as a virtual subclass of anything. It forces the + negative cache to be cleared before its next use. + Note: this counter is private. Use `abc.get_cache_token()` for + external code. */ +static unsigned long long abc_invalidation_counter = 0; + +/* This object stores internal state for ABCs. + Note that we can use normal sets for caches, + since they are never iterated over. */ +typedef struct { + PyObject_HEAD + PyObject *_abc_registry; + PyObject *_abc_cache; /* Normal set of weak references. */ + PyObject *_abc_negative_cache; /* Normal set of weak references. */ + unsigned long long _abc_negative_cache_version; +} _abc_data; + +static void +abc_data_dealloc(_abc_data *self) +{ + Py_XDECREF(self->_abc_registry); + Py_XDECREF(self->_abc_cache); + Py_XDECREF(self->_abc_negative_cache); + Py_TYPE(self)->tp_free(self); +} + +static PyObject * +abc_data_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + _abc_data *self = (_abc_data *) type->tp_alloc(type, 0); + if (self == NULL) { + return NULL; + } + + self->_abc_registry = NULL; + self->_abc_cache = NULL; + self->_abc_negative_cache = NULL; + self->_abc_negative_cache_version = abc_invalidation_counter; + return (PyObject *) self; +} + +PyDoc_STRVAR(abc_data_doc, +"Internal state held by ABC machinery."); + +static PyTypeObject _abc_data_type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "_abc_data", /*tp_name*/ + sizeof(_abc_data), /*tp_size*/ + .tp_dealloc = (destructor)abc_data_dealloc, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_alloc = PyType_GenericAlloc, + .tp_new = abc_data_new, +}; + +static _abc_data * +_get_impl(PyObject *self) +{ + PyObject *impl = _PyObject_GetAttrId(self, &PyId__abc_impl); + if (impl == NULL) { + return NULL; + } + if (Py_TYPE(impl) != &_abc_data_type) { + PyErr_SetString(PyExc_TypeError, "_abc_impl is set to a wrong type"); + Py_DECREF(impl); + return NULL; + } + return (_abc_data *)impl; +} + +static int +_in_weak_set(PyObject *set, PyObject *obj) +{ + if (set == NULL || PySet_GET_SIZE(set) == 0) { + return 0; + } + PyObject *ref = PyWeakref_NewRef(obj, NULL); + if (ref == NULL) { + if (PyErr_ExceptionMatches(PyExc_TypeError)) { + PyErr_Clear(); + return 0; + } + return -1; + } + int res = PySet_Contains(set, ref); + Py_DECREF(ref); + return res; +} + +static PyObject * +_destroy(PyObject *setweakref, PyObject *objweakref) +{ + PyObject *set; + set = PyWeakref_GET_OBJECT(setweakref); + if (set == Py_None) { + Py_RETURN_NONE; + } + Py_INCREF(set); + if (PySet_Discard(set, objweakref) < 0) { + Py_DECREF(set); + return NULL; + } + Py_DECREF(set); + Py_RETURN_NONE; +} + +static PyMethodDef _destroy_def = { + "_destroy", (PyCFunction) _destroy, METH_O +}; + +static int +_add_to_weak_set(PyObject **pset, PyObject *obj) +{ + if (*pset == NULL) { + *pset = PySet_New(NULL); + if (*pset == NULL) { + return -1; + } + } + + PyObject *set = *pset; + PyObject *ref, *wr; + PyObject *destroy_cb; + wr = PyWeakref_NewRef(set, NULL); + if (wr == NULL) { + return -1; + } + destroy_cb = PyCFunction_NewEx(&_destroy_def, wr, NULL); + if (destroy_cb == NULL) { + Py_DECREF(wr); + return -1; + } + ref = PyWeakref_NewRef(obj, destroy_cb); + Py_DECREF(destroy_cb); + if (ref == NULL) { + Py_DECREF(wr); + return -1; + } + int ret = PySet_Add(set, ref); + Py_DECREF(wr); + Py_DECREF(ref); + return ret; +} + +/*[clinic input] +_abc._reset_registry + + self: object + / + +Internal ABC helper to reset registry of a given class. + +Should be only used by refleak.py +[clinic start generated code]*/ + +static PyObject * +_abc__reset_registry(PyObject *module, PyObject *self) +/*[clinic end generated code: output=92d591a43566cc10 input=12a0b7eb339ac35c]*/ +{ + _abc_data *impl = _get_impl(self); + if (impl == NULL) { + return NULL; + } + if (impl->_abc_registry != NULL && PySet_Clear(impl->_abc_registry) < 0) { + Py_DECREF(impl); + return NULL; + } + Py_DECREF(impl); + Py_RETURN_NONE; +} + +/*[clinic input] +_abc._reset_caches + + self: object + / + +Internal ABC helper to reset both caches of a given class. + +Should be only used by refleak.py +[clinic start generated code]*/ + +static PyObject * +_abc__reset_caches(PyObject *module, PyObject *self) +/*[clinic end generated code: output=f296f0d5c513f80c input=c0ac616fd8acfb6f]*/ +{ + _abc_data *impl = _get_impl(self); + if (impl == NULL) { + return NULL; + } + if (impl->_abc_cache != NULL && PySet_Clear(impl->_abc_cache) < 0) { + Py_DECREF(impl); + return NULL; + } + /* also the second cache */ + if (impl->_abc_negative_cache != NULL && + PySet_Clear(impl->_abc_negative_cache) < 0) { + Py_DECREF(impl); + return NULL; + } + Py_DECREF(impl); + Py_RETURN_NONE; +} + +/*[clinic input] +_abc._get_dump + + self: object + / + +Internal ABC helper for cache and registry debugging. + +Return shallow copies of registry, of both caches, and +negative cache version. Don't call this function directly, +instead use ABC._dump_registry() for a nice repr. +[clinic start generated code]*/ + +static PyObject * +_abc__get_dump(PyObject *module, PyObject *self) +/*[clinic end generated code: output=9d9569a8e2c1c443 input=2c5deb1bfe9e3c79]*/ +{ + _abc_data *impl = _get_impl(self); + if (impl == NULL) { + return NULL; + } + PyObject *res = Py_BuildValue("NNNK", + PySet_New(impl->_abc_registry), + PySet_New(impl->_abc_cache), + PySet_New(impl->_abc_negative_cache), + impl->_abc_negative_cache_version); + Py_DECREF(impl); + return res; +} + +// Compute set of abstract method names. +static int +compute_abstract_methods(PyObject *self) +{ + int ret = -1; + PyObject *abstracts = PyFrozenSet_New(NULL); + if (abstracts == NULL) { + return -1; + } + + PyObject *ns = NULL, *items = NULL, *bases = NULL; // Py_XDECREF()ed on error. + + /* Stage 1: direct abstract methods. */ + ns = _PyObject_GetAttrId(self, &PyId___dict__); + if (!ns) { + goto error; + } + + // We can't use PyDict_Next(ns) even when ns is dict because + // _PyObject_IsAbstract() can mutate ns. + items = PyMapping_Items(ns); + if (!items) { + goto error; + } + assert(PyList_Check(items)); + for (Py_ssize_t pos = 0; pos < PyList_GET_SIZE(items); pos++) { + PyObject *it = PySequence_Fast( + PyList_GET_ITEM(items, pos), + "items() returned non-iterable"); + if (!it) { + goto error; + } + if (PySequence_Fast_GET_SIZE(it) != 2) { + PyErr_SetString(PyExc_TypeError, + "items() returned item which size is not 2"); + Py_DECREF(it); + goto error; + } + + // borrowed + PyObject *key = PySequence_Fast_GET_ITEM(it, 0); + PyObject *value = PySequence_Fast_GET_ITEM(it, 1); + // items or it may be cleared while accessing __abstractmethod__ + // So we need to keep strong reference for key + Py_INCREF(key); + int is_abstract = _PyObject_IsAbstract(value); + if (is_abstract < 0 || + (is_abstract && PySet_Add(abstracts, key) < 0)) { + Py_DECREF(it); + Py_DECREF(key); + goto error; + } + Py_DECREF(key); + Py_DECREF(it); + } + + /* Stage 2: inherited abstract methods. */ + bases = _PyObject_GetAttrId(self, &PyId___bases__); + if (!bases) { + goto error; + } + if (!PyTuple_Check(bases)) { + PyErr_SetString(PyExc_TypeError, "__bases__ is not tuple"); + goto error; + } + + for (Py_ssize_t pos = 0; pos < PyTuple_GET_SIZE(bases); pos++) { + PyObject *item = PyTuple_GET_ITEM(bases, pos); // borrowed + PyObject *base_abstracts, *iter; + + if (_PyObject_LookupAttrId(item, &PyId___abstractmethods__, + &base_abstracts) < 0) { + goto error; + } + if (base_abstracts == NULL) { + continue; + } + if (!(iter = PyObject_GetIter(base_abstracts))) { + Py_DECREF(base_abstracts); + goto error; + } + Py_DECREF(base_abstracts); + PyObject *key, *value; + while ((key = PyIter_Next(iter))) { + if (_PyObject_LookupAttr(self, key, &value) < 0) { + Py_DECREF(key); + Py_DECREF(iter); + goto error; + } + if (value == NULL) { + Py_DECREF(key); + continue; + } + + int is_abstract = _PyObject_IsAbstract(value); + Py_DECREF(value); + if (is_abstract < 0 || + (is_abstract && PySet_Add(abstracts, key) < 0)) + { + Py_DECREF(key); + Py_DECREF(iter); + goto error; + } + Py_DECREF(key); + } + Py_DECREF(iter); + if (PyErr_Occurred()) { + goto error; + } + } + + if (_PyObject_SetAttrId(self, &PyId___abstractmethods__, abstracts) < 0) { + goto error; + } + + ret = 0; +error: + Py_DECREF(abstracts); + Py_XDECREF(ns); + Py_XDECREF(items); + Py_XDECREF(bases); + return ret; +} + +/*[clinic input] +_abc._abc_init + + self: object + / + +Internal ABC helper for class set-up. Should be never used outside abc module. +[clinic start generated code]*/ + +static PyObject * +_abc__abc_init(PyObject *module, PyObject *self) +/*[clinic end generated code: output=594757375714cda1 input=8d7fe470ff77f029]*/ +{ + PyObject *data; + if (compute_abstract_methods(self) < 0) { + return NULL; + } + + /* Set up inheritance registry. */ + data = abc_data_new(&_abc_data_type, NULL, NULL); + if (data == NULL) { + return NULL; + } + if (_PyObject_SetAttrId(self, &PyId__abc_impl, data) < 0) { + Py_DECREF(data); + return NULL; + } + Py_DECREF(data); + Py_RETURN_NONE; +} + +/*[clinic input] +_abc._abc_register + + self: object + subclass: object + / + +Internal ABC helper for subclasss registration. Should be never used outside abc module. +[clinic start generated code]*/ + +static PyObject * +_abc__abc_register_impl(PyObject *module, PyObject *self, PyObject *subclass) +/*[clinic end generated code: output=7851e7668c963524 input=ca589f8c3080e67f]*/ +{ + if (!PyType_Check(subclass)) { + PyErr_SetString(PyExc_TypeError, "Can only register classes"); + return NULL; + } + int result = PyObject_IsSubclass(subclass, self); + if (result > 0) { + Py_INCREF(subclass); + return subclass; /* Already a subclass. */ + } + if (result < 0) { + return NULL; + } + /* Subtle: test for cycles *after* testing for "already a subclass"; + this means we allow X.register(X) and interpret it as a no-op. */ + result = PyObject_IsSubclass(self, subclass); + if (result > 0) { + /* This would create a cycle, which is bad for the algorithm below. */ + PyErr_SetString(PyExc_RuntimeError, "Refusing to create an inheritance cycle"); + return NULL; + } + if (result < 0) { + return NULL; + } + _abc_data *impl = _get_impl(self); + if (impl == NULL) { + return NULL; + } + if (_add_to_weak_set(&impl->_abc_registry, subclass) < 0) { + Py_DECREF(impl); + return NULL; + } + Py_DECREF(impl); + + /* Invalidate negative cache */ + abc_invalidation_counter++; + + Py_INCREF(subclass); + return subclass; +} + + +/*[clinic input] +_abc._abc_instancecheck + + self: object + instance: object + / + +Internal ABC helper for instance checks. Should be never used outside abc module. +[clinic start generated code]*/ + +static PyObject * +_abc__abc_instancecheck_impl(PyObject *module, PyObject *self, + PyObject *instance) +/*[clinic end generated code: output=b8b5148f63b6b56f input=a4f4525679261084]*/ +{ + PyObject *subtype, *result = NULL, *subclass = NULL; + _abc_data *impl = _get_impl(self); + if (impl == NULL) { + return NULL; + } + + subclass = _PyObject_GetAttrId(instance, &PyId___class__); + if (subclass == NULL) { + Py_DECREF(impl); + return NULL; + } + /* Inline the cache checking. */ + int incache = _in_weak_set(impl->_abc_cache, subclass); + if (incache < 0) { + goto end; + } + if (incache > 0) { + result = Py_True; + Py_INCREF(result); + goto end; + } + subtype = (PyObject *)Py_TYPE(instance); + if (subtype == subclass) { + if (impl->_abc_negative_cache_version == abc_invalidation_counter) { + incache = _in_weak_set(impl->_abc_negative_cache, subclass); + if (incache < 0) { + goto end; + } + if (incache > 0) { + result = Py_False; + Py_INCREF(result); + goto end; + } + } + /* Fall back to the subclass check. */ + result = _PyObject_CallMethodIdObjArgs(self, &PyId___subclasscheck__, + subclass, NULL); + goto end; + } + result = _PyObject_CallMethodIdObjArgs(self, &PyId___subclasscheck__, + subclass, NULL); + if (result == NULL) { + goto end; + } + + switch (PyObject_IsTrue(result)) { + case -1: + Py_DECREF(result); + result = NULL; + break; + case 0: + Py_DECREF(result); + result = _PyObject_CallMethodIdObjArgs(self, &PyId___subclasscheck__, + subtype, NULL); + break; + case 1: // Nothing to do. + break; + default: + Py_UNREACHABLE(); + } + +end: + Py_XDECREF(impl); + Py_XDECREF(subclass); + return result; +} + + +// Return -1 when exception occured. +// Return 1 when result is set. +// Return 0 otherwise. +static int subclasscheck_check_registry(_abc_data *impl, PyObject *subclass, + PyObject **result); + +/*[clinic input] +_abc._abc_subclasscheck + + self: object + subclass: object + / + +Internal ABC helper for subclasss checks. Should be never used outside abc module. +[clinic start generated code]*/ + +static PyObject * +_abc__abc_subclasscheck_impl(PyObject *module, PyObject *self, + PyObject *subclass) +/*[clinic end generated code: output=b56c9e4a530e3894 input=1d947243409d10b8]*/ +{ + PyObject *ok, *mro, *subclasses = NULL, *result = NULL; + Py_ssize_t pos; + int incache; + _abc_data *impl = _get_impl(self); + if (impl == NULL) { + return NULL; + } + + /* 1. Check cache. */ + incache = _in_weak_set(impl->_abc_cache, subclass); + if (incache < 0) { + goto end; + } + if (incache > 0) { + result = Py_True; + goto end; + } + + /* 2. Check negative cache; may have to invalidate. */ + if (impl->_abc_negative_cache_version < abc_invalidation_counter) { + /* Invalidate the negative cache. */ + if (impl->_abc_negative_cache != NULL && + PySet_Clear(impl->_abc_negative_cache) < 0) + { + goto end; + } + impl->_abc_negative_cache_version = abc_invalidation_counter; + } + else { + incache = _in_weak_set(impl->_abc_negative_cache, subclass); + if (incache < 0) { + goto end; + } + if (incache > 0) { + result = Py_False; + goto end; + } + } + + /* 3. Check the subclass hook. */ + ok = _PyObject_CallMethodIdObjArgs((PyObject *)self, &PyId___subclasshook__, + subclass, NULL); + if (ok == NULL) { + goto end; + } + if (ok == Py_True) { + Py_DECREF(ok); + if (_add_to_weak_set(&impl->_abc_cache, subclass) < 0) { + goto end; + } + result = Py_True; + goto end; + } + if (ok == Py_False) { + Py_DECREF(ok); + if (_add_to_weak_set(&impl->_abc_negative_cache, subclass) < 0) { + goto end; + } + result = Py_False; + goto end; + } + if (ok != Py_NotImplemented) { + Py_DECREF(ok); + PyErr_SetString(PyExc_AssertionError, "__subclasshook__ must return either" + " False, True, or NotImplemented"); + goto end; + } + Py_DECREF(ok); + + /* 4. Check if it's a direct subclass. */ + mro = ((PyTypeObject *)subclass)->tp_mro; + assert(PyTuple_Check(mro)); + for (pos = 0; pos < PyTuple_GET_SIZE(mro); pos++) { + PyObject *mro_item = PyTuple_GET_ITEM(mro, pos); + if (mro_item == NULL) { + goto end; + } + if ((PyObject *)self == mro_item) { + if (_add_to_weak_set(&impl->_abc_cache, subclass) < 0) { + goto end; + } + result = Py_True; + goto end; + } + } + + /* 5. Check if it's a subclass of a registered class (recursive). */ + if (subclasscheck_check_registry(impl, subclass, &result)) { + // Exception occured or result is set. + goto end; + } + + /* 6. Check if it's a subclass of a subclass (recursive). */ + subclasses = PyObject_CallMethod(self, "__subclasses__", NULL); + if (!PyList_Check(subclasses)) { + PyErr_SetString(PyExc_TypeError, "__subclasses__() must return a list"); + goto end; + } + for (pos = 0; pos < PyList_GET_SIZE(subclasses); pos++) { + PyObject *scls = PyList_GET_ITEM(subclasses, pos); + Py_INCREF(scls); + int r = PyObject_IsSubclass(subclass, scls); + Py_DECREF(scls); + if (r > 0) { + if (_add_to_weak_set(&impl->_abc_cache, subclass) < 0) { + goto end; + } + result = Py_True; + goto end; + } + if (r < 0) { + goto end; + } + } + + /* No dice; update negative cache. */ + if (_add_to_weak_set(&impl->_abc_negative_cache, subclass) < 0) { + goto end; + } + result = Py_False; + +end: + Py_XDECREF(impl); + Py_XDECREF(subclasses); + Py_XINCREF(result); + return result; +} + + +static int +subclasscheck_check_registry(_abc_data *impl, PyObject *subclass, + PyObject **result) +{ + // Fast path: check subclass is in weakref directly. + int ret = _in_weak_set(impl->_abc_registry, subclass); + if (ret < 0) { + *result = NULL; + return -1; + } + if (ret > 0) { + *result = Py_True; + return 1; + } + + if (impl->_abc_registry == NULL) { + return 0; + } + Py_ssize_t registry_size = PySet_Size(impl->_abc_registry); + if (registry_size == 0) { + return 0; + } + // Weakref callback may remove entry from set. + // So we take snapshot of registry first. + PyObject **copy = PyMem_Malloc(sizeof(PyObject*) * registry_size); + PyObject *key; + Py_ssize_t pos = 0; + Py_hash_t hash; + Py_ssize_t i = 0; + + while (_PySet_NextEntry(impl->_abc_registry, &pos, &key, &hash)) { + Py_INCREF(key); + copy[i++] = key; + } + assert(i == registry_size); + + for (i = 0; i < registry_size; i++) { + PyObject *rkey = PyWeakref_GetObject(copy[i]); + if (rkey == NULL) { + // Someone inject non-weakref type in the registry. + ret = -1; + break; + } + if (rkey == Py_None) { + continue; + } + Py_INCREF(rkey); + int r = PyObject_IsSubclass(subclass, rkey); + Py_DECREF(rkey); + if (r < 0) { + ret = -1; + break; + } + if (r > 0) { + if (_add_to_weak_set(&impl->_abc_cache, subclass) < 0) { + ret = -1; + break; + } + *result = Py_True; + ret = 1; + break; + } + } + + for (i = 0; i < registry_size; i++) { + Py_DECREF(copy[i]); + } + PyMem_Free(copy); + return ret; +} + +/*[clinic input] +_abc.get_cache_token + +Returns the current ABC cache token. + +The token is an opaque object (supporting equality testing) identifying the +current version of the ABC cache for virtual subclasses. The token changes +with every call to register() on any ABC. +[clinic start generated code]*/ + +static PyObject * +_abc_get_cache_token_impl(PyObject *module) +/*[clinic end generated code: output=c7d87841e033dacc input=70413d1c423ad9f9]*/ +{ + return PyLong_FromUnsignedLongLong(abc_invalidation_counter); +} + +static struct PyMethodDef module_functions[] = { + _ABC_GET_CACHE_TOKEN_METHODDEF + _ABC__ABC_INIT_METHODDEF + _ABC__RESET_REGISTRY_METHODDEF + _ABC__RESET_CACHES_METHODDEF + _ABC__GET_DUMP_METHODDEF + _ABC__ABC_REGISTER_METHODDEF + _ABC__ABC_INSTANCECHECK_METHODDEF + _ABC__ABC_SUBCLASSCHECK_METHODDEF + {NULL, NULL} /* sentinel */ +}; + +static struct PyModuleDef _abcmodule = { + PyModuleDef_HEAD_INIT, + "_abc", + _abc__doc__, + -1, + module_functions, + NULL, + NULL, + NULL, + NULL +}; + + +PyMODINIT_FUNC +PyInit__abc(void) +{ + if (PyType_Ready(&_abc_data_type) < 0) { + return NULL; + } + _abc_data_type.tp_doc = abc_data_doc; + + return PyModule_Create(&_abcmodule); +} diff --git a/Modules/clinic/_abc.c.h b/Modules/clinic/_abc.c.h new file mode 100644 index 000000000000..b1ec371d1551 --- /dev/null +++ b/Modules/clinic/_abc.c.h @@ -0,0 +1,162 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +PyDoc_STRVAR(_abc__reset_registry__doc__, +"_reset_registry($module, self, /)\n" +"--\n" +"\n" +"Internal ABC helper to reset registry of a given class.\n" +"\n" +"Should be only used by refleak.py"); + +#define _ABC__RESET_REGISTRY_METHODDEF \ + {"_reset_registry", (PyCFunction)_abc__reset_registry, METH_O, _abc__reset_registry__doc__}, + +PyDoc_STRVAR(_abc__reset_caches__doc__, +"_reset_caches($module, self, /)\n" +"--\n" +"\n" +"Internal ABC helper to reset both caches of a given class.\n" +"\n" +"Should be only used by refleak.py"); + +#define _ABC__RESET_CACHES_METHODDEF \ + {"_reset_caches", (PyCFunction)_abc__reset_caches, METH_O, _abc__reset_caches__doc__}, + +PyDoc_STRVAR(_abc__get_dump__doc__, +"_get_dump($module, self, /)\n" +"--\n" +"\n" +"Internal ABC helper for cache and registry debugging.\n" +"\n" +"Return shallow copies of registry, of both caches, and\n" +"negative cache version. Don\'t call this function directly,\n" +"instead use ABC._dump_registry() for a nice repr."); + +#define _ABC__GET_DUMP_METHODDEF \ + {"_get_dump", (PyCFunction)_abc__get_dump, METH_O, _abc__get_dump__doc__}, + +PyDoc_STRVAR(_abc__abc_init__doc__, +"_abc_init($module, self, /)\n" +"--\n" +"\n" +"Internal ABC helper for class set-up. Should be never used outside abc module."); + +#define _ABC__ABC_INIT_METHODDEF \ + {"_abc_init", (PyCFunction)_abc__abc_init, METH_O, _abc__abc_init__doc__}, + +PyDoc_STRVAR(_abc__abc_register__doc__, +"_abc_register($module, self, subclass, /)\n" +"--\n" +"\n" +"Internal ABC helper for subclasss registration. Should be never used outside abc module."); + +#define _ABC__ABC_REGISTER_METHODDEF \ + {"_abc_register", (PyCFunction)_abc__abc_register, METH_FASTCALL, _abc__abc_register__doc__}, + +static PyObject * +_abc__abc_register_impl(PyObject *module, PyObject *self, PyObject *subclass); + +static PyObject * +_abc__abc_register(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *self; + PyObject *subclass; + + if (!_PyArg_UnpackStack(args, nargs, "_abc_register", + 2, 2, + &self, &subclass)) { + goto exit; + } + return_value = _abc__abc_register_impl(module, self, subclass); + +exit: + return return_value; +} + +PyDoc_STRVAR(_abc__abc_instancecheck__doc__, +"_abc_instancecheck($module, self, instance, /)\n" +"--\n" +"\n" +"Internal ABC helper for instance checks. Should be never used outside abc module."); + +#define _ABC__ABC_INSTANCECHECK_METHODDEF \ + {"_abc_instancecheck", (PyCFunction)_abc__abc_instancecheck, METH_FASTCALL, _abc__abc_instancecheck__doc__}, + +static PyObject * +_abc__abc_instancecheck_impl(PyObject *module, PyObject *self, + PyObject *instance); + +static PyObject * +_abc__abc_instancecheck(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *self; + PyObject *instance; + + if (!_PyArg_UnpackStack(args, nargs, "_abc_instancecheck", + 2, 2, + &self, &instance)) { + goto exit; + } + return_value = _abc__abc_instancecheck_impl(module, self, instance); + +exit: + return return_value; +} + +PyDoc_STRVAR(_abc__abc_subclasscheck__doc__, +"_abc_subclasscheck($module, self, subclass, /)\n" +"--\n" +"\n" +"Internal ABC helper for subclasss checks. Should be never used outside abc module."); + +#define _ABC__ABC_SUBCLASSCHECK_METHODDEF \ + {"_abc_subclasscheck", (PyCFunction)_abc__abc_subclasscheck, METH_FASTCALL, _abc__abc_subclasscheck__doc__}, + +static PyObject * +_abc__abc_subclasscheck_impl(PyObject *module, PyObject *self, + PyObject *subclass); + +static PyObject * +_abc__abc_subclasscheck(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject *self; + PyObject *subclass; + + if (!_PyArg_UnpackStack(args, nargs, "_abc_subclasscheck", + 2, 2, + &self, &subclass)) { + goto exit; + } + return_value = _abc__abc_subclasscheck_impl(module, self, subclass); + +exit: + return return_value; +} + +PyDoc_STRVAR(_abc_get_cache_token__doc__, +"get_cache_token($module, /)\n" +"--\n" +"\n" +"Returns the current ABC cache token.\n" +"\n" +"The token is an opaque object (supporting equality testing) identifying the\n" +"current version of the ABC cache for virtual subclasses. The token changes\n" +"with every call to register() on any ABC."); + +#define _ABC_GET_CACHE_TOKEN_METHODDEF \ + {"get_cache_token", (PyCFunction)_abc_get_cache_token, METH_NOARGS, _abc_get_cache_token__doc__}, + +static PyObject * +_abc_get_cache_token_impl(PyObject *module); + +static PyObject * +_abc_get_cache_token(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _abc_get_cache_token_impl(module); +} +/*[clinic end generated code: output=9d6f861a8f45bc6f input=a9049054013a1b77]*/ diff --git a/PC/config.c b/PC/config.c index 0c08bfeaa0dc..568a0fa9a467 100644 --- a/PC/config.c +++ b/PC/config.c @@ -5,6 +5,7 @@ #include "Python.h" +extern PyObject* PyInit__abc(void); extern PyObject* PyInit_array(void); extern PyObject* PyInit_audioop(void); extern PyObject* PyInit_binascii(void); @@ -80,6 +81,7 @@ extern PyObject* PyInit__imp(void); struct _inittab _PyImport_Inittab[] = { + {"_abc", PyInit__abc}, {"array", PyInit_array}, {"_ast", PyInit__ast}, {"audioop", PyInit_audioop}, diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index bf4131e91b0a..90330faa0cf2 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -228,6 +228,7 @@ + diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index 5f980388e5f3..b51fd54f8b4d 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -473,6 +473,9 @@ + + Modules + Modules diff --git a/setup.py b/setup.py index 6f9a39719b43..f4f6e4fdb1f0 100644 --- a/setup.py +++ b/setup.py @@ -712,6 +712,8 @@ def detect_modules(self): exts.append( Extension('_opcode', ['_opcode.c']) ) # asyncio speedups exts.append( Extension("_asyncio", ["_asynciomodule.c"]) ) + # _abc speedups + exts.append( Extension("_abc", ["_abc.c"]) ) # _queue module exts.append( Extension("_queue", ["_queuemodule.c"]) ) From webhook-mailer at python.org Sun Feb 18 12:41:01 2018 From: webhook-mailer at python.org (Ivan Levkivskyi) Date: Sun, 18 Feb 2018 17:41:01 -0000 Subject: [Python-checkins] bpo-25988: Emit a warning when use or import ABCs from 'collections'. (GH-5734) Message-ID: https://github.com/python/cpython/commit/0442de5ad7835814d60f46c22a22942abb101aef commit: 0442de5ad7835814d60f46c22a22942abb101aef branch: 3.7 author: Ivan Levkivskyi committer: GitHub date: 2018-02-18T17:40:59Z summary: bpo-25988: Emit a warning when use or import ABCs from 'collections'. (GH-5734) files: M Lib/collections/__init__.py M Modules/_decimal/_decimal.c diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py index c481fe2f2012..9a753db71cae 100644 --- a/Lib/collections/__init__.py +++ b/Lib/collections/__init__.py @@ -17,16 +17,7 @@ __all__ = ['deque', 'defaultdict', 'namedtuple', 'UserDict', 'UserList', 'UserString', 'Counter', 'OrderedDict', 'ChainMap'] -# For backwards compatibility, continue to make the collections ABCs -# through Python 3.6 available through the collections module. -# Note, no new collections ABCs were added in Python 3.7 import _collections_abc -from _collections_abc import (AsyncGenerator, AsyncIterable, AsyncIterator, - Awaitable, ByteString, Callable, Collection, Container, Coroutine, - Generator, Hashable, ItemsView, Iterable, Iterator, KeysView, Mapping, - MappingView, MutableMapping, MutableSequence, MutableSet, Reversible, - Sequence, Set, Sized, ValuesView) - from operator import itemgetter as _itemgetter, eq as _eq from keyword import iskeyword as _iskeyword import sys as _sys @@ -40,7 +31,7 @@ except ImportError: pass else: - MutableSequence.register(deque) + _collections_abc.MutableSequence.register(deque) try: from _collections import defaultdict @@ -48,22 +39,37 @@ pass +def __getattr__(name): + # For backwards compatibility, continue to make the collections ABCs + # through Python 3.6 available through the collections module. + # Note, no new collections ABCs were added in Python 3.7 + if name in _collections_abc.__all__: + obj = getattr(_collections_abc, name) + import warnings + warnings.warn("Using or importing the ABCs from 'collections' instead " + "of from 'collections.abc' is deprecated, " + "and in 3.8 it will stop working", + DeprecationWarning, stacklevel=2) + globals()[name] = obj + return obj + raise AttributeError(f'module {__name__!r} has no attribute {name!r}') + ################################################################################ ### OrderedDict ################################################################################ -class _OrderedDictKeysView(KeysView): +class _OrderedDictKeysView(_collections_abc.KeysView): def __reversed__(self): yield from reversed(self._mapping) -class _OrderedDictItemsView(ItemsView): +class _OrderedDictItemsView(_collections_abc.ItemsView): def __reversed__(self): for key in reversed(self._mapping): yield (key, self._mapping[key]) -class _OrderedDictValuesView(ValuesView): +class _OrderedDictValuesView(_collections_abc.ValuesView): def __reversed__(self): for key in reversed(self._mapping): @@ -215,7 +221,7 @@ def __sizeof__(self): size += sizeof(self.__root) * n # proxy objects return size - update = __update = MutableMapping.update + update = __update = _collections_abc.MutableMapping.update def keys(self): "D.keys() -> a set-like object providing a view on D's keys" @@ -229,7 +235,7 @@ def values(self): "D.values() -> an object providing a view on D's values" return _OrderedDictValuesView(self) - __ne__ = MutableMapping.__ne__ + __ne__ = _collections_abc.MutableMapping.__ne__ __marker = object() @@ -636,7 +642,7 @@ def update(*args, **kwds): raise TypeError('expected at most 1 arguments, got %d' % len(args)) iterable = args[0] if args else None if iterable is not None: - if isinstance(iterable, Mapping): + if isinstance(iterable, _collections_abc.Mapping): if self: self_get = self.get for elem, count in iterable.items(): @@ -673,7 +679,7 @@ def subtract(*args, **kwds): iterable = args[0] if args else None if iterable is not None: self_get = self.get - if isinstance(iterable, Mapping): + if isinstance(iterable, _collections_abc.Mapping): for elem, count in iterable.items(): self[elem] = self_get(elem, 0) - count else: @@ -875,7 +881,7 @@ def __iand__(self, other): ### ChainMap ######################################################################## -class ChainMap(MutableMapping): +class ChainMap(_collections_abc.MutableMapping): ''' A ChainMap groups multiple dicts (or other mappings) together to create a single, updateable view. @@ -986,7 +992,7 @@ def clear(self): ### UserDict ################################################################################ -class UserDict(MutableMapping): +class UserDict(_collections_abc.MutableMapping): # Start by filling-out the abstract methods def __init__(*args, **kwargs): @@ -1053,7 +1059,7 @@ def fromkeys(cls, iterable, value=None): ### UserList ################################################################################ -class UserList(MutableSequence): +class UserList(_collections_abc.MutableSequence): """A more or less complete user-defined wrapper around list objects.""" def __init__(self, initlist=None): self.data = [] @@ -1126,7 +1132,7 @@ def extend(self, other): ### UserString ################################################################################ -class UserString(Sequence): +class UserString(_collections_abc.Sequence): def __init__(self, seq): if isinstance(seq, str): self.data = seq diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index fddb39ef652a..5bce780cb7fb 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -5521,6 +5521,7 @@ PyInit__decimal(void) PyObject *numbers = NULL; PyObject *Number = NULL; PyObject *collections = NULL; + PyObject *collections_abc = NULL; PyObject *MutableMapping = NULL; PyObject *obj = NULL; DecCondMap *cm; @@ -5595,7 +5596,8 @@ PyInit__decimal(void) Py_CLEAR(obj); /* MutableMapping */ - ASSIGN_PTR(MutableMapping, PyObject_GetAttrString(collections, + ASSIGN_PTR(collections_abc, PyImport_ImportModule("collections.abc")); + ASSIGN_PTR(MutableMapping, PyObject_GetAttrString(collections_abc, "MutableMapping")); /* Create SignalDict type */ ASSIGN_PTR(PyDecSignalDict_Type, @@ -5606,6 +5608,7 @@ PyInit__decimal(void) /* Done with collections, MutableMapping */ Py_CLEAR(collections); + Py_CLEAR(collections_abc); Py_CLEAR(MutableMapping); @@ -5765,6 +5768,7 @@ PyInit__decimal(void) Py_CLEAR(Number); /* GCOV_NOT_REACHED */ Py_CLEAR(Rational); /* GCOV_NOT_REACHED */ Py_CLEAR(collections); /* GCOV_NOT_REACHED */ + Py_CLEAR(collections_abc); /* GCOV_NOT_REACHED */ Py_CLEAR(MutableMapping); /* GCOV_NOT_REACHED */ Py_CLEAR(SignalTuple); /* GCOV_NOT_REACHED */ Py_CLEAR(DecimalTuple); /* GCOV_NOT_REACHED */ From webhook-mailer at python.org Sun Feb 18 12:57:27 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sun, 18 Feb 2018 17:57:27 -0000 Subject: [Python-checkins] bpo-32869: Fix incorrect dst buffer size for MultiByteToWideChar (#5739) Message-ID: https://github.com/python/cpython/commit/b3b4a9d3001f1fc7df8efcccdce081de54fa5eab commit: b3b4a9d3001f1fc7df8efcccdce081de54fa5eab branch: master author: Alexey Izbyshev committer: Serhiy Storchaka date: 2018-02-18T19:57:24+02:00 summary: bpo-32869: Fix incorrect dst buffer size for MultiByteToWideChar (#5739) This function expects the destination buffer size to be given in wide characters, not bytes. files: M Python/fileutils.c diff --git a/Python/fileutils.c b/Python/fileutils.c index 3cf8b7a8b69d..32aeea4f1037 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -1289,7 +1289,8 @@ _Py_fopen_obj(PyObject *path, const char *mode) if (wpath == NULL) return NULL; - usize = MultiByteToWideChar(CP_ACP, 0, mode, -1, wmode, sizeof(wmode)); + usize = MultiByteToWideChar(CP_ACP, 0, mode, -1, + wmode, Py_ARRAY_LENGTH(wmode)); if (usize == 0) { PyErr_SetFromWindowsErr(0); return NULL; From webhook-mailer at python.org Sun Feb 18 13:18:47 2018 From: webhook-mailer at python.org (Ned Deily) Date: Sun, 18 Feb 2018 18:18:47 -0000 Subject: [Python-checkins] bpo-25988: add NEWS entry for 3.7.0b2 (#5743) Message-ID: https://github.com/python/cpython/commit/2e84e47626c6eafacc9f011cd9fccc8bf1c8508e commit: 2e84e47626c6eafacc9f011cd9fccc8bf1c8508e branch: 3.7 author: Ned Deily committer: GitHub date: 2018-02-18T13:18:44-05:00 summary: bpo-25988: add NEWS entry for 3.7.0b2 (#5743) files: A Misc/NEWS.d/next/Library/2018-02-18-13-04-59.bpo-25988.ACidKC.rst diff --git a/Misc/NEWS.d/next/Library/2018-02-18-13-04-59.bpo-25988.ACidKC.rst b/Misc/NEWS.d/next/Library/2018-02-18-13-04-59.bpo-25988.ACidKC.rst new file mode 100644 index 000000000000..9730ab4a6101 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-18-13-04-59.bpo-25988.ACidKC.rst @@ -0,0 +1,2 @@ +Emit a :exc:`DeprecationWarning` when using or importing an ABC directly +from :mod:`collections` rather than from :mod:`collections.abc`. From webhook-mailer at python.org Sun Feb 18 13:40:10 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sun, 18 Feb 2018 18:40:10 -0000 Subject: [Python-checkins] bpo-32869: Fix incorrect dst buffer size for MultiByteToWideChar (GH-5739) Message-ID: https://github.com/python/cpython/commit/ca82e3c0ec4d0d5ce4e1ffec98cc341cb5913446 commit: ca82e3c0ec4d0d5ce4e1ffec98cc341cb5913446 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-18T10:40:07-08:00 summary: bpo-32869: Fix incorrect dst buffer size for MultiByteToWideChar (GH-5739) This function expects the destination buffer size to be given in wide characters, not bytes. (cherry picked from commit b3b4a9d3001f1fc7df8efcccdce081de54fa5eab) Co-authored-by: Alexey Izbyshev files: M Python/fileutils.c diff --git a/Python/fileutils.c b/Python/fileutils.c index 3cf8b7a8b69d..32aeea4f1037 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -1289,7 +1289,8 @@ _Py_fopen_obj(PyObject *path, const char *mode) if (wpath == NULL) return NULL; - usize = MultiByteToWideChar(CP_ACP, 0, mode, -1, wmode, sizeof(wmode)); + usize = MultiByteToWideChar(CP_ACP, 0, mode, -1, + wmode, Py_ARRAY_LENGTH(wmode)); if (usize == 0) { PyErr_SetFromWindowsErr(0); return NULL; From webhook-mailer at python.org Sun Feb 18 13:58:12 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sun, 18 Feb 2018 18:58:12 -0000 Subject: [Python-checkins] bpo-32869: Fix incorrect dst buffer size for MultiByteToWideChar (GH-5739) Message-ID: https://github.com/python/cpython/commit/65a13c19e86488119cc9bc192f5a0b846d90940f commit: 65a13c19e86488119cc9bc192f5a0b846d90940f branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-18T10:58:09-08:00 summary: bpo-32869: Fix incorrect dst buffer size for MultiByteToWideChar (GH-5739) This function expects the destination buffer size to be given in wide characters, not bytes. (cherry picked from commit b3b4a9d3001f1fc7df8efcccdce081de54fa5eab) Co-authored-by: Alexey Izbyshev files: M Python/fileutils.c diff --git a/Python/fileutils.c b/Python/fileutils.c index 899ea8aecac0..b9638d2df513 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -1185,7 +1185,8 @@ _Py_fopen_obj(PyObject *path, const char *mode) if (wpath == NULL) return NULL; - usize = MultiByteToWideChar(CP_ACP, 0, mode, -1, wmode, sizeof(wmode)); + usize = MultiByteToWideChar(CP_ACP, 0, mode, -1, + wmode, Py_ARRAY_LENGTH(wmode)); if (usize == 0) { PyErr_SetFromWindowsErr(0); return NULL; From webhook-mailer at python.org Sun Feb 18 16:44:52 2018 From: webhook-mailer at python.org (Zachary Ware) Date: Sun, 18 Feb 2018 21:44:52 -0000 Subject: [Python-checkins] [3.6] Clean up Travis config (GH-5727) Message-ID: https://github.com/python/cpython/commit/ea49c03313af014cbc0b3ec184c7e3731ea21aaf commit: ea49c03313af014cbc0b3ec184c7e3731ea21aaf branch: 3.6 author: Zachary Ware committer: GitHub date: 2018-02-18T15:44:49-06:00 summary: [3.6] Clean up Travis config (GH-5727) (cherry picked from commit 7eb3f8226ea7b79dae4e4e8b05730cfe0d9af7c1) files: M .travis.yml diff --git a/.travis.yml b/.travis.yml index 2bed28103522..7d92c2e2f852 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,13 +5,14 @@ group: beta # To cache doc-building dependencies and C compiler output. cache: - - pip - - ccache + - pip + - ccache branches: only: - master - /^\d\.\d$/ + - buildbot-custom matrix: fast_finish: true @@ -41,19 +42,12 @@ matrix: compiler: gcc env: OPTIONAL=true before_script: - - | - if ! git diff --name-only $TRAVIS_COMMIT_RANGE | grep -qvE '(\.rst$)|(^Doc)|(^Misc)' - then - echo "Only docs were updated, stopping build process." - exit - fi - # Build in release mode - ./configure PYTHON_FOR_REGEN=python3 - make -s -j4 - # Need a venv that can parse covered code. - ./python -m venv venv - ./venv/bin/python -m pip install -U coverage - ./venv/bin/python -m test.pythoninfo + - ./configure PYTHON_FOR_REGEN=python3 + - make -s -j4 + # Need a venv that can parse covered code. + - ./python -m venv venv + - ./venv/bin/python -m pip install -U coverage + - ./venv/bin/python -m test.pythoninfo script: # Skip tests that re-run the entire test suite. - ./venv/bin/python -m coverage run --pylib -m test -uall,-cpu -x test_multiprocessing_fork -x test_multiprocessing_forkserver -x test_multiprocessing_spawn @@ -62,41 +56,48 @@ matrix: - source ./venv/bin/activate - bash <(curl -s https://codecov.io/bash) -# Travis provides only 2 cores, so don't overdo the parallelism and waste memory. -before_script: - - | - set -e - if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then - files_changed=$(git diff --name-only $TRAVIS_COMMIT_RANGE) - else - # Pull requests are slightly complicated because merging the PR commit without - # rebasing causes it to retain its old commit date. Meaning in history if any - # commits have been made on master that post-date it, they will be accidentally - # included in the diff if we use the TRAVIS_COMMIT_RANGE variable. - files_changed=$(git diff --name-only HEAD $(git merge-base HEAD $TRAVIS_BRANCH)) - fi - - # Prints changed files in this commit to help debug doc-only build issues. - echo "Files changed: " - echo $files_changed - if ! echo "$files_changed" | grep -qvE '(\.rst$)|(^Doc)|(^Misc)' +before_install: + - set -e + - | + # Check short-circuit conditions + if [ "${TESTING}" != "docs" ] then - echo "Only docs were updated, stopping build process." - exit + if [ "$TRAVIS_PULL_REQUEST" = "false" ] + then + echo "Not a PR, doing full build." + else + # Pull requests are slightly complicated because $TRAVIS_COMMIT_RANGE + # may include more changes than desired if the history is convoluted. + # Instead, explicitly fetch the base branch and compare against the + # merge-base commit. + git fetch -q origin +refs/heads/$TRAVIS_BRANCH + changes=$(git diff --name-only HEAD $(git merge-base HEAD FETCH_HEAD)) + echo "Files changed:" + echo "$changes" + if ! echo "$changes" | grep -qvE '(\.rst$)|(^Doc)|(^Misc)' + then + echo "Only docs were updated, stopping build process." + exit + fi + fi fi - # Build in debug mode - ./configure --with-pydebug PYTHON_FOR_REGEN=python3 - make -j4 regen-all - changes=`git status --porcelain` + +# Travis provides only 2 cores, so don't overdo the parallelism and waste memory. +before_script: + - ./configure --with-pydebug PYTHON_FOR_REGEN=python3 + - make -j4 regen-all + - changes=`git status --porcelain` + - | + # Check for changes in regenerated files if ! test -z "$changes" then echo "Generated files not up to date" echo "$changes" exit 1 fi - make -j4 - make pythoninfo + - make -j4 + - make pythoninfo script: # Using the built Python as patchcheck.py is built around the idea of using @@ -104,6 +105,8 @@ script: # should be compared against. # Only run on Linux as the check only needs to be run once. - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./python Tools/scripts/patchcheck.py --travis $TRAVIS_PULL_REQUEST; fi + # Check that all symbols exported by libpython start with "Py" or "_Py" + - make smelly # `-r -w` implicitly provided through `make buildbottest`. - make buildbottest TESTOPTS="-j4 -uall,-cpu" From webhook-mailer at python.org Sun Feb 18 16:45:51 2018 From: webhook-mailer at python.org (Zachary Ware) Date: Sun, 18 Feb 2018 21:45:51 -0000 Subject: [Python-checkins] [2.7] Clean up Travis config (GH-5727) Message-ID: https://github.com/python/cpython/commit/21f53e7249d838489033abf4fc267bec00c1af3e commit: 21f53e7249d838489033abf4fc267bec00c1af3e branch: 2.7 author: Zachary Ware committer: GitHub date: 2018-02-18T15:45:48-06:00 summary: [2.7] Clean up Travis config (GH-5727) (cherry picked from commit 7eb3f8226ea7b79dae4e4e8b05730cfe0d9af7c1) files: M .travis.yml diff --git a/.travis.yml b/.travis.yml index 6a64ec62ab84..175432dd45ab 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,13 +5,14 @@ group: beta # To cache doc-building dependencies and C compiler output. cache: - - pip - - ccache + - pip + - ccache branches: only: - master - /^\d\.\d$/ + - buildbot-custom matrix: fast_finish: true @@ -37,28 +38,53 @@ matrix: script: - make check suspicious html SPHINXOPTS="-q -W -j4" -# Travis provides only 2 cores, so don't overdo the parallelism and waste memory. -before_script: + +before_install: + - set -e - | - set -e - if ! git diff --name-only $TRAVIS_COMMIT_RANGE | grep -qvE '(\.rst$)|(^Doc)' + # Check short-circuit conditions + if [ "${TESTING}" != "docs" ] then - echo "Only docs were updated, stopping build process." - exit + if [ "$TRAVIS_PULL_REQUEST" = "false" ] + then + echo "Not a PR, doing full build." + else + # Pull requests are slightly complicated because $TRAVIS_COMMIT_RANGE + # may include more changes than desired if the history is convoluted. + # Instead, explicitly fetch the base branch and compare against the + # merge-base commit. + git fetch -q origin +refs/heads/$TRAVIS_BRANCH + changes=$(git diff --name-only HEAD $(git merge-base HEAD FETCH_HEAD)) + echo "Files changed:" + echo "$changes" + if ! echo "$changes" | grep -qvE '(\.rst$)|(^Doc)|(^Misc)' + then + echo "Only docs were updated, stopping build process." + exit + fi + fi fi - ./configure --with-pydebug - make -j4 - make -j4 regen-all - changes=`git status --porcelain` + + +# Travis provides only 2 cores, so don't overdo the parallelism and waste memory. +before_script: + - ./configure --with-pydebug + - make -j4 regen-all + - changes=`git status --porcelain` + - | + # Check for changes in regenerated files if ! test -z "$changes" then echo "Generated files not up to date" echo "$changes" exit 1 fi - make pythoninfo + - make -j4 + - make pythoninfo script: + # Check that all symbols exported by libpython start with "Py" or "_Py" + - make smelly # `-r -w` implicitly provided through `make buildbottest`. - make buildbottest TESTOPTS="-j4 -uall,-cpu" From webhook-mailer at python.org Sun Feb 18 16:46:52 2018 From: webhook-mailer at python.org (Ivan Levkivskyi) Date: Sun, 18 Feb 2018 21:46:52 -0000 Subject: [Python-checkins] bpo-31333: Fix typo in whatsnew/3.7.rst (GH-5744) Message-ID: https://github.com/python/cpython/commit/3fb813d2c67fe28cc98ae51e53a6890294b6e423 commit: 3fb813d2c67fe28cc98ae51e53a6890294b6e423 branch: master author: Terry Jan Reedy committer: Ivan Levkivskyi date: 2018-02-18T21:46:49Z summary: bpo-31333: Fix typo in whatsnew/3.7.rst (GH-5744) files: M Doc/whatsnew/3.7.rst diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index c35f07c0eabf..50c9238e4aa8 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -853,7 +853,7 @@ Optimizations * 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 rewrittent in C. +* 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 From webhook-mailer at python.org Sun Feb 18 17:35:42 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sun, 18 Feb 2018 22:35:42 -0000 Subject: [Python-checkins] bpo-31333: Fix typo in whatsnew/3.7.rst (GH-5744) Message-ID: https://github.com/python/cpython/commit/034a945fa723bf68ca4127bb43bfa5c5be899f17 commit: 034a945fa723bf68ca4127bb43bfa5c5be899f17 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-18T14:35:40-08:00 summary: bpo-31333: Fix typo in whatsnew/3.7.rst (GH-5744) (cherry picked from commit 3fb813d2c67fe28cc98ae51e53a6890294b6e423) Co-authored-by: Terry Jan Reedy files: M Doc/whatsnew/3.7.rst diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 80bc8fb3d951..2ca1eed2155e 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -845,7 +845,7 @@ Optimizations * 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 rewrittent in C. +* 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 From webhook-mailer at python.org Sun Feb 18 18:15:00 2018 From: webhook-mailer at python.org (=?utf-8?q?=C3=89ric?= Araujo) Date: Sun, 18 Feb 2018 23:15:00 -0000 Subject: [Python-checkins] Improve error message for "setup.py upload" without dist files (#21060) Message-ID: https://github.com/python/cpython/commit/08a6926b2584040fe3c3f06263b0b5f1fbbdc24c commit: 08a6926b2584040fe3c3f06263b0b5f1fbbdc24c branch: master author: ?ric Araujo committer: GitHub date: 2018-02-18T18:14:54-05:00 summary: Improve error message for "setup.py upload" without dist files (#21060) files: A Misc/NEWS.d/next/Library/2018-02-17-19-20-19.bpo-21060.S1Z-x6.rst M Lib/distutils/command/upload.py diff --git a/Lib/distutils/command/upload.py b/Lib/distutils/command/upload.py index f7752f9d12c7..32dda359badb 100644 --- a/Lib/distutils/command/upload.py +++ b/Lib/distutils/command/upload.py @@ -57,7 +57,8 @@ def finalize_options(self): def run(self): if not self.distribution.dist_files: - msg = "No dist file created in earlier command" + msg = ("Must create and upload files in one command " + "(e.g. setup.py sdist upload)") raise DistutilsOptionError(msg) for command, pyversion, filename in self.distribution.dist_files: self.upload_file(command, pyversion, filename) diff --git a/Misc/NEWS.d/next/Library/2018-02-17-19-20-19.bpo-21060.S1Z-x6.rst b/Misc/NEWS.d/next/Library/2018-02-17-19-20-19.bpo-21060.S1Z-x6.rst new file mode 100644 index 000000000000..4e0a11362086 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-17-19-20-19.bpo-21060.S1Z-x6.rst @@ -0,0 +1,3 @@ +Rewrite confusing message from setup.py upload from +"No dist file created in earlier command" to the more helpful +"Must create and upload files in one command". From webhook-mailer at python.org Sun Feb 18 18:36:34 2018 From: webhook-mailer at python.org (=?utf-8?q?=C3=89ric?= Araujo) Date: Sun, 18 Feb 2018 23:36:34 -0000 Subject: [Python-checkins] bpo-31972: Improve docstrings for pathlib classes (#5310) Message-ID: https://github.com/python/cpython/commit/dfa015cf77a148d229ddc0a5b063562c9f9664f2 commit: dfa015cf77a148d229ddc0a5b063562c9f9664f2 branch: master author: chason committer: ?ric Araujo date: 2018-02-18T18:36:32-05:00 summary: bpo-31972: Improve docstrings for pathlib classes (#5310) files: A Misc/NEWS.d/next/Documentation/2018-01-25-14-23-12.bpo-31972.w1m_8r.rst M Lib/pathlib.py diff --git a/Lib/pathlib.py b/Lib/pathlib.py index 73dd513b200e..8431c29c1d65 100644 --- a/Lib/pathlib.py +++ b/Lib/pathlib.py @@ -584,7 +584,9 @@ def __repr__(self): class PurePath(object): - """PurePath represents a filesystem path and offers operations which + """Base class for manipulating paths without I/O. + + PurePath represents a filesystem path and offers operations which don't imply any actual filesystem I/O. Depending on your system, instantiating a PurePath will return either a PurePosixPath or a PureWindowsPath object. You can also instantiate either of these classes @@ -939,11 +941,21 @@ def match(self, path_pattern): class PurePosixPath(PurePath): + """PurePath subclass for non-Windows systems. + + On a POSIX system, instantiating a PurePath should return this object. + However, you can also instantiate it directly on any system. + """ _flavour = _posix_flavour __slots__ = () class PureWindowsPath(PurePath): + """PurePath subclass for Windows systems. + + On a Windows system, instantiating a PurePath should return this object. + However, you can also instantiate it directly on any system. + """ _flavour = _windows_flavour __slots__ = () @@ -952,6 +964,14 @@ class PureWindowsPath(PurePath): class Path(PurePath): + """PurePath subclass that can make system calls. + + Path represents a filesystem path but unlike PurePath, also offers + methods to do system calls on path objects. Depending on your system, + instantiating a Path will return either a PosixPath or a WindowsPath + object. You can also instantiate a PosixPath or WindowsPath directly, + but cannot instantiate a WindowsPath on a POSIX system or vice versa. + """ __slots__ = ( '_accessor', '_closed', @@ -1427,9 +1447,17 @@ def expanduser(self): class PosixPath(Path, PurePosixPath): + """Path subclass for non-Windows systems. + + On a POSIX system, instantiating a Path should return this object. + """ __slots__ = () class WindowsPath(Path, PureWindowsPath): + """Path subclass for Windows systems. + + On a Windows system, instantiating a Path should return this object. + """ __slots__ = () def owner(self): diff --git a/Misc/NEWS.d/next/Documentation/2018-01-25-14-23-12.bpo-31972.w1m_8r.rst b/Misc/NEWS.d/next/Documentation/2018-01-25-14-23-12.bpo-31972.w1m_8r.rst new file mode 100644 index 000000000000..e0361df578b3 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2018-01-25-14-23-12.bpo-31972.w1m_8r.rst @@ -0,0 +1 @@ +Improve docstrings for `pathlib.PurePath` subclasses. From webhook-mailer at python.org Sun Feb 18 19:37:03 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 19 Feb 2018 00:37:03 -0000 Subject: [Python-checkins] bpo-31972: Improve docstrings for pathlib classes (GH-5310) Message-ID: https://github.com/python/cpython/commit/5c81ed49412e41a671283cdb4c297dab52f5b7c5 commit: 5c81ed49412e41a671283cdb4c297dab52f5b7c5 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-18T16:37:00-08:00 summary: bpo-31972: Improve docstrings for pathlib classes (GH-5310) (cherry picked from commit dfa015cf77a148d229ddc0a5b063562c9f9664f2) Co-authored-by: chason files: A Misc/NEWS.d/next/Documentation/2018-01-25-14-23-12.bpo-31972.w1m_8r.rst M Lib/pathlib.py diff --git a/Lib/pathlib.py b/Lib/pathlib.py index 48b566d9295f..44788c02c2f3 100644 --- a/Lib/pathlib.py +++ b/Lib/pathlib.py @@ -600,7 +600,9 @@ def __repr__(self): class PurePath(object): - """PurePath represents a filesystem path and offers operations which + """Base class for manipulating paths without I/O. + + PurePath represents a filesystem path and offers operations which don't imply any actual filesystem I/O. Depending on your system, instantiating a PurePath will return either a PurePosixPath or a PureWindowsPath object. You can also instantiate either of these classes @@ -955,11 +957,21 @@ def match(self, path_pattern): class PurePosixPath(PurePath): + """PurePath subclass for non-Windows systems. + + On a POSIX system, instantiating a PurePath should return this object. + However, you can also instantiate it directly on any system. + """ _flavour = _posix_flavour __slots__ = () class PureWindowsPath(PurePath): + """PurePath subclass for Windows systems. + + On a Windows system, instantiating a PurePath should return this object. + However, you can also instantiate it directly on any system. + """ _flavour = _windows_flavour __slots__ = () @@ -968,6 +980,14 @@ class PureWindowsPath(PurePath): class Path(PurePath): + """PurePath subclass that can make system calls. + + Path represents a filesystem path but unlike PurePath, also offers + methods to do system calls on path objects. Depending on your system, + instantiating a Path will return either a PosixPath or a WindowsPath + object. You can also instantiate a PosixPath or WindowsPath directly, + but cannot instantiate a WindowsPath on a POSIX system or vice versa. + """ __slots__ = ( '_accessor', '_closed', @@ -1422,9 +1442,17 @@ def expanduser(self): class PosixPath(Path, PurePosixPath): + """Path subclass for non-Windows systems. + + On a POSIX system, instantiating a Path should return this object. + """ __slots__ = () class WindowsPath(Path, PureWindowsPath): + """Path subclass for Windows systems. + + On a Windows system, instantiating a Path should return this object. + """ __slots__ = () def owner(self): diff --git a/Misc/NEWS.d/next/Documentation/2018-01-25-14-23-12.bpo-31972.w1m_8r.rst b/Misc/NEWS.d/next/Documentation/2018-01-25-14-23-12.bpo-31972.w1m_8r.rst new file mode 100644 index 000000000000..e0361df578b3 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2018-01-25-14-23-12.bpo-31972.w1m_8r.rst @@ -0,0 +1 @@ +Improve docstrings for `pathlib.PurePath` subclasses. From webhook-mailer at python.org Sun Feb 18 19:48:10 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 19 Feb 2018 00:48:10 -0000 Subject: [Python-checkins] bpo-31972: Improve docstrings for pathlib classes (GH-5310) Message-ID: https://github.com/python/cpython/commit/19b7f6694af56a1c9fdc0f1f9fc09ae48439ab4c commit: 19b7f6694af56a1c9fdc0f1f9fc09ae48439ab4c branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-18T16:48:07-08:00 summary: bpo-31972: Improve docstrings for pathlib classes (GH-5310) (cherry picked from commit dfa015cf77a148d229ddc0a5b063562c9f9664f2) Co-authored-by: chason files: A Misc/NEWS.d/next/Documentation/2018-01-25-14-23-12.bpo-31972.w1m_8r.rst M Lib/pathlib.py diff --git a/Lib/pathlib.py b/Lib/pathlib.py index 73dd513b200e..8431c29c1d65 100644 --- a/Lib/pathlib.py +++ b/Lib/pathlib.py @@ -584,7 +584,9 @@ def __repr__(self): class PurePath(object): - """PurePath represents a filesystem path and offers operations which + """Base class for manipulating paths without I/O. + + PurePath represents a filesystem path and offers operations which don't imply any actual filesystem I/O. Depending on your system, instantiating a PurePath will return either a PurePosixPath or a PureWindowsPath object. You can also instantiate either of these classes @@ -939,11 +941,21 @@ def match(self, path_pattern): class PurePosixPath(PurePath): + """PurePath subclass for non-Windows systems. + + On a POSIX system, instantiating a PurePath should return this object. + However, you can also instantiate it directly on any system. + """ _flavour = _posix_flavour __slots__ = () class PureWindowsPath(PurePath): + """PurePath subclass for Windows systems. + + On a Windows system, instantiating a PurePath should return this object. + However, you can also instantiate it directly on any system. + """ _flavour = _windows_flavour __slots__ = () @@ -952,6 +964,14 @@ class PureWindowsPath(PurePath): class Path(PurePath): + """PurePath subclass that can make system calls. + + Path represents a filesystem path but unlike PurePath, also offers + methods to do system calls on path objects. Depending on your system, + instantiating a Path will return either a PosixPath or a WindowsPath + object. You can also instantiate a PosixPath or WindowsPath directly, + but cannot instantiate a WindowsPath on a POSIX system or vice versa. + """ __slots__ = ( '_accessor', '_closed', @@ -1427,9 +1447,17 @@ def expanduser(self): class PosixPath(Path, PurePosixPath): + """Path subclass for non-Windows systems. + + On a POSIX system, instantiating a Path should return this object. + """ __slots__ = () class WindowsPath(Path, PureWindowsPath): + """Path subclass for Windows systems. + + On a Windows system, instantiating a Path should return this object. + """ __slots__ = () def owner(self): diff --git a/Misc/NEWS.d/next/Documentation/2018-01-25-14-23-12.bpo-31972.w1m_8r.rst b/Misc/NEWS.d/next/Documentation/2018-01-25-14-23-12.bpo-31972.w1m_8r.rst new file mode 100644 index 000000000000..e0361df578b3 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2018-01-25-14-23-12.bpo-31972.w1m_8r.rst @@ -0,0 +1 @@ +Improve docstrings for `pathlib.PurePath` subclasses. From webhook-mailer at python.org Sun Feb 18 22:45:14 2018 From: webhook-mailer at python.org (Zachary Ware) Date: Mon, 19 Feb 2018 03:45:14 -0000 Subject: [Python-checkins] bpo-32682: Improve libz version parsing in test_zilb (GH-5347) Message-ID: https://github.com/python/cpython/commit/4c7108a77144493d0aa6fc0105b67d3797e143f5 commit: 4c7108a77144493d0aa6fc0105b67d3797e143f5 branch: master author: pmp-p committer: Zachary Ware date: 2018-02-18T21:45:11-06:00 summary: bpo-32682: Improve libz version parsing in test_zilb (GH-5347) files: M Lib/test/test_zlib.py diff --git a/Lib/test/test_zlib.py b/Lib/test/test_zlib.py index e67bee97cb3d..db950fc1907a 100644 --- a/Lib/test/test_zlib.py +++ b/Lib/test/test_zlib.py @@ -751,10 +751,15 @@ def test_large_unconsumed_tail(self, size): def test_wbits(self): # wbits=0 only supported since zlib v1.2.3.5 # Register "1.2.3" as "1.2.3.0" - v = (zlib.ZLIB_RUNTIME_VERSION + ".0").split(".", 4) - supports_wbits_0 = int(v[0]) > 1 or int(v[0]) == 1 \ - and (int(v[1]) > 2 or int(v[1]) == 2 - and (int(v[2]) > 3 or int(v[2]) == 3 and int(v[3]) >= 5)) + # or "1.2.0-linux","1.2.0.f","1.2.0.f-linux" + v = zlib.ZLIB_RUNTIME_VERSION.split('-', 1)[0].split('.') + if len(v) < 4: + v.append('0') + elif not v[-1].isnumeric(): + v[-1] = '0' + + v = tuple(map(int, v)) + supports_wbits_0 = v >= (1, 2, 3, 5) co = zlib.compressobj(level=1, wbits=15) zlib15 = co.compress(HAMLET_SCENE) + co.flush() From webhook-mailer at python.org Sun Feb 18 22:56:10 2018 From: webhook-mailer at python.org (Mariatta) Date: Mon, 19 Feb 2018 03:56:10 -0000 Subject: [Python-checkins] [2.7] bpo-21060 Improve error message for "setup.py upload" without dist files (GH-5726). Message-ID: https://github.com/python/cpython/commit/eeb33651bfadcceea68bd27bb4c4d8de2e690656 commit: eeb33651bfadcceea68bd27bb4c4d8de2e690656 branch: 2.7 author: ?ric Araujo committer: Mariatta date: 2018-02-18T19:56:06-08:00 summary: [2.7] bpo-21060 Improve error message for "setup.py upload" without dist files (GH-5726). (cherry picked from commit 08a6926b2584040fe3c3f06263b0b5f1fbbdc24c) Co-authored-by: ?ric Araujo files: A Misc/NEWS.d/next/Library/2018-02-17-19-20-19.bpo-21060.S1Z-x6.rst M Lib/distutils/command/upload.py diff --git a/Lib/distutils/command/upload.py b/Lib/distutils/command/upload.py index ea4b8a551a60..ff043d2e1252 100644 --- a/Lib/distutils/command/upload.py +++ b/Lib/distutils/command/upload.py @@ -55,7 +55,9 @@ def finalize_options(self): def run(self): if not self.distribution.dist_files: - raise DistutilsOptionError("No dist file created in earlier command") + msg = ("Must create and upload files in one command " + "(e.g. setup.py sdist upload)") + raise DistutilsOptionError(msg) for command, pyversion, filename in self.distribution.dist_files: self.upload_file(command, pyversion, filename) diff --git a/Misc/NEWS.d/next/Library/2018-02-17-19-20-19.bpo-21060.S1Z-x6.rst b/Misc/NEWS.d/next/Library/2018-02-17-19-20-19.bpo-21060.S1Z-x6.rst new file mode 100644 index 000000000000..4e0a11362086 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-17-19-20-19.bpo-21060.S1Z-x6.rst @@ -0,0 +1,3 @@ +Rewrite confusing message from setup.py upload from +"No dist file created in earlier command" to the more helpful +"Must create and upload files in one command". From webhook-mailer at python.org Sun Feb 18 22:57:21 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 19 Feb 2018 03:57:21 -0000 Subject: [Python-checkins] Improve error message for "setup.py upload" without dist files (GH-21060) Message-ID: https://github.com/python/cpython/commit/2072c80d061fc879dd51ce67dbd5ed672b92a9cd commit: 2072c80d061fc879dd51ce67dbd5ed672b92a9cd branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-18T19:57:17-08:00 summary: Improve error message for "setup.py upload" without dist files (GH-21060) (cherry picked from commit 08a6926b2584040fe3c3f06263b0b5f1fbbdc24c) Co-authored-by: ?ric Araujo files: A Misc/NEWS.d/next/Library/2018-02-17-19-20-19.bpo-21060.S1Z-x6.rst M Lib/distutils/command/upload.py diff --git a/Lib/distutils/command/upload.py b/Lib/distutils/command/upload.py index f7752f9d12c7..32dda359badb 100644 --- a/Lib/distutils/command/upload.py +++ b/Lib/distutils/command/upload.py @@ -57,7 +57,8 @@ def finalize_options(self): def run(self): if not self.distribution.dist_files: - msg = "No dist file created in earlier command" + msg = ("Must create and upload files in one command " + "(e.g. setup.py sdist upload)") raise DistutilsOptionError(msg) for command, pyversion, filename in self.distribution.dist_files: self.upload_file(command, pyversion, filename) diff --git a/Misc/NEWS.d/next/Library/2018-02-17-19-20-19.bpo-21060.S1Z-x6.rst b/Misc/NEWS.d/next/Library/2018-02-17-19-20-19.bpo-21060.S1Z-x6.rst new file mode 100644 index 000000000000..4e0a11362086 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-17-19-20-19.bpo-21060.S1Z-x6.rst @@ -0,0 +1,3 @@ +Rewrite confusing message from setup.py upload from +"No dist file created in earlier command" to the more helpful +"Must create and upload files in one command". From webhook-mailer at python.org Sun Feb 18 23:10:02 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 19 Feb 2018 04:10:02 -0000 Subject: [Python-checkins] bpo-32682: Improve libz version parsing in test_zilb (GH-5347) Message-ID: https://github.com/python/cpython/commit/0cd35817e8278588f04dc574f6eca53273799f25 commit: 0cd35817e8278588f04dc574f6eca53273799f25 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-18T20:09:59-08:00 summary: bpo-32682: Improve libz version parsing in test_zilb (GH-5347) (cherry picked from commit 4c7108a77144493d0aa6fc0105b67d3797e143f5) Co-authored-by: pmp-p files: M Lib/test/test_zlib.py diff --git a/Lib/test/test_zlib.py b/Lib/test/test_zlib.py index e67bee97cb3d..db950fc1907a 100644 --- a/Lib/test/test_zlib.py +++ b/Lib/test/test_zlib.py @@ -751,10 +751,15 @@ def test_large_unconsumed_tail(self, size): def test_wbits(self): # wbits=0 only supported since zlib v1.2.3.5 # Register "1.2.3" as "1.2.3.0" - v = (zlib.ZLIB_RUNTIME_VERSION + ".0").split(".", 4) - supports_wbits_0 = int(v[0]) > 1 or int(v[0]) == 1 \ - and (int(v[1]) > 2 or int(v[1]) == 2 - and (int(v[2]) > 3 or int(v[2]) == 3 and int(v[3]) >= 5)) + # or "1.2.0-linux","1.2.0.f","1.2.0.f-linux" + v = zlib.ZLIB_RUNTIME_VERSION.split('-', 1)[0].split('.') + if len(v) < 4: + v.append('0') + elif not v[-1].isnumeric(): + v[-1] = '0' + + v = tuple(map(int, v)) + supports_wbits_0 = v >= (1, 2, 3, 5) co = zlib.compressobj(level=1, wbits=15) zlib15 = co.compress(HAMLET_SCENE) + co.flush() From webhook-mailer at python.org Sun Feb 18 23:14:30 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 19 Feb 2018 04:14:30 -0000 Subject: [Python-checkins] Improve error message for "setup.py upload" without dist files (GH-21060) Message-ID: https://github.com/python/cpython/commit/2a93fae8b5b26cbfef6c8afb702d305d3919de85 commit: 2a93fae8b5b26cbfef6c8afb702d305d3919de85 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-18T20:14:27-08:00 summary: Improve error message for "setup.py upload" without dist files (GH-21060) (cherry picked from commit 08a6926b2584040fe3c3f06263b0b5f1fbbdc24c) Co-authored-by: ?ric Araujo files: A Misc/NEWS.d/next/Library/2018-02-17-19-20-19.bpo-21060.S1Z-x6.rst M Lib/distutils/command/upload.py diff --git a/Lib/distutils/command/upload.py b/Lib/distutils/command/upload.py index f7752f9d12c7..32dda359badb 100644 --- a/Lib/distutils/command/upload.py +++ b/Lib/distutils/command/upload.py @@ -57,7 +57,8 @@ def finalize_options(self): def run(self): if not self.distribution.dist_files: - msg = "No dist file created in earlier command" + msg = ("Must create and upload files in one command " + "(e.g. setup.py sdist upload)") raise DistutilsOptionError(msg) for command, pyversion, filename in self.distribution.dist_files: self.upload_file(command, pyversion, filename) diff --git a/Misc/NEWS.d/next/Library/2018-02-17-19-20-19.bpo-21060.S1Z-x6.rst b/Misc/NEWS.d/next/Library/2018-02-17-19-20-19.bpo-21060.S1Z-x6.rst new file mode 100644 index 000000000000..4e0a11362086 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-17-19-20-19.bpo-21060.S1Z-x6.rst @@ -0,0 +1,3 @@ +Rewrite confusing message from setup.py upload from +"No dist file created in earlier command" to the more helpful +"Must create and upload files in one command". From webhook-mailer at python.org Sun Feb 18 23:31:18 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 19 Feb 2018 04:31:18 -0000 Subject: [Python-checkins] bpo-32682: Improve libz version parsing in test_zilb (GH-5347) Message-ID: https://github.com/python/cpython/commit/b0fd935360e81b6bb4733deed69f51516c771f7a commit: b0fd935360e81b6bb4733deed69f51516c771f7a branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-18T20:31:15-08:00 summary: bpo-32682: Improve libz version parsing in test_zilb (GH-5347) (cherry picked from commit 4c7108a77144493d0aa6fc0105b67d3797e143f5) Co-authored-by: pmp-p files: M Lib/test/test_zlib.py diff --git a/Lib/test/test_zlib.py b/Lib/test/test_zlib.py index 20174d8343f2..8e29b1bcebff 100644 --- a/Lib/test/test_zlib.py +++ b/Lib/test/test_zlib.py @@ -751,10 +751,15 @@ def test_large_unconsumed_tail(self, size): def test_wbits(self): # wbits=0 only supported since zlib v1.2.3.5 # Register "1.2.3" as "1.2.3.0" - v = (zlib.ZLIB_RUNTIME_VERSION + ".0").split(".", 4) - supports_wbits_0 = int(v[0]) > 1 or int(v[0]) == 1 \ - and (int(v[1]) > 2 or int(v[1]) == 2 - and (int(v[2]) > 3 or int(v[2]) == 3 and int(v[3]) >= 5)) + # or "1.2.0-linux","1.2.0.f","1.2.0.f-linux" + v = zlib.ZLIB_RUNTIME_VERSION.split('-', 1)[0].split('.') + if len(v) < 4: + v.append('0') + elif not v[-1].isnumeric(): + v[-1] = '0' + + v = tuple(map(int, v)) + supports_wbits_0 = v >= (1, 2, 3, 5) co = zlib.compressobj(level=1, wbits=15) zlib15 = co.compress(HAMLET_SCENE) + co.flush() From solipsis at pitrou.net Mon Feb 19 04:12:49 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Mon, 19 Feb 2018 09:12:49 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=10 Message-ID: <20180219091249.1.15B86E80C1A5B038@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 [-2, 2, 0] memory blocks, sum=0 test_multiprocessing_spawn leaked [-2, 2, -1] memory blocks, sum=-1 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflog_Jch5m', '--timeout', '7200'] From webhook-mailer at python.org Mon Feb 19 15:02:42 2018 From: webhook-mailer at python.org (Zachary Ware) Date: Mon, 19 Feb 2018 20:02:42 -0000 Subject: [Python-checkins] bpo-30121: Fix test_subprocess for Windows Debug builds (GH-5758) Message-ID: https://github.com/python/cpython/commit/5537646bfacec463b450871dde31cb06c44a0556 commit: 5537646bfacec463b450871dde31cb06c44a0556 branch: master author: Zachary Ware committer: GitHub date: 2018-02-19T14:02:38-06:00 summary: bpo-30121: Fix test_subprocess for Windows Debug builds (GH-5758) files: M Lib/test/test_subprocess.py diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index 858a70131205..b3ccb0de63a8 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -1179,7 +1179,7 @@ def test_nonexisting_with_pipes(self): msvcrt.CrtSetReportFile(report_type, msvcrt.CRTDBG_FILE_STDERR) try: - subprocess.Popen([cmd], + subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) except OSError: From webhook-mailer at python.org Mon Feb 19 15:49:49 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 19 Feb 2018 20:49:49 -0000 Subject: [Python-checkins] bpo-30121: Fix test_subprocess for Windows Debug builds (GH-5758) Message-ID: https://github.com/python/cpython/commit/ef0bb5c7b76a49a5f3c5b85b5f9112cfefe54328 commit: ef0bb5c7b76a49a5f3c5b85b5f9112cfefe54328 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-19T12:49:46-08:00 summary: bpo-30121: Fix test_subprocess for Windows Debug builds (GH-5758) (cherry picked from commit 5537646bfacec463b450871dde31cb06c44a0556) Co-authored-by: Zachary Ware files: M Lib/test/test_subprocess.py diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index d7eb982dc574..5c6429cc0227 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -1183,7 +1183,7 @@ def test_nonexisting_with_pipes(self): msvcrt.CrtSetReportFile(report_type, msvcrt.CRTDBG_FILE_STDERR) try: - subprocess.Popen([cmd], + subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) except OSError: From webhook-mailer at python.org Mon Feb 19 16:00:25 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 19 Feb 2018 21:00:25 -0000 Subject: [Python-checkins] bpo-30121: Fix test_subprocess for Windows Debug builds (GH-5758) Message-ID: https://github.com/python/cpython/commit/622a824802771fc5aa133ae92101bc8303360294 commit: 622a824802771fc5aa133ae92101bc8303360294 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-19T13:00:22-08:00 summary: bpo-30121: Fix test_subprocess for Windows Debug builds (GH-5758) (cherry picked from commit 5537646bfacec463b450871dde31cb06c44a0556) Co-authored-by: Zachary Ware files: M Lib/test/test_subprocess.py diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index 858a70131205..b3ccb0de63a8 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -1179,7 +1179,7 @@ def test_nonexisting_with_pipes(self): msvcrt.CrtSetReportFile(report_type, msvcrt.CRTDBG_FILE_STDERR) try: - subprocess.Popen([cmd], + subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) except OSError: From webhook-mailer at python.org Mon Feb 19 18:39:29 2018 From: webhook-mailer at python.org (Raymond Hettinger) Date: Mon, 19 Feb 2018 23:39:29 -0000 Subject: [Python-checkins] Fix typo in docs (GH-5763) Message-ID: https://github.com/python/cpython/commit/5dc275a2c00839cce4cd717f64fc9456e05d5af3 commit: 5dc275a2c00839cce4cd717f64fc9456e05d5af3 branch: 2.7 author: Raymond Hettinger committer: GitHub date: 2018-02-19T15:39:20-08:00 summary: Fix typo in docs (GH-5763) files: M Doc/library/collections.rst diff --git a/Doc/library/collections.rst b/Doc/library/collections.rst index 679931e089f2..9610419f078e 100644 --- a/Doc/library/collections.rst +++ b/Doc/library/collections.rst @@ -300,7 +300,7 @@ counts, but the output will exclude results with counts of zero or less. .. method:: remove(value) - Removed the first occurrence of *value*. If not found, raises a + Remove the first occurrence of *value*. If not found, raises a :exc:`ValueError`. .. versionadded:: 2.5 From webhook-mailer at python.org Mon Feb 19 20:25:27 2018 From: webhook-mailer at python.org (Steve Dower) Date: Tue, 20 Feb 2018 01:25:27 -0000 Subject: [Python-checkins] bpo-32409: Ensures activate.bat can handle Unicode contents (GH-5757) Message-ID: https://github.com/python/cpython/commit/6240917b773b52f8883387b9e3a5f327a4372068 commit: 6240917b773b52f8883387b9e3a5f327a4372068 branch: master author: Steve Dower committer: GitHub date: 2018-02-19T17:25:24-08:00 summary: bpo-32409: Ensures activate.bat can handle Unicode contents (GH-5757) files: A Misc/NEWS.d/next/Windows/2018-02-19-10-00-57.bpo-32409.nocuDg.rst M Lib/test/test_venv.py M Lib/venv/scripts/nt/activate.bat diff --git a/Lib/test/test_venv.py b/Lib/test/test_venv.py index c55042677067..9cea87e2fefa 100644 --- a/Lib/test/test_venv.py +++ b/Lib/test/test_venv.py @@ -281,6 +281,24 @@ def test_executable_symlinks(self): out, err = p.communicate() self.assertEqual(out.strip(), envpy.encode()) + @unittest.skipUnless(os.name == 'nt', 'only relevant on Windows') + def test_unicode_in_batch_file(self): + """ + Test isolation from system site-packages + """ + rmtree(self.env_dir) + env_dir = os.path.join(os.path.realpath(self.env_dir), '??????') + builder = venv.EnvBuilder(clear=True) + builder.create(env_dir) + activate = os.path.join(env_dir, self.bindir, 'activate.bat') + envpy = os.path.join(env_dir, self.bindir, self.exe) + cmd = [activate, '&', self.exe, '-c', 'print(0)'] + p = subprocess.Popen(cmd, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, encoding='oem', + shell=True) + out, err = p.communicate() + print(err) + self.assertEqual(out.strip(), '0') @skipInVenv class EnsurePipTest(BaseTest): diff --git a/Lib/venv/scripts/nt/activate.bat b/Lib/venv/scripts/nt/activate.bat index d76ca1359627..126049f495fe 100644 --- a/Lib/venv/scripts/nt/activate.bat +++ b/Lib/venv/scripts/nt/activate.bat @@ -1,4 +1,13 @@ @echo off + +rem This file is UTF-8 encoded, so we need to update the current code page while executing it +for /f "tokens=2 delims=:" %%a in ('"%SystemRoot%\System32\chcp.com"') do ( + set "_OLD_CODEPAGE=%%a" +) +if defined _OLD_CODEPAGE ( + "%SystemRoot%\System32\chcp.com" 65001 > nul +) + set "VIRTUAL_ENV=__VENV_DIR__" if not defined PROMPT ( @@ -30,3 +39,7 @@ if defined _OLD_VIRTUAL_PATH ( set "PATH=%VIRTUAL_ENV%\__VENV_BIN_NAME__;%PATH%" :END +if defined _OLD_CODEPAGE ( + "%SystemRoot%\System32\chcp.com" %_OLD_CODEPAGE% > nul + set "_OLD_CODEPAGE=" +) diff --git a/Misc/NEWS.d/next/Windows/2018-02-19-10-00-57.bpo-32409.nocuDg.rst b/Misc/NEWS.d/next/Windows/2018-02-19-10-00-57.bpo-32409.nocuDg.rst new file mode 100644 index 000000000000..36251b0b4783 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2018-02-19-10-00-57.bpo-32409.nocuDg.rst @@ -0,0 +1 @@ +Ensures activate.bat can handle Unicode contents. From webhook-mailer at python.org Mon Feb 19 20:45:06 2018 From: webhook-mailer at python.org (Steve Dower) Date: Tue, 20 Feb 2018 01:45:06 -0000 Subject: [Python-checkins] bpo-32409: Ensures activate.bat can handle Unicode contents (GH-5765) Message-ID: https://github.com/python/cpython/commit/a3d6c1b23b8a49b5003fdbd115d3598fe3d4c4bf commit: a3d6c1b23b8a49b5003fdbd115d3598fe3d4c4bf branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Steve Dower date: 2018-02-19T17:45:02-08:00 summary: bpo-32409: Ensures activate.bat can handle Unicode contents (GH-5765) (cherry picked from commit 6240917b773b52f8883387b9e3a5f327a4372068) Co-authored-by: Steve Dower files: A Misc/NEWS.d/next/Windows/2018-02-19-10-00-57.bpo-32409.nocuDg.rst M Lib/test/test_venv.py M Lib/venv/scripts/nt/activate.bat diff --git a/Lib/test/test_venv.py b/Lib/test/test_venv.py index c55042677067..9cea87e2fefa 100644 --- a/Lib/test/test_venv.py +++ b/Lib/test/test_venv.py @@ -281,6 +281,24 @@ def test_executable_symlinks(self): out, err = p.communicate() self.assertEqual(out.strip(), envpy.encode()) + @unittest.skipUnless(os.name == 'nt', 'only relevant on Windows') + def test_unicode_in_batch_file(self): + """ + Test isolation from system site-packages + """ + rmtree(self.env_dir) + env_dir = os.path.join(os.path.realpath(self.env_dir), '??????') + builder = venv.EnvBuilder(clear=True) + builder.create(env_dir) + activate = os.path.join(env_dir, self.bindir, 'activate.bat') + envpy = os.path.join(env_dir, self.bindir, self.exe) + cmd = [activate, '&', self.exe, '-c', 'print(0)'] + p = subprocess.Popen(cmd, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, encoding='oem', + shell=True) + out, err = p.communicate() + print(err) + self.assertEqual(out.strip(), '0') @skipInVenv class EnsurePipTest(BaseTest): diff --git a/Lib/venv/scripts/nt/activate.bat b/Lib/venv/scripts/nt/activate.bat index d76ca1359627..126049f495fe 100644 --- a/Lib/venv/scripts/nt/activate.bat +++ b/Lib/venv/scripts/nt/activate.bat @@ -1,4 +1,13 @@ @echo off + +rem This file is UTF-8 encoded, so we need to update the current code page while executing it +for /f "tokens=2 delims=:" %%a in ('"%SystemRoot%\System32\chcp.com"') do ( + set "_OLD_CODEPAGE=%%a" +) +if defined _OLD_CODEPAGE ( + "%SystemRoot%\System32\chcp.com" 65001 > nul +) + set "VIRTUAL_ENV=__VENV_DIR__" if not defined PROMPT ( @@ -30,3 +39,7 @@ if defined _OLD_VIRTUAL_PATH ( set "PATH=%VIRTUAL_ENV%\__VENV_BIN_NAME__;%PATH%" :END +if defined _OLD_CODEPAGE ( + "%SystemRoot%\System32\chcp.com" %_OLD_CODEPAGE% > nul + set "_OLD_CODEPAGE=" +) diff --git a/Misc/NEWS.d/next/Windows/2018-02-19-10-00-57.bpo-32409.nocuDg.rst b/Misc/NEWS.d/next/Windows/2018-02-19-10-00-57.bpo-32409.nocuDg.rst new file mode 100644 index 000000000000..36251b0b4783 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2018-02-19-10-00-57.bpo-32409.nocuDg.rst @@ -0,0 +1 @@ +Ensures activate.bat can handle Unicode contents. From webhook-mailer at python.org Mon Feb 19 21:18:46 2018 From: webhook-mailer at python.org (Steve Dower) Date: Tue, 20 Feb 2018 02:18:46 -0000 Subject: [Python-checkins] bpo-32409: Ensures activate.bat can handle Unicode contents (GH-5766) Message-ID: https://github.com/python/cpython/commit/8e149ff481acbb3889c825b8bf7b10aa191f09a7 commit: 8e149ff481acbb3889c825b8bf7b10aa191f09a7 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Steve Dower date: 2018-02-19T18:18:43-08:00 summary: bpo-32409: Ensures activate.bat can handle Unicode contents (GH-5766) (cherry picked from commit 6240917b773b52f8883387b9e3a5f327a4372068) Co-authored-by: Steve Dower files: A Misc/NEWS.d/next/Windows/2018-02-19-10-00-57.bpo-32409.nocuDg.rst M Lib/test/test_venv.py M Lib/venv/scripts/nt/activate.bat diff --git a/Lib/test/test_venv.py b/Lib/test/test_venv.py index 0c1ea89b51c0..2569a1fe49ef 100644 --- a/Lib/test/test_venv.py +++ b/Lib/test/test_venv.py @@ -286,6 +286,24 @@ def test_executable_symlinks(self): out, err = p.communicate() self.assertEqual(out.strip(), envpy.encode()) + @unittest.skipUnless(os.name == 'nt', 'only relevant on Windows') + def test_unicode_in_batch_file(self): + """ + Test isolation from system site-packages + """ + rmtree(self.env_dir) + env_dir = os.path.join(os.path.realpath(self.env_dir), '??????') + builder = venv.EnvBuilder(clear=True) + builder.create(env_dir) + activate = os.path.join(env_dir, self.bindir, 'activate.bat') + envpy = os.path.join(env_dir, self.bindir, self.exe) + cmd = [activate, '&', self.exe, '-c', 'print(0)'] + p = subprocess.Popen(cmd, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, encoding='oem', + shell=True) + out, err = p.communicate() + print(err) + self.assertEqual(out.strip(), '0') @skipInVenv class EnsurePipTest(BaseTest): diff --git a/Lib/venv/scripts/nt/activate.bat b/Lib/venv/scripts/nt/activate.bat index d76ca1359627..126049f495fe 100644 --- a/Lib/venv/scripts/nt/activate.bat +++ b/Lib/venv/scripts/nt/activate.bat @@ -1,4 +1,13 @@ @echo off + +rem This file is UTF-8 encoded, so we need to update the current code page while executing it +for /f "tokens=2 delims=:" %%a in ('"%SystemRoot%\System32\chcp.com"') do ( + set "_OLD_CODEPAGE=%%a" +) +if defined _OLD_CODEPAGE ( + "%SystemRoot%\System32\chcp.com" 65001 > nul +) + set "VIRTUAL_ENV=__VENV_DIR__" if not defined PROMPT ( @@ -30,3 +39,7 @@ if defined _OLD_VIRTUAL_PATH ( set "PATH=%VIRTUAL_ENV%\__VENV_BIN_NAME__;%PATH%" :END +if defined _OLD_CODEPAGE ( + "%SystemRoot%\System32\chcp.com" %_OLD_CODEPAGE% > nul + set "_OLD_CODEPAGE=" +) diff --git a/Misc/NEWS.d/next/Windows/2018-02-19-10-00-57.bpo-32409.nocuDg.rst b/Misc/NEWS.d/next/Windows/2018-02-19-10-00-57.bpo-32409.nocuDg.rst new file mode 100644 index 000000000000..36251b0b4783 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2018-02-19-10-00-57.bpo-32409.nocuDg.rst @@ -0,0 +1 @@ +Ensures activate.bat can handle Unicode contents. From webhook-mailer at python.org Tue Feb 20 02:25:55 2018 From: webhook-mailer at python.org (Benjamin Peterson) Date: Tue, 20 Feb 2018 07:25:55 -0000 Subject: [Python-checkins] closes bpo-32859: Don't retry dup3() if it is not available at runtime (GH-5708) Message-ID: https://github.com/python/cpython/commit/b3caf388a0418f6c031e4dbdcc0c1ce7e5cc36bd commit: b3caf388a0418f6c031e4dbdcc0c1ce7e5cc36bd branch: master author: Alexey Izbyshev committer: Benjamin Peterson date: 2018-02-19T23:25:46-08:00 summary: closes bpo-32859: Don't retry dup3() if it is not available at runtime (GH-5708) os.dup2() tests for dup3() system call availability at runtime, but doesn't remember the result across calls, repeating the test on each call with inheritable=False. Since the caller of os.dup2() is expected to hold the GIL, fix this by making the variable holding the test result static. files: A Misc/NEWS.d/next/Library/2018-02-19-17-46-31.bpo-32859.kAT-Xp.rst M Modules/posixmodule.c diff --git a/Misc/NEWS.d/next/Library/2018-02-19-17-46-31.bpo-32859.kAT-Xp.rst b/Misc/NEWS.d/next/Library/2018-02-19-17-46-31.bpo-32859.kAT-Xp.rst new file mode 100644 index 000000000000..755bdc118610 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-19-17-46-31.bpo-32859.kAT-Xp.rst @@ -0,0 +1,2 @@ +In ``os.dup2``, don't check every call whether the ``dup3`` syscall exists +or not. diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index d242df0b6f31..0bbf7c57961f 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -8016,7 +8016,7 @@ os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable) #if defined(HAVE_DUP3) && \ !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)) /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */ - int dup3_works = -1; + static int dup3_works = -1; #endif if (fd < 0 || fd2 < 0) { From webhook-mailer at python.org Tue Feb 20 02:46:50 2018 From: webhook-mailer at python.org (Benjamin Peterson) Date: Tue, 20 Feb 2018 07:46:50 -0000 Subject: [Python-checkins] closes bpo-32859: Don't retry dup3() if it is not available at runtime (GH-5708) Message-ID: https://github.com/python/cpython/commit/bab4fe320ad2e24c1084fd57d2059ef342688aa9 commit: bab4fe320ad2e24c1084fd57d2059ef342688aa9 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Benjamin Peterson date: 2018-02-19T23:46:47-08:00 summary: closes bpo-32859: Don't retry dup3() if it is not available at runtime (GH-5708) os.dup2() tests for dup3() system call availability at runtime, but doesn't remember the result across calls, repeating the test on each call with inheritable=False. Since the caller of os.dup2() is expected to hold the GIL, fix this by making the variable holding the test result static. (cherry picked from commit b3caf388a0418f6c031e4dbdcc0c1ce7e5cc36bd) Co-authored-by: Alexey Izbyshev files: A Misc/NEWS.d/next/Library/2018-02-19-17-46-31.bpo-32859.kAT-Xp.rst M Modules/posixmodule.c diff --git a/Misc/NEWS.d/next/Library/2018-02-19-17-46-31.bpo-32859.kAT-Xp.rst b/Misc/NEWS.d/next/Library/2018-02-19-17-46-31.bpo-32859.kAT-Xp.rst new file mode 100644 index 000000000000..755bdc118610 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-19-17-46-31.bpo-32859.kAT-Xp.rst @@ -0,0 +1,2 @@ +In ``os.dup2``, don't check every call whether the ``dup3`` syscall exists +or not. diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 7304feed72df..eff74dffceec 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -8016,7 +8016,7 @@ os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable) #if defined(HAVE_DUP3) && \ !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)) /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */ - int dup3_works = -1; + static int dup3_works = -1; #endif if (fd < 0 || fd2 < 0) { From solipsis at pitrou.net Tue Feb 20 04:12:38 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Tue, 20 Feb 2018 09:12:38 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=10 Message-ID: <20180220091238.1.738068267F7B9572@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, 1, -2] memory blocks, sum=0 test_multiprocessing_forkserver leaked [0, -2, 1] memory blocks, sum=-1 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogMHxEdS', '--timeout', '7200'] From webhook-mailer at python.org Tue Feb 20 12:24:33 2018 From: webhook-mailer at python.org (Mariatta) Date: Tue, 20 Feb 2018 17:24:33 -0000 Subject: [Python-checkins] bpo-32500: Correct the documentation for PySequence_Size() and PySequence_Length() (GH-5767) Message-ID: https://github.com/python/cpython/commit/7a1e1786f98ad49caa157dcdf14ada9d0b07d0fd commit: 7a1e1786f98ad49caa157dcdf14ada9d0b07d0fd branch: master author: Zackery Spytz committer: Mariatta date: 2018-02-20T09:24:29-08:00 summary: bpo-32500: Correct the documentation for PySequence_Size() and PySequence_Length() (GH-5767) Dropped the part that says: "For objects that do not provide sequence protocol". files: M Doc/c-api/sequence.rst diff --git a/Doc/c-api/sequence.rst b/Doc/c-api/sequence.rst index f1825f079be4..81f8557ea6e6 100644 --- a/Doc/c-api/sequence.rst +++ b/Doc/c-api/sequence.rst @@ -17,9 +17,8 @@ Sequence Protocol .. index:: builtin: len - Returns the number of objects in sequence *o* on success, and ``-1`` on failure. - For objects that do not provide sequence protocol, this is equivalent to the - Python expression ``len(o)``. + Returns the number of objects in sequence *o* on success, and ``-1`` on + failure. This is equivalent to the Python expression ``len(o)``. .. c:function:: PyObject* PySequence_Concat(PyObject *o1, PyObject *o2) From webhook-mailer at python.org Tue Feb 20 14:46:18 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 20 Feb 2018 19:46:18 -0000 Subject: [Python-checkins] bpo-32500: Correct the documentation for PySequence_Size() and PySequence_Length() (GH-5767) Message-ID: https://github.com/python/cpython/commit/6ae87cae091f4835090c10c1e65eb057a13fca2c commit: 6ae87cae091f4835090c10c1e65eb057a13fca2c branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-20T11:46:06-08:00 summary: bpo-32500: Correct the documentation for PySequence_Size() and PySequence_Length() (GH-5767) Dropped the part that says: "For objects that do not provide sequence protocol". (cherry picked from commit 7a1e1786f98ad49caa157dcdf14ada9d0b07d0fd) Co-authored-by: Zackery Spytz files: M Doc/c-api/sequence.rst diff --git a/Doc/c-api/sequence.rst b/Doc/c-api/sequence.rst index f1825f079be4..81f8557ea6e6 100644 --- a/Doc/c-api/sequence.rst +++ b/Doc/c-api/sequence.rst @@ -17,9 +17,8 @@ Sequence Protocol .. index:: builtin: len - Returns the number of objects in sequence *o* on success, and ``-1`` on failure. - For objects that do not provide sequence protocol, this is equivalent to the - Python expression ``len(o)``. + Returns the number of objects in sequence *o* on success, and ``-1`` on + failure. This is equivalent to the Python expression ``len(o)``. .. c:function:: PyObject* PySequence_Concat(PyObject *o1, PyObject *o2) From webhook-mailer at python.org Tue Feb 20 16:06:14 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Tue, 20 Feb 2018 21:06:14 -0000 Subject: [Python-checkins] bpo-31848: Fix broken error handling in Aifc_read.initfp() when the SSND chunk is not found (#5240) Message-ID: https://github.com/python/cpython/commit/80d20b918bd8a882043c493a7f958333ecb41727 commit: 80d20b918bd8a882043c493a7f958333ecb41727 branch: master author: Zackery Spytz committer: Serhiy Storchaka date: 2018-02-20T23:06:11+02:00 summary: bpo-31848: Fix broken error handling in Aifc_read.initfp() when the SSND chunk is not found (#5240) Initialize self._ssnd_chunk so that aifc.Error is raised as intended, not AttributeError. files: A Misc/NEWS.d/next/Library/2018-01-18-23-34-17.bpo-31848.M2cldy.rst M Lib/aifc.py M Lib/test/test_aifc.py M Misc/ACKS diff --git a/Lib/aifc.py b/Lib/aifc.py index e51e8f8e4840..3d2dc56de198 100644 --- a/Lib/aifc.py +++ b/Lib/aifc.py @@ -322,6 +322,7 @@ def initfp(self, file): else: raise Error('not an AIFF or AIFF-C file') self._comm_chunk_read = 0 + self._ssnd_chunk = None while 1: self._ssnd_seek_needed = 1 try: diff --git a/Lib/test/test_aifc.py b/Lib/test/test_aifc.py index a064a3247057..8fd306a36592 100644 --- a/Lib/test/test_aifc.py +++ b/Lib/test/test_aifc.py @@ -266,6 +266,14 @@ def test_read_no_comm_chunk(self): b = io.BytesIO(b'FORM' + struct.pack('>L', 4) + b'AIFF') self.assertRaises(aifc.Error, aifc.open, b) + def test_read_no_ssnd_chunk(self): + b = b'FORM' + struct.pack('>L', 4) + b'AIFC' + b += b'COMM' + struct.pack('>LhlhhLL', 38, 0, 0, 0, 0, 0, 0) + b += b'NONE' + struct.pack('B', 14) + b'not compressed' + b'\x00' + with self.assertRaisesRegex(aifc.Error, 'COMM chunk and/or SSND chunk' + ' missing'): + aifc.open(io.BytesIO(b)) + def test_read_wrong_compression_type(self): b = b'FORM' + struct.pack('>L', 4) + b'AIFC' b += b'COMM' + struct.pack('>LhlhhLL', 23, 0, 0, 0, 0, 0, 0) diff --git a/Misc/ACKS b/Misc/ACKS index ea1d9418870a..b15b20e6c1c0 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1512,6 +1512,7 @@ Nicholas Spies Per Spilling Joshua Spoerri Noah Spurrier +Zackery Spytz Nathan Srebro RajGopal Srinivasan Tage Stabell-Kulo diff --git a/Misc/NEWS.d/next/Library/2018-01-18-23-34-17.bpo-31848.M2cldy.rst b/Misc/NEWS.d/next/Library/2018-01-18-23-34-17.bpo-31848.M2cldy.rst new file mode 100644 index 000000000000..c8e61acb0b06 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-01-18-23-34-17.bpo-31848.M2cldy.rst @@ -0,0 +1,2 @@ +Fix the error handling in Aifc_read.initfp() when the SSND chunk is not found. +Patch by Zackery Spytz. From webhook-mailer at python.org Tue Feb 20 17:07:08 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 20 Feb 2018 22:07:08 -0000 Subject: [Python-checkins] bpo-31848: Fix broken error handling in Aifc_read.initfp() when the SSND chunk is not found (GH-5240) Message-ID: https://github.com/python/cpython/commit/1d927d4feba856cacc026a9167ba38c73a4e7657 commit: 1d927d4feba856cacc026a9167ba38c73a4e7657 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-20T14:06:58-08:00 summary: bpo-31848: Fix broken error handling in Aifc_read.initfp() when the SSND chunk is not found (GH-5240) Initialize self._ssnd_chunk so that aifc.Error is raised as intended, not AttributeError. (cherry picked from commit 80d20b918bd8a882043c493a7f958333ecb41727) Co-authored-by: Zackery Spytz files: A Misc/NEWS.d/next/Library/2018-01-18-23-34-17.bpo-31848.M2cldy.rst M Lib/aifc.py M Lib/test/test_aifc.py M Misc/ACKS diff --git a/Lib/aifc.py b/Lib/aifc.py index e51e8f8e4840..3d2dc56de198 100644 --- a/Lib/aifc.py +++ b/Lib/aifc.py @@ -322,6 +322,7 @@ def initfp(self, file): else: raise Error('not an AIFF or AIFF-C file') self._comm_chunk_read = 0 + self._ssnd_chunk = None while 1: self._ssnd_seek_needed = 1 try: diff --git a/Lib/test/test_aifc.py b/Lib/test/test_aifc.py index a064a3247057..8fd306a36592 100644 --- a/Lib/test/test_aifc.py +++ b/Lib/test/test_aifc.py @@ -266,6 +266,14 @@ def test_read_no_comm_chunk(self): b = io.BytesIO(b'FORM' + struct.pack('>L', 4) + b'AIFF') self.assertRaises(aifc.Error, aifc.open, b) + def test_read_no_ssnd_chunk(self): + b = b'FORM' + struct.pack('>L', 4) + b'AIFC' + b += b'COMM' + struct.pack('>LhlhhLL', 38, 0, 0, 0, 0, 0, 0) + b += b'NONE' + struct.pack('B', 14) + b'not compressed' + b'\x00' + with self.assertRaisesRegex(aifc.Error, 'COMM chunk and/or SSND chunk' + ' missing'): + aifc.open(io.BytesIO(b)) + def test_read_wrong_compression_type(self): b = b'FORM' + struct.pack('>L', 4) + b'AIFC' b += b'COMM' + struct.pack('>LhlhhLL', 23, 0, 0, 0, 0, 0, 0) diff --git a/Misc/ACKS b/Misc/ACKS index b31190ca5283..17505dfdcf0a 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1511,6 +1511,7 @@ Nicholas Spies Per Spilling Joshua Spoerri Noah Spurrier +Zackery Spytz Nathan Srebro RajGopal Srinivasan Tage Stabell-Kulo diff --git a/Misc/NEWS.d/next/Library/2018-01-18-23-34-17.bpo-31848.M2cldy.rst b/Misc/NEWS.d/next/Library/2018-01-18-23-34-17.bpo-31848.M2cldy.rst new file mode 100644 index 000000000000..c8e61acb0b06 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-01-18-23-34-17.bpo-31848.M2cldy.rst @@ -0,0 +1,2 @@ +Fix the error handling in Aifc_read.initfp() when the SSND chunk is not found. +Patch by Zackery Spytz. From webhook-mailer at python.org Tue Feb 20 17:17:33 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 20 Feb 2018 22:17:33 -0000 Subject: [Python-checkins] bpo-31848: Fix broken error handling in Aifc_read.initfp() when the SSND chunk is not found (GH-5240) Message-ID: https://github.com/python/cpython/commit/2b9726eb647e856d83eafdc30cdbbc31a5920ab6 commit: 2b9726eb647e856d83eafdc30cdbbc31a5920ab6 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-20T14:17:30-08:00 summary: bpo-31848: Fix broken error handling in Aifc_read.initfp() when the SSND chunk is not found (GH-5240) Initialize self._ssnd_chunk so that aifc.Error is raised as intended, not AttributeError. (cherry picked from commit 80d20b918bd8a882043c493a7f958333ecb41727) Co-authored-by: Zackery Spytz files: A Misc/NEWS.d/next/Library/2018-01-18-23-34-17.bpo-31848.M2cldy.rst M Lib/aifc.py M Lib/test/test_aifc.py M Misc/ACKS diff --git a/Lib/aifc.py b/Lib/aifc.py index 13ad7dc5ca3d..9df6cd1d5e9c 100644 --- a/Lib/aifc.py +++ b/Lib/aifc.py @@ -322,6 +322,7 @@ def initfp(self, file): else: raise Error('not an AIFF or AIFF-C file') self._comm_chunk_read = 0 + self._ssnd_chunk = None while 1: self._ssnd_seek_needed = 1 try: diff --git a/Lib/test/test_aifc.py b/Lib/test/test_aifc.py index a731a5136ba5..9e8cd17be14b 100644 --- a/Lib/test/test_aifc.py +++ b/Lib/test/test_aifc.py @@ -263,6 +263,14 @@ def test_read_no_comm_chunk(self): b = io.BytesIO(b'FORM' + struct.pack('>L', 4) + b'AIFF') self.assertRaises(aifc.Error, aifc.open, b) + def test_read_no_ssnd_chunk(self): + b = b'FORM' + struct.pack('>L', 4) + b'AIFC' + b += b'COMM' + struct.pack('>LhlhhLL', 38, 0, 0, 0, 0, 0, 0) + b += b'NONE' + struct.pack('B', 14) + b'not compressed' + b'\x00' + with self.assertRaisesRegex(aifc.Error, 'COMM chunk and/or SSND chunk' + ' missing'): + aifc.open(io.BytesIO(b)) + def test_read_wrong_compression_type(self): b = b'FORM' + struct.pack('>L', 4) + b'AIFC' b += b'COMM' + struct.pack('>LhlhhLL', 23, 0, 0, 0, 0, 0, 0) diff --git a/Misc/ACKS b/Misc/ACKS index 0e64609df64e..2a7b1b8140a4 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1478,6 +1478,7 @@ Nicholas Spies Per Spilling Joshua Spoerri Noah Spurrier +Zackery Spytz Nathan Srebro RajGopal Srinivasan Tage Stabell-Kulo diff --git a/Misc/NEWS.d/next/Library/2018-01-18-23-34-17.bpo-31848.M2cldy.rst b/Misc/NEWS.d/next/Library/2018-01-18-23-34-17.bpo-31848.M2cldy.rst new file mode 100644 index 000000000000..c8e61acb0b06 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-01-18-23-34-17.bpo-31848.M2cldy.rst @@ -0,0 +1,2 @@ +Fix the error handling in Aifc_read.initfp() when the SSND chunk is not found. +Patch by Zackery Spytz. From webhook-mailer at python.org Tue Feb 20 18:30:26 2018 From: webhook-mailer at python.org (Eric Snow) Date: Tue, 20 Feb 2018 23:30:26 -0000 Subject: [Python-checkins] bpo-32604: Swap threads only if the interpreter is different. (gh-5778) Message-ID: https://github.com/python/cpython/commit/f53d9f2778a87bdd48eb9030f782a4ebf9e7622f commit: f53d9f2778a87bdd48eb9030f782a4ebf9e7622f branch: master author: Eric Snow committer: GitHub date: 2018-02-20T16:30:17-07:00 summary: bpo-32604: Swap threads only if the interpreter is different. (gh-5778) The CPython runtime assumes that there is a one-to-one relationship (for a given interpreter) between PyThreadState and OS threads. Sending and receiving on a channel in the same interpreter was causing crashes because of this (specifically due to a check in PyThreadState_Swap()). The solution is to not switch threads if the interpreter is the same. 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 d280270af91b..397d3599312b 100644 --- a/Lib/test/test__xxsubinterpreters.py +++ b/Lib/test/test__xxsubinterpreters.py @@ -3,6 +3,7 @@ import pickle from textwrap import dedent, indent import threading +import time import unittest from test import support @@ -1147,6 +1148,54 @@ def test_send_recv_different_interpreters(self): 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') diff --git a/Modules/_xxsubinterpretersmodule.c b/Modules/_xxsubinterpretersmodule.c index d7588079f225..49d3b48e3879 100644 --- a/Modules/_xxsubinterpretersmodule.c +++ b/Modules/_xxsubinterpretersmodule.c @@ -1759,8 +1759,13 @@ _run_script_in_interpreter(PyInterpreterState *interp, const char *codestr, } // Switch to interpreter. - PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); - PyThreadState *save_tstate = PyThreadState_Swap(tstate); + 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; @@ -2079,9 +2084,9 @@ interp_create(PyObject *self, PyObject *args) } // Create and initialize the new interpreter. - PyThreadState *tstate, *save_tstate; - save_tstate = PyThreadState_Swap(NULL); - tstate = Py_NewInterpreter(); + 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 @@ -2096,6 +2101,7 @@ interp_create(PyObject *self, PyObject *args) return _get_id(tstate->interp); error: + // XXX Possible GILState issues? save_tstate = PyThreadState_Swap(tstate); Py_EndInterpreter(tstate); PyThreadState_Swap(save_tstate); @@ -2146,9 +2152,9 @@ interp_destroy(PyObject *self, PyObject *args) // Destroy the interpreter. //PyInterpreterState_Delete(interp); - PyThreadState *tstate, *save_tstate; - tstate = PyInterpreterState_ThreadHead(interp); - save_tstate = PyThreadState_Swap(tstate); + PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); + // XXX Possible GILState issues? + PyThreadState *save_tstate = PyThreadState_Swap(tstate); Py_EndInterpreter(tstate); PyThreadState_Swap(save_tstate); diff --git a/Python/pystate.c b/Python/pystate.c index 8cbf1fa10a59..a87801f56922 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -331,9 +331,10 @@ _PyInterpreterState_IDDecref(PyInterpreterState *interp) PyThread_release_lock(interp->id_mutex); if (refcount == 0) { - PyThreadState *tstate, *save_tstate; - tstate = PyInterpreterState_ThreadHead(interp); - save_tstate = PyThreadState_Swap(tstate); + // XXX Using the "head" thread isn't strictly correct. + PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); + // XXX Possible GILState issues? + PyThreadState *save_tstate = PyThreadState_Swap(tstate); Py_EndInterpreter(tstate); PyThreadState_Swap(save_tstate); } @@ -1213,8 +1214,14 @@ _PyCrossInterpreterData_Release(_PyCrossInterpreterData *data) } return; } - PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); - PyThreadState *save_tstate = PyThreadState_Swap(tstate); + + 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) { @@ -1223,8 +1230,9 @@ _PyCrossInterpreterData_Release(_PyCrossInterpreterData *data) Py_XDECREF(data->obj); // Switch back. - if (save_tstate != NULL) + if (save_tstate != NULL) { PyThreadState_Swap(save_tstate); + } } PyObject * From webhook-mailer at python.org Tue Feb 20 19:09:45 2018 From: webhook-mailer at python.org (Eric Snow) Date: Wed, 21 Feb 2018 00:09:45 -0000 Subject: [Python-checkins] bpo-32604: Swap threads only if the interpreter is different. (gh-5783) Message-ID: https://github.com/python/cpython/commit/eed3c7af4ec520d324a55e0357f41589a66906f7 commit: eed3c7af4ec520d324a55e0357f41589a66906f7 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Eric Snow date: 2018-02-20T17:09:41-07:00 summary: bpo-32604: Swap threads only if the interpreter is different. (gh-5783) The CPython runtime assumes that there is a one-to-one relationship (for a given interpreter) between PyThreadState and OS threads. Sending and receiving on a channel in the same interpreter was causing crashes because of this (specifically due to a check in PyThreadState_Swap()). The solution is to not switch threads if the interpreter is the same. (cherry picked from commit f53d9f2778a87bdd48eb9030f782a4ebf9e7622f) Co-authored-by: Eric Snow 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 d280270af91b..397d3599312b 100644 --- a/Lib/test/test__xxsubinterpreters.py +++ b/Lib/test/test__xxsubinterpreters.py @@ -3,6 +3,7 @@ import pickle from textwrap import dedent, indent import threading +import time import unittest from test import support @@ -1147,6 +1148,54 @@ def test_send_recv_different_interpreters(self): 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') diff --git a/Modules/_xxsubinterpretersmodule.c b/Modules/_xxsubinterpretersmodule.c index d7588079f225..49d3b48e3879 100644 --- a/Modules/_xxsubinterpretersmodule.c +++ b/Modules/_xxsubinterpretersmodule.c @@ -1759,8 +1759,13 @@ _run_script_in_interpreter(PyInterpreterState *interp, const char *codestr, } // Switch to interpreter. - PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); - PyThreadState *save_tstate = PyThreadState_Swap(tstate); + 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; @@ -2079,9 +2084,9 @@ interp_create(PyObject *self, PyObject *args) } // Create and initialize the new interpreter. - PyThreadState *tstate, *save_tstate; - save_tstate = PyThreadState_Swap(NULL); - tstate = Py_NewInterpreter(); + 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 @@ -2096,6 +2101,7 @@ interp_create(PyObject *self, PyObject *args) return _get_id(tstate->interp); error: + // XXX Possible GILState issues? save_tstate = PyThreadState_Swap(tstate); Py_EndInterpreter(tstate); PyThreadState_Swap(save_tstate); @@ -2146,9 +2152,9 @@ interp_destroy(PyObject *self, PyObject *args) // Destroy the interpreter. //PyInterpreterState_Delete(interp); - PyThreadState *tstate, *save_tstate; - tstate = PyInterpreterState_ThreadHead(interp); - save_tstate = PyThreadState_Swap(tstate); + PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); + // XXX Possible GILState issues? + PyThreadState *save_tstate = PyThreadState_Swap(tstate); Py_EndInterpreter(tstate); PyThreadState_Swap(save_tstate); diff --git a/Python/pystate.c b/Python/pystate.c index 8cbf1fa10a59..a87801f56922 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -331,9 +331,10 @@ _PyInterpreterState_IDDecref(PyInterpreterState *interp) PyThread_release_lock(interp->id_mutex); if (refcount == 0) { - PyThreadState *tstate, *save_tstate; - tstate = PyInterpreterState_ThreadHead(interp); - save_tstate = PyThreadState_Swap(tstate); + // XXX Using the "head" thread isn't strictly correct. + PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); + // XXX Possible GILState issues? + PyThreadState *save_tstate = PyThreadState_Swap(tstate); Py_EndInterpreter(tstate); PyThreadState_Swap(save_tstate); } @@ -1213,8 +1214,14 @@ _PyCrossInterpreterData_Release(_PyCrossInterpreterData *data) } return; } - PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); - PyThreadState *save_tstate = PyThreadState_Swap(tstate); + + 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) { @@ -1223,8 +1230,9 @@ _PyCrossInterpreterData_Release(_PyCrossInterpreterData *data) Py_XDECREF(data->obj); // Switch back. - if (save_tstate != NULL) + if (save_tstate != NULL) { PyThreadState_Swap(save_tstate); + } } PyObject * From webhook-mailer at python.org Tue Feb 20 23:25:39 2018 From: webhook-mailer at python.org (Mariatta) Date: Wed, 21 Feb 2018 04:25:39 -0000 Subject: [Python-checkins] bpo-32540: Update venv documentation (GH-5736) Message-ID: https://github.com/python/cpython/commit/98a86cbb9bed94a232263698041acd2775da3dad commit: 98a86cbb9bed94a232263698041acd2775da3dad branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Mariatta date: 2018-02-20T20:25:37-08:00 summary: bpo-32540: Update venv documentation (GH-5736) If the directory already exists, it will be re-used. (cherry picked from commit e8eb972514cad6086b752754c1d34d703c04dd82) Co-authored-by: TROUVERIE Joachim files: M Doc/using/venv-create.inc diff --git a/Doc/using/venv-create.inc b/Doc/using/venv-create.inc index 4292592ba7a2..4c7795ad8019 100644 --- a/Doc/using/venv-create.inc +++ b/Doc/using/venv-create.inc @@ -9,7 +9,8 @@ with a ``home`` key pointing to the Python installation from which the command was run. It also creates a ``bin`` (or ``Scripts`` on Windows) subdirectory containing a copy of the ``python`` binary (or binaries, in the case of Windows). It also creates an (initially empty) ``lib/pythonX.Y/site-packages`` -subdirectory (on Windows, this is ``Lib\site-packages``). +subdirectory (on Windows, this is ``Lib\site-packages``). If an existing +directory is specified, it will be re-used. .. deprecated:: 3.6 ``pyvenv`` was the recommended tool for creating virtual environments for @@ -71,9 +72,7 @@ The command, if run with ``-h``, will show the available options:: .. versionchanged:: 3.4 In earlier versions, if the target directory already existed, an error was - raised, unless the ``--clear`` or ``--upgrade`` option was provided. Now, - if an existing directory is specified, its contents are removed and - the directory is processed as if it had been newly created. + raised, unless the ``--clear`` or ``--upgrade`` option was provided. The created ``pyvenv.cfg`` file also includes the ``include-system-site-packages`` key, set to ``true`` if ``venv`` is From webhook-mailer at python.org Tue Feb 20 23:26:24 2018 From: webhook-mailer at python.org (Mariatta) Date: Wed, 21 Feb 2018 04:26:24 -0000 Subject: [Python-checkins] bpo-32540: Update venv documentation (GH-5736) Message-ID: https://github.com/python/cpython/commit/76c3f5eeb07aeb037da1ed6761dd9bd95e2c1d8d commit: 76c3f5eeb07aeb037da1ed6761dd9bd95e2c1d8d branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Mariatta date: 2018-02-20T20:26:21-08:00 summary: bpo-32540: Update venv documentation (GH-5736) If the directory already exists, it will be re-used. (cherry picked from commit e8eb972514cad6086b752754c1d34d703c04dd82) Co-authored-by: TROUVERIE Joachim files: M Doc/using/venv-create.inc diff --git a/Doc/using/venv-create.inc b/Doc/using/venv-create.inc index 4292592ba7a2..4c7795ad8019 100644 --- a/Doc/using/venv-create.inc +++ b/Doc/using/venv-create.inc @@ -9,7 +9,8 @@ with a ``home`` key pointing to the Python installation from which the command was run. It also creates a ``bin`` (or ``Scripts`` on Windows) subdirectory containing a copy of the ``python`` binary (or binaries, in the case of Windows). It also creates an (initially empty) ``lib/pythonX.Y/site-packages`` -subdirectory (on Windows, this is ``Lib\site-packages``). +subdirectory (on Windows, this is ``Lib\site-packages``). If an existing +directory is specified, it will be re-used. .. deprecated:: 3.6 ``pyvenv`` was the recommended tool for creating virtual environments for @@ -71,9 +72,7 @@ The command, if run with ``-h``, will show the available options:: .. versionchanged:: 3.4 In earlier versions, if the target directory already existed, an error was - raised, unless the ``--clear`` or ``--upgrade`` option was provided. Now, - if an existing directory is specified, its contents are removed and - the directory is processed as if it had been newly created. + raised, unless the ``--clear`` or ``--upgrade`` option was provided. The created ``pyvenv.cfg`` file also includes the ``include-system-site-packages`` key, set to ``true`` if ``venv`` is From webhook-mailer at python.org Tue Feb 20 23:30:04 2018 From: webhook-mailer at python.org (INADA Naoki) Date: Wed, 21 Feb 2018 04:30:04 -0000 Subject: [Python-checkins] bpo-28886: doc: Move deprecated abc decorators to separate section (GH-176) Message-ID: https://github.com/python/cpython/commit/52c6b89796a7ec391db20281e05b256f57e97b35 commit: 52c6b89796a7ec391db20281e05b256f57e97b35 branch: master author: Harshul jain committer: INADA Naoki date: 2018-02-21T13:30:01+09:00 summary: bpo-28886: doc: Move deprecated abc decorators to separate section (GH-176) files: M Doc/library/abc.rst diff --git a/Doc/library/abc.rst b/Doc/library/abc.rst index 9522dd620491..70710761a395 100644 --- a/Doc/library/abc.rst +++ b/Doc/library/abc.rst @@ -160,7 +160,7 @@ a helper class :class:`ABC` to alternatively define ABCs through inheritance: -The :mod:`abc` module also provides the following decorators: +The :mod:`abc` module also provides the following decorator: .. decorator:: abstractmethod @@ -236,8 +236,15 @@ The :mod:`abc` module also provides the following decorators: multiple-inheritance. +The :mod:`abc` module also supports the following legacy decorators: + .. decorator:: abstractclassmethod + .. versionadded:: 3.2 + .. deprecated:: 3.3 + It is now possible to use :class:`classmethod` with + :func:`abstractmethod`, making this decorator redundant. + A subclass of the built-in :func:`classmethod`, indicating an abstract classmethod. Otherwise it is similar to :func:`abstractmethod`. @@ -251,14 +258,14 @@ The :mod:`abc` module also provides the following decorators: def my_abstract_classmethod(cls, ...): ... + +.. decorator:: abstractstaticmethod + .. versionadded:: 3.2 .. deprecated:: 3.3 - It is now possible to use :class:`classmethod` with + It is now possible to use :class:`staticmethod` with :func:`abstractmethod`, making this decorator redundant. - -.. decorator:: abstractstaticmethod - A subclass of the built-in :func:`staticmethod`, indicating an abstract staticmethod. Otherwise it is similar to :func:`abstractmethod`. @@ -272,23 +279,17 @@ The :mod:`abc` module also provides the following decorators: def my_abstract_staticmethod(...): ... - .. versionadded:: 3.2 - .. deprecated:: 3.3 - It is now possible to use :class:`staticmethod` with - :func:`abstractmethod`, making this decorator redundant. - .. decorator:: abstractproperty + .. deprecated:: 3.3 + It is now possible to use :class:`property`, :meth:`property.getter`, + :meth:`property.setter` and :meth:`property.deleter` with + :func:`abstractmethod`, making this decorator redundant. + A subclass of the built-in :func:`property`, indicating an abstract property. - Using this function requires that the class's metaclass is :class:`ABCMeta` - or is derived from it. A class that has a metaclass derived from - :class:`ABCMeta` cannot be instantiated unless all of its abstract methods - and properties are overridden. The abstract properties can be called using - any of the normal 'super' call mechanisms. - This special case is deprecated, as the :func:`property` decorator is now correctly identified as abstract when applied to an abstract method:: @@ -322,12 +323,6 @@ The :mod:`abc` module also provides the following decorators: ... - .. deprecated:: 3.3 - It is now possible to use :class:`property`, :meth:`property.getter`, - :meth:`property.setter` and :meth:`property.deleter` with - :func:`abstractmethod`, making this decorator redundant. - - The :mod:`abc` module also provides the following functions: .. function:: get_cache_token() From webhook-mailer at python.org Wed Feb 21 00:21:16 2018 From: webhook-mailer at python.org (Benjamin Peterson) Date: Wed, 21 Feb 2018 05:21:16 -0000 Subject: [Python-checkins] closes bpo-32859: Don't retry dup3() if it is not available at runtime (GH-5708) Message-ID: https://github.com/python/cpython/commit/16de2a9b8697cf90840eb217fb079f9c4c73e588 commit: 16de2a9b8697cf90840eb217fb079f9c4c73e588 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Benjamin Peterson date: 2018-02-20T21:21:12-08:00 summary: closes bpo-32859: Don't retry dup3() if it is not available at runtime (GH-5708) os.dup2() tests for dup3() system call availability at runtime, but doesn't remember the result across calls, repeating the test on each call with inheritable=False. Since the caller of os.dup2() is expected to hold the GIL, fix this by making the variable holding the test result static. (cherry picked from commit b3caf388a0418f6c031e4dbdcc0c1ce7e5cc36bd) Co-authored-by: Alexey Izbyshev files: A Misc/NEWS.d/next/Library/2018-02-19-17-46-31.bpo-32859.kAT-Xp.rst M Modules/posixmodule.c diff --git a/Misc/NEWS.d/next/Library/2018-02-19-17-46-31.bpo-32859.kAT-Xp.rst b/Misc/NEWS.d/next/Library/2018-02-19-17-46-31.bpo-32859.kAT-Xp.rst new file mode 100644 index 000000000000..755bdc118610 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-19-17-46-31.bpo-32859.kAT-Xp.rst @@ -0,0 +1,2 @@ +In ``os.dup2``, don't check every call whether the ``dup3`` syscall exists +or not. diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 85ec255fcb4f..885c2674e336 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -7704,7 +7704,7 @@ os_dup2_impl(PyObject *module, int fd, int fd2, int inheritable) #if defined(HAVE_DUP3) && \ !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)) /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */ - int dup3_works = -1; + static int dup3_works = -1; #endif if (fd < 0 || fd2 < 0) From webhook-mailer at python.org Wed Feb 21 00:24:24 2018 From: webhook-mailer at python.org (INADA Naoki) Date: Wed, 21 Feb 2018 05:24:24 -0000 Subject: [Python-checkins] bpo-28886: doc: Move deprecated abc decorators to separate section (GH-176) Message-ID: https://github.com/python/cpython/commit/7452f6d8fa3ffe5dab20f7e4244851a6eca397be commit: 7452f6d8fa3ffe5dab20f7e4244851a6eca397be branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: INADA Naoki date: 2018-02-21T14:24:22+09:00 summary: bpo-28886: doc: Move deprecated abc decorators to separate section (GH-176) (cherry picked from commit 52c6b89796a7ec391db20281e05b256f57e97b35) Co-authored-by: Harshul jain files: M Doc/library/abc.rst diff --git a/Doc/library/abc.rst b/Doc/library/abc.rst index 9522dd620491..70710761a395 100644 --- a/Doc/library/abc.rst +++ b/Doc/library/abc.rst @@ -160,7 +160,7 @@ a helper class :class:`ABC` to alternatively define ABCs through inheritance: -The :mod:`abc` module also provides the following decorators: +The :mod:`abc` module also provides the following decorator: .. decorator:: abstractmethod @@ -236,8 +236,15 @@ The :mod:`abc` module also provides the following decorators: multiple-inheritance. +The :mod:`abc` module also supports the following legacy decorators: + .. decorator:: abstractclassmethod + .. versionadded:: 3.2 + .. deprecated:: 3.3 + It is now possible to use :class:`classmethod` with + :func:`abstractmethod`, making this decorator redundant. + A subclass of the built-in :func:`classmethod`, indicating an abstract classmethod. Otherwise it is similar to :func:`abstractmethod`. @@ -251,14 +258,14 @@ The :mod:`abc` module also provides the following decorators: def my_abstract_classmethod(cls, ...): ... + +.. decorator:: abstractstaticmethod + .. versionadded:: 3.2 .. deprecated:: 3.3 - It is now possible to use :class:`classmethod` with + It is now possible to use :class:`staticmethod` with :func:`abstractmethod`, making this decorator redundant. - -.. decorator:: abstractstaticmethod - A subclass of the built-in :func:`staticmethod`, indicating an abstract staticmethod. Otherwise it is similar to :func:`abstractmethod`. @@ -272,23 +279,17 @@ The :mod:`abc` module also provides the following decorators: def my_abstract_staticmethod(...): ... - .. versionadded:: 3.2 - .. deprecated:: 3.3 - It is now possible to use :class:`staticmethod` with - :func:`abstractmethod`, making this decorator redundant. - .. decorator:: abstractproperty + .. deprecated:: 3.3 + It is now possible to use :class:`property`, :meth:`property.getter`, + :meth:`property.setter` and :meth:`property.deleter` with + :func:`abstractmethod`, making this decorator redundant. + A subclass of the built-in :func:`property`, indicating an abstract property. - Using this function requires that the class's metaclass is :class:`ABCMeta` - or is derived from it. A class that has a metaclass derived from - :class:`ABCMeta` cannot be instantiated unless all of its abstract methods - and properties are overridden. The abstract properties can be called using - any of the normal 'super' call mechanisms. - This special case is deprecated, as the :func:`property` decorator is now correctly identified as abstract when applied to an abstract method:: @@ -322,12 +323,6 @@ The :mod:`abc` module also provides the following decorators: ... - .. deprecated:: 3.3 - It is now possible to use :class:`property`, :meth:`property.getter`, - :meth:`property.setter` and :meth:`property.deleter` with - :func:`abstractmethod`, making this decorator redundant. - - The :mod:`abc` module also provides the following functions: .. function:: get_cache_token() From webhook-mailer at python.org Wed Feb 21 00:24:40 2018 From: webhook-mailer at python.org (INADA Naoki) Date: Wed, 21 Feb 2018 05:24:40 -0000 Subject: [Python-checkins] bpo-28886: doc: Move deprecated abc decorators to separate section (GH-176) Message-ID: https://github.com/python/cpython/commit/0150dc589439a9a78c80c2aa8d7d6c5d3bba1d6d commit: 0150dc589439a9a78c80c2aa8d7d6c5d3bba1d6d branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: INADA Naoki date: 2018-02-21T14:24:37+09:00 summary: bpo-28886: doc: Move deprecated abc decorators to separate section (GH-176) (cherry picked from commit 52c6b89796a7ec391db20281e05b256f57e97b35) Co-authored-by: Harshul jain files: M Doc/library/abc.rst diff --git a/Doc/library/abc.rst b/Doc/library/abc.rst index 9522dd620491..70710761a395 100644 --- a/Doc/library/abc.rst +++ b/Doc/library/abc.rst @@ -160,7 +160,7 @@ a helper class :class:`ABC` to alternatively define ABCs through inheritance: -The :mod:`abc` module also provides the following decorators: +The :mod:`abc` module also provides the following decorator: .. decorator:: abstractmethod @@ -236,8 +236,15 @@ The :mod:`abc` module also provides the following decorators: multiple-inheritance. +The :mod:`abc` module also supports the following legacy decorators: + .. decorator:: abstractclassmethod + .. versionadded:: 3.2 + .. deprecated:: 3.3 + It is now possible to use :class:`classmethod` with + :func:`abstractmethod`, making this decorator redundant. + A subclass of the built-in :func:`classmethod`, indicating an abstract classmethod. Otherwise it is similar to :func:`abstractmethod`. @@ -251,14 +258,14 @@ The :mod:`abc` module also provides the following decorators: def my_abstract_classmethod(cls, ...): ... + +.. decorator:: abstractstaticmethod + .. versionadded:: 3.2 .. deprecated:: 3.3 - It is now possible to use :class:`classmethod` with + It is now possible to use :class:`staticmethod` with :func:`abstractmethod`, making this decorator redundant. - -.. decorator:: abstractstaticmethod - A subclass of the built-in :func:`staticmethod`, indicating an abstract staticmethod. Otherwise it is similar to :func:`abstractmethod`. @@ -272,23 +279,17 @@ The :mod:`abc` module also provides the following decorators: def my_abstract_staticmethod(...): ... - .. versionadded:: 3.2 - .. deprecated:: 3.3 - It is now possible to use :class:`staticmethod` with - :func:`abstractmethod`, making this decorator redundant. - .. decorator:: abstractproperty + .. deprecated:: 3.3 + It is now possible to use :class:`property`, :meth:`property.getter`, + :meth:`property.setter` and :meth:`property.deleter` with + :func:`abstractmethod`, making this decorator redundant. + A subclass of the built-in :func:`property`, indicating an abstract property. - Using this function requires that the class's metaclass is :class:`ABCMeta` - or is derived from it. A class that has a metaclass derived from - :class:`ABCMeta` cannot be instantiated unless all of its abstract methods - and properties are overridden. The abstract properties can be called using - any of the normal 'super' call mechanisms. - This special case is deprecated, as the :func:`property` decorator is now correctly identified as abstract when applied to an abstract method:: @@ -322,12 +323,6 @@ The :mod:`abc` module also provides the following decorators: ... - .. deprecated:: 3.3 - It is now possible to use :class:`property`, :meth:`property.getter`, - :meth:`property.setter` and :meth:`property.deleter` with - :func:`abstractmethod`, making this decorator redundant. - - The :mod:`abc` module also provides the following functions: .. function:: get_cache_token() From webhook-mailer at python.org Wed Feb 21 00:55:04 2018 From: webhook-mailer at python.org (Benjamin Peterson) Date: Wed, 21 Feb 2018 05:55:04 -0000 Subject: [Python-checkins] bpo-32008: don't use PROTOCOL_TLSv1 in example (GH-5789) Message-ID: https://github.com/python/cpython/commit/e9edee0b65650c4f9db90cefc2e9a8125bad762c commit: e9edee0b65650c4f9db90cefc2e9a8125bad762c branch: master author: Benjamin Peterson committer: GitHub date: 2018-02-20T21:55:01-08:00 summary: bpo-32008: don't use PROTOCOL_TLSv1 in example (GH-5789) It's bad form to pin to an old version of TLS. ssl.SSLContext has the right protocol default, so let's not pass anyway. files: M Doc/library/ssl.rst diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index aa1075d4b02b..21da4f638713 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -1707,7 +1707,7 @@ to speed up repeated connections from the same clients. import socket, ssl - context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) + context = ssl.SSLContext() context.verify_mode = ssl.CERT_REQUIRED context.check_hostname = True context.load_default_certs() @@ -1952,7 +1952,7 @@ If you prefer to tune security settings yourself, you might create a context from scratch (but beware that you might not get the settings right):: - >>> context = ssl.SSLContext(ssl.PROTOCOL_TLS) + >>> context = ssl.SSLContext() >>> context.verify_mode = ssl.CERT_REQUIRED >>> context.check_hostname = True >>> context.load_verify_locations("/etc/ssl/certs/ca-bundle.crt") From webhook-mailer at python.org Wed Feb 21 01:00:04 2018 From: webhook-mailer at python.org (Benjamin Peterson) Date: Wed, 21 Feb 2018 06:00:04 -0000 Subject: [Python-checkins] bpo-32889: update valgrind suppressions (GH-5779) Message-ID: https://github.com/python/cpython/commit/ba518804bf4c1ea01df5e622b333d3116cbaa3bd commit: ba518804bf4c1ea01df5e622b333d3116cbaa3bd branch: master author: Paul Price committer: Benjamin Peterson date: 2018-02-20T22:00:01-08:00 summary: bpo-32889: update valgrind suppressions (GH-5779) Py_ADDRESS_IN_RANGE was renamed address_in_range in 3.6 (commit 3924f93794fd740c547b44884f73303196475cd5). files: A Misc/NEWS.d/next/Core and Builtins/2018-02-20-21-53-48.bpo-32889.J6eWy5.rst M Misc/valgrind-python.supp diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-02-20-21-53-48.bpo-32889.J6eWy5.rst b/Misc/NEWS.d/next/Core and Builtins/2018-02-20-21-53-48.bpo-32889.J6eWy5.rst new file mode 100644 index 000000000000..99128ccc1826 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-02-20-21-53-48.bpo-32889.J6eWy5.rst @@ -0,0 +1,2 @@ +Update Valgrind suppression list to account for the rename of +``Py_ADDRESS_IN_RANG`` to ``address_in_range``. diff --git a/Misc/valgrind-python.supp b/Misc/valgrind-python.supp index e612555b6d3a..5bc60fc0a732 100644 --- a/Misc/valgrind-python.supp +++ b/Misc/valgrind-python.supp @@ -8,7 +8,7 @@ # ./python -E ./Lib/test/regrtest.py -u gui,network # # You must edit Objects/obmalloc.c and uncomment Py_USING_MEMORY_DEBUGGER -# to use the preferred suppressions with Py_ADDRESS_IN_RANGE. +# to use the preferred suppressions with address_in_range. # # If you do not want to recompile Python, you can uncomment # suppressions for PyObject_Free and PyObject_Realloc. @@ -19,25 +19,25 @@ { ADDRESS_IN_RANGE/Invalid read of size 4 Memcheck:Addr4 - fun:Py_ADDRESS_IN_RANGE + fun:address_in_range } { ADDRESS_IN_RANGE/Invalid read of size 4 Memcheck:Value4 - fun:Py_ADDRESS_IN_RANGE + fun:address_in_range } { ADDRESS_IN_RANGE/Invalid read of size 8 (x86_64 aka amd64) Memcheck:Value8 - fun:Py_ADDRESS_IN_RANGE + fun:address_in_range } { ADDRESS_IN_RANGE/Conditional jump or move depends on uninitialised value Memcheck:Cond - fun:Py_ADDRESS_IN_RANGE + fun:address_in_range } # From webhook-mailer at python.org Wed Feb 21 01:02:21 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 21 Feb 2018 06:02:21 -0000 Subject: [Python-checkins] bpo-32008: don't use PROTOCOL_TLSv1 in example (GH-5789) Message-ID: https://github.com/python/cpython/commit/e5d38deb045d0907e6fcf82af8d2d8f0556a8591 commit: e5d38deb045d0907e6fcf82af8d2d8f0556a8591 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-20T22:02:18-08:00 summary: bpo-32008: don't use PROTOCOL_TLSv1 in example (GH-5789) It's bad form to pin to an old version of TLS. ssl.SSLContext has the right protocol default, so let's not pass anyway. (cherry picked from commit e9edee0b65650c4f9db90cefc2e9a8125bad762c) Co-authored-by: Benjamin Peterson files: M Doc/library/ssl.rst diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index aa1075d4b02b..21da4f638713 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -1707,7 +1707,7 @@ to speed up repeated connections from the same clients. import socket, ssl - context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) + context = ssl.SSLContext() context.verify_mode = ssl.CERT_REQUIRED context.check_hostname = True context.load_default_certs() @@ -1952,7 +1952,7 @@ If you prefer to tune security settings yourself, you might create a context from scratch (but beware that you might not get the settings right):: - >>> context = ssl.SSLContext(ssl.PROTOCOL_TLS) + >>> context = ssl.SSLContext() >>> context.verify_mode = ssl.CERT_REQUIRED >>> context.check_hostname = True >>> context.load_verify_locations("/etc/ssl/certs/ca-bundle.crt") From webhook-mailer at python.org Wed Feb 21 01:07:20 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 21 Feb 2018 06:07:20 -0000 Subject: [Python-checkins] bpo-32008: don't use PROTOCOL_TLSv1 in example (GH-5789) Message-ID: https://github.com/python/cpython/commit/f8a794c04c8d375da279fc830770a5e6b4f363fb commit: f8a794c04c8d375da279fc830770a5e6b4f363fb branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-20T22:07:17-08:00 summary: bpo-32008: don't use PROTOCOL_TLSv1 in example (GH-5789) It's bad form to pin to an old version of TLS. ssl.SSLContext has the right protocol default, so let's not pass anyway. (cherry picked from commit e9edee0b65650c4f9db90cefc2e9a8125bad762c) Co-authored-by: Benjamin Peterson files: M Doc/library/ssl.rst diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 8f219c57940c..1c9e597306a9 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -1634,7 +1634,7 @@ to speed up repeated connections from the same clients. import socket, ssl - context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) + context = ssl.SSLContext() context.verify_mode = ssl.CERT_REQUIRED context.check_hostname = True context.load_default_certs() @@ -1861,7 +1861,7 @@ If you prefer to tune security settings yourself, you might create a context from scratch (but beware that you might not get the settings right):: - >>> context = ssl.SSLContext(ssl.PROTOCOL_TLS) + >>> context = ssl.SSLContext() >>> context.verify_mode = ssl.CERT_REQUIRED >>> context.check_hostname = True >>> context.load_verify_locations("/etc/ssl/certs/ca-bundle.crt") From webhook-mailer at python.org Wed Feb 21 01:17:13 2018 From: webhook-mailer at python.org (Benjamin Peterson) Date: Wed, 21 Feb 2018 06:17:13 -0000 Subject: [Python-checkins] [2.7] closes bpo-32008: don't use PROTOCOL_TLSv1 in example (GH-5789) (#5792) Message-ID: https://github.com/python/cpython/commit/6c7edba1665ea676328c6b50f92e8423c8f0d164 commit: 6c7edba1665ea676328c6b50f92e8423c8f0d164 branch: 2.7 author: Benjamin Peterson committer: GitHub date: 2018-02-20T22:17:10-08:00 summary: [2.7] closes bpo-32008: don't use PROTOCOL_TLSv1 in example (GH-5789) (#5792) It's bad form to pin to an old version of TLS. ssl.SSLContext has the right protocol default, so let's not pass anyway.. (cherry picked from commit e9edee0b65650c4f9db90cefc2e9a8125bad762c) files: M Doc/library/ssl.rst diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 5b55a82f5ecd..0ac06fa166f6 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -1330,7 +1330,7 @@ to speed up repeated connections from the same clients. import socket, ssl - context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) + context = ssl.SSLContext(ssl.PROTOCOL_TLS) context.verify_mode = ssl.CERT_REQUIRED context.check_hostname = True context.load_default_certs() @@ -1536,7 +1536,7 @@ If you prefer to tune security settings yourself, you might create a context from scratch (but beware that you might not get the settings right):: - >>> context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) + >>> context = ssl.SSLContext(ssl.PROTOCOL_TLS) >>> context.verify_mode = ssl.CERT_REQUIRED >>> context.check_hostname = True >>> context.load_verify_locations("/etc/ssl/certs/ca-bundle.crt") From webhook-mailer at python.org Wed Feb 21 01:27:41 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 21 Feb 2018 06:27:41 -0000 Subject: [Python-checkins] bpo-32889: update valgrind suppressions (GH-5779) Message-ID: https://github.com/python/cpython/commit/69607b4ecf917aea59632ff72695a97a6689ed8c commit: 69607b4ecf917aea59632ff72695a97a6689ed8c branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-20T22:27:38-08:00 summary: bpo-32889: update valgrind suppressions (GH-5779) Py_ADDRESS_IN_RANGE was renamed address_in_range in 3.6 (commit 3924f93794fd740c547b44884f73303196475cd5). (cherry picked from commit ba518804bf4c1ea01df5e622b333d3116cbaa3bd) Co-authored-by: Paul Price files: A Misc/NEWS.d/next/Core and Builtins/2018-02-20-21-53-48.bpo-32889.J6eWy5.rst M Misc/valgrind-python.supp diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-02-20-21-53-48.bpo-32889.J6eWy5.rst b/Misc/NEWS.d/next/Core and Builtins/2018-02-20-21-53-48.bpo-32889.J6eWy5.rst new file mode 100644 index 000000000000..99128ccc1826 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-02-20-21-53-48.bpo-32889.J6eWy5.rst @@ -0,0 +1,2 @@ +Update Valgrind suppression list to account for the rename of +``Py_ADDRESS_IN_RANG`` to ``address_in_range``. diff --git a/Misc/valgrind-python.supp b/Misc/valgrind-python.supp index e612555b6d3a..5bc60fc0a732 100644 --- a/Misc/valgrind-python.supp +++ b/Misc/valgrind-python.supp @@ -8,7 +8,7 @@ # ./python -E ./Lib/test/regrtest.py -u gui,network # # You must edit Objects/obmalloc.c and uncomment Py_USING_MEMORY_DEBUGGER -# to use the preferred suppressions with Py_ADDRESS_IN_RANGE. +# to use the preferred suppressions with address_in_range. # # If you do not want to recompile Python, you can uncomment # suppressions for PyObject_Free and PyObject_Realloc. @@ -19,25 +19,25 @@ { ADDRESS_IN_RANGE/Invalid read of size 4 Memcheck:Addr4 - fun:Py_ADDRESS_IN_RANGE + fun:address_in_range } { ADDRESS_IN_RANGE/Invalid read of size 4 Memcheck:Value4 - fun:Py_ADDRESS_IN_RANGE + fun:address_in_range } { ADDRESS_IN_RANGE/Invalid read of size 8 (x86_64 aka amd64) Memcheck:Value8 - fun:Py_ADDRESS_IN_RANGE + fun:address_in_range } { ADDRESS_IN_RANGE/Conditional jump or move depends on uninitialised value Memcheck:Cond - fun:Py_ADDRESS_IN_RANGE + fun:address_in_range } # From webhook-mailer at python.org Wed Feb 21 01:37:38 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Wed, 21 Feb 2018 06:37:38 -0000 Subject: [Python-checkins] [2.7] bpo-31848: Fix broken error handling in Aifc_read.initfp() when the SSND chunk is not found (GH-5240) (GH-5781) Message-ID: https://github.com/python/cpython/commit/b852d8c1f0b12e84549d83cd9b1ec0992b9d9703 commit: b852d8c1f0b12e84549d83cd9b1ec0992b9d9703 branch: 2.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Serhiy Storchaka date: 2018-02-21T08:37:18+02:00 summary: [2.7] bpo-31848: Fix broken error handling in Aifc_read.initfp() when the SSND chunk is not found (GH-5240) (GH-5781) Initialize self._ssnd_chunk so that aifc.Error is raised as intended, not AttributeError. (cherry picked from commit 80d20b918bd8a882043c493a7f958333ecb41727) Co-authored-by: Zackery Spytz files: A Misc/NEWS.d/next/Library/2018-01-18-23-34-17.bpo-31848.M2cldy.rst M Lib/aifc.py M Lib/test/test_aifc.py M Misc/ACKS diff --git a/Lib/aifc.py b/Lib/aifc.py index e6783277a471..981f8010690e 100644 --- a/Lib/aifc.py +++ b/Lib/aifc.py @@ -308,6 +308,7 @@ def initfp(self, file): else: raise Error, 'not an AIFF or AIFF-C file' self._comm_chunk_read = 0 + self._ssnd_chunk = None while 1: self._ssnd_seek_needed = 1 try: diff --git a/Lib/test/test_aifc.py b/Lib/test/test_aifc.py index d1b7dd043257..92bbe7bc75da 100644 --- a/Lib/test/test_aifc.py +++ b/Lib/test/test_aifc.py @@ -214,6 +214,14 @@ def test_read_no_comm_chunk(self): b = io.BytesIO('FORM' + struct.pack('>L', 4) + 'AIFF') self.assertRaises(aifc.Error, aifc.open, b) + def test_read_no_ssnd_chunk(self): + b = b'FORM' + struct.pack('>L', 4) + b'AIFC' + b += b'COMM' + struct.pack('>LhlhhLL', 38, 0, 0, 0, 0, 0, 0) + b += b'NONE' + struct.pack('B', 14) + b'not compressed' + b'\x00' + with self.assertRaisesRegexp(aifc.Error, 'COMM chunk and/or SSND chunk' + ' missing'): + aifc.open(io.BytesIO(b)) + def test_read_wrong_compression_type(self): b = 'FORM' + struct.pack('>L', 4) + 'AIFC' b += 'COMM' + struct.pack('>LhlhhLL', 23, 0, 0, 0, 0, 0, 0) diff --git a/Misc/ACKS b/Misc/ACKS index f0a115d5d555..e02060d8dcf1 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1345,6 +1345,7 @@ Nicholas Spies Per Spilling Joshua Spoerri Noah Spurrier +Zackery Spytz Nathan Srebro RajGopal Srinivasan Tage Stabell-Kulo diff --git a/Misc/NEWS.d/next/Library/2018-01-18-23-34-17.bpo-31848.M2cldy.rst b/Misc/NEWS.d/next/Library/2018-01-18-23-34-17.bpo-31848.M2cldy.rst new file mode 100644 index 000000000000..c8e61acb0b06 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-01-18-23-34-17.bpo-31848.M2cldy.rst @@ -0,0 +1,2 @@ +Fix the error handling in Aifc_read.initfp() when the SSND chunk is not found. +Patch by Zackery Spytz. From solipsis at pitrou.net Wed Feb 21 04:11:07 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 21 Feb 2018 09:11:07 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=-1 Message-ID: <20180221091107.1.3929B399792599C6@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_forkserver leaked [2, -1, 0] memory blocks, sum=1 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/refloghLjoxr', '--timeout', '7200'] From webhook-mailer at python.org Wed Feb 21 22:48:47 2018 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Thu, 22 Feb 2018 03:48:47 -0000 Subject: [Python-checkins] bpo-32874: IDLE: add tests for pyparse (GH-5755) Message-ID: https://github.com/python/cpython/commit/c84cf6c03fce1fb73bfaf91d7909f1c2708f14a2 commit: c84cf6c03fce1fb73bfaf91d7909f1c2708f14a2 branch: master author: Cheryl Sabella committer: Terry Jan Reedy date: 2018-02-21T22:48:36-05:00 summary: bpo-32874: IDLE: add tests for pyparse (GH-5755) There are no code changes other than comments and docstrings. files: A Lib/idlelib/idle_test/test_pyparse.py A Misc/NEWS.d/next/IDLE/2018-02-19-10-56-41.bpo-32874.6pZ9Gv.rst M Lib/idlelib/pyparse.py diff --git a/Lib/idlelib/idle_test/test_pyparse.py b/Lib/idlelib/idle_test/test_pyparse.py new file mode 100644 index 000000000000..b84e9f843081 --- /dev/null +++ b/Lib/idlelib/idle_test/test_pyparse.py @@ -0,0 +1,523 @@ +"""Unittest for idlelib.pyparse.py.""" + +from collections import namedtuple +import unittest +from idlelib import pyparse + + +class StringTranslatePseudoMappingTest(unittest.TestCase): + + @classmethod + def setUpClass(cls): + whitespace_chars = ' \t\n\r' + cls.preserve_dict = {ord(c): ord(c) for c in whitespace_chars} + cls.default = ord('x') + cls.mapping = pyparse.StringTranslatePseudoMapping( + cls.preserve_dict, default_value=ord('x')) + + @classmethod + def tearDownClass(cls): + del cls.preserve_dict, cls.default, cls.mapping + + def test__init__(self): + m = self.mapping + self.assertEqual(m._non_defaults, self.preserve_dict) + self.assertEqual(m._default_value, self.default) + + def test__get_item__(self): + self.assertEqual(self.mapping[ord('\t')], ord('\t')) + self.assertEqual(self.mapping[ord('a')], self.default) + + def test__len__(self): + self.assertEqual(len(self.mapping), len(self.preserve_dict)) + + def test__iter__(self): + count = 0 + for key, value in self.mapping.items(): + self.assertIn(key, self.preserve_dict) + count += 1 + self.assertEqual(count, len(self.mapping)) + + def test_get(self): + self.assertEqual(self.mapping.get(ord('\t')), ord('\t')) + self.assertEqual(self.mapping.get('a'), self.default) + # Default is a parameter, but it isn't used. + self.assertEqual(self.mapping.get('a', default=500), self.default) + + +class PyParseTest(unittest.TestCase): + + @classmethod + def setUpClass(cls): + cls.parser = pyparse.Parser(indentwidth=4, tabwidth=4) + + @classmethod + def tearDownClass(cls): + del cls.parser + + def test_init(self): + self.assertEqual(self.parser.indentwidth, 4) + self.assertEqual(self.parser.tabwidth, 4) + + def test_set_str(self): + eq = self.assertEqual + p = self.parser + setstr = p.set_str + + # Not empty and doesn't end with newline. + with self.assertRaises(AssertionError): + setstr('a') + + tests = ('', + 'a\n') + + for string in tests: + with self.subTest(string=string): + setstr(string) + eq(p.str, string) + eq(p.study_level, 0) + + def test_find_good_parse_start(self): + eq = self.assertEqual + p = self.parser + setstr = p.set_str + start = p.find_good_parse_start + + # Split def across lines. + setstr('"""This is a module docstring"""\n' + 'class C():\n' + ' def __init__(self, a,\n' + ' b=True):\n' + ' pass\n' + ) + + # No value sent for is_char_in_string(). + self.assertIsNone(start()) + + # Make text look like a string. This returns pos as the start + # position, but it's set to None. + self.assertIsNone(start(is_char_in_string=lambda index: True)) + + # Make all text look like it's not in a string. This means that it + # found a good start position. + eq(start(is_char_in_string=lambda index: False), 44) + + # If the beginning of the def line is not in a string, then it + # returns that as the index. + eq(start(is_char_in_string=lambda index: index > 44), 44) + # If the beginning of the def line is in a string, then it + # looks for a previous index. + eq(start(is_char_in_string=lambda index: index >= 44), 33) + # If everything before the 'def' is in a string, then returns None. + # The non-continuation def line returns 44 (see below). + eq(start(is_char_in_string=lambda index: index < 44), None) + + # Code without extra line break in def line - mostly returns the same + # values. + setstr('"""This is a module docstring"""\n' + 'class C():\n' + ' def __init__(self, a, b=True):\n' + ' pass\n' + ) + eq(start(is_char_in_string=lambda index: False), 44) + eq(start(is_char_in_string=lambda index: index > 44), 44) + eq(start(is_char_in_string=lambda index: index >= 44), 33) + # When the def line isn't split, this returns which doesn't match the + # split line test. + eq(start(is_char_in_string=lambda index: index < 44), 44) + + def test_set_lo(self): + code = ( + '"""This is a module docstring"""\n' + 'class C():\n' + ' def __init__(self, a,\n' + ' b=True):\n' + ' pass\n' + ) + p = self.parser + p.set_str(code) + + # Previous character is not a newline. + with self.assertRaises(AssertionError): + p.set_lo(5) + + # A value of 0 doesn't change self.str. + p.set_lo(0) + self.assertEqual(p.str, code) + + # An index that is preceded by a newline. + p.set_lo(44) + self.assertEqual(p.str, code[44:]) + + def test_tran(self): + self.assertEqual('\t a([{b}])b"c\'d\n'.translate(self.parser._tran), + 'xxx(((x)))x"x\'x\n') + + def test_study1(self): + eq = self.assertEqual + p = self.parser + setstr = p.set_str + study = p._study1 + + (NONE, BACKSLASH, FIRST, NEXT, BRACKET) = range(5) + TestInfo = namedtuple('TestInfo', ['string', 'goodlines', + 'continuation']) + tests = ( + TestInfo('', [0], NONE), + # Docstrings. + TestInfo('"""This is a complete docstring."""\n', [0, 1], NONE), + TestInfo("'''This is a complete docstring.'''\n", [0, 1], NONE), + TestInfo('"""This is a continued docstring.\n', [0, 1], FIRST), + TestInfo("'''This is a continued docstring.\n", [0, 1], FIRST), + TestInfo('"""Closing quote does not match."\n', [0, 1], FIRST), + TestInfo('"""Bracket in docstring [\n', [0, 1], FIRST), + TestInfo("'''Incomplete two line docstring.\n\n", [0, 2], NEXT), + # Single-quoted strings. + TestInfo('"This is a complete string."\n', [0, 1], NONE), + TestInfo('"This is an incomplete string.\n', [0, 1], NONE), + TestInfo("'This is more incomplete.\n\n", [0, 1, 2], NONE), + # Comment (backslash does not continue comments). + TestInfo('# Comment\\\n', [0, 1], NONE), + # Brackets. + TestInfo('("""Complete string in bracket"""\n', [0, 1], BRACKET), + TestInfo('("""Open string in bracket\n', [0, 1], FIRST), + TestInfo('a = (1 + 2) - 5 *\\\n', [0, 1], BACKSLASH), # No bracket. + TestInfo('\n def function1(self, a,\n b):\n', + [0, 1, 3], NONE), + TestInfo('\n def function1(self, a,\\\n', [0, 1, 2], BRACKET), + TestInfo('\n def function1(self, a,\n', [0, 1, 2], BRACKET), + TestInfo('())\n', [0, 1], NONE), # Extra closer. + TestInfo(')(\n', [0, 1], BRACKET), # Extra closer. + # For the mismatched example, it doesn't look like contination. + TestInfo('{)(]\n', [0, 1], NONE), # Mismatched. + ) + + for test in tests: + with self.subTest(string=test.string): + setstr(test.string) # resets study_level + study() + eq(p.study_level, 1) + eq(p.goodlines, test.goodlines) + eq(p.continuation, test.continuation) + + # Called again, just returns without reprocessing. + self.assertIsNone(study()) + + def test_get_continuation_type(self): + eq = self.assertEqual + p = self.parser + setstr = p.set_str + gettype = p.get_continuation_type + + (NONE, BACKSLASH, FIRST, NEXT, BRACKET) = range(5) + TestInfo = namedtuple('TestInfo', ['string', 'continuation']) + tests = ( + TestInfo('', NONE), + TestInfo('"""This is a continuation docstring.\n', FIRST), + TestInfo("'''This is a multiline-continued docstring.\n\n", NEXT), + TestInfo('a = (1 + 2) - 5 *\\\n', BACKSLASH), + TestInfo('\n def function1(self, a,\\\n', BRACKET) + ) + + for test in tests: + with self.subTest(string=test.string): + setstr(test.string) + eq(gettype(), test.continuation) + + def test_study2(self): + eq = self.assertEqual + p = self.parser + setstr = p.set_str + study = p._study2 + + TestInfo = namedtuple('TestInfo', ['string', 'start', 'end', 'lastch', + 'openbracket', 'bracketing']) + tests = ( + TestInfo('', 0, 0, '', None, ((0, 0),)), + TestInfo("'''This is a multiline continutation docstring.\n\n", + 0, 49, "'", None, ((0, 0), (0, 1), (49, 0))), + TestInfo(' # Comment\\\n', + 0, 12, '', None, ((0, 0), (1, 1), (12, 0))), + # A comment without a space is a special case + TestInfo(' #Comment\\\n', + 0, 0, '', None, ((0, 0),)), + # Backslash continuation. + TestInfo('a = (1 + 2) - 5 *\\\n', + 0, 19, '*', None, ((0, 0), (4, 1), (11, 0))), + # Bracket continuation with close. + TestInfo('\n def function1(self, a,\n b):\n', + 1, 48, ':', None, ((1, 0), (17, 1), (46, 0))), + # Bracket continuation with unneeded backslash. + TestInfo('\n def function1(self, a,\\\n', + 1, 28, ',', 17, ((1, 0), (17, 1))), + # Bracket continuation. + TestInfo('\n def function1(self, a,\n', + 1, 27, ',', 17, ((1, 0), (17, 1))), + # Bracket continuation with comment at end of line with text. + TestInfo('\n def function1(self, a, # End of line comment.\n', + 1, 51, ',', 17, ((1, 0), (17, 1), (28, 2), (51, 1))), + # Multi-line statement with comment line in between code lines. + TestInfo(' a = ["first item",\n # Comment line\n "next item",\n', + 0, 55, ',', 6, ((0, 0), (6, 1), (7, 2), (19, 1), + (23, 2), (38, 1), (42, 2), (53, 1))), + TestInfo('())\n', + 0, 4, ')', None, ((0, 0), (0, 1), (2, 0), (3, 0))), + TestInfo(')(\n', 0, 3, '(', 1, ((0, 0), (1, 0), (1, 1))), + # Wrong closers still decrement stack level. + TestInfo('{)(]\n', + 0, 5, ']', None, ((0, 0), (0, 1), (2, 0), (2, 1), (4, 0))), + # Character after backslash. + TestInfo(':\\a\n', 0, 4, '\\a', None, ((0, 0),)), + TestInfo('\n', 0, 0, '', None, ((0, 0),)), + ) + + for test in tests: + # There is a bug where this is carried forward from last item. + p.lastopenbracketpos = None + with self.subTest(string=test.string): + setstr(test.string) + study() + eq(p.study_level, 2) + eq(p.stmt_start, test.start) + eq(p.stmt_end, test.end) + eq(p.lastch, test.lastch) + eq(p.lastopenbracketpos, test.openbracket) + eq(p.stmt_bracketing, test.bracketing) + + # Called again, just returns without reprocessing. + self.assertIsNone(study()) + + def test_get_num_lines_in_stmt(self): + eq = self.assertEqual + p = self.parser + setstr = p.set_str + getlines = p.get_num_lines_in_stmt + + TestInfo = namedtuple('TestInfo', ['string', 'lines']) + tests = ( + TestInfo('[x for x in a]\n', 1), # Closed on one line. + TestInfo('[x\nfor x in a\n', 2), # Not closed. + TestInfo('[x\\\nfor x in a\\\n', 2), # "", uneeded backslashes. + TestInfo('[x\nfor x in a\n]\n', 3), # Closed on multi-line. + TestInfo('\n"""Docstring comment L1"""\nL2\nL3\nL4\n', 1), + TestInfo('\n"""Docstring comment L1\nL2"""\nL3\nL4\n', 1), + TestInfo('\n"""Docstring comment L1\\\nL2\\\nL3\\\nL4\\\n', 4), + TestInfo('\n\n"""Docstring comment L1\\\nL2\\\nL3\\\nL4\\\n"""\n', 5) + ) + + # Blank string doesn't have enough elements in goodlines. + setstr('') + with self.assertRaises(IndexError): + getlines() + + for test in tests: + with self.subTest(string=test.string): + setstr(test.string) + eq(getlines(), test.lines) + + def test_compute_bracket_indent(self): + eq = self.assertEqual + p = self.parser + setstr = p.set_str + indent = p.compute_bracket_indent + + TestInfo = namedtuple('TestInfo', ['string', 'spaces']) + tests = ( + TestInfo('def function1(self, a,\n', 14), + # Characters after bracket. + TestInfo('\n def function1(self, a,\n', 18), + TestInfo('\n\tdef function1(self, a,\n', 18), + # No characters after bracket. + TestInfo('\n def function1(\n', 8), + TestInfo('\n\tdef function1(\n', 8), + TestInfo('\n def function1( \n', 8), # Ignore extra spaces. + TestInfo('[\n"first item",\n # Comment line\n "next item",\n', 0), + TestInfo('[\n "first item",\n # Comment line\n "next item",\n', 2), + TestInfo('["first item",\n # Comment line\n "next item",\n', 1), + TestInfo('(\n', 4), + TestInfo('(a\n', 1), + ) + + # Must be C_BRACKET continuation type. + setstr('def function1(self, a, b):\n') + with self.assertRaises(AssertionError): + indent() + + for test in tests: + setstr(test.string) + eq(indent(), test.spaces) + + def test_compute_backslash_indent(self): + eq = self.assertEqual + p = self.parser + setstr = p.set_str + indent = p.compute_backslash_indent + + # Must be C_BACKSLASH continuation type. + errors = (('def function1(self, a, b\\\n'), # Bracket. + (' """ (\\\n'), # Docstring. + ('a = #\\\n'), # Inline comment. + ) + for string in errors: + with self.subTest(string=string): + setstr(string) + with self.assertRaises(AssertionError): + indent() + + TestInfo = namedtuple('TestInfo', ('string', 'spaces')) + tests = (TestInfo('a = (1 + 2) - 5 *\\\n', 4), + TestInfo('a = 1 + 2 - 5 *\\\n', 4), + TestInfo(' a = 1 + 2 - 5 *\\\n', 8), + TestInfo(' a = "spam"\\\n', 6), + TestInfo(' a = \\\n"a"\\\n', 4), + TestInfo(' a = #\\\n"a"\\\n', 5), + TestInfo('a == \\\n', 2), + TestInfo('a != \\\n', 2), + # Difference between containing = and those not. + TestInfo('\\\n', 2), + TestInfo(' \\\n', 6), + TestInfo('\t\\\n', 6), + TestInfo('a\\\n', 3), + TestInfo('{}\\\n', 4), + TestInfo('(1 + 2) - 5 *\\\n', 3), + ) + for test in tests: + with self.subTest(string=test.string): + setstr(test.string) + eq(indent(), test.spaces) + + def test_get_base_indent_string(self): + eq = self.assertEqual + p = self.parser + setstr = p.set_str + baseindent = p.get_base_indent_string + + TestInfo = namedtuple('TestInfo', ['string', 'indent']) + tests = (TestInfo('', ''), + TestInfo('def a():\n', ''), + TestInfo('\tdef a():\n', '\t'), + TestInfo(' def a():\n', ' '), + TestInfo(' def a(\n', ' '), + TestInfo('\t\n def a(\n', ' '), + TestInfo('\t\n # Comment.\n', ' '), + ) + + for test in tests: + with self.subTest(string=test.string): + setstr(test.string) + eq(baseindent(), test.indent) + + def test_is_block_opener(self): + yes = self.assertTrue + no = self.assertFalse + p = self.parser + setstr = p.set_str + opener = p.is_block_opener + + TestInfo = namedtuple('TestInfo', ['string', 'assert_']) + tests = ( + TestInfo('def a():\n', yes), + TestInfo('\n def function1(self, a,\n b):\n', yes), + TestInfo(':\n', yes), + TestInfo('a:\n', yes), + TestInfo('):\n', yes), + TestInfo('(:\n', yes), + TestInfo('":\n', no), + TestInfo('\n def function1(self, a,\n', no), + TestInfo('def function1(self, a):\n pass\n', no), + TestInfo('# A comment:\n', no), + TestInfo('"""A docstring:\n', no), + TestInfo('"""A docstring:\n', no), + ) + + for test in tests: + with self.subTest(string=test.string): + setstr(test.string) + test.assert_(opener()) + + def test_is_block_closer(self): + yes = self.assertTrue + no = self.assertFalse + p = self.parser + setstr = p.set_str + closer = p.is_block_closer + + TestInfo = namedtuple('TestInfo', ['string', 'assert_']) + tests = ( + TestInfo('return\n', yes), + TestInfo('\tbreak\n', yes), + TestInfo(' continue\n', yes), + TestInfo(' raise\n', yes), + TestInfo('pass \n', yes), + TestInfo('pass\t\n', yes), + TestInfo('return #\n', yes), + TestInfo('raised\n', no), + TestInfo('returning\n', no), + TestInfo('# return\n', no), + TestInfo('"""break\n', no), + TestInfo('"continue\n', no), + TestInfo('def function1(self, a):\n pass\n', yes), + ) + + for test in tests: + with self.subTest(string=test.string): + setstr(test.string) + test.assert_(closer()) + + def test_get_last_open_bracket_pos(self): + eq = self.assertEqual + p = self.parser + setstr = p.set_str + openbracket = p.get_last_open_bracket_pos + + TestInfo = namedtuple('TestInfo', ['string', 'position']) + tests = ( + TestInfo('', None), + TestInfo('a\n', None), + TestInfo('# (\n', None), + TestInfo('""" (\n', None), + TestInfo('a = (1 + 2) - 5 *\\\n', None), + TestInfo('\n def function1(self, a,\n', 17), + TestInfo('\n def function1(self, a, # End of line comment.\n', 17), + TestInfo('{)(]\n', None), + TestInfo('(((((((((()))))))\n', 2), + TestInfo('(((((((((())\n)))\n))\n', 2), + ) + + for test in tests: + # There is a bug where the value is carried forward from last item. + p.lastopenbracketpos = None + with self.subTest(string=test.string): + setstr(test.string) + eq(openbracket(), test.position) + + def test_get_last_stmt_bracketing(self): + eq = self.assertEqual + p = self.parser + setstr = p.set_str + bracketing = p.get_last_stmt_bracketing + + TestInfo = namedtuple('TestInfo', ['string', 'bracket']) + tests = ( + TestInfo('', ((0, 0),)), + TestInfo('a\n', ((0, 0),)), + TestInfo('()()\n', ((0, 0), (0, 1), (2, 0), (2, 1), (4, 0))), + TestInfo('(\n)()\n', ((0, 0), (0, 1), (3, 0), (3, 1), (5, 0))), + TestInfo('()\n()\n', ((3, 0), (3, 1), (5, 0))), + TestInfo('()(\n)\n', ((0, 0), (0, 1), (2, 0), (2, 1), (5, 0))), + TestInfo('(())\n', ((0, 0), (0, 1), (1, 2), (3, 1), (4, 0))), + TestInfo('(\n())\n', ((0, 0), (0, 1), (2, 2), (4, 1), (5, 0))), + # Same as matched test. + TestInfo('{)(]\n', ((0, 0), (0, 1), (2, 0), (2, 1), (4, 0))), + TestInfo('(((())\n', + ((0, 0), (0, 1), (1, 2), (2, 3), (3, 4), (5, 3), (6, 2))), + ) + + for test in tests: + with self.subTest(string=test.string): + setstr(test.string) + eq(bracketing(), test.bracket) + + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/Lib/idlelib/pyparse.py b/Lib/idlelib/pyparse.py index 536b2d7f5fef..72bd9e00c1e9 100644 --- a/Lib/idlelib/pyparse.py +++ b/Lib/idlelib/pyparse.py @@ -1,8 +1,20 @@ +"""Define partial Python code Parser used by editor and hyperparser. + +Instances of StringTranslatePseudoMapping are used with str.translate. + +The following bound search and match functions are defined: +_synchre - start of popular statement; +_junkre - whitespace or comment line; +_match_stringre: string, possibly without closer; +_itemre - line that may have bracket structure start; +_closere - line that must be followed by dedent. +_chew_ordinaryre - non-special characters. +""" from collections.abc import Mapping import re import sys -# Reason last stmt is continued (or C_NONE if it's not). +# Reason last statement is continued (or C_NONE if it's not). (C_NONE, C_BACKSLASH, C_STRING_FIRST_LINE, C_STRING_NEXT_LINES, C_BRACKET) = range(5) @@ -10,7 +22,7 @@ def dump(*stuff): sys.__stdout__.write(" ".join(map(str, stuff)) + "\n") -# Find what looks like the start of a popular stmt. +# Find what looks like the start of a popular statement. _synchre = re.compile(r""" ^ @@ -70,7 +82,7 @@ def dump(*stuff): [^\s#\\] # if we match, m.end()-1 is the interesting char """, re.VERBOSE).match -# Match start of stmts that should be followed by a dedent. +# Match start of statements that should be followed by a dedent. _closere = re.compile(r""" \s* @@ -146,19 +158,20 @@ def set_str(self, s): self.str = s self.study_level = 0 - # Return index of a good place to begin parsing, as close to the - # end of the string as possible. This will be the start of some - # popular stmt like "if" or "def". Return None if none found: - # the caller should pass more prior context then, if possible, or - # if not (the entire program text up until the point of interest - # has already been tried) pass 0 to set_lo. - # - # This will be reliable iff given a reliable is_char_in_string - # function, meaning that when it says "no", it's absolutely - # guaranteed that the char is not in a string. - def find_good_parse_start(self, is_char_in_string=None, _synchre=_synchre): + """ + Return index of a good place to begin parsing, as close to the + end of the string as possible. This will be the start of some + popular stmt like "if" or "def". Return None if none found: + the caller should pass more prior context then, if possible, or + if not (the entire program text up until the point of interest + has already been tried) pass 0 to set_lo(). + + This will be reliable iff given a reliable is_char_in_string() + function, meaning that when it says "no", it's absolutely + guaranteed that the char is not in a string. + """ str, pos = self.str, None if not is_char_in_string: @@ -173,7 +186,7 @@ def find_good_parse_start(self, is_char_in_string=None, i = str.rfind(":\n", 0, limit) if i < 0: break - i = str.rfind('\n', 0, i) + 1 # start of colon line + i = str.rfind('\n', 0, i) + 1 # start of colon line (-1+1=0) m = _synchre(str, i, limit) if m and not is_char_in_string(m.start()): pos = m.start() @@ -206,10 +219,11 @@ def find_good_parse_start(self, is_char_in_string=None, break return pos - # Throw away the start of the string. Intended to be called with - # find_good_parse_start's result. - def set_lo(self, lo): + """ Throw away the start of the string. + + Intended to be called with the result of find_good_parse_start(). + """ assert lo == 0 or self.str[lo-1] == '\n' if lo > 0: self.str = self.str[lo:] @@ -224,11 +238,13 @@ def set_lo(self, lo): _tran.update((ord(c), ord(c)) for c in "\"'\\\n#") _tran = StringTranslatePseudoMapping(_tran, default_value=ord('x')) - # As quickly as humanly possible , find the line numbers (0- - # based) of the non-continuation lines. - # Creates self.{goodlines, continuation}. - def _study1(self): + """Find the line numbers of non-continuation lines. + + As quickly as humanly possible , find the line numbers (0- + based) of the non-continuation lines. + Creates self.{goodlines, continuation}. + """ if self.study_level >= 1: return self.study_level = 1 @@ -244,8 +260,8 @@ def _study1(self): str = str.replace('xx', 'x') str = str.replace('xx', 'x') str = str.replace('\nx', '\n') - # note that replacing x\n with \n would be incorrect, because - # x may be preceded by a backslash + # Replacing x\n with \n would be incorrect because + # x may be preceded by a backslash. # March over the squashed version of the program, accumulating # the line numbers of non-continued stmts, and determining @@ -360,24 +376,25 @@ def get_continuation_type(self): self._study1() return self.continuation - # study1 was sufficient to determine the continuation status, - # but doing more requires looking at every character. study2 - # does this for the last interesting statement in the block. - # Creates: - # self.stmt_start, stmt_end - # slice indices of last interesting stmt - # self.stmt_bracketing - # the bracketing structure of the last interesting stmt; - # for example, for the statement "say(boo) or die", stmt_bracketing - # will be [(0, 0), (3, 1), (8, 0)]. Strings and comments are - # treated as brackets, for the matter. - # self.lastch - # last non-whitespace character before optional trailing - # comment - # self.lastopenbracketpos - # if continuation is C_BRACKET, index of last open bracket - def _study2(self): + """ + study1 was sufficient to determine the continuation status, + but doing more requires looking at every character. study2 + does this for the last interesting statement in the block. + Creates: + self.stmt_start, stmt_end + slice indices of last interesting stmt + self.stmt_bracketing + the bracketing structure of the last interesting stmt; for + example, for the statement "say(boo) or die", + stmt_bracketing will be ((0, 0), (0, 1), (2, 0), (2, 1), + (4, 0)). Strings and comments are treated as brackets, for + the matter. + self.lastch + last interesting character before optional trailing comment + self.lastopenbracketpos + if continuation is C_BRACKET, index of last open bracket + """ if self.study_level >= 2: return self._study1() @@ -385,11 +402,11 @@ def _study2(self): # Set p and q to slice indices of last interesting stmt. str, goodlines = self.str, self.goodlines - i = len(goodlines) - 1 - p = len(str) # index of newest line + i = len(goodlines) - 1 # Index of newest line. + p = len(str) # End of goodlines[i] while i: assert p - # p is the index of the stmt at line number goodlines[i]. + # Make p be the index of the stmt at line number goodlines[i]. # Move p back to the stmt at line number goodlines[i-1]. q = p for nothing in range(goodlines[i-1], goodlines[i]): @@ -483,10 +500,11 @@ def _study2(self): self.lastopenbracketpos = stack[-1] self.stmt_bracketing = tuple(bracketing) - # Assuming continuation is C_BRACKET, return the number - # of spaces the next line should be indented. - def compute_bracket_indent(self): + """Return number of spaces the next line should be indented. + + Line continuation must be C_BRACKET. + """ self._study2() assert self.continuation == C_BRACKET j = self.lastopenbracketpos @@ -513,20 +531,22 @@ def compute_bracket_indent(self): extra = self.indentwidth return len(str[i:j].expandtabs(self.tabwidth)) + extra - # Return number of physical lines in last stmt (whether or not - # it's an interesting stmt! this is intended to be called when - # continuation is C_BACKSLASH). - def get_num_lines_in_stmt(self): + """Return number of physical lines in last stmt. + + The statement doesn't have to be an interesting statement. This is + intended to be called when continuation is C_BACKSLASH. + """ self._study1() goodlines = self.goodlines return goodlines[-1] - goodlines[-2] - # Assuming continuation is C_BACKSLASH, return the number of spaces - # the next line should be indented. Also assuming the new line is - # the first one following the initial line of the stmt. - def compute_backslash_indent(self): + """Return number of spaces the next line should be indented. + + Line continuation must be C_BACKSLASH. Also assume that the new + line is the first one following the initial line of the stmt. + """ self._study2() assert self.continuation == C_BACKSLASH str = self.str @@ -551,6 +571,8 @@ def compute_backslash_indent(self): elif ch == '"' or ch == "'": i = _match_stringre(str, i, endpos).end() elif ch == '#': + # This line is unreachable because the # makes a comment of + # everything after it. break elif level == 0 and ch == '=' and \ (i == 0 or str[i-1] not in "=<>!") and \ @@ -576,10 +598,10 @@ def compute_backslash_indent(self): return len(str[self.stmt_start:i].expandtabs(\ self.tabwidth)) + 1 - # Return the leading whitespace on the initial line of the last - # interesting stmt. - def get_base_indent_string(self): + """Return the leading whitespace on the initial line of the last + interesting stmt. + """ self._study2() i, n = self.stmt_start, self.stmt_end j = i @@ -588,30 +610,37 @@ def get_base_indent_string(self): j = j + 1 return str[i:j] - # Did the last interesting stmt open a block? - def is_block_opener(self): + "Return True if the last interesting statemtent opens a block." self._study2() return self.lastch == ':' - # Did the last interesting stmt close a block? - def is_block_closer(self): + "Return True if the last interesting statement closes a block." self._study2() return _closere(self.str, self.stmt_start) is not None - # index of last open bracket ({[, or None if none + # XXX - is this used? lastopenbracketpos = None def get_last_open_bracket_pos(self): + "Return index of last open bracket or None." self._study2() return self.lastopenbracketpos - # the structure of the bracketing of the last interesting statement, - # in the format defined in _study2, or None if the text didn't contain - # anything + # XXX - is this used? stmt_bracketing = None def get_last_stmt_bracketing(self): + """Return a tuple of the structure of the bracketing of the last + interesting statement. + + Tuple is in the format defined in _study2(). + """ self._study2() return self.stmt_bracketing + + +if __name__ == '__main__': #pragma: nocover + import unittest + unittest.main('idlelib.idle_test.test_pyparse', verbosity=2) diff --git a/Misc/NEWS.d/next/IDLE/2018-02-19-10-56-41.bpo-32874.6pZ9Gv.rst b/Misc/NEWS.d/next/IDLE/2018-02-19-10-56-41.bpo-32874.6pZ9Gv.rst new file mode 100644 index 000000000000..79655315fff4 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2018-02-19-10-56-41.bpo-32874.6pZ9Gv.rst @@ -0,0 +1 @@ +Add tests for pyparse. From webhook-mailer at python.org Wed Feb 21 23:09:42 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 22 Feb 2018 04:09:42 -0000 Subject: [Python-checkins] bpo-32874: IDLE: add tests for pyparse (GH-5755) Message-ID: https://github.com/python/cpython/commit/c59bc98fb26ff1a2361f168a97da4a5f6c1e5b43 commit: c59bc98fb26ff1a2361f168a97da4a5f6c1e5b43 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-21T20:09:39-08:00 summary: bpo-32874: IDLE: add tests for pyparse (GH-5755) There are no code changes other than comments and docstrings. (cherry picked from commit c84cf6c03fce1fb73bfaf91d7909f1c2708f14a2) Co-authored-by: Cheryl Sabella files: A Lib/idlelib/idle_test/test_pyparse.py A Misc/NEWS.d/next/IDLE/2018-02-19-10-56-41.bpo-32874.6pZ9Gv.rst M Lib/idlelib/pyparse.py diff --git a/Lib/idlelib/idle_test/test_pyparse.py b/Lib/idlelib/idle_test/test_pyparse.py new file mode 100644 index 000000000000..b84e9f843081 --- /dev/null +++ b/Lib/idlelib/idle_test/test_pyparse.py @@ -0,0 +1,523 @@ +"""Unittest for idlelib.pyparse.py.""" + +from collections import namedtuple +import unittest +from idlelib import pyparse + + +class StringTranslatePseudoMappingTest(unittest.TestCase): + + @classmethod + def setUpClass(cls): + whitespace_chars = ' \t\n\r' + cls.preserve_dict = {ord(c): ord(c) for c in whitespace_chars} + cls.default = ord('x') + cls.mapping = pyparse.StringTranslatePseudoMapping( + cls.preserve_dict, default_value=ord('x')) + + @classmethod + def tearDownClass(cls): + del cls.preserve_dict, cls.default, cls.mapping + + def test__init__(self): + m = self.mapping + self.assertEqual(m._non_defaults, self.preserve_dict) + self.assertEqual(m._default_value, self.default) + + def test__get_item__(self): + self.assertEqual(self.mapping[ord('\t')], ord('\t')) + self.assertEqual(self.mapping[ord('a')], self.default) + + def test__len__(self): + self.assertEqual(len(self.mapping), len(self.preserve_dict)) + + def test__iter__(self): + count = 0 + for key, value in self.mapping.items(): + self.assertIn(key, self.preserve_dict) + count += 1 + self.assertEqual(count, len(self.mapping)) + + def test_get(self): + self.assertEqual(self.mapping.get(ord('\t')), ord('\t')) + self.assertEqual(self.mapping.get('a'), self.default) + # Default is a parameter, but it isn't used. + self.assertEqual(self.mapping.get('a', default=500), self.default) + + +class PyParseTest(unittest.TestCase): + + @classmethod + def setUpClass(cls): + cls.parser = pyparse.Parser(indentwidth=4, tabwidth=4) + + @classmethod + def tearDownClass(cls): + del cls.parser + + def test_init(self): + self.assertEqual(self.parser.indentwidth, 4) + self.assertEqual(self.parser.tabwidth, 4) + + def test_set_str(self): + eq = self.assertEqual + p = self.parser + setstr = p.set_str + + # Not empty and doesn't end with newline. + with self.assertRaises(AssertionError): + setstr('a') + + tests = ('', + 'a\n') + + for string in tests: + with self.subTest(string=string): + setstr(string) + eq(p.str, string) + eq(p.study_level, 0) + + def test_find_good_parse_start(self): + eq = self.assertEqual + p = self.parser + setstr = p.set_str + start = p.find_good_parse_start + + # Split def across lines. + setstr('"""This is a module docstring"""\n' + 'class C():\n' + ' def __init__(self, a,\n' + ' b=True):\n' + ' pass\n' + ) + + # No value sent for is_char_in_string(). + self.assertIsNone(start()) + + # Make text look like a string. This returns pos as the start + # position, but it's set to None. + self.assertIsNone(start(is_char_in_string=lambda index: True)) + + # Make all text look like it's not in a string. This means that it + # found a good start position. + eq(start(is_char_in_string=lambda index: False), 44) + + # If the beginning of the def line is not in a string, then it + # returns that as the index. + eq(start(is_char_in_string=lambda index: index > 44), 44) + # If the beginning of the def line is in a string, then it + # looks for a previous index. + eq(start(is_char_in_string=lambda index: index >= 44), 33) + # If everything before the 'def' is in a string, then returns None. + # The non-continuation def line returns 44 (see below). + eq(start(is_char_in_string=lambda index: index < 44), None) + + # Code without extra line break in def line - mostly returns the same + # values. + setstr('"""This is a module docstring"""\n' + 'class C():\n' + ' def __init__(self, a, b=True):\n' + ' pass\n' + ) + eq(start(is_char_in_string=lambda index: False), 44) + eq(start(is_char_in_string=lambda index: index > 44), 44) + eq(start(is_char_in_string=lambda index: index >= 44), 33) + # When the def line isn't split, this returns which doesn't match the + # split line test. + eq(start(is_char_in_string=lambda index: index < 44), 44) + + def test_set_lo(self): + code = ( + '"""This is a module docstring"""\n' + 'class C():\n' + ' def __init__(self, a,\n' + ' b=True):\n' + ' pass\n' + ) + p = self.parser + p.set_str(code) + + # Previous character is not a newline. + with self.assertRaises(AssertionError): + p.set_lo(5) + + # A value of 0 doesn't change self.str. + p.set_lo(0) + self.assertEqual(p.str, code) + + # An index that is preceded by a newline. + p.set_lo(44) + self.assertEqual(p.str, code[44:]) + + def test_tran(self): + self.assertEqual('\t a([{b}])b"c\'d\n'.translate(self.parser._tran), + 'xxx(((x)))x"x\'x\n') + + def test_study1(self): + eq = self.assertEqual + p = self.parser + setstr = p.set_str + study = p._study1 + + (NONE, BACKSLASH, FIRST, NEXT, BRACKET) = range(5) + TestInfo = namedtuple('TestInfo', ['string', 'goodlines', + 'continuation']) + tests = ( + TestInfo('', [0], NONE), + # Docstrings. + TestInfo('"""This is a complete docstring."""\n', [0, 1], NONE), + TestInfo("'''This is a complete docstring.'''\n", [0, 1], NONE), + TestInfo('"""This is a continued docstring.\n', [0, 1], FIRST), + TestInfo("'''This is a continued docstring.\n", [0, 1], FIRST), + TestInfo('"""Closing quote does not match."\n', [0, 1], FIRST), + TestInfo('"""Bracket in docstring [\n', [0, 1], FIRST), + TestInfo("'''Incomplete two line docstring.\n\n", [0, 2], NEXT), + # Single-quoted strings. + TestInfo('"This is a complete string."\n', [0, 1], NONE), + TestInfo('"This is an incomplete string.\n', [0, 1], NONE), + TestInfo("'This is more incomplete.\n\n", [0, 1, 2], NONE), + # Comment (backslash does not continue comments). + TestInfo('# Comment\\\n', [0, 1], NONE), + # Brackets. + TestInfo('("""Complete string in bracket"""\n', [0, 1], BRACKET), + TestInfo('("""Open string in bracket\n', [0, 1], FIRST), + TestInfo('a = (1 + 2) - 5 *\\\n', [0, 1], BACKSLASH), # No bracket. + TestInfo('\n def function1(self, a,\n b):\n', + [0, 1, 3], NONE), + TestInfo('\n def function1(self, a,\\\n', [0, 1, 2], BRACKET), + TestInfo('\n def function1(self, a,\n', [0, 1, 2], BRACKET), + TestInfo('())\n', [0, 1], NONE), # Extra closer. + TestInfo(')(\n', [0, 1], BRACKET), # Extra closer. + # For the mismatched example, it doesn't look like contination. + TestInfo('{)(]\n', [0, 1], NONE), # Mismatched. + ) + + for test in tests: + with self.subTest(string=test.string): + setstr(test.string) # resets study_level + study() + eq(p.study_level, 1) + eq(p.goodlines, test.goodlines) + eq(p.continuation, test.continuation) + + # Called again, just returns without reprocessing. + self.assertIsNone(study()) + + def test_get_continuation_type(self): + eq = self.assertEqual + p = self.parser + setstr = p.set_str + gettype = p.get_continuation_type + + (NONE, BACKSLASH, FIRST, NEXT, BRACKET) = range(5) + TestInfo = namedtuple('TestInfo', ['string', 'continuation']) + tests = ( + TestInfo('', NONE), + TestInfo('"""This is a continuation docstring.\n', FIRST), + TestInfo("'''This is a multiline-continued docstring.\n\n", NEXT), + TestInfo('a = (1 + 2) - 5 *\\\n', BACKSLASH), + TestInfo('\n def function1(self, a,\\\n', BRACKET) + ) + + for test in tests: + with self.subTest(string=test.string): + setstr(test.string) + eq(gettype(), test.continuation) + + def test_study2(self): + eq = self.assertEqual + p = self.parser + setstr = p.set_str + study = p._study2 + + TestInfo = namedtuple('TestInfo', ['string', 'start', 'end', 'lastch', + 'openbracket', 'bracketing']) + tests = ( + TestInfo('', 0, 0, '', None, ((0, 0),)), + TestInfo("'''This is a multiline continutation docstring.\n\n", + 0, 49, "'", None, ((0, 0), (0, 1), (49, 0))), + TestInfo(' # Comment\\\n', + 0, 12, '', None, ((0, 0), (1, 1), (12, 0))), + # A comment without a space is a special case + TestInfo(' #Comment\\\n', + 0, 0, '', None, ((0, 0),)), + # Backslash continuation. + TestInfo('a = (1 + 2) - 5 *\\\n', + 0, 19, '*', None, ((0, 0), (4, 1), (11, 0))), + # Bracket continuation with close. + TestInfo('\n def function1(self, a,\n b):\n', + 1, 48, ':', None, ((1, 0), (17, 1), (46, 0))), + # Bracket continuation with unneeded backslash. + TestInfo('\n def function1(self, a,\\\n', + 1, 28, ',', 17, ((1, 0), (17, 1))), + # Bracket continuation. + TestInfo('\n def function1(self, a,\n', + 1, 27, ',', 17, ((1, 0), (17, 1))), + # Bracket continuation with comment at end of line with text. + TestInfo('\n def function1(self, a, # End of line comment.\n', + 1, 51, ',', 17, ((1, 0), (17, 1), (28, 2), (51, 1))), + # Multi-line statement with comment line in between code lines. + TestInfo(' a = ["first item",\n # Comment line\n "next item",\n', + 0, 55, ',', 6, ((0, 0), (6, 1), (7, 2), (19, 1), + (23, 2), (38, 1), (42, 2), (53, 1))), + TestInfo('())\n', + 0, 4, ')', None, ((0, 0), (0, 1), (2, 0), (3, 0))), + TestInfo(')(\n', 0, 3, '(', 1, ((0, 0), (1, 0), (1, 1))), + # Wrong closers still decrement stack level. + TestInfo('{)(]\n', + 0, 5, ']', None, ((0, 0), (0, 1), (2, 0), (2, 1), (4, 0))), + # Character after backslash. + TestInfo(':\\a\n', 0, 4, '\\a', None, ((0, 0),)), + TestInfo('\n', 0, 0, '', None, ((0, 0),)), + ) + + for test in tests: + # There is a bug where this is carried forward from last item. + p.lastopenbracketpos = None + with self.subTest(string=test.string): + setstr(test.string) + study() + eq(p.study_level, 2) + eq(p.stmt_start, test.start) + eq(p.stmt_end, test.end) + eq(p.lastch, test.lastch) + eq(p.lastopenbracketpos, test.openbracket) + eq(p.stmt_bracketing, test.bracketing) + + # Called again, just returns without reprocessing. + self.assertIsNone(study()) + + def test_get_num_lines_in_stmt(self): + eq = self.assertEqual + p = self.parser + setstr = p.set_str + getlines = p.get_num_lines_in_stmt + + TestInfo = namedtuple('TestInfo', ['string', 'lines']) + tests = ( + TestInfo('[x for x in a]\n', 1), # Closed on one line. + TestInfo('[x\nfor x in a\n', 2), # Not closed. + TestInfo('[x\\\nfor x in a\\\n', 2), # "", uneeded backslashes. + TestInfo('[x\nfor x in a\n]\n', 3), # Closed on multi-line. + TestInfo('\n"""Docstring comment L1"""\nL2\nL3\nL4\n', 1), + TestInfo('\n"""Docstring comment L1\nL2"""\nL3\nL4\n', 1), + TestInfo('\n"""Docstring comment L1\\\nL2\\\nL3\\\nL4\\\n', 4), + TestInfo('\n\n"""Docstring comment L1\\\nL2\\\nL3\\\nL4\\\n"""\n', 5) + ) + + # Blank string doesn't have enough elements in goodlines. + setstr('') + with self.assertRaises(IndexError): + getlines() + + for test in tests: + with self.subTest(string=test.string): + setstr(test.string) + eq(getlines(), test.lines) + + def test_compute_bracket_indent(self): + eq = self.assertEqual + p = self.parser + setstr = p.set_str + indent = p.compute_bracket_indent + + TestInfo = namedtuple('TestInfo', ['string', 'spaces']) + tests = ( + TestInfo('def function1(self, a,\n', 14), + # Characters after bracket. + TestInfo('\n def function1(self, a,\n', 18), + TestInfo('\n\tdef function1(self, a,\n', 18), + # No characters after bracket. + TestInfo('\n def function1(\n', 8), + TestInfo('\n\tdef function1(\n', 8), + TestInfo('\n def function1( \n', 8), # Ignore extra spaces. + TestInfo('[\n"first item",\n # Comment line\n "next item",\n', 0), + TestInfo('[\n "first item",\n # Comment line\n "next item",\n', 2), + TestInfo('["first item",\n # Comment line\n "next item",\n', 1), + TestInfo('(\n', 4), + TestInfo('(a\n', 1), + ) + + # Must be C_BRACKET continuation type. + setstr('def function1(self, a, b):\n') + with self.assertRaises(AssertionError): + indent() + + for test in tests: + setstr(test.string) + eq(indent(), test.spaces) + + def test_compute_backslash_indent(self): + eq = self.assertEqual + p = self.parser + setstr = p.set_str + indent = p.compute_backslash_indent + + # Must be C_BACKSLASH continuation type. + errors = (('def function1(self, a, b\\\n'), # Bracket. + (' """ (\\\n'), # Docstring. + ('a = #\\\n'), # Inline comment. + ) + for string in errors: + with self.subTest(string=string): + setstr(string) + with self.assertRaises(AssertionError): + indent() + + TestInfo = namedtuple('TestInfo', ('string', 'spaces')) + tests = (TestInfo('a = (1 + 2) - 5 *\\\n', 4), + TestInfo('a = 1 + 2 - 5 *\\\n', 4), + TestInfo(' a = 1 + 2 - 5 *\\\n', 8), + TestInfo(' a = "spam"\\\n', 6), + TestInfo(' a = \\\n"a"\\\n', 4), + TestInfo(' a = #\\\n"a"\\\n', 5), + TestInfo('a == \\\n', 2), + TestInfo('a != \\\n', 2), + # Difference between containing = and those not. + TestInfo('\\\n', 2), + TestInfo(' \\\n', 6), + TestInfo('\t\\\n', 6), + TestInfo('a\\\n', 3), + TestInfo('{}\\\n', 4), + TestInfo('(1 + 2) - 5 *\\\n', 3), + ) + for test in tests: + with self.subTest(string=test.string): + setstr(test.string) + eq(indent(), test.spaces) + + def test_get_base_indent_string(self): + eq = self.assertEqual + p = self.parser + setstr = p.set_str + baseindent = p.get_base_indent_string + + TestInfo = namedtuple('TestInfo', ['string', 'indent']) + tests = (TestInfo('', ''), + TestInfo('def a():\n', ''), + TestInfo('\tdef a():\n', '\t'), + TestInfo(' def a():\n', ' '), + TestInfo(' def a(\n', ' '), + TestInfo('\t\n def a(\n', ' '), + TestInfo('\t\n # Comment.\n', ' '), + ) + + for test in tests: + with self.subTest(string=test.string): + setstr(test.string) + eq(baseindent(), test.indent) + + def test_is_block_opener(self): + yes = self.assertTrue + no = self.assertFalse + p = self.parser + setstr = p.set_str + opener = p.is_block_opener + + TestInfo = namedtuple('TestInfo', ['string', 'assert_']) + tests = ( + TestInfo('def a():\n', yes), + TestInfo('\n def function1(self, a,\n b):\n', yes), + TestInfo(':\n', yes), + TestInfo('a:\n', yes), + TestInfo('):\n', yes), + TestInfo('(:\n', yes), + TestInfo('":\n', no), + TestInfo('\n def function1(self, a,\n', no), + TestInfo('def function1(self, a):\n pass\n', no), + TestInfo('# A comment:\n', no), + TestInfo('"""A docstring:\n', no), + TestInfo('"""A docstring:\n', no), + ) + + for test in tests: + with self.subTest(string=test.string): + setstr(test.string) + test.assert_(opener()) + + def test_is_block_closer(self): + yes = self.assertTrue + no = self.assertFalse + p = self.parser + setstr = p.set_str + closer = p.is_block_closer + + TestInfo = namedtuple('TestInfo', ['string', 'assert_']) + tests = ( + TestInfo('return\n', yes), + TestInfo('\tbreak\n', yes), + TestInfo(' continue\n', yes), + TestInfo(' raise\n', yes), + TestInfo('pass \n', yes), + TestInfo('pass\t\n', yes), + TestInfo('return #\n', yes), + TestInfo('raised\n', no), + TestInfo('returning\n', no), + TestInfo('# return\n', no), + TestInfo('"""break\n', no), + TestInfo('"continue\n', no), + TestInfo('def function1(self, a):\n pass\n', yes), + ) + + for test in tests: + with self.subTest(string=test.string): + setstr(test.string) + test.assert_(closer()) + + def test_get_last_open_bracket_pos(self): + eq = self.assertEqual + p = self.parser + setstr = p.set_str + openbracket = p.get_last_open_bracket_pos + + TestInfo = namedtuple('TestInfo', ['string', 'position']) + tests = ( + TestInfo('', None), + TestInfo('a\n', None), + TestInfo('# (\n', None), + TestInfo('""" (\n', None), + TestInfo('a = (1 + 2) - 5 *\\\n', None), + TestInfo('\n def function1(self, a,\n', 17), + TestInfo('\n def function1(self, a, # End of line comment.\n', 17), + TestInfo('{)(]\n', None), + TestInfo('(((((((((()))))))\n', 2), + TestInfo('(((((((((())\n)))\n))\n', 2), + ) + + for test in tests: + # There is a bug where the value is carried forward from last item. + p.lastopenbracketpos = None + with self.subTest(string=test.string): + setstr(test.string) + eq(openbracket(), test.position) + + def test_get_last_stmt_bracketing(self): + eq = self.assertEqual + p = self.parser + setstr = p.set_str + bracketing = p.get_last_stmt_bracketing + + TestInfo = namedtuple('TestInfo', ['string', 'bracket']) + tests = ( + TestInfo('', ((0, 0),)), + TestInfo('a\n', ((0, 0),)), + TestInfo('()()\n', ((0, 0), (0, 1), (2, 0), (2, 1), (4, 0))), + TestInfo('(\n)()\n', ((0, 0), (0, 1), (3, 0), (3, 1), (5, 0))), + TestInfo('()\n()\n', ((3, 0), (3, 1), (5, 0))), + TestInfo('()(\n)\n', ((0, 0), (0, 1), (2, 0), (2, 1), (5, 0))), + TestInfo('(())\n', ((0, 0), (0, 1), (1, 2), (3, 1), (4, 0))), + TestInfo('(\n())\n', ((0, 0), (0, 1), (2, 2), (4, 1), (5, 0))), + # Same as matched test. + TestInfo('{)(]\n', ((0, 0), (0, 1), (2, 0), (2, 1), (4, 0))), + TestInfo('(((())\n', + ((0, 0), (0, 1), (1, 2), (2, 3), (3, 4), (5, 3), (6, 2))), + ) + + for test in tests: + with self.subTest(string=test.string): + setstr(test.string) + eq(bracketing(), test.bracket) + + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/Lib/idlelib/pyparse.py b/Lib/idlelib/pyparse.py index 536b2d7f5fef..72bd9e00c1e9 100644 --- a/Lib/idlelib/pyparse.py +++ b/Lib/idlelib/pyparse.py @@ -1,8 +1,20 @@ +"""Define partial Python code Parser used by editor and hyperparser. + +Instances of StringTranslatePseudoMapping are used with str.translate. + +The following bound search and match functions are defined: +_synchre - start of popular statement; +_junkre - whitespace or comment line; +_match_stringre: string, possibly without closer; +_itemre - line that may have bracket structure start; +_closere - line that must be followed by dedent. +_chew_ordinaryre - non-special characters. +""" from collections.abc import Mapping import re import sys -# Reason last stmt is continued (or C_NONE if it's not). +# Reason last statement is continued (or C_NONE if it's not). (C_NONE, C_BACKSLASH, C_STRING_FIRST_LINE, C_STRING_NEXT_LINES, C_BRACKET) = range(5) @@ -10,7 +22,7 @@ def dump(*stuff): sys.__stdout__.write(" ".join(map(str, stuff)) + "\n") -# Find what looks like the start of a popular stmt. +# Find what looks like the start of a popular statement. _synchre = re.compile(r""" ^ @@ -70,7 +82,7 @@ def dump(*stuff): [^\s#\\] # if we match, m.end()-1 is the interesting char """, re.VERBOSE).match -# Match start of stmts that should be followed by a dedent. +# Match start of statements that should be followed by a dedent. _closere = re.compile(r""" \s* @@ -146,19 +158,20 @@ def set_str(self, s): self.str = s self.study_level = 0 - # Return index of a good place to begin parsing, as close to the - # end of the string as possible. This will be the start of some - # popular stmt like "if" or "def". Return None if none found: - # the caller should pass more prior context then, if possible, or - # if not (the entire program text up until the point of interest - # has already been tried) pass 0 to set_lo. - # - # This will be reliable iff given a reliable is_char_in_string - # function, meaning that when it says "no", it's absolutely - # guaranteed that the char is not in a string. - def find_good_parse_start(self, is_char_in_string=None, _synchre=_synchre): + """ + Return index of a good place to begin parsing, as close to the + end of the string as possible. This will be the start of some + popular stmt like "if" or "def". Return None if none found: + the caller should pass more prior context then, if possible, or + if not (the entire program text up until the point of interest + has already been tried) pass 0 to set_lo(). + + This will be reliable iff given a reliable is_char_in_string() + function, meaning that when it says "no", it's absolutely + guaranteed that the char is not in a string. + """ str, pos = self.str, None if not is_char_in_string: @@ -173,7 +186,7 @@ def find_good_parse_start(self, is_char_in_string=None, i = str.rfind(":\n", 0, limit) if i < 0: break - i = str.rfind('\n', 0, i) + 1 # start of colon line + i = str.rfind('\n', 0, i) + 1 # start of colon line (-1+1=0) m = _synchre(str, i, limit) if m and not is_char_in_string(m.start()): pos = m.start() @@ -206,10 +219,11 @@ def find_good_parse_start(self, is_char_in_string=None, break return pos - # Throw away the start of the string. Intended to be called with - # find_good_parse_start's result. - def set_lo(self, lo): + """ Throw away the start of the string. + + Intended to be called with the result of find_good_parse_start(). + """ assert lo == 0 or self.str[lo-1] == '\n' if lo > 0: self.str = self.str[lo:] @@ -224,11 +238,13 @@ def set_lo(self, lo): _tran.update((ord(c), ord(c)) for c in "\"'\\\n#") _tran = StringTranslatePseudoMapping(_tran, default_value=ord('x')) - # As quickly as humanly possible , find the line numbers (0- - # based) of the non-continuation lines. - # Creates self.{goodlines, continuation}. - def _study1(self): + """Find the line numbers of non-continuation lines. + + As quickly as humanly possible , find the line numbers (0- + based) of the non-continuation lines. + Creates self.{goodlines, continuation}. + """ if self.study_level >= 1: return self.study_level = 1 @@ -244,8 +260,8 @@ def _study1(self): str = str.replace('xx', 'x') str = str.replace('xx', 'x') str = str.replace('\nx', '\n') - # note that replacing x\n with \n would be incorrect, because - # x may be preceded by a backslash + # Replacing x\n with \n would be incorrect because + # x may be preceded by a backslash. # March over the squashed version of the program, accumulating # the line numbers of non-continued stmts, and determining @@ -360,24 +376,25 @@ def get_continuation_type(self): self._study1() return self.continuation - # study1 was sufficient to determine the continuation status, - # but doing more requires looking at every character. study2 - # does this for the last interesting statement in the block. - # Creates: - # self.stmt_start, stmt_end - # slice indices of last interesting stmt - # self.stmt_bracketing - # the bracketing structure of the last interesting stmt; - # for example, for the statement "say(boo) or die", stmt_bracketing - # will be [(0, 0), (3, 1), (8, 0)]. Strings and comments are - # treated as brackets, for the matter. - # self.lastch - # last non-whitespace character before optional trailing - # comment - # self.lastopenbracketpos - # if continuation is C_BRACKET, index of last open bracket - def _study2(self): + """ + study1 was sufficient to determine the continuation status, + but doing more requires looking at every character. study2 + does this for the last interesting statement in the block. + Creates: + self.stmt_start, stmt_end + slice indices of last interesting stmt + self.stmt_bracketing + the bracketing structure of the last interesting stmt; for + example, for the statement "say(boo) or die", + stmt_bracketing will be ((0, 0), (0, 1), (2, 0), (2, 1), + (4, 0)). Strings and comments are treated as brackets, for + the matter. + self.lastch + last interesting character before optional trailing comment + self.lastopenbracketpos + if continuation is C_BRACKET, index of last open bracket + """ if self.study_level >= 2: return self._study1() @@ -385,11 +402,11 @@ def _study2(self): # Set p and q to slice indices of last interesting stmt. str, goodlines = self.str, self.goodlines - i = len(goodlines) - 1 - p = len(str) # index of newest line + i = len(goodlines) - 1 # Index of newest line. + p = len(str) # End of goodlines[i] while i: assert p - # p is the index of the stmt at line number goodlines[i]. + # Make p be the index of the stmt at line number goodlines[i]. # Move p back to the stmt at line number goodlines[i-1]. q = p for nothing in range(goodlines[i-1], goodlines[i]): @@ -483,10 +500,11 @@ def _study2(self): self.lastopenbracketpos = stack[-1] self.stmt_bracketing = tuple(bracketing) - # Assuming continuation is C_BRACKET, return the number - # of spaces the next line should be indented. - def compute_bracket_indent(self): + """Return number of spaces the next line should be indented. + + Line continuation must be C_BRACKET. + """ self._study2() assert self.continuation == C_BRACKET j = self.lastopenbracketpos @@ -513,20 +531,22 @@ def compute_bracket_indent(self): extra = self.indentwidth return len(str[i:j].expandtabs(self.tabwidth)) + extra - # Return number of physical lines in last stmt (whether or not - # it's an interesting stmt! this is intended to be called when - # continuation is C_BACKSLASH). - def get_num_lines_in_stmt(self): + """Return number of physical lines in last stmt. + + The statement doesn't have to be an interesting statement. This is + intended to be called when continuation is C_BACKSLASH. + """ self._study1() goodlines = self.goodlines return goodlines[-1] - goodlines[-2] - # Assuming continuation is C_BACKSLASH, return the number of spaces - # the next line should be indented. Also assuming the new line is - # the first one following the initial line of the stmt. - def compute_backslash_indent(self): + """Return number of spaces the next line should be indented. + + Line continuation must be C_BACKSLASH. Also assume that the new + line is the first one following the initial line of the stmt. + """ self._study2() assert self.continuation == C_BACKSLASH str = self.str @@ -551,6 +571,8 @@ def compute_backslash_indent(self): elif ch == '"' or ch == "'": i = _match_stringre(str, i, endpos).end() elif ch == '#': + # This line is unreachable because the # makes a comment of + # everything after it. break elif level == 0 and ch == '=' and \ (i == 0 or str[i-1] not in "=<>!") and \ @@ -576,10 +598,10 @@ def compute_backslash_indent(self): return len(str[self.stmt_start:i].expandtabs(\ self.tabwidth)) + 1 - # Return the leading whitespace on the initial line of the last - # interesting stmt. - def get_base_indent_string(self): + """Return the leading whitespace on the initial line of the last + interesting stmt. + """ self._study2() i, n = self.stmt_start, self.stmt_end j = i @@ -588,30 +610,37 @@ def get_base_indent_string(self): j = j + 1 return str[i:j] - # Did the last interesting stmt open a block? - def is_block_opener(self): + "Return True if the last interesting statemtent opens a block." self._study2() return self.lastch == ':' - # Did the last interesting stmt close a block? - def is_block_closer(self): + "Return True if the last interesting statement closes a block." self._study2() return _closere(self.str, self.stmt_start) is not None - # index of last open bracket ({[, or None if none + # XXX - is this used? lastopenbracketpos = None def get_last_open_bracket_pos(self): + "Return index of last open bracket or None." self._study2() return self.lastopenbracketpos - # the structure of the bracketing of the last interesting statement, - # in the format defined in _study2, or None if the text didn't contain - # anything + # XXX - is this used? stmt_bracketing = None def get_last_stmt_bracketing(self): + """Return a tuple of the structure of the bracketing of the last + interesting statement. + + Tuple is in the format defined in _study2(). + """ self._study2() return self.stmt_bracketing + + +if __name__ == '__main__': #pragma: nocover + import unittest + unittest.main('idlelib.idle_test.test_pyparse', verbosity=2) diff --git a/Misc/NEWS.d/next/IDLE/2018-02-19-10-56-41.bpo-32874.6pZ9Gv.rst b/Misc/NEWS.d/next/IDLE/2018-02-19-10-56-41.bpo-32874.6pZ9Gv.rst new file mode 100644 index 000000000000..79655315fff4 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2018-02-19-10-56-41.bpo-32874.6pZ9Gv.rst @@ -0,0 +1 @@ +Add tests for pyparse. From webhook-mailer at python.org Wed Feb 21 23:34:45 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 22 Feb 2018 04:34:45 -0000 Subject: [Python-checkins] bpo-32874: IDLE: add tests for pyparse (GH-5755) Message-ID: https://github.com/python/cpython/commit/52064c3d8a62c8c14967ec1e004927e9297bb62c commit: 52064c3d8a62c8c14967ec1e004927e9297bb62c branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-21T20:34:43-08:00 summary: bpo-32874: IDLE: add tests for pyparse (GH-5755) There are no code changes other than comments and docstrings. (cherry picked from commit c84cf6c03fce1fb73bfaf91d7909f1c2708f14a2) Co-authored-by: Cheryl Sabella files: A Lib/idlelib/idle_test/test_pyparse.py A Misc/NEWS.d/next/IDLE/2018-02-19-10-56-41.bpo-32874.6pZ9Gv.rst M Lib/idlelib/pyparse.py diff --git a/Lib/idlelib/idle_test/test_pyparse.py b/Lib/idlelib/idle_test/test_pyparse.py new file mode 100644 index 000000000000..b84e9f843081 --- /dev/null +++ b/Lib/idlelib/idle_test/test_pyparse.py @@ -0,0 +1,523 @@ +"""Unittest for idlelib.pyparse.py.""" + +from collections import namedtuple +import unittest +from idlelib import pyparse + + +class StringTranslatePseudoMappingTest(unittest.TestCase): + + @classmethod + def setUpClass(cls): + whitespace_chars = ' \t\n\r' + cls.preserve_dict = {ord(c): ord(c) for c in whitespace_chars} + cls.default = ord('x') + cls.mapping = pyparse.StringTranslatePseudoMapping( + cls.preserve_dict, default_value=ord('x')) + + @classmethod + def tearDownClass(cls): + del cls.preserve_dict, cls.default, cls.mapping + + def test__init__(self): + m = self.mapping + self.assertEqual(m._non_defaults, self.preserve_dict) + self.assertEqual(m._default_value, self.default) + + def test__get_item__(self): + self.assertEqual(self.mapping[ord('\t')], ord('\t')) + self.assertEqual(self.mapping[ord('a')], self.default) + + def test__len__(self): + self.assertEqual(len(self.mapping), len(self.preserve_dict)) + + def test__iter__(self): + count = 0 + for key, value in self.mapping.items(): + self.assertIn(key, self.preserve_dict) + count += 1 + self.assertEqual(count, len(self.mapping)) + + def test_get(self): + self.assertEqual(self.mapping.get(ord('\t')), ord('\t')) + self.assertEqual(self.mapping.get('a'), self.default) + # Default is a parameter, but it isn't used. + self.assertEqual(self.mapping.get('a', default=500), self.default) + + +class PyParseTest(unittest.TestCase): + + @classmethod + def setUpClass(cls): + cls.parser = pyparse.Parser(indentwidth=4, tabwidth=4) + + @classmethod + def tearDownClass(cls): + del cls.parser + + def test_init(self): + self.assertEqual(self.parser.indentwidth, 4) + self.assertEqual(self.parser.tabwidth, 4) + + def test_set_str(self): + eq = self.assertEqual + p = self.parser + setstr = p.set_str + + # Not empty and doesn't end with newline. + with self.assertRaises(AssertionError): + setstr('a') + + tests = ('', + 'a\n') + + for string in tests: + with self.subTest(string=string): + setstr(string) + eq(p.str, string) + eq(p.study_level, 0) + + def test_find_good_parse_start(self): + eq = self.assertEqual + p = self.parser + setstr = p.set_str + start = p.find_good_parse_start + + # Split def across lines. + setstr('"""This is a module docstring"""\n' + 'class C():\n' + ' def __init__(self, a,\n' + ' b=True):\n' + ' pass\n' + ) + + # No value sent for is_char_in_string(). + self.assertIsNone(start()) + + # Make text look like a string. This returns pos as the start + # position, but it's set to None. + self.assertIsNone(start(is_char_in_string=lambda index: True)) + + # Make all text look like it's not in a string. This means that it + # found a good start position. + eq(start(is_char_in_string=lambda index: False), 44) + + # If the beginning of the def line is not in a string, then it + # returns that as the index. + eq(start(is_char_in_string=lambda index: index > 44), 44) + # If the beginning of the def line is in a string, then it + # looks for a previous index. + eq(start(is_char_in_string=lambda index: index >= 44), 33) + # If everything before the 'def' is in a string, then returns None. + # The non-continuation def line returns 44 (see below). + eq(start(is_char_in_string=lambda index: index < 44), None) + + # Code without extra line break in def line - mostly returns the same + # values. + setstr('"""This is a module docstring"""\n' + 'class C():\n' + ' def __init__(self, a, b=True):\n' + ' pass\n' + ) + eq(start(is_char_in_string=lambda index: False), 44) + eq(start(is_char_in_string=lambda index: index > 44), 44) + eq(start(is_char_in_string=lambda index: index >= 44), 33) + # When the def line isn't split, this returns which doesn't match the + # split line test. + eq(start(is_char_in_string=lambda index: index < 44), 44) + + def test_set_lo(self): + code = ( + '"""This is a module docstring"""\n' + 'class C():\n' + ' def __init__(self, a,\n' + ' b=True):\n' + ' pass\n' + ) + p = self.parser + p.set_str(code) + + # Previous character is not a newline. + with self.assertRaises(AssertionError): + p.set_lo(5) + + # A value of 0 doesn't change self.str. + p.set_lo(0) + self.assertEqual(p.str, code) + + # An index that is preceded by a newline. + p.set_lo(44) + self.assertEqual(p.str, code[44:]) + + def test_tran(self): + self.assertEqual('\t a([{b}])b"c\'d\n'.translate(self.parser._tran), + 'xxx(((x)))x"x\'x\n') + + def test_study1(self): + eq = self.assertEqual + p = self.parser + setstr = p.set_str + study = p._study1 + + (NONE, BACKSLASH, FIRST, NEXT, BRACKET) = range(5) + TestInfo = namedtuple('TestInfo', ['string', 'goodlines', + 'continuation']) + tests = ( + TestInfo('', [0], NONE), + # Docstrings. + TestInfo('"""This is a complete docstring."""\n', [0, 1], NONE), + TestInfo("'''This is a complete docstring.'''\n", [0, 1], NONE), + TestInfo('"""This is a continued docstring.\n', [0, 1], FIRST), + TestInfo("'''This is a continued docstring.\n", [0, 1], FIRST), + TestInfo('"""Closing quote does not match."\n', [0, 1], FIRST), + TestInfo('"""Bracket in docstring [\n', [0, 1], FIRST), + TestInfo("'''Incomplete two line docstring.\n\n", [0, 2], NEXT), + # Single-quoted strings. + TestInfo('"This is a complete string."\n', [0, 1], NONE), + TestInfo('"This is an incomplete string.\n', [0, 1], NONE), + TestInfo("'This is more incomplete.\n\n", [0, 1, 2], NONE), + # Comment (backslash does not continue comments). + TestInfo('# Comment\\\n', [0, 1], NONE), + # Brackets. + TestInfo('("""Complete string in bracket"""\n', [0, 1], BRACKET), + TestInfo('("""Open string in bracket\n', [0, 1], FIRST), + TestInfo('a = (1 + 2) - 5 *\\\n', [0, 1], BACKSLASH), # No bracket. + TestInfo('\n def function1(self, a,\n b):\n', + [0, 1, 3], NONE), + TestInfo('\n def function1(self, a,\\\n', [0, 1, 2], BRACKET), + TestInfo('\n def function1(self, a,\n', [0, 1, 2], BRACKET), + TestInfo('())\n', [0, 1], NONE), # Extra closer. + TestInfo(')(\n', [0, 1], BRACKET), # Extra closer. + # For the mismatched example, it doesn't look like contination. + TestInfo('{)(]\n', [0, 1], NONE), # Mismatched. + ) + + for test in tests: + with self.subTest(string=test.string): + setstr(test.string) # resets study_level + study() + eq(p.study_level, 1) + eq(p.goodlines, test.goodlines) + eq(p.continuation, test.continuation) + + # Called again, just returns without reprocessing. + self.assertIsNone(study()) + + def test_get_continuation_type(self): + eq = self.assertEqual + p = self.parser + setstr = p.set_str + gettype = p.get_continuation_type + + (NONE, BACKSLASH, FIRST, NEXT, BRACKET) = range(5) + TestInfo = namedtuple('TestInfo', ['string', 'continuation']) + tests = ( + TestInfo('', NONE), + TestInfo('"""This is a continuation docstring.\n', FIRST), + TestInfo("'''This is a multiline-continued docstring.\n\n", NEXT), + TestInfo('a = (1 + 2) - 5 *\\\n', BACKSLASH), + TestInfo('\n def function1(self, a,\\\n', BRACKET) + ) + + for test in tests: + with self.subTest(string=test.string): + setstr(test.string) + eq(gettype(), test.continuation) + + def test_study2(self): + eq = self.assertEqual + p = self.parser + setstr = p.set_str + study = p._study2 + + TestInfo = namedtuple('TestInfo', ['string', 'start', 'end', 'lastch', + 'openbracket', 'bracketing']) + tests = ( + TestInfo('', 0, 0, '', None, ((0, 0),)), + TestInfo("'''This is a multiline continutation docstring.\n\n", + 0, 49, "'", None, ((0, 0), (0, 1), (49, 0))), + TestInfo(' # Comment\\\n', + 0, 12, '', None, ((0, 0), (1, 1), (12, 0))), + # A comment without a space is a special case + TestInfo(' #Comment\\\n', + 0, 0, '', None, ((0, 0),)), + # Backslash continuation. + TestInfo('a = (1 + 2) - 5 *\\\n', + 0, 19, '*', None, ((0, 0), (4, 1), (11, 0))), + # Bracket continuation with close. + TestInfo('\n def function1(self, a,\n b):\n', + 1, 48, ':', None, ((1, 0), (17, 1), (46, 0))), + # Bracket continuation with unneeded backslash. + TestInfo('\n def function1(self, a,\\\n', + 1, 28, ',', 17, ((1, 0), (17, 1))), + # Bracket continuation. + TestInfo('\n def function1(self, a,\n', + 1, 27, ',', 17, ((1, 0), (17, 1))), + # Bracket continuation with comment at end of line with text. + TestInfo('\n def function1(self, a, # End of line comment.\n', + 1, 51, ',', 17, ((1, 0), (17, 1), (28, 2), (51, 1))), + # Multi-line statement with comment line in between code lines. + TestInfo(' a = ["first item",\n # Comment line\n "next item",\n', + 0, 55, ',', 6, ((0, 0), (6, 1), (7, 2), (19, 1), + (23, 2), (38, 1), (42, 2), (53, 1))), + TestInfo('())\n', + 0, 4, ')', None, ((0, 0), (0, 1), (2, 0), (3, 0))), + TestInfo(')(\n', 0, 3, '(', 1, ((0, 0), (1, 0), (1, 1))), + # Wrong closers still decrement stack level. + TestInfo('{)(]\n', + 0, 5, ']', None, ((0, 0), (0, 1), (2, 0), (2, 1), (4, 0))), + # Character after backslash. + TestInfo(':\\a\n', 0, 4, '\\a', None, ((0, 0),)), + TestInfo('\n', 0, 0, '', None, ((0, 0),)), + ) + + for test in tests: + # There is a bug where this is carried forward from last item. + p.lastopenbracketpos = None + with self.subTest(string=test.string): + setstr(test.string) + study() + eq(p.study_level, 2) + eq(p.stmt_start, test.start) + eq(p.stmt_end, test.end) + eq(p.lastch, test.lastch) + eq(p.lastopenbracketpos, test.openbracket) + eq(p.stmt_bracketing, test.bracketing) + + # Called again, just returns without reprocessing. + self.assertIsNone(study()) + + def test_get_num_lines_in_stmt(self): + eq = self.assertEqual + p = self.parser + setstr = p.set_str + getlines = p.get_num_lines_in_stmt + + TestInfo = namedtuple('TestInfo', ['string', 'lines']) + tests = ( + TestInfo('[x for x in a]\n', 1), # Closed on one line. + TestInfo('[x\nfor x in a\n', 2), # Not closed. + TestInfo('[x\\\nfor x in a\\\n', 2), # "", uneeded backslashes. + TestInfo('[x\nfor x in a\n]\n', 3), # Closed on multi-line. + TestInfo('\n"""Docstring comment L1"""\nL2\nL3\nL4\n', 1), + TestInfo('\n"""Docstring comment L1\nL2"""\nL3\nL4\n', 1), + TestInfo('\n"""Docstring comment L1\\\nL2\\\nL3\\\nL4\\\n', 4), + TestInfo('\n\n"""Docstring comment L1\\\nL2\\\nL3\\\nL4\\\n"""\n', 5) + ) + + # Blank string doesn't have enough elements in goodlines. + setstr('') + with self.assertRaises(IndexError): + getlines() + + for test in tests: + with self.subTest(string=test.string): + setstr(test.string) + eq(getlines(), test.lines) + + def test_compute_bracket_indent(self): + eq = self.assertEqual + p = self.parser + setstr = p.set_str + indent = p.compute_bracket_indent + + TestInfo = namedtuple('TestInfo', ['string', 'spaces']) + tests = ( + TestInfo('def function1(self, a,\n', 14), + # Characters after bracket. + TestInfo('\n def function1(self, a,\n', 18), + TestInfo('\n\tdef function1(self, a,\n', 18), + # No characters after bracket. + TestInfo('\n def function1(\n', 8), + TestInfo('\n\tdef function1(\n', 8), + TestInfo('\n def function1( \n', 8), # Ignore extra spaces. + TestInfo('[\n"first item",\n # Comment line\n "next item",\n', 0), + TestInfo('[\n "first item",\n # Comment line\n "next item",\n', 2), + TestInfo('["first item",\n # Comment line\n "next item",\n', 1), + TestInfo('(\n', 4), + TestInfo('(a\n', 1), + ) + + # Must be C_BRACKET continuation type. + setstr('def function1(self, a, b):\n') + with self.assertRaises(AssertionError): + indent() + + for test in tests: + setstr(test.string) + eq(indent(), test.spaces) + + def test_compute_backslash_indent(self): + eq = self.assertEqual + p = self.parser + setstr = p.set_str + indent = p.compute_backslash_indent + + # Must be C_BACKSLASH continuation type. + errors = (('def function1(self, a, b\\\n'), # Bracket. + (' """ (\\\n'), # Docstring. + ('a = #\\\n'), # Inline comment. + ) + for string in errors: + with self.subTest(string=string): + setstr(string) + with self.assertRaises(AssertionError): + indent() + + TestInfo = namedtuple('TestInfo', ('string', 'spaces')) + tests = (TestInfo('a = (1 + 2) - 5 *\\\n', 4), + TestInfo('a = 1 + 2 - 5 *\\\n', 4), + TestInfo(' a = 1 + 2 - 5 *\\\n', 8), + TestInfo(' a = "spam"\\\n', 6), + TestInfo(' a = \\\n"a"\\\n', 4), + TestInfo(' a = #\\\n"a"\\\n', 5), + TestInfo('a == \\\n', 2), + TestInfo('a != \\\n', 2), + # Difference between containing = and those not. + TestInfo('\\\n', 2), + TestInfo(' \\\n', 6), + TestInfo('\t\\\n', 6), + TestInfo('a\\\n', 3), + TestInfo('{}\\\n', 4), + TestInfo('(1 + 2) - 5 *\\\n', 3), + ) + for test in tests: + with self.subTest(string=test.string): + setstr(test.string) + eq(indent(), test.spaces) + + def test_get_base_indent_string(self): + eq = self.assertEqual + p = self.parser + setstr = p.set_str + baseindent = p.get_base_indent_string + + TestInfo = namedtuple('TestInfo', ['string', 'indent']) + tests = (TestInfo('', ''), + TestInfo('def a():\n', ''), + TestInfo('\tdef a():\n', '\t'), + TestInfo(' def a():\n', ' '), + TestInfo(' def a(\n', ' '), + TestInfo('\t\n def a(\n', ' '), + TestInfo('\t\n # Comment.\n', ' '), + ) + + for test in tests: + with self.subTest(string=test.string): + setstr(test.string) + eq(baseindent(), test.indent) + + def test_is_block_opener(self): + yes = self.assertTrue + no = self.assertFalse + p = self.parser + setstr = p.set_str + opener = p.is_block_opener + + TestInfo = namedtuple('TestInfo', ['string', 'assert_']) + tests = ( + TestInfo('def a():\n', yes), + TestInfo('\n def function1(self, a,\n b):\n', yes), + TestInfo(':\n', yes), + TestInfo('a:\n', yes), + TestInfo('):\n', yes), + TestInfo('(:\n', yes), + TestInfo('":\n', no), + TestInfo('\n def function1(self, a,\n', no), + TestInfo('def function1(self, a):\n pass\n', no), + TestInfo('# A comment:\n', no), + TestInfo('"""A docstring:\n', no), + TestInfo('"""A docstring:\n', no), + ) + + for test in tests: + with self.subTest(string=test.string): + setstr(test.string) + test.assert_(opener()) + + def test_is_block_closer(self): + yes = self.assertTrue + no = self.assertFalse + p = self.parser + setstr = p.set_str + closer = p.is_block_closer + + TestInfo = namedtuple('TestInfo', ['string', 'assert_']) + tests = ( + TestInfo('return\n', yes), + TestInfo('\tbreak\n', yes), + TestInfo(' continue\n', yes), + TestInfo(' raise\n', yes), + TestInfo('pass \n', yes), + TestInfo('pass\t\n', yes), + TestInfo('return #\n', yes), + TestInfo('raised\n', no), + TestInfo('returning\n', no), + TestInfo('# return\n', no), + TestInfo('"""break\n', no), + TestInfo('"continue\n', no), + TestInfo('def function1(self, a):\n pass\n', yes), + ) + + for test in tests: + with self.subTest(string=test.string): + setstr(test.string) + test.assert_(closer()) + + def test_get_last_open_bracket_pos(self): + eq = self.assertEqual + p = self.parser + setstr = p.set_str + openbracket = p.get_last_open_bracket_pos + + TestInfo = namedtuple('TestInfo', ['string', 'position']) + tests = ( + TestInfo('', None), + TestInfo('a\n', None), + TestInfo('# (\n', None), + TestInfo('""" (\n', None), + TestInfo('a = (1 + 2) - 5 *\\\n', None), + TestInfo('\n def function1(self, a,\n', 17), + TestInfo('\n def function1(self, a, # End of line comment.\n', 17), + TestInfo('{)(]\n', None), + TestInfo('(((((((((()))))))\n', 2), + TestInfo('(((((((((())\n)))\n))\n', 2), + ) + + for test in tests: + # There is a bug where the value is carried forward from last item. + p.lastopenbracketpos = None + with self.subTest(string=test.string): + setstr(test.string) + eq(openbracket(), test.position) + + def test_get_last_stmt_bracketing(self): + eq = self.assertEqual + p = self.parser + setstr = p.set_str + bracketing = p.get_last_stmt_bracketing + + TestInfo = namedtuple('TestInfo', ['string', 'bracket']) + tests = ( + TestInfo('', ((0, 0),)), + TestInfo('a\n', ((0, 0),)), + TestInfo('()()\n', ((0, 0), (0, 1), (2, 0), (2, 1), (4, 0))), + TestInfo('(\n)()\n', ((0, 0), (0, 1), (3, 0), (3, 1), (5, 0))), + TestInfo('()\n()\n', ((3, 0), (3, 1), (5, 0))), + TestInfo('()(\n)\n', ((0, 0), (0, 1), (2, 0), (2, 1), (5, 0))), + TestInfo('(())\n', ((0, 0), (0, 1), (1, 2), (3, 1), (4, 0))), + TestInfo('(\n())\n', ((0, 0), (0, 1), (2, 2), (4, 1), (5, 0))), + # Same as matched test. + TestInfo('{)(]\n', ((0, 0), (0, 1), (2, 0), (2, 1), (4, 0))), + TestInfo('(((())\n', + ((0, 0), (0, 1), (1, 2), (2, 3), (3, 4), (5, 3), (6, 2))), + ) + + for test in tests: + with self.subTest(string=test.string): + setstr(test.string) + eq(bracketing(), test.bracket) + + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/Lib/idlelib/pyparse.py b/Lib/idlelib/pyparse.py index 536b2d7f5fef..72bd9e00c1e9 100644 --- a/Lib/idlelib/pyparse.py +++ b/Lib/idlelib/pyparse.py @@ -1,8 +1,20 @@ +"""Define partial Python code Parser used by editor and hyperparser. + +Instances of StringTranslatePseudoMapping are used with str.translate. + +The following bound search and match functions are defined: +_synchre - start of popular statement; +_junkre - whitespace or comment line; +_match_stringre: string, possibly without closer; +_itemre - line that may have bracket structure start; +_closere - line that must be followed by dedent. +_chew_ordinaryre - non-special characters. +""" from collections.abc import Mapping import re import sys -# Reason last stmt is continued (or C_NONE if it's not). +# Reason last statement is continued (or C_NONE if it's not). (C_NONE, C_BACKSLASH, C_STRING_FIRST_LINE, C_STRING_NEXT_LINES, C_BRACKET) = range(5) @@ -10,7 +22,7 @@ def dump(*stuff): sys.__stdout__.write(" ".join(map(str, stuff)) + "\n") -# Find what looks like the start of a popular stmt. +# Find what looks like the start of a popular statement. _synchre = re.compile(r""" ^ @@ -70,7 +82,7 @@ def dump(*stuff): [^\s#\\] # if we match, m.end()-1 is the interesting char """, re.VERBOSE).match -# Match start of stmts that should be followed by a dedent. +# Match start of statements that should be followed by a dedent. _closere = re.compile(r""" \s* @@ -146,19 +158,20 @@ def set_str(self, s): self.str = s self.study_level = 0 - # Return index of a good place to begin parsing, as close to the - # end of the string as possible. This will be the start of some - # popular stmt like "if" or "def". Return None if none found: - # the caller should pass more prior context then, if possible, or - # if not (the entire program text up until the point of interest - # has already been tried) pass 0 to set_lo. - # - # This will be reliable iff given a reliable is_char_in_string - # function, meaning that when it says "no", it's absolutely - # guaranteed that the char is not in a string. - def find_good_parse_start(self, is_char_in_string=None, _synchre=_synchre): + """ + Return index of a good place to begin parsing, as close to the + end of the string as possible. This will be the start of some + popular stmt like "if" or "def". Return None if none found: + the caller should pass more prior context then, if possible, or + if not (the entire program text up until the point of interest + has already been tried) pass 0 to set_lo(). + + This will be reliable iff given a reliable is_char_in_string() + function, meaning that when it says "no", it's absolutely + guaranteed that the char is not in a string. + """ str, pos = self.str, None if not is_char_in_string: @@ -173,7 +186,7 @@ def find_good_parse_start(self, is_char_in_string=None, i = str.rfind(":\n", 0, limit) if i < 0: break - i = str.rfind('\n', 0, i) + 1 # start of colon line + i = str.rfind('\n', 0, i) + 1 # start of colon line (-1+1=0) m = _synchre(str, i, limit) if m and not is_char_in_string(m.start()): pos = m.start() @@ -206,10 +219,11 @@ def find_good_parse_start(self, is_char_in_string=None, break return pos - # Throw away the start of the string. Intended to be called with - # find_good_parse_start's result. - def set_lo(self, lo): + """ Throw away the start of the string. + + Intended to be called with the result of find_good_parse_start(). + """ assert lo == 0 or self.str[lo-1] == '\n' if lo > 0: self.str = self.str[lo:] @@ -224,11 +238,13 @@ def set_lo(self, lo): _tran.update((ord(c), ord(c)) for c in "\"'\\\n#") _tran = StringTranslatePseudoMapping(_tran, default_value=ord('x')) - # As quickly as humanly possible , find the line numbers (0- - # based) of the non-continuation lines. - # Creates self.{goodlines, continuation}. - def _study1(self): + """Find the line numbers of non-continuation lines. + + As quickly as humanly possible , find the line numbers (0- + based) of the non-continuation lines. + Creates self.{goodlines, continuation}. + """ if self.study_level >= 1: return self.study_level = 1 @@ -244,8 +260,8 @@ def _study1(self): str = str.replace('xx', 'x') str = str.replace('xx', 'x') str = str.replace('\nx', '\n') - # note that replacing x\n with \n would be incorrect, because - # x may be preceded by a backslash + # Replacing x\n with \n would be incorrect because + # x may be preceded by a backslash. # March over the squashed version of the program, accumulating # the line numbers of non-continued stmts, and determining @@ -360,24 +376,25 @@ def get_continuation_type(self): self._study1() return self.continuation - # study1 was sufficient to determine the continuation status, - # but doing more requires looking at every character. study2 - # does this for the last interesting statement in the block. - # Creates: - # self.stmt_start, stmt_end - # slice indices of last interesting stmt - # self.stmt_bracketing - # the bracketing structure of the last interesting stmt; - # for example, for the statement "say(boo) or die", stmt_bracketing - # will be [(0, 0), (3, 1), (8, 0)]. Strings and comments are - # treated as brackets, for the matter. - # self.lastch - # last non-whitespace character before optional trailing - # comment - # self.lastopenbracketpos - # if continuation is C_BRACKET, index of last open bracket - def _study2(self): + """ + study1 was sufficient to determine the continuation status, + but doing more requires looking at every character. study2 + does this for the last interesting statement in the block. + Creates: + self.stmt_start, stmt_end + slice indices of last interesting stmt + self.stmt_bracketing + the bracketing structure of the last interesting stmt; for + example, for the statement "say(boo) or die", + stmt_bracketing will be ((0, 0), (0, 1), (2, 0), (2, 1), + (4, 0)). Strings and comments are treated as brackets, for + the matter. + self.lastch + last interesting character before optional trailing comment + self.lastopenbracketpos + if continuation is C_BRACKET, index of last open bracket + """ if self.study_level >= 2: return self._study1() @@ -385,11 +402,11 @@ def _study2(self): # Set p and q to slice indices of last interesting stmt. str, goodlines = self.str, self.goodlines - i = len(goodlines) - 1 - p = len(str) # index of newest line + i = len(goodlines) - 1 # Index of newest line. + p = len(str) # End of goodlines[i] while i: assert p - # p is the index of the stmt at line number goodlines[i]. + # Make p be the index of the stmt at line number goodlines[i]. # Move p back to the stmt at line number goodlines[i-1]. q = p for nothing in range(goodlines[i-1], goodlines[i]): @@ -483,10 +500,11 @@ def _study2(self): self.lastopenbracketpos = stack[-1] self.stmt_bracketing = tuple(bracketing) - # Assuming continuation is C_BRACKET, return the number - # of spaces the next line should be indented. - def compute_bracket_indent(self): + """Return number of spaces the next line should be indented. + + Line continuation must be C_BRACKET. + """ self._study2() assert self.continuation == C_BRACKET j = self.lastopenbracketpos @@ -513,20 +531,22 @@ def compute_bracket_indent(self): extra = self.indentwidth return len(str[i:j].expandtabs(self.tabwidth)) + extra - # Return number of physical lines in last stmt (whether or not - # it's an interesting stmt! this is intended to be called when - # continuation is C_BACKSLASH). - def get_num_lines_in_stmt(self): + """Return number of physical lines in last stmt. + + The statement doesn't have to be an interesting statement. This is + intended to be called when continuation is C_BACKSLASH. + """ self._study1() goodlines = self.goodlines return goodlines[-1] - goodlines[-2] - # Assuming continuation is C_BACKSLASH, return the number of spaces - # the next line should be indented. Also assuming the new line is - # the first one following the initial line of the stmt. - def compute_backslash_indent(self): + """Return number of spaces the next line should be indented. + + Line continuation must be C_BACKSLASH. Also assume that the new + line is the first one following the initial line of the stmt. + """ self._study2() assert self.continuation == C_BACKSLASH str = self.str @@ -551,6 +571,8 @@ def compute_backslash_indent(self): elif ch == '"' or ch == "'": i = _match_stringre(str, i, endpos).end() elif ch == '#': + # This line is unreachable because the # makes a comment of + # everything after it. break elif level == 0 and ch == '=' and \ (i == 0 or str[i-1] not in "=<>!") and \ @@ -576,10 +598,10 @@ def compute_backslash_indent(self): return len(str[self.stmt_start:i].expandtabs(\ self.tabwidth)) + 1 - # Return the leading whitespace on the initial line of the last - # interesting stmt. - def get_base_indent_string(self): + """Return the leading whitespace on the initial line of the last + interesting stmt. + """ self._study2() i, n = self.stmt_start, self.stmt_end j = i @@ -588,30 +610,37 @@ def get_base_indent_string(self): j = j + 1 return str[i:j] - # Did the last interesting stmt open a block? - def is_block_opener(self): + "Return True if the last interesting statemtent opens a block." self._study2() return self.lastch == ':' - # Did the last interesting stmt close a block? - def is_block_closer(self): + "Return True if the last interesting statement closes a block." self._study2() return _closere(self.str, self.stmt_start) is not None - # index of last open bracket ({[, or None if none + # XXX - is this used? lastopenbracketpos = None def get_last_open_bracket_pos(self): + "Return index of last open bracket or None." self._study2() return self.lastopenbracketpos - # the structure of the bracketing of the last interesting statement, - # in the format defined in _study2, or None if the text didn't contain - # anything + # XXX - is this used? stmt_bracketing = None def get_last_stmt_bracketing(self): + """Return a tuple of the structure of the bracketing of the last + interesting statement. + + Tuple is in the format defined in _study2(). + """ self._study2() return self.stmt_bracketing + + +if __name__ == '__main__': #pragma: nocover + import unittest + unittest.main('idlelib.idle_test.test_pyparse', verbosity=2) diff --git a/Misc/NEWS.d/next/IDLE/2018-02-19-10-56-41.bpo-32874.6pZ9Gv.rst b/Misc/NEWS.d/next/IDLE/2018-02-19-10-56-41.bpo-32874.6pZ9Gv.rst new file mode 100644 index 000000000000..79655315fff4 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2018-02-19-10-56-41.bpo-32874.6pZ9Gv.rst @@ -0,0 +1 @@ +Add tests for pyparse. From webhook-mailer at python.org Wed Feb 21 23:55:21 2018 From: webhook-mailer at python.org (Benjamin Peterson) Date: Thu, 22 Feb 2018 04:55:21 -0000 Subject: [Python-checkins] closes bpo-32898: Fix debug build crash with COUNT_ALLOCS (GH-5800) Message-ID: https://github.com/python/cpython/commit/745dc65b17b3936e3f9f4099f735f174d30c4e0c commit: 745dc65b17b3936e3f9f4099f735f174d30c4e0c branch: master author: Eddie Elizondo committer: Benjamin Peterson date: 2018-02-21T20:55:18-08:00 summary: closes bpo-32898: Fix debug build crash with COUNT_ALLOCS (GH-5800) files: A Misc/NEWS.d/next/Build/2018-02-21-12-46-00.bpo-32898.M15bZh.rst M Misc/ACKS M Objects/listobject.c M Objects/object.c M Objects/tupleobject.c diff --git a/Misc/ACKS b/Misc/ACKS index b15b20e6c1c0..2eddc56d34d3 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -425,6 +425,7 @@ Tal Einat Eric Eisner Andrew Eland Julien ?lie +Eduardo Elizondo Lance Ellinghaus Daniel Ellis Phil Elson diff --git a/Misc/NEWS.d/next/Build/2018-02-21-12-46-00.bpo-32898.M15bZh.rst b/Misc/NEWS.d/next/Build/2018-02-21-12-46-00.bpo-32898.M15bZh.rst new file mode 100644 index 000000000000..4c75466bfd0f --- /dev/null +++ b/Misc/NEWS.d/next/Build/2018-02-21-12-46-00.bpo-32898.M15bZh.rst @@ -0,0 +1 @@ +Fix the python debug build when using COUNT_ALLOCS. diff --git a/Objects/listobject.c b/Objects/listobject.c index f0fe962be941..c8ffeff09368 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -86,7 +86,7 @@ static void show_alloc(void) { PyInterpreterState *interp = PyThreadState_GET()->interp; - if (!inter->core_config.show_alloc_count) { + if (!interp->core_config.show_alloc_count) { return; } diff --git a/Objects/object.c b/Objects/object.c index fef57fce7ba7..220aa90bf59c 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -97,10 +97,11 @@ void dump_counts(FILE* f) { PyInterpreterState *interp = PyThreadState_GET()->interp; - if (!inter->core_config.show_alloc_count) { + if (!interp->core_config.show_alloc_count) { return; } + PyTypeObject *tp; for (tp = type_list; tp; tp = tp->tp_next) fprintf(f, "%s alloc'd: %" PY_FORMAT_SIZE_T "d, " "freed: %" PY_FORMAT_SIZE_T "d, " diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index 39d43dd04a59..9bb91a5e65a0 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -45,7 +45,7 @@ static void show_track(void) { PyInterpreterState *interp = PyThreadState_GET()->interp; - if (!inter->core_config.show_alloc_count) { + if (!interp->core_config.show_alloc_count) { return; } From webhook-mailer at python.org Thu Feb 22 00:44:14 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 22 Feb 2018 05:44:14 -0000 Subject: [Python-checkins] closes bpo-32898: Fix debug build crash with COUNT_ALLOCS (GH-5800) Message-ID: https://github.com/python/cpython/commit/bc2e1104693fd471b96ecac5b2ab4cffa09830ab commit: bc2e1104693fd471b96ecac5b2ab4cffa09830ab branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-21T21:44:08-08:00 summary: closes bpo-32898: Fix debug build crash with COUNT_ALLOCS (GH-5800) (cherry picked from commit 745dc65b17b3936e3f9f4099f735f174d30c4e0c) Co-authored-by: Eddie Elizondo files: A Misc/NEWS.d/next/Build/2018-02-21-12-46-00.bpo-32898.M15bZh.rst M Misc/ACKS M Objects/listobject.c M Objects/object.c M Objects/tupleobject.c diff --git a/Misc/ACKS b/Misc/ACKS index 17505dfdcf0a..ec7ba956dc08 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -425,6 +425,7 @@ Tal Einat Eric Eisner Andrew Eland Julien ?lie +Eduardo Elizondo Lance Ellinghaus Daniel Ellis Phil Elson diff --git a/Misc/NEWS.d/next/Build/2018-02-21-12-46-00.bpo-32898.M15bZh.rst b/Misc/NEWS.d/next/Build/2018-02-21-12-46-00.bpo-32898.M15bZh.rst new file mode 100644 index 000000000000..4c75466bfd0f --- /dev/null +++ b/Misc/NEWS.d/next/Build/2018-02-21-12-46-00.bpo-32898.M15bZh.rst @@ -0,0 +1 @@ +Fix the python debug build when using COUNT_ALLOCS. diff --git a/Objects/listobject.c b/Objects/listobject.c index f0fe962be941..c8ffeff09368 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -86,7 +86,7 @@ static void show_alloc(void) { PyInterpreterState *interp = PyThreadState_GET()->interp; - if (!inter->core_config.show_alloc_count) { + if (!interp->core_config.show_alloc_count) { return; } diff --git a/Objects/object.c b/Objects/object.c index fef57fce7ba7..220aa90bf59c 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -97,10 +97,11 @@ void dump_counts(FILE* f) { PyInterpreterState *interp = PyThreadState_GET()->interp; - if (!inter->core_config.show_alloc_count) { + if (!interp->core_config.show_alloc_count) { return; } + PyTypeObject *tp; for (tp = type_list; tp; tp = tp->tp_next) fprintf(f, "%s alloc'd: %" PY_FORMAT_SIZE_T "d, " "freed: %" PY_FORMAT_SIZE_T "d, " diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index 39d43dd04a59..9bb91a5e65a0 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -45,7 +45,7 @@ static void show_track(void) { PyInterpreterState *interp = PyThreadState_GET()->interp; - if (!inter->core_config.show_alloc_count) { + if (!interp->core_config.show_alloc_count) { return; } From webhook-mailer at python.org Thu Feb 22 01:19:05 2018 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Thu, 22 Feb 2018 06:19:05 -0000 Subject: [Python-checkins] bpo-32905: IDLE - remove unused code in pyparse module (GH-5807) Message-ID: https://github.com/python/cpython/commit/451d1edaf4d27c4e632d81246d308e8dd6ea945f commit: 451d1edaf4d27c4e632d81246d308e8dd6ea945f branch: master author: Terry Jan Reedy committer: GitHub date: 2018-02-22T01:19:02-05:00 summary: bpo-32905: IDLE - remove unused code in pyparse module (GH-5807) dump is similar to print but less flexible. lastopenbracketpos is now always initialized in _study2, as was stmt_bracketing, so the class settings are not needed. get_last_open_bracket_pos is never called. files: A Misc/NEWS.d/next/IDLE/2018-02-22-00-09-27.bpo-32905.VlXj0x.rst M Lib/idlelib/idle_test/test_pyparse.py M Lib/idlelib/pyparse.py diff --git a/Lib/idlelib/idle_test/test_pyparse.py b/Lib/idlelib/idle_test/test_pyparse.py index b84e9f843081..c45815b36ff2 100644 --- a/Lib/idlelib/idle_test/test_pyparse.py +++ b/Lib/idlelib/idle_test/test_pyparse.py @@ -1,4 +1,7 @@ -"""Unittest for idlelib.pyparse.py.""" +"""Unittest for idlelib.pyparse.py. + +Coverage: 97% +""" from collections import namedtuple import unittest @@ -272,8 +275,6 @@ def test_study2(self): ) for test in tests: - # There is a bug where this is carried forward from last item. - p.lastopenbracketpos = None with self.subTest(string=test.string): setstr(test.string) study() @@ -464,33 +465,6 @@ def test_is_block_closer(self): setstr(test.string) test.assert_(closer()) - def test_get_last_open_bracket_pos(self): - eq = self.assertEqual - p = self.parser - setstr = p.set_str - openbracket = p.get_last_open_bracket_pos - - TestInfo = namedtuple('TestInfo', ['string', 'position']) - tests = ( - TestInfo('', None), - TestInfo('a\n', None), - TestInfo('# (\n', None), - TestInfo('""" (\n', None), - TestInfo('a = (1 + 2) - 5 *\\\n', None), - TestInfo('\n def function1(self, a,\n', 17), - TestInfo('\n def function1(self, a, # End of line comment.\n', 17), - TestInfo('{)(]\n', None), - TestInfo('(((((((((()))))))\n', 2), - TestInfo('(((((((((())\n)))\n))\n', 2), - ) - - for test in tests: - # There is a bug where the value is carried forward from last item. - p.lastopenbracketpos = None - with self.subTest(string=test.string): - setstr(test.string) - eq(openbracket(), test.position) - def test_get_last_stmt_bracketing(self): eq = self.assertEqual p = self.parser diff --git a/Lib/idlelib/pyparse.py b/Lib/idlelib/pyparse.py index 72bd9e00c1e9..93607dc5bcd0 100644 --- a/Lib/idlelib/pyparse.py +++ b/Lib/idlelib/pyparse.py @@ -18,10 +18,6 @@ (C_NONE, C_BACKSLASH, C_STRING_FIRST_LINE, C_STRING_NEXT_LINES, C_BRACKET) = range(5) -if 0: # for throwaway debugging output - def dump(*stuff): - sys.__stdout__.write(" ".join(map(str, stuff)) + "\n") - # Find what looks like the start of a popular statement. _synchre = re.compile(r""" @@ -496,8 +492,7 @@ def _study2(self): # end while p < q: self.lastch = lastch - if stack: - self.lastopenbracketpos = stack[-1] + self.lastopenbracketpos = stack[-1] if stack else None self.stmt_bracketing = tuple(bracketing) def compute_bracket_indent(self): @@ -620,22 +615,10 @@ def is_block_closer(self): self._study2() return _closere(self.str, self.stmt_start) is not None - # XXX - is this used? - lastopenbracketpos = None - - def get_last_open_bracket_pos(self): - "Return index of last open bracket or None." - self._study2() - return self.lastopenbracketpos - - # XXX - is this used? - stmt_bracketing = None - def get_last_stmt_bracketing(self): - """Return a tuple of the structure of the bracketing of the last - interesting statement. + """Return bracketing structure of the last interesting statement. - Tuple is in the format defined in _study2(). + The returned tuple is in the format defined in _study2(). """ self._study2() return self.stmt_bracketing diff --git a/Misc/NEWS.d/next/IDLE/2018-02-22-00-09-27.bpo-32905.VlXj0x.rst b/Misc/NEWS.d/next/IDLE/2018-02-22-00-09-27.bpo-32905.VlXj0x.rst new file mode 100644 index 000000000000..c9bedd98f2e0 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2018-02-22-00-09-27.bpo-32905.VlXj0x.rst @@ -0,0 +1 @@ +Remove unused code in pyparse module. From webhook-mailer at python.org Thu Feb 22 01:41:43 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 22 Feb 2018 06:41:43 -0000 Subject: [Python-checkins] bpo-32905: IDLE - remove unused code in pyparse module (GH-5807) Message-ID: https://github.com/python/cpython/commit/dfa1144582e19e5fee2c07e6b7e281da1bef7782 commit: dfa1144582e19e5fee2c07e6b7e281da1bef7782 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-21T22:41:41-08:00 summary: bpo-32905: IDLE - remove unused code in pyparse module (GH-5807) dump is similar to print but less flexible. lastopenbracketpos is now always initialized in _study2, as was stmt_bracketing, so the class settings are not needed. get_last_open_bracket_pos is never called. (cherry picked from commit 451d1edaf4d27c4e632d81246d308e8dd6ea945f) Co-authored-by: Terry Jan Reedy files: A Misc/NEWS.d/next/IDLE/2018-02-22-00-09-27.bpo-32905.VlXj0x.rst M Lib/idlelib/idle_test/test_pyparse.py M Lib/idlelib/pyparse.py diff --git a/Lib/idlelib/idle_test/test_pyparse.py b/Lib/idlelib/idle_test/test_pyparse.py index b84e9f843081..c45815b36ff2 100644 --- a/Lib/idlelib/idle_test/test_pyparse.py +++ b/Lib/idlelib/idle_test/test_pyparse.py @@ -1,4 +1,7 @@ -"""Unittest for idlelib.pyparse.py.""" +"""Unittest for idlelib.pyparse.py. + +Coverage: 97% +""" from collections import namedtuple import unittest @@ -272,8 +275,6 @@ def test_study2(self): ) for test in tests: - # There is a bug where this is carried forward from last item. - p.lastopenbracketpos = None with self.subTest(string=test.string): setstr(test.string) study() @@ -464,33 +465,6 @@ def test_is_block_closer(self): setstr(test.string) test.assert_(closer()) - def test_get_last_open_bracket_pos(self): - eq = self.assertEqual - p = self.parser - setstr = p.set_str - openbracket = p.get_last_open_bracket_pos - - TestInfo = namedtuple('TestInfo', ['string', 'position']) - tests = ( - TestInfo('', None), - TestInfo('a\n', None), - TestInfo('# (\n', None), - TestInfo('""" (\n', None), - TestInfo('a = (1 + 2) - 5 *\\\n', None), - TestInfo('\n def function1(self, a,\n', 17), - TestInfo('\n def function1(self, a, # End of line comment.\n', 17), - TestInfo('{)(]\n', None), - TestInfo('(((((((((()))))))\n', 2), - TestInfo('(((((((((())\n)))\n))\n', 2), - ) - - for test in tests: - # There is a bug where the value is carried forward from last item. - p.lastopenbracketpos = None - with self.subTest(string=test.string): - setstr(test.string) - eq(openbracket(), test.position) - def test_get_last_stmt_bracketing(self): eq = self.assertEqual p = self.parser diff --git a/Lib/idlelib/pyparse.py b/Lib/idlelib/pyparse.py index 72bd9e00c1e9..93607dc5bcd0 100644 --- a/Lib/idlelib/pyparse.py +++ b/Lib/idlelib/pyparse.py @@ -18,10 +18,6 @@ (C_NONE, C_BACKSLASH, C_STRING_FIRST_LINE, C_STRING_NEXT_LINES, C_BRACKET) = range(5) -if 0: # for throwaway debugging output - def dump(*stuff): - sys.__stdout__.write(" ".join(map(str, stuff)) + "\n") - # Find what looks like the start of a popular statement. _synchre = re.compile(r""" @@ -496,8 +492,7 @@ def _study2(self): # end while p < q: self.lastch = lastch - if stack: - self.lastopenbracketpos = stack[-1] + self.lastopenbracketpos = stack[-1] if stack else None self.stmt_bracketing = tuple(bracketing) def compute_bracket_indent(self): @@ -620,22 +615,10 @@ def is_block_closer(self): self._study2() return _closere(self.str, self.stmt_start) is not None - # XXX - is this used? - lastopenbracketpos = None - - def get_last_open_bracket_pos(self): - "Return index of last open bracket or None." - self._study2() - return self.lastopenbracketpos - - # XXX - is this used? - stmt_bracketing = None - def get_last_stmt_bracketing(self): - """Return a tuple of the structure of the bracketing of the last - interesting statement. + """Return bracketing structure of the last interesting statement. - Tuple is in the format defined in _study2(). + The returned tuple is in the format defined in _study2(). """ self._study2() return self.stmt_bracketing diff --git a/Misc/NEWS.d/next/IDLE/2018-02-22-00-09-27.bpo-32905.VlXj0x.rst b/Misc/NEWS.d/next/IDLE/2018-02-22-00-09-27.bpo-32905.VlXj0x.rst new file mode 100644 index 000000000000..c9bedd98f2e0 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2018-02-22-00-09-27.bpo-32905.VlXj0x.rst @@ -0,0 +1 @@ +Remove unused code in pyparse module. From webhook-mailer at python.org Thu Feb 22 02:04:08 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 22 Feb 2018 07:04:08 -0000 Subject: [Python-checkins] bpo-32905: IDLE - remove unused code in pyparse module (GH-5807) Message-ID: https://github.com/python/cpython/commit/d8e7b98b17cd2cc15b307f54a768c9ca31072b5f commit: d8e7b98b17cd2cc15b307f54a768c9ca31072b5f branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-21T23:04:05-08:00 summary: bpo-32905: IDLE - remove unused code in pyparse module (GH-5807) dump is similar to print but less flexible. lastopenbracketpos is now always initialized in _study2, as was stmt_bracketing, so the class settings are not needed. get_last_open_bracket_pos is never called. (cherry picked from commit 451d1edaf4d27c4e632d81246d308e8dd6ea945f) Co-authored-by: Terry Jan Reedy files: A Misc/NEWS.d/next/IDLE/2018-02-22-00-09-27.bpo-32905.VlXj0x.rst M Lib/idlelib/idle_test/test_pyparse.py M Lib/idlelib/pyparse.py diff --git a/Lib/idlelib/idle_test/test_pyparse.py b/Lib/idlelib/idle_test/test_pyparse.py index b84e9f843081..c45815b36ff2 100644 --- a/Lib/idlelib/idle_test/test_pyparse.py +++ b/Lib/idlelib/idle_test/test_pyparse.py @@ -1,4 +1,7 @@ -"""Unittest for idlelib.pyparse.py.""" +"""Unittest for idlelib.pyparse.py. + +Coverage: 97% +""" from collections import namedtuple import unittest @@ -272,8 +275,6 @@ def test_study2(self): ) for test in tests: - # There is a bug where this is carried forward from last item. - p.lastopenbracketpos = None with self.subTest(string=test.string): setstr(test.string) study() @@ -464,33 +465,6 @@ def test_is_block_closer(self): setstr(test.string) test.assert_(closer()) - def test_get_last_open_bracket_pos(self): - eq = self.assertEqual - p = self.parser - setstr = p.set_str - openbracket = p.get_last_open_bracket_pos - - TestInfo = namedtuple('TestInfo', ['string', 'position']) - tests = ( - TestInfo('', None), - TestInfo('a\n', None), - TestInfo('# (\n', None), - TestInfo('""" (\n', None), - TestInfo('a = (1 + 2) - 5 *\\\n', None), - TestInfo('\n def function1(self, a,\n', 17), - TestInfo('\n def function1(self, a, # End of line comment.\n', 17), - TestInfo('{)(]\n', None), - TestInfo('(((((((((()))))))\n', 2), - TestInfo('(((((((((())\n)))\n))\n', 2), - ) - - for test in tests: - # There is a bug where the value is carried forward from last item. - p.lastopenbracketpos = None - with self.subTest(string=test.string): - setstr(test.string) - eq(openbracket(), test.position) - def test_get_last_stmt_bracketing(self): eq = self.assertEqual p = self.parser diff --git a/Lib/idlelib/pyparse.py b/Lib/idlelib/pyparse.py index 72bd9e00c1e9..93607dc5bcd0 100644 --- a/Lib/idlelib/pyparse.py +++ b/Lib/idlelib/pyparse.py @@ -18,10 +18,6 @@ (C_NONE, C_BACKSLASH, C_STRING_FIRST_LINE, C_STRING_NEXT_LINES, C_BRACKET) = range(5) -if 0: # for throwaway debugging output - def dump(*stuff): - sys.__stdout__.write(" ".join(map(str, stuff)) + "\n") - # Find what looks like the start of a popular statement. _synchre = re.compile(r""" @@ -496,8 +492,7 @@ def _study2(self): # end while p < q: self.lastch = lastch - if stack: - self.lastopenbracketpos = stack[-1] + self.lastopenbracketpos = stack[-1] if stack else None self.stmt_bracketing = tuple(bracketing) def compute_bracket_indent(self): @@ -620,22 +615,10 @@ def is_block_closer(self): self._study2() return _closere(self.str, self.stmt_start) is not None - # XXX - is this used? - lastopenbracketpos = None - - def get_last_open_bracket_pos(self): - "Return index of last open bracket or None." - self._study2() - return self.lastopenbracketpos - - # XXX - is this used? - stmt_bracketing = None - def get_last_stmt_bracketing(self): - """Return a tuple of the structure of the bracketing of the last - interesting statement. + """Return bracketing structure of the last interesting statement. - Tuple is in the format defined in _study2(). + The returned tuple is in the format defined in _study2(). """ self._study2() return self.stmt_bracketing diff --git a/Misc/NEWS.d/next/IDLE/2018-02-22-00-09-27.bpo-32905.VlXj0x.rst b/Misc/NEWS.d/next/IDLE/2018-02-22-00-09-27.bpo-32905.VlXj0x.rst new file mode 100644 index 000000000000..c9bedd98f2e0 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2018-02-22-00-09-27.bpo-32905.VlXj0x.rst @@ -0,0 +1 @@ +Remove unused code in pyparse module. From solipsis at pitrou.net Thu Feb 22 04:09:34 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 22 Feb 2018 09:09:34 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=3 Message-ID: <20180222090934.1.2FB5FAD128851E81@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 [1, 0, -2] memory blocks, sum=-1 test_multiprocessing_spawn leaked [0, 1, -2] memory blocks, sum=-1 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogQ5uxop', '--timeout', '7200'] From webhook-mailer at python.org Thu Feb 22 12:37:43 2018 From: webhook-mailer at python.org (Mariatta) Date: Thu, 22 Feb 2018 17:37:43 -0000 Subject: [Python-checkins] bpo-30449: Improve __slots__ documentation (GH-1819) Message-ID: https://github.com/python/cpython/commit/6eab93cfe5ee08a6168e5bb69474e461cc7ac535 commit: 6eab93cfe5ee08a6168e5bb69474e461cc7ac535 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Mariatta date: 2018-02-22T09:37:40-08:00 summary: bpo-30449: Improve __slots__ documentation (GH-1819) (cherry picked from commit 2b44e302ec3079363c4d5c875677945953705c58) Co-authored-by: Aaron Hall, MBA files: M Doc/reference/datamodel.rst diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 773eeb233540..c95f4a970930 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1653,15 +1653,11 @@ instances cannot override the behavior of a property. __slots__ ^^^^^^^^^ -By default, instances of classes have a dictionary for attribute storage. This -wastes space for objects having very few instance variables. The space -consumption can become acute when creating large numbers of instances. - -The default can be overridden by defining *__slots__* in a class definition. -The *__slots__* declaration takes a sequence of instance variables and reserves -just enough space in each instance to hold a value for each variable. Space is -saved because *__dict__* is not created for each instance. +*__slots__* allow us to explicitly declare data members (like +properties) and deny the creation of *__dict__* and *__weakref__* +(unless explicitly declared in *__slots__* or available in a parent.) +The space saved over using *__dict__* can be significant. .. data:: object.__slots__ @@ -1674,9 +1670,8 @@ saved because *__dict__* is not created for each instance. Notes on using *__slots__* """""""""""""""""""""""""" -* When inheriting from a class without *__slots__*, the *__dict__* attribute of - that class will always be accessible, so a *__slots__* definition in the - subclass is meaningless. +* When inheriting from a class without *__slots__*, the *__dict__* and + *__weakref__* attribute of the instances will always be accessible. * Without a *__dict__* variable, instances cannot be assigned new variables not listed in the *__slots__* definition. Attempts to assign to an unlisted @@ -1695,9 +1690,11 @@ Notes on using *__slots__* *__slots__*; otherwise, the class attribute would overwrite the descriptor assignment. -* The action of a *__slots__* declaration is limited to the class where it is - defined. As a result, subclasses will have a *__dict__* unless they also define - *__slots__* (which must only contain names of any *additional* slots). +* The action of a *__slots__* declaration is not limited to the class + where it is defined. *__slots__* declared in parents are available in + child classes. However, child subclasses will get a *__dict__* and + *__weakref__* unless they also define *__slots__* (which should only + contain names of any *additional* slots). * If a class defines a slot also defined in a base class, the instance variable defined by the base class slot is inaccessible (except by retrieving its @@ -1713,6 +1710,10 @@ Notes on using *__slots__* * *__class__* assignment works only if both classes have the same *__slots__*. +* Multiple inheritance with multiple slotted parent classes can be used, + but only one parent is allowed to have attributes created by slots + (the other bases must have empty slot layouts) - violations raise + :exc:`TypeError`. .. _class-customization: From webhook-mailer at python.org Thu Feb 22 13:39:20 2018 From: webhook-mailer at python.org (Steve Dower) Date: Thu, 22 Feb 2018 18:39:20 -0000 Subject: [Python-checkins] bpo-32556: nt._getfinalpathname, nt._getvolumepathname and nt._getdiskusage now correctly convert from bytes. (GH-5761) Message-ID: https://github.com/python/cpython/commit/23ad6d0d1a7a6145a01494f4f3913a63d1f0250c commit: 23ad6d0d1a7a6145a01494f4f3913a63d1f0250c branch: master author: Steve Dower committer: GitHub date: 2018-02-22T10:39:10-08:00 summary: bpo-32556: nt._getfinalpathname, nt._getvolumepathname and nt._getdiskusage now correctly convert from bytes. (GH-5761) files: A Misc/NEWS.d/next/Library/2018-02-19-14-27-51.bpo-32556.CsRsgr.rst M Lib/test/test_ntpath.py M Modules/clinic/posixmodule.c.h M Modules/posixmodule.c diff --git a/Lib/test/test_ntpath.py b/Lib/test/test_ntpath.py index 15215e497d3f..1eec26b20013 100644 --- a/Lib/test/test_ntpath.py +++ b/Lib/test/test_ntpath.py @@ -7,6 +7,12 @@ from test import support, test_genericpath from tempfile import TemporaryFile +try: + import nt +except ImportError: + # Most tests can complete without the nt module, + # but for those that require it we import here. + nt = None def tester(fn, wantResult): fn = fn.replace("\\", "\\\\") @@ -271,17 +277,9 @@ def test_expanduser(self): tester('ntpath.expanduser("~/foo/bar")', 'C:\\idle\\eric/foo/bar') + @unittest.skipUnless(nt, "abspath requires 'nt' module") def test_abspath(self): - # ntpath.abspath() can only be used on a system with the "nt" module - # (reasonably), so we protect this test with "import nt". This allows - # the rest of the tests for the ntpath module to be run to completion - # on any platform, since most of the module is intended to be usable - # from any platform. - try: - import nt - tester('ntpath.abspath("C:\\")', "C:\\") - except ImportError: - self.skipTest('nt module not available') + tester('ntpath.abspath("C:\\")', "C:\\") def test_relpath(self): tester('ntpath.relpath("a")', 'a') @@ -424,6 +422,34 @@ def test_ismount(self): self.assertTrue(ntpath.ismount(b"\\\\localhost\\c$")) self.assertTrue(ntpath.ismount(b"\\\\localhost\\c$\\")) + @unittest.skipUnless(nt, "OS helpers require 'nt' module") + def test_nt_helpers(self): + # Trivial validation that the helpers do not break, and support both + # unicode and bytes (UTF-8) paths + + drive, path = ntpath.splitdrive(sys.executable) + drive = drive.rstrip(ntpath.sep) + ntpath.sep + self.assertEqual(drive, nt._getvolumepathname(sys.executable)) + self.assertEqual(drive.encode(), + nt._getvolumepathname(sys.executable.encode())) + + cap, free = nt._getdiskusage(sys.exec_prefix) + self.assertGreater(cap, 0) + self.assertGreater(free, 0) + b_cap, b_free = nt._getdiskusage(sys.exec_prefix.encode()) + # Free space may change, so only test the capacity is equal + self.assertEqual(b_cap, cap) + self.assertGreater(b_free, 0) + + for path in [sys.prefix, sys.executable]: + final_path = nt._getfinalpathname(path) + self.assertIsInstance(final_path, str) + self.assertGreater(len(final_path), 0) + + b_final_path = nt._getfinalpathname(path.encode()) + self.assertIsInstance(b_final_path, bytes) + self.assertGreater(len(b_final_path), 0) + class NtCommonTest(test_genericpath.CommonTest, unittest.TestCase): pathmodule = ntpath attributes = ['relpath'] diff --git a/Misc/NEWS.d/next/Library/2018-02-19-14-27-51.bpo-32556.CsRsgr.rst b/Misc/NEWS.d/next/Library/2018-02-19-14-27-51.bpo-32556.CsRsgr.rst new file mode 100644 index 000000000000..1a475b308f5e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-19-14-27-51.bpo-32556.CsRsgr.rst @@ -0,0 +1,2 @@ +nt._getfinalpathname, nt._getvolumepathname and nt._getdiskusage now +correctly convert from bytes. diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h index d6af15ffc2ca..4054389d15f3 100644 --- a/Modules/clinic/posixmodule.c.h +++ b/Modules/clinic/posixmodule.c.h @@ -972,20 +972,23 @@ PyDoc_STRVAR(os__getfinalpathname__doc__, {"_getfinalpathname", (PyCFunction)os__getfinalpathname, METH_O, os__getfinalpathname__doc__}, static PyObject * -os__getfinalpathname_impl(PyObject *module, PyObject *path); +os__getfinalpathname_impl(PyObject *module, path_t *path); static PyObject * os__getfinalpathname(PyObject *module, PyObject *arg) { PyObject *return_value = NULL; - PyObject *path; + path_t path = PATH_T_INITIALIZE("_getfinalpathname", "path", 0, 0); - if (!PyArg_Parse(arg, "U:_getfinalpathname", &path)) { + if (!PyArg_Parse(arg, "O&:_getfinalpathname", path_converter, &path)) { goto exit; } - return_value = os__getfinalpathname_impl(module, path); + return_value = os__getfinalpathname_impl(module, &path); exit: + /* Cleanup for path */ + path_cleanup(&path); + return return_value; } @@ -1037,23 +1040,26 @@ PyDoc_STRVAR(os__getvolumepathname__doc__, {"_getvolumepathname", (PyCFunction)os__getvolumepathname, METH_FASTCALL|METH_KEYWORDS, os__getvolumepathname__doc__}, static PyObject * -os__getvolumepathname_impl(PyObject *module, PyObject *path); +os__getvolumepathname_impl(PyObject *module, path_t *path); static PyObject * os__getvolumepathname(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", NULL}; - static _PyArg_Parser _parser = {"U:_getvolumepathname", _keywords, 0}; - PyObject *path; + static _PyArg_Parser _parser = {"O&:_getvolumepathname", _keywords, 0}; + path_t path = PATH_T_INITIALIZE("_getvolumepathname", "path", 0, 0); if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, - &path)) { + path_converter, &path)) { goto exit; } - return_value = os__getvolumepathname_impl(module, path); + return_value = os__getvolumepathname_impl(module, &path); exit: + /* Cleanup for path */ + path_cleanup(&path); + return return_value; } @@ -5014,23 +5020,26 @@ PyDoc_STRVAR(os__getdiskusage__doc__, {"_getdiskusage", (PyCFunction)os__getdiskusage, METH_FASTCALL|METH_KEYWORDS, os__getdiskusage__doc__}, static PyObject * -os__getdiskusage_impl(PyObject *module, Py_UNICODE *path); +os__getdiskusage_impl(PyObject *module, path_t *path); static PyObject * os__getdiskusage(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", NULL}; - static _PyArg_Parser _parser = {"u:_getdiskusage", _keywords, 0}; - Py_UNICODE *path; + static _PyArg_Parser _parser = {"O&:_getdiskusage", _keywords, 0}; + path_t path = PATH_T_INITIALIZE("_getdiskusage", "path", 0, 0); if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, - &path)) { + path_converter, &path)) { goto exit; } - return_value = os__getdiskusage_impl(module, path); + return_value = os__getdiskusage_impl(module, &path); exit: + /* Cleanup for path */ + path_cleanup(&path); + return return_value; } @@ -6580,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=8e5d4a01257b6292 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=fc603214822bdda6 input=a9049054013a1b77]*/ diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 0bbf7c57961f..4b592298834d 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -3720,29 +3720,26 @@ os__getfullpathname_impl(PyObject *module, path_t *path) /*[clinic input] os._getfinalpathname - path: unicode + path: path_t / A helper function for samepath on windows. [clinic start generated code]*/ static PyObject * -os__getfinalpathname_impl(PyObject *module, PyObject *path) -/*[clinic end generated code: output=9bd78d0e52782e75 input=71d5e89334891bf4]*/ +os__getfinalpathname_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/ { HANDLE hFile; int buf_size; wchar_t *target_path; int result_length; PyObject *result; - const wchar_t *path_wchar; - - path_wchar = _PyUnicode_AsUnicode(path); - if (path_wchar == NULL) - return NULL; + const char *err = NULL; + Py_BEGIN_ALLOW_THREADS hFile = CreateFileW( - path_wchar, + path->wide, 0, /* desired access */ 0, /* share mode */ NULL, /* security attributes */ @@ -3751,32 +3748,54 @@ os__getfinalpathname_impl(PyObject *module, PyObject *path) FILE_FLAG_BACKUP_SEMANTICS, NULL); - if(hFile == INVALID_HANDLE_VALUE) - return win32_error_object("CreateFileW", path); + if (hFile == INVALID_HANDLE_VALUE) { + err = "CreateFileW"; + goto done1; + } /* We have a good handle to the target, use it to determine the target path name. */ buf_size = GetFinalPathNameByHandleW(hFile, 0, 0, VOLUME_NAME_NT); - if(!buf_size) - return win32_error_object("GetFinalPathNameByHandle", path); + if (!buf_size) { + err = "GetFinalPathNameByHandle"; + goto done1; + } +done1: + Py_END_ALLOW_THREADS + if (err) + return win32_error_object(err, path->object); target_path = PyMem_New(wchar_t, buf_size+1); if(!target_path) return PyErr_NoMemory(); + Py_BEGIN_ALLOW_THREADS result_length = GetFinalPathNameByHandleW(hFile, target_path, buf_size, VOLUME_NAME_DOS); - if(!result_length) - return win32_error_object("GetFinalPathNamyByHandle", path); + if (!result_length) { + err = "GetFinalPathNameByHandle"; + goto done2; + } - if(!CloseHandle(hFile)) - return win32_error_object("CloseHandle", path); + if (!CloseHandle(hFile)) { + err = "CloseHandle"; + goto done2; + } +done2: + Py_END_ALLOW_THREADS + if (err) { + PyMem_Free(target_path); + return win32_error_object(err, path->object); + } target_path[result_length] = 0; result = PyUnicode_FromWideChar(target_path, result_length); PyMem_Free(target_path); + if (path->narrow) + Py_SETREF(result, PyUnicode_EncodeFSDefault(result)); return result; + } /*[clinic input] @@ -3811,28 +3830,22 @@ os__isdir_impl(PyObject *module, path_t *path) /*[clinic input] os._getvolumepathname - path: unicode + path: path_t A helper function for ismount on Win32. [clinic start generated code]*/ static PyObject * -os__getvolumepathname_impl(PyObject *module, PyObject *path) -/*[clinic end generated code: output=cbdcbd1059ceef4c input=7eacadc40acbda6b]*/ +os__getvolumepathname_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/ { PyObject *result; - const wchar_t *path_wchar; wchar_t *mountpath=NULL; size_t buflen; BOOL ret; - path_wchar = PyUnicode_AsUnicodeAndSize(path, &buflen); - if (path_wchar == NULL) - return NULL; - buflen += 1; - /* Volume path should be shorter than entire path */ - buflen = Py_MAX(buflen, MAX_PATH); + buflen = Py_MAX(path->length, MAX_PATH); if (buflen > PY_DWORD_MAX) { PyErr_SetString(PyExc_OverflowError, "path too long"); @@ -3844,15 +3857,17 @@ os__getvolumepathname_impl(PyObject *module, PyObject *path) return PyErr_NoMemory(); Py_BEGIN_ALLOW_THREADS - ret = GetVolumePathNameW(path_wchar, mountpath, + ret = GetVolumePathNameW(path->wide, mountpath, Py_SAFE_DOWNCAST(buflen, size_t, DWORD)); Py_END_ALLOW_THREADS if (!ret) { - result = win32_error_object("_getvolumepathname", path); + result = win32_error_object("_getvolumepathname", path->object); goto exit; } result = PyUnicode_FromWideChar(mountpath, wcslen(mountpath)); + if (path->narrow) + Py_SETREF(result, PyUnicode_EncodeFSDefault(result)); exit: PyMem_Free(mountpath); @@ -9844,20 +9859,20 @@ os_statvfs_impl(PyObject *module, path_t *path) /*[clinic input] os._getdiskusage - path: Py_UNICODE + path: path_t Return disk usage statistics about the given path as a (total, free) tuple. [clinic start generated code]*/ static PyObject * -os__getdiskusage_impl(PyObject *module, Py_UNICODE *path) -/*[clinic end generated code: output=76d6adcd86b1db0b input=6458133aed893c78]*/ +os__getdiskusage_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/ { BOOL retval; ULARGE_INTEGER _, total, free; Py_BEGIN_ALLOW_THREADS - retval = GetDiskFreeSpaceExW(path, &_, &total, &free); + retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free); Py_END_ALLOW_THREADS if (retval == 0) return PyErr_SetFromWindowsErr(0); From webhook-mailer at python.org Thu Feb 22 13:39:30 2018 From: webhook-mailer at python.org (Steve Dower) Date: Thu, 22 Feb 2018 18:39:30 -0000 Subject: [Python-checkins] bpo-32457: Improves handling of denormalized executable path when launching Python (GH-5756) Message-ID: https://github.com/python/cpython/commit/48e8c82fc63d2ddcddce8aa637a892839b551619 commit: 48e8c82fc63d2ddcddce8aa637a892839b551619 branch: master author: Steve Dower committer: GitHub date: 2018-02-22T10:39:26-08:00 summary: bpo-32457: Improves handling of denormalized executable path when launching Python (GH-5756) files: A Misc/NEWS.d/next/Windows/2018-02-19-08-54-06.bpo-32457.vVP0Iz.rst M Lib/test/test_cmd_line.py M PC/getpathp.c diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py index fe89e3c0ee34..d8a96c49ce96 100644 --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -701,6 +701,17 @@ def test_pythondevmode_env(self): self.assertEqual(proc.stdout.rstrip(), 'True') self.assertEqual(proc.returncode, 0, proc) + @unittest.skipUnless(sys.platform == 'win32', + 'bpo-32457 only applies on Windows') + def test_argv0_normalization(self): + args = sys.executable, '-c', 'print(0)' + prefix, exe = os.path.split(sys.executable) + executable = prefix + '\\.\\.\\.\\' + exe + + proc = subprocess.run(args, stdout=subprocess.PIPE, + executable=executable) + self.assertEqual(proc.returncode, 0, proc) + self.assertEqual(proc.stdout.strip(), b'0') @unittest.skipIf(interpreter_requires_environment(), 'Cannot run -I tests when PYTHON env vars are required.') diff --git a/Misc/NEWS.d/next/Windows/2018-02-19-08-54-06.bpo-32457.vVP0Iz.rst b/Misc/NEWS.d/next/Windows/2018-02-19-08-54-06.bpo-32457.vVP0Iz.rst new file mode 100644 index 000000000000..b55ec821e622 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2018-02-19-08-54-06.bpo-32457.vVP0Iz.rst @@ -0,0 +1 @@ +Improves handling of denormalized executable path when launching Python. diff --git a/PC/getpathp.c b/PC/getpathp.c index e90a643ab82a..93828432ae3c 100644 --- a/PC/getpathp.c +++ b/PC/getpathp.c @@ -266,6 +266,41 @@ join(wchar_t *buffer, const wchar_t *stuff) } } +static int _PathCchCanonicalizeEx_Initialized = 0; +typedef HRESULT(__stdcall *PPathCchCanonicalizeEx) (PWSTR pszPathOut, size_t cchPathOut, + PCWSTR pszPathIn, unsigned long dwFlags); +static PPathCchCanonicalizeEx _PathCchCanonicalizeEx; + +static _PyInitError canonicalize(wchar_t *buffer, const wchar_t *path) +{ + if (buffer == NULL) { + return _Py_INIT_NO_MEMORY(); + } + + if (_PathCchCanonicalizeEx_Initialized == 0) { + HMODULE pathapi = LoadLibraryW(L"api-ms-win-core-path-l1-1-0.dll"); + if (pathapi) { + _PathCchCanonicalizeEx = (PPathCchCanonicalizeEx)GetProcAddress(pathapi, "PathCchCanonicalizeEx"); + } + else { + _PathCchCanonicalizeEx = NULL; + } + _PathCchCanonicalizeEx_Initialized = 1; + } + + if (_PathCchCanonicalizeEx) { + if (FAILED(_PathCchCanonicalizeEx(buffer, MAXPATHLEN + 1, path, 0))) { + return _Py_INIT_ERR("buffer overflow in getpathp.c's canonicalize()"); + } + } + else { + if (!PathCanonicalizeW(buffer, path)) { + return _Py_INIT_ERR("buffer overflow in getpathp.c's canonicalize()"); + } + } + return _Py_INIT_OK(); +} + /* gotlandmark only called by search_for_prefix, which ensures 'prefix' is null terminated in bounds. join() ensures @@ -504,63 +539,16 @@ get_program_full_path(const _PyCoreConfig *core_config, wchar_t program_full_path[MAXPATHLEN+1]; memset(program_full_path, 0, sizeof(program_full_path)); - if (GetModuleFileNameW(NULL, program_full_path, MAXPATHLEN)) { - goto done; - } - - /* If there is no slash in the argv0 path, then we have to - * assume python is on the user's $PATH, since there's no - * other way to find a directory to start the search from. If - * $PATH isn't exported, you lose. - */ -#ifdef ALTSEP - if (wcschr(core_config->program_name, SEP) || - wcschr(core_config->program_name, ALTSEP)) -#else - if (wcschr(core_config->program_name, SEP)) -#endif - { - wcsncpy(program_full_path, core_config->program_name, MAXPATHLEN); + if (!GetModuleFileNameW(NULL, program_full_path, MAXPATHLEN)) { + /* GetModuleFileName should never fail when passed NULL */ + return _Py_INIT_ERR("Cannot determine program path"); } - else if (calculate->path_env) { - const wchar_t *path = calculate->path_env; - while (1) { - const wchar_t *delim = wcschr(path, DELIM); - - if (delim) { - size_t len = delim - path; - /* ensure we can't overwrite buffer */ - len = min(MAXPATHLEN,len); - wcsncpy(program_full_path, path, len); - program_full_path[len] = '\0'; - } - else { - wcsncpy(program_full_path, path, MAXPATHLEN); - } - - /* join() is safe for MAXPATHLEN+1 size buffer */ - join(program_full_path, core_config->program_name); - if (exists(program_full_path)) { - break; - } - if (!delim) { - program_full_path[0] = '\0'; - break; - } - path = delim + 1; - } - } - else { - program_full_path[0] = '\0'; - } + config->program_full_path = PyMem_RawMalloc( + sizeof(wchar_t) * (MAXPATHLEN + 1)); -done: - config->program_full_path = _PyMem_RawWcsdup(program_full_path); - if (config->program_full_path == NULL) { - return _Py_INIT_NO_MEMORY(); - } - return _Py_INIT_OK(); + return canonicalize(config->program_full_path, + program_full_path); } From webhook-mailer at python.org Thu Feb 22 14:02:15 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 22 Feb 2018 19:02:15 -0000 Subject: [Python-checkins] bpo-32556: nt._getfinalpathname, nt._getvolumepathname and nt._getdiskusage now correctly convert from bytes. (GH-5761) Message-ID: https://github.com/python/cpython/commit/01dd52fb29566893dde59dea7bca582625c04762 commit: 01dd52fb29566893dde59dea7bca582625c04762 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-22T11:02:12-08:00 summary: bpo-32556: nt._getfinalpathname, nt._getvolumepathname and nt._getdiskusage now correctly convert from bytes. (GH-5761) (cherry picked from commit 23ad6d0d1a7a6145a01494f4f3913a63d1f0250c) Co-authored-by: Steve Dower files: A Misc/NEWS.d/next/Library/2018-02-19-14-27-51.bpo-32556.CsRsgr.rst M Lib/test/test_ntpath.py M Modules/clinic/posixmodule.c.h M Modules/posixmodule.c diff --git a/Lib/test/test_ntpath.py b/Lib/test/test_ntpath.py index 15215e497d3f..1eec26b20013 100644 --- a/Lib/test/test_ntpath.py +++ b/Lib/test/test_ntpath.py @@ -7,6 +7,12 @@ from test import support, test_genericpath from tempfile import TemporaryFile +try: + import nt +except ImportError: + # Most tests can complete without the nt module, + # but for those that require it we import here. + nt = None def tester(fn, wantResult): fn = fn.replace("\\", "\\\\") @@ -271,17 +277,9 @@ def test_expanduser(self): tester('ntpath.expanduser("~/foo/bar")', 'C:\\idle\\eric/foo/bar') + @unittest.skipUnless(nt, "abspath requires 'nt' module") def test_abspath(self): - # ntpath.abspath() can only be used on a system with the "nt" module - # (reasonably), so we protect this test with "import nt". This allows - # the rest of the tests for the ntpath module to be run to completion - # on any platform, since most of the module is intended to be usable - # from any platform. - try: - import nt - tester('ntpath.abspath("C:\\")', "C:\\") - except ImportError: - self.skipTest('nt module not available') + tester('ntpath.abspath("C:\\")', "C:\\") def test_relpath(self): tester('ntpath.relpath("a")', 'a') @@ -424,6 +422,34 @@ def test_ismount(self): self.assertTrue(ntpath.ismount(b"\\\\localhost\\c$")) self.assertTrue(ntpath.ismount(b"\\\\localhost\\c$\\")) + @unittest.skipUnless(nt, "OS helpers require 'nt' module") + def test_nt_helpers(self): + # Trivial validation that the helpers do not break, and support both + # unicode and bytes (UTF-8) paths + + drive, path = ntpath.splitdrive(sys.executable) + drive = drive.rstrip(ntpath.sep) + ntpath.sep + self.assertEqual(drive, nt._getvolumepathname(sys.executable)) + self.assertEqual(drive.encode(), + nt._getvolumepathname(sys.executable.encode())) + + cap, free = nt._getdiskusage(sys.exec_prefix) + self.assertGreater(cap, 0) + self.assertGreater(free, 0) + b_cap, b_free = nt._getdiskusage(sys.exec_prefix.encode()) + # Free space may change, so only test the capacity is equal + self.assertEqual(b_cap, cap) + self.assertGreater(b_free, 0) + + for path in [sys.prefix, sys.executable]: + final_path = nt._getfinalpathname(path) + self.assertIsInstance(final_path, str) + self.assertGreater(len(final_path), 0) + + b_final_path = nt._getfinalpathname(path.encode()) + self.assertIsInstance(b_final_path, bytes) + self.assertGreater(len(b_final_path), 0) + class NtCommonTest(test_genericpath.CommonTest, unittest.TestCase): pathmodule = ntpath attributes = ['relpath'] diff --git a/Misc/NEWS.d/next/Library/2018-02-19-14-27-51.bpo-32556.CsRsgr.rst b/Misc/NEWS.d/next/Library/2018-02-19-14-27-51.bpo-32556.CsRsgr.rst new file mode 100644 index 000000000000..1a475b308f5e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-19-14-27-51.bpo-32556.CsRsgr.rst @@ -0,0 +1,2 @@ +nt._getfinalpathname, nt._getvolumepathname and nt._getdiskusage now +correctly convert from bytes. diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h index d6af15ffc2ca..4054389d15f3 100644 --- a/Modules/clinic/posixmodule.c.h +++ b/Modules/clinic/posixmodule.c.h @@ -972,20 +972,23 @@ PyDoc_STRVAR(os__getfinalpathname__doc__, {"_getfinalpathname", (PyCFunction)os__getfinalpathname, METH_O, os__getfinalpathname__doc__}, static PyObject * -os__getfinalpathname_impl(PyObject *module, PyObject *path); +os__getfinalpathname_impl(PyObject *module, path_t *path); static PyObject * os__getfinalpathname(PyObject *module, PyObject *arg) { PyObject *return_value = NULL; - PyObject *path; + path_t path = PATH_T_INITIALIZE("_getfinalpathname", "path", 0, 0); - if (!PyArg_Parse(arg, "U:_getfinalpathname", &path)) { + if (!PyArg_Parse(arg, "O&:_getfinalpathname", path_converter, &path)) { goto exit; } - return_value = os__getfinalpathname_impl(module, path); + return_value = os__getfinalpathname_impl(module, &path); exit: + /* Cleanup for path */ + path_cleanup(&path); + return return_value; } @@ -1037,23 +1040,26 @@ PyDoc_STRVAR(os__getvolumepathname__doc__, {"_getvolumepathname", (PyCFunction)os__getvolumepathname, METH_FASTCALL|METH_KEYWORDS, os__getvolumepathname__doc__}, static PyObject * -os__getvolumepathname_impl(PyObject *module, PyObject *path); +os__getvolumepathname_impl(PyObject *module, path_t *path); static PyObject * os__getvolumepathname(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", NULL}; - static _PyArg_Parser _parser = {"U:_getvolumepathname", _keywords, 0}; - PyObject *path; + static _PyArg_Parser _parser = {"O&:_getvolumepathname", _keywords, 0}; + path_t path = PATH_T_INITIALIZE("_getvolumepathname", "path", 0, 0); if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, - &path)) { + path_converter, &path)) { goto exit; } - return_value = os__getvolumepathname_impl(module, path); + return_value = os__getvolumepathname_impl(module, &path); exit: + /* Cleanup for path */ + path_cleanup(&path); + return return_value; } @@ -5014,23 +5020,26 @@ PyDoc_STRVAR(os__getdiskusage__doc__, {"_getdiskusage", (PyCFunction)os__getdiskusage, METH_FASTCALL|METH_KEYWORDS, os__getdiskusage__doc__}, static PyObject * -os__getdiskusage_impl(PyObject *module, Py_UNICODE *path); +os__getdiskusage_impl(PyObject *module, path_t *path); static PyObject * os__getdiskusage(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"path", NULL}; - static _PyArg_Parser _parser = {"u:_getdiskusage", _keywords, 0}; - Py_UNICODE *path; + static _PyArg_Parser _parser = {"O&:_getdiskusage", _keywords, 0}; + path_t path = PATH_T_INITIALIZE("_getdiskusage", "path", 0, 0); if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, - &path)) { + path_converter, &path)) { goto exit; } - return_value = os__getdiskusage_impl(module, path); + return_value = os__getdiskusage_impl(module, &path); exit: + /* Cleanup for path */ + path_cleanup(&path); + return return_value; } @@ -6580,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=8e5d4a01257b6292 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=fc603214822bdda6 input=a9049054013a1b77]*/ diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index eff74dffceec..130e8c1b36f7 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -3720,29 +3720,26 @@ os__getfullpathname_impl(PyObject *module, path_t *path) /*[clinic input] os._getfinalpathname - path: unicode + path: path_t / A helper function for samepath on windows. [clinic start generated code]*/ static PyObject * -os__getfinalpathname_impl(PyObject *module, PyObject *path) -/*[clinic end generated code: output=9bd78d0e52782e75 input=71d5e89334891bf4]*/ +os__getfinalpathname_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=621a3c79bc29ebfa input=2b6b6c7cbad5fb84]*/ { HANDLE hFile; int buf_size; wchar_t *target_path; int result_length; PyObject *result; - const wchar_t *path_wchar; - - path_wchar = _PyUnicode_AsUnicode(path); - if (path_wchar == NULL) - return NULL; + const char *err = NULL; + Py_BEGIN_ALLOW_THREADS hFile = CreateFileW( - path_wchar, + path->wide, 0, /* desired access */ 0, /* share mode */ NULL, /* security attributes */ @@ -3751,32 +3748,54 @@ os__getfinalpathname_impl(PyObject *module, PyObject *path) FILE_FLAG_BACKUP_SEMANTICS, NULL); - if(hFile == INVALID_HANDLE_VALUE) - return win32_error_object("CreateFileW", path); + if (hFile == INVALID_HANDLE_VALUE) { + err = "CreateFileW"; + goto done1; + } /* We have a good handle to the target, use it to determine the target path name. */ buf_size = GetFinalPathNameByHandleW(hFile, 0, 0, VOLUME_NAME_NT); - if(!buf_size) - return win32_error_object("GetFinalPathNameByHandle", path); + if (!buf_size) { + err = "GetFinalPathNameByHandle"; + goto done1; + } +done1: + Py_END_ALLOW_THREADS + if (err) + return win32_error_object(err, path->object); target_path = PyMem_New(wchar_t, buf_size+1); if(!target_path) return PyErr_NoMemory(); + Py_BEGIN_ALLOW_THREADS result_length = GetFinalPathNameByHandleW(hFile, target_path, buf_size, VOLUME_NAME_DOS); - if(!result_length) - return win32_error_object("GetFinalPathNamyByHandle", path); + if (!result_length) { + err = "GetFinalPathNameByHandle"; + goto done2; + } - if(!CloseHandle(hFile)) - return win32_error_object("CloseHandle", path); + if (!CloseHandle(hFile)) { + err = "CloseHandle"; + goto done2; + } +done2: + Py_END_ALLOW_THREADS + if (err) { + PyMem_Free(target_path); + return win32_error_object(err, path->object); + } target_path[result_length] = 0; result = PyUnicode_FromWideChar(target_path, result_length); PyMem_Free(target_path); + if (path->narrow) + Py_SETREF(result, PyUnicode_EncodeFSDefault(result)); return result; + } /*[clinic input] @@ -3811,28 +3830,22 @@ os__isdir_impl(PyObject *module, path_t *path) /*[clinic input] os._getvolumepathname - path: unicode + path: path_t A helper function for ismount on Win32. [clinic start generated code]*/ static PyObject * -os__getvolumepathname_impl(PyObject *module, PyObject *path) -/*[clinic end generated code: output=cbdcbd1059ceef4c input=7eacadc40acbda6b]*/ +os__getvolumepathname_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=804c63fd13a1330b input=722b40565fa21552]*/ { PyObject *result; - const wchar_t *path_wchar; wchar_t *mountpath=NULL; size_t buflen; BOOL ret; - path_wchar = PyUnicode_AsUnicodeAndSize(path, &buflen); - if (path_wchar == NULL) - return NULL; - buflen += 1; - /* Volume path should be shorter than entire path */ - buflen = Py_MAX(buflen, MAX_PATH); + buflen = Py_MAX(path->length, MAX_PATH); if (buflen > PY_DWORD_MAX) { PyErr_SetString(PyExc_OverflowError, "path too long"); @@ -3844,15 +3857,17 @@ os__getvolumepathname_impl(PyObject *module, PyObject *path) return PyErr_NoMemory(); Py_BEGIN_ALLOW_THREADS - ret = GetVolumePathNameW(path_wchar, mountpath, + ret = GetVolumePathNameW(path->wide, mountpath, Py_SAFE_DOWNCAST(buflen, size_t, DWORD)); Py_END_ALLOW_THREADS if (!ret) { - result = win32_error_object("_getvolumepathname", path); + result = win32_error_object("_getvolumepathname", path->object); goto exit; } result = PyUnicode_FromWideChar(mountpath, wcslen(mountpath)); + if (path->narrow) + Py_SETREF(result, PyUnicode_EncodeFSDefault(result)); exit: PyMem_Free(mountpath); @@ -9844,20 +9859,20 @@ os_statvfs_impl(PyObject *module, path_t *path) /*[clinic input] os._getdiskusage - path: Py_UNICODE + path: path_t Return disk usage statistics about the given path as a (total, free) tuple. [clinic start generated code]*/ static PyObject * -os__getdiskusage_impl(PyObject *module, Py_UNICODE *path) -/*[clinic end generated code: output=76d6adcd86b1db0b input=6458133aed893c78]*/ +os__getdiskusage_impl(PyObject *module, path_t *path) +/*[clinic end generated code: output=3bd3991f5e5c5dfb input=6af8d1b7781cc042]*/ { BOOL retval; ULARGE_INTEGER _, total, free; Py_BEGIN_ALLOW_THREADS - retval = GetDiskFreeSpaceExW(path, &_, &total, &free); + retval = GetDiskFreeSpaceExW(path->wide, &_, &total, &free); Py_END_ALLOW_THREADS if (retval == 0) return PyErr_SetFromWindowsErr(0); From webhook-mailer at python.org Thu Feb 22 14:15:20 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Thu, 22 Feb 2018 19:15:20 -0000 Subject: [Python-checkins] bpo-32457: Improves handling of denormalized executable path when launching Python (GH-5756) Message-ID: https://github.com/python/cpython/commit/e5a9b3574c89a070fbc43caf541759f504e3d492 commit: e5a9b3574c89a070fbc43caf541759f504e3d492 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-22T11:15:16-08:00 summary: bpo-32457: Improves handling of denormalized executable path when launching Python (GH-5756) (cherry picked from commit 48e8c82fc63d2ddcddce8aa637a892839b551619) Co-authored-by: Steve Dower files: A Misc/NEWS.d/next/Windows/2018-02-19-08-54-06.bpo-32457.vVP0Iz.rst M Lib/test/test_cmd_line.py M PC/getpathp.c diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py index fe89e3c0ee34..d8a96c49ce96 100644 --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -701,6 +701,17 @@ def test_pythondevmode_env(self): self.assertEqual(proc.stdout.rstrip(), 'True') self.assertEqual(proc.returncode, 0, proc) + @unittest.skipUnless(sys.platform == 'win32', + 'bpo-32457 only applies on Windows') + def test_argv0_normalization(self): + args = sys.executable, '-c', 'print(0)' + prefix, exe = os.path.split(sys.executable) + executable = prefix + '\\.\\.\\.\\' + exe + + proc = subprocess.run(args, stdout=subprocess.PIPE, + executable=executable) + self.assertEqual(proc.returncode, 0, proc) + self.assertEqual(proc.stdout.strip(), b'0') @unittest.skipIf(interpreter_requires_environment(), 'Cannot run -I tests when PYTHON env vars are required.') diff --git a/Misc/NEWS.d/next/Windows/2018-02-19-08-54-06.bpo-32457.vVP0Iz.rst b/Misc/NEWS.d/next/Windows/2018-02-19-08-54-06.bpo-32457.vVP0Iz.rst new file mode 100644 index 000000000000..b55ec821e622 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2018-02-19-08-54-06.bpo-32457.vVP0Iz.rst @@ -0,0 +1 @@ +Improves handling of denormalized executable path when launching Python. diff --git a/PC/getpathp.c b/PC/getpathp.c index e90a643ab82a..93828432ae3c 100644 --- a/PC/getpathp.c +++ b/PC/getpathp.c @@ -266,6 +266,41 @@ join(wchar_t *buffer, const wchar_t *stuff) } } +static int _PathCchCanonicalizeEx_Initialized = 0; +typedef HRESULT(__stdcall *PPathCchCanonicalizeEx) (PWSTR pszPathOut, size_t cchPathOut, + PCWSTR pszPathIn, unsigned long dwFlags); +static PPathCchCanonicalizeEx _PathCchCanonicalizeEx; + +static _PyInitError canonicalize(wchar_t *buffer, const wchar_t *path) +{ + if (buffer == NULL) { + return _Py_INIT_NO_MEMORY(); + } + + if (_PathCchCanonicalizeEx_Initialized == 0) { + HMODULE pathapi = LoadLibraryW(L"api-ms-win-core-path-l1-1-0.dll"); + if (pathapi) { + _PathCchCanonicalizeEx = (PPathCchCanonicalizeEx)GetProcAddress(pathapi, "PathCchCanonicalizeEx"); + } + else { + _PathCchCanonicalizeEx = NULL; + } + _PathCchCanonicalizeEx_Initialized = 1; + } + + if (_PathCchCanonicalizeEx) { + if (FAILED(_PathCchCanonicalizeEx(buffer, MAXPATHLEN + 1, path, 0))) { + return _Py_INIT_ERR("buffer overflow in getpathp.c's canonicalize()"); + } + } + else { + if (!PathCanonicalizeW(buffer, path)) { + return _Py_INIT_ERR("buffer overflow in getpathp.c's canonicalize()"); + } + } + return _Py_INIT_OK(); +} + /* gotlandmark only called by search_for_prefix, which ensures 'prefix' is null terminated in bounds. join() ensures @@ -504,63 +539,16 @@ get_program_full_path(const _PyCoreConfig *core_config, wchar_t program_full_path[MAXPATHLEN+1]; memset(program_full_path, 0, sizeof(program_full_path)); - if (GetModuleFileNameW(NULL, program_full_path, MAXPATHLEN)) { - goto done; - } - - /* If there is no slash in the argv0 path, then we have to - * assume python is on the user's $PATH, since there's no - * other way to find a directory to start the search from. If - * $PATH isn't exported, you lose. - */ -#ifdef ALTSEP - if (wcschr(core_config->program_name, SEP) || - wcschr(core_config->program_name, ALTSEP)) -#else - if (wcschr(core_config->program_name, SEP)) -#endif - { - wcsncpy(program_full_path, core_config->program_name, MAXPATHLEN); + if (!GetModuleFileNameW(NULL, program_full_path, MAXPATHLEN)) { + /* GetModuleFileName should never fail when passed NULL */ + return _Py_INIT_ERR("Cannot determine program path"); } - else if (calculate->path_env) { - const wchar_t *path = calculate->path_env; - while (1) { - const wchar_t *delim = wcschr(path, DELIM); - - if (delim) { - size_t len = delim - path; - /* ensure we can't overwrite buffer */ - len = min(MAXPATHLEN,len); - wcsncpy(program_full_path, path, len); - program_full_path[len] = '\0'; - } - else { - wcsncpy(program_full_path, path, MAXPATHLEN); - } - - /* join() is safe for MAXPATHLEN+1 size buffer */ - join(program_full_path, core_config->program_name); - if (exists(program_full_path)) { - break; - } - if (!delim) { - program_full_path[0] = '\0'; - break; - } - path = delim + 1; - } - } - else { - program_full_path[0] = '\0'; - } + config->program_full_path = PyMem_RawMalloc( + sizeof(wchar_t) * (MAXPATHLEN + 1)); -done: - config->program_full_path = _PyMem_RawWcsdup(program_full_path); - if (config->program_full_path == NULL) { - return _Py_INIT_NO_MEMORY(); - } - return _Py_INIT_OK(); + return canonicalize(config->program_full_path, + program_full_path); } From webhook-mailer at python.org Thu Feb 22 15:15:41 2018 From: webhook-mailer at python.org (Alexander Belopolsky) Date: Thu, 22 Feb 2018 20:15:41 -0000 Subject: [Python-checkins] Test that new_timezone can return the UTC singleton (gh-5318) Message-ID: https://github.com/python/cpython/commit/a049f5790e38fe1b1ba1d4c10ed5ab35150806fa commit: a049f5790e38fe1b1ba1d4c10ed5ab35150806fa branch: master author: Paul Ganssle committer: Alexander Belopolsky date: 2018-02-22T15:15:32-05:00 summary: Test that new_timezone can return the UTC singleton (gh-5318) files: M Lib/test/datetimetester.py M Modules/_testcapimodule.c diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index 8f9ebddff5a9..436cbea9669e 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -5489,6 +5489,28 @@ def test_timezones_capi(self): self.assertEqual(dt1.astimezone(timezone.utc), dt_utc) + def test_timezones_offset_zero(self): + utc0, utc1, non_utc = _testcapi.get_timezones_offset_zero() + + with self.subTest(testname="utc0"): + self.assertIs(utc0, timezone.utc) + + with self.subTest(testname="utc1"): + self.assertIs(utc1, timezone.utc) + + with self.subTest(testname="non_utc"): + self.assertIsNot(non_utc, timezone.utc) + + non_utc_exp = timezone(timedelta(hours=0), "") + + self.assertEqual(non_utc, non_utc_exp) + + dt1 = datetime(2000, 2, 4, tzinfo=non_utc) + dt2 = datetime(2000, 2, 4, tzinfo=non_utc_exp) + + self.assertEqual(dt1, dt2) + self.assertEqual(dt1.tzname(), dt2.tzname()) + def test_check_date(self): class DateSubclass(date): pass diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 2ad4322ecaa4..afce6c944895 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -2293,6 +2293,29 @@ make_timezones_capi(PyObject *self, PyObject *args) { return rv; } +static PyObject * +get_timezones_offset_zero(PyObject *self, PyObject *args) { + PyObject *offset = PyDelta_FromDSU(0, 0, 0); + PyObject *name = PyUnicode_FromString(""); + + // These two should return the UTC singleton + PyObject *utc_singleton_0 = PyTimeZone_FromOffset(offset); + PyObject *utc_singleton_1 = PyTimeZone_FromOffsetAndName(offset, NULL); + + // This one will return +00:00 zone, but not the UTC singleton + PyObject *non_utc_zone = PyTimeZone_FromOffsetAndName(offset, name); + + Py_DecRef(offset); + Py_DecRef(name); + + PyObject *rv = PyTuple_New(3); + PyTuple_SET_ITEM(rv, 0, utc_singleton_0); + PyTuple_SET_ITEM(rv, 1, utc_singleton_1); + PyTuple_SET_ITEM(rv, 2, non_utc_zone); + + return rv; +} + static PyObject * get_timezone_utc_capi(PyObject* self, PyObject *args) { int macro = 0; @@ -4540,6 +4563,7 @@ static PyMethodDef TestMethods[] = { {"datetime_check_delta", datetime_check_delta, METH_VARARGS}, {"datetime_check_tzinfo", datetime_check_tzinfo, METH_VARARGS}, {"make_timezones_capi", make_timezones_capi, METH_NOARGS}, + {"get_timezones_offset_zero", get_timezones_offset_zero, METH_NOARGS}, {"get_timezone_utc_capi", get_timezone_utc_capi, METH_VARARGS}, {"test_list_api", (PyCFunction)test_list_api, METH_NOARGS}, {"test_dict_iteration", (PyCFunction)test_dict_iteration,METH_NOARGS}, From webhook-mailer at python.org Thu Feb 22 15:26:26 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Thu, 22 Feb 2018 20:26:26 -0000 Subject: [Python-checkins] bpo-32838: Fix Python versions in the table of magic numbers. (#5658) Message-ID: https://github.com/python/cpython/commit/4af8fd561433826ac897c55e41a087a5c5dbacf3 commit: 4af8fd561433826ac897c55e41a087a5c5dbacf3 branch: master author: Serhiy Storchaka committer: GitHub date: 2018-02-22T22:26:23+02:00 summary: bpo-32838: Fix Python versions in the table of magic numbers. (#5658) 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 f9a708c29131..e2951746835e 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -197,52 +197,55 @@ def _write_atomic(path, data, mode=0o666): # 3101 (merge from 2.6a0, see 62151) # 3103 (__file__ points to source file) # Python 3.0a4: 3111 (WITH_CLEANUP optimization). -# Python 3.0a5: 3131 (lexical exception stacking, including POP_EXCEPT) -# Python 3.1a0: 3141 (optimize list, set and dict comprehensions: -# change LIST_APPEND and SET_ADD, add MAP_ADD) -# Python 3.1a0: 3151 (optimize conditional branches: -# introduce POP_JUMP_IF_FALSE and POP_JUMP_IF_TRUE) -# Python 3.2a0: 3160 (add SETUP_WITH) +# Python 3.0b1: 3131 (lexical exception stacking, including POP_EXCEPT + #3021) +# Python 3.1a1: 3141 (optimize list, set and dict comprehensions: +# change LIST_APPEND and SET_ADD, add MAP_ADD #2183) +# Python 3.1a1: 3151 (optimize conditional branches: +# introduce POP_JUMP_IF_FALSE and POP_JUMP_IF_TRUE + #4715) +# Python 3.2a1: 3160 (add SETUP_WITH #6101) # tag: cpython-32 -# Python 3.2a1: 3170 (add DUP_TOP_TWO, remove DUP_TOPX and ROT_FOUR) +# Python 3.2a2: 3170 (add DUP_TOP_TWO, remove DUP_TOPX and ROT_FOUR #9225) # tag: cpython-32 -# Python 3.2a2 3180 (add DELETE_DEREF) -# Python 3.3a0 3190 __class__ super closure changed -# Python 3.3a0 3200 (__qualname__ added) -# 3210 (added size modulo 2**32 to the pyc header) -# Python 3.3a1 3220 (changed PEP 380 implementation) -# Python 3.3a4 3230 (revert changes to implicit __class__ closure) +# Python 3.2a3 3180 (add DELETE_DEREF #4617) +# Python 3.3a1 3190 (__class__ super closure changed) +# Python 3.3a1 3200 (PEP 3155 __qualname__ added #13448) +# Python 3.3a1 3210 (added size modulo 2**32 to the pyc header #13645) +# Python 3.3a2 3220 (changed PEP 380 implementation #14230) +# Python 3.3a4 3230 (revert changes to implicit __class__ closure #14857) # Python 3.4a1 3250 (evaluate positional default arguments before -# keyword-only defaults) +# keyword-only defaults #16967) # Python 3.4a1 3260 (add LOAD_CLASSDEREF; allow locals of class to override -# free vars) -# Python 3.4a1 3270 (various tweaks to the __class__ closure) +# free vars #17853) +# Python 3.4a1 3270 (various tweaks to the __class__ closure #12370) # Python 3.4a1 3280 (remove implicit class argument) -# Python 3.4a4 3290 (changes to __qualname__ computation) -# Python 3.4a4 3300 (more changes to __qualname__ computation) -# Python 3.4rc2 3310 (alter __qualname__ computation) -# Python 3.5a0 3320 (matrix multiplication operator) -# Python 3.5b1 3330 (PEP 448: Additional Unpacking Generalizations) +# Python 3.4a4 3290 (changes to __qualname__ computation #19301) +# Python 3.4a4 3300 (more changes to __qualname__ computation #19301) +# Python 3.4rc2 3310 (alter __qualname__ computation #20625) +# Python 3.5a1 3320 (PEP 465: Matrix multiplication operator #21176) +# Python 3.5b1 3330 (PEP 448: Additional Unpacking Generalizations #2292) # Python 3.5b2 3340 (fix dictionary display evaluation order #11205) -# Python 3.5b2 3350 (add GET_YIELD_FROM_ITER opcode #24400) +# Python 3.5b3 3350 (add GET_YIELD_FROM_ITER opcode #24400) # Python 3.5.2 3351 (fix BUILD_MAP_UNPACK_WITH_CALL opcode #27286) -# Python 3.6a0 3360 (add FORMAT_VALUE opcode #25483 -# Python 3.6a0 3361 (lineno delta of code.co_lnotab becomes signed) -# Python 3.6a1 3370 (16 bit wordcode) -# Python 3.6a1 3371 (add BUILD_CONST_KEY_MAP opcode #27140) -# Python 3.6a1 3372 (MAKE_FUNCTION simplification, remove MAKE_CLOSURE +# Python 3.6a0 3360 (add FORMAT_VALUE opcode #25483) +# Python 3.6a1 3361 (lineno delta of code.co_lnotab becomes signed #26107) +# Python 3.6a2 3370 (16 bit wordcode #26647) +# Python 3.6a2 3371 (add BUILD_CONST_KEY_MAP opcode #27140) +# Python 3.6a2 3372 (MAKE_FUNCTION simplification, remove MAKE_CLOSURE # #27095) # Python 3.6b1 3373 (add BUILD_STRING opcode #27078) # Python 3.6b1 3375 (add SETUP_ANNOTATIONS and STORE_ANNOTATION opcodes # #27985) -# Python 3.6b1 3376 (simplify CALL_FUNCTIONs & BUILD_MAP_UNPACK_WITH_CALL) +# Python 3.6b1 3376 (simplify CALL_FUNCTIONs & BUILD_MAP_UNPACK_WITH_CALL + #27213) # Python 3.6b1 3377 (set __class__ cell from type.__new__ #23722) # Python 3.6b2 3378 (add BUILD_TUPLE_UNPACK_WITH_CALL #28257) # Python 3.6rc1 3379 (more thorough __class__ validation #23722) -# Python 3.7a0 3390 (add LOAD_METHOD and CALL_METHOD opcodes) -# Python 3.7a0 3391 (update GET_AITER #31709) -# Python 3.7a0 3392 (PEP 552: Deterministic pycs) -# Python 3.7a0 3393 (remove STORE_ANNOTATION opcode) +# Python 3.7a1 3390 (add LOAD_METHOD and CALL_METHOD opcodes #26110) +# 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) # # MAGIC must change whenever the bytecode emitted by the compiler may no # longer be understood by older implementations of the eval loop (usually diff --git a/Python/importlib_external.h b/Python/importlib_external.h index 73376a02e97e..7dd82492ef32 100644 --- a/Python/importlib_external.h +++ b/Python/importlib_external.h @@ -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, - 10,1,0,0,115,48,0,0,0,0,18,8,1,6,1,6, + 13,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,55,1,0,0,115,46,0,0,0,0,9, + 99,97,99,104,101,58,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,89,1,0,0, + 116,95,115,111,117,114,99,101,102,105,108,101,92,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,108,1,0,0,115,16,0,0,0,0,1,14,1,2, + 101,100,111,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,120,1,0,0,115,12,0,0,0, + 108,99,95,109,111,100,101,123,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,140, + 99,107,95,110,97,109,101,95,119,114,97,112,112,101,114,143, 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,151,1,0,0, + 114,4,0,0,0,218,5,95,119,114,97,112,154,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,132,1,0,0,115,14,0, + 104,101,99,107,95,110,97,109,101,135,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,160,1,0,0,115,10, + 111,100,117,108,101,95,115,104,105,109,163,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, - 177,1,0,0,115,28,0,0,0,0,16,12,1,8,1,16, + 180,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,210,1,0,0,115,14,0,0, + 116,97,109,112,95,112,121,99,213,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,238,1,0,0,115,8,0,0,0,0,17,16,1,2,1, + 99,241,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,6,2,0,0,115,16,0, + 95,98,121,116,101,99,111,100,101,9,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,19,2,0,0,115,12, + 101,115,116,97,109,112,95,112,121,99,22,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,29,2,0,0,115,14,0, + 95,104,97,115,104,95,112,121,99,32,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,40,2, + 13,100,101,99,111,100,101,95,115,111,117,114,99,101,43,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,57,2,0,0,115,62,0,0,0, + 111,99,97,116,105,111,110,60,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,137,2,0,0,115,8,0,0,0,0,2,2,1,14,1, + 121,140,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,144,2, + 101,97,114,99,104,95,114,101,103,105,115,116,114,121,147,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, - 159,2,0,0,115,26,0,0,0,0,2,10,1,8,1,4, + 162,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,175, + 0,0,218,11,102,105,110,100,95,109,111,100,117,108,101,178, 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,7 +1004,7 @@ 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,125,2,0,0,115,18,0, + 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, @@ -1039,7 +1039,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,194,2,0,0,115,8,0,0,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, @@ -1049,7 +1049,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,202,2, + 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, @@ -1069,7 +1069,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,205,2,0,0,115,10, + 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, @@ -1080,14 +1080,14 @@ const unsigned char _Py_M__importlib_external[] = { 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,213,2, + 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,189,2,0,0,115,8,0,0, + 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, @@ -1112,7 +1112,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,220,2,0,0,115,2,0, + 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, @@ -1147,7 +1147,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,228,2,0,0,115,2,0, + 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, @@ -1171,7 +1171,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,241,2,0,0,115,2,0,0,0,0,8,122, + 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, @@ -1188,7 +1188,7 @@ const unsigned char _Py_M__importlib_external[] = { 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, - 251,2,0,0,115,0,0,0,0,122,21,83,111,117,114,99, + 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, @@ -1208,7 +1208,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,2,3,0,0,115, + 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, @@ -1230,7 +1230,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,12,3,0,0,115,4,0,0, + 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, @@ -1309,7 +1309,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,20,3,0,0,115,134,0, + 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, @@ -1324,7 +1324,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,218,2,0, + 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, @@ -1354,7 +1354,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,111,3,0,0,115,4,0,0,0,0,3,6,1,122,19, + 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, @@ -1362,7 +1362,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,117, + 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, @@ -1371,7 +1371,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,121,3,0,0,115,2,0,0,0,0,1,122,19,70, + 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, @@ -1385,7 +1385,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,124,3,0,0,115,2,0, + 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, @@ -1396,7 +1396,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,136,3,0,0,115,2,0,0,0,0,3,122,23,70,105, + 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, @@ -1408,7 +1408,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,141,3,0,0,115,4,0,0,0,0,2, + 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, @@ -1416,7 +1416,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,148,3,0, + 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, @@ -1429,7 +1429,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,154,3,0,0,115,4,0,0,0,0,1,20,1,122, + 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, @@ -1442,7 +1442,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,158,3,0,0,115,8,0,0,0,0,1,10,1,4,1, + 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, @@ -1453,7 +1453,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,164,3,0,0,115,8,0,0,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, @@ -1463,7 +1463,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,170,3,0,0,115,2, + 218,8,99,111,110,116,101,110,116,115,173,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, @@ -1473,7 +1473,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,106,3,0,0,115,22,0,0,0,12, + 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, @@ -1495,7 +1495,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,178,3,0,0,115,4,0,0,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, @@ -1505,7 +1505,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,183,3,0,0,115,4,0, + 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, @@ -1540,7 +1540,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,188,3,0,0,115,42,0,0,0,0,2, + 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, @@ -1549,7 +1549,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,174,3,0,0,115,6,0,0,0,12,4,8,5,8, + 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, @@ -1570,7 +1570,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,223, + 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, @@ -1581,13 +1581,13 @@ const unsigned char _Py_M__importlib_external[] = { 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,239,3,0,0,115,2,0,0, + 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,219,3, + 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, @@ -1609,7 +1609,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,0,4,0,0,115,4, + 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, @@ -1618,7 +1618,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,4,4,0,0,115,4,0,0,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, @@ -1626,7 +1626,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,8,4,0,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, @@ -1643,7 +1643,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,11,4,0,0,115,10, + 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, @@ -1660,7 +1660,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,19,4,0,0,115,6,0, + 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, @@ -1678,7 +1678,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,28,4,0,0,115,2,0,0,0,4,1,122,49, + 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, @@ -1686,7 +1686,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,25,4,0,0,115,6,0,0, + 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, @@ -1697,7 +1697,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,31,4, + 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, @@ -1708,7 +1708,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,35,4,0,0,115,2,0,0,0,0,2,122, + 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, @@ -1719,7 +1719,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,39,4,0,0,115,2,0,0,0,0,3,122, + 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, @@ -1728,7 +1728,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,248,3,0,0,115,18,0,0,0,12,8,8,4, + 0,0,0,251,3,0,0,115,18,0,0,0,12,8,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 +1769,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,52,4,0,0,115,8,0,0,0,0,1, + 114,186,0,0,0,55,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 +1786,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,58,4,0,0,115,8, + 112,97,116,104,95,110,97,109,101,115,61,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 +1799,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,68,4,0,0,115,4,0,0,0,0,1, + 114,244,0,0,0,71,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 +1815,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, - 72,4,0,0,115,16,0,0,0,0,2,12,1,10,1,14, + 75,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 +1823,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,85,4,0,0,115, + 0,218,8,95,95,105,116,101,114,95,95,88,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 +1832,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, - 88,4,0,0,115,2,0,0,0,0,1,122,26,95,78,97, + 91,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,91,4,0,0,115, + 0,0,218,7,95,95,108,101,110,95,95,94,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 +1848,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,94,4,0,0,115,2,0, + 8,95,95,114,101,112,114,95,95,97,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 +1856,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,97,4,0,0,115,2,0,0,0, + 116,97,105,110,115,95,95,100,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 +1864,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,100,4,0,0,115,2,0,0, + 0,0,0,114,165,0,0,0,103,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,7 +1872,7 @@ 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,45,4,0,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, @@ -1889,7 +1889,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,106,4,0,0,115,2,0,0,0,0,1,122,25,95,78, + 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, @@ -1906,21 +1906,21 @@ const unsigned char _Py_M__importlib_external[] = { 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,109,4,0,0,115,2,0,0,0,0,7,122,28, + 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,118,4,0,0,115,2,0,0,0,0,1,122,27, + 0,0,0,121,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,121,4,0,0,115,2,0,0,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, @@ -1929,7 +1929,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,124,4, + 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, @@ -1939,14 +1939,14 @@ const unsigned char _Py_M__importlib_external[] = { 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,127,4,0,0,115,0,0,0,0,122, + 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,130,4,0,0,115,2,0,0,0,0,1, + 114,192,0,0,0,133,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, @@ -1964,7 +1964,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,133,4,0,0,115,6,0,0,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, @@ -1972,7 +1972,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,105,4,0,0,115, + 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, @@ -2006,7 +2006,7 @@ const unsigned char _Py_M__importlib_external[] = { 218,6,118,97,108,117,101,115,114,110,0,0,0,114,6,1, 0,0,41,2,114,172,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,151,4,0,0,115,6,0,0,0,0,4, + 114,6,1,0,0,154,4,0,0,115,6,0,0,0,0,4, 16,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, @@ -2026,7 +2026,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,159,4,0,0,115,16,0,0,0,0,3,16,1,12,1, + 115,162,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, @@ -2056,7 +2056,7 @@ const unsigned char _Py_M__importlib_external[] = { 114,111,114,114,11,1,0,0,41,3,114,172,0,0,0,114, 35,0,0,0,114,9,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,172,4, + 105,109,112,111,114,116,101,114,95,99,97,99,104,101,175,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, @@ -2074,7 +2074,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,0,114,9,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,194,4,0,0,115,18,0,0, + 103,101,116,95,115,112,101,99,197,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, @@ -2105,7 +2105,7 @@ const unsigned char _Py_M__importlib_external[] = { 110,97,109,101,115,112,97,99,101,95,112,97,116,104,90,5, 101,110,116,114,121,114,9,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,209,4, + 0,0,0,218,9,95,103,101,116,95,115,112,101,99,212,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, @@ -2132,7 +2132,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,16,1,0,0,114,2,0,0,0,114, - 2,0,0,0,114,4,0,0,0,114,182,0,0,0,241,4, + 2,0,0,0,114,4,0,0,0,114,182,0,0,0,244,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, @@ -2154,7 +2154,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,9,5,0,0,115,8,0,0,0,0,8,12, + 183,0,0,0,12,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, @@ -2162,7 +2162,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,114,6,1,0,0,114,11,1,0,0,114,13,1,0, 0,114,14,1,0,0,114,17,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,147,4, + 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,8,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, @@ -2206,7 +2206,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,38,5,0,0,115,2, + 114,4,0,0,0,114,238,0,0,0,41,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, @@ -2219,7 +2219,7 @@ const unsigned char _Py_M__importlib_external[] = { 108,111,97,100,101,114,95,100,101,116,97,105,108,115,90,7, 108,111,97,100,101,114,115,114,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,32,5,0,0,115,16,0,0,0,0,4,4,1,14, + 0,0,35,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, @@ -2228,7 +2228,7 @@ const unsigned char _Py_M__importlib_external[] = { 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, 20,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,46, + 114,2,0,0,0,114,4,0,0,0,114,6,1,0,0,49, 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, @@ -2251,7 +2251,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,52,5,0,0, + 0,0,114,4,0,0,0,114,119,0,0,0,55,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, @@ -2262,7 +2262,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,17,1,0,0,64,5,0,0,115,6,0, + 4,0,0,0,114,17,1,0,0,67,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, @@ -2316,7 +2316,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,69,5,0, + 0,0,0,114,4,0,0,0,114,182,0,0,0,72,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, @@ -2348,7 +2348,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,146,5,0,0,115,2,0,0,0,6, + 116,99,111,109,112,62,149,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, @@ -2364,7 +2364,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,25,1,0,0,117,5, + 2,0,0,0,114,4,0,0,0,114,25,1,0,0,120,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, @@ -2402,7 +2402,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,0,114,101,0,0,0,41,1,114,35,0,0,0,41, 2,114,172,0,0,0,114,24,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,158, + 95,102,111,114,95,70,105,108,101,70,105,110,100,101,114,161, 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, @@ -2410,7 +2410,7 @@ const unsigned char _Py_M__importlib_external[] = { 70,105,110,100,101,114,114,2,0,0,0,41,3,114,172,0, 0,0,114,24,1,0,0,114,30,1,0,0,114,2,0,0, 0,41,2,114,172,0,0,0,114,24,1,0,0,114,4,0, - 0,0,218,9,112,97,116,104,95,104,111,111,107,148,5,0, + 0,0,218,9,112,97,116,104,95,104,111,111,107,151,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, @@ -2419,7 +2419,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,166,5,0,0,115,2,0,0,0,0,1,122,19,70, + 0,0,169,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, @@ -2427,7 +2427,7 @@ const unsigned char _Py_M__importlib_external[] = { 119,0,0,0,114,17,1,0,0,114,182,0,0,0,114,25, 1,0,0,114,184,0,0,0,114,31,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,18,1,0,0,23,5,0,0,115, + 0,114,4,0,0,0,114,18,1,0,0,26,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,18,1,0,0,99,4,0,0,0, 0,0,0,0,6,0,0,0,8,0,0,0,67,0,0,0, @@ -2450,7 +2450,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,172,5,0,0, + 105,120,95,117,112,95,109,111,100,117,108,101,175,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,36,1,0,0,99,0,0,0, @@ -2470,7 +2470,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,195,5,0,0,115,8,0,0,0, + 0,0,114,163,0,0,0,198,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, @@ -2521,7 +2521,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,231,5,0,0,115,2,0,0,0,4,0,122,25, + 0,0,0,234,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, @@ -2548,7 +2548,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,206,5,0,0,115,76,0, + 0,218,6,95,115,101,116,117,112,209,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, @@ -2568,7 +2568,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,114,5,1,0,0,41,2,114,42,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,14,6,0,0,115,8, + 218,8,95,105,110,115,116,97,108,108,17,6,0,0,115,8, 0,0,0,0,2,8,1,6,1,20,1,114,45,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, @@ -2599,12 +2599,12 @@ const unsigned char _Py_M__importlib_external[] = { 163,0,0,0,114,43,1,0,0,114,45,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,116,0,0,0,4,0,4,1,4,1,2,1,6,3,8, + 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,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,5,14, - 127,0,22,10,23,8,11,8,64, + 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, + 5,14,127,0,22,10,23,8,11,8,64, }; From webhook-mailer at python.org Thu Feb 22 15:33:19 2018 From: webhook-mailer at python.org (Steve Dower) Date: Thu, 22 Feb 2018 20:33:19 -0000 Subject: [Python-checkins] bpo-32457: Improves handling of denormalized executable path when launching Python (GH-5756) (#5818) Message-ID: https://github.com/python/cpython/commit/1d3c518c5ecbd78478738f068f4f035f81f035f9 commit: 1d3c518c5ecbd78478738f068f4f035f81f035f9 branch: 3.6 author: Steve Dower committer: GitHub date: 2018-02-22T12:33:16-08:00 summary: bpo-32457: Improves handling of denormalized executable path when launching Python (GH-5756) (#5818) files: A Misc/NEWS.d/next/Windows/2018-02-19-08-54-06.bpo-32457.vVP0Iz.rst M Lib/test/test_cmd_line.py M PC/getpathp.c diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py index 32d2df9d6c26..38156b49265e 100644 --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -489,6 +489,18 @@ def test_isolatedmode(self): cwd=tmpdir) self.assertEqual(out.strip(), b"ok") + @unittest.skipUnless(sys.platform == 'win32', + 'bpo-32457 only applies on Windows') + def test_argv0_normalization(self): + args = sys.executable, '-c', 'print(0)' + prefix, exe = os.path.split(sys.executable) + executable = prefix + '\\.\\.\\.\\' + exe + + proc = subprocess.run(args, stdout=subprocess.PIPE, + executable=executable) + self.assertEqual(proc.returncode, 0, proc) + self.assertEqual(proc.stdout.strip(), b'0') + def test_main(): test.support.run_unittest(CmdLineTest) diff --git a/Misc/NEWS.d/next/Windows/2018-02-19-08-54-06.bpo-32457.vVP0Iz.rst b/Misc/NEWS.d/next/Windows/2018-02-19-08-54-06.bpo-32457.vVP0Iz.rst new file mode 100644 index 000000000000..b55ec821e622 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2018-02-19-08-54-06.bpo-32457.vVP0Iz.rst @@ -0,0 +1 @@ +Improves handling of denormalized executable path when launching Python. diff --git a/PC/getpathp.c b/PC/getpathp.c index e7be704a9a78..af4af766a70f 100644 --- a/PC/getpathp.c +++ b/PC/getpathp.c @@ -241,6 +241,36 @@ join(wchar_t *buffer, const wchar_t *stuff) } } +static int _PathCchCanonicalizeEx_Initialized = 0; +typedef HRESULT(__stdcall *PPathCchCanonicalizeEx) (PWSTR pszPathOut, size_t cchPathOut, + PCWSTR pszPathIn, unsigned long dwFlags); +static PPathCchCanonicalizeEx _PathCchCanonicalizeEx; + +static void canonicalize(wchar_t *buffer, const wchar_t *path) +{ + if (_PathCchCanonicalizeEx_Initialized == 0) { + HMODULE pathapi = LoadLibraryW(L"api-ms-win-core-path-l1-1-0.dll"); + if (pathapi) { + _PathCchCanonicalizeEx = (PPathCchCanonicalizeEx)GetProcAddress(pathapi, "PathCchCanonicalizeEx"); + } + else { + _PathCchCanonicalizeEx = NULL; + } + _PathCchCanonicalizeEx_Initialized = 1; + } + + if (_PathCchCanonicalizeEx) { + if (FAILED(_PathCchCanonicalizeEx(buffer, MAXPATHLEN + 1, path, 0))) { + Py_FatalError("buffer overflow in getpathp.c's canonicalize()"); + } + } + else { + if (!PathCanonicalizeW(buffer, path)) { + Py_FatalError("buffer overflow in getpathp.c's canonicalize()"); + } + } +} + /* gotlandmark only called by search_for_prefix, which ensures 'prefix' is null terminated in bounds. join() ensures 'landmark' can not overflow prefix if too long. @@ -431,6 +461,7 @@ static void get_progpath(void) { extern wchar_t *Py_GetProgramName(void); + wchar_t modulepath[MAXPATHLEN]; wchar_t *path = _wgetenv(L"PATH"); wchar_t *prog = Py_GetProgramName(); @@ -443,8 +474,10 @@ get_progpath(void) #else dllpath[0] = 0; #endif - if (GetModuleFileNameW(NULL, progpath, MAXPATHLEN)) + if (GetModuleFileNameW(NULL, modulepath, MAXPATHLEN)) { + canonicalize(progpath, modulepath); return; + } if (prog == NULL || *prog == '\0') prog = L"python"; From webhook-mailer at python.org Thu Feb 22 16:19:03 2018 From: webhook-mailer at python.org (Alexander Belopolsky) Date: Thu, 22 Feb 2018 21:19:03 -0000 Subject: [Python-checkins] Test that new_timezone can return the UTC singleton (gh-5318) (#5819) Message-ID: https://github.com/python/cpython/commit/24d6e3c56bf99fd122e23da4c843fed3eb2a8b1c commit: 24d6e3c56bf99fd122e23da4c843fed3eb2a8b1c branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Alexander Belopolsky date: 2018-02-22T16:18:54-05:00 summary: Test that new_timezone can return the UTC singleton (gh-5318) (#5819) (cherry picked from commit a049f5790e38fe1b1ba1d4c10ed5ab35150806fa) Co-authored-by: Paul Ganssle files: M Lib/test/datetimetester.py M Modules/_testcapimodule.c diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index 8f9ebddff5a9..436cbea9669e 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -5489,6 +5489,28 @@ def test_timezones_capi(self): self.assertEqual(dt1.astimezone(timezone.utc), dt_utc) + def test_timezones_offset_zero(self): + utc0, utc1, non_utc = _testcapi.get_timezones_offset_zero() + + with self.subTest(testname="utc0"): + self.assertIs(utc0, timezone.utc) + + with self.subTest(testname="utc1"): + self.assertIs(utc1, timezone.utc) + + with self.subTest(testname="non_utc"): + self.assertIsNot(non_utc, timezone.utc) + + non_utc_exp = timezone(timedelta(hours=0), "") + + self.assertEqual(non_utc, non_utc_exp) + + dt1 = datetime(2000, 2, 4, tzinfo=non_utc) + dt2 = datetime(2000, 2, 4, tzinfo=non_utc_exp) + + self.assertEqual(dt1, dt2) + self.assertEqual(dt1.tzname(), dt2.tzname()) + def test_check_date(self): class DateSubclass(date): pass diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 2ad4322ecaa4..afce6c944895 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -2293,6 +2293,29 @@ make_timezones_capi(PyObject *self, PyObject *args) { return rv; } +static PyObject * +get_timezones_offset_zero(PyObject *self, PyObject *args) { + PyObject *offset = PyDelta_FromDSU(0, 0, 0); + PyObject *name = PyUnicode_FromString(""); + + // These two should return the UTC singleton + PyObject *utc_singleton_0 = PyTimeZone_FromOffset(offset); + PyObject *utc_singleton_1 = PyTimeZone_FromOffsetAndName(offset, NULL); + + // This one will return +00:00 zone, but not the UTC singleton + PyObject *non_utc_zone = PyTimeZone_FromOffsetAndName(offset, name); + + Py_DecRef(offset); + Py_DecRef(name); + + PyObject *rv = PyTuple_New(3); + PyTuple_SET_ITEM(rv, 0, utc_singleton_0); + PyTuple_SET_ITEM(rv, 1, utc_singleton_1); + PyTuple_SET_ITEM(rv, 2, non_utc_zone); + + return rv; +} + static PyObject * get_timezone_utc_capi(PyObject* self, PyObject *args) { int macro = 0; @@ -4540,6 +4563,7 @@ static PyMethodDef TestMethods[] = { {"datetime_check_delta", datetime_check_delta, METH_VARARGS}, {"datetime_check_tzinfo", datetime_check_tzinfo, METH_VARARGS}, {"make_timezones_capi", make_timezones_capi, METH_NOARGS}, + {"get_timezones_offset_zero", get_timezones_offset_zero, METH_NOARGS}, {"get_timezone_utc_capi", get_timezone_utc_capi, METH_VARARGS}, {"test_list_api", (PyCFunction)test_list_api, METH_NOARGS}, {"test_dict_iteration", (PyCFunction)test_dict_iteration,METH_NOARGS}, From webhook-mailer at python.org Thu Feb 22 16:33:34 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Thu, 22 Feb 2018 21:33:34 -0000 Subject: [Python-checkins] bpo-17611. Move unwinding of stack for "pseudo exceptions" from interpreter to compiler. (GH-5006) Message-ID: https://github.com/python/cpython/commit/520b7ae27e39d1c77ea74ccd1b184d7cb43f9dcb commit: 520b7ae27e39d1c77ea74ccd1b184d7cb43f9dcb branch: master author: Serhiy Storchaka committer: GitHub date: 2018-02-22T23:33:30+02:00 summary: bpo-17611. Move unwinding of stack for "pseudo exceptions" from interpreter to compiler. (GH-5006) Co-authored-by: Mark Shannon Co-authored-by: Antoine Pitrou files: A Misc/NEWS.d/next/Core and Builtins/2017-12-24-19-48-59.bpo-17611.P85kWL.rst M Doc/library/dis.rst M Doc/whatsnew/3.8.rst M Include/opcode.h M Lib/importlib/_bootstrap_external.py M Lib/opcode.py M Lib/test/test_dis.py M Lib/test/test_importlib/test_util.py M Lib/test/test_peepholer.py M Lib/test/test_sys_settrace.py M Objects/frameobject.c M Objects/genobject.c M PC/launcher.c M Python/ceval.c M Python/compile.c M Python/importlib.h M Python/importlib_external.h M Python/opcode_targets.h M Python/peephole.c diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index 535b36efbf2e..aa66128d60dd 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -335,6 +335,14 @@ The Python compiler currently generates the following bytecode instructions. three. +.. opcode:: ROT_FOUR + + Lifts second, third and forth stack items one position up, moves top down + to position four. + + .. versionadded:: 3.8 + + .. opcode:: DUP_TOP Duplicates the reference on top of the stack. @@ -605,17 +613,6 @@ the original TOS1. is terminated with :opcode:`POP_TOP`. -.. opcode:: BREAK_LOOP - - Terminates a loop due to a :keyword:`break` statement. - - -.. opcode:: CONTINUE_LOOP (target) - - Continues a loop due to a :keyword:`continue` statement. *target* is the - address to jump to (which should be a :opcode:`FOR_ITER` instruction). - - .. opcode:: SET_ADD (i) Calls ``set.add(TOS1[-i], TOS)``. Used to implement set comprehensions. @@ -676,7 +673,7 @@ iterations of the loop. .. opcode:: POP_BLOCK Removes one block from the block stack. Per frame, there is a stack of - blocks, denoting nested loops, try statements, and such. + blocks, denoting :keyword:`try` statements, and such. .. opcode:: POP_EXCEPT @@ -687,11 +684,50 @@ iterations of the loop. popped values are used to restore the exception state. +.. opcode:: POP_FINALLY (preserve_tos) + + Cleans up the value stack and the block stack. If *preserve_tos* is not + ``0`` TOS first is popped from the stack and pushed on the stack after + perfoming other stack operations: + + * If TOS is ``NULL`` or an integer (pushed by :opcode:`BEGIN_FINALLY` + or :opcode:`CALL_FINALLY`) it is popped from the stack. + * If TOS is an exception type (pushed when an exception has been raised) + 6 values are popped from the stack, the last three popped values are + used to restore the exception state. An exception handler block is + removed from the block stack. + + It is similar to :opcode:`END_FINALLY`, but doesn't change the bytecode + counter nor raise an exception. Used for implementing :keyword:`break` + and :keyword:`return` in the :keyword:`finally` block. + + .. versionadded:: 3.8 + + +.. opcode:: BEGIN_FINALLY + + Pushes ``NULL`` onto the stack for using it in :opcode:`END_FINALLY`, + :opcode:`POP_FINALLY`, :opcode:`WITH_CLEANUP_START` and + :opcode:`WITH_CLEANUP_FINISH`. Starts the :keyword:`finally` block. + + .. versionadded:: 3.8 + + .. opcode:: END_FINALLY Terminates a :keyword:`finally` clause. The interpreter recalls whether the - exception has to be re-raised, or whether the function returns, and continues - with the outer-next block. + exception has to be re-raised or execution has to be continued depending on + the value of TOS. + + * If TOS is ``NULL`` (pushed by :opcode:`BEGIN_FINALLY`) continue from + the next instruction. TOS is popped. + * If TOS is an integer (pushed by :opcode:`CALL_FINALLY`), sets the + bytecode counter to TOS. TOS is popped. + * If TOS is an exception type (pushed when an exception has been raised) + 6 values are popped from the stack, the first three popped values are + used to re-raise the exception and the last three popped values are used + to restore the exception state. An exception handler block is removed + from the block stack. .. opcode:: LOAD_BUILD_CLASS @@ -704,9 +740,9 @@ iterations of the loop. This opcode performs several operations before a with block starts. First, it loads :meth:`~object.__exit__` from the context manager and pushes it onto - the stack for later use by :opcode:`WITH_CLEANUP`. Then, + the stack for later use by :opcode:`WITH_CLEANUP_START`. Then, :meth:`~object.__enter__` is called, and a finally block pointing to *delta* - is pushed. Finally, the result of calling the enter method is pushed onto + is pushed. Finally, the result of calling the ``__enter__()`` method is pushed onto the stack. The next opcode will either ignore it (:opcode:`POP_TOP`), or store it in (a) variable(s) (:opcode:`STORE_FAST`, :opcode:`STORE_NAME`, or :opcode:`UNPACK_SEQUENCE`). @@ -716,30 +752,31 @@ iterations of the loop. .. opcode:: WITH_CLEANUP_START - Cleans up the stack when a :keyword:`with` statement block exits. TOS is the - context manager's :meth:`__exit__` bound method. Below TOS are 1--3 values - indicating how/why the finally clause was entered: + Starts cleaning up the stack when a :keyword:`with` statement block exits. - * SECOND = ``None`` - * (SECOND, THIRD) = (``WHY_{RETURN,CONTINUE}``), retval - * SECOND = ``WHY_*``; no retval below it - * (SECOND, THIRD, FOURTH) = exc_info() + At the top of the stack are either ``NULL`` (pushed by + :opcode:`BEGIN_FINALLY`) or 6 values pushed if an exception has been + raised in the with block. Below is the context manager's + :meth:`~object.__exit__` or :meth:`~object.__aexit__` bound method. - In the last case, ``TOS(SECOND, THIRD, FOURTH)`` is called, otherwise - ``TOS(None, None, None)``. Pushes SECOND and result of the call - to the stack. + If TOS is ``NULL``, calls ``SECOND(None, None, None)``, + removes the function from the stack, leaving TOS, and pushes ``None`` + to the stack. Otherwise calls ``SEVENTH(TOP, SECOND, THIRD)``, + shifts the bottom 3 values of the stack down, replaces the empty spot + with ``NULL`` and pushes TOS. Finally pushes the result of the call. .. opcode:: WITH_CLEANUP_FINISH - Pops exception type and result of 'exit' function call from the stack. + Finishes cleaning up the stack when a :keyword:`with` statement block exits. - If the stack represents an exception, *and* the function call returns a - 'true' value, this information is "zapped" and replaced with a single - ``WHY_SILENCED`` to prevent :opcode:`END_FINALLY` from re-raising the - exception. (But non-local gotos will still be resumed.) + TOS is result of ``__exit__()`` or ``__aexit__()`` function call pushed + by :opcode:`WITH_CLEANUP_START`. SECOND is ``None`` or an exception type + (pushed when an exception has been raised). - .. XXX explain the WHY stuff! + Pops two values from the stack. If SECOND is not None and TOS is true + unwinds the EXCEPT_HANDLER block which was created when the exception + was caught and pushes ``NULL`` to the stack. All of the following opcodes use their arguments. @@ -987,22 +1024,19 @@ All of the following opcodes use their arguments. Loads the global named ``co_names[namei]`` onto the stack. -.. opcode:: SETUP_LOOP (delta) - - Pushes a block for a loop onto the block stack. The block spans from the - current instruction with a size of *delta* bytes. - +.. opcode:: SETUP_FINALLY (delta) -.. opcode:: SETUP_EXCEPT (delta) + Pushes a try block from a try-finally or try-except clause onto the block + stack. *delta* points to the finally block or the first except block. - Pushes a try block from a try-except clause onto the block stack. *delta* - points to the first except block. +.. opcode:: CALL_FINALLY (delta) -.. opcode:: SETUP_FINALLY (delta) + Pushes the address of the next instruction onto the stack and increments + bytecode counter by *delta*. Used for calling the finally block as a + "subroutine". - Pushes a try block from a try-except clause onto the block stack. *delta* - points to the finally block. + .. versionadded:: 3.8 .. opcode:: LOAD_FAST (var_num) diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 41819815e399..1d722ef5f0cd 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -137,3 +137,21 @@ Changes in the Python API :func:`dbm.dumb.open` with flags ``'r'`` and ``'w'`` no longer creates a database if it does not exist. (Contributed by Serhiy Storchaka in :issue:`32749`.) + + +CPython bytecode changes +------------------------ + +* The interpreter loop has been simplified by moving the logic of unrolling + the stack of blocks into the compiler. The compiler emits now explicit + instructions for adjusting the stack of values and calling the cleaning + up code for :keyword:`break`, :keyword:`continue` and :keyword:`return`. + + Removed opcodes :opcode:`BREAK_LOOP`, :opcode:`CONTINUE_LOOP`, + :opcode:`SETUP_LOOP` and :opcode:`SETUP_EXCEPT`. Added new opcodes + :opcode:`ROT_FOUR`, :opcode:`BEGIN_FINALLY`, :opcode:`CALL_FINALLY` and + :opcode:`POP_FINALLY`. Changed the behavior of :opcode:`END_FINALLY` + and :opcode:`WITH_CLEANUP_START`. + + (Contributed by Mark Shannon, Antoine Pitrou and Serhiy Storchaka in + :issue:`17611`.) diff --git a/Include/opcode.h b/Include/opcode.h index fc6cbf3a7af4..fba74af44578 100644 --- a/Include/opcode.h +++ b/Include/opcode.h @@ -12,6 +12,7 @@ extern "C" { #define ROT_THREE 3 #define DUP_TOP 4 #define DUP_TOP_TWO 5 +#define ROT_FOUR 6 #define NOP 9 #define UNARY_POSITIVE 10 #define UNARY_NEGATIVE 11 @@ -32,6 +33,7 @@ extern "C" { #define GET_AITER 50 #define GET_ANEXT 51 #define BEFORE_ASYNC_WITH 52 +#define BEGIN_FINALLY 53 #define INPLACE_ADD 55 #define INPLACE_SUBTRACT 56 #define INPLACE_MULTIPLY 57 @@ -55,7 +57,6 @@ extern "C" { #define INPLACE_AND 77 #define INPLACE_XOR 78 #define INPLACE_OR 79 -#define BREAK_LOOP 80 #define WITH_CLEANUP_START 81 #define WITH_CLEANUP_FINISH 82 #define RETURN_VALUE 83 @@ -92,9 +93,6 @@ extern "C" { #define POP_JUMP_IF_FALSE 114 #define POP_JUMP_IF_TRUE 115 #define LOAD_GLOBAL 116 -#define CONTINUE_LOOP 119 -#define SETUP_LOOP 120 -#define SETUP_EXCEPT 121 #define SETUP_FINALLY 122 #define LOAD_FAST 124 #define STORE_FAST 125 @@ -127,6 +125,8 @@ extern "C" { #define BUILD_TUPLE_UNPACK_WITH_CALL 158 #define LOAD_METHOD 160 #define CALL_METHOD 161 +#define CALL_FINALLY 162 +#define POP_FINALLY 163 /* EXCEPT_HANDLER is a special, implicit block type which is created when entering an except handler. It is not an opcode but we define it here diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index e2951746835e..27aaf555390f 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -246,6 +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.8a1 3400 (move frame block handling to compiler #17611) # # 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 +255,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 = (3400).to_bytes(2, 'little') + b'\r\n' _RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c _PYCACHE = '__pycache__' diff --git a/Lib/opcode.py b/Lib/opcode.py index 368472d98116..6de24c34affe 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -60,6 +60,7 @@ def jabs_op(name, op): def_op('ROT_THREE', 3) def_op('DUP_TOP', 4) def_op('DUP_TOP_TWO', 5) +def_op('ROT_FOUR', 6) def_op('NOP', 9) def_op('UNARY_POSITIVE', 10) @@ -86,6 +87,7 @@ def jabs_op(name, op): def_op('GET_AITER', 50) def_op('GET_ANEXT', 51) def_op('BEFORE_ASYNC_WITH', 52) +def_op('BEGIN_FINALLY', 53) def_op('INPLACE_ADD', 55) def_op('INPLACE_SUBTRACT', 56) @@ -113,10 +115,8 @@ def jabs_op(name, op): def_op('INPLACE_AND', 77) def_op('INPLACE_XOR', 78) def_op('INPLACE_OR', 79) -def_op('BREAK_LOOP', 80) def_op('WITH_CLEANUP_START', 81) def_op('WITH_CLEANUP_FINISH', 82) - def_op('RETURN_VALUE', 83) def_op('IMPORT_STAR', 84) def_op('SETUP_ANNOTATIONS', 85) @@ -158,10 +158,7 @@ def jabs_op(name, op): name_op('LOAD_GLOBAL', 116) # Index in name list -jabs_op('CONTINUE_LOOP', 119) # Target address -jrel_op('SETUP_LOOP', 120) # Distance to target address -jrel_op('SETUP_EXCEPT', 121) # "" -jrel_op('SETUP_FINALLY', 122) # "" +jrel_op('SETUP_FINALLY', 122) # Distance to target address def_op('LOAD_FAST', 124) # Local variable number haslocal.append(124) @@ -213,5 +210,7 @@ def jabs_op(name, op): name_op('LOAD_METHOD', 160) def_op('CALL_METHOD', 161) +jrel_op('CALL_FINALLY', 162) +def_op('POP_FINALLY', 163) del def_op, name_op, jrel_op, jabs_op diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index ba8c6b940b04..08393f734ba5 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -120,20 +120,18 @@ def bug708901(): pass dis_bug708901 = """\ -%3d 0 SETUP_LOOP 18 (to 20) - 2 LOAD_GLOBAL 0 (range) - 4 LOAD_CONST 1 (1) - -%3d 6 LOAD_CONST 2 (10) - 8 CALL_FUNCTION 2 - 10 GET_ITER - >> 12 FOR_ITER 4 (to 18) - 14 STORE_FAST 0 (res) - -%3d 16 JUMP_ABSOLUTE 12 - >> 18 POP_BLOCK - >> 20 LOAD_CONST 0 (None) - 22 RETURN_VALUE +%3d 0 LOAD_GLOBAL 0 (range) + 2 LOAD_CONST 1 (1) + +%3d 4 LOAD_CONST 2 (10) + 6 CALL_FUNCTION 2 + 8 GET_ITER + >> 10 FOR_ITER 4 (to 16) + 12 STORE_FAST 0 (res) + +%3d 14 JUMP_ABSOLUTE 10 + >> 16 LOAD_CONST 0 (None) + 18 RETURN_VALUE """ % (bug708901.__code__.co_firstlineno + 1, bug708901.__code__.co_firstlineno + 2, bug708901.__code__.co_firstlineno + 3) @@ -259,20 +257,17 @@ def bug1333982(x=[]): 1 0 LOAD_CONST 0 (0) 2 STORE_NAME 0 (x) - 2 4 SETUP_LOOP 12 (to 18) - - 3 >> 6 LOAD_NAME 0 (x) - 8 LOAD_CONST 1 (1) - 10 INPLACE_ADD - 12 STORE_NAME 0 (x) - 14 JUMP_ABSOLUTE 6 - 16 POP_BLOCK - >> 18 LOAD_CONST 2 (None) - 20 RETURN_VALUE + 3 >> 4 LOAD_NAME 0 (x) + 6 LOAD_CONST 1 (1) + 8 INPLACE_ADD + 10 STORE_NAME 0 (x) + 12 JUMP_ABSOLUTE 4 + 14 LOAD_CONST 2 (None) + 16 RETURN_VALUE """ dis_traceback = """\ -%3d 0 SETUP_EXCEPT 12 (to 14) +%3d 0 SETUP_FINALLY 12 (to 14) %3d 2 LOAD_CONST 1 (1) 4 LOAD_CONST 2 (0) @@ -294,7 +289,7 @@ def bug1333982(x=[]): 32 LOAD_ATTR 1 (__traceback__) 34 STORE_FAST 1 (tb) 36 POP_BLOCK - 38 LOAD_CONST 0 (None) + 38 BEGIN_FINALLY >> 40 LOAD_CONST 0 (None) 42 STORE_FAST 0 (e) 44 DELETE_FAST 0 (e) @@ -749,7 +744,14 @@ def f(c=c): Flags: OPTIMIZED, NEWLOCALS, NOFREE, COROUTINE Constants: 0: None - 1: 1""" + 1: 1 +Names: + 0: b + 1: StopAsyncIteration + 2: c +Variable names: + 0: a + 1: d""" class CodeInfoTests(unittest.TestCase): test_pairs = [ @@ -913,103 +915,100 @@ def jumpy(): ] expected_opinfo_jumpy = [ - Instruction(opname='SETUP_LOOP', opcode=120, arg=52, argval=54, argrepr='to 54', offset=0, starts_line=3, is_jump_target=False), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=0, argval='range', argrepr='range', offset=2, starts_line=None, is_jump_target=False), - Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval=10, argrepr='10', offset=4, starts_line=None, is_jump_target=False), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=6, starts_line=None, is_jump_target=False), - Instruction(opname='GET_ITER', opcode=68, arg=None, argval=None, argrepr='', offset=8, starts_line=None, is_jump_target=False), - Instruction(opname='FOR_ITER', opcode=93, arg=32, argval=44, argrepr='to 44', offset=10, starts_line=None, is_jump_target=True), - Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=12, starts_line=None, is_jump_target=False), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=14, starts_line=4, is_jump_target=False), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=16, starts_line=None, is_jump_target=False), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=18, starts_line=None, is_jump_target=False), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=20, starts_line=None, is_jump_target=False), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=22, starts_line=5, is_jump_target=False), - Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=24, starts_line=None, is_jump_target=False), - Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=26, starts_line=None, is_jump_target=False), - Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=32, argval=32, argrepr='', offset=28, starts_line=None, is_jump_target=False), - Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=10, argval=10, argrepr='', offset=30, starts_line=6, is_jump_target=False), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=32, starts_line=7, is_jump_target=True), - Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=34, starts_line=None, is_jump_target=False), - Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=36, starts_line=None, is_jump_target=False), - Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=10, argval=10, argrepr='', offset=38, starts_line=None, is_jump_target=False), - Instruction(opname='BREAK_LOOP', opcode=80, arg=None, argval=None, argrepr='', offset=40, starts_line=8, is_jump_target=False), - Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=10, argval=10, argrepr='', offset=42, starts_line=None, is_jump_target=False), - Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=44, starts_line=None, is_jump_target=True), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=46, starts_line=10, is_jump_target=False), - Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=48, starts_line=None, is_jump_target=False), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=50, starts_line=None, is_jump_target=False), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=52, starts_line=None, is_jump_target=False), - Instruction(opname='SETUP_LOOP', opcode=120, arg=52, argval=108, argrepr='to 108', offset=54, starts_line=11, is_jump_target=True), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=56, starts_line=None, is_jump_target=True), - Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=98, argval=98, argrepr='', offset=58, starts_line=None, is_jump_target=False), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=60, starts_line=12, is_jump_target=False), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=62, starts_line=None, is_jump_target=False), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=64, starts_line=None, is_jump_target=False), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=66, starts_line=None, is_jump_target=False), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=68, starts_line=13, is_jump_target=False), - Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=70, starts_line=None, is_jump_target=False), - Instruction(opname='INPLACE_SUBTRACT', opcode=56, arg=None, argval=None, argrepr='', offset=72, starts_line=None, is_jump_target=False), - Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=74, starts_line=None, is_jump_target=False), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=76, starts_line=14, is_jump_target=False), - Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=78, starts_line=None, is_jump_target=False), - Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=80, starts_line=None, is_jump_target=False), - Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=86, argval=86, argrepr='', offset=82, starts_line=None, is_jump_target=False), - Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=56, argval=56, argrepr='', offset=84, starts_line=15, is_jump_target=False), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=86, starts_line=16, is_jump_target=True), - Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=88, starts_line=None, is_jump_target=False), - Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=90, starts_line=None, is_jump_target=False), - Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=56, argval=56, argrepr='', offset=92, starts_line=None, is_jump_target=False), - Instruction(opname='BREAK_LOOP', opcode=80, arg=None, argval=None, argrepr='', offset=94, starts_line=17, is_jump_target=False), - Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=56, argval=56, argrepr='', offset=96, starts_line=None, is_jump_target=False), - Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=98, starts_line=None, is_jump_target=True), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=100, starts_line=19, is_jump_target=False), - Instruction(opname='LOAD_CONST', opcode=100, arg=6, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=102, starts_line=None, is_jump_target=False), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=104, starts_line=None, is_jump_target=False), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=106, starts_line=None, is_jump_target=False), - Instruction(opname='SETUP_FINALLY', opcode=122, arg=70, argval=180, argrepr='to 180', offset=108, starts_line=20, is_jump_target=True), - Instruction(opname='SETUP_EXCEPT', opcode=121, arg=12, argval=124, argrepr='to 124', offset=110, starts_line=None, is_jump_target=False), - Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=112, starts_line=21, is_jump_target=False), - Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval=0, argrepr='0', offset=114, starts_line=None, is_jump_target=False), - Instruction(opname='BINARY_TRUE_DIVIDE', opcode=27, arg=None, argval=None, argrepr='', offset=116, starts_line=None, is_jump_target=False), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=118, starts_line=None, is_jump_target=False), - Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=120, starts_line=None, is_jump_target=False), - Instruction(opname='JUMP_FORWARD', opcode=110, arg=28, argval=152, argrepr='to 152', offset=122, starts_line=None, is_jump_target=False), - Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=124, starts_line=22, is_jump_target=True), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=2, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=126, starts_line=None, is_jump_target=False), - Instruction(opname='COMPARE_OP', opcode=107, arg=10, argval='exception match', argrepr='exception match', offset=128, starts_line=None, is_jump_target=False), - Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=150, argval=150, argrepr='', offset=130, starts_line=None, is_jump_target=False), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=132, starts_line=None, is_jump_target=False), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=134, starts_line=None, is_jump_target=False), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=136, starts_line=None, is_jump_target=False), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=138, starts_line=23, is_jump_target=False), - Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=140, starts_line=None, is_jump_target=False), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=142, starts_line=None, is_jump_target=False), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=144, starts_line=None, is_jump_target=False), - Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=146, starts_line=None, is_jump_target=False), - Instruction(opname='JUMP_FORWARD', opcode=110, arg=26, argval=176, argrepr='to 176', offset=148, starts_line=None, is_jump_target=False), - Instruction(opname='END_FINALLY', opcode=88, arg=None, argval=None, argrepr='', offset=150, starts_line=None, is_jump_target=True), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=152, starts_line=25, is_jump_target=True), - Instruction(opname='SETUP_WITH', opcode=143, arg=14, argval=170, argrepr='to 170', offset=154, starts_line=None, is_jump_target=False), - Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=156, starts_line=None, is_jump_target=False), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=158, starts_line=26, is_jump_target=False), - Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Never reach this', argrepr="'Never reach this'", offset=160, starts_line=None, is_jump_target=False), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=162, starts_line=None, is_jump_target=False), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=164, starts_line=None, is_jump_target=False), - Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=166, starts_line=None, is_jump_target=False), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=168, starts_line=None, is_jump_target=False), - Instruction(opname='WITH_CLEANUP_START', opcode=81, arg=None, argval=None, argrepr='', offset=170, starts_line=None, is_jump_target=True), - Instruction(opname='WITH_CLEANUP_FINISH', opcode=82, arg=None, argval=None, argrepr='', offset=172, starts_line=None, is_jump_target=False), - Instruction(opname='END_FINALLY', opcode=88, arg=None, argval=None, argrepr='', offset=174, starts_line=None, is_jump_target=False), - Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=176, starts_line=None, is_jump_target=True), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=178, starts_line=None, is_jump_target=False), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=180, starts_line=28, is_jump_target=True), - Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=182, starts_line=None, is_jump_target=False), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=184, starts_line=None, is_jump_target=False), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=186, starts_line=None, is_jump_target=False), - Instruction(opname='END_FINALLY', opcode=88, arg=None, argval=None, argrepr='', offset=188, starts_line=None, is_jump_target=False), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=190, starts_line=None, is_jump_target=False), - Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=192, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=0, argval='range', argrepr='range', offset=0, starts_line=3, is_jump_target=False), + Instruction(opname='LOAD_CONST', opcode=100, arg=1, argval=10, argrepr='10', offset=2, starts_line=None, is_jump_target=False), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=4, starts_line=None, is_jump_target=False), + Instruction(opname='GET_ITER', opcode=68, arg=None, argval=None, argrepr='', offset=6, starts_line=None, is_jump_target=False), + Instruction(opname='FOR_ITER', opcode=93, arg=34, argval=44, argrepr='to 44', offset=8, starts_line=None, is_jump_target=True), + Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=10, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=12, starts_line=4, is_jump_target=False), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=14, starts_line=None, is_jump_target=False), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=16, starts_line=None, is_jump_target=False), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=18, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=20, starts_line=5, is_jump_target=False), + Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=22, starts_line=None, is_jump_target=False), + Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=24, starts_line=None, is_jump_target=False), + Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=30, argval=30, argrepr='', offset=26, starts_line=None, is_jump_target=False), + Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=8, argval=8, argrepr='', offset=28, starts_line=6, is_jump_target=False), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=30, starts_line=7, is_jump_target=True), + Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=32, starts_line=None, is_jump_target=False), + Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=34, starts_line=None, is_jump_target=False), + Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=8, argval=8, argrepr='', offset=36, starts_line=None, is_jump_target=False), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=38, starts_line=8, is_jump_target=False), + Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=52, argval=52, argrepr='', offset=40, starts_line=None, is_jump_target=False), + Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=8, argval=8, argrepr='', offset=42, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=44, starts_line=10, is_jump_target=True), + Instruction(opname='LOAD_CONST', opcode=100, arg=4, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=46, starts_line=None, is_jump_target=False), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=48, starts_line=None, is_jump_target=False), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=50, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=52, starts_line=11, is_jump_target=True), + Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=94, argval=94, argrepr='', offset=54, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=56, starts_line=12, is_jump_target=False), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=58, starts_line=None, is_jump_target=False), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=60, starts_line=None, is_jump_target=False), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=62, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=64, starts_line=13, is_jump_target=False), + Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=66, starts_line=None, is_jump_target=False), + Instruction(opname='INPLACE_SUBTRACT', opcode=56, arg=None, argval=None, argrepr='', offset=68, starts_line=None, is_jump_target=False), + Instruction(opname='STORE_FAST', opcode=125, arg=0, argval='i', argrepr='i', offset=70, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=72, starts_line=14, is_jump_target=False), + Instruction(opname='LOAD_CONST', opcode=100, arg=3, argval=6, argrepr='6', offset=74, starts_line=None, is_jump_target=False), + Instruction(opname='COMPARE_OP', opcode=107, arg=4, argval='>', argrepr='>', offset=76, starts_line=None, is_jump_target=False), + Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=82, argval=82, argrepr='', offset=78, starts_line=None, is_jump_target=False), + Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=52, argval=52, argrepr='', offset=80, starts_line=15, is_jump_target=False), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=82, starts_line=16, is_jump_target=True), + Instruction(opname='LOAD_CONST', opcode=100, arg=2, argval=4, argrepr='4', offset=84, starts_line=None, is_jump_target=False), + Instruction(opname='COMPARE_OP', opcode=107, arg=0, argval='<', argrepr='<', offset=86, starts_line=None, is_jump_target=False), + Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=52, argval=52, argrepr='', offset=88, starts_line=None, is_jump_target=False), + Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=102, argval=102, argrepr='', offset=90, starts_line=17, is_jump_target=False), + Instruction(opname='JUMP_ABSOLUTE', opcode=113, arg=52, argval=52, argrepr='', offset=92, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=94, starts_line=19, is_jump_target=True), + Instruction(opname='LOAD_CONST', opcode=100, arg=6, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=96, starts_line=None, is_jump_target=False), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=98, starts_line=None, is_jump_target=False), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=100, starts_line=None, is_jump_target=False), + Instruction(opname='SETUP_FINALLY', opcode=122, arg=70, argval=174, argrepr='to 174', offset=102, starts_line=20, is_jump_target=True), + Instruction(opname='SETUP_FINALLY', opcode=122, arg=12, argval=118, argrepr='to 118', offset=104, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=1, argrepr='1', offset=106, starts_line=21, is_jump_target=False), + Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval=0, argrepr='0', offset=108, starts_line=None, is_jump_target=False), + Instruction(opname='BINARY_TRUE_DIVIDE', opcode=27, arg=None, argval=None, argrepr='', offset=110, starts_line=None, is_jump_target=False), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=112, starts_line=None, is_jump_target=False), + Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=114, starts_line=None, is_jump_target=False), + Instruction(opname='JUMP_FORWARD', opcode=110, arg=28, argval=146, argrepr='to 146', offset=116, starts_line=None, is_jump_target=False), + Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=118, starts_line=22, is_jump_target=True), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=2, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=120, starts_line=None, is_jump_target=False), + Instruction(opname='COMPARE_OP', opcode=107, arg=10, argval='exception match', argrepr='exception match', offset=122, starts_line=None, is_jump_target=False), + Instruction(opname='POP_JUMP_IF_FALSE', opcode=114, arg=144, argval=144, argrepr='', offset=124, starts_line=None, is_jump_target=False), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=126, starts_line=None, is_jump_target=False), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=128, starts_line=None, is_jump_target=False), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=130, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=132, starts_line=23, is_jump_target=False), + Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=134, starts_line=None, is_jump_target=False), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=136, starts_line=None, is_jump_target=False), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=138, starts_line=None, is_jump_target=False), + Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=140, starts_line=None, is_jump_target=False), + Instruction(opname='JUMP_FORWARD', opcode=110, arg=26, argval=170, argrepr='to 170', offset=142, starts_line=None, is_jump_target=False), + Instruction(opname='END_FINALLY', opcode=88, arg=None, argval=None, argrepr='', offset=144, starts_line=None, is_jump_target=True), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=146, starts_line=25, is_jump_target=True), + Instruction(opname='SETUP_WITH', opcode=143, arg=14, argval=164, argrepr='to 164', offset=148, starts_line=None, is_jump_target=False), + Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=150, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=152, starts_line=26, is_jump_target=False), + Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Never reach this', argrepr="'Never reach this'", offset=154, starts_line=None, is_jump_target=False), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=156, starts_line=None, is_jump_target=False), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=158, starts_line=None, is_jump_target=False), + Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=160, starts_line=None, is_jump_target=False), + Instruction(opname='BEGIN_FINALLY', opcode=53, arg=None, argval=None, argrepr='', offset=162, starts_line=None, is_jump_target=False), + Instruction(opname='WITH_CLEANUP_START', opcode=81, arg=None, argval=None, argrepr='', offset=164, starts_line=None, is_jump_target=True), + Instruction(opname='WITH_CLEANUP_FINISH', opcode=82, arg=None, argval=None, argrepr='', offset=166, starts_line=None, is_jump_target=False), + Instruction(opname='END_FINALLY', opcode=88, arg=None, argval=None, argrepr='', offset=168, starts_line=None, is_jump_target=False), + Instruction(opname='POP_BLOCK', opcode=87, arg=None, argval=None, argrepr='', offset=170, starts_line=None, is_jump_target=True), + Instruction(opname='BEGIN_FINALLY', opcode=53, arg=None, argval=None, argrepr='', offset=172, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=174, starts_line=28, is_jump_target=True), + Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=176, starts_line=None, is_jump_target=False), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=178, starts_line=None, is_jump_target=False), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=180, starts_line=None, is_jump_target=False), + Instruction(opname='END_FINALLY', opcode=88, arg=None, argval=None, argrepr='', offset=182, starts_line=None, is_jump_target=False), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=184, starts_line=None, is_jump_target=False), + Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=186, starts_line=None, is_jump_target=False), ] # One last piece of inspect fodder to check the default line number handling diff --git a/Lib/test/test_importlib/test_util.py b/Lib/test/test_importlib/test_util.py index 56a0b0e7a518..0946b3487bb8 100644 --- a/Lib/test/test_importlib/test_util.py +++ b/Lib/test/test_importlib/test_util.py @@ -789,7 +789,7 @@ def test_magic_number(self): in advance. Such exceptional releases will then require an adjustment to this test case. """ - EXPECTED_MAGIC_NUMBER = 3379 + EXPECTED_MAGIC_NUMBER = 3400 actual = int.from_bytes(importlib.util.MAGIC_NUMBER[:2], 'little') msg = ( diff --git a/Lib/test/test_peepholer.py b/Lib/test/test_peepholer.py index 0cc1e92907b5..c24cf77e7b2d 100644 --- a/Lib/test/test_peepholer.py +++ b/Lib/test/test_peepholer.py @@ -268,7 +268,7 @@ def f(cond1, cond2): self.assertNotInBytecode(f, 'JUMP_ABSOLUTE') returns = [instr for instr in dis.get_instructions(f) if instr.opname == 'RETURN_VALUE'] - self.assertEqual(len(returns), 6) + self.assertLessEqual(len(returns), 6) def test_elim_jump_after_return2(self): # Eliminate dead code: jumps immediately after returns can't be reached @@ -282,7 +282,7 @@ def f(cond1, cond2): self.assertEqual(len(returns), 1) returns = [instr for instr in dis.get_instructions(f) if instr.opname == 'RETURN_VALUE'] - self.assertEqual(len(returns), 2) + self.assertLessEqual(len(returns), 2) def test_make_function_doesnt_bail(self): def f(): diff --git a/Lib/test/test_sys_settrace.py b/Lib/test/test_sys_settrace.py index e6eb80ad86a8..7df10cb5c1f7 100644 --- a/Lib/test/test_sys_settrace.py +++ b/Lib/test/test_sys_settrace.py @@ -187,7 +187,6 @@ def tightloop_example(): (1, 'line'), (2, 'line'), (3, 'line'), - (4, 'line'), (5, 'line'), (5, 'line'), (5, 'line'), @@ -715,6 +714,21 @@ def test_jump_in_nested_finally_3(output): output.append(11) output.append(12) + @jump_test(5, 11, [2, 4, 12]) + def test_jump_over_return_try_finally_in_finally_block(output): + try: + output.append(2) + finally: + output.append(4) + output.append(5) + return + try: + output.append(8) + finally: + output.append(10) + pass + output.append(12) + @jump_test(3, 4, [1, 4]) def test_jump_infinite_while_loop(output): output.append(1) @@ -722,6 +736,22 @@ def test_jump_infinite_while_loop(output): output.append(3) output.append(4) + @jump_test(2, 4, [4, 4]) + def test_jump_forwards_into_while_block(output): + i = 1 + output.append(2) + while i <= 2: + output.append(4) + i += 1 + + @jump_test(5, 3, [3, 3, 3, 5]) + def test_jump_backwards_into_while_block(output): + i = 1 + while i <= 2: + output.append(3) + i += 1 + output.append(5) + @jump_test(2, 3, [1, 3]) def test_jump_forwards_out_of_with_block(output): with tracecontext(output, 1): @@ -916,22 +946,6 @@ def test_no_jump_backwards_into_for_block(output): output.append(2) output.append(3) - @jump_test(2, 4, [], (ValueError, 'into')) - def test_no_jump_forwards_into_while_block(output): - i = 1 - output.append(2) - while i <= 2: - output.append(4) - i += 1 - - @jump_test(5, 3, [3, 3], (ValueError, 'into')) - def test_no_jump_backwards_into_while_block(output): - i = 1 - while i <= 2: - output.append(3) - i += 1 - output.append(5) - @jump_test(1, 3, [], (ValueError, 'into')) def test_no_jump_forwards_into_with_block(output): output.append(1) @@ -1024,6 +1038,16 @@ def test_no_jump_between_with_blocks(output): with tracecontext(output, 4): output.append(5) + @jump_test(5, 7, [2, 4], (ValueError, 'finally')) + def test_no_jump_over_return_out_of_finally_block(output): + try: + output.append(2) + finally: + output.append(4) + output.append(5) + return + output.append(7) + @jump_test(7, 4, [1, 6], (ValueError, 'into')) def test_no_jump_into_for_block_before_else(output): output.append(1) diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-12-24-19-48-59.bpo-17611.P85kWL.rst b/Misc/NEWS.d/next/Core and Builtins/2017-12-24-19-48-59.bpo-17611.P85kWL.rst new file mode 100644 index 000000000000..52949e6018af --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-12-24-19-48-59.bpo-17611.P85kWL.rst @@ -0,0 +1,10 @@ +Simplified the interpreter loop by moving the logic of unrolling the stack +of blocks into the compiler. The compiler emits now explicit instructions +for adjusting the stack of values and calling the cleaning up code for +:keyword:`break`, :keyword:`continue` and :keyword:`return`. + +Removed opcodes :opcode:`BREAK_LOOP`, :opcode:`CONTINUE_LOOP`, +:opcode:`SETUP_LOOP` and :opcode:`SETUP_EXCEPT`. Added new opcodes +:opcode:`ROT_FOUR`, :opcode:`BEGIN_FINALLY` and :opcode:`CALL_FINALLY` and +:opcode:`POP_FINALLY`. Changed the behavior of :opcode:`END_FINALLY` and +:opcode:`WITH_CLEANUP_START`. diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 3083e5b6445c..d308457b7547 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -45,6 +45,27 @@ frame_getlineno(PyFrameObject *f, void *closure) return PyLong_FromLong(PyFrame_GetLineNumber(f)); } + +/* Given the index of the effective opcode, + scan back to construct the oparg with EXTENDED_ARG */ +static unsigned int +get_arg(const _Py_CODEUNIT *codestr, Py_ssize_t i) +{ + _Py_CODEUNIT word; + unsigned int oparg = _Py_OPARG(codestr[i]); + if (i >= 1 && _Py_OPCODE(word = codestr[i-1]) == EXTENDED_ARG) { + oparg |= _Py_OPARG(word) << 8; + if (i >= 2 && _Py_OPCODE(word = codestr[i-2]) == EXTENDED_ARG) { + oparg |= _Py_OPARG(word) << 16; + if (i >= 3 && _Py_OPCODE(word = codestr[i-3]) == EXTENDED_ARG) { + oparg |= _Py_OPARG(word) << 24; + } + } + } + return oparg; +} + + /* Setter for f_lineno - you can set f_lineno from within a trace function in * order to jump to a given line of code, subject to some restrictions. Most * lines are OK to jump to because they don't make any assumptions about the @@ -56,8 +77,9 @@ frame_getlineno(PyFrameObject *f, void *closure) * they expect an exception to be on the top of the stack. * o Lines that live in a 'finally' block can't be jumped from or to, since * the END_FINALLY expects to clean up the stack after the 'try' block. - * o 'try'/'for'/'while' blocks can't be jumped into because the blockstack - * needs to be set up before their code runs, and for 'for' loops the + * o 'try', 'with' and 'async with' blocks can't be jumped into because + * the blockstack needs to be set up before their code runs. + * o 'for' and 'async for' loops can't be jumped into because the * iterator needs to be on the stack. */ static int @@ -75,17 +97,10 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno) int offset = 0; /* (ditto) */ int line = 0; /* (ditto) */ int addr = 0; /* (ditto) */ - int min_addr = 0; /* Scanning the SETUPs and POPs */ - int max_addr = 0; /* (ditto) */ - int delta_iblock = 0; /* (ditto) */ - int min_delta_iblock = 0; /* (ditto) */ - int min_iblock = 0; /* (ditto) */ - int f_lasti_setup_addr = 0; /* Policing no-jump-into-finally */ - int new_lasti_setup_addr = 0; /* (ditto) */ + int delta_iblock = 0; /* Scanning the SETUPs and POPs */ + int for_loop_delta = 0; /* (ditto) */ int blockstack[CO_MAXBLOCKS]; /* Walking the 'finally' blocks */ - int in_finally[CO_MAXBLOCKS]; /* (ditto) */ int blockstack_top = 0; /* (ditto) */ - unsigned char setup_op = 0; /* (ditto) */ /* f_lineno must be an integer. */ if (!PyLong_CheckExact(p_new_lineno)) { @@ -159,8 +174,6 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno) /* We're now ready to look at the bytecode. */ PyBytes_AsStringAndSize(f->f_code->co_code, (char **)&code, &code_len); - min_addr = Py_MIN(new_lasti, f->f_lasti); - max_addr = Py_MAX(new_lasti, f->f_lasti); /* You can't jump onto a line with an 'except' statement on it - * they expect to have an exception on the top of the stack, which @@ -179,141 +192,73 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno) } /* You can't jump into or out of a 'finally' block because the 'try' - * block leaves something on the stack for the END_FINALLY to clean - * up. So we walk the bytecode, maintaining a simulated blockstack. - * When we reach the old or new address and it's in a 'finally' block - * we note the address of the corresponding SETUP_FINALLY. The jump - * is only legal if neither address is in a 'finally' block or - * they're both in the same one. 'blockstack' is a stack of the - * bytecode addresses of the SETUP_X opcodes, and 'in_finally' tracks - * whether we're in a 'finally' block at each blockstack level. */ - f_lasti_setup_addr = -1; - new_lasti_setup_addr = -1; + * block leaves something on the stack for the END_FINALLY to clean up. + * So we walk the bytecode, maintaining a simulated blockstack. + * 'blockstack' is a stack of the bytecode addresses of the starts of + * the 'finally' blocks. */ memset(blockstack, '\0', sizeof(blockstack)); - memset(in_finally, '\0', sizeof(in_finally)); blockstack_top = 0; for (addr = 0; addr < code_len; addr += sizeof(_Py_CODEUNIT)) { unsigned char op = code[addr]; switch (op) { - case SETUP_LOOP: - case SETUP_EXCEPT: case SETUP_FINALLY: case SETUP_WITH: case SETUP_ASYNC_WITH: - blockstack[blockstack_top++] = addr; - in_finally[blockstack_top-1] = 0; - break; - - case POP_BLOCK: - assert(blockstack_top > 0); - setup_op = code[blockstack[blockstack_top-1]]; - if (setup_op == SETUP_FINALLY || setup_op == SETUP_WITH - || setup_op == SETUP_ASYNC_WITH) { - in_finally[blockstack_top-1] = 1; - } - else { - blockstack_top--; + case FOR_ITER: { + unsigned int oparg = get_arg((const _Py_CODEUNIT *)code, + addr / sizeof(_Py_CODEUNIT)); + int target_addr = addr + oparg + sizeof(_Py_CODEUNIT); + assert(target_addr < code_len); + /* Police block-jumping (you can't jump into the middle of a block) + * and ensure that the blockstack finishes up in a sensible state (by + * popping any blocks we're jumping out of). We look at all the + * blockstack operations between the current position and the new + * one, and keep track of how many blocks we drop out of on the way. + * By also keeping track of the lowest blockstack position we see, we + * can tell whether the jump goes into any blocks without coming out + * again - in that case we raise an exception below. */ + int first_in = addr < f->f_lasti && f->f_lasti < target_addr; + int second_in = addr < new_lasti && new_lasti < target_addr; + if (!first_in && second_in) { + PyErr_SetString(PyExc_ValueError, + "can't jump into the middle of a block"); + return -1; } - break; - - case END_FINALLY: - /* Ignore END_FINALLYs for SETUP_EXCEPTs - they exist - * in the bytecode but don't correspond to an actual - * 'finally' block. (If blockstack_top is 0, we must - * be seeing such an END_FINALLY.) */ - if (blockstack_top > 0) { - setup_op = code[blockstack[blockstack_top-1]]; - if (setup_op == SETUP_FINALLY || setup_op == SETUP_WITH - || setup_op == SETUP_ASYNC_WITH) { - blockstack_top--; + if (first_in && !second_in) { + if (op == FOR_ITER && !delta_iblock) { + for_loop_delta++; + } + if (op != FOR_ITER) { + delta_iblock++; } } + if (op != FOR_ITER) { + blockstack[blockstack_top++] = target_addr; + } break; } - /* For the addresses we're interested in, see whether they're - * within a 'finally' block and if so, remember the address - * of the SETUP_FINALLY. */ - if (addr == new_lasti || addr == f->f_lasti) { - int i = 0; - int setup_addr = -1; - for (i = blockstack_top-1; i >= 0; i--) { - if (in_finally[i]) { - setup_addr = blockstack[i]; - break; - } - } - - if (setup_addr != -1) { - if (addr == new_lasti) { - new_lasti_setup_addr = setup_addr; - } - - if (addr == f->f_lasti) { - f_lasti_setup_addr = setup_addr; - } + case END_FINALLY: { + assert(blockstack_top > 0); + int target_addr = blockstack[--blockstack_top]; + assert(target_addr <= addr); + int first_in = target_addr <= f->f_lasti && f->f_lasti <= addr; + int second_in = target_addr <= new_lasti && new_lasti <= addr; + if (first_in != second_in) { + PyErr_SetString(PyExc_ValueError, + "can't jump into or out of a 'finally' block"); + return -1; } + break; + } } } /* Verify that the blockstack tracking code didn't get lost. */ assert(blockstack_top == 0); - /* After all that, are we jumping into / out of a 'finally' block? */ - if (new_lasti_setup_addr != f_lasti_setup_addr) { - PyErr_SetString(PyExc_ValueError, - "can't jump into or out of a 'finally' block"); - return -1; - } - - - /* Police block-jumping (you can't jump into the middle of a block) - * and ensure that the blockstack finishes up in a sensible state (by - * popping any blocks we're jumping out of). We look at all the - * blockstack operations between the current position and the new - * one, and keep track of how many blocks we drop out of on the way. - * By also keeping track of the lowest blockstack position we see, we - * can tell whether the jump goes into any blocks without coming out - * again - in that case we raise an exception below. */ - delta_iblock = 0; - for (addr = min_addr; addr < max_addr; addr += sizeof(_Py_CODEUNIT)) { - unsigned char op = code[addr]; - switch (op) { - case SETUP_LOOP: - case SETUP_EXCEPT: - case SETUP_FINALLY: - case SETUP_WITH: - case SETUP_ASYNC_WITH: - delta_iblock++; - break; - - case POP_BLOCK: - delta_iblock--; - break; - } - - min_delta_iblock = Py_MIN(min_delta_iblock, delta_iblock); - } - - /* Derive the absolute iblock values from the deltas. */ - min_iblock = f->f_iblock + min_delta_iblock; - if (new_lasti > f->f_lasti) { - /* Forwards jump. */ - new_iblock = f->f_iblock + delta_iblock; - } - else { - /* Backwards jump. */ - new_iblock = f->f_iblock - delta_iblock; - } - - /* Are we jumping into a block? */ - if (new_iblock > min_iblock) { - PyErr_SetString(PyExc_ValueError, - "can't jump into the middle of a block"); - return -1; - } - /* Pop any blocks that we're jumping out of. */ + new_iblock = f->f_iblock - delta_iblock; while (f->f_iblock > new_iblock) { PyTryBlock *b = &f->f_blockstack[--f->f_iblock]; while ((f->f_stacktop - f->f_valuestack) > b->b_level) { @@ -321,6 +266,12 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno) Py_DECREF(v); } } + /* Pop the iterators of any 'for' loop we're jumping out of. */ + while (for_loop_delta > 0) { + PyObject *v = (*--f->f_stacktop); + Py_DECREF(v); + for_loop_delta--; + } /* Finally set the new f_lineno and f_lasti and return OK. */ f->f_lineno = new_lineno; diff --git a/Objects/genobject.c b/Objects/genobject.c index 88b03c5ef313..9f593382f56a 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -822,18 +822,16 @@ PyGen_New(PyFrameObject *f) int PyGen_NeedsFinalizing(PyGenObject *gen) { - int i; PyFrameObject *f = gen->gi_frame; if (f == NULL || f->f_stacktop == NULL) return 0; /* no frame or empty blockstack == no finalization */ - /* Any block type besides a loop requires cleanup. */ - for (i = 0; i < f->f_iblock; i++) - if (f->f_blockstack[i].b_type != SETUP_LOOP) - return 1; + /* Any (exception-handling) block type requires cleanup. */ + if (f->f_iblock > 0) + return 1; - /* No blocks except loops, it's safe to skip finalization. */ + /* No blocks, it's safe to skip finalization. */ return 0; } diff --git a/PC/launcher.c b/PC/launcher.c index d717a7e3419a..d43eb92a1292 100644 --- a/PC/launcher.c +++ b/PC/launcher.c @@ -1116,6 +1116,7 @@ static PYC_MAGIC magic_values[] = { { 3320, 3351, L"3.5" }, { 3360, 3379, L"3.6" }, { 3390, 3399, L"3.7" }, + { 3400, 3409, L"3.8" }, { 0 } }; diff --git a/Python/ceval.c b/Python/ceval.c index af5eb99d6c90..1a72413c9e15 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -500,17 +500,6 @@ _Py_CheckRecursiveCall(const char *where) return 0; } -/* Status code for main loop (reason for stack unwind) */ -enum why_code { - WHY_NOT = 0x0001, /* No error */ - WHY_EXCEPTION = 0x0002, /* Exception occurred */ - WHY_RETURN = 0x0008, /* 'return' statement */ - WHY_BREAK = 0x0010, /* 'break' statement */ - WHY_CONTINUE = 0x0020, /* 'continue' statement */ - WHY_YIELD = 0x0040, /* 'yield' operator */ - WHY_SILENCED = 0x0080 /* Exception silenced by 'with' */ -}; - static int do_raise(PyObject *, PyObject *); static int unpack_iterable(PyObject *, int, int, PyObject **); @@ -556,7 +545,6 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) const _Py_CODEUNIT *next_instr; int opcode; /* Current opcode */ int oparg; /* Current opcode argument, if any */ - enum why_code why; /* Reason for block stack unwind */ PyObject **fastlocals, **freevars; PyObject *retval = NULL; /* Return value */ PyThreadState *tstate = PyThreadState_GET(); @@ -914,8 +902,6 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) lltrace = _PyDict_GetItemId(f->f_globals, &PyId___ltrace__) != NULL; #endif - why = WHY_NOT; - if (throwflag) /* support for generator.throw() */ goto error; @@ -926,6 +912,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) assert(!PyErr_Occurred()); #endif +main_loop: for (;;) { assert(stack_pointer >= f->f_valuestack); /* else underflow */ assert(STACK_LEVEL() <= co->co_stacksize); /* else overflow */ @@ -1056,9 +1043,8 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) switch (opcode) { /* BEWARE! - It is essential that any operation that fails sets either - x to NULL, err to nonzero, or why to anything but WHY_NOT, - and that no operation that succeeds does this! */ + It is essential that any operation that fails must goto error + and that all operation that succeed call [FAST_]DISPATCH() ! */ TARGET(NOP) FAST_DISPATCH(); @@ -1115,6 +1101,18 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) FAST_DISPATCH(); } + TARGET(ROT_FOUR) { + PyObject *top = TOP(); + PyObject *second = SECOND(); + PyObject *third = THIRD(); + PyObject *fourth = FOURTH(); + SET_TOP(second); + SET_SECOND(third); + SET_THIRD(fourth); + SET_FOURTH(top); + FAST_DISPATCH(); + } + TARGET(DUP_TOP) { PyObject *top = TOP(); Py_INCREF(top); @@ -1618,8 +1616,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) /* fall through */ case 0: if (do_raise(exc, cause)) { - why = WHY_EXCEPTION; - goto fast_block_end; + goto exception_unwind; } break; default: @@ -1632,8 +1629,8 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) TARGET(RETURN_VALUE) { retval = POP(); - why = WHY_RETURN; - goto fast_block_end; + assert(f->f_iblock == 0); + goto return_or_yield; } TARGET(GET_AITER) { @@ -1794,11 +1791,10 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) } /* receiver remains on stack, retval is value to be yielded */ f->f_stacktop = stack_pointer; - why = WHY_YIELD; /* and repeat... */ assert(f->f_lasti >= (int)sizeof(_Py_CODEUNIT)); f->f_lasti -= sizeof(_Py_CODEUNIT); - goto fast_yield; + goto return_or_yield; } TARGET(YIELD_VALUE) { @@ -1815,67 +1811,137 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) } f->f_stacktop = stack_pointer; - why = WHY_YIELD; - goto fast_yield; + goto return_or_yield; } TARGET(POP_EXCEPT) { + PyObject *type, *value, *traceback; + _PyErr_StackItem *exc_info; PyTryBlock *b = PyFrame_BlockPop(f); if (b->b_type != EXCEPT_HANDLER) { PyErr_SetString(PyExc_SystemError, "popped block is not an except handler"); goto error; } - UNWIND_EXCEPT_HANDLER(b); + assert(STACK_LEVEL() >= (b)->b_level + 3 && + STACK_LEVEL() <= (b)->b_level + 4); + exc_info = tstate->exc_info; + type = exc_info->exc_type; + value = exc_info->exc_value; + traceback = exc_info->exc_traceback; + exc_info->exc_type = POP(); + exc_info->exc_value = POP(); + exc_info->exc_traceback = POP(); + Py_XDECREF(type); + Py_XDECREF(value); + Py_XDECREF(traceback); DISPATCH(); } PREDICTED(POP_BLOCK); TARGET(POP_BLOCK) { - PyTryBlock *b = PyFrame_BlockPop(f); - UNWIND_BLOCK(b); + PyFrame_BlockPop(f); DISPATCH(); } + TARGET(POP_FINALLY) { + /* If oparg is 0 at the top of the stack are 1 or 6 values: + Either: + - TOP = NULL or an integer + or: + - (TOP, SECOND, THIRD) = exc_info() + - (FOURTH, FITH, SIXTH) = previous exception for EXCEPT_HANDLER + + If oparg is 1 the value for 'return' was additionally pushed + at the top of the stack. + */ + PyObject *res = NULL; + if (oparg) { + res = POP(); + } + PyObject *exc = POP(); + if (exc == NULL || PyLong_CheckExact(exc)) { + Py_XDECREF(exc); + } + else { + Py_DECREF(exc); + Py_DECREF(POP()); + Py_DECREF(POP()); + + PyObject *type, *value, *traceback; + _PyErr_StackItem *exc_info; + PyTryBlock *b = PyFrame_BlockPop(f); + if (b->b_type != EXCEPT_HANDLER) { + PyErr_SetString(PyExc_SystemError, + "popped block is not an except handler"); + Py_XDECREF(res); + goto error; + } + assert(STACK_LEVEL() == (b)->b_level + 3); + exc_info = tstate->exc_info; + type = exc_info->exc_type; + value = exc_info->exc_value; + traceback = exc_info->exc_traceback; + exc_info->exc_type = POP(); + exc_info->exc_value = POP(); + exc_info->exc_traceback = POP(); + Py_XDECREF(type); + Py_XDECREF(value); + Py_XDECREF(traceback); + } + if (oparg) { + PUSH(res); + } + DISPATCH(); + } + + TARGET(CALL_FINALLY) { + PyObject *ret = PyLong_FromLong(INSTR_OFFSET()); + if (ret == NULL) { + goto error; + } + PUSH(ret); + JUMPBY(oparg); + FAST_DISPATCH(); + } + + TARGET(BEGIN_FINALLY) { + /* Push NULL onto the stack for using it in END_FINALLY, + POP_FINALLY, WITH_CLEANUP_START and WITH_CLEANUP_FINISH. + */ + PUSH(NULL); + FAST_DISPATCH(); + } + PREDICTED(END_FINALLY); TARGET(END_FINALLY) { - PyObject *status = POP(); - if (PyLong_Check(status)) { - why = (enum why_code) PyLong_AS_LONG(status); - assert(why != WHY_YIELD && why != WHY_EXCEPTION); - if (why == WHY_RETURN || - why == WHY_CONTINUE) - retval = POP(); - if (why == WHY_SILENCED) { - /* An exception was silenced by 'with', we must - manually unwind the EXCEPT_HANDLER block which was - created when the exception was caught, otherwise - the stack will be in an inconsistent state. */ - PyTryBlock *b = PyFrame_BlockPop(f); - assert(b->b_type == EXCEPT_HANDLER); - UNWIND_EXCEPT_HANDLER(b); - why = WHY_NOT; - Py_DECREF(status); - DISPATCH(); + /* At the top of the stack are 1 or 6 values: + Either: + - TOP = NULL or an integer + or: + - (TOP, SECOND, THIRD) = exc_info() + - (FOURTH, FITH, SIXTH) = previous exception for EXCEPT_HANDLER + */ + PyObject *exc = POP(); + if (exc == NULL) { + FAST_DISPATCH(); + } + else if (PyLong_CheckExact(exc)) { + int ret = _PyLong_AsInt(exc); + Py_DECREF(exc); + if (ret == -1 && PyErr_Occurred()) { + goto error; } - Py_DECREF(status); - goto fast_block_end; + JUMPTO(ret); + FAST_DISPATCH(); } - else if (PyExceptionClass_Check(status)) { - PyObject *exc = POP(); + else { + assert(PyExceptionClass_Check(exc)); + PyObject *val = POP(); PyObject *tb = POP(); - PyErr_Restore(status, exc, tb); - why = WHY_EXCEPTION; - goto fast_block_end; - } - else if (status != Py_None) { - PyErr_SetString(PyExc_SystemError, - "'finally' pops bad exception"); - Py_DECREF(status); - goto error; + PyErr_Restore(exc, val, tb); + goto exception_unwind; } - Py_DECREF(status); - DISPATCH(); } TARGET(LOAD_BUILD_CLASS) { @@ -2815,28 +2881,13 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) DISPATCH(); } - TARGET(BREAK_LOOP) { - why = WHY_BREAK; - goto fast_block_end; - } - - TARGET(CONTINUE_LOOP) { - retval = PyLong_FromLong(oparg); - if (retval == NULL) - goto error; - why = WHY_CONTINUE; - goto fast_block_end; - } - - TARGET(SETUP_LOOP) - TARGET(SETUP_EXCEPT) TARGET(SETUP_FINALLY) { /* NOTE: If you add any new block-setup opcodes that are not try/except/finally handlers, you may need to update the PyGen_NeedsFinalizing() function. */ - PyFrame_BlockSetup(f, opcode, INSTR_OFFSET() + oparg, + PyFrame_BlockSetup(f, SETUP_FINALLY, INSTR_OFFSET() + oparg, STACK_LEVEL()); DISPATCH(); } @@ -2904,60 +2955,40 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) } TARGET(WITH_CLEANUP_START) { - /* At the top of the stack are 1-6 values indicating + /* At the top of the stack are 1 or 6 values indicating how/why we entered the finally clause: - - TOP = None - - (TOP, SECOND) = (WHY_{RETURN,CONTINUE}), retval - - TOP = WHY_*; no retval below it + - TOP = NULL - (TOP, SECOND, THIRD) = exc_info() (FOURTH, FITH, SIXTH) = previous exception for EXCEPT_HANDLER - Below them is EXIT, the context.__exit__ bound method. - In the last case, we must call - EXIT(TOP, SECOND, THIRD) - otherwise we must call + Below them is EXIT, the context.__exit__ or context.__aexit__ + bound method. + In the first case, we must call EXIT(None, None, None) + otherwise we must call + EXIT(TOP, SECOND, THIRD) - In the first three cases, we remove EXIT from the - stack, leaving the rest in the same order. In the - fourth case, we shift the bottom 3 values of the - stack down, and replace the empty spot with NULL. + In the first case, we remove EXIT from the + stack, leaving TOP, and push TOP on the stack. + Otherwise we shift the bottom 3 values of the + stack down, replace the empty spot with NULL, and push + None on the stack. - In addition, if the stack represents an exception, - *and* the function call returns a 'true' value, we - push WHY_SILENCED onto the stack. END_FINALLY will - then not re-raise the exception. (But non-local - gotos should still be resumed.) + Finally we push the result of the call. */ - - PyObject* stack[3]; + PyObject *stack[3]; PyObject *exit_func; PyObject *exc, *val, *tb, *res; val = tb = Py_None; exc = TOP(); - if (exc == Py_None) { - (void)POP(); + if (exc == NULL) { + STACKADJ(-1); exit_func = TOP(); SET_TOP(exc); - } - else if (PyLong_Check(exc)) { - STACKADJ(-1); - switch (PyLong_AsLong(exc)) { - case WHY_RETURN: - case WHY_CONTINUE: - /* Retval in TOP. */ - exit_func = SECOND(); - SET_SECOND(TOP()); - SET_TOP(exc); - break; - default: - exit_func = TOP(); - SET_TOP(exc); - break; - } exc = Py_None; } else { + assert(PyExceptionClass_Check(exc)); PyObject *tp2, *exc2, *tb2; PyTryBlock *block; val = SECOND(); @@ -2974,8 +3005,10 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) /* We just shifted the stack down, so we have to tell the except handler block that the values are lower than it expects. */ + assert(f->f_iblock > 0); block = &f->f_blockstack[f->f_iblock - 1]; assert(block->b_type == EXCEPT_HANDLER); + assert(block->b_level > 0); block->b_level--; } @@ -2996,6 +3029,12 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) PREDICTED(WITH_CLEANUP_FINISH); TARGET(WITH_CLEANUP_FINISH) { + /* TOP = the result of calling the context.__exit__ bound method + SECOND = either None or exception type + + If SECOND is None below is NULL or the return address, + otherwise below are 7 values representing an exception. + */ PyObject *res = POP(); PyObject *exc = POP(); int err; @@ -3011,8 +3050,15 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) if (err < 0) goto error; else if (err > 0) { - /* There was an exception and a True return */ - PUSH(PyLong_FromLong((long) WHY_SILENCED)); + /* There was an exception and a True return. + * We must manually unwind the EXCEPT_HANDLER block + * which was created when the exception was caught, + * otherwise the stack will be in an inconsisten state. + */ + PyTryBlock *b = PyFrame_BlockPop(f); + assert(b->b_type == EXCEPT_HANDLER); + UNWIND_EXCEPT_HANDLER(b); + PUSH(NULL); } PREDICT(END_FINALLY); DISPATCH(); @@ -3322,10 +3368,6 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) Py_UNREACHABLE(); error: - - assert(why == WHY_NOT); - why = WHY_EXCEPTION; - /* Double-check exception status. */ #ifdef NDEBUG if (!PyErr_Occurred()) @@ -3342,36 +3384,18 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) call_exc_trace(tstate->c_tracefunc, tstate->c_traceobj, tstate, f); -fast_block_end: - assert(why != WHY_NOT); - - /* Unwind stacks if a (pseudo) exception occurred */ - while (why != WHY_NOT && f->f_iblock > 0) { - /* Peek at the current block. */ - PyTryBlock *b = &f->f_blockstack[f->f_iblock - 1]; - - assert(why != WHY_YIELD); - if (b->b_type == SETUP_LOOP && why == WHY_CONTINUE) { - why = WHY_NOT; - JUMPTO(PyLong_AS_LONG(retval)); - Py_DECREF(retval); - break; - } - /* Now we have to pop the block. */ - f->f_iblock--; +exception_unwind: + /* Unwind stacks if an exception occurred */ + while (f->f_iblock > 0) { + /* Pop the current block. */ + PyTryBlock *b = &f->f_blockstack[--f->f_iblock]; if (b->b_type == EXCEPT_HANDLER) { UNWIND_EXCEPT_HANDLER(b); continue; } UNWIND_BLOCK(b); - if (b->b_type == SETUP_LOOP && why == WHY_BREAK) { - why = WHY_NOT; - JUMPTO(b->b_handler); - break; - } - if (why == WHY_EXCEPTION && (b->b_type == SETUP_EXCEPT - || b->b_type == SETUP_FINALLY)) { + if (b->b_type == SETUP_FINALLY) { PyObject *exc, *val, *tb; int handler = b->b_handler; _PyErr_StackItem *exc_info = tstate->exc_info; @@ -3408,70 +3432,37 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag) PUSH(tb); PUSH(val); PUSH(exc); - why = WHY_NOT; JUMPTO(handler); - break; - } - if (b->b_type == SETUP_FINALLY) { - if (why & (WHY_RETURN | WHY_CONTINUE)) - PUSH(retval); - PUSH(PyLong_FromLong((long)why)); - why = WHY_NOT; - JUMPTO(b->b_handler); - break; + /* Resume normal execution */ + goto main_loop; } } /* unwind stack */ - /* End the loop if we still have an error (or return) */ - - if (why != WHY_NOT) - break; - - assert(!PyErr_Occurred()); - + /* End the loop as we still have an error */ + break; } /* main loop */ - assert(why != WHY_YIELD); /* Pop remaining stack entries. */ while (!EMPTY()) { PyObject *o = POP(); Py_XDECREF(o); } - if (why != WHY_RETURN) - retval = NULL; - - assert((retval != NULL) ^ (PyErr_Occurred() != NULL)); - -fast_yield: + assert(retval == NULL); + assert(PyErr_Occurred()); +return_or_yield: if (tstate->use_tracing) { if (tstate->c_tracefunc) { - if (why == WHY_RETURN || why == WHY_YIELD) { - if (call_trace(tstate->c_tracefunc, tstate->c_traceobj, - tstate, f, - PyTrace_RETURN, retval)) { - Py_CLEAR(retval); - why = WHY_EXCEPTION; - } - } - else if (why == WHY_EXCEPTION) { - call_trace_protected(tstate->c_tracefunc, tstate->c_traceobj, - tstate, f, - PyTrace_RETURN, NULL); + if (call_trace_protected(tstate->c_tracefunc, tstate->c_traceobj, + tstate, f, PyTrace_RETURN, retval)) { + Py_CLEAR(retval); } } if (tstate->c_profilefunc) { - if (why == WHY_EXCEPTION) - call_trace_protected(tstate->c_profilefunc, - tstate->c_profileobj, - tstate, f, - PyTrace_RETURN, NULL); - else if (call_trace(tstate->c_profilefunc, tstate->c_profileobj, - tstate, f, - PyTrace_RETURN, retval)) { + if (call_trace_protected(tstate->c_profilefunc, tstate->c_profileobj, + tstate, f, PyTrace_RETURN, retval)) { Py_CLEAR(retval); - /* why = WHY_EXCEPTION; useless yet but cause compiler warnings */ } } } diff --git a/Python/compile.c b/Python/compile.c index 0dc35662749b..f14647b4f641 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -81,11 +81,14 @@ It's called a frame block to distinguish it from a basic block in the compiler IR. */ -enum fblocktype { LOOP, EXCEPT, FINALLY_TRY, FINALLY_END }; +enum fblocktype { WHILE_LOOP, FOR_LOOP, EXCEPT, FINALLY_TRY, FINALLY_END, + WITH, ASYNC_WITH, HANDLER_CLEANUP }; struct fblockinfo { enum fblocktype fb_type; basicblock *fb_block; + /* (optional) type-specific exit or cleanup block */ + basicblock *fb_exit; }; enum { @@ -183,13 +186,6 @@ static int compiler_annassign(struct compiler *, stmt_ty); static int compiler_visit_slice(struct compiler *, slice_ty, expr_context_ty); -static int compiler_push_fblock(struct compiler *, enum fblocktype, - basicblock *); -static void compiler_pop_fblock(struct compiler *, enum fblocktype, - basicblock *); -/* Returns true if there is a loop on the fblock stack. */ -static int compiler_in_loop(struct compiler *); - static int inplace_binop(struct compiler *, operator_ty); static int expr_constant(expr_ty); @@ -846,7 +842,7 @@ compiler_next_instr(struct compiler *c, basicblock *b) - when entering a new scope - on each statement - on each expression that start a new line - - before the "except" clause + - before the "except" and "finally" clauses - before the "for" and "while" expressions */ @@ -881,6 +877,7 @@ stack_effect(int opcode, int oparg, int jump) return -1; case ROT_TWO: case ROT_THREE: + case ROT_FOUR: return 0; case DUP_TOP: return 1; @@ -947,8 +944,7 @@ stack_effect(int opcode, int oparg, int jump) case INPLACE_XOR: case INPLACE_OR: return -1; - case BREAK_LOOP: - return 0; + case SETUP_WITH: /* 1 in the normal flow. * Restore the stack position and push 6 values before jumping to @@ -975,6 +971,7 @@ stack_effect(int opcode, int oparg, int jump) case POP_EXCEPT: return -3; case END_FINALLY: + case POP_FINALLY: /* Pop 6 values when an exception was raised. */ return -6; @@ -1043,16 +1040,20 @@ stack_effect(int opcode, int oparg, int jump) case LOAD_GLOBAL: return 1; - case CONTINUE_LOOP: - return 0; - case SETUP_LOOP: - return 0; - case SETUP_EXCEPT: + /* Exception handling */ case SETUP_FINALLY: /* 0 in the normal flow. * Restore the stack position and push 6 values before jumping to * the handler if an exception be raised. */ return jump ? 6 : 0; + case BEGIN_FINALLY: + /* Actually pushes 1 value, but count 6 for balancing with + * END_FINALLY and POP_FINALLY. + * This is the main reason of using this opcode instead of + * "LOAD_CONST None". */ + return 6; + case CALL_FINALLY: + return jump ? 1 : 0; case LOAD_FAST: return 1; @@ -1458,6 +1459,103 @@ find_ann(asdl_seq *stmts) return res; } +/* + * Frame block handling functions + */ + +static int +compiler_push_fblock(struct compiler *c, enum fblocktype t, basicblock *b, + basicblock *exit) +{ + struct fblockinfo *f; + if (c->u->u_nfblocks >= CO_MAXBLOCKS) { + PyErr_SetString(PyExc_SyntaxError, + "too many statically nested blocks"); + return 0; + } + f = &c->u->u_fblock[c->u->u_nfblocks++]; + f->fb_type = t; + f->fb_block = b; + f->fb_exit = exit; + return 1; +} + +static void +compiler_pop_fblock(struct compiler *c, enum fblocktype t, basicblock *b) +{ + struct compiler_unit *u = c->u; + assert(u->u_nfblocks > 0); + u->u_nfblocks--; + assert(u->u_fblock[u->u_nfblocks].fb_type == t); + assert(u->u_fblock[u->u_nfblocks].fb_block == b); +} + +/* Unwind a frame block. If preserve_tos is true, the TOS before + * popping the blocks will be restored afterwards. + */ +static int +compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info, + int preserve_tos) +{ + switch (info->fb_type) { + case WHILE_LOOP: + return 1; + + case FINALLY_END: + ADDOP_I(c, POP_FINALLY, preserve_tos); + return 1; + + case FOR_LOOP: + /* Pop the iterator */ + if (preserve_tos) { + ADDOP(c, ROT_TWO); + } + ADDOP(c, POP_TOP); + return 1; + + case EXCEPT: + ADDOP(c, POP_BLOCK); + return 1; + + case FINALLY_TRY: + ADDOP(c, POP_BLOCK); + ADDOP_JREL(c, CALL_FINALLY, info->fb_exit); + return 1; + + case WITH: + case ASYNC_WITH: + ADDOP(c, POP_BLOCK); + if (preserve_tos) { + ADDOP(c, ROT_TWO); + } + ADDOP(c, BEGIN_FINALLY); + ADDOP(c, WITH_CLEANUP_START); + if (info->fb_type == ASYNC_WITH) { + ADDOP(c, GET_AWAITABLE); + ADDOP_O(c, LOAD_CONST, Py_None, consts); + ADDOP(c, YIELD_FROM); + } + ADDOP(c, WITH_CLEANUP_FINISH); + ADDOP_I(c, POP_FINALLY, 0); + return 1; + + case HANDLER_CLEANUP: + if (preserve_tos) { + ADDOP(c, ROT_FOUR); + } + if (info->fb_exit) { + ADDOP(c, POP_BLOCK); + ADDOP(c, POP_EXCEPT); + ADDOP_JREL(c, CALL_FINALLY, info->fb_exit); + } + else { + ADDOP(c, POP_EXCEPT); + } + return 1; + } + Py_UNREACHABLE(); +} + /* Compile a sequence of statements, checking for a docstring and for annotations. */ @@ -2312,9 +2410,10 @@ compiler_for(struct compiler *c, stmt_ty s) end = compiler_new_block(c); if (start == NULL || end == NULL || cleanup == NULL) return 0; - ADDOP_JREL(c, SETUP_LOOP, end); - if (!compiler_push_fblock(c, LOOP, start)) + + if (!compiler_push_fblock(c, FOR_LOOP, start, end)) return 0; + VISIT(c, expr, s->v.For.iter); ADDOP(c, GET_ITER); compiler_use_next_block(c, start); @@ -2323,8 +2422,9 @@ compiler_for(struct compiler *c, stmt_ty s) VISIT_SEQ(c, stmt, s->v.For.body); ADDOP_JABS(c, JUMP_ABSOLUTE, start); compiler_use_next_block(c, cleanup); - ADDOP(c, POP_BLOCK); - compiler_pop_fblock(c, LOOP, start); + + compiler_pop_fblock(c, FOR_LOOP, start); + VISIT_SEQ(c, stmt, s->v.For.orelse); compiler_use_next_block(c, end); return 1; @@ -2356,8 +2456,7 @@ compiler_async_for(struct compiler *c, stmt_ty s) || after_try == NULL || try_cleanup == NULL) return 0; - ADDOP_JREL(c, SETUP_LOOP, after_loop); - if (!compiler_push_fblock(c, LOOP, try)) + if (!compiler_push_fblock(c, FOR_LOOP, try, after_loop)) return 0; VISIT(c, expr, s->v.AsyncFor.iter); @@ -2366,19 +2465,21 @@ compiler_async_for(struct compiler *c, stmt_ty s) compiler_use_next_block(c, try); - ADDOP_JREL(c, SETUP_EXCEPT, except); - if (!compiler_push_fblock(c, EXCEPT, try)) + /* SETUP_FINALLY to guard the __anext__ call */ + ADDOP_JREL(c, SETUP_FINALLY, except); + if (!compiler_push_fblock(c, EXCEPT, try, NULL)) return 0; ADDOP(c, GET_ANEXT); ADDOP_O(c, LOAD_CONST, Py_None, consts); ADDOP(c, YIELD_FROM); VISIT(c, expr, s->v.AsyncFor.target); - ADDOP(c, POP_BLOCK); + ADDOP(c, POP_BLOCK); /* for SETUP_FINALLY */ compiler_pop_fblock(c, EXCEPT, try); ADDOP_JREL(c, JUMP_FORWARD, after_try); + /* Except block for __anext__ */ compiler_use_next_block(c, except); ADDOP(c, DUP_TOP); ADDOP_O(c, LOAD_GLOBAL, stop_aiter_error, names); @@ -2388,25 +2489,26 @@ compiler_async_for(struct compiler *c, stmt_ty s) ADDOP(c, POP_TOP); ADDOP(c, POP_TOP); ADDOP(c, POP_TOP); - ADDOP(c, POP_EXCEPT); /* for SETUP_EXCEPT */ - ADDOP(c, POP_TOP); /* for correct calculation of stack effect */ - ADDOP(c, POP_BLOCK); /* for SETUP_LOOP */ + ADDOP(c, POP_EXCEPT); /* for SETUP_FINALLY */ + ADDOP(c, POP_TOP); /* pop iterator from stack */ ADDOP_JABS(c, JUMP_ABSOLUTE, after_loop_else); compiler_use_next_block(c, try_cleanup); ADDOP(c, END_FINALLY); + /* Success block for __anext__ */ compiler_use_next_block(c, after_try); VISIT_SEQ(c, stmt, s->v.AsyncFor.body); ADDOP_JABS(c, JUMP_ABSOLUTE, try); - ADDOP(c, POP_BLOCK); /* for SETUP_LOOP */ - compiler_pop_fblock(c, LOOP, try); + compiler_pop_fblock(c, FOR_LOOP, try); + /* Block reached after `break`ing from loop */ compiler_use_next_block(c, after_loop); ADDOP_JABS(c, JUMP_ABSOLUTE, end); + /* `else` block */ compiler_use_next_block(c, after_loop_else); VISIT_SEQ(c, stmt, s->v.For.orelse); @@ -2443,9 +2545,8 @@ compiler_while(struct compiler *c, stmt_ty s) else orelse = NULL; - ADDOP_JREL(c, SETUP_LOOP, end); compiler_use_next_block(c, loop); - if (!compiler_push_fblock(c, LOOP, loop)) + if (!compiler_push_fblock(c, WHILE_LOOP, loop, end)) return 0; if (constant == -1) { if (!compiler_jump_if(c, s->v.While.test, anchor, 0)) @@ -2460,8 +2561,8 @@ compiler_while(struct compiler *c, stmt_ty s) if (constant == -1) compiler_use_next_block(c, anchor); - ADDOP(c, POP_BLOCK); - compiler_pop_fblock(c, LOOP, loop); + compiler_pop_fblock(c, WHILE_LOOP, loop); + if (orelse != NULL) /* what if orelse is just pass? */ VISIT_SEQ(c, stmt, s->v.While.orelse); compiler_use_next_block(c, end); @@ -2470,46 +2571,83 @@ compiler_while(struct compiler *c, stmt_ty s) } static int -compiler_continue(struct compiler *c) +compiler_return(struct compiler *c, stmt_ty s) { - static const char LOOP_ERROR_MSG[] = "'continue' not properly in loop"; - static const char IN_FINALLY_ERROR_MSG[] = - "'continue' not supported inside 'finally' clause"; - int i; + int preserve_tos = ((s->v.Return.value != NULL) && + !is_const(s->v.Return.value)); + if (c->u->u_ste->ste_type != FunctionBlock) + return compiler_error(c, "'return' outside function"); + if (s->v.Return.value != NULL && + c->u->u_ste->ste_coroutine && c->u->u_ste->ste_generator) + { + return compiler_error( + c, "'return' with value in async generator"); + } + if (preserve_tos) { + VISIT(c, expr, s->v.Return.value); + } + for (int depth = c->u->u_nfblocks; depth--;) { + struct fblockinfo *info = &c->u->u_fblock[depth]; - if (!c->u->u_nfblocks) - return compiler_error(c, LOOP_ERROR_MSG); - i = c->u->u_nfblocks - 1; - switch (c->u->u_fblock[i].fb_type) { - case LOOP: - ADDOP_JABS(c, JUMP_ABSOLUTE, c->u->u_fblock[i].fb_block); - break; - case EXCEPT: - case FINALLY_TRY: - while (--i >= 0 && c->u->u_fblock[i].fb_type != LOOP) { - /* Prevent continue anywhere under a finally - even if hidden in a sub-try or except. */ - if (c->u->u_fblock[i].fb_type == FINALLY_END) - return compiler_error(c, IN_FINALLY_ERROR_MSG); - } - if (i == -1) - return compiler_error(c, LOOP_ERROR_MSG); - ADDOP_JABS(c, CONTINUE_LOOP, c->u->u_fblock[i].fb_block); - break; - case FINALLY_END: - return compiler_error(c, IN_FINALLY_ERROR_MSG); + if (!compiler_unwind_fblock(c, info, preserve_tos)) + return 0; + } + if (s->v.Return.value == NULL) { + ADDOP_O(c, LOAD_CONST, Py_None, consts); + } + else if (!preserve_tos) { + VISIT(c, expr, s->v.Return.value); } + ADDOP(c, RETURN_VALUE); return 1; } +static int +compiler_break(struct compiler *c) +{ + for (int depth = c->u->u_nfblocks; depth--;) { + struct fblockinfo *info = &c->u->u_fblock[depth]; + + if (!compiler_unwind_fblock(c, info, 0)) + return 0; + if (info->fb_type == WHILE_LOOP || info->fb_type == FOR_LOOP) { + ADDOP_JABS(c, JUMP_ABSOLUTE, info->fb_exit); + return 1; + } + } + return compiler_error(c, "'break' outside loop"); +} + +static int +compiler_continue(struct compiler *c) +{ + for (int depth = c->u->u_nfblocks; depth--;) { + struct fblockinfo *info = &c->u->u_fblock[depth]; + + if (info->fb_type == WHILE_LOOP || info->fb_type == FOR_LOOP) { + ADDOP_JABS(c, JUMP_ABSOLUTE, info->fb_block); + return 1; + } + if (info->fb_type == FINALLY_END) { + return compiler_error(c, + "'continue' not supported inside 'finally' clause"); + } + if (!compiler_unwind_fblock(c, info, 0)) + return 0; + } + return compiler_error(c, "'continue' not properly in loop"); +} + + /* Code generated for "try: finally: " is as follows: SETUP_FINALLY L POP_BLOCK - LOAD_CONST - L: + BEGIN_FINALLY + L: + END_FINALLY The special instructions use the block stack. Each block @@ -2521,33 +2659,34 @@ compiler_continue(struct compiler *c) Pushes the current value stack level and the label onto the block stack. POP_BLOCK: - Pops en entry from the block stack, and pops the value - stack until its level is the same as indicated on the - block stack. (The label is ignored.) + Pops en entry from the block stack. + BEGIN_FINALLY + Pushes NULL onto the value stack. END_FINALLY: - Pops a variable number of entries from the *value* stack - and re-raises the exception they specify. The number of - entries popped depends on the (pseudo) exception type. + Pops 1 (NULL or int) or 6 entries from the *value* stack and restore + the raised and the caught exceptions they specify. The block stack is unwound when an exception is raised: - when a SETUP_FINALLY entry is found, the exception is pushed - onto the value stack (and the exception condition is cleared), - and the interpreter jumps to the label gotten from the block - stack. + when a SETUP_FINALLY entry is found, the raised and the caught + exceptions are pushed onto the value stack (and the exception + condition is cleared), and the interpreter jumps to the label + gotten from the block stack. */ static int compiler_try_finally(struct compiler *c, stmt_ty s) { basicblock *body, *end; + body = compiler_new_block(c); end = compiler_new_block(c); if (body == NULL || end == NULL) return 0; + /* `try` block */ ADDOP_JREL(c, SETUP_FINALLY, end); compiler_use_next_block(c, body); - if (!compiler_push_fblock(c, FINALLY_TRY, body)) + if (!compiler_push_fblock(c, FINALLY_TRY, body, end)) return 0; if (s->v.Try.handlers && asdl_seq_LEN(s->v.Try.handlers)) { if (!compiler_try_except(c, s)) @@ -2557,16 +2696,16 @@ compiler_try_finally(struct compiler *c, stmt_ty s) VISIT_SEQ(c, stmt, s->v.Try.body); } ADDOP(c, POP_BLOCK); + ADDOP(c, BEGIN_FINALLY); compiler_pop_fblock(c, FINALLY_TRY, body); - ADDOP_O(c, LOAD_CONST, Py_None, consts); + /* `finally` block */ compiler_use_next_block(c, end); - if (!compiler_push_fblock(c, FINALLY_END, end)) + if (!compiler_push_fblock(c, FINALLY_END, end, NULL)) return 0; VISIT_SEQ(c, stmt, s->v.Try.finalbody); ADDOP(c, END_FINALLY); compiler_pop_fblock(c, FINALLY_END, end); - return 1; } @@ -2577,7 +2716,7 @@ compiler_try_finally(struct compiler *c, stmt_ty s) associated value, and 'exc' the exception.) Value stack Label Instruction Argument - [] SETUP_EXCEPT L1 + [] SETUP_FINALLY L1 [] [] POP_BLOCK [] JUMP_FORWARD L0 @@ -2613,9 +2752,9 @@ compiler_try_except(struct compiler *c, stmt_ty s) end = compiler_new_block(c); if (body == NULL || except == NULL || orelse == NULL || end == NULL) return 0; - ADDOP_JREL(c, SETUP_EXCEPT, except); + ADDOP_JREL(c, SETUP_FINALLY, except); compiler_use_next_block(c, body); - if (!compiler_push_fblock(c, EXCEPT, body)) + if (!compiler_push_fblock(c, EXCEPT, body, NULL)) return 0; VISIT_SEQ(c, stmt, s->v.Try.body); ADDOP(c, POP_BLOCK); @@ -2666,25 +2805,23 @@ compiler_try_except(struct compiler *c, stmt_ty s) /* second try: */ ADDOP_JREL(c, SETUP_FINALLY, cleanup_end); compiler_use_next_block(c, cleanup_body); - if (!compiler_push_fblock(c, FINALLY_TRY, cleanup_body)) + if (!compiler_push_fblock(c, HANDLER_CLEANUP, cleanup_body, cleanup_end)) return 0; /* second # body */ VISIT_SEQ(c, stmt, handler->v.ExceptHandler.body); ADDOP(c, POP_BLOCK); - compiler_pop_fblock(c, FINALLY_TRY, cleanup_body); + ADDOP(c, BEGIN_FINALLY); + compiler_pop_fblock(c, HANDLER_CLEANUP, cleanup_body); /* finally: */ - ADDOP_O(c, LOAD_CONST, Py_None, consts); compiler_use_next_block(c, cleanup_end); - if (!compiler_push_fblock(c, FINALLY_END, cleanup_end)) + if (!compiler_push_fblock(c, FINALLY_END, cleanup_end, NULL)) return 0; - /* name = None */ + /* name = None; del name */ ADDOP_O(c, LOAD_CONST, Py_None, consts); compiler_nameop(c, handler->v.ExceptHandler.name, Store); - - /* del name */ compiler_nameop(c, handler->v.ExceptHandler.name, Del); ADDOP(c, END_FINALLY); @@ -2701,11 +2838,11 @@ compiler_try_except(struct compiler *c, stmt_ty s) ADDOP(c, POP_TOP); ADDOP(c, POP_TOP); compiler_use_next_block(c, cleanup_body); - if (!compiler_push_fblock(c, FINALLY_TRY, cleanup_body)) + if (!compiler_push_fblock(c, HANDLER_CLEANUP, cleanup_body, NULL)) return 0; VISIT_SEQ(c, stmt, handler->v.ExceptHandler.body); ADDOP(c, POP_EXCEPT); - compiler_pop_fblock(c, FINALLY_TRY, cleanup_body); + compiler_pop_fblock(c, HANDLER_CLEANUP, cleanup_body); } ADDOP_JREL(c, JUMP_FORWARD, end); compiler_use_next_block(c, except); @@ -2964,18 +3101,7 @@ compiler_visit_stmt(struct compiler *c, stmt_ty s) case ClassDef_kind: return compiler_class(c, s); case Return_kind: - if (c->u->u_ste->ste_type != FunctionBlock) - return compiler_error(c, "'return' outside function"); - if (s->v.Return.value) { - if (c->u->u_ste->ste_coroutine && c->u->u_ste->ste_generator) - return compiler_error( - c, "'return' with value in async generator"); - VISIT(c, expr, s->v.Return.value); - } - else - ADDOP_O(c, LOAD_CONST, Py_None, consts); - ADDOP(c, RETURN_VALUE); - break; + return compiler_return(c, s); case Delete_kind: VISIT_SEQ(c, expr, s->v.Delete.targets) break; @@ -3027,10 +3153,7 @@ compiler_visit_stmt(struct compiler *c, stmt_ty s) case Pass_kind: break; case Break_kind: - if (!compiler_in_loop(c)) - return compiler_error(c, "'break' outside loop"); - ADDOP(c, BREAK_LOOP); - break; + return compiler_break(c); case Continue_kind: return compiler_continue(c); case With_kind: @@ -3771,8 +3894,6 @@ compiler_call_helper(struct compiler *c, The LC/SC version returns the populated container, while the GE version is flagged in symtable.c as a generator, so it returns the generator object when the function is called. - This code *knows* that the loop cannot contain break, continue, or return, - so it cheats and skips the SETUP_LOOP/POP_BLOCK steps used in normal loops. Possible cleanups: - iterate over the generator sequence instead of using recursion @@ -3932,8 +4053,8 @@ compiler_async_comprehension_generator(struct compiler *c, compiler_use_next_block(c, try); - ADDOP_JREL(c, SETUP_EXCEPT, except); - if (!compiler_push_fblock(c, EXCEPT, try)) + ADDOP_JREL(c, SETUP_FINALLY, except); + if (!compiler_push_fblock(c, EXCEPT, try, NULL)) return 0; ADDOP(c, GET_ANEXT); @@ -3954,7 +4075,7 @@ compiler_async_comprehension_generator(struct compiler *c, ADDOP(c, POP_TOP); ADDOP(c, POP_TOP); ADDOP(c, POP_TOP); - ADDOP(c, POP_EXCEPT); /* for SETUP_EXCEPT */ + ADDOP(c, POP_EXCEPT); /* for SETUP_FINALLY */ ADDOP_JABS(c, JUMP_ABSOLUTE, anchor); @@ -4246,7 +4367,7 @@ compiler_async_with(struct compiler *c, stmt_ty s, int pos) /* SETUP_ASYNC_WITH pushes a finally block. */ compiler_use_next_block(c, block); - if (!compiler_push_fblock(c, FINALLY_TRY, block)) { + if (!compiler_push_fblock(c, ASYNC_WITH, block, finally)) { return 0; } @@ -4267,11 +4388,11 @@ compiler_async_with(struct compiler *c, stmt_ty s, int pos) /* End of try block; start the finally block */ ADDOP(c, POP_BLOCK); - compiler_pop_fblock(c, FINALLY_TRY, block); + ADDOP(c, BEGIN_FINALLY); + compiler_pop_fblock(c, ASYNC_WITH, block); - ADDOP_O(c, LOAD_CONST, Py_None, consts); compiler_use_next_block(c, finally); - if (!compiler_push_fblock(c, FINALLY_END, finally)) + if (!compiler_push_fblock(c, FINALLY_END, finally, NULL)) return 0; /* Finally block starts; context.__exit__ is on the stack under @@ -4334,7 +4455,7 @@ compiler_with(struct compiler *c, stmt_ty s, int pos) /* SETUP_WITH pushes a finally block. */ compiler_use_next_block(c, block); - if (!compiler_push_fblock(c, FINALLY_TRY, block)) { + if (!compiler_push_fblock(c, WITH, block, finally)) { return 0; } @@ -4355,11 +4476,11 @@ compiler_with(struct compiler *c, stmt_ty s, int pos) /* End of try block; start the finally block */ ADDOP(c, POP_BLOCK); - compiler_pop_fblock(c, FINALLY_TRY, block); + ADDOP(c, BEGIN_FINALLY); + compiler_pop_fblock(c, WITH, block); - ADDOP_O(c, LOAD_CONST, Py_None, consts); compiler_use_next_block(c, finally); - if (!compiler_push_fblock(c, FINALLY_END, finally)) + if (!compiler_push_fblock(c, FINALLY_END, finally, NULL)) return 0; /* Finally block starts; context.__exit__ is on the stack under @@ -4745,41 +4866,6 @@ compiler_annassign(struct compiler *c, stmt_ty s) return 1; } -static int -compiler_push_fblock(struct compiler *c, enum fblocktype t, basicblock *b) -{ - struct fblockinfo *f; - if (c->u->u_nfblocks >= CO_MAXBLOCKS) { - PyErr_SetString(PyExc_SyntaxError, - "too many statically nested blocks"); - return 0; - } - f = &c->u->u_fblock[c->u->u_nfblocks++]; - f->fb_type = t; - f->fb_block = b; - return 1; -} - -static void -compiler_pop_fblock(struct compiler *c, enum fblocktype t, basicblock *b) -{ - struct compiler_unit *u = c->u; - assert(u->u_nfblocks > 0); - u->u_nfblocks--; - assert(u->u_fblock[u->u_nfblocks].fb_type == t); - assert(u->u_fblock[u->u_nfblocks].fb_block == b); -} - -static int -compiler_in_loop(struct compiler *c) { - int i; - struct compiler_unit *u = c->u; - for (i = 0; i < u->u_nfblocks; ++i) { - if (u->u_fblock[i].fb_type == LOOP) - return 1; - } - return 0; -} /* Raises a SyntaxError and returns 0. If something goes wrong, a different exception may be raised. */ @@ -4974,9 +5060,7 @@ dfs(struct compiler *c, basicblock *b, struct assembler *a, int end) Py_LOCAL_INLINE(void) stackdepth_push(basicblock ***sp, basicblock *b, int depth) { - /* XXX b->b_startdepth > depth only for the target of SETUP_FINALLY, - * SETUP_WITH and SETUP_ASYNC_WITH. */ - assert(b->b_startdepth < 0 || b->b_startdepth >= depth); + assert(b->b_startdepth < 0 || b->b_startdepth == depth); if (b->b_startdepth < depth) { assert(b->b_startdepth < 0); b->b_startdepth = depth; @@ -5033,15 +5117,11 @@ stackdepth(struct compiler *c) maxdepth = target_depth; } assert(target_depth >= 0); /* invalid code or bug in stackdepth() */ - if (instr->i_opcode == CONTINUE_LOOP) { - /* Pops a variable number of values from the stack, - * but the target should be already proceeding. - */ + if (instr->i_opcode == CALL_FINALLY) { assert(instr->i_target->b_startdepth >= 0); - assert(instr->i_target->b_startdepth <= depth); - /* remaining code is dead */ - next = NULL; - break; + assert(instr->i_target->b_startdepth >= target_depth); + depth = new_depth; + continue; } stackdepth_push(&sp, instr->i_target, target_depth); } @@ -5049,8 +5129,7 @@ stackdepth(struct compiler *c) if (instr->i_opcode == JUMP_ABSOLUTE || instr->i_opcode == JUMP_FORWARD || instr->i_opcode == RETURN_VALUE || - instr->i_opcode == RAISE_VARARGS || - instr->i_opcode == BREAK_LOOP) + instr->i_opcode == RAISE_VARARGS) { /* remaining code is dead */ next = NULL; diff --git a/Python/importlib.h b/Python/importlib.h index 822ffa0c067e..83c5dd5d650e 100644 --- a/Python/importlib.h +++ b/Python/importlib.h @@ -53,97 +53,97 @@ const unsigned char _Py_M__importlib[] = { 108,105,99,45,102,97,99,105,110,103,32,118,101,114,115,105, 111,110,32,111,102,32,116,104,105,115,32,109,111,100,117,108, 101,46,10,10,78,99,2,0,0,0,0,0,0,0,3,0, - 0,0,7,0,0,0,67,0,0,0,115,60,0,0,0,120, - 40,100,1,68,0,93,32,125,2,116,0,124,1,124,2,131, - 2,114,6,116,1,124,0,124,2,116,2,124,1,124,2,131, - 2,131,3,1,0,113,6,87,0,124,0,106,3,160,4,124, - 1,106,3,161,1,1,0,100,2,83,0,41,3,122,47,83, - 105,109,112,108,101,32,115,117,98,115,116,105,116,117,116,101, - 32,102,111,114,32,102,117,110,99,116,111,111,108,115,46,117, - 112,100,97,116,101,95,119,114,97,112,112,101,114,46,41,4, - 218,10,95,95,109,111,100,117,108,101,95,95,218,8,95,95, - 110,97,109,101,95,95,218,12,95,95,113,117,97,108,110,97, - 109,101,95,95,218,7,95,95,100,111,99,95,95,78,41,5, - 218,7,104,97,115,97,116,116,114,218,7,115,101,116,97,116, - 116,114,218,7,103,101,116,97,116,116,114,218,8,95,95,100, - 105,99,116,95,95,218,6,117,112,100,97,116,101,41,3,90, - 3,110,101,119,90,3,111,108,100,218,7,114,101,112,108,97, - 99,101,169,0,114,10,0,0,0,250,29,60,102,114,111,122, - 101,110,32,105,109,112,111,114,116,108,105,98,46,95,98,111, - 111,116,115,116,114,97,112,62,218,5,95,119,114,97,112,27, - 0,0,0,115,8,0,0,0,0,2,10,1,10,1,22,1, - 114,12,0,0,0,99,1,0,0,0,0,0,0,0,1,0, - 0,0,2,0,0,0,67,0,0,0,115,12,0,0,0,116, - 0,116,1,131,1,124,0,131,1,83,0,41,1,78,41,2, - 218,4,116,121,112,101,218,3,115,121,115,41,1,218,4,110, - 97,109,101,114,10,0,0,0,114,10,0,0,0,114,11,0, - 0,0,218,11,95,110,101,119,95,109,111,100,117,108,101,35, - 0,0,0,115,2,0,0,0,0,1,114,16,0,0,0,99, - 0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0, - 64,0,0,0,115,12,0,0,0,101,0,90,1,100,0,90, - 2,100,1,83,0,41,2,218,14,95,68,101,97,100,108,111, - 99,107,69,114,114,111,114,78,41,3,114,1,0,0,0,114, - 0,0,0,0,114,2,0,0,0,114,10,0,0,0,114,10, - 0,0,0,114,10,0,0,0,114,11,0,0,0,114,17,0, - 0,0,48,0,0,0,115,2,0,0,0,8,1,114,17,0, - 0,0,99,0,0,0,0,0,0,0,0,0,0,0,0,2, - 0,0,0,64,0,0,0,115,56,0,0,0,101,0,90,1, - 100,0,90,2,100,1,90,3,100,2,100,3,132,0,90,4, - 100,4,100,5,132,0,90,5,100,6,100,7,132,0,90,6, - 100,8,100,9,132,0,90,7,100,10,100,11,132,0,90,8, - 100,12,83,0,41,13,218,11,95,77,111,100,117,108,101,76, - 111,99,107,122,169,65,32,114,101,99,117,114,115,105,118,101, - 32,108,111,99,107,32,105,109,112,108,101,109,101,110,116,97, - 116,105,111,110,32,119,104,105,99,104,32,105,115,32,97,98, - 108,101,32,116,111,32,100,101,116,101,99,116,32,100,101,97, - 100,108,111,99,107,115,10,32,32,32,32,40,101,46,103,46, - 32,116,104,114,101,97,100,32,49,32,116,114,121,105,110,103, - 32,116,111,32,116,97,107,101,32,108,111,99,107,115,32,65, - 32,116,104,101,110,32,66,44,32,97,110,100,32,116,104,114, - 101,97,100,32,50,32,116,114,121,105,110,103,32,116,111,10, - 32,32,32,32,116,97,107,101,32,108,111,99,107,115,32,66, - 32,116,104,101,110,32,65,41,46,10,32,32,32,32,99,2, - 0,0,0,0,0,0,0,2,0,0,0,2,0,0,0,67, - 0,0,0,115,48,0,0,0,116,0,160,1,161,0,124,0, - 95,2,116,0,160,1,161,0,124,0,95,3,124,1,124,0, - 95,4,100,0,124,0,95,5,100,1,124,0,95,6,100,1, - 124,0,95,7,100,0,83,0,41,2,78,233,0,0,0,0, - 41,8,218,7,95,116,104,114,101,97,100,90,13,97,108,108, - 111,99,97,116,101,95,108,111,99,107,218,4,108,111,99,107, - 218,6,119,97,107,101,117,112,114,15,0,0,0,218,5,111, - 119,110,101,114,218,5,99,111,117,110,116,218,7,119,97,105, - 116,101,114,115,41,2,218,4,115,101,108,102,114,15,0,0, - 0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, - 218,8,95,95,105,110,105,116,95,95,58,0,0,0,115,12, - 0,0,0,0,1,10,1,10,1,6,1,6,1,6,1,122, - 20,95,77,111,100,117,108,101,76,111,99,107,46,95,95,105, - 110,105,116,95,95,99,1,0,0,0,0,0,0,0,4,0, - 0,0,3,0,0,0,67,0,0,0,115,64,0,0,0,116, - 0,160,1,161,0,125,1,124,0,106,2,125,2,120,44,116, - 3,160,4,124,2,161,1,125,3,124,3,100,0,107,8,114, - 38,100,1,83,0,124,3,106,2,125,2,124,2,124,1,107, - 2,114,16,100,2,83,0,113,16,87,0,100,0,83,0,41, - 3,78,70,84,41,5,114,20,0,0,0,218,9,103,101,116, - 95,105,100,101,110,116,114,23,0,0,0,218,12,95,98,108, - 111,99,107,105,110,103,95,111,110,218,3,103,101,116,41,4, - 114,26,0,0,0,90,2,109,101,218,3,116,105,100,114,21, - 0,0,0,114,10,0,0,0,114,10,0,0,0,114,11,0, - 0,0,218,12,104,97,115,95,100,101,97,100,108,111,99,107, - 66,0,0,0,115,18,0,0,0,0,2,8,1,6,1,2, - 1,10,1,8,1,4,1,6,1,8,1,122,24,95,77,111, - 100,117,108,101,76,111,99,107,46,104,97,115,95,100,101,97, - 100,108,111,99,107,99,1,0,0,0,0,0,0,0,2,0, - 0,0,9,0,0,0,67,0,0,0,115,168,0,0,0,116, - 0,160,1,161,0,125,1,124,0,116,2,124,1,60,0,122, - 138,120,132,124,0,106,3,143,96,1,0,124,0,106,4,100, - 1,107,2,115,48,124,0,106,5,124,1,107,2,114,72,124, - 1,124,0,95,5,124,0,4,0,106,4,100,2,55,0,2, - 0,95,4,100,3,83,0,124,0,160,6,161,0,114,92,116, - 7,100,4,124,0,22,0,131,1,130,1,124,0,106,8,160, - 9,100,5,161,1,114,118,124,0,4,0,106,10,100,2,55, - 0,2,0,95,10,87,0,100,6,81,0,82,0,88,0,124, - 0,106,8,160,9,161,0,1,0,124,0,106,8,160,11,161, - 0,1,0,113,20,87,0,87,0,100,6,116,2,124,1,61, + 0,0,7,0,0,0,67,0,0,0,115,56,0,0,0,100, + 1,68,0,93,32,125,2,116,0,124,1,124,2,131,2,114, + 4,116,1,124,0,124,2,116,2,124,1,124,2,131,2,131, + 3,1,0,113,4,124,0,106,3,160,4,124,1,106,3,161, + 1,1,0,100,2,83,0,41,3,122,47,83,105,109,112,108, + 101,32,115,117,98,115,116,105,116,117,116,101,32,102,111,114, + 32,102,117,110,99,116,111,111,108,115,46,117,112,100,97,116, + 101,95,119,114,97,112,112,101,114,46,41,4,218,10,95,95, + 109,111,100,117,108,101,95,95,218,8,95,95,110,97,109,101, + 95,95,218,12,95,95,113,117,97,108,110,97,109,101,95,95, + 218,7,95,95,100,111,99,95,95,78,41,5,218,7,104,97, + 115,97,116,116,114,218,7,115,101,116,97,116,116,114,218,7, + 103,101,116,97,116,116,114,218,8,95,95,100,105,99,116,95, + 95,218,6,117,112,100,97,116,101,41,3,90,3,110,101,119, + 90,3,111,108,100,218,7,114,101,112,108,97,99,101,169,0, + 114,10,0,0,0,250,29,60,102,114,111,122,101,110,32,105, + 109,112,111,114,116,108,105,98,46,95,98,111,111,116,115,116, + 114,97,112,62,218,5,95,119,114,97,112,27,0,0,0,115, + 8,0,0,0,0,2,8,1,10,1,20,1,114,12,0,0, + 0,99,1,0,0,0,0,0,0,0,1,0,0,0,2,0, + 0,0,67,0,0,0,115,12,0,0,0,116,0,116,1,131, + 1,124,0,131,1,83,0,41,1,78,41,2,218,4,116,121, + 112,101,218,3,115,121,115,41,1,218,4,110,97,109,101,114, + 10,0,0,0,114,10,0,0,0,114,11,0,0,0,218,11, + 95,110,101,119,95,109,111,100,117,108,101,35,0,0,0,115, + 2,0,0,0,0,1,114,16,0,0,0,99,0,0,0,0, + 0,0,0,0,0,0,0,0,1,0,0,0,64,0,0,0, + 115,12,0,0,0,101,0,90,1,100,0,90,2,100,1,83, + 0,41,2,218,14,95,68,101,97,100,108,111,99,107,69,114, + 114,111,114,78,41,3,114,1,0,0,0,114,0,0,0,0, + 114,2,0,0,0,114,10,0,0,0,114,10,0,0,0,114, + 10,0,0,0,114,11,0,0,0,114,17,0,0,0,48,0, + 0,0,115,2,0,0,0,8,1,114,17,0,0,0,99,0, + 0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,64, + 0,0,0,115,56,0,0,0,101,0,90,1,100,0,90,2, + 100,1,90,3,100,2,100,3,132,0,90,4,100,4,100,5, + 132,0,90,5,100,6,100,7,132,0,90,6,100,8,100,9, + 132,0,90,7,100,10,100,11,132,0,90,8,100,12,83,0, + 41,13,218,11,95,77,111,100,117,108,101,76,111,99,107,122, + 169,65,32,114,101,99,117,114,115,105,118,101,32,108,111,99, + 107,32,105,109,112,108,101,109,101,110,116,97,116,105,111,110, + 32,119,104,105,99,104,32,105,115,32,97,98,108,101,32,116, + 111,32,100,101,116,101,99,116,32,100,101,97,100,108,111,99, + 107,115,10,32,32,32,32,40,101,46,103,46,32,116,104,114, + 101,97,100,32,49,32,116,114,121,105,110,103,32,116,111,32, + 116,97,107,101,32,108,111,99,107,115,32,65,32,116,104,101, + 110,32,66,44,32,97,110,100,32,116,104,114,101,97,100,32, + 50,32,116,114,121,105,110,103,32,116,111,10,32,32,32,32, + 116,97,107,101,32,108,111,99,107,115,32,66,32,116,104,101, + 110,32,65,41,46,10,32,32,32,32,99,2,0,0,0,0, + 0,0,0,2,0,0,0,2,0,0,0,67,0,0,0,115, + 48,0,0,0,116,0,160,1,161,0,124,0,95,2,116,0, + 160,1,161,0,124,0,95,3,124,1,124,0,95,4,100,0, + 124,0,95,5,100,1,124,0,95,6,100,1,124,0,95,7, + 100,0,83,0,41,2,78,233,0,0,0,0,41,8,218,7, + 95,116,104,114,101,97,100,90,13,97,108,108,111,99,97,116, + 101,95,108,111,99,107,218,4,108,111,99,107,218,6,119,97, + 107,101,117,112,114,15,0,0,0,218,5,111,119,110,101,114, + 218,5,99,111,117,110,116,218,7,119,97,105,116,101,114,115, + 41,2,218,4,115,101,108,102,114,15,0,0,0,114,10,0, + 0,0,114,10,0,0,0,114,11,0,0,0,218,8,95,95, + 105,110,105,116,95,95,58,0,0,0,115,12,0,0,0,0, + 1,10,1,10,1,6,1,6,1,6,1,122,20,95,77,111, + 100,117,108,101,76,111,99,107,46,95,95,105,110,105,116,95, + 95,99,1,0,0,0,0,0,0,0,4,0,0,0,3,0, + 0,0,67,0,0,0,115,60,0,0,0,116,0,160,1,161, + 0,125,1,124,0,106,2,125,2,116,3,160,4,124,2,161, + 1,125,3,124,3,100,0,107,8,114,36,100,1,83,0,124, + 3,106,2,125,2,124,2,124,1,107,2,114,14,100,2,83, + 0,113,14,100,0,83,0,41,3,78,70,84,41,5,114,20, + 0,0,0,218,9,103,101,116,95,105,100,101,110,116,114,23, + 0,0,0,218,12,95,98,108,111,99,107,105,110,103,95,111, + 110,218,3,103,101,116,41,4,114,26,0,0,0,90,2,109, + 101,218,3,116,105,100,114,21,0,0,0,114,10,0,0,0, + 114,10,0,0,0,114,11,0,0,0,218,12,104,97,115,95, + 100,101,97,100,108,111,99,107,66,0,0,0,115,16,0,0, + 0,0,2,8,1,6,2,10,1,8,1,4,1,6,1,8, + 1,122,24,95,77,111,100,117,108,101,76,111,99,107,46,104, + 97,115,95,100,101,97,100,108,111,99,107,99,1,0,0,0, + 0,0,0,0,2,0,0,0,9,0,0,0,67,0,0,0, + 115,178,0,0,0,116,0,160,1,161,0,125,1,124,0,116, + 2,124,1,60,0,122,148,124,0,106,3,143,110,1,0,124, + 0,106,4,100,1,107,2,115,46,124,0,106,5,124,1,107, + 2,114,84,124,1,124,0,95,5,124,0,4,0,106,4,100, + 2,55,0,2,0,95,4,87,0,53,0,81,0,82,0,163, + 0,87,0,162,86,100,3,83,0,124,0,160,6,161,0,114, + 104,116,7,100,4,124,0,22,0,131,1,130,1,124,0,106, + 8,160,9,100,5,161,1,114,130,124,0,4,0,106,10,100, + 2,55,0,2,0,95,10,87,0,53,0,81,0,82,0,88, + 0,124,0,106,8,160,9,161,0,1,0,124,0,106,8,160, + 11,161,0,1,0,113,18,87,0,53,0,116,2,124,1,61, 0,88,0,100,6,83,0,41,7,122,185,10,32,32,32,32, 32,32,32,32,65,99,113,117,105,114,101,32,116,104,101,32, 109,111,100,117,108,101,32,108,111,99,107,46,32,32,73,102, @@ -165,1265 +165,1269 @@ const unsigned char _Py_M__importlib[] = { 114,101,114,25,0,0,0,218,7,114,101,108,101,97,115,101, 41,2,114,26,0,0,0,114,31,0,0,0,114,10,0,0, 0,114,10,0,0,0,114,11,0,0,0,114,34,0,0,0, - 78,0,0,0,115,32,0,0,0,0,6,8,1,8,1,2, - 1,2,1,8,1,20,1,6,1,14,1,4,1,8,1,12, - 1,12,1,24,2,10,1,18,2,122,19,95,77,111,100,117, - 108,101,76,111,99,107,46,97,99,113,117,105,114,101,99,1, - 0,0,0,0,0,0,0,2,0,0,0,9,0,0,0,67, - 0,0,0,115,122,0,0,0,116,0,160,1,161,0,125,1, - 124,0,106,2,143,98,1,0,124,0,106,3,124,1,107,3, - 114,34,116,4,100,1,131,1,130,1,124,0,106,5,100,2, - 107,4,115,48,116,6,130,1,124,0,4,0,106,5,100,3, - 56,0,2,0,95,5,124,0,106,5,100,2,107,2,114,108, - 100,0,124,0,95,3,124,0,106,7,114,108,124,0,4,0, - 106,7,100,3,56,0,2,0,95,7,124,0,106,8,160,9, - 161,0,1,0,87,0,100,0,81,0,82,0,88,0,100,0, - 83,0,41,4,78,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,19,0,0,0,114,33,0,0,0, - 41,10,114,20,0,0,0,114,28,0,0,0,114,21,0,0, - 0,114,23,0,0,0,218,12,82,117,110,116,105,109,101,69, - 114,114,111,114,114,24,0,0,0,218,14,65,115,115,101,114, - 116,105,111,110,69,114,114,111,114,114,25,0,0,0,114,22, - 0,0,0,114,35,0,0,0,41,2,114,26,0,0,0,114, - 31,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, - 0,0,0,114,35,0,0,0,103,0,0,0,115,22,0,0, - 0,0,1,8,1,8,1,10,1,8,1,14,1,14,1,10, - 1,6,1,6,1,14,1,122,19,95,77,111,100,117,108,101, - 76,111,99,107,46,114,101,108,101,97,115,101,99,1,0,0, - 0,0,0,0,0,1,0,0,0,5,0,0,0,67,0,0, - 0,115,18,0,0,0,100,1,160,0,124,0,106,1,116,2, - 124,0,131,1,161,2,83,0,41,2,78,122,23,95,77,111, - 100,117,108,101,76,111,99,107,40,123,33,114,125,41,32,97, - 116,32,123,125,41,3,218,6,102,111,114,109,97,116,114,15, - 0,0,0,218,2,105,100,41,1,114,26,0,0,0,114,10, - 0,0,0,114,10,0,0,0,114,11,0,0,0,218,8,95, - 95,114,101,112,114,95,95,116,0,0,0,115,2,0,0,0, - 0,1,122,20,95,77,111,100,117,108,101,76,111,99,107,46, - 95,95,114,101,112,114,95,95,78,41,9,114,1,0,0,0, - 114,0,0,0,0,114,2,0,0,0,114,3,0,0,0,114, - 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, - 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, + 78,0,0,0,115,30,0,0,0,0,6,8,1,8,1,2, + 2,8,1,20,1,6,1,14,1,18,1,8,1,12,1,12, + 1,24,2,10,1,16,2,122,19,95,77,111,100,117,108,101, + 76,111,99,107,46,97,99,113,117,105,114,101,99,1,0,0, + 0,0,0,0,0,2,0,0,0,9,0,0,0,67,0,0, + 0,115,122,0,0,0,116,0,160,1,161,0,125,1,124,0, + 106,2,143,98,1,0,124,0,106,3,124,1,107,3,114,34, + 116,4,100,1,131,1,130,1,124,0,106,5,100,2,107,4, + 115,48,116,6,130,1,124,0,4,0,106,5,100,3,56,0, + 2,0,95,5,124,0,106,5,100,2,107,2,114,108,100,0, + 124,0,95,3,124,0,106,7,114,108,124,0,4,0,106,7, + 100,3,56,0,2,0,95,7,124,0,106,8,160,9,161,0, + 1,0,87,0,53,0,81,0,82,0,88,0,100,0,83,0, + 41,4,78,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,19,0,0,0,114,33,0,0,0,41,10, + 114,20,0,0,0,114,28,0,0,0,114,21,0,0,0,114, + 23,0,0,0,218,12,82,117,110,116,105,109,101,69,114,114, + 111,114,114,24,0,0,0,218,14,65,115,115,101,114,116,105, + 111,110,69,114,114,111,114,114,25,0,0,0,114,22,0,0, + 0,114,35,0,0,0,41,2,114,26,0,0,0,114,31,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, - 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, + 0,114,35,0,0,0,103,0,0,0,115,22,0,0,0,0, + 1,8,1,8,1,10,1,8,1,14,1,14,1,10,1,6, + 1,6,1,14,1,122,19,95,77,111,100,117,108,101,76,111, + 99,107,46,114,101,108,101,97,115,101,99,1,0,0,0,0, + 0,0,0,1,0,0,0,5,0,0,0,67,0,0,0,115, + 18,0,0,0,100,1,160,0,124,0,106,1,116,2,124,0, + 131,1,161,2,83,0,41,2,78,122,23,95,77,111,100,117, + 108,101,76,111,99,107,40,123,33,114,125,41,32,97,116,32, + 123,125,41,3,218,6,102,111,114,109,97,116,114,15,0,0, + 0,218,2,105,100,41,1,114,26,0,0,0,114,10,0,0, + 0,114,10,0,0,0,114,11,0,0,0,218,8,95,95,114, + 101,112,114,95,95,116,0,0,0,115,2,0,0,0,0,1, + 122,20,95,77,111,100,117,108,101,76,111,99,107,46,95,95, + 114,101,112,114,95,95,78,41,9,114,1,0,0,0,114,0, + 0,0,0,114,2,0,0,0,114,3,0,0,0,114,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,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, - 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, + 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,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,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,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,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,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,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, - 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, - 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, + 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, + 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,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, + 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,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,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, - 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,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,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,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, + 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,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, + 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, - 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,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, + 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,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, + 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, - 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, + 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,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, + 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, @@ -1442,9 +1446,9 @@ const unsigned char _Py_M__importlib[] = { 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, + 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, @@ -1481,7 +1485,7 @@ const unsigned char _Py_M__importlib[] = { 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, + 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, @@ -1509,315 +1513,316 @@ const unsigned char _Py_M__importlib[] = { 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, + 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,236,0,0,0,116,0,124,0,100,1, + 131,2,114,232,124,1,68,0,93,216,125,4,116,1,124,4, + 116,2,131,2,115,76,124,3,114,44,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,14,124,4,100,6,107,2,114,118,124,3, + 115,230,116,0,124,0,100,7,131,2,114,230,116,6,124,0, + 124,0,106,7,124,2,100,8,100,9,141,4,1,0,113,14, + 116,0,124,0,124,4,131,2,115,14,100,10,160,8,124,0, + 106,3,124,4,161,2,125,6,122,14,116,9,124,2,124,6, + 131,2,1,0,87,0,113,14,4,0,116,10,107,10,114,228, + 1,0,125,7,1,0,122,42,124,7,106,11,124,6,107,2, + 114,210,116,12,106,13,160,14,124,6,116,15,161,2,100,11, + 107,9,114,210,87,0,89,0,162,8,113,14,130,0,87,0, + 53,0,100,11,125,7,126,7,88,0,89,0,113,14,88,0, + 113,14,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,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,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,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,92,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, + 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,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,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, }; diff --git a/Python/importlib_external.h b/Python/importlib_external.h index 7dd82492ef32..a1f80b5c53c4 100644 --- a/Python/importlib_external.h +++ b/Python/importlib_external.h @@ -144,10 +144,10 @@ const unsigned char _Py_M__importlib_external[] = { 0,5,0,0,0,67,0,0,0,115,96,0,0,0,116,0, 116,1,131,1,100,1,107,2,114,36,124,0,160,2,116,3, 161,1,92,3,125,1,125,2,125,3,124,1,124,3,102,2, - 83,0,120,50,116,4,124,0,131,1,68,0,93,38,125,4, - 124,4,116,1,107,6,114,46,124,0,106,5,124,4,100,1, - 100,2,141,2,92,2,125,1,125,3,124,1,124,3,102,2, - 83,0,113,46,87,0,100,3,124,0,102,2,83,0,41,4, + 83,0,116,4,124,0,131,1,68,0,93,42,125,4,124,4, + 116,1,107,6,114,44,124,0,106,5,124,4,100,1,100,2, + 141,2,92,2,125,1,125,3,124,1,124,3,102,2,2,0, + 1,0,83,0,113,44,100,3,124,0,102,2,83,0,41,4, 122,32,82,101,112,108,97,99,101,109,101,110,116,32,102,111, 114,32,111,115,46,112,97,116,104,46,115,112,108,105,116,40, 41,46,233,1,0,0,0,41,1,90,8,109,97,120,115,112, @@ -158,8 +158,8 @@ const unsigned char _Py_M__importlib_external[] = { 111,110,116,218,1,95,218,4,116,97,105,108,114,16,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,115,112,108,105,116,62,0,0, - 0,115,16,0,0,0,0,2,12,1,16,1,8,1,14,1, - 8,1,18,1,12,1,114,38,0,0,0,99,1,0,0,0, + 0,115,16,0,0,0,0,2,12,1,16,1,8,1,12,1, + 8,1,18,1,14,1,114,38,0,0,0,99,1,0,0,0, 0,0,0,0,1,0,0,0,3,0,0,0,67,0,0,0, 115,10,0,0,0,116,0,160,1,124,0,161,1,83,0,41, 1,122,126,83,116,97,116,32,116,104,101,32,112,97,116,104, @@ -175,362 +175,362 @@ const unsigned char _Py_M__importlib_external[] = { 4,0,0,0,218,10,95,112,97,116,104,95,115,116,97,116, 74,0,0,0,115,2,0,0,0,0,7,114,39,0,0,0, 99,2,0,0,0,0,0,0,0,3,0,0,0,8,0,0, - 0,67,0,0,0,115,48,0,0,0,121,12,116,0,124,0, - 131,1,125,2,87,0,110,20,4,0,116,1,107,10,114,32, - 1,0,1,0,1,0,100,1,83,0,88,0,124,2,106,2, - 100,2,64,0,124,1,107,2,83,0,41,3,122,49,84,101, - 115,116,32,119,104,101,116,104,101,114,32,116,104,101,32,112, - 97,116,104,32,105,115,32,116,104,101,32,115,112,101,99,105, - 102,105,101,100,32,109,111,100,101,32,116,121,112,101,46,70, - 105,0,240,0,0,41,3,114,39,0,0,0,218,7,79,83, - 69,114,114,111,114,218,7,115,116,95,109,111,100,101,41,3, - 114,35,0,0,0,218,4,109,111,100,101,90,9,115,116,97, - 116,95,105,110,102,111,114,2,0,0,0,114,2,0,0,0, - 114,4,0,0,0,218,18,95,112,97,116,104,95,105,115,95, - 109,111,100,101,95,116,121,112,101,84,0,0,0,115,10,0, - 0,0,0,2,2,1,12,1,14,1,6,1,114,43,0,0, - 0,99,1,0,0,0,0,0,0,0,1,0,0,0,3,0, - 0,0,67,0,0,0,115,10,0,0,0,116,0,124,0,100, - 1,131,2,83,0,41,2,122,31,82,101,112,108,97,99,101, - 109,101,110,116,32,102,111,114,32,111,115,46,112,97,116,104, - 46,105,115,102,105,108,101,46,105,0,128,0,0,41,1,114, - 43,0,0,0,41,1,114,35,0,0,0,114,2,0,0,0, - 114,2,0,0,0,114,4,0,0,0,218,12,95,112,97,116, - 104,95,105,115,102,105,108,101,93,0,0,0,115,2,0,0, - 0,0,2,114,44,0,0,0,99,1,0,0,0,0,0,0, - 0,1,0,0,0,3,0,0,0,67,0,0,0,115,22,0, - 0,0,124,0,115,12,116,0,160,1,161,0,125,0,116,2, - 124,0,100,1,131,2,83,0,41,2,122,30,82,101,112,108, - 97,99,101,109,101,110,116,32,102,111,114,32,111,115,46,112, - 97,116,104,46,105,115,100,105,114,46,105,0,64,0,0,41, - 3,114,1,0,0,0,218,6,103,101,116,99,119,100,114,43, - 0,0,0,41,1,114,35,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,105,115,100,105,114,98,0,0,0,115,6,0,0,0,0, - 2,4,1,8,1,114,46,0,0,0,233,182,1,0,0,99, - 3,0,0,0,0,0,0,0,6,0,0,0,11,0,0,0, - 67,0,0,0,115,162,0,0,0,100,1,160,0,124,0,116, - 1,124,0,131,1,161,2,125,3,116,2,160,3,124,3,116, - 2,106,4,116,2,106,5,66,0,116,2,106,6,66,0,124, - 2,100,2,64,0,161,3,125,4,121,50,116,7,160,8,124, - 4,100,3,161,2,143,16,125,5,124,5,160,9,124,1,161, - 1,1,0,87,0,100,4,81,0,82,0,88,0,116,2,160, - 10,124,3,124,0,161,2,1,0,87,0,110,58,4,0,116, - 11,107,10,114,156,1,0,1,0,1,0,121,14,116,2,160, - 12,124,3,161,1,1,0,87,0,110,20,4,0,116,11,107, - 10,114,148,1,0,1,0,1,0,89,0,110,2,88,0,130, - 0,89,0,110,2,88,0,100,4,83,0,41,5,122,162,66, - 101,115,116,45,101,102,102,111,114,116,32,102,117,110,99,116, - 105,111,110,32,116,111,32,119,114,105,116,101,32,100,97,116, - 97,32,116,111,32,97,32,112,97,116,104,32,97,116,111,109, - 105,99,97,108,108,121,46,10,32,32,32,32,66,101,32,112, - 114,101,112,97,114,101,100,32,116,111,32,104,97,110,100,108, - 101,32,97,32,70,105,108,101,69,120,105,115,116,115,69,114, - 114,111,114,32,105,102,32,99,111,110,99,117,114,114,101,110, - 116,32,119,114,105,116,105,110,103,32,111,102,32,116,104,101, - 10,32,32,32,32,116,101,109,112,111,114,97,114,121,32,102, - 105,108,101,32,105,115,32,97,116,116,101,109,112,116,101,100, - 46,122,5,123,125,46,123,125,105,182,1,0,0,90,2,119, - 98,78,41,13,218,6,102,111,114,109,97,116,218,2,105,100, - 114,1,0,0,0,90,4,111,112,101,110,90,6,79,95,69, - 88,67,76,90,7,79,95,67,82,69,65,84,90,8,79,95, - 87,82,79,78,76,89,218,3,95,105,111,218,6,70,105,108, - 101,73,79,218,5,119,114,105,116,101,218,7,114,101,112,108, - 97,99,101,114,40,0,0,0,90,6,117,110,108,105,110,107, - 41,6,114,35,0,0,0,218,4,100,97,116,97,114,42,0, - 0,0,90,8,112,97,116,104,95,116,109,112,90,2,102,100, - 218,4,102,105,108,101,114,2,0,0,0,114,2,0,0,0, - 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, - 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, - 78,41,1,218,12,111,112,116,105,109,105,122,97,116,105,111, - 110,99,2,0,0,0,1,0,0,0,11,0,0,0,6,0, - 0,0,67,0,0,0,115,244,0,0,0,124,1,100,1,107, - 9,114,52,116,0,160,1,100,2,116,2,161,2,1,0,124, - 2,100,1,107,9,114,40,100,3,125,3,116,3,124,3,131, - 1,130,1,124,1,114,48,100,4,110,2,100,5,125,2,116, - 4,160,5,124,0,161,1,125,0,116,6,124,0,131,1,92, - 2,125,4,125,5,124,5,160,7,100,6,161,1,92,3,125, - 6,125,7,125,8,116,8,106,9,106,10,125,9,124,9,100, - 1,107,8,114,114,116,11,100,7,131,1,130,1,100,4,160, - 12,124,6,114,126,124,6,110,2,124,8,124,7,124,9,103, - 3,161,1,125,10,124,2,100,1,107,8,114,172,116,8,106, - 13,106,14,100,8,107,2,114,164,100,4,125,2,110,8,116, - 8,106,13,106,14,125,2,116,15,124,2,131,1,125,2,124, - 2,100,4,107,3,114,224,124,2,160,16,161,0,115,210,116, - 17,100,9,160,18,124,2,161,1,131,1,130,1,100,10,160, - 18,124,10,116,19,124,2,161,3,125,10,116,20,124,4,116, - 21,124,10,116,22,100,8,25,0,23,0,131,3,83,0,41, - 11,97,254,2,0,0,71,105,118,101,110,32,116,104,101,32, - 112,97,116,104,32,116,111,32,97,32,46,112,121,32,102,105, - 108,101,44,32,114,101,116,117,114,110,32,116,104,101,32,112, - 97,116,104,32,116,111,32,105,116,115,32,46,112,121,99,32, - 102,105,108,101,46,10,10,32,32,32,32,84,104,101,32,46, - 112,121,32,102,105,108,101,32,100,111,101,115,32,110,111,116, - 32,110,101,101,100,32,116,111,32,101,120,105,115,116,59,32, - 116,104,105,115,32,115,105,109,112,108,121,32,114,101,116,117, - 114,110,115,32,116,104,101,32,112,97,116,104,32,116,111,32, - 116,104,101,10,32,32,32,32,46,112,121,99,32,102,105,108, - 101,32,99,97,108,99,117,108,97,116,101,100,32,97,115,32, - 105,102,32,116,104,101,32,46,112,121,32,102,105,108,101,32, - 119,101,114,101,32,105,109,112,111,114,116,101,100,46,10,10, - 32,32,32,32,84,104,101,32,39,111,112,116,105,109,105,122, - 97,116,105,111,110,39,32,112,97,114,97,109,101,116,101,114, - 32,99,111,110,116,114,111,108,115,32,116,104,101,32,112,114, - 101,115,117,109,101,100,32,111,112,116,105,109,105,122,97,116, - 105,111,110,32,108,101,118,101,108,32,111,102,10,32,32,32, - 32,116,104,101,32,98,121,116,101,99,111,100,101,32,102,105, - 108,101,46,32,73,102,32,39,111,112,116,105,109,105,122,97, - 116,105,111,110,39,32,105,115,32,110,111,116,32,78,111,110, - 101,44,32,116,104,101,32,115,116,114,105,110,103,32,114,101, - 112,114,101,115,101,110,116,97,116,105,111,110,10,32,32,32, - 32,111,102,32,116,104,101,32,97,114,103,117,109,101,110,116, - 32,105,115,32,116,97,107,101,110,32,97,110,100,32,118,101, - 114,105,102,105,101,100,32,116,111,32,98,101,32,97,108,112, - 104,97,110,117,109,101,114,105,99,32,40,101,108,115,101,32, - 86,97,108,117,101,69,114,114,111,114,10,32,32,32,32,105, - 115,32,114,97,105,115,101,100,41,46,10,10,32,32,32,32, - 84,104,101,32,100,101,98,117,103,95,111,118,101,114,114,105, - 100,101,32,112,97,114,97,109,101,116,101,114,32,105,115,32, - 100,101,112,114,101,99,97,116,101,100,46,32,73,102,32,100, - 101,98,117,103,95,111,118,101,114,114,105,100,101,32,105,115, - 32,110,111,116,32,78,111,110,101,44,10,32,32,32,32,97, - 32,84,114,117,101,32,118,97,108,117,101,32,105,115,32,116, - 104,101,32,115,97,109,101,32,97,115,32,115,101,116,116,105, - 110,103,32,39,111,112,116,105,109,105,122,97,116,105,111,110, - 39,32,116,111,32,116,104,101,32,101,109,112,116,121,32,115, - 116,114,105,110,103,10,32,32,32,32,119,104,105,108,101,32, - 97,32,70,97,108,115,101,32,118,97,108,117,101,32,105,115, - 32,101,113,117,105,118,97,108,101,110,116,32,116,111,32,115, - 101,116,116,105,110,103,32,39,111,112,116,105,109,105,122,97, - 116,105,111,110,39,32,116,111,32,39,49,39,46,10,10,32, - 32,32,32,73,102,32,115,121,115,46,105,109,112,108,101,109, - 101,110,116,97,116,105,111,110,46,99,97,99,104,101,95,116, - 97,103,32,105,115,32,78,111,110,101,32,116,104,101,110,32, - 78,111,116,73,109,112,108,101,109,101,110,116,101,100,69,114, - 114,111,114,32,105,115,32,114,97,105,115,101,100,46,10,10, - 32,32,32,32,78,122,70,116,104,101,32,100,101,98,117,103, - 95,111,118,101,114,114,105,100,101,32,112,97,114,97,109,101, - 116,101,114,32,105,115,32,100,101,112,114,101,99,97,116,101, - 100,59,32,117,115,101,32,39,111,112,116,105,109,105,122,97, - 116,105,111,110,39,32,105,110,115,116,101,97,100,122,50,100, - 101,98,117,103,95,111,118,101,114,114,105,100,101,32,111,114, - 32,111,112,116,105,109,105,122,97,116,105,111,110,32,109,117, - 115,116,32,98,101,32,115,101,116,32,116,111,32,78,111,110, - 101,114,30,0,0,0,114,29,0,0,0,218,1,46,122,36, - 115,121,115,46,105,109,112,108,101,109,101,110,116,97,116,105, - 111,110,46,99,97,99,104,101,95,116,97,103,32,105,115,32, - 78,111,110,101,233,0,0,0,0,122,24,123,33,114,125,32, - 105,115,32,110,111,116,32,97,108,112,104,97,110,117,109,101, - 114,105,99,122,7,123,125,46,123,125,123,125,41,23,218,9, - 95,119,97,114,110,105,110,103,115,218,4,119,97,114,110,218, - 18,68,101,112,114,101,99,97,116,105,111,110,87,97,114,110, - 105,110,103,218,9,84,121,112,101,69,114,114,111,114,114,1, - 0,0,0,218,6,102,115,112,97,116,104,114,38,0,0,0, - 114,32,0,0,0,114,6,0,0,0,218,14,105,109,112,108, - 101,109,101,110,116,97,116,105,111,110,218,9,99,97,99,104, - 101,95,116,97,103,218,19,78,111,116,73,109,112,108,101,109, - 101,110,116,101,100,69,114,114,111,114,114,26,0,0,0,218, - 5,102,108,97,103,115,218,8,111,112,116,105,109,105,122,101, - 218,3,115,116,114,218,7,105,115,97,108,110,117,109,218,10, - 86,97,108,117,101,69,114,114,111,114,114,48,0,0,0,218, - 4,95,79,80,84,114,28,0,0,0,218,8,95,80,89,67, - 65,67,72,69,218,17,66,89,84,69,67,79,68,69,95,83, - 85,70,70,73,88,69,83,41,11,114,35,0,0,0,90,14, - 100,101,98,117,103,95,111,118,101,114,114,105,100,101,114,58, - 0,0,0,218,7,109,101,115,115,97,103,101,218,4,104,101, - 97,100,114,37,0,0,0,90,4,98,97,115,101,218,3,115, - 101,112,218,4,114,101,115,116,90,3,116,97,103,90,15,97, - 108,109,111,115,116,95,102,105,108,101,110,97,109,101,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, - 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, - 0,0,0,0,0,0,0,8,0,0,0,5,0,0,0,67, - 0,0,0,115,230,0,0,0,116,0,106,1,106,2,100,1, - 107,8,114,20,116,3,100,2,131,1,130,1,116,4,160,5, - 124,0,161,1,125,0,116,6,124,0,131,1,92,2,125,1, - 125,2,116,6,124,1,131,1,92,2,125,1,125,3,124,3, - 116,7,107,3,114,78,116,8,100,3,160,9,116,7,124,0, - 161,2,131,1,130,1,124,2,160,10,100,4,161,1,125,4, - 124,4,100,5,107,7,114,112,116,8,100,6,160,9,124,2, - 161,1,131,1,130,1,110,86,124,4,100,7,107,2,114,198, - 124,2,160,11,100,4,100,8,161,2,100,9,25,0,125,5, - 124,5,160,12,116,13,161,1,115,160,116,8,100,10,160,9, - 116,13,161,1,131,1,130,1,124,5,116,14,116,13,131,1, - 100,1,133,2,25,0,125,6,124,6,160,15,161,0,115,198, - 116,8,100,11,160,9,124,5,161,1,131,1,130,1,124,2, - 160,16,100,4,161,1,100,12,25,0,125,7,116,17,124,1, - 124,7,116,18,100,12,25,0,23,0,131,2,83,0,41,13, - 97,110,1,0,0,71,105,118,101,110,32,116,104,101,32,112, - 97,116,104,32,116,111,32,97,32,46,112,121,99,46,32,102, - 105,108,101,44,32,114,101,116,117,114,110,32,116,104,101,32, - 112,97,116,104,32,116,111,32,105,116,115,32,46,112,121,32, - 102,105,108,101,46,10,10,32,32,32,32,84,104,101,32,46, - 112,121,99,32,102,105,108,101,32,100,111,101,115,32,110,111, - 116,32,110,101,101,100,32,116,111,32,101,120,105,115,116,59, - 32,116,104,105,115,32,115,105,109,112,108,121,32,114,101,116, - 117,114,110,115,32,116,104,101,32,112,97,116,104,32,116,111, - 10,32,32,32,32,116,104,101,32,46,112,121,32,102,105,108, - 101,32,99,97,108,99,117,108,97,116,101,100,32,116,111,32, - 99,111,114,114,101,115,112,111,110,100,32,116,111,32,116,104, - 101,32,46,112,121,99,32,102,105,108,101,46,32,32,73,102, - 32,112,97,116,104,32,100,111,101,115,10,32,32,32,32,110, - 111,116,32,99,111,110,102,111,114,109,32,116,111,32,80,69, - 80,32,51,49,52,55,47,52,56,56,32,102,111,114,109,97, - 116,44,32,86,97,108,117,101,69,114,114,111,114,32,119,105, - 108,108,32,98,101,32,114,97,105,115,101,100,46,32,73,102, - 10,32,32,32,32,115,121,115,46,105,109,112,108,101,109,101, - 110,116,97,116,105,111,110,46,99,97,99,104,101,95,116,97, - 103,32,105,115,32,78,111,110,101,32,116,104,101,110,32,78, - 111,116,73,109,112,108,101,109,101,110,116,101,100,69,114,114, + 0,67,0,0,0,115,50,0,0,0,122,12,116,0,124,0, + 131,1,125,2,87,0,110,22,4,0,116,1,107,10,114,34, + 1,0,1,0,1,0,89,0,100,1,83,0,88,0,124,2, + 106,2,100,2,64,0,124,1,107,2,83,0,41,3,122,49, + 84,101,115,116,32,119,104,101,116,104,101,114,32,116,104,101, + 32,112,97,116,104,32,105,115,32,116,104,101,32,115,112,101, + 99,105,102,105,101,100,32,109,111,100,101,32,116,121,112,101, + 46,70,105,0,240,0,0,41,3,114,39,0,0,0,218,7, + 79,83,69,114,114,111,114,218,7,115,116,95,109,111,100,101, + 41,3,114,35,0,0,0,218,4,109,111,100,101,90,9,115, + 116,97,116,95,105,110,102,111,114,2,0,0,0,114,2,0, + 0,0,114,4,0,0,0,218,18,95,112,97,116,104,95,105, + 115,95,109,111,100,101,95,116,121,112,101,84,0,0,0,115, + 10,0,0,0,0,2,2,1,12,1,14,1,8,1,114,43, + 0,0,0,99,1,0,0,0,0,0,0,0,1,0,0,0, + 3,0,0,0,67,0,0,0,115,10,0,0,0,116,0,124, + 0,100,1,131,2,83,0,41,2,122,31,82,101,112,108,97, + 99,101,109,101,110,116,32,102,111,114,32,111,115,46,112,97, + 116,104,46,105,115,102,105,108,101,46,105,0,128,0,0,41, + 1,114,43,0,0,0,41,1,114,35,0,0,0,114,2,0, + 0,0,114,2,0,0,0,114,4,0,0,0,218,12,95,112, + 97,116,104,95,105,115,102,105,108,101,93,0,0,0,115,2, + 0,0,0,0,2,114,44,0,0,0,99,1,0,0,0,0, + 0,0,0,1,0,0,0,3,0,0,0,67,0,0,0,115, + 22,0,0,0,124,0,115,12,116,0,160,1,161,0,125,0, + 116,2,124,0,100,1,131,2,83,0,41,2,122,30,82,101, + 112,108,97,99,101,109,101,110,116,32,102,111,114,32,111,115, + 46,112,97,116,104,46,105,115,100,105,114,46,105,0,64,0, + 0,41,3,114,1,0,0,0,218,6,103,101,116,99,119,100, + 114,43,0,0,0,41,1,114,35,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,105,115,100,105,114,98,0,0,0,115,6,0,0, + 0,0,2,4,1,8,1,114,46,0,0,0,233,182,1,0, + 0,99,3,0,0,0,0,0,0,0,6,0,0,0,11,0, + 0,0,67,0,0,0,115,162,0,0,0,100,1,160,0,124, + 0,116,1,124,0,131,1,161,2,125,3,116,2,160,3,124, + 3,116,2,106,4,116,2,106,5,66,0,116,2,106,6,66, + 0,124,2,100,2,64,0,161,3,125,4,122,50,116,7,160, + 8,124,4,100,3,161,2,143,16,125,5,124,5,160,9,124, + 1,161,1,1,0,87,0,53,0,81,0,82,0,88,0,116, + 2,160,10,124,3,124,0,161,2,1,0,87,0,110,58,4, + 0,116,11,107,10,114,156,1,0,1,0,1,0,122,14,116, + 2,160,12,124,3,161,1,1,0,87,0,110,20,4,0,116, + 11,107,10,114,148,1,0,1,0,1,0,89,0,110,2,88, + 0,130,0,89,0,110,2,88,0,100,4,83,0,41,5,122, + 162,66,101,115,116,45,101,102,102,111,114,116,32,102,117,110, + 99,116,105,111,110,32,116,111,32,119,114,105,116,101,32,100, + 97,116,97,32,116,111,32,97,32,112,97,116,104,32,97,116, + 111,109,105,99,97,108,108,121,46,10,32,32,32,32,66,101, + 32,112,114,101,112,97,114,101,100,32,116,111,32,104,97,110, + 100,108,101,32,97,32,70,105,108,101,69,120,105,115,116,115, + 69,114,114,111,114,32,105,102,32,99,111,110,99,117,114,114, + 101,110,116,32,119,114,105,116,105,110,103,32,111,102,32,116, + 104,101,10,32,32,32,32,116,101,109,112,111,114,97,114,121, + 32,102,105,108,101,32,105,115,32,97,116,116,101,109,112,116, + 101,100,46,122,5,123,125,46,123,125,105,182,1,0,0,90, + 2,119,98,78,41,13,218,6,102,111,114,109,97,116,218,2, + 105,100,114,1,0,0,0,90,4,111,112,101,110,90,6,79, + 95,69,88,67,76,90,7,79,95,67,82,69,65,84,90,8, + 79,95,87,82,79,78,76,89,218,3,95,105,111,218,6,70, + 105,108,101,73,79,218,5,119,114,105,116,101,218,7,114,101, + 112,108,97,99,101,114,40,0,0,0,90,6,117,110,108,105, + 110,107,41,6,114,35,0,0,0,218,4,100,97,116,97,114, + 42,0,0,0,90,8,112,97,116,104,95,116,109,112,90,2, + 102,100,218,4,102,105,108,101,114,2,0,0,0,114,2,0, + 0,0,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,72, + 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,78,41,1,218,12,111,112,116,105,109,105,122,97,116, + 105,111,110,99,2,0,0,0,1,0,0,0,11,0,0,0, + 6,0,0,0,67,0,0,0,115,244,0,0,0,124,1,100, + 1,107,9,114,52,116,0,160,1,100,2,116,2,161,2,1, + 0,124,2,100,1,107,9,114,40,100,3,125,3,116,3,124, + 3,131,1,130,1,124,1,114,48,100,4,110,2,100,5,125, + 2,116,4,160,5,124,0,161,1,125,0,116,6,124,0,131, + 1,92,2,125,4,125,5,124,5,160,7,100,6,161,1,92, + 3,125,6,125,7,125,8,116,8,106,9,106,10,125,9,124, + 9,100,1,107,8,114,114,116,11,100,7,131,1,130,1,100, + 4,160,12,124,6,114,126,124,6,110,2,124,8,124,7,124, + 9,103,3,161,1,125,10,124,2,100,1,107,8,114,172,116, + 8,106,13,106,14,100,8,107,2,114,164,100,4,125,2,110, + 8,116,8,106,13,106,14,125,2,116,15,124,2,131,1,125, + 2,124,2,100,4,107,3,114,224,124,2,160,16,161,0,115, + 210,116,17,100,9,160,18,124,2,161,1,131,1,130,1,100, + 10,160,18,124,10,116,19,124,2,161,3,125,10,116,20,124, + 4,116,21,124,10,116,22,100,8,25,0,23,0,131,3,83, + 0,41,11,97,254,2,0,0,71,105,118,101,110,32,116,104, + 101,32,112,97,116,104,32,116,111,32,97,32,46,112,121,32, + 102,105,108,101,44,32,114,101,116,117,114,110,32,116,104,101, + 32,112,97,116,104,32,116,111,32,105,116,115,32,46,112,121, + 99,32,102,105,108,101,46,10,10,32,32,32,32,84,104,101, + 32,46,112,121,32,102,105,108,101,32,100,111,101,115,32,110, + 111,116,32,110,101,101,100,32,116,111,32,101,120,105,115,116, + 59,32,116,104,105,115,32,115,105,109,112,108,121,32,114,101, + 116,117,114,110,115,32,116,104,101,32,112,97,116,104,32,116, + 111,32,116,104,101,10,32,32,32,32,46,112,121,99,32,102, + 105,108,101,32,99,97,108,99,117,108,97,116,101,100,32,97, + 115,32,105,102,32,116,104,101,32,46,112,121,32,102,105,108, + 101,32,119,101,114,101,32,105,109,112,111,114,116,101,100,46, + 10,10,32,32,32,32,84,104,101,32,39,111,112,116,105,109, + 105,122,97,116,105,111,110,39,32,112,97,114,97,109,101,116, + 101,114,32,99,111,110,116,114,111,108,115,32,116,104,101,32, + 112,114,101,115,117,109,101,100,32,111,112,116,105,109,105,122, + 97,116,105,111,110,32,108,101,118,101,108,32,111,102,10,32, + 32,32,32,116,104,101,32,98,121,116,101,99,111,100,101,32, + 102,105,108,101,46,32,73,102,32,39,111,112,116,105,109,105, + 122,97,116,105,111,110,39,32,105,115,32,110,111,116,32,78, + 111,110,101,44,32,116,104,101,32,115,116,114,105,110,103,32, + 114,101,112,114,101,115,101,110,116,97,116,105,111,110,10,32, + 32,32,32,111,102,32,116,104,101,32,97,114,103,117,109,101, + 110,116,32,105,115,32,116,97,107,101,110,32,97,110,100,32, + 118,101,114,105,102,105,101,100,32,116,111,32,98,101,32,97, + 108,112,104,97,110,117,109,101,114,105,99,32,40,101,108,115, + 101,32,86,97,108,117,101,69,114,114,111,114,10,32,32,32, + 32,105,115,32,114,97,105,115,101,100,41,46,10,10,32,32, + 32,32,84,104,101,32,100,101,98,117,103,95,111,118,101,114, + 114,105,100,101,32,112,97,114,97,109,101,116,101,114,32,105, + 115,32,100,101,112,114,101,99,97,116,101,100,46,32,73,102, + 32,100,101,98,117,103,95,111,118,101,114,114,105,100,101,32, + 105,115,32,110,111,116,32,78,111,110,101,44,10,32,32,32, + 32,97,32,84,114,117,101,32,118,97,108,117,101,32,105,115, + 32,116,104,101,32,115,97,109,101,32,97,115,32,115,101,116, + 116,105,110,103,32,39,111,112,116,105,109,105,122,97,116,105, + 111,110,39,32,116,111,32,116,104,101,32,101,109,112,116,121, + 32,115,116,114,105,110,103,10,32,32,32,32,119,104,105,108, + 101,32,97,32,70,97,108,115,101,32,118,97,108,117,101,32, + 105,115,32,101,113,117,105,118,97,108,101,110,116,32,116,111, + 32,115,101,116,116,105,110,103,32,39,111,112,116,105,109,105, + 122,97,116,105,111,110,39,32,116,111,32,39,49,39,46,10, + 10,32,32,32,32,73,102,32,115,121,115,46,105,109,112,108, + 101,109,101,110,116,97,116,105,111,110,46,99,97,99,104,101, + 95,116,97,103,32,105,115,32,78,111,110,101,32,116,104,101, + 110,32,78,111,116,73,109,112,108,101,109,101,110,116,101,100, + 69,114,114,111,114,32,105,115,32,114,97,105,115,101,100,46, + 10,10,32,32,32,32,78,122,70,116,104,101,32,100,101,98, + 117,103,95,111,118,101,114,114,105,100,101,32,112,97,114,97, + 109,101,116,101,114,32,105,115,32,100,101,112,114,101,99,97, + 116,101,100,59,32,117,115,101,32,39,111,112,116,105,109,105, + 122,97,116,105,111,110,39,32,105,110,115,116,101,97,100,122, + 50,100,101,98,117,103,95,111,118,101,114,114,105,100,101,32, + 111,114,32,111,112,116,105,109,105,122,97,116,105,111,110,32, + 109,117,115,116,32,98,101,32,115,101,116,32,116,111,32,78, + 111,110,101,114,30,0,0,0,114,29,0,0,0,218,1,46, + 122,36,115,121,115,46,105,109,112,108,101,109,101,110,116,97, + 116,105,111,110,46,99,97,99,104,101,95,116,97,103,32,105, + 115,32,78,111,110,101,233,0,0,0,0,122,24,123,33,114, + 125,32,105,115,32,110,111,116,32,97,108,112,104,97,110,117, + 109,101,114,105,99,122,7,123,125,46,123,125,123,125,41,23, + 218,9,95,119,97,114,110,105,110,103,115,218,4,119,97,114, + 110,218,18,68,101,112,114,101,99,97,116,105,111,110,87,97, + 114,110,105,110,103,218,9,84,121,112,101,69,114,114,111,114, + 114,1,0,0,0,218,6,102,115,112,97,116,104,114,38,0, + 0,0,114,32,0,0,0,114,6,0,0,0,218,14,105,109, + 112,108,101,109,101,110,116,97,116,105,111,110,218,9,99,97, + 99,104,101,95,116,97,103,218,19,78,111,116,73,109,112,108, + 101,109,101,110,116,101,100,69,114,114,111,114,114,26,0,0, + 0,218,5,102,108,97,103,115,218,8,111,112,116,105,109,105, + 122,101,218,3,115,116,114,218,7,105,115,97,108,110,117,109, + 218,10,86,97,108,117,101,69,114,114,111,114,114,48,0,0, + 0,218,4,95,79,80,84,114,28,0,0,0,218,8,95,80, + 89,67,65,67,72,69,218,17,66,89,84,69,67,79,68,69, + 95,83,85,70,70,73,88,69,83,41,11,114,35,0,0,0, + 90,14,100,101,98,117,103,95,111,118,101,114,114,105,100,101, + 114,58,0,0,0,218,7,109,101,115,115,97,103,101,218,4, + 104,101,97,100,114,37,0,0,0,90,4,98,97,115,101,218, + 3,115,101,112,218,4,114,101,115,116,90,3,116,97,103,90, + 15,97,108,109,111,115,116,95,102,105,108,101,110,97,109,101, + 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,14,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,0,0,0,0,0,0,0,8,0,0,0,5,0,0, + 0,67,0,0,0,115,230,0,0,0,116,0,106,1,106,2, + 100,1,107,8,114,20,116,3,100,2,131,1,130,1,116,4, + 160,5,124,0,161,1,125,0,116,6,124,0,131,1,92,2, + 125,1,125,2,116,6,124,1,131,1,92,2,125,1,125,3, + 124,3,116,7,107,3,114,78,116,8,100,3,160,9,116,7, + 124,0,161,2,131,1,130,1,124,2,160,10,100,4,161,1, + 125,4,124,4,100,5,107,7,114,112,116,8,100,6,160,9, + 124,2,161,1,131,1,130,1,110,86,124,4,100,7,107,2, + 114,198,124,2,160,11,100,4,100,8,161,2,100,9,25,0, + 125,5,124,5,160,12,116,13,161,1,115,160,116,8,100,10, + 160,9,116,13,161,1,131,1,130,1,124,5,116,14,116,13, + 131,1,100,1,133,2,25,0,125,6,124,6,160,15,161,0, + 115,198,116,8,100,11,160,9,124,5,161,1,131,1,130,1, + 124,2,160,16,100,4,161,1,100,12,25,0,125,7,116,17, + 124,1,124,7,116,18,100,12,25,0,23,0,131,2,83,0, + 41,13,97,110,1,0,0,71,105,118,101,110,32,116,104,101, + 32,112,97,116,104,32,116,111,32,97,32,46,112,121,99,46, + 32,102,105,108,101,44,32,114,101,116,117,114,110,32,116,104, + 101,32,112,97,116,104,32,116,111,32,105,116,115,32,46,112, + 121,32,102,105,108,101,46,10,10,32,32,32,32,84,104,101, + 32,46,112,121,99,32,102,105,108,101,32,100,111,101,115,32, + 110,111,116,32,110,101,101,100,32,116,111,32,101,120,105,115, + 116,59,32,116,104,105,115,32,115,105,109,112,108,121,32,114, + 101,116,117,114,110,115,32,116,104,101,32,112,97,116,104,32, + 116,111,10,32,32,32,32,116,104,101,32,46,112,121,32,102, + 105,108,101,32,99,97,108,99,117,108,97,116,101,100,32,116, + 111,32,99,111,114,114,101,115,112,111,110,100,32,116,111,32, + 116,104,101,32,46,112,121,99,32,102,105,108,101,46,32,32, + 73,102,32,112,97,116,104,32,100,111,101,115,10,32,32,32, + 32,110,111,116,32,99,111,110,102,111,114,109,32,116,111,32, + 80,69,80,32,51,49,52,55,47,52,56,56,32,102,111,114, + 109,97,116,44,32,86,97,108,117,101,69,114,114,111,114,32, + 119,105,108,108,32,98,101,32,114,97,105,115,101,100,46,32, + 73,102,10,32,32,32,32,115,121,115,46,105,109,112,108,101, + 109,101,110,116,97,116,105,111,110,46,99,97,99,104,101,95, + 116,97,103,32,105,115,32,78,111,110,101,32,116,104,101,110, + 32,78,111,116,73,109,112,108,101,109,101,110,116,101,100,69, + 114,114,111,114,32,105,115,32,114,97,105,115,101,100,46,10, + 10,32,32,32,32,78,122,36,115,121,115,46,105,109,112,108, + 101,109,101,110,116,97,116,105,111,110,46,99,97,99,104,101, + 95,116,97,103,32,105,115,32,78,111,110,101,122,37,123,125, + 32,110,111,116,32,98,111,116,116,111,109,45,108,101,118,101, + 108,32,100,105,114,101,99,116,111,114,121,32,105,110,32,123, + 33,114,125,114,59,0,0,0,62,2,0,0,0,114,57,0, + 0,0,233,3,0,0,0,122,33,101,120,112,101,99,116,101, + 100,32,111,110,108,121,32,50,32,111,114,32,51,32,100,111, + 116,115,32,105,110,32,123,33,114,125,114,82,0,0,0,114, + 57,0,0,0,233,254,255,255,255,122,57,111,112,116,105,109, + 105,122,97,116,105,111,110,32,112,111,114,116,105,111,110,32, + 111,102,32,102,105,108,101,110,97,109,101,32,100,111,101,115, + 32,110,111,116,32,115,116,97,114,116,32,119,105,116,104,32, + 123,33,114,125,122,52,111,112,116,105,109,105,122,97,116,105, + 111,110,32,108,101,118,101,108,32,123,33,114,125,32,105,115, + 32,110,111,116,32,97,110,32,97,108,112,104,97,110,117,109, + 101,114,105,99,32,118,97,108,117,101,114,60,0,0,0,41, + 19,114,6,0,0,0,114,66,0,0,0,114,67,0,0,0, + 114,68,0,0,0,114,1,0,0,0,114,65,0,0,0,114, + 38,0,0,0,114,75,0,0,0,114,73,0,0,0,114,48, + 0,0,0,218,5,99,111,117,110,116,114,34,0,0,0,114, + 8,0,0,0,114,74,0,0,0,114,31,0,0,0,114,72, + 0,0,0,218,9,112,97,114,116,105,116,105,111,110,114,28, + 0,0,0,218,15,83,79,85,82,67,69,95,83,85,70,70, + 73,88,69,83,41,8,114,35,0,0,0,114,78,0,0,0, + 90,16,112,121,99,97,99,104,101,95,102,105,108,101,110,97, + 109,101,90,7,112,121,99,97,99,104,101,90,9,100,111,116, + 95,99,111,117,110,116,114,58,0,0,0,90,9,111,112,116, + 95,108,101,118,101,108,90,13,98,97,115,101,95,102,105,108, + 101,110,97,109,101,114,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,59,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,0,99,1,0,0,0,0,0,0,0,5,0,0,0, + 9,0,0,0,67,0,0,0,115,126,0,0,0,116,0,124, + 0,131,1,100,1,107,2,114,16,100,2,83,0,124,0,160, + 1,100,3,161,1,92,3,125,1,125,2,125,3,124,1,114, + 56,124,3,160,2,161,0,100,4,100,5,133,2,25,0,100, + 6,107,3,114,60,124,0,83,0,122,12,116,3,124,0,131, + 1,125,4,87,0,110,36,4,0,116,4,116,5,102,2,107, + 10,114,108,1,0,1,0,1,0,124,0,100,2,100,5,133, + 2,25,0,125,4,89,0,110,2,88,0,116,6,124,4,131, + 1,114,122,124,4,83,0,124,0,83,0,41,7,122,188,67, + 111,110,118,101,114,116,32,97,32,98,121,116,101,99,111,100, + 101,32,102,105,108,101,32,112,97,116,104,32,116,111,32,97, + 32,115,111,117,114,99,101,32,112,97,116,104,32,40,105,102, + 32,112,111,115,115,105,98,108,101,41,46,10,10,32,32,32, + 32,84,104,105,115,32,102,117,110,99,116,105,111,110,32,101, + 120,105,115,116,115,32,112,117,114,101,108,121,32,102,111,114, + 32,98,97,99,107,119,97,114,100,115,45,99,111,109,112,97, + 116,105,98,105,108,105,116,121,32,102,111,114,10,32,32,32, + 32,80,121,73,109,112,111,114,116,95,69,120,101,99,67,111, + 100,101,77,111,100,117,108,101,87,105,116,104,70,105,108,101, + 110,97,109,101,115,40,41,32,105,110,32,116,104,101,32,67, + 32,65,80,73,46,10,10,32,32,32,32,114,60,0,0,0, + 78,114,59,0,0,0,233,253,255,255,255,233,255,255,255,255, + 90,2,112,121,41,7,114,31,0,0,0,114,32,0,0,0, + 218,5,108,111,119,101,114,114,87,0,0,0,114,68,0,0, + 0,114,73,0,0,0,114,44,0,0,0,41,5,218,13,98, + 121,116,101,99,111,100,101,95,112,97,116,104,114,80,0,0, + 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,93,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,0,0,0,115,74,0,0,0,124,0,160,0,116,1, + 116,2,131,1,161,1,114,48,122,10,116,3,124,0,131,1, + 87,0,83,0,4,0,116,4,107,10,114,44,1,0,1,0, + 1,0,89,0,113,70,88,0,110,22,124,0,160,0,116,1, + 116,5,131,1,161,1,114,66,124,0,83,0,100,0,83,0, + 100,0,83,0,41,1,78,41,6,218,8,101,110,100,115,119, + 105,116,104,218,5,116,117,112,108,101,114,86,0,0,0,114, + 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,112,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, + 116,0,124,0,131,1,106,1,125,1,87,0,110,24,4,0, + 116,2,107,10,114,38,1,0,1,0,1,0,100,1,125,1, + 89,0,110,2,88,0,124,1,100,2,79,0,125,1,124,1, + 83,0,41,3,122,51,67,97,108,99,117,108,97,116,101,32, + 116,104,101,32,109,111,100,101,32,112,101,114,109,105,115,115, + 105,111,110,115,32,102,111,114,32,97,32,98,121,116,101,99, + 111,100,101,32,102,105,108,101,46,105,182,1,0,0,233,128, + 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,124,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,1,100,2,100,3,132,9,125,1,122,10,116, + 0,106,1,125,2,87,0,110,28,4,0,116,2,107,10,114, + 52,1,0,1,0,1,0,100,4,100,5,132,0,125,2,89, + 0,110,2,88,0,124,2,124,1,136,0,131,2,1,0,124, + 1,83,0,41,7,122,252,68,101,99,111,114,97,116,111,114, + 32,116,111,32,118,101,114,105,102,121,32,116,104,97,116,32, + 116,104,101,32,109,111,100,117,108,101,32,98,101,105,110,103, + 32,114,101,113,117,101,115,116,101,100,32,109,97,116,99,104, + 101,115,32,116,104,101,32,111,110,101,32,116,104,101,10,32, + 32,32,32,108,111,97,100,101,114,32,99,97,110,32,104,97, + 110,100,108,101,46,10,10,32,32,32,32,84,104,101,32,102, + 105,114,115,116,32,97,114,103,117,109,101,110,116,32,40,115, + 101,108,102,41,32,109,117,115,116,32,100,101,102,105,110,101, + 32,95,110,97,109,101,32,119,104,105,99,104,32,116,104,101, + 32,115,101,99,111,110,100,32,97,114,103,117,109,101,110,116, + 32,105,115,10,32,32,32,32,99,111,109,112,97,114,101,100, + 32,97,103,97,105,110,115,116,46,32,73,102,32,116,104,101, + 32,99,111,109,112,97,114,105,115,111,110,32,102,97,105,108, + 115,32,116,104,101,110,32,73,109,112,111,114,116,69,114,114, 111,114,32,105,115,32,114,97,105,115,101,100,46,10,10,32, - 32,32,32,78,122,36,115,121,115,46,105,109,112,108,101,109, - 101,110,116,97,116,105,111,110,46,99,97,99,104,101,95,116, - 97,103,32,105,115,32,78,111,110,101,122,37,123,125,32,110, - 111,116,32,98,111,116,116,111,109,45,108,101,118,101,108,32, - 100,105,114,101,99,116,111,114,121,32,105,110,32,123,33,114, - 125,114,59,0,0,0,62,2,0,0,0,114,57,0,0,0, - 233,3,0,0,0,122,33,101,120,112,101,99,116,101,100,32, - 111,110,108,121,32,50,32,111,114,32,51,32,100,111,116,115, - 32,105,110,32,123,33,114,125,114,82,0,0,0,114,57,0, - 0,0,233,254,255,255,255,122,57,111,112,116,105,109,105,122, - 97,116,105,111,110,32,112,111,114,116,105,111,110,32,111,102, - 32,102,105,108,101,110,97,109,101,32,100,111,101,115,32,110, - 111,116,32,115,116,97,114,116,32,119,105,116,104,32,123,33, - 114,125,122,52,111,112,116,105,109,105,122,97,116,105,111,110, - 32,108,101,118,101,108,32,123,33,114,125,32,105,115,32,110, - 111,116,32,97,110,32,97,108,112,104,97,110,117,109,101,114, - 105,99,32,118,97,108,117,101,114,60,0,0,0,41,19,114, - 6,0,0,0,114,66,0,0,0,114,67,0,0,0,114,68, - 0,0,0,114,1,0,0,0,114,65,0,0,0,114,38,0, - 0,0,114,75,0,0,0,114,73,0,0,0,114,48,0,0, - 0,218,5,99,111,117,110,116,114,34,0,0,0,114,8,0, - 0,0,114,74,0,0,0,114,31,0,0,0,114,72,0,0, - 0,218,9,112,97,114,116,105,116,105,111,110,114,28,0,0, - 0,218,15,83,79,85,82,67,69,95,83,85,70,70,73,88, - 69,83,41,8,114,35,0,0,0,114,78,0,0,0,90,16, - 112,121,99,97,99,104,101,95,102,105,108,101,110,97,109,101, - 90,7,112,121,99,97,99,104,101,90,9,100,111,116,95,99, - 111,117,110,116,114,58,0,0,0,90,9,111,112,116,95,108, - 101,118,101,108,90,13,98,97,115,101,95,102,105,108,101,110, - 97,109,101,114,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, - 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, - 0,99,1,0,0,0,0,0,0,0,5,0,0,0,9,0, - 0,0,67,0,0,0,115,126,0,0,0,116,0,124,0,131, - 1,100,1,107,2,114,16,100,2,83,0,124,0,160,1,100, - 3,161,1,92,3,125,1,125,2,125,3,124,1,114,56,124, - 3,160,2,161,0,100,4,100,5,133,2,25,0,100,6,107, - 3,114,60,124,0,83,0,121,12,116,3,124,0,131,1,125, - 4,87,0,110,36,4,0,116,4,116,5,102,2,107,10,114, - 108,1,0,1,0,1,0,124,0,100,2,100,5,133,2,25, - 0,125,4,89,0,110,2,88,0,116,6,124,4,131,1,114, - 122,124,4,83,0,124,0,83,0,41,7,122,188,67,111,110, - 118,101,114,116,32,97,32,98,121,116,101,99,111,100,101,32, - 102,105,108,101,32,112,97,116,104,32,116,111,32,97,32,115, - 111,117,114,99,101,32,112,97,116,104,32,40,105,102,32,112, - 111,115,115,105,98,108,101,41,46,10,10,32,32,32,32,84, - 104,105,115,32,102,117,110,99,116,105,111,110,32,101,120,105, - 115,116,115,32,112,117,114,101,108,121,32,102,111,114,32,98, - 97,99,107,119,97,114,100,115,45,99,111,109,112,97,116,105, - 98,105,108,105,116,121,32,102,111,114,10,32,32,32,32,80, - 121,73,109,112,111,114,116,95,69,120,101,99,67,111,100,101, - 77,111,100,117,108,101,87,105,116,104,70,105,108,101,110,97, - 109,101,115,40,41,32,105,110,32,116,104,101,32,67,32,65, - 80,73,46,10,10,32,32,32,32,114,60,0,0,0,78,114, - 59,0,0,0,233,253,255,255,255,233,255,255,255,255,90,2, - 112,121,41,7,114,31,0,0,0,114,32,0,0,0,218,5, - 108,111,119,101,114,114,87,0,0,0,114,68,0,0,0,114, - 73,0,0,0,114,44,0,0,0,41,5,218,13,98,121,116, - 101,99,111,100,101,95,112,97,116,104,114,80,0,0,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,92,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, - 0,0,0,115,72,0,0,0,124,0,160,0,116,1,116,2, - 131,1,161,1,114,46,121,8,116,3,124,0,131,1,83,0, - 4,0,116,4,107,10,114,42,1,0,1,0,1,0,89,0, - 113,68,88,0,110,22,124,0,160,0,116,1,116,5,131,1, - 161,1,114,64,124,0,83,0,100,0,83,0,100,0,83,0, - 41,1,78,41,6,218,8,101,110,100,115,119,105,116,104,218, - 5,116,117,112,108,101,114,86,0,0,0,114,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,111,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, - 131,1,106,1,125,1,87,0,110,24,4,0,116,2,107,10, - 114,38,1,0,1,0,1,0,100,1,125,1,89,0,110,2, - 88,0,124,1,100,2,79,0,125,1,124,1,83,0,41,3, - 122,51,67,97,108,99,117,108,97,116,101,32,116,104,101,32, - 109,111,100,101,32,112,101,114,109,105,115,115,105,111,110,115, - 32,102,111,114,32,97,32,98,121,116,101,99,111,100,101,32, - 102,105,108,101,46,105,182,1,0,0,233,128,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,123,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, - 1,100,2,100,3,132,9,125,1,121,10,116,0,106,1,125, - 2,87,0,110,28,4,0,116,2,107,10,114,52,1,0,1, - 0,1,0,100,4,100,5,132,0,125,2,89,0,110,2,88, - 0,124,2,124,1,136,0,131,2,1,0,124,1,83,0,41, - 7,122,252,68,101,99,111,114,97,116,111,114,32,116,111,32, - 118,101,114,105,102,121,32,116,104,97,116,32,116,104,101,32, - 109,111,100,117,108,101,32,98,101,105,110,103,32,114,101,113, - 117,101,115,116,101,100,32,109,97,116,99,104,101,115,32,116, - 104,101,32,111,110,101,32,116,104,101,10,32,32,32,32,108, - 111,97,100,101,114,32,99,97,110,32,104,97,110,100,108,101, - 46,10,10,32,32,32,32,84,104,101,32,102,105,114,115,116, - 32,97,114,103,117,109,101,110,116,32,40,115,101,108,102,41, - 32,109,117,115,116,32,100,101,102,105,110,101,32,95,110,97, - 109,101,32,119,104,105,99,104,32,116,104,101,32,115,101,99, - 111,110,100,32,97,114,103,117,109,101,110,116,32,105,115,10, - 32,32,32,32,99,111,109,112,97,114,101,100,32,97,103,97, - 105,110,115,116,46,32,73,102,32,116,104,101,32,99,111,109, - 112,97,114,105,115,111,110,32,102,97,105,108,115,32,116,104, - 101,110,32,73,109,112,111,114,116,69,114,114,111,114,32,105, - 115,32,114,97,105,115,101,100,46,10,10,32,32,32,32,78, - 99,2,0,0,0,0,0,0,0,4,0,0,0,4,0,0, - 0,31,0,0,0,115,66,0,0,0,124,1,100,0,107,8, - 114,16,124,0,106,0,125,1,110,32,124,0,106,0,124,1, - 107,3,114,48,116,1,100,1,124,0,106,0,124,1,102,2, - 22,0,124,1,100,2,141,2,130,1,136,0,124,0,124,1, - 102,2,124,2,158,2,124,3,142,1,83,0,41,3,78,122, - 30,108,111,97,100,101,114,32,102,111,114,32,37,115,32,99, - 97,110,110,111,116,32,104,97,110,100,108,101,32,37,115,41, - 1,218,4,110,97,109,101,41,2,114,100,0,0,0,218,11, - 73,109,112,111,114,116,69,114,114,111,114,41,4,218,4,115, - 101,108,102,114,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, - 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,101,114,99,2, - 0,0,0,0,0,0,0,3,0,0,0,7,0,0,0,83, - 0,0,0,115,60,0,0,0,120,40,100,1,68,0,93,32, - 125,2,116,0,124,1,124,2,131,2,114,6,116,1,124,0, - 124,2,116,2,124,1,124,2,131,2,131,3,1,0,113,6, - 87,0,124,0,106,3,160,4,124,1,106,3,161,1,1,0, + 32,32,32,78,99,2,0,0,0,0,0,0,0,4,0,0, + 0,4,0,0,0,31,0,0,0,115,66,0,0,0,124,1, + 100,0,107,8,114,16,124,0,106,0,125,1,110,32,124,0, + 106,0,124,1,107,3,114,48,116,1,100,1,124,0,106,0, + 124,1,102,2,22,0,124,1,100,2,141,2,130,1,136,0, + 124,0,124,1,102,2,124,2,158,2,124,3,142,1,83,0, + 41,3,78,122,30,108,111,97,100,101,114,32,102,111,114,32, + 37,115,32,99,97,110,110,111,116,32,104,97,110,100,108,101, + 32,37,115,41,1,218,4,110,97,109,101,41,2,114,100,0, + 0,0,218,11,73,109,112,111,114,116,69,114,114,111,114,41, + 4,218,4,115,101,108,102,114,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,144,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, + 101,114,99,2,0,0,0,0,0,0,0,3,0,0,0,7, + 0,0,0,83,0,0,0,115,56,0,0,0,100,1,68,0, + 93,32,125,2,116,0,124,1,124,2,131,2,114,4,116,1, + 124,0,124,2,116,2,124,1,124,2,131,2,131,3,1,0, + 113,4,124,0,106,3,160,4,124,1,106,3,161,1,1,0, 100,0,83,0,41,2,78,41,4,218,10,95,95,109,111,100, 117,108,101,95,95,218,8,95,95,110,97,109,101,95,95,218, 12,95,95,113,117,97,108,110,97,109,101,95,95,218,7,95, @@ -539,15 +539,15 @@ 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, - 115,8,0,0,0,0,1,10,1,10,1,22,1,122,26,95, + 114,4,0,0,0,218,5,95,119,114,97,112,155,1,0,0, + 115,8,0,0,0,0,1,8,1,10,1,20,1,122,26,95, 99,104,101,99,107,95,110,97,109,101,46,60,108,111,99,97, 108,115,62,46,95,119,114,97,112,41,1,78,41,3,218,10, 95,98,111,111,116,115,116,114,97,112,114,115,0,0,0,218, 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,136,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,164,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, + 181,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,214,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,242,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,10,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,23,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,33,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,330 +829,354 @@ 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,44,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, 108,111,99,97,116,105,111,110,115,99,2,0,0,0,2,0, - 0,0,9,0,0,0,8,0,0,0,67,0,0,0,115,18, + 0,0,9,0,0,0,8,0,0,0,67,0,0,0,115,16, 1,0,0,124,1,100,1,107,8,114,60,100,2,125,1,116, - 0,124,2,100,3,131,2,114,70,121,14,124,2,160,1,124, + 0,124,2,100,3,131,2,114,70,122,14,124,2,160,1,124, 0,161,1,125,1,87,0,113,70,4,0,116,2,107,10,114, 56,1,0,1,0,1,0,89,0,113,70,88,0,110,10,116, 3,160,4,124,1,161,1,125,1,116,5,106,6,124,0,124, 2,124,1,100,4,141,3,125,4,100,5,124,4,95,7,124, - 2,100,1,107,8,114,156,120,54,116,8,131,0,68,0,93, - 40,92,2,125,5,125,6,124,1,160,9,116,10,124,6,131, - 1,161,1,114,108,124,5,124,0,124,1,131,2,125,2,124, - 2,124,4,95,11,80,0,113,108,87,0,100,1,83,0,124, - 3,116,12,107,8,114,222,116,0,124,2,100,6,131,2,114, - 228,121,14,124,2,160,13,124,0,161,1,125,7,87,0,110, - 20,4,0,116,2,107,10,114,208,1,0,1,0,1,0,89, - 0,113,228,88,0,124,7,114,228,103,0,124,4,95,14,110, - 6,124,3,124,4,95,14,124,4,106,14,103,0,107,2,144, - 1,114,14,124,1,144,1,114,14,116,15,124,1,131,1,100, - 7,25,0,125,8,124,4,106,14,160,16,124,8,161,1,1, - 0,124,4,83,0,41,8,97,61,1,0,0,82,101,116,117, - 114,110,32,97,32,109,111,100,117,108,101,32,115,112,101,99, - 32,98,97,115,101,100,32,111,110,32,97,32,102,105,108,101, - 32,108,111,99,97,116,105,111,110,46,10,10,32,32,32,32, - 84,111,32,105,110,100,105,99,97,116,101,32,116,104,97,116, - 32,116,104,101,32,109,111,100,117,108,101,32,105,115,32,97, - 32,112,97,99,107,97,103,101,44,32,115,101,116,10,32,32, - 32,32,115,117,98,109,111,100,117,108,101,95,115,101,97,114, - 99,104,95,108,111,99,97,116,105,111,110,115,32,116,111,32, - 97,32,108,105,115,116,32,111,102,32,100,105,114,101,99,116, - 111,114,121,32,112,97,116,104,115,46,32,32,65,110,10,32, - 32,32,32,101,109,112,116,121,32,108,105,115,116,32,105,115, - 32,115,117,102,102,105,99,105,101,110,116,44,32,116,104,111, - 117,103,104,32,105,116,115,32,110,111,116,32,111,116,104,101, - 114,119,105,115,101,32,117,115,101,102,117,108,32,116,111,32, - 116,104,101,10,32,32,32,32,105,109,112,111,114,116,32,115, - 121,115,116,101,109,46,10,10,32,32,32,32,84,104,101,32, - 108,111,97,100,101,114,32,109,117,115,116,32,116,97,107,101, - 32,97,32,115,112,101,99,32,97,115,32,105,116,115,32,111, - 110,108,121,32,95,95,105,110,105,116,95,95,40,41,32,97, - 114,103,46,10,10,32,32,32,32,78,122,9,60,117,110,107, - 110,111,119,110,62,218,12,103,101,116,95,102,105,108,101,110, - 97,109,101,41,1,218,6,111,114,105,103,105,110,84,218,10, - 105,115,95,112,97,99,107,97,103,101,114,60,0,0,0,41, - 17,114,110,0,0,0,114,159,0,0,0,114,101,0,0,0, - 114,1,0,0,0,114,65,0,0,0,114,116,0,0,0,218, - 10,77,111,100,117,108,101,83,112,101,99,90,13,95,115,101, - 116,95,102,105,108,101,97,116,116,114,218,27,95,103,101,116, - 95,115,117,112,112,111,114,116,101,100,95,102,105,108,101,95, - 108,111,97,100,101,114,115,114,94,0,0,0,114,95,0,0, - 0,114,122,0,0,0,218,9,95,80,79,80,85,76,65,84, - 69,114,161,0,0,0,114,158,0,0,0,114,38,0,0,0, - 218,6,97,112,112,101,110,100,41,9,114,100,0,0,0,90, - 8,108,111,99,97,116,105,111,110,114,122,0,0,0,114,158, - 0,0,0,218,4,115,112,101,99,218,12,108,111,97,100,101, - 114,95,99,108,97,115,115,218,8,115,117,102,102,105,120,101, - 115,114,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, - 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, - 4,1,8,2,6,1,12,1,6,1,12,1,12,2,114,169, - 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,80,0,0,0,101,0,90, - 1,100,0,90,2,100,1,90,3,100,2,90,4,100,3,90, - 5,100,4,90,6,101,7,100,5,100,6,132,0,131,1,90, - 8,101,7,100,7,100,8,132,0,131,1,90,9,101,7,100, - 14,100,10,100,11,132,1,131,1,90,10,101,7,100,15,100, - 12,100,13,132,1,131,1,90,11,100,9,83,0,41,16,218, - 21,87,105,110,100,111,119,115,82,101,103,105,115,116,114,121, - 70,105,110,100,101,114,122,62,77,101,116,97,32,112,97,116, - 104,32,102,105,110,100,101,114,32,102,111,114,32,109,111,100, - 117,108,101,115,32,100,101,99,108,97,114,101,100,32,105,110, - 32,116,104,101,32,87,105,110,100,111,119,115,32,114,101,103, - 105,115,116,114,121,46,122,59,83,111,102,116,119,97,114,101, - 92,80,121,116,104,111,110,92,80,121,116,104,111,110,67,111, - 114,101,92,123,115,121,115,95,118,101,114,115,105,111,110,125, - 92,77,111,100,117,108,101,115,92,123,102,117,108,108,110,97, - 109,101,125,122,65,83,111,102,116,119,97,114,101,92,80,121, - 116,104,111,110,92,80,121,116,104,111,110,67,111,114,101,92, - 123,115,121,115,95,118,101,114,115,105,111,110,125,92,77,111, - 100,117,108,101,115,92,123,102,117,108,108,110,97,109,101,125, - 92,68,101,98,117,103,70,99,2,0,0,0,0,0,0,0, - 2,0,0,0,8,0,0,0,67,0,0,0,115,50,0,0, - 0,121,14,116,0,160,1,116,0,106,2,124,1,161,2,83, - 0,4,0,116,3,107,10,114,44,1,0,1,0,1,0,116, - 0,160,1,116,0,106,4,124,1,161,2,83,0,88,0,100, - 0,83,0,41,1,78,41,5,218,7,95,119,105,110,114,101, - 103,90,7,79,112,101,110,75,101,121,90,17,72,75,69,89, - 95,67,85,82,82,69,78,84,95,85,83,69,82,114,40,0, - 0,0,90,18,72,75,69,89,95,76,79,67,65,76,95,77, - 65,67,72,73,78,69,41,2,218,3,99,108,115,114,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, - 14,1,122,36,87,105,110,100,111,119,115,82,101,103,105,115, - 116,114,121,70,105,110,100,101,114,46,95,111,112,101,110,95, - 114,101,103,105,115,116,114,121,99,2,0,0,0,0,0,0, - 0,6,0,0,0,9,0,0,0,67,0,0,0,115,112,0, - 0,0,124,0,106,0,114,14,124,0,106,1,125,2,110,6, - 124,0,106,2,125,2,124,2,106,3,124,1,100,1,116,4, - 106,5,100,0,100,2,133,2,25,0,22,0,100,3,141,2, - 125,3,121,38,124,0,160,6,124,3,161,1,143,18,125,4, - 116,7,160,8,124,4,100,4,161,2,125,5,87,0,100,0, - 81,0,82,0,88,0,87,0,110,20,4,0,116,9,107,10, - 114,106,1,0,1,0,1,0,100,0,83,0,88,0,124,5, - 83,0,41,5,78,122,5,37,100,46,37,100,114,57,0,0, - 0,41,2,114,121,0,0,0,90,11,115,121,115,95,118,101, - 114,115,105,111,110,114,30,0,0,0,41,10,218,11,68,69, - 66,85,71,95,66,85,73,76,68,218,18,82,69,71,73,83, - 84,82,89,95,75,69,89,95,68,69,66,85,71,218,12,82, - 69,71,73,83,84,82,89,95,75,69,89,114,48,0,0,0, - 114,6,0,0,0,218,12,118,101,114,115,105,111,110,95,105, - 110,102,111,114,173,0,0,0,114,171,0,0,0,90,10,81, - 117,101,114,121,86,97,108,117,101,114,40,0,0,0,41,6, - 114,172,0,0,0,114,121,0,0,0,90,12,114,101,103,105, - 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, - 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, + 2,100,1,107,8,114,154,116,8,131,0,68,0,93,42,92, + 2,125,5,125,6,124,1,160,9,116,10,124,6,131,1,161, + 1,114,106,124,5,124,0,124,1,131,2,125,2,124,2,124, + 4,95,11,1,0,113,154,113,106,100,1,83,0,124,3,116, + 12,107,8,114,220,116,0,124,2,100,6,131,2,114,226,122, + 14,124,2,160,13,124,0,161,1,125,7,87,0,110,20,4, + 0,116,2,107,10,114,206,1,0,1,0,1,0,89,0,113, + 226,88,0,124,7,114,226,103,0,124,4,95,14,110,6,124, + 3,124,4,95,14,124,4,106,14,103,0,107,2,144,1,114, + 12,124,1,144,1,114,12,116,15,124,1,131,1,100,7,25, + 0,125,8,124,4,106,14,160,16,124,8,161,1,1,0,124, + 4,83,0,41,8,97,61,1,0,0,82,101,116,117,114,110, + 32,97,32,109,111,100,117,108,101,32,115,112,101,99,32,98, + 97,115,101,100,32,111,110,32,97,32,102,105,108,101,32,108, + 111,99,97,116,105,111,110,46,10,10,32,32,32,32,84,111, + 32,105,110,100,105,99,97,116,101,32,116,104,97,116,32,116, + 104,101,32,109,111,100,117,108,101,32,105,115,32,97,32,112, + 97,99,107,97,103,101,44,32,115,101,116,10,32,32,32,32, + 115,117,98,109,111,100,117,108,101,95,115,101,97,114,99,104, + 95,108,111,99,97,116,105,111,110,115,32,116,111,32,97,32, + 108,105,115,116,32,111,102,32,100,105,114,101,99,116,111,114, + 121,32,112,97,116,104,115,46,32,32,65,110,10,32,32,32, + 32,101,109,112,116,121,32,108,105,115,116,32,105,115,32,115, + 117,102,102,105,99,105,101,110,116,44,32,116,104,111,117,103, + 104,32,105,116,115,32,110,111,116,32,111,116,104,101,114,119, + 105,115,101,32,117,115,101,102,117,108,32,116,111,32,116,104, + 101,10,32,32,32,32,105,109,112,111,114,116,32,115,121,115, + 116,101,109,46,10,10,32,32,32,32,84,104,101,32,108,111, + 97,100,101,114,32,109,117,115,116,32,116,97,107,101,32,97, + 32,115,112,101,99,32,97,115,32,105,116,115,32,111,110,108, + 121,32,95,95,105,110,105,116,95,95,40,41,32,97,114,103, + 46,10,10,32,32,32,32,78,122,9,60,117,110,107,110,111, + 119,110,62,218,12,103,101,116,95,102,105,108,101,110,97,109, + 101,41,1,218,6,111,114,105,103,105,110,84,218,10,105,115, + 95,112,97,99,107,97,103,101,114,60,0,0,0,41,17,114, + 110,0,0,0,114,159,0,0,0,114,101,0,0,0,114,1, + 0,0,0,114,65,0,0,0,114,116,0,0,0,218,10,77, + 111,100,117,108,101,83,112,101,99,90,13,95,115,101,116,95, + 102,105,108,101,97,116,116,114,218,27,95,103,101,116,95,115, + 117,112,112,111,114,116,101,100,95,102,105,108,101,95,108,111, + 97,100,101,114,115,114,94,0,0,0,114,95,0,0,0,114, + 122,0,0,0,218,9,95,80,79,80,85,76,65,84,69,114, + 161,0,0,0,114,158,0,0,0,114,38,0,0,0,218,6, + 97,112,112,101,110,100,41,9,114,100,0,0,0,90,8,108, + 111,99,97,116,105,111,110,114,122,0,0,0,114,158,0,0, + 0,218,4,115,112,101,99,218,12,108,111,97,100,101,114,95, + 99,108,97,115,115,218,8,115,117,102,102,105,120,101,115,114, + 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,61,2,0,0,115,62,0,0,0,0,12, + 8,4,4,1,10,2,2,1,14,1,14,1,8,2,10,8, + 16,1,6,3,8,1,14,1,14,1,10,1,6,1,6,2, + 4,3,8,2,10,1,2,1,14,1,14,1,6,2,4,1, + 8,2,6,1,12,1,6,1,12,1,12,2,114,169,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,80,0,0,0,101,0,90,1,100, + 0,90,2,100,1,90,3,100,2,90,4,100,3,90,5,100, + 4,90,6,101,7,100,5,100,6,132,0,131,1,90,8,101, + 7,100,7,100,8,132,0,131,1,90,9,101,7,100,14,100, + 10,100,11,132,1,131,1,90,10,101,7,100,15,100,12,100, + 13,132,1,131,1,90,11,100,9,83,0,41,16,218,21,87, 105,110,100,111,119,115,82,101,103,105,115,116,114,121,70,105, - 110,100,101,114,46,95,115,101,97,114,99,104,95,114,101,103, - 105,115,116,114,121,78,99,4,0,0,0,0,0,0,0,8, - 0,0,0,8,0,0,0,67,0,0,0,115,120,0,0,0, - 124,0,160,0,124,1,161,1,125,4,124,4,100,0,107,8, - 114,22,100,0,83,0,121,12,116,1,124,4,131,1,1,0, - 87,0,110,20,4,0,116,2,107,10,114,54,1,0,1,0, - 1,0,100,0,83,0,88,0,120,58,116,3,131,0,68,0, - 93,48,92,2,125,5,125,6,124,4,160,4,116,5,124,6, - 131,1,161,1,114,64,116,6,106,7,124,1,124,5,124,1, - 124,4,131,2,124,4,100,1,141,3,125,7,124,7,83,0, - 113,64,87,0,100,0,83,0,41,2,78,41,1,114,160,0, - 0,0,41,8,114,179,0,0,0,114,39,0,0,0,114,40, - 0,0,0,114,163,0,0,0,114,94,0,0,0,114,95,0, - 0,0,114,116,0,0,0,218,16,115,112,101,99,95,102,114, - 111,109,95,108,111,97,100,101,114,41,8,114,172,0,0,0, - 114,121,0,0,0,114,35,0,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, - 162,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, - 115,112,101,99,99,3,0,0,0,0,0,0,0,4,0,0, - 0,4,0,0,0,67,0,0,0,115,34,0,0,0,124,0, - 160,0,124,1,124,2,161,2,125,3,124,3,100,1,107,9, - 114,26,124,3,106,1,83,0,100,1,83,0,100,1,83,0, - 41,2,122,108,70,105,110,100,32,109,111,100,117,108,101,32, - 110,97,109,101,100,32,105,110,32,116,104,101,32,114,101,103, - 105,115,116,114,121,46,10,10,32,32,32,32,32,32,32,32, - 84,104,105,115,32,109,101,116,104,111,100,32,105,115,32,100, - 101,112,114,101,99,97,116,101,100,46,32,32,85,115,101,32, - 101,120,101,99,95,109,111,100,117,108,101,40,41,32,105,110, - 115,116,101,97,100,46,10,10,32,32,32,32,32,32,32,32, - 78,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, - 2,0,0,115,8,0,0,0,0,7,12,1,8,1,6,2, - 122,33,87,105,110,100,111,119,115,82,101,103,105,115,116,114, - 121,70,105,110,100,101,114,46,102,105,110,100,95,109,111,100, - 117,108,101,41,2,78,78,41,1,78,41,12,114,107,0,0, - 0,114,106,0,0,0,114,108,0,0,0,114,109,0,0,0, - 114,176,0,0,0,114,175,0,0,0,114,174,0,0,0,218, - 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, - 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, + 110,100,101,114,122,62,77,101,116,97,32,112,97,116,104,32, + 102,105,110,100,101,114,32,102,111,114,32,109,111,100,117,108, + 101,115,32,100,101,99,108,97,114,101,100,32,105,110,32,116, + 104,101,32,87,105,110,100,111,119,115,32,114,101,103,105,115, + 116,114,121,46,122,59,83,111,102,116,119,97,114,101,92,80, + 121,116,104,111,110,92,80,121,116,104,111,110,67,111,114,101, + 92,123,115,121,115,95,118,101,114,115,105,111,110,125,92,77, + 111,100,117,108,101,115,92,123,102,117,108,108,110,97,109,101, + 125,122,65,83,111,102,116,119,97,114,101,92,80,121,116,104, + 111,110,92,80,121,116,104,111,110,67,111,114,101,92,123,115, + 121,115,95,118,101,114,115,105,111,110,125,92,77,111,100,117, + 108,101,115,92,123,102,117,108,108,110,97,109,101,125,92,68, + 101,98,117,103,70,99,2,0,0,0,0,0,0,0,2,0, + 0,0,8,0,0,0,67,0,0,0,115,56,0,0,0,122, + 16,116,0,160,1,116,0,106,2,124,1,161,2,87,0,83, + 0,4,0,116,3,107,10,114,50,1,0,1,0,1,0,116, + 0,160,1,116,0,106,4,124,1,161,2,6,0,89,0,83, + 0,88,0,100,0,83,0,41,1,78,41,5,218,7,95,119, + 105,110,114,101,103,90,7,79,112,101,110,75,101,121,90,17, + 72,75,69,89,95,67,85,82,82,69,78,84,95,85,83,69, + 82,114,40,0,0,0,90,18,72,75,69,89,95,76,79,67, + 65,76,95,77,65,67,72,73,78,69,41,2,218,3,99,108, + 115,114,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,141,2,0,0,115,8,0,0,0,0,2, + 2,1,16,1,14,1,122,36,87,105,110,100,111,119,115,82, + 101,103,105,115,116,114,121,70,105,110,100,101,114,46,95,111, + 112,101,110,95,114,101,103,105,115,116,114,121,99,2,0,0, + 0,0,0,0,0,6,0,0,0,9,0,0,0,67,0,0, + 0,115,114,0,0,0,124,0,106,0,114,14,124,0,106,1, + 125,2,110,6,124,0,106,2,125,2,124,2,106,3,124,1, + 100,1,116,4,106,5,100,0,100,2,133,2,25,0,22,0, + 100,3,141,2,125,3,122,38,124,0,160,6,124,3,161,1, + 143,18,125,4,116,7,160,8,124,4,100,4,161,2,125,5, + 87,0,53,0,81,0,82,0,88,0,87,0,110,22,4,0, + 116,9,107,10,114,108,1,0,1,0,1,0,89,0,100,0, + 83,0,88,0,124,5,83,0,41,5,78,122,5,37,100,46, + 37,100,114,57,0,0,0,41,2,114,121,0,0,0,90,11, + 115,121,115,95,118,101,114,115,105,111,110,114,30,0,0,0, + 41,10,218,11,68,69,66,85,71,95,66,85,73,76,68,218, + 18,82,69,71,73,83,84,82,89,95,75,69,89,95,68,69, + 66,85,71,218,12,82,69,71,73,83,84,82,89,95,75,69, + 89,114,48,0,0,0,114,6,0,0,0,218,12,118,101,114, + 115,105,111,110,95,105,110,102,111,114,173,0,0,0,114,171, + 0,0,0,90,10,81,117,101,114,121,86,97,108,117,101,114, + 40,0,0,0,41,6,114,172,0,0,0,114,121,0,0,0, + 90,12,114,101,103,105,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,148,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, + 99,104,95,114,101,103,105,115,116,114,121,78,99,4,0,0, + 0,0,0,0,0,8,0,0,0,8,0,0,0,67,0,0, + 0,115,122,0,0,0,124,0,160,0,124,1,161,1,125,4, + 124,4,100,0,107,8,114,22,100,0,83,0,122,12,116,1, + 124,4,131,1,1,0,87,0,110,22,4,0,116,2,107,10, + 114,56,1,0,1,0,1,0,89,0,100,0,83,0,88,0, + 116,3,131,0,68,0,93,52,92,2,125,5,125,6,124,4, + 160,4,116,5,124,6,131,1,161,1,114,64,116,6,106,7, + 124,1,124,5,124,1,124,4,131,2,124,4,100,1,141,3, + 125,7,124,7,2,0,1,0,83,0,113,64,100,0,83,0, + 41,2,78,41,1,114,160,0,0,0,41,8,114,179,0,0, + 0,114,39,0,0,0,114,40,0,0,0,114,163,0,0,0, + 114,94,0,0,0,114,95,0,0,0,114,116,0,0,0,218, + 16,115,112,101,99,95,102,114,111,109,95,108,111,97,100,101, + 114,41,8,114,172,0,0,0,114,121,0,0,0,114,35,0, + 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,163,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, + 101,114,46,102,105,110,100,95,115,112,101,99,99,3,0,0, + 0,0,0,0,0,4,0,0,0,4,0,0,0,67,0,0, + 0,115,34,0,0,0,124,0,160,0,124,1,124,2,161,2, + 125,3,124,3,100,1,107,9,114,26,124,3,106,1,83,0, + 100,1,83,0,100,1,83,0,41,2,122,108,70,105,110,100, + 32,109,111,100,117,108,101,32,110,97,109,101,100,32,105,110, + 32,116,104,101,32,114,101,103,105,115,116,114,121,46,10,10, + 32,32,32,32,32,32,32,32,84,104,105,115,32,109,101,116, + 104,111,100,32,105,115,32,100,101,112,114,101,99,97,116,101, + 100,46,32,32,85,115,101,32,101,120,101,99,95,109,111,100, + 117,108,101,40,41,32,105,110,115,116,101,97,100,46,10,10, + 32,32,32,32,32,32,32,32,78,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,179,2,0,0,115,8,0,0,0, + 0,7,12,1,8,1,6,2,122,33,87,105,110,100,111,119, + 115,82,101,103,105,115,116,114,121,70,105,110,100,101,114,46, + 102,105,110,100,95,109,111,100,117,108,101,41,2,78,78,41, + 1,78,41,12,114,107,0,0,0,114,106,0,0,0,114,108, + 0,0,0,114,109,0,0,0,114,176,0,0,0,114,175,0, + 0,0,114,174,0,0,0,218,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,129,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,198, + 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,206,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,209,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,217,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, + 193,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,224,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,232,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,245,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, @@ -1161,936 +1185,913 @@ const unsigned char _Py_M__importlib_external[] = { 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, + 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,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,0,0,114,198,0,0,0,255,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,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,6,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, - 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, - 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, + 218,14,115,111,117,114,99,101,95,116,111,95,99,111,100,101, + 16,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,24,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,222,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,115,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,121,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,125,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, + 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,128,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,140,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,145,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,152,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,158,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,162,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,168,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,174,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,110,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,182,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,187,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,192,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,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,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,178,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,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, + 114,188,0,0,0,227,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,243,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,223,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,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, + 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, - 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, + 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, + 4,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,8,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,12,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, + 15,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,23, + 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,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, - 111,32,115,111,117,114,99,101,32,99,111,100,101,46,78,114, + 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,32,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,29,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, - 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, - 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, - 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,2,100,3,132,0,90, - 4,100,4,100,5,132,0,90,5,100,6,100,7,132,0,90, - 6,100,8,100,9,132,0,90,7,100,10,100,11,132,0,90, - 8,100,12,100,13,132,0,90,9,100,14,100,15,132,0,90, - 10,100,16,100,17,132,0,90,11,100,18,100,19,132,0,90, - 12,100,20,100,21,132,0,90,13,100,22,83,0,41,23,218, - 14,95,78,97,109,101,115,112,97,99,101,80,97,116,104,97, - 38,1,0,0,82,101,112,114,101,115,101,110,116,115,32,97, - 32,110,97,109,101,115,112,97,99,101,32,112,97,99,107,97, - 103,101,39,115,32,112,97,116,104,46,32,32,73,116,32,117, - 115,101,115,32,116,104,101,32,109,111,100,117,108,101,32,110, - 97,109,101,10,32,32,32,32,116,111,32,102,105,110,100,32, - 105,116,115,32,112,97,114,101,110,116,32,109,111,100,117,108, - 101,44,32,97,110,100,32,102,114,111,109,32,116,104,101,114, - 101,32,105,116,32,108,111,111,107,115,32,117,112,32,116,104, - 101,32,112,97,114,101,110,116,39,115,10,32,32,32,32,95, - 95,112,97,116,104,95,95,46,32,32,87,104,101,110,32,116, - 104,105,115,32,99,104,97,110,103,101,115,44,32,116,104,101, - 32,109,111,100,117,108,101,39,115,32,111,119,110,32,112,97, - 116,104,32,105,115,32,114,101,99,111,109,112,117,116,101,100, - 44,10,32,32,32,32,117,115,105,110,103,32,112,97,116,104, - 95,102,105,110,100,101,114,46,32,32,70,111,114,32,116,111, - 112,45,108,101,118,101,108,32,109,111,100,117,108,101,115,44, - 32,116,104,101,32,112,97,114,101,110,116,32,109,111,100,117, - 108,101,39,115,32,112,97,116,104,10,32,32,32,32,105,115, - 32,115,121,115,46,112,97,116,104,46,99,4,0,0,0,0, - 0,0,0,4,0,0,0,3,0,0,0,67,0,0,0,115, - 36,0,0,0,124,1,124,0,95,0,124,2,124,0,95,1, - 116,2,124,0,160,3,161,0,131,1,124,0,95,4,124,3, - 124,0,95,5,100,0,83,0,41,1,78,41,6,218,5,95, - 110,97,109,101,218,5,95,112,97,116,104,114,95,0,0,0, - 218,16,95,103,101,116,95,112,97,114,101,110,116,95,112,97, - 116,104,218,17,95,108,97,115,116,95,112,97,114,101,110,116, - 95,112,97,116,104,218,12,95,112,97,116,104,95,102,105,110, - 100,101,114,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, - 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, - 67,0,0,0,115,38,0,0,0,124,0,106,0,160,1,100, - 1,161,1,92,3,125,1,125,2,125,3,124,2,100,2,107, - 2,114,30,100,3,83,0,124,1,100,4,102,2,83,0,41, - 5,122,62,82,101,116,117,114,110,115,32,97,32,116,117,112, - 108,101,32,111,102,32,40,112,97,114,101,110,116,45,109,111, - 100,117,108,101,45,110,97,109,101,44,32,112,97,114,101,110, - 116,45,112,97,116,104,45,97,116,116,114,45,110,97,109,101, - 41,114,59,0,0,0,114,30,0,0,0,41,2,114,6,0, - 0,0,114,35,0,0,0,90,8,95,95,112,97,116,104,95, - 95,41,2,114,242,0,0,0,114,32,0,0,0,41,4,114, - 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, - 0,0,0,0,2,18,1,8,2,4,3,122,38,95,78,97, - 109,101,115,112,97,99,101,80,97,116,104,46,95,102,105,110, - 100,95,112,97,114,101,110,116,95,112,97,116,104,95,110,97, - 109,101,115,99,1,0,0,0,0,0,0,0,3,0,0,0, - 3,0,0,0,67,0,0,0,115,28,0,0,0,124,0,160, - 0,161,0,92,2,125,1,125,2,116,1,116,2,106,3,124, - 1,25,0,124,2,131,2,83,0,41,1,78,41,4,114,249, - 0,0,0,114,112,0,0,0,114,6,0,0,0,218,7,109, - 111,100,117,108,101,115,41,3,114,102,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,71,4,0,0,115,4,0,0,0,0,1, - 12,1,122,31,95,78,97,109,101,115,112,97,99,101,80,97, - 116,104,46,95,103,101,116,95,112,97,114,101,110,116,95,112, - 97,116,104,99,1,0,0,0,0,0,0,0,3,0,0,0, - 4,0,0,0,67,0,0,0,115,80,0,0,0,116,0,124, - 0,160,1,161,0,131,1,125,1,124,1,124,0,106,2,107, - 3,114,74,124,0,160,3,124,0,106,4,124,1,161,2,125, - 2,124,2,100,0,107,9,114,68,124,2,106,5,100,0,107, - 8,114,68,124,2,106,6,114,68,124,2,106,6,124,0,95, - 7,124,1,124,0,95,2,124,0,106,7,83,0,41,1,78, - 41,8,114,95,0,0,0,114,244,0,0,0,114,245,0,0, - 0,114,246,0,0,0,114,242,0,0,0,114,122,0,0,0, - 114,158,0,0,0,114,243,0,0,0,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, - 75,4,0,0,115,16,0,0,0,0,2,12,1,10,1,14, - 3,18,1,6,1,8,1,6,1,122,27,95,78,97,109,101, - 115,112,97,99,101,80,97,116,104,46,95,114,101,99,97,108, - 99,117,108,97,116,101,99,1,0,0,0,0,0,0,0,1, - 0,0,0,3,0,0,0,67,0,0,0,115,12,0,0,0, - 116,0,124,0,160,1,161,0,131,1,83,0,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, - 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,2,124,0,106,0,124, - 1,60,0,100,0,83,0,41,1,78,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, - 91,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, - 2,0,0,0,0,1,122,22,95,78,97,109,101,115,112,97, - 99,101,80,97,116,104,46,95,95,108,101,110,95,95,99,1, - 0,0,0,0,0,0,0,1,0,0,0,3,0,0,0,67, - 0,0,0,115,12,0,0,0,100,1,160,0,124,0,106,1, - 161,1,83,0,41,2,78,122,20,95,78,97,109,101,115,112, - 97,99,101,80,97,116,104,40,123,33,114,125,41,41,2,114, - 48,0,0,0,114,243,0,0,0,41,1,114,102,0,0,0, + 188,0,0,0,35,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,39,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,43,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,252,3,0,0,115,18,0, + 0,0,12,8,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, + 2,100,3,132,0,90,4,100,4,100,5,132,0,90,5,100, + 6,100,7,132,0,90,6,100,8,100,9,132,0,90,7,100, + 10,100,11,132,0,90,8,100,12,100,13,132,0,90,9,100, + 14,100,15,132,0,90,10,100,16,100,17,132,0,90,11,100, + 18,100,19,132,0,90,12,100,20,100,21,132,0,90,13,100, + 22,83,0,41,23,218,14,95,78,97,109,101,115,112,97,99, + 101,80,97,116,104,97,38,1,0,0,82,101,112,114,101,115, + 101,110,116,115,32,97,32,110,97,109,101,115,112,97,99,101, + 32,112,97,99,107,97,103,101,39,115,32,112,97,116,104,46, + 32,32,73,116,32,117,115,101,115,32,116,104,101,32,109,111, + 100,117,108,101,32,110,97,109,101,10,32,32,32,32,116,111, + 32,102,105,110,100,32,105,116,115,32,112,97,114,101,110,116, + 32,109,111,100,117,108,101,44,32,97,110,100,32,102,114,111, + 109,32,116,104,101,114,101,32,105,116,32,108,111,111,107,115, + 32,117,112,32,116,104,101,32,112,97,114,101,110,116,39,115, + 10,32,32,32,32,95,95,112,97,116,104,95,95,46,32,32, + 87,104,101,110,32,116,104,105,115,32,99,104,97,110,103,101, + 115,44,32,116,104,101,32,109,111,100,117,108,101,39,115,32, + 111,119,110,32,112,97,116,104,32,105,115,32,114,101,99,111, + 109,112,117,116,101,100,44,10,32,32,32,32,117,115,105,110, + 103,32,112,97,116,104,95,102,105,110,100,101,114,46,32,32, + 70,111,114,32,116,111,112,45,108,101,118,101,108,32,109,111, + 100,117,108,101,115,44,32,116,104,101,32,112,97,114,101,110, + 116,32,109,111,100,117,108,101,39,115,32,112,97,116,104,10, + 32,32,32,32,105,115,32,115,121,115,46,112,97,116,104,46, + 99,4,0,0,0,0,0,0,0,4,0,0,0,3,0,0, + 0,67,0,0,0,115,36,0,0,0,124,1,124,0,95,0, + 124,2,124,0,95,1,116,2,124,0,160,3,161,0,131,1, + 124,0,95,4,124,3,124,0,95,5,100,0,83,0,41,1, + 78,41,6,218,5,95,110,97,109,101,218,5,95,112,97,116, + 104,114,95,0,0,0,218,16,95,103,101,116,95,112,97,114, + 101,110,116,95,112,97,116,104,218,17,95,108,97,115,116,95, + 112,97,114,101,110,116,95,112,97,116,104,218,12,95,112,97, + 116,104,95,102,105,110,100,101,114,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,56,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,67,0,0,0,115,38,0,0,0,124, + 0,106,0,160,1,100,1,161,1,92,3,125,1,125,2,125, + 3,124,2,100,2,107,2,114,30,100,3,83,0,124,1,100, + 4,102,2,83,0,41,5,122,62,82,101,116,117,114,110,115, + 32,97,32,116,117,112,108,101,32,111,102,32,40,112,97,114, + 101,110,116,45,109,111,100,117,108,101,45,110,97,109,101,44, + 32,112,97,114,101,110,116,45,112,97,116,104,45,97,116,116, + 114,45,110,97,109,101,41,114,59,0,0,0,114,30,0,0, + 0,41,2,114,6,0,0,0,114,35,0,0,0,90,8,95, + 95,112,97,116,104,95,95,41,2,114,242,0,0,0,114,32, + 0,0,0,41,4,114,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, + 62,4,0,0,115,8,0,0,0,0,2,18,1,8,2,4, + 3,122,38,95,78,97,109,101,115,112,97,99,101,80,97,116, + 104,46,95,102,105,110,100,95,112,97,114,101,110,116,95,112, + 97,116,104,95,110,97,109,101,115,99,1,0,0,0,0,0, + 0,0,3,0,0,0,3,0,0,0,67,0,0,0,115,28, + 0,0,0,124,0,160,0,161,0,92,2,125,1,125,2,116, + 1,116,2,106,3,124,1,25,0,124,2,131,2,83,0,41, + 1,78,41,4,114,249,0,0,0,114,112,0,0,0,114,6, + 0,0,0,218,7,109,111,100,117,108,101,115,41,3,114,102, + 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,72,4,0,0,115, + 4,0,0,0,0,1,12,1,122,31,95,78,97,109,101,115, + 112,97,99,101,80,97,116,104,46,95,103,101,116,95,112,97, + 114,101,110,116,95,112,97,116,104,99,1,0,0,0,0,0, + 0,0,3,0,0,0,4,0,0,0,67,0,0,0,115,80, + 0,0,0,116,0,124,0,160,1,161,0,131,1,125,1,124, + 1,124,0,106,2,107,3,114,74,124,0,160,3,124,0,106, + 4,124,1,161,2,125,2,124,2,100,0,107,9,114,68,124, + 2,106,5,100,0,107,8,114,68,124,2,106,6,114,68,124, + 2,106,6,124,0,95,7,124,1,124,0,95,2,124,0,106, + 7,83,0,41,1,78,41,8,114,95,0,0,0,114,244,0, + 0,0,114,245,0,0,0,114,246,0,0,0,114,242,0,0, + 0,114,122,0,0,0,114,158,0,0,0,114,243,0,0,0, + 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,76,4,0,0,115,16,0,0,0,0, + 2,12,1,10,1,14,3,18,1,6,1,8,1,6,1,122, + 27,95,78,97,109,101,115,112,97,99,101,80,97,116,104,46, + 95,114,101,99,97,108,99,117,108,97,116,101,99,1,0,0, + 0,0,0,0,0,1,0,0,0,3,0,0,0,67,0,0, + 0,115,12,0,0,0,116,0,124,0,160,1,161,0,131,1, + 83,0,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,89,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, + 2,124,0,106,0,124,1,60,0,100,0,83,0,41,1,78, + 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,92,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,95,4,0,0,115,2,0,0,0,0,1,122,22,95,78, + 97,109,101,115,112,97,99,101,80,97,116,104,46,95,95,108, + 101,110,95,95,99,1,0,0,0,0,0,0,0,1,0,0, + 0,3,0,0,0,67,0,0,0,115,12,0,0,0,100,1, + 160,0,124,0,106,1,161,1,83,0,41,2,78,122,20,95, + 78,97,109,101,115,112,97,99,101,80,97,116,104,40,123,33, + 114,125,41,41,2,114,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,98, + 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,0,0,115,12,0,0,0,124,1,124, + 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, - 8,95,95,114,101,112,114,95,95,97,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, + 12,95,95,99,111,110,116,97,105,110,115,95,95,101,4,0, + 0,115,2,0,0,0,0,1,122,27,95,78,97,109,101,115, + 112,97,99,101,80,97,116,104,46,95,95,99,111,110,116,97, + 105,110,115,95,95,99,2,0,0,0,0,0,0,0,2,0, + 0,0,3,0,0,0,67,0,0,0,115,16,0,0,0,124, + 0,106,0,160,1,124,1,161,1,1,0,100,0,83,0,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,104,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,0,114,186,0,0,0,114,249,0,0, + 0,114,244,0,0,0,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,49,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,110,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,124,1,124,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,100,4,0,0,115,2,0,0,0, - 0,1,122,27,95,78,97,109,101,115,112,97,99,101,80,97, - 116,104,46,95,95,99,111,110,116,97,105,110,115,95,95,99, - 2,0,0,0,0,0,0,0,2,0,0,0,3,0,0,0, - 67,0,0,0,115,16,0,0,0,124,0,106,0,160,1,124, - 1,161,1,1,0,100,0,83,0,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,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, - 0,114,186,0,0,0,114,249,0,0,0,114,244,0,0,0, - 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,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,113,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,122,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,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,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,128,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,131,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,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, - 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, - 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,2,0,0,0,4,0,0,0,67,0,0,0, - 115,42,0,0,0,120,36,116,0,106,1,160,2,161,0,68, - 0,93,22,125,1,116,3,124,1,100,1,131,2,114,12,124, - 1,160,4,161,0,1,0,113,12,87,0,100,2,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, - 218,17,105,110,118,97,108,105,100,97,116,101,95,99,97,99, - 104,101,115,78,41,5,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,6,118,97,108,117,101,115,114,110,0,0,0,114,6,1, - 0,0,41,2,114,172,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,6,0,0,0,0,4, - 16,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,162,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,7,1,0,0,218,8,75,101,121,69,114, - 114,111,114,114,11,1,0,0,41,3,114,172,0,0,0,114, - 35,0,0,0,114,9,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,175,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,9,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,197,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, + 0,114,4,0,0,0,114,192,0,0,0,134,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,137,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,109,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,2,0,0,0,4,0, + 0,0,67,0,0,0,115,38,0,0,0,116,0,106,1,160, + 2,161,0,68,0,93,22,125,1,116,3,124,1,100,1,131, + 2,114,10,124,1,160,4,161,0,1,0,113,10,100,2,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,218,17,105,110,118,97,108,105,100,97,116,101,95,99, + 97,99,104,101,115,78,41,5,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,6,118,97,108,117,101,115,114,110,0,0,0,114, + 6,1,0,0,41,2,114,172,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,155,4,0,0,115,6,0,0,0, + 0,4,14,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,163,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,7,1,0,0,218,8,75, + 101,121,69,114,114,111,114,114,11,1,0,0,41,3,114,172, + 0,0,0,114,35,0,0,0,114,9,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,176,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,9,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,198,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, @@ -2105,10 +2106,10 @@ const unsigned char _Py_M__importlib_external[] = { 110,97,109,101,115,112,97,99,101,95,112,97,116,104,90,5, 101,110,116,114,121,114,9,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,212,4, - 0,0,115,40,0,0,0,0,5,4,1,10,1,14,1,2, + 0,0,0,218,9,95,103,101,116,95,115,112,101,99,213,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,4,1,6,1,8,1,8,5,14,2,12,1,6,1,122, + 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, @@ -2132,7 +2133,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,16,1,0,0,114,2,0,0,0,114, - 2,0,0,0,114,4,0,0,0,114,182,0,0,0,244,4, + 2,0,0,0,114,4,0,0,0,114,182,0,0,0,245,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, @@ -2154,7 +2155,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,12,5,0,0,115,8,0,0,0,0,8,12, + 183,0,0,0,13,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, @@ -2162,7 +2163,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,114,6,1,0,0,114,11,1,0,0,114,13,1,0, 0,114,14,1,0,0,114,17,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, + 2,0,0,0,114,4,0,0,0,114,5,1,0,0,151,4, 0,0,115,20,0,0,0,12,4,12,8,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, @@ -2185,426 +2186,426 @@ const unsigned char _Py_M__importlib_external[] = { 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,41,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,35,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, - 20,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,49, - 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,55,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,17,1,0,0,67,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,20,1,0, - 0,218,11,95,102,105,108,108,95,99,97,99,104,101,114,5, - 0,0,0,114,23,1,0,0,114,90,0,0,0,114,22,1, - 0,0,114,28,0,0,0,114,19,1,0,0,114,44,0,0, - 0,114,17,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,72,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,149,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,21,1,0, - 0,114,22,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, - 23,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,25,1,0,0,120,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, + 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,42,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,36,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,20,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,50,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,56,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,17,1,0,0,68,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,20,1,0,0,218,11,95, + 102,105,108,108,95,99,97,99,104,101,114,5,0,0,0,114, + 23,1,0,0,114,90,0,0,0,114,22,1,0,0,114,28, + 0,0,0,114,19,1,0,0,114,44,0,0,0,114,17,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,73,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,250,9,60,115,101,116,99,111,109,112,62,150,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,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,24,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,161, - 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,24,1,0,0,114,30,1,0,0,114,2,0,0, - 0,41,2,114,172,0,0,0,114,24,1,0,0,114,4,0, - 0,0,218,9,112,97,116,104,95,104,111,111,107,151,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,169,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,17,1,0,0,114,182,0,0,0,114,25, - 1,0,0,114,184,0,0,0,114,31,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,18,1,0,0,26,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,18,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,175,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,36,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,198,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,234,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,37, - 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,209,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,43, - 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, - 43,1,0,0,114,163,0,0,0,114,6,0,0,0,114,10, - 1,0,0,114,147,0,0,0,114,18,1,0,0,114,31,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,42,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,17,6,0,0,115,8, - 0,0,0,0,2,8,1,6,1,20,1,114,45,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,18,1,0,0,114,36,1,0,0,114, - 163,0,0,0,114,43,1,0,0,114,45,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, - 5,14,127,0,22,10,23,8,11,8,64, + 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,21,1,0,0,114,22,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,23,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,25,1,0,0,121,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,24, + 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,162,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,24,1,0,0,114, + 30,1,0,0,114,2,0,0,0,41,2,114,172,0,0,0, + 114,24,1,0,0,114,4,0,0,0,218,9,112,97,116,104, + 95,104,111,111,107,152,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,170,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,17,1,0, + 0,114,182,0,0,0,114,25,1,0,0,114,184,0,0,0, + 114,31,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,18, + 1,0,0,27,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,18, + 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,176,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, + 36,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,199, + 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,235,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,37,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,210,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,43,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,43,1,0,0,114,163,0,0, + 0,114,6,0,0,0,114,10,1,0,0,114,147,0,0,0, + 114,18,1,0,0,114,31,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,42,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,18,6,0,0,115,8,0,0,0,0,2,8,1,6, + 1,20,1,114,45,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,18,1, + 0,0,114,36,1,0,0,114,163,0,0,0,114,43,1,0, + 0,114,45,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,4,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,5,14,127,0,22,10,23,8, + 11,8,64, }; diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index da6d032bce41..c9c903487fd9 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -5,7 +5,7 @@ static void *opcode_targets[256] = { &&TARGET_ROT_THREE, &&TARGET_DUP_TOP, &&TARGET_DUP_TOP_TWO, - &&_unknown_opcode, + &&TARGET_ROT_FOUR, &&_unknown_opcode, &&_unknown_opcode, &&TARGET_NOP, @@ -52,7 +52,7 @@ static void *opcode_targets[256] = { &&TARGET_GET_AITER, &&TARGET_GET_ANEXT, &&TARGET_BEFORE_ASYNC_WITH, - &&_unknown_opcode, + &&TARGET_BEGIN_FINALLY, &&_unknown_opcode, &&TARGET_INPLACE_ADD, &&TARGET_INPLACE_SUBTRACT, @@ -79,7 +79,7 @@ static void *opcode_targets[256] = { &&TARGET_INPLACE_AND, &&TARGET_INPLACE_XOR, &&TARGET_INPLACE_OR, - &&TARGET_BREAK_LOOP, + &&_unknown_opcode, &&TARGET_WITH_CLEANUP_START, &&TARGET_WITH_CLEANUP_FINISH, &&TARGET_RETURN_VALUE, @@ -118,9 +118,9 @@ static void *opcode_targets[256] = { &&TARGET_LOAD_GLOBAL, &&_unknown_opcode, &&_unknown_opcode, - &&TARGET_CONTINUE_LOOP, - &&TARGET_SETUP_LOOP, - &&TARGET_SETUP_EXCEPT, + &&_unknown_opcode, + &&_unknown_opcode, + &&_unknown_opcode, &&TARGET_SETUP_FINALLY, &&_unknown_opcode, &&TARGET_LOAD_FAST, @@ -161,8 +161,8 @@ static void *opcode_targets[256] = { &&_unknown_opcode, &&TARGET_LOAD_METHOD, &&TARGET_CALL_METHOD, - &&_unknown_opcode, - &&_unknown_opcode, + &&TARGET_CALL_FINALLY, + &&TARGET_POP_FINALLY, &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, diff --git a/Python/peephole.c b/Python/peephole.c index 76a0edbcc2bc..16fd5009bf1d 100644 --- a/Python/peephole.c +++ b/Python/peephole.c @@ -13,7 +13,7 @@ #define UNCONDITIONAL_JUMP(op) (op==JUMP_ABSOLUTE || op==JUMP_FORWARD) #define CONDITIONAL_JUMP(op) (op==POP_JUMP_IF_FALSE || op==POP_JUMP_IF_TRUE \ || op==JUMP_IF_FALSE_OR_POP || op==JUMP_IF_TRUE_OR_POP) -#define ABSOLUTE_JUMP(op) (op==JUMP_ABSOLUTE || op==CONTINUE_LOOP \ +#define ABSOLUTE_JUMP(op) (op==JUMP_ABSOLUTE \ || op==POP_JUMP_IF_FALSE || op==POP_JUMP_IF_TRUE \ || op==JUMP_IF_FALSE_OR_POP || op==JUMP_IF_TRUE_OR_POP) #define JUMPS_ON_TRUE(op) (op==POP_JUMP_IF_TRUE || op==JUMP_IF_TRUE_OR_POP) @@ -185,12 +185,10 @@ markblocks(_Py_CODEUNIT *code, Py_ssize_t len) case POP_JUMP_IF_FALSE: case POP_JUMP_IF_TRUE: case JUMP_ABSOLUTE: - case CONTINUE_LOOP: - case SETUP_LOOP: - case SETUP_EXCEPT: case SETUP_FINALLY: case SETUP_WITH: case SETUP_ASYNC_WITH: + case CALL_FINALLY: j = GETJUMPTGT(code, i); assert(j < len); blocks[j] = 1; @@ -373,15 +371,8 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, /* Replace jumps to unconditional jumps */ case POP_JUMP_IF_FALSE: case POP_JUMP_IF_TRUE: - case FOR_ITER: case JUMP_FORWARD: case JUMP_ABSOLUTE: - case CONTINUE_LOOP: - case SETUP_LOOP: - case SETUP_EXCEPT: - case SETUP_FINALLY: - case SETUP_WITH: - case SETUP_ASYNC_WITH: h = GETJUMPTGT(codestr, i); tgt = find_op(codestr, h); /* Replace JUMP_* to a RETURN into just a RETURN */ @@ -407,7 +398,21 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, /* Remove unreachable ops after RETURN */ case RETURN_VALUE: h = i + 1; - while (h < codelen && ISBASICBLOCK(blocks, i, h)) { + /* END_FINALLY should be kept since it denotes the end of + the 'finally' block in frame_setlineno() in frameobject.c. + SETUP_FINALLY should be kept for balancing. + */ + while (h < codelen && ISBASICBLOCK(blocks, i, h) && + _Py_OPCODE(codestr[h]) != END_FINALLY) + { + if (_Py_OPCODE(codestr[h]) == SETUP_FINALLY) { + while (h > i + 1 && + _Py_OPCODE(codestr[h - 1]) == EXTENDED_ARG) + { + h--; + } + break; + } h++; } if (h > i + 1) { @@ -452,7 +457,6 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, case NOP:continue; case JUMP_ABSOLUTE: - case CONTINUE_LOOP: case POP_JUMP_IF_FALSE: case POP_JUMP_IF_TRUE: case JUMP_IF_FALSE_OR_POP: @@ -462,11 +466,10 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names, case FOR_ITER: case JUMP_FORWARD: - case SETUP_LOOP: - case SETUP_EXCEPT: case SETUP_FINALLY: case SETUP_WITH: case SETUP_ASYNC_WITH: + case CALL_FINALLY: j = blocks[j / sizeof(_Py_CODEUNIT) + i + 1] - blocks[i] - 1; j *= sizeof(_Py_CODEUNIT); break; From webhook-mailer at python.org Thu Feb 22 20:37:45 2018 From: webhook-mailer at python.org (Gregory P. Smith) Date: Fri, 23 Feb 2018 01:37:45 -0000 Subject: [Python-checkins] bpo-30028: make test.support.temp_cwd() fork-safe (GH-1066) Message-ID: https://github.com/python/cpython/commit/33dddac00ba8d9b72cf21b8698504077eb3c23ad commit: 33dddac00ba8d9b72cf21b8698504077eb3c23ad branch: master author: Anselm Kruis committer: Gregory P. Smith date: 2018-02-22T17:37:38-08:00 summary: bpo-30028: make test.support.temp_cwd() fork-safe (GH-1066) Make test.support.temp_cwd() fork-safe. The context manager test.support.temp_cwd() no longer removes the temporary directory when executing in a process other than the parent it entered from. If a forked child exits the context manager it won't do the cleanup. files: M Lib/test/support/__init__.py M Lib/test/test_support.py M Misc/ACKS diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 6c9e31a22c10..b4269f4a5b70 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -948,10 +948,14 @@ def temp_dir(path=None, quiet=False): warnings.warn(f'tests may fail, unable to create ' f'temporary directory {path!r}: {exc}', RuntimeWarning, stacklevel=3) + if dir_created: + pid = os.getpid() try: yield path finally: - if dir_created: + # In case the process forks, let only the parent remove the + # directory. The child has a diffent process id. (bpo-30028) + if dir_created and pid == os.getpid(): rmtree(path) @contextlib.contextmanager diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py index e06f7b8e9952..36d5f849e1ad 100644 --- a/Lib/test/test_support.py +++ b/Lib/test/test_support.py @@ -9,9 +9,11 @@ import subprocess import sys import tempfile +import textwrap import time import unittest from test import support +from test.support import script_helper TESTFN = support.TESTFN @@ -165,6 +167,33 @@ def test_temp_dir__existing_dir__quiet_true(self): f'temporary directory {path!r}: '), warn) + @unittest.skipUnless(hasattr(os, "fork"), "test requires os.fork") + def test_temp_dir__forked_child(self): + """Test that a forked child process does not remove the directory.""" + # See bpo-30028 for details. + # Run the test as an external script, because it uses fork. + script_helper.assert_python_ok("-c", textwrap.dedent(""" + import os + from test import support + with support.temp_cwd() as temp_path: + pid = os.fork() + if pid != 0: + # parent process (child has pid == 0) + + # wait for the child to terminate + (pid, status) = os.waitpid(pid, 0) + if status != 0: + raise AssertionError(f"Child process failed with exit " + f"status indication 0x{status:x}.") + + # Make sure that temp_path is still present. When the child + # process leaves the 'temp_cwd'-context, the __exit__()- + # method of the context must not remove the temporary + # directory. + if not os.path.isdir(temp_path): + raise AssertionError("Child removed temp_path.") + """)) + # Tests for change_cwd() def test_change_cwd(self): diff --git a/Misc/ACKS b/Misc/ACKS index 2eddc56d34d3..dee022f2ff0a 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -857,6 +857,7 @@ Pedro Kroger Hannu Krosing Andrej Krpic Ivan Krsti? +Anselm Kruis Steven Kryskalla Andrew Kuchling Dave Kuhlman From webhook-mailer at python.org Fri Feb 23 00:39:10 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 23 Feb 2018 05:39:10 -0000 Subject: [Python-checkins] bpo-30028: make test.support.temp_cwd() fork-safe (GH-1066) Message-ID: https://github.com/python/cpython/commit/694c5e0e1f7f23595fab314f26b89e241477ff18 commit: 694c5e0e1f7f23595fab314f26b89e241477ff18 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-22T21:39:02-08:00 summary: bpo-30028: make test.support.temp_cwd() fork-safe (GH-1066) Make test.support.temp_cwd() fork-safe. The context manager test.support.temp_cwd() no longer removes the temporary directory when executing in a process other than the parent it entered from. If a forked child exits the context manager it won't do the cleanup. (cherry picked from commit 33dddac00ba8d9b72cf21b8698504077eb3c23ad) Co-authored-by: Anselm Kruis files: M Lib/test/support/__init__.py M Lib/test/test_support.py M Misc/ACKS diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 22868d4ba1a3..78298ca434a1 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -948,10 +948,14 @@ def temp_dir(path=None, quiet=False): warnings.warn(f'tests may fail, unable to create ' f'temporary directory {path!r}: {exc}', RuntimeWarning, stacklevel=3) + if dir_created: + pid = os.getpid() try: yield path finally: - if dir_created: + # In case the process forks, let only the parent remove the + # directory. The child has a diffent process id. (bpo-30028) + if dir_created and pid == os.getpid(): rmtree(path) @contextlib.contextmanager diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py index e06f7b8e9952..36d5f849e1ad 100644 --- a/Lib/test/test_support.py +++ b/Lib/test/test_support.py @@ -9,9 +9,11 @@ import subprocess import sys import tempfile +import textwrap import time import unittest from test import support +from test.support import script_helper TESTFN = support.TESTFN @@ -165,6 +167,33 @@ def test_temp_dir__existing_dir__quiet_true(self): f'temporary directory {path!r}: '), warn) + @unittest.skipUnless(hasattr(os, "fork"), "test requires os.fork") + def test_temp_dir__forked_child(self): + """Test that a forked child process does not remove the directory.""" + # See bpo-30028 for details. + # Run the test as an external script, because it uses fork. + script_helper.assert_python_ok("-c", textwrap.dedent(""" + import os + from test import support + with support.temp_cwd() as temp_path: + pid = os.fork() + if pid != 0: + # parent process (child has pid == 0) + + # wait for the child to terminate + (pid, status) = os.waitpid(pid, 0) + if status != 0: + raise AssertionError(f"Child process failed with exit " + f"status indication 0x{status:x}.") + + # Make sure that temp_path is still present. When the child + # process leaves the 'temp_cwd'-context, the __exit__()- + # method of the context must not remove the temporary + # directory. + if not os.path.isdir(temp_path): + raise AssertionError("Child removed temp_path.") + """)) + # Tests for change_cwd() def test_change_cwd(self): diff --git a/Misc/ACKS b/Misc/ACKS index ec7ba956dc08..4c0b0e5720e1 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -856,6 +856,7 @@ Pedro Kroger Hannu Krosing Andrej Krpic Ivan Krsti? +Anselm Kruis Steven Kryskalla Andrew Kuchling Dave Kuhlman From solipsis at pitrou.net Fri Feb 23 04:15:38 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 23 Feb 2018 09:15:38 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=6 Message-ID: <20180223091538.1.3DF22FD4AE8D65E9@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_forkserver leaked [2, -1, 0] memory blocks, sum=1 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogICsUZU', '--timeout', '7200'] From webhook-mailer at python.org Fri Feb 23 06:02:45 2018 From: webhook-mailer at python.org (INADA Naoki) Date: Fri, 23 Feb 2018 11:02:45 -0000 Subject: [Python-checkins] ipaddress: Use str.isascii() instead of frozenset (GH-5811) Message-ID: https://github.com/python/cpython/commit/58a10967619d0281adf346f227c254f1c3b3f32e commit: 58a10967619d0281adf346f227c254f1c3b3f32e branch: master author: INADA Naoki committer: GitHub date: 2018-02-23T20:02:41+09:00 summary: ipaddress: Use str.isascii() instead of frozenset (GH-5811) files: M Lib/ipaddress.py diff --git a/Lib/ipaddress.py b/Lib/ipaddress.py index e8ce4cef2ded..77df0511e78a 100644 --- a/Lib/ipaddress.py +++ b/Lib/ipaddress.py @@ -488,7 +488,7 @@ def _prefix_from_prefix_string(cls, prefixlen_str): """ # int allows a leading +/- as well as surrounding whitespace, # so we ensure that isn't the case - if not _BaseV4._DECIMAL_DIGITS.issuperset(prefixlen_str): + if not (prefixlen_str.isascii() and prefixlen_str.isdigit()): cls._report_invalid_netmask(prefixlen_str) try: prefixlen = int(prefixlen_str) @@ -1076,7 +1076,6 @@ class _BaseV4: _version = 4 # Equivalent to 255.255.255.255 or 32 bits of 1's. _ALL_ONES = (2**IPV4LENGTH) - 1 - _DECIMAL_DIGITS = frozenset('0123456789') # the valid octets for host and netmasks. only useful for IPv4. _valid_mask_octets = frozenset({255, 254, 252, 248, 240, 224, 192, 128, 0}) @@ -1156,7 +1155,7 @@ def _parse_octet(cls, octet_str): if not octet_str: raise ValueError("Empty octet not permitted") # Whitelist the characters, since int() allows a lot of bizarre stuff. - if not cls._DECIMAL_DIGITS.issuperset(octet_str): + if not (octet_str.isascii() and octet_str.isdigit()): msg = "Only decimal digits permitted in %r" raise ValueError(msg % octet_str) # We do the length check second, since the invalid character error From webhook-mailer at python.org Fri Feb 23 06:47:22 2018 From: webhook-mailer at python.org (INADA Naoki) Date: Fri, 23 Feb 2018 11:47:22 -0000 Subject: [Python-checkins] bpo-32087: Doc: Make "deprecated-removed" directive translatable (GH-4473) Message-ID: https://github.com/python/cpython/commit/0febc053736112d7bb9081742b3ac0ece7b973e7 commit: 0febc053736112d7bb9081742b3ac0ece7b973e7 branch: master author: cocoatomo committer: INADA Naoki date: 2018-02-23T20:47:19+09:00 summary: bpo-32087: Doc: Make "deprecated-removed" directive translatable (GH-4473) files: M Doc/tools/extensions/pyspecific.py M Doc/tools/templates/dummy.html diff --git a/Doc/tools/extensions/pyspecific.py b/Doc/tools/extensions/pyspecific.py index 00acd4f55b8b..47d3823e7d94 100644 --- a/Doc/tools/extensions/pyspecific.py +++ b/Doc/tools/extensions/pyspecific.py @@ -196,7 +196,7 @@ class DeprecatedRemoved(Directive): final_argument_whitespace = True option_spec = {} - _label = 'Deprecated since version %s, will be removed in version %s' + _label = 'Deprecated since version {deprecated}, will be removed in version {removed}' def run(self): node = addnodes.versionmodified() @@ -204,11 +204,12 @@ def run(self): node['type'] = 'deprecated-removed' version = (self.arguments[0], self.arguments[1]) node['version'] = version - text = self._label % version + label = translators['sphinx'].gettext(self._label) + text = label.format(deprecated=self.arguments[0], removed=self.arguments[1]) if len(self.arguments) == 3: inodes, messages = self.state.inline_text(self.arguments[2], self.lineno+1) - para = nodes.paragraph(self.arguments[2], '', *inodes) + para = nodes.paragraph(self.arguments[2], '', *inodes, translatable=False) node.append(para) else: messages = [] @@ -220,13 +221,14 @@ def run(self): content.source = node[0].source content.line = node[0].line content += node[0].children - node[0].replace_self(nodes.paragraph('', '', content)) + node[0].replace_self(nodes.paragraph('', '', content, translatable=False)) node[0].insert(0, nodes.inline('', '%s: ' % text, classes=['versionmodified'])) else: para = nodes.paragraph('', '', nodes.inline('', '%s.' % text, - classes=['versionmodified'])) + classes=['versionmodified']), + translatable=False) node.append(para) env = self.state.document.settings.env env.note_versionchange('deprecated', version[0], node, self.lineno) diff --git a/Doc/tools/templates/dummy.html b/Doc/tools/templates/dummy.html index 6e43be23230b..8d94137b01b5 100644 --- a/Doc/tools/templates/dummy.html +++ b/Doc/tools/templates/dummy.html @@ -4,3 +4,4 @@ In extensions/pyspecific.py: {% trans %}CPython implementation detail:{% endtrans %} +{% trans %}Deprecated since version {deprecated}, will be removed in version {removed}{% endtrans %} From webhook-mailer at python.org Fri Feb 23 07:08:49 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 23 Feb 2018 12:08:49 -0000 Subject: [Python-checkins] bpo-32087: Doc: Make "deprecated-removed" directive translatable (GH-4473) Message-ID: https://github.com/python/cpython/commit/c673a62d5f3c650130bf40f2161a2eac64419bce commit: c673a62d5f3c650130bf40f2161a2eac64419bce branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-23T04:08:45-08:00 summary: bpo-32087: Doc: Make "deprecated-removed" directive translatable (GH-4473) (cherry picked from commit 0febc053736112d7bb9081742b3ac0ece7b973e7) Co-authored-by: cocoatomo files: M Doc/tools/extensions/pyspecific.py M Doc/tools/templates/dummy.html diff --git a/Doc/tools/extensions/pyspecific.py b/Doc/tools/extensions/pyspecific.py index 5cb9f1d66e10..bb69366ecd49 100644 --- a/Doc/tools/extensions/pyspecific.py +++ b/Doc/tools/extensions/pyspecific.py @@ -196,7 +196,7 @@ class DeprecatedRemoved(Directive): final_argument_whitespace = True option_spec = {} - _label = 'Deprecated since version %s, will be removed in version %s' + _label = 'Deprecated since version {deprecated}, will be removed in version {removed}' def run(self): node = addnodes.versionmodified() @@ -204,11 +204,12 @@ def run(self): node['type'] = 'deprecated-removed' version = (self.arguments[0], self.arguments[1]) node['version'] = version - text = self._label % version + label = translators['sphinx'].gettext(self._label) + text = label.format(deprecated=self.arguments[0], removed=self.arguments[1]) if len(self.arguments) == 3: inodes, messages = self.state.inline_text(self.arguments[2], self.lineno+1) - para = nodes.paragraph(self.arguments[2], '', *inodes) + para = nodes.paragraph(self.arguments[2], '', *inodes, translatable=False) node.append(para) else: messages = [] @@ -220,13 +221,14 @@ def run(self): content.source = node[0].source content.line = node[0].line content += node[0].children - node[0].replace_self(nodes.paragraph('', '', content)) + node[0].replace_self(nodes.paragraph('', '', content, translatable=False)) node[0].insert(0, nodes.inline('', '%s: ' % text, classes=['versionmodified'])) else: para = nodes.paragraph('', '', nodes.inline('', '%s.' % text, - classes=['versionmodified'])) + classes=['versionmodified']), + translatable=False) node.append(para) env = self.state.document.settings.env env.note_versionchange('deprecated', version[0], node, self.lineno) diff --git a/Doc/tools/templates/dummy.html b/Doc/tools/templates/dummy.html index 6e43be23230b..8d94137b01b5 100644 --- a/Doc/tools/templates/dummy.html +++ b/Doc/tools/templates/dummy.html @@ -4,3 +4,4 @@ In extensions/pyspecific.py: {% trans %}CPython implementation detail:{% endtrans %} +{% trans %}Deprecated since version {deprecated}, will be removed in version {removed}{% endtrans %} From webhook-mailer at python.org Fri Feb 23 07:14:07 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 23 Feb 2018 12:14:07 -0000 Subject: [Python-checkins] bpo-32087: Doc: Make "deprecated-removed" directive translatable (GH-4473) Message-ID: https://github.com/python/cpython/commit/dd52d5c868fb1eb33bcf22e777317de0391bfaf6 commit: dd52d5c868fb1eb33bcf22e777317de0391bfaf6 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-23T04:14:04-08:00 summary: bpo-32087: Doc: Make "deprecated-removed" directive translatable (GH-4473) (cherry picked from commit 0febc053736112d7bb9081742b3ac0ece7b973e7) Co-authored-by: cocoatomo files: M Doc/tools/extensions/pyspecific.py M Doc/tools/templates/dummy.html diff --git a/Doc/tools/extensions/pyspecific.py b/Doc/tools/extensions/pyspecific.py index 8f507e461504..f533ac4882a7 100644 --- a/Doc/tools/extensions/pyspecific.py +++ b/Doc/tools/extensions/pyspecific.py @@ -196,7 +196,7 @@ class DeprecatedRemoved(Directive): final_argument_whitespace = True option_spec = {} - _label = 'Deprecated since version %s, will be removed in version %s' + _label = 'Deprecated since version {deprecated}, will be removed in version {removed}' def run(self): node = addnodes.versionmodified() @@ -204,11 +204,12 @@ def run(self): node['type'] = 'deprecated-removed' version = (self.arguments[0], self.arguments[1]) node['version'] = version - text = self._label % version + label = translators['sphinx'].gettext(self._label) + text = label.format(deprecated=self.arguments[0], removed=self.arguments[1]) if len(self.arguments) == 3: inodes, messages = self.state.inline_text(self.arguments[2], self.lineno+1) - para = nodes.paragraph(self.arguments[2], '', *inodes) + para = nodes.paragraph(self.arguments[2], '', *inodes, translatable=False) node.append(para) else: messages = [] @@ -220,13 +221,14 @@ def run(self): content.source = node[0].source content.line = node[0].line content += node[0].children - node[0].replace_self(nodes.paragraph('', '', content)) + node[0].replace_self(nodes.paragraph('', '', content, translatable=False)) node[0].insert(0, nodes.inline('', '%s: ' % text, classes=['versionmodified'])) else: para = nodes.paragraph('', '', nodes.inline('', '%s.' % text, - classes=['versionmodified'])) + classes=['versionmodified']), + translatable=False) node.append(para) env = self.state.document.settings.env env.note_versionchange('deprecated', version[0], node, self.lineno) diff --git a/Doc/tools/templates/dummy.html b/Doc/tools/templates/dummy.html index 6e43be23230b..8d94137b01b5 100644 --- a/Doc/tools/templates/dummy.html +++ b/Doc/tools/templates/dummy.html @@ -4,3 +4,4 @@ In extensions/pyspecific.py: {% trans %}CPython implementation detail:{% endtrans %} +{% trans %}Deprecated since version {deprecated}, will be removed in version {removed}{% endtrans %} From webhook-mailer at python.org Fri Feb 23 11:27:30 2018 From: webhook-mailer at python.org (Gregory P. Smith) Date: Fri, 23 Feb 2018 16:27:30 -0000 Subject: [Python-checkins] [2.7] bpo-30028: make test.support.temp_cwd() fork-safe (GH-1066) (GH-5825) Message-ID: https://github.com/python/cpython/commit/61bd4d2e6319a3c5c3b9ce5f807b44a45cc1d4a1 commit: 61bd4d2e6319a3c5c3b9ce5f807b44a45cc1d4a1 branch: 2.7 author: Anselm Kruis committer: Gregory P. Smith date: 2018-02-23T08:27:28-08:00 summary: [2.7] bpo-30028: make test.support.temp_cwd() fork-safe (GH-1066) (GH-5825) Make test.support.temp_cwd() fork-safe. The context manager test.support.temp_cwd() no longer removes the temporary directory when executing in a process other than the parent it entered from. If a forked child exits the context manager it won't do the cleanup.. (cherry picked from commit 33dddac00ba8d9b72cf21b8698504077eb3c23ad) Co-authored-by: Anselm Kruis files: M Lib/test/support/__init__.py M Lib/test/test_test_support.py M Misc/ACKS diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index cabf548ec38f..1e0f14eb3a18 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -753,10 +753,14 @@ def temp_dir(path=None, quiet=False): raise warnings.warn('tests may fail, unable to create temp dir: ' + path, RuntimeWarning, stacklevel=3) + if dir_created: + pid = os.getpid() try: yield path finally: - if dir_created: + # In case the process forks, let only the parent remove the + # directory. The child has a diffent process id. (bpo-30028) + if dir_created and pid == os.getpid(): rmtree(path) @contextlib.contextmanager diff --git a/Lib/test/test_test_support.py b/Lib/test/test_test_support.py index 1b62ac99028e..421a9ef8892f 100644 --- a/Lib/test/test_test_support.py +++ b/Lib/test/test_test_support.py @@ -6,8 +6,10 @@ import unittest import socket import tempfile +import textwrap import errno from test import support +from test.support import script_helper TESTFN = support.TESTFN @@ -176,6 +178,34 @@ def test_temp_dir__existing_dir__quiet_true(self): expected = ['tests may fail, unable to create temp dir: ' + path] self.assertEqual(warnings, expected) + @unittest.skipUnless(hasattr(os, "fork"), "test requires os.fork") + def test_temp_dir__forked_child(self): + """Test that a forked child process does not remove the directory.""" + # See bpo-30028 for details. + # Run the test as an external script, because it uses fork. + script_helper.assert_python_ok("-c", textwrap.dedent(""" + import os + from test import support + with support.temp_cwd() as temp_path: + pid = os.fork() + if pid != 0: + # parent process (child has pid == 0) + + # wait for the child to terminate + (pid, status) = os.waitpid(pid, 0) + if status != 0: + raise AssertionError("Child process failed with exit " + "status indication " + "0x{:x}.".format(status)) + + # Make sure that temp_path is still present. When the child + # process leaves the 'temp_cwd'-context, the __exit__()- + # method of the context must not remove the temporary + # directory. + if not os.path.isdir(temp_path): + raise AssertionError("Child removed temp_path.") + """)) + # Tests for change_cwd() def test_change_cwd(self): diff --git a/Misc/ACKS b/Misc/ACKS index e02060d8dcf1..28b01e8cc7c5 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -774,6 +774,7 @@ Pedro Kroger Hannu Krosing Andrej Krpic Ivan Krsti? +Anselm Kruis Steven Kryskalla Andrew Kuchling Dave Kuhlman From webhook-mailer at python.org Fri Feb 23 11:27:57 2018 From: webhook-mailer at python.org (Gregory P. Smith) Date: Fri, 23 Feb 2018 16:27:57 -0000 Subject: [Python-checkins] [3.6] bpo-30028: make test.support.temp_cwd() fork-safe (GH-1066) (GH-5826) Message-ID: https://github.com/python/cpython/commit/9c819a6a7d34594779fea3a25fd69ec5745e185e commit: 9c819a6a7d34594779fea3a25fd69ec5745e185e branch: 3.6 author: Anselm Kruis committer: Gregory P. Smith date: 2018-02-23T08:27:54-08:00 summary: [3.6] bpo-30028: make test.support.temp_cwd() fork-safe (GH-1066) (GH-5826) Make test.support.temp_cwd() fork-safe. The context manager test.support.temp_cwd() no longer removes the temporary directory when executing in a process other than the parent it entered from. If a forked child exits the context manager it won't do the cleanup.. (cherry picked from commit 33dddac00ba8d9b72cf21b8698504077eb3c23ad) Co-authored-by: Anselm Kruis files: M Lib/test/support/__init__.py M Lib/test/test_support.py M Misc/ACKS diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 2930ab24e4d0..e4840e6a9618 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -952,10 +952,14 @@ def temp_dir(path=None, quiet=False): raise warnings.warn('tests may fail, unable to create temp dir: ' + path, RuntimeWarning, stacklevel=3) + if dir_created: + pid = os.getpid() try: yield path finally: - if dir_created: + # In case the process forks, let only the parent remove the + # directory. The child has a diffent process id. (bpo-30028) + if dir_created and pid == os.getpid(): rmtree(path) @contextlib.contextmanager diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py index c070809cbe9b..fff0fc742f36 100644 --- a/Lib/test/test_support.py +++ b/Lib/test/test_support.py @@ -6,8 +6,10 @@ import unittest import socket import tempfile +import textwrap import errno from test import support +from test.support import script_helper TESTFN = support.TESTFN @@ -158,6 +160,33 @@ def test_temp_dir__existing_dir__quiet_true(self): expected = ['tests may fail, unable to create temp dir: ' + path] self.assertEqual(warnings, expected) + @unittest.skipUnless(hasattr(os, "fork"), "test requires os.fork") + def test_temp_dir__forked_child(self): + """Test that a forked child process does not remove the directory.""" + # See bpo-30028 for details. + # Run the test as an external script, because it uses fork. + script_helper.assert_python_ok("-c", textwrap.dedent(""" + import os + from test import support + with support.temp_cwd() as temp_path: + pid = os.fork() + if pid != 0: + # parent process (child has pid == 0) + + # wait for the child to terminate + (pid, status) = os.waitpid(pid, 0) + if status != 0: + raise AssertionError(f"Child process failed with exit " + f"status indication 0x{status:x}.") + + # Make sure that temp_path is still present. When the child + # process leaves the 'temp_cwd'-context, the __exit__()- + # method of the context must not remove the temporary + # directory. + if not os.path.isdir(temp_path): + raise AssertionError("Child removed temp_path.") + """)) + # Tests for change_cwd() def test_change_cwd(self): diff --git a/Misc/ACKS b/Misc/ACKS index 2a7b1b8140a4..75c9b3f0563d 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -841,6 +841,7 @@ Pedro Kroger Hannu Krosing Andrej Krpic Ivan Krsti? +Anselm Kruis Steven Kryskalla Andrew Kuchling Dave Kuhlman From webhook-mailer at python.org Fri Feb 23 11:44:30 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 23 Feb 2018 16:44:30 -0000 Subject: [Python-checkins] bpo-32901: Update Tcl and Tk versions to 8.6.8 (GH-5823) Message-ID: https://github.com/python/cpython/commit/74b73642596caa287ee59bf7901ca009606c24cc commit: 74b73642596caa287ee59bf7901ca009606c24cc branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-23T08:44:27-08:00 summary: bpo-32901: Update Tcl and Tk versions to 8.6.8 (GH-5823) (cherry picked from commit efa6c762268d68985f3012234f62ea9e5ced8b7c) Co-authored-by: Steve Dower files: A Misc/NEWS.d/next/Windows/2018-02-23-00-47-13.bpo-32901.mGKz5_.rst M PCbuild/get_externals.bat M PCbuild/tcltk.props diff --git a/Misc/NEWS.d/next/Windows/2018-02-23-00-47-13.bpo-32901.mGKz5_.rst b/Misc/NEWS.d/next/Windows/2018-02-23-00-47-13.bpo-32901.mGKz5_.rst new file mode 100644 index 000000000000..af0ca65e3c82 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2018-02-23-00-47-13.bpo-32901.mGKz5_.rst @@ -0,0 +1 @@ +Update Tcl and Tk versions to 8.6.8 diff --git a/PCbuild/get_externals.bat b/PCbuild/get_externals.bat index d2af042d4aae..6d3075171889 100644 --- a/PCbuild/get_externals.bat +++ b/PCbuild/get_externals.bat @@ -51,8 +51,8 @@ set libraries= set libraries=%libraries% bzip2-1.0.6 if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries% openssl-1.1.0f set libraries=%libraries% sqlite-3.21.0.0 -if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.6.0 -if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tk-8.6.6.0 +if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.8.0 +if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tk-8.6.8.0 if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tix-8.4.3.6 set libraries=%libraries% xz-5.2.2 set libraries=%libraries% zlib-1.2.11 @@ -73,7 +73,7 @@ echo.Fetching external binaries... set binaries= if NOT "%IncludeSSL%"=="false" set binaries=%binaries% openssl-bin-1.1.0f -if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-8.6.6.0 +if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-8.6.8.0 if NOT "%IncludeSSLSrc%"=="false" set binaries=%binaries% nasm-2.11.06 for %%b in (%binaries%) do ( diff --git a/PCbuild/tcltk.props b/PCbuild/tcltk.props index cad52b8f0220..0a59c0894d74 100644 --- a/PCbuild/tcltk.props +++ b/PCbuild/tcltk.props @@ -4,7 +4,7 @@ 8 6 - 6 + 8 0 $(TclMajorVersion) $(TclMinorVersion) From webhook-mailer at python.org Fri Feb 23 12:51:16 2018 From: webhook-mailer at python.org (Mariatta) Date: Fri, 23 Feb 2018 17:51:16 -0000 Subject: [Python-checkins] bpo-32923: Unittest doc: replace `whilst` with `while` (GH-5833) Message-ID: https://github.com/python/cpython/commit/98f42aac23f3863973cb6e9964c5212cfd3a1d98 commit: 98f42aac23f3863973cb6e9964c5212cfd3a1d98 branch: master author: Mariatta committer: GitHub date: 2018-02-23T09:51:11-08:00 summary: bpo-32923: Unittest doc: replace `whilst` with `while` (GH-5833) `whilst` and `while` are both english words, `whilst` is not as commonly used. This can be confusing to readers whose primary language is not english. files: M Doc/library/unittest.rst diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst index 93ccd0fd6113..af71be40b89f 100644 --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -2316,7 +2316,7 @@ handling functionality within test frameworks. When called without arguments this function removes the control-c handler if it has been installed. This function can also be used as a test decorator - to temporarily remove the handler whilst the test is being executed:: + to temporarily remove the handler while the test is being executed:: @unittest.removeHandler def test_signal_handling(self): From webhook-mailer at python.org Fri Feb 23 13:01:34 2018 From: webhook-mailer at python.org (Eric V. Smith) Date: Fri, 23 Feb 2018 18:01:34 -0000 Subject: [Python-checkins] Exhaustively test dataclass hashing when no hash= value is provided. This is in anticipation of changing how non-default hashing is handled. (#5834) Message-ID: https://github.com/python/cpython/commit/718070db26b35da4aedc03088c58558a833ccf6e commit: 718070db26b35da4aedc03088c58558a833ccf6e branch: master author: Eric V. Smith committer: GitHub date: 2018-02-23T13:01:31-05:00 summary: Exhaustively test dataclass hashing when no hash= value is provided. This is in anticipation of changing how non-default hashing is handled. (#5834) files: M Lib/test/test_dataclasses.py diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index 736bc490867b..9752f5502c7d 100755 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -2393,6 +2393,79 @@ def __eq__(self, other): self.assertNotEqual(C(1), C(1)) self.assertEqual(hash(C(1)), hash(C(1.0))) + def test_hash_no_args(self): + # Test dataclasses with no hash= argument. This exists to + # make sure that when hash is changed, the default hashability + # keeps working. + + class Base: + def __hash__(self): + return 301 + + # If frozen or eq is None, then use the default value (do not + # specify any value in the deecorator). + for frozen, eq, base, expected in [ + (None, None, object, 'unhashable'), + (None, None, Base, 'unhashable'), + (None, False, object, 'object'), + (None, False, Base, 'base'), + (None, True, object, 'unhashable'), + (None, True, Base, 'unhashable'), + (False, None, object, 'unhashable'), + (False, None, Base, 'unhashable'), + (False, False, object, 'object'), + (False, False, Base, 'base'), + (False, True, object, 'unhashable'), + (False, True, Base, 'unhashable'), + (True, None, object, 'tuple'), + (True, None, Base, 'tuple'), + (True, False, object, 'object'), + (True, False, Base, 'base'), + (True, True, object, 'tuple'), + (True, True, Base, 'tuple'), + ]: + + with self.subTest(frozen=frozen, eq=eq, base=base, expected=expected): + # First, create the class. + if frozen is None and eq is None: + @dataclass + class C(base): + i: int + elif frozen is None: + @dataclass(eq=eq) + class C(base): + i: int + elif eq is None: + @dataclass(frozen=frozen) + class C(base): + i: int + else: + @dataclass(frozen=frozen, eq=eq) + class C(base): + i: int + + # Now, make sure it hashes as expected. + if expected == 'unhashable': + c = C(10) + with self.assertRaisesRegex(TypeError, 'unhashable type'): + hash(c) + + elif expected == 'base': + self.assertEqual(hash(C(10)), 301) + + elif expected == 'object': + # I'm not sure what test to use here. object's + # hash isn't based on id(), so calling hash() + # won't tell us much. So, just check the function + # used is object's. + self.assertIs(C.__hash__, object.__hash__) + + elif expected == 'tuple': + self.assertEqual(hash(C(42)), hash((42,))) + + else: + assert False, f'unknown value for expected={expected!r}' + if __name__ == '__main__': unittest.main() From webhook-mailer at python.org Fri Feb 23 13:02:33 2018 From: webhook-mailer at python.org (Mariatta) Date: Fri, 23 Feb 2018 18:02:33 -0000 Subject: [Python-checkins] bpo-32924: Fix the Show Source url in the docs. (GH-5835) Message-ID: https://github.com/python/cpython/commit/079d75d099f228a4261f63a94217571e05e8fa8e commit: 079d75d099f228a4261f63a94217571e05e8fa8e branch: 3.7 author: Mariatta committer: GitHub date: 2018-02-23T10:02:30-08:00 summary: bpo-32924: Fix the Show Source url in the docs. (GH-5835) The Show Source link in Python 3.7 docs is pointing to GitHub's master branch. It should point to the 3.7 branch. files: M Doc/tools/templates/customsourcelink.html diff --git a/Doc/tools/templates/customsourcelink.html b/Doc/tools/templates/customsourcelink.html index fca44e9163ca..21af621efce9 100644 --- a/Doc/tools/templates/customsourcelink.html +++ b/Doc/tools/templates/customsourcelink.html @@ -4,7 +4,7 @@

      {{ _('This Page') }}

      • {% trans %}Report a Bug{% endtrans %}
      • - {{ _('Show Source') }}
      • From webhook-mailer at python.org Fri Feb 23 13:14:26 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 23 Feb 2018 18:14:26 -0000 Subject: [Python-checkins] bpo-32923: Unittest doc: replace `whilst` with `while` (GH-5833) Message-ID: https://github.com/python/cpython/commit/1ad6ca5eb95ebb7351e0f5d9ce607dec54de6407 commit: 1ad6ca5eb95ebb7351e0f5d9ce607dec54de6407 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-23T10:14:23-08:00 summary: bpo-32923: Unittest doc: replace `whilst` with `while` (GH-5833) `whilst` and `while` are both english words, `whilst` is not as commonly used. This can be confusing to readers whose primary language is not english. (cherry picked from commit 98f42aac23f3863973cb6e9964c5212cfd3a1d98) Co-authored-by: Mariatta files: M Doc/library/unittest.rst diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst index 93ccd0fd6113..af71be40b89f 100644 --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -2316,7 +2316,7 @@ handling functionality within test frameworks. When called without arguments this function removes the control-c handler if it has been installed. This function can also be used as a test decorator - to temporarily remove the handler whilst the test is being executed:: + to temporarily remove the handler while the test is being executed:: @unittest.removeHandler def test_signal_handling(self): From webhook-mailer at python.org Fri Feb 23 13:16:59 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 23 Feb 2018 18:16:59 -0000 Subject: [Python-checkins] bpo-32923: Unittest doc: replace `whilst` with `while` (GH-5833) Message-ID: https://github.com/python/cpython/commit/8a7f1f4b0ffddf230864ebf16b481546970dd9c2 commit: 8a7f1f4b0ffddf230864ebf16b481546970dd9c2 branch: 2.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-23T10:16:56-08:00 summary: bpo-32923: Unittest doc: replace `whilst` with `while` (GH-5833) `whilst` and `while` are both english words, `whilst` is not as commonly used. This can be confusing to readers whose primary language is not english. (cherry picked from commit 98f42aac23f3863973cb6e9964c5212cfd3a1d98) Co-authored-by: Mariatta files: M Doc/library/unittest.rst diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst index 15765f5ed588..b36126e1cc65 100644 --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -2038,7 +2038,7 @@ handling functionality within test frameworks. When called without arguments this function removes the control-c handler if it has been installed. This function can also be used as a test decorator - to temporarily remove the handler whilst the test is being executed:: + to temporarily remove the handler while the test is being executed:: @unittest.removeHandler def test_signal_handling(self): From webhook-mailer at python.org Fri Feb 23 13:22:30 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 23 Feb 2018 18:22:30 -0000 Subject: [Python-checkins] bpo-32923: Unittest doc: replace `whilst` with `while` (GH-5833) Message-ID: https://github.com/python/cpython/commit/cffe0467ab7b164739693598826bd3860f01b11f commit: cffe0467ab7b164739693598826bd3860f01b11f branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-23T10:22:27-08:00 summary: bpo-32923: Unittest doc: replace `whilst` with `while` (GH-5833) `whilst` and `while` are both english words, `whilst` is not as commonly used. This can be confusing to readers whose primary language is not english. (cherry picked from commit 98f42aac23f3863973cb6e9964c5212cfd3a1d98) Co-authored-by: Mariatta files: M Doc/library/unittest.rst diff --git a/Doc/library/unittest.rst b/Doc/library/unittest.rst index e52f140029c5..a4c4c5c64a6e 100644 --- a/Doc/library/unittest.rst +++ b/Doc/library/unittest.rst @@ -2282,7 +2282,7 @@ handling functionality within test frameworks. When called without arguments this function removes the control-c handler if it has been installed. This function can also be used as a test decorator - to temporarily remove the handler whilst the test is being executed:: + to temporarily remove the handler while the test is being executed:: @unittest.removeHandler def test_signal_handling(self): From webhook-mailer at python.org Fri Feb 23 14:02:01 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Fri, 23 Feb 2018 19:02:01 -0000 Subject: [Python-checkins] bpo-32838: Fix Python versions in the table of magic numbers. (GH-5658) Message-ID: https://github.com/python/cpython/commit/8d9d4b57ae57baee4401cab6067ef22c0172661d commit: 8d9d4b57ae57baee4401cab6067ef22c0172661d branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-23T11:01:54-08:00 summary: bpo-32838: Fix Python versions in the table of magic numbers. (GH-5658) (cherry picked from commit 4af8fd561433826ac897c55e41a087a5c5dbacf3) Co-authored-by: Serhiy Storchaka 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 f9a708c29131..e2951746835e 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -197,52 +197,55 @@ def _write_atomic(path, data, mode=0o666): # 3101 (merge from 2.6a0, see 62151) # 3103 (__file__ points to source file) # Python 3.0a4: 3111 (WITH_CLEANUP optimization). -# Python 3.0a5: 3131 (lexical exception stacking, including POP_EXCEPT) -# Python 3.1a0: 3141 (optimize list, set and dict comprehensions: -# change LIST_APPEND and SET_ADD, add MAP_ADD) -# Python 3.1a0: 3151 (optimize conditional branches: -# introduce POP_JUMP_IF_FALSE and POP_JUMP_IF_TRUE) -# Python 3.2a0: 3160 (add SETUP_WITH) +# Python 3.0b1: 3131 (lexical exception stacking, including POP_EXCEPT + #3021) +# Python 3.1a1: 3141 (optimize list, set and dict comprehensions: +# change LIST_APPEND and SET_ADD, add MAP_ADD #2183) +# Python 3.1a1: 3151 (optimize conditional branches: +# introduce POP_JUMP_IF_FALSE and POP_JUMP_IF_TRUE + #4715) +# Python 3.2a1: 3160 (add SETUP_WITH #6101) # tag: cpython-32 -# Python 3.2a1: 3170 (add DUP_TOP_TWO, remove DUP_TOPX and ROT_FOUR) +# Python 3.2a2: 3170 (add DUP_TOP_TWO, remove DUP_TOPX and ROT_FOUR #9225) # tag: cpython-32 -# Python 3.2a2 3180 (add DELETE_DEREF) -# Python 3.3a0 3190 __class__ super closure changed -# Python 3.3a0 3200 (__qualname__ added) -# 3210 (added size modulo 2**32 to the pyc header) -# Python 3.3a1 3220 (changed PEP 380 implementation) -# Python 3.3a4 3230 (revert changes to implicit __class__ closure) +# Python 3.2a3 3180 (add DELETE_DEREF #4617) +# Python 3.3a1 3190 (__class__ super closure changed) +# Python 3.3a1 3200 (PEP 3155 __qualname__ added #13448) +# Python 3.3a1 3210 (added size modulo 2**32 to the pyc header #13645) +# Python 3.3a2 3220 (changed PEP 380 implementation #14230) +# Python 3.3a4 3230 (revert changes to implicit __class__ closure #14857) # Python 3.4a1 3250 (evaluate positional default arguments before -# keyword-only defaults) +# keyword-only defaults #16967) # Python 3.4a1 3260 (add LOAD_CLASSDEREF; allow locals of class to override -# free vars) -# Python 3.4a1 3270 (various tweaks to the __class__ closure) +# free vars #17853) +# Python 3.4a1 3270 (various tweaks to the __class__ closure #12370) # Python 3.4a1 3280 (remove implicit class argument) -# Python 3.4a4 3290 (changes to __qualname__ computation) -# Python 3.4a4 3300 (more changes to __qualname__ computation) -# Python 3.4rc2 3310 (alter __qualname__ computation) -# Python 3.5a0 3320 (matrix multiplication operator) -# Python 3.5b1 3330 (PEP 448: Additional Unpacking Generalizations) +# Python 3.4a4 3290 (changes to __qualname__ computation #19301) +# Python 3.4a4 3300 (more changes to __qualname__ computation #19301) +# Python 3.4rc2 3310 (alter __qualname__ computation #20625) +# Python 3.5a1 3320 (PEP 465: Matrix multiplication operator #21176) +# Python 3.5b1 3330 (PEP 448: Additional Unpacking Generalizations #2292) # Python 3.5b2 3340 (fix dictionary display evaluation order #11205) -# Python 3.5b2 3350 (add GET_YIELD_FROM_ITER opcode #24400) +# Python 3.5b3 3350 (add GET_YIELD_FROM_ITER opcode #24400) # Python 3.5.2 3351 (fix BUILD_MAP_UNPACK_WITH_CALL opcode #27286) -# Python 3.6a0 3360 (add FORMAT_VALUE opcode #25483 -# Python 3.6a0 3361 (lineno delta of code.co_lnotab becomes signed) -# Python 3.6a1 3370 (16 bit wordcode) -# Python 3.6a1 3371 (add BUILD_CONST_KEY_MAP opcode #27140) -# Python 3.6a1 3372 (MAKE_FUNCTION simplification, remove MAKE_CLOSURE +# Python 3.6a0 3360 (add FORMAT_VALUE opcode #25483) +# Python 3.6a1 3361 (lineno delta of code.co_lnotab becomes signed #26107) +# Python 3.6a2 3370 (16 bit wordcode #26647) +# Python 3.6a2 3371 (add BUILD_CONST_KEY_MAP opcode #27140) +# Python 3.6a2 3372 (MAKE_FUNCTION simplification, remove MAKE_CLOSURE # #27095) # Python 3.6b1 3373 (add BUILD_STRING opcode #27078) # Python 3.6b1 3375 (add SETUP_ANNOTATIONS and STORE_ANNOTATION opcodes # #27985) -# Python 3.6b1 3376 (simplify CALL_FUNCTIONs & BUILD_MAP_UNPACK_WITH_CALL) +# Python 3.6b1 3376 (simplify CALL_FUNCTIONs & BUILD_MAP_UNPACK_WITH_CALL + #27213) # Python 3.6b1 3377 (set __class__ cell from type.__new__ #23722) # Python 3.6b2 3378 (add BUILD_TUPLE_UNPACK_WITH_CALL #28257) # Python 3.6rc1 3379 (more thorough __class__ validation #23722) -# Python 3.7a0 3390 (add LOAD_METHOD and CALL_METHOD opcodes) -# Python 3.7a0 3391 (update GET_AITER #31709) -# Python 3.7a0 3392 (PEP 552: Deterministic pycs) -# Python 3.7a0 3393 (remove STORE_ANNOTATION opcode) +# Python 3.7a1 3390 (add LOAD_METHOD and CALL_METHOD opcodes #26110) +# 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) # # MAGIC must change whenever the bytecode emitted by the compiler may no # longer be understood by older implementations of the eval loop (usually diff --git a/Python/importlib_external.h b/Python/importlib_external.h index 73376a02e97e..7dd82492ef32 100644 --- a/Python/importlib_external.h +++ b/Python/importlib_external.h @@ -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, - 10,1,0,0,115,48,0,0,0,0,18,8,1,6,1,6, + 13,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,55,1,0,0,115,46,0,0,0,0,9, + 99,97,99,104,101,58,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,89,1,0,0, + 116,95,115,111,117,114,99,101,102,105,108,101,92,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,108,1,0,0,115,16,0,0,0,0,1,14,1,2, + 101,100,111,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,120,1,0,0,115,12,0,0,0, + 108,99,95,109,111,100,101,123,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,140, + 99,107,95,110,97,109,101,95,119,114,97,112,112,101,114,143, 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,151,1,0,0, + 114,4,0,0,0,218,5,95,119,114,97,112,154,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,132,1,0,0,115,14,0, + 104,101,99,107,95,110,97,109,101,135,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,160,1,0,0,115,10, + 111,100,117,108,101,95,115,104,105,109,163,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, - 177,1,0,0,115,28,0,0,0,0,16,12,1,8,1,16, + 180,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,210,1,0,0,115,14,0,0, + 116,97,109,112,95,112,121,99,213,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,238,1,0,0,115,8,0,0,0,0,17,16,1,2,1, + 99,241,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,6,2,0,0,115,16,0, + 95,98,121,116,101,99,111,100,101,9,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,19,2,0,0,115,12, + 101,115,116,97,109,112,95,112,121,99,22,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,29,2,0,0,115,14,0, + 95,104,97,115,104,95,112,121,99,32,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,40,2, + 13,100,101,99,111,100,101,95,115,111,117,114,99,101,43,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,57,2,0,0,115,62,0,0,0, + 111,99,97,116,105,111,110,60,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,137,2,0,0,115,8,0,0,0,0,2,2,1,14,1, + 121,140,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,144,2, + 101,97,114,99,104,95,114,101,103,105,115,116,114,121,147,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, - 159,2,0,0,115,26,0,0,0,0,2,10,1,8,1,4, + 162,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,175, + 0,0,218,11,102,105,110,100,95,109,111,100,117,108,101,178, 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,7 +1004,7 @@ 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,125,2,0,0,115,18,0, + 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, @@ -1039,7 +1039,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,194,2,0,0,115,8,0,0,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, @@ -1049,7 +1049,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,202,2, + 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, @@ -1069,7 +1069,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,205,2,0,0,115,10, + 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, @@ -1080,14 +1080,14 @@ const unsigned char _Py_M__importlib_external[] = { 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,213,2, + 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,189,2,0,0,115,8,0,0, + 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, @@ -1112,7 +1112,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,220,2,0,0,115,2,0, + 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, @@ -1147,7 +1147,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,228,2,0,0,115,2,0, + 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, @@ -1171,7 +1171,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,241,2,0,0,115,2,0,0,0,0,8,122, + 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, @@ -1188,7 +1188,7 @@ const unsigned char _Py_M__importlib_external[] = { 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, - 251,2,0,0,115,0,0,0,0,122,21,83,111,117,114,99, + 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, @@ -1208,7 +1208,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,2,3,0,0,115, + 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, @@ -1230,7 +1230,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,12,3,0,0,115,4,0,0, + 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, @@ -1309,7 +1309,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,20,3,0,0,115,134,0, + 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, @@ -1324,7 +1324,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,218,2,0, + 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, @@ -1354,7 +1354,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,111,3,0,0,115,4,0,0,0,0,3,6,1,122,19, + 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, @@ -1362,7 +1362,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,117, + 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, @@ -1371,7 +1371,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,121,3,0,0,115,2,0,0,0,0,1,122,19,70, + 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, @@ -1385,7 +1385,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,124,3,0,0,115,2,0, + 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, @@ -1396,7 +1396,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,136,3,0,0,115,2,0,0,0,0,3,122,23,70,105, + 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, @@ -1408,7 +1408,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,141,3,0,0,115,4,0,0,0,0,2, + 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, @@ -1416,7 +1416,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,148,3,0, + 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, @@ -1429,7 +1429,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,154,3,0,0,115,4,0,0,0,0,1,20,1,122, + 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, @@ -1442,7 +1442,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,158,3,0,0,115,8,0,0,0,0,1,10,1,4,1, + 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, @@ -1453,7 +1453,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,164,3,0,0,115,8,0,0,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, @@ -1463,7 +1463,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,170,3,0,0,115,2, + 218,8,99,111,110,116,101,110,116,115,173,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, @@ -1473,7 +1473,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,106,3,0,0,115,22,0,0,0,12, + 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, @@ -1495,7 +1495,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,178,3,0,0,115,4,0,0,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, @@ -1505,7 +1505,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,183,3,0,0,115,4,0, + 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, @@ -1540,7 +1540,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,188,3,0,0,115,42,0,0,0,0,2, + 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, @@ -1549,7 +1549,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,174,3,0,0,115,6,0,0,0,12,4,8,5,8, + 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, @@ -1570,7 +1570,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,223, + 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, @@ -1581,13 +1581,13 @@ const unsigned char _Py_M__importlib_external[] = { 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,239,3,0,0,115,2,0,0, + 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,219,3, + 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, @@ -1609,7 +1609,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,0,4,0,0,115,4, + 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, @@ -1618,7 +1618,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,4,4,0,0,115,4,0,0,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, @@ -1626,7 +1626,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,8,4,0,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, @@ -1643,7 +1643,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,11,4,0,0,115,10, + 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, @@ -1660,7 +1660,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,19,4,0,0,115,6,0, + 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, @@ -1678,7 +1678,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,28,4,0,0,115,2,0,0,0,4,1,122,49, + 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, @@ -1686,7 +1686,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,25,4,0,0,115,6,0,0, + 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, @@ -1697,7 +1697,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,31,4, + 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, @@ -1708,7 +1708,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,35,4,0,0,115,2,0,0,0,0,2,122, + 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, @@ -1719,7 +1719,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,39,4,0,0,115,2,0,0,0,0,3,122, + 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, @@ -1728,7 +1728,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,248,3,0,0,115,18,0,0,0,12,8,8,4, + 0,0,0,251,3,0,0,115,18,0,0,0,12,8,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 +1769,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,52,4,0,0,115,8,0,0,0,0,1, + 114,186,0,0,0,55,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 +1786,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,58,4,0,0,115,8, + 112,97,116,104,95,110,97,109,101,115,61,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 +1799,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,68,4,0,0,115,4,0,0,0,0,1, + 114,244,0,0,0,71,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 +1815,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, - 72,4,0,0,115,16,0,0,0,0,2,12,1,10,1,14, + 75,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 +1823,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,85,4,0,0,115, + 0,218,8,95,95,105,116,101,114,95,95,88,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 +1832,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, - 88,4,0,0,115,2,0,0,0,0,1,122,26,95,78,97, + 91,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,91,4,0,0,115, + 0,0,218,7,95,95,108,101,110,95,95,94,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 +1848,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,94,4,0,0,115,2,0, + 8,95,95,114,101,112,114,95,95,97,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 +1856,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,97,4,0,0,115,2,0,0,0, + 116,97,105,110,115,95,95,100,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 +1864,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,100,4,0,0,115,2,0,0, + 0,0,0,114,165,0,0,0,103,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,7 +1872,7 @@ 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,45,4,0,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, @@ -1889,7 +1889,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,106,4,0,0,115,2,0,0,0,0,1,122,25,95,78, + 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, @@ -1906,21 +1906,21 @@ const unsigned char _Py_M__importlib_external[] = { 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,109,4,0,0,115,2,0,0,0,0,7,122,28, + 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,118,4,0,0,115,2,0,0,0,0,1,122,27, + 0,0,0,121,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,121,4,0,0,115,2,0,0,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, @@ -1929,7 +1929,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,124,4, + 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, @@ -1939,14 +1939,14 @@ const unsigned char _Py_M__importlib_external[] = { 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,127,4,0,0,115,0,0,0,0,122, + 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,130,4,0,0,115,2,0,0,0,0,1, + 114,192,0,0,0,133,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, @@ -1964,7 +1964,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,133,4,0,0,115,6,0,0,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, @@ -1972,7 +1972,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,105,4,0,0,115, + 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, @@ -2006,7 +2006,7 @@ const unsigned char _Py_M__importlib_external[] = { 218,6,118,97,108,117,101,115,114,110,0,0,0,114,6,1, 0,0,41,2,114,172,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,151,4,0,0,115,6,0,0,0,0,4, + 114,6,1,0,0,154,4,0,0,115,6,0,0,0,0,4, 16,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, @@ -2026,7 +2026,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,159,4,0,0,115,16,0,0,0,0,3,16,1,12,1, + 115,162,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, @@ -2056,7 +2056,7 @@ const unsigned char _Py_M__importlib_external[] = { 114,111,114,114,11,1,0,0,41,3,114,172,0,0,0,114, 35,0,0,0,114,9,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,172,4, + 105,109,112,111,114,116,101,114,95,99,97,99,104,101,175,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, @@ -2074,7 +2074,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,0,114,9,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,194,4,0,0,115,18,0,0, + 103,101,116,95,115,112,101,99,197,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, @@ -2105,7 +2105,7 @@ const unsigned char _Py_M__importlib_external[] = { 110,97,109,101,115,112,97,99,101,95,112,97,116,104,90,5, 101,110,116,114,121,114,9,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,209,4, + 0,0,0,218,9,95,103,101,116,95,115,112,101,99,212,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, @@ -2132,7 +2132,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,16,1,0,0,114,2,0,0,0,114, - 2,0,0,0,114,4,0,0,0,114,182,0,0,0,241,4, + 2,0,0,0,114,4,0,0,0,114,182,0,0,0,244,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, @@ -2154,7 +2154,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,9,5,0,0,115,8,0,0,0,0,8,12, + 183,0,0,0,12,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, @@ -2162,7 +2162,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,114,6,1,0,0,114,11,1,0,0,114,13,1,0, 0,114,14,1,0,0,114,17,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,147,4, + 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,8,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, @@ -2206,7 +2206,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,38,5,0,0,115,2, + 114,4,0,0,0,114,238,0,0,0,41,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, @@ -2219,7 +2219,7 @@ const unsigned char _Py_M__importlib_external[] = { 108,111,97,100,101,114,95,100,101,116,97,105,108,115,90,7, 108,111,97,100,101,114,115,114,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,32,5,0,0,115,16,0,0,0,0,4,4,1,14, + 0,0,35,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, @@ -2228,7 +2228,7 @@ const unsigned char _Py_M__importlib_external[] = { 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, 20,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,46, + 114,2,0,0,0,114,4,0,0,0,114,6,1,0,0,49, 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, @@ -2251,7 +2251,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,52,5,0,0, + 0,0,114,4,0,0,0,114,119,0,0,0,55,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, @@ -2262,7 +2262,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,17,1,0,0,64,5,0,0,115,6,0, + 4,0,0,0,114,17,1,0,0,67,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, @@ -2316,7 +2316,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,69,5,0, + 0,0,0,114,4,0,0,0,114,182,0,0,0,72,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, @@ -2348,7 +2348,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,146,5,0,0,115,2,0,0,0,6, + 116,99,111,109,112,62,149,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, @@ -2364,7 +2364,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,25,1,0,0,117,5, + 2,0,0,0,114,4,0,0,0,114,25,1,0,0,120,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, @@ -2402,7 +2402,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,0,114,101,0,0,0,41,1,114,35,0,0,0,41, 2,114,172,0,0,0,114,24,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,158, + 95,102,111,114,95,70,105,108,101,70,105,110,100,101,114,161, 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, @@ -2410,7 +2410,7 @@ const unsigned char _Py_M__importlib_external[] = { 70,105,110,100,101,114,114,2,0,0,0,41,3,114,172,0, 0,0,114,24,1,0,0,114,30,1,0,0,114,2,0,0, 0,41,2,114,172,0,0,0,114,24,1,0,0,114,4,0, - 0,0,218,9,112,97,116,104,95,104,111,111,107,148,5,0, + 0,0,218,9,112,97,116,104,95,104,111,111,107,151,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, @@ -2419,7 +2419,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,166,5,0,0,115,2,0,0,0,0,1,122,19,70, + 0,0,169,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, @@ -2427,7 +2427,7 @@ const unsigned char _Py_M__importlib_external[] = { 119,0,0,0,114,17,1,0,0,114,182,0,0,0,114,25, 1,0,0,114,184,0,0,0,114,31,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,18,1,0,0,23,5,0,0,115, + 0,114,4,0,0,0,114,18,1,0,0,26,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,18,1,0,0,99,4,0,0,0, 0,0,0,0,6,0,0,0,8,0,0,0,67,0,0,0, @@ -2450,7 +2450,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,172,5,0,0, + 105,120,95,117,112,95,109,111,100,117,108,101,175,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,36,1,0,0,99,0,0,0, @@ -2470,7 +2470,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,195,5,0,0,115,8,0,0,0, + 0,0,114,163,0,0,0,198,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, @@ -2521,7 +2521,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,231,5,0,0,115,2,0,0,0,4,0,122,25, + 0,0,0,234,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, @@ -2548,7 +2548,7 @@ const unsigned char _Py_M__importlib_external[] = { 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,206,5,0,0,115,76,0, + 0,218,6,95,115,101,116,117,112,209,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, @@ -2568,7 +2568,7 @@ const unsigned char _Py_M__importlib_external[] = { 0,0,114,5,1,0,0,41,2,114,42,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,14,6,0,0,115,8, + 218,8,95,105,110,115,116,97,108,108,17,6,0,0,115,8, 0,0,0,0,2,8,1,6,1,20,1,114,45,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, @@ -2599,12 +2599,12 @@ const unsigned char _Py_M__importlib_external[] = { 163,0,0,0,114,43,1,0,0,114,45,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,116,0,0,0,4,0,4,1,4,1,2,1,6,3,8, + 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,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,5,14, - 127,0,22,10,23,8,11,8,64, + 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, + 5,14,127,0,22,10,23,8,11,8,64, }; From webhook-mailer at python.org Fri Feb 23 18:48:28 2018 From: webhook-mailer at python.org (Mariatta) Date: Fri, 23 Feb 2018 23:48:28 -0000 Subject: [Python-checkins] Update the Pull_request_template.md file (GH-5841) Message-ID: https://github.com/python/cpython/commit/82ab13d756a04eab1dae58629473b95ddf363484 commit: 82ab13d756a04eab1dae58629473b95ddf363484 branch: master author: Mariatta committer: GitHub date: 2018-02-23T15:48:21-08:00 summary: Update the Pull_request_template.md file (GH-5841) Changed the template to be inside a comment tag. files: M .github/PULL_REQUEST_TEMPLATE.md diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 0f238d0558cd..9040474860c5 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,4 +1,21 @@ -!!! If this is a backport PR (PR made against branches other than `master`), + From webhook-mailer at python.org Fri Feb 23 20:35:18 2018 From: webhook-mailer at python.org (Nathaniel J. Smith) Date: Sat, 24 Feb 2018 01:35:18 -0000 Subject: [Python-checkins] [bpo-28414] Make all hostnames in SSL module IDN A-labels (GH-5128) Message-ID: https://github.com/python/cpython/commit/11a1493bc4198f1def5e572049485779cf54dc57 commit: 11a1493bc4198f1def5e572049485779cf54dc57 branch: master author: Christian Heimes committer: Nathaniel J. Smith date: 2018-02-23T17:35:08-08:00 summary: [bpo-28414] Make all hostnames in SSL module IDN A-labels (GH-5128) Previously, the ssl module stored international domain names (IDNs) as U-labels. This is problematic for a number of reasons -- for example, it made it impossible for users to use a different version of IDNA than the one built into Python. After this change, we always convert to A-labels as soon as possible, and use them for all internal processing. In particular, server_hostname attribute is now an A-label, and on the server side there's a new sni_callback that receives the SNI servername as an A-label rather than a U-label. files: A Misc/NEWS.d/next/Security/2017-08-06-14-43-45.bpo-28414.mzZ6vD.rst M Doc/library/ssl.rst M Doc/whatsnew/3.7.rst M Lib/ssl.py M Lib/test/test_ssl.py M Modules/_ssl.c M Modules/clinic/_ssl.c.h diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 21da4f638713..4cad9f667c48 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -1268,6 +1268,12 @@ SSL sockets also have the following additional methods and attributes: .. versionadded:: 3.2 + .. versionchanged:: 3.7 + The attribute is now always ASCII text. When ``server_hostname`` is + an internationalized domain name (IDN), this attribute now stores the + A-label form (``"xn--pythn-mua.org"``), rather than the U-label form + (``"pyth?n.org"``). + .. attribute:: SSLSocket.session The :class:`SSLSession` for this SSL connection. The session is available @@ -1532,23 +1538,24 @@ to speed up repeated connections from the same clients. .. versionadded:: 3.3 -.. method:: SSLContext.set_servername_callback(server_name_callback) +.. attribute:: SSLContext.sni_callback Register a callback function that will be called after the TLS Client Hello handshake message has been received by the SSL/TLS server when the TLS client specifies a server name indication. The server name indication mechanism is specified in :rfc:`6066` section 3 - Server Name Indication. - Only one callback can be set per ``SSLContext``. If *server_name_callback* - is ``None`` then the callback is disabled. Calling this function a + Only one callback can be set per ``SSLContext``. If *sni_callback* + is set to ``None`` then the callback is disabled. Calling this function a subsequent time will disable the previously registered callback. - The callback function, *server_name_callback*, will be called with three + The callback function will be called with three arguments; the first being the :class:`ssl.SSLSocket`, the second is a string that represents the server name that the client is intending to communicate (or :const:`None` if the TLS Client Hello does not contain a server name) and the third argument is the original :class:`SSLContext`. The server name - argument is the IDNA decoded server name. + argument is text. For internationalized domain name, the server + name is an IDN A-label (``"xn--pythn-mua.org"``). A typical use of this callback is to change the :class:`ssl.SSLSocket`'s :attr:`SSLSocket.context` attribute to a new object of type @@ -1563,23 +1570,33 @@ to speed up repeated connections from the same clients. the TLS connection has progressed beyond the TLS Client Hello and therefore will not contain return meaningful values nor can they be called safely. - The *server_name_callback* function must return ``None`` to allow the + The *sni_callback* function must return ``None`` to allow the TLS negotiation to continue. If a TLS failure is required, a constant :const:`ALERT_DESCRIPTION_* ` can be returned. Other return values will result in a TLS fatal error with :const:`ALERT_DESCRIPTION_INTERNAL_ERROR`. - If there is an IDNA decoding error on the server name, the TLS connection - will terminate with an :const:`ALERT_DESCRIPTION_INTERNAL_ERROR` fatal TLS - alert message to the client. - - If an exception is raised from the *server_name_callback* function the TLS + If an exception is raised from the *sni_callback* function the TLS connection will terminate with a fatal TLS alert message :const:`ALERT_DESCRIPTION_HANDSHAKE_FAILURE`. This method will raise :exc:`NotImplementedError` if the OpenSSL library had OPENSSL_NO_TLSEXT defined when it was built. + .. versionadded:: 3.7 + +.. attribute:: SSLContext.set_servername_callback(server_name_callback) + + This is a legacy API retained for backwards compatibility. When possible, + you should use :attr:`sni_callback` instead. The given *server_name_callback* + is similar to *sni_callback*, except that when the server hostname is an + IDN-encoded internationalized domain name, the *server_name_callback* + receives a decoded U-label (``"pyth?n.org"``). + + If there is an decoding error on the server name, the TLS connection will + terminate with an :const:`ALERT_DESCRIPTION_INTERNAL_ERROR` fatal TLS + alert message to the client. + .. versionadded:: 3.4 .. method:: SSLContext.load_dh_params(dhfile) diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 50c9238e4aa8..c924f6ddd471 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -662,6 +662,14 @@ ciphers that have been blocked by OpenSSL security update. Default cipher suite selection can be configured on 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 +Nathaniel J. Smith and Christian Heimes in :issue:`28414`.) + + string ------ diff --git a/Lib/ssl.py b/Lib/ssl.py index b6161d0f178d..f2537698d303 100644 --- a/Lib/ssl.py +++ b/Lib/ssl.py @@ -355,13 +355,20 @@ def __new__(cls, protocol=PROTOCOL_TLS, *args, **kwargs): self = _SSLContext.__new__(cls, protocol) return self - def __init__(self, protocol=PROTOCOL_TLS): - self.protocol = protocol + def _encode_hostname(self, hostname): + if hostname is None: + return None + elif isinstance(hostname, str): + return hostname.encode('idna').decode('ascii') + else: + return hostname.decode('ascii') def wrap_socket(self, sock, server_side=False, do_handshake_on_connect=True, suppress_ragged_eofs=True, server_hostname=None, session=None): + # SSLSocket class handles server_hostname encoding before it calls + # ctx._wrap_socket() return self.sslsocket_class( sock=sock, server_side=server_side, @@ -374,8 +381,12 @@ def wrap_socket(self, sock, server_side=False, def wrap_bio(self, incoming, outgoing, server_side=False, server_hostname=None, session=None): - sslobj = self._wrap_bio(incoming, outgoing, server_side=server_side, - server_hostname=server_hostname) + # Need to encode server_hostname here because _wrap_bio() can only + # handle ASCII str. + sslobj = self._wrap_bio( + incoming, outgoing, server_side=server_side, + server_hostname=self._encode_hostname(server_hostname) + ) return self.sslobject_class(sslobj, session=session) def set_npn_protocols(self, npn_protocols): @@ -389,6 +400,19 @@ def set_npn_protocols(self, npn_protocols): self._set_npn_protocols(protos) + def set_servername_callback(self, server_name_callback): + if server_name_callback is None: + self.sni_callback = None + else: + if not callable(server_name_callback): + raise TypeError("not a callable object") + + def shim_cb(sslobj, servername, sslctx): + servername = self._encode_hostname(servername) + return server_name_callback(sslobj, servername, sslctx) + + self.sni_callback = shim_cb + def set_alpn_protocols(self, alpn_protocols): protos = bytearray() for protocol in alpn_protocols: @@ -447,6 +471,10 @@ def hostname_checks_common_name(self, value): def hostname_checks_common_name(self): return True + @property + def protocol(self): + return _SSLMethod(super().protocol) + @property def verify_flags(self): return VerifyFlags(super().verify_flags) @@ -749,7 +777,7 @@ def __init__(self, sock=None, keyfile=None, certfile=None, raise ValueError("check_hostname requires server_hostname") self._session = _session self.server_side = server_side - self.server_hostname = server_hostname + self.server_hostname = self._context._encode_hostname(server_hostname) self.do_handshake_on_connect = do_handshake_on_connect self.suppress_ragged_eofs = suppress_ragged_eofs if sock is not None: @@ -781,7 +809,7 @@ def __init__(self, sock=None, keyfile=None, certfile=None, # create the SSL object try: sslobj = self._context._wrap_socket(self, server_side, - server_hostname) + self.server_hostname) self._sslobj = SSLObject(sslobj, owner=self, session=self._session) if do_handshake_on_connect: diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index a253f51d2a44..a48eb890da43 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -1528,16 +1528,6 @@ def test_subclass(self): # For compatibility self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ) - def test_bad_idna_in_server_hostname(self): - # Note: this test is testing some code that probably shouldn't exist - # in the first place, so if it starts failing at some point because - # you made the ssl module stop doing IDNA decoding then please feel - # free to remove it. The test was mainly added because this case used - # to cause memory corruption (see bpo-30594). - ctx = ssl.create_default_context() - with self.assertRaises(UnicodeError): - ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(), - server_hostname="xn--.com") def test_bad_server_hostname(self): ctx = ssl.create_default_context() @@ -2634,10 +2624,10 @@ def test_check_hostname_idn(self): if support.verbose: sys.stdout.write("\n") - server_context = ssl.SSLContext(ssl.PROTOCOL_TLS) + server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) server_context.load_cert_chain(IDNSANSFILE) - context = ssl.SSLContext(ssl.PROTOCOL_TLS) + context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) context.verify_mode = ssl.CERT_REQUIRED context.check_hostname = True context.load_verify_locations(SIGNING_CA) @@ -2646,18 +2636,26 @@ def test_check_hostname_idn(self): # different ways idn_hostnames = [ ('k?nig.idn.pythontest.net', - 'k?nig.idn.pythontest.net',), + 'xn--knig-5qa.idn.pythontest.net'), ('xn--knig-5qa.idn.pythontest.net', 'xn--knig-5qa.idn.pythontest.net'), (b'xn--knig-5qa.idn.pythontest.net', - b'xn--knig-5qa.idn.pythontest.net'), + 'xn--knig-5qa.idn.pythontest.net'), ('k?nigsg??chen.idna2003.pythontest.net', - 'k?nigsg??chen.idna2003.pythontest.net'), + 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'), ('xn--knigsgsschen-lcb0w.idna2003.pythontest.net', 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'), (b'xn--knigsgsschen-lcb0w.idna2003.pythontest.net', - b'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'), + 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'), + + # ('k?nigsg??chen.idna2008.pythontest.net', + # 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'), + ('xn--knigsgchen-b4a3dun.idna2008.pythontest.net', + 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'), + (b'xn--knigsgchen-b4a3dun.idna2008.pythontest.net', + 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'), + ] for server_hostname, expected_hostname in idn_hostnames: server = ThreadedEchoServer(context=server_context, chatty=True) @@ -2676,16 +2674,6 @@ def test_check_hostname_idn(self): s.getpeercert() self.assertEqual(s.server_hostname, expected_hostname) - # bug https://bugs.python.org/issue28414 - # IDNA 2008 deviations are broken - idna2008 = 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net' - server = ThreadedEchoServer(context=server_context, chatty=True) - with server: - with self.assertRaises(UnicodeError): - with context.wrap_socket(socket.socket(), - server_hostname=idna2008) as s: - s.connect((HOST, server.port)) - # incorrect hostname should raise an exception server = ThreadedEchoServer(context=server_context, chatty=True) with server: diff --git a/Misc/NEWS.d/next/Security/2017-08-06-14-43-45.bpo-28414.mzZ6vD.rst b/Misc/NEWS.d/next/Security/2017-08-06-14-43-45.bpo-28414.mzZ6vD.rst new file mode 100644 index 000000000000..06528c93ee19 --- /dev/null +++ b/Misc/NEWS.d/next/Security/2017-08-06-14-43-45.bpo-28414.mzZ6vD.rst @@ -0,0 +1 @@ +The ssl module now allows users to perform their own IDN en/decoding when using SNI. diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 7545e91babdb..a0f8c1cb3244 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -337,13 +337,14 @@ typedef struct { unsigned int alpn_protocols_len; #endif #ifndef OPENSSL_NO_TLSEXT - PyObject *set_hostname; + PyObject *set_sni_cb; #endif int check_hostname; /* OpenSSL has no API to get hostflags from X509_VERIFY_PARAM* struct. * We have to maintain our own copy. OpenSSL's hostflags default to 0. */ unsigned int hostflags; + int protocol; } PySSLContext; typedef struct { @@ -407,8 +408,6 @@ class _ssl.SSLSession "PySSLSession *" "&PySSLSession_Type" static int PySSL_select(PySocketSockObject *s, int writing, _PyTime_t timeout); - -#define PySSLContext_Check(v) (Py_TYPE(v) == &PySSLContext_Type) #define PySSLSocket_Check(v) (Py_TYPE(v) == &PySSLSocket_Type) #define PySSLMemoryBIO_Check(v) (Py_TYPE(v) == &PySSLMemoryBIO_Type) #define PySSLSession_Check(v) (Py_TYPE(v) == &PySSLSession_Type) @@ -761,7 +760,7 @@ _ssl_configure_hostname(PySSLSocket *self, const char* server_hostname) ERR_clear_error(); } - hostname = PyUnicode_Decode(server_hostname, len, "idna", "strict"); + hostname = PyUnicode_Decode(server_hostname, len, "ascii", "strict"); if (hostname == NULL) { goto error; } @@ -1992,7 +1991,7 @@ PyDoc_STRVAR(PySSL_set_context_doc, "_setter_context(ctx)\n\ \ This changes the context associated with the SSLSocket. This is typically\n\ -used from within a callback function set by the set_servername_callback\n\ +used from within a callback function set by the sni_callback\n\ on the SSLContext to change the certificate information associated with the\n\ SSLSocket before the cryptographic exchange handshake messages\n"); @@ -2850,6 +2849,7 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version) } self->ctx = ctx; self->hostflags = X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS; + self->protocol = proto_version; #if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG) self->npn_protocols = NULL; #endif @@ -2857,7 +2857,7 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version) self->alpn_protocols = NULL; #endif #ifndef OPENSSL_NO_TLSEXT - self->set_hostname = NULL; + self->set_sni_cb = NULL; #endif /* Don't check host name by default */ if (proto_version == PY_SSL_VERSION_TLS_CLIENT) { @@ -2968,7 +2968,7 @@ static int context_traverse(PySSLContext *self, visitproc visit, void *arg) { #ifndef OPENSSL_NO_TLSEXT - Py_VISIT(self->set_hostname); + Py_VISIT(self->set_sni_cb); #endif return 0; } @@ -2977,7 +2977,7 @@ static int context_clear(PySSLContext *self) { #ifndef OPENSSL_NO_TLSEXT - Py_CLEAR(self->set_hostname); + Py_CLEAR(self->set_sni_cb); #endif return 0; } @@ -3354,6 +3354,10 @@ set_check_hostname(PySSLContext *self, PyObject *arg, void *c) return 0; } +static PyObject * +get_protocol(PySSLContext *self, void *c) { + return PyLong_FromLong(self->protocol); +} typedef struct { PyThreadState *thread_state; @@ -3818,9 +3822,9 @@ _ssl__SSLContext__wrap_socket_impl(PySSLContext *self, PyObject *sock, PyObject *res; /* server_hostname is either None (or absent), or to be encoded - using the idna encoding. */ + as IDN A-label (ASCII str). */ if (hostname_obj != Py_None) { - if (!PyArg_Parse(hostname_obj, "et", "idna", &hostname)) + if (!PyArg_Parse(hostname_obj, "es", "ascii", &hostname)) return NULL; } @@ -3851,9 +3855,9 @@ _ssl__SSLContext__wrap_bio_impl(PySSLContext *self, PySSLMemoryBIO *incoming, PyObject *res; /* server_hostname is either None (or absent), or to be encoded - using the idna encoding. */ + as IDN A-label (ASCII str). */ if (hostname_obj != Py_None) { - if (!PyArg_Parse(hostname_obj, "et", "idna", &hostname)) + if (!PyArg_Parse(hostname_obj, "es", "ascii", &hostname)) return NULL; } @@ -3967,15 +3971,13 @@ _servername_callback(SSL *s, int *al, void *args) int ret; PySSLContext *ssl_ctx = (PySSLContext *) args; PySSLSocket *ssl; - PyObject *servername_o; - PyObject *servername_idna; PyObject *result; /* The high-level ssl.SSLSocket object */ PyObject *ssl_socket; const char *servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name); PyGILState_STATE gstate = PyGILState_Ensure(); - if (ssl_ctx->set_hostname == NULL) { + if (ssl_ctx->set_sni_cb == NULL) { /* remove race condition in this the call back while if removing the * callback is in progress */ PyGILState_Release(gstate); @@ -4005,35 +4007,46 @@ _servername_callback(SSL *s, int *al, void *args) goto error; if (servername == NULL) { - result = PyObject_CallFunctionObjArgs(ssl_ctx->set_hostname, ssl_socket, + result = PyObject_CallFunctionObjArgs(ssl_ctx->set_sni_cb, ssl_socket, Py_None, ssl_ctx, NULL); } else { - servername_o = PyBytes_FromString(servername); - if (servername_o == NULL) { + PyObject *servername_bytes; + PyObject *servername_str; + + servername_bytes = PyBytes_FromString(servername); + if (servername_bytes == NULL) { PyErr_WriteUnraisable((PyObject *) ssl_ctx); goto error; } - servername_idna = PyUnicode_FromEncodedObject(servername_o, "idna", NULL); - if (servername_idna == NULL) { - PyErr_WriteUnraisable(servername_o); - Py_DECREF(servername_o); + /* server_hostname was encoded to an A-label by our caller; put it + * back into a str object, but still as an A-label (bpo-28414) + */ + servername_str = PyUnicode_FromEncodedObject(servername_bytes, "ascii", NULL); + Py_DECREF(servername_bytes); + if (servername_str == NULL) { + PyErr_WriteUnraisable(servername_bytes); goto error; } - Py_DECREF(servername_o); - result = PyObject_CallFunctionObjArgs(ssl_ctx->set_hostname, ssl_socket, - servername_idna, ssl_ctx, NULL); - Py_DECREF(servername_idna); + result = PyObject_CallFunctionObjArgs( + ssl_ctx->set_sni_cb, ssl_socket, servername_str, + ssl_ctx, NULL); + Py_DECREF(servername_str); } Py_DECREF(ssl_socket); if (result == NULL) { - PyErr_WriteUnraisable(ssl_ctx->set_hostname); + PyErr_WriteUnraisable(ssl_ctx->set_sni_cb); *al = SSL_AD_HANDSHAKE_FAILURE; ret = SSL_TLSEXT_ERR_ALERT_FATAL; } else { - if (result != Py_None) { + /* Result may be None, a SSLContext or an integer + * None and SSLContext are OK, integer or other values are an error. + */ + if (result == Py_None) { + ret = SSL_TLSEXT_ERR_OK; + } else { *al = (int) PyLong_AsLong(result); if (PyErr_Occurred()) { PyErr_WriteUnraisable(result); @@ -4041,9 +4054,6 @@ _servername_callback(SSL *s, int *al, void *args) } ret = SSL_TLSEXT_ERR_ALERT_FATAL; } - else { - ret = SSL_TLSEXT_ERR_OK; - } Py_DECREF(result); } @@ -4059,49 +4069,59 @@ _servername_callback(SSL *s, int *al, void *args) } #endif -/*[clinic input] -_ssl._SSLContext.set_servername_callback - method as cb: object - / - -Set a callback that will be called when a server name is provided by the SSL/TLS client in the SNI extension. - -If the argument is None then the callback is disabled. The method is called -with the SSLSocket, the server name as a string, and the SSLContext object. -See RFC 6066 for details of the SNI extension. -[clinic start generated code]*/ - static PyObject * -_ssl__SSLContext_set_servername_callback(PySSLContext *self, PyObject *cb) -/*[clinic end generated code: output=3439a1b2d5d3b7ea input=a2a83620197d602b]*/ +get_sni_callback(PySSLContext *self, void *c) { + PyObject *cb = self->set_sni_cb; + if (cb == NULL) { + Py_RETURN_NONE; + } + Py_INCREF(cb); + return cb; +} + +static int +set_sni_callback(PySSLContext *self, PyObject *arg, void *c) +{ + if (self->protocol == PY_SSL_VERSION_TLS_CLIENT) { + PyErr_SetString(PyExc_ValueError, + "sni_callback cannot be set on TLS_CLIENT context"); + return -1; + } #if HAVE_SNI && !defined(OPENSSL_NO_TLSEXT) - Py_CLEAR(self->set_hostname); - if (cb == Py_None) { + Py_CLEAR(self->set_sni_cb); + if (arg == Py_None) { SSL_CTX_set_tlsext_servername_callback(self->ctx, NULL); } else { - if (!PyCallable_Check(cb)) { + if (!PyCallable_Check(arg)) { SSL_CTX_set_tlsext_servername_callback(self->ctx, NULL); PyErr_SetString(PyExc_TypeError, "not a callable object"); - return NULL; + return -1; } - Py_INCREF(cb); - self->set_hostname = cb; + Py_INCREF(arg); + self->set_sni_cb = arg; SSL_CTX_set_tlsext_servername_callback(self->ctx, _servername_callback); SSL_CTX_set_tlsext_servername_arg(self->ctx, self); } - Py_RETURN_NONE; + return 0; #else PyErr_SetString(PyExc_NotImplementedError, "The TLS extension servername callback, " "SSL_CTX_set_tlsext_servername_callback, " "is not in the current OpenSSL library."); - return NULL; + return -1; #endif } +PyDoc_STRVAR(PySSLContext_sni_callback_doc, +"Set a callback that will be called when a server name is provided by the SSL/TLS client in the SNI extension.\n\ +\n\ +If the argument is None then the callback is disabled. The method is called\n\ +with the SSLSocket, the server name as a string, and the SSLContext object.\n\ +See RFC 6066 for details of the SNI extension."); + /*[clinic input] _ssl._SSLContext.cert_store_stats @@ -4217,8 +4237,12 @@ static PyGetSetDef context_getsetlist[] = { (setter) set_check_hostname, NULL}, {"_host_flags", (getter) get_host_flags, (setter) set_host_flags, NULL}, + {"sni_callback", (getter) get_sni_callback, + (setter) set_sni_callback, PySSLContext_sni_callback_doc}, {"options", (getter) get_options, (setter) set_options, NULL}, + {"protocol", (getter) get_protocol, + NULL, NULL}, {"verify_flags", (getter) get_verify_flags, (setter) set_verify_flags, NULL}, {"verify_mode", (getter) get_verify_mode, @@ -4238,7 +4262,6 @@ static struct PyMethodDef context_methods[] = { _SSL__SSLCONTEXT_SESSION_STATS_METHODDEF _SSL__SSLCONTEXT_SET_DEFAULT_VERIFY_PATHS_METHODDEF _SSL__SSLCONTEXT_SET_ECDH_CURVE_METHODDEF - _SSL__SSLCONTEXT_SET_SERVERNAME_CALLBACK_METHODDEF _SSL__SSLCONTEXT_CERT_STORE_STATS_METHODDEF _SSL__SSLCONTEXT_GET_CA_CERTS_METHODDEF _SSL__SSLCONTEXT_GET_CIPHERS_METHODDEF diff --git a/Modules/clinic/_ssl.c.h b/Modules/clinic/_ssl.c.h index 32743e710f59..d1a9afcd1d1e 100644 --- a/Modules/clinic/_ssl.c.h +++ b/Modules/clinic/_ssl.c.h @@ -650,19 +650,6 @@ PyDoc_STRVAR(_ssl__SSLContext_set_ecdh_curve__doc__, #endif /* !defined(OPENSSL_NO_ECDH) */ -PyDoc_STRVAR(_ssl__SSLContext_set_servername_callback__doc__, -"set_servername_callback($self, method, /)\n" -"--\n" -"\n" -"Set a callback that will be called when a server name is provided by the SSL/TLS client in the SNI extension.\n" -"\n" -"If the argument is None then the callback is disabled. The method is called\n" -"with the SSLSocket, the server name as a string, and the SSLContext object.\n" -"See RFC 6066 for details of the SNI extension."); - -#define _SSL__SSLCONTEXT_SET_SERVERNAME_CALLBACK_METHODDEF \ - {"set_servername_callback", (PyCFunction)_ssl__SSLContext_set_servername_callback, METH_O, _ssl__SSLContext_set_servername_callback__doc__}, - PyDoc_STRVAR(_ssl__SSLContext_cert_store_stats__doc__, "cert_store_stats($self, /)\n" "--\n" @@ -1168,4 +1155,4 @@ _ssl_enum_crls(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje #ifndef _SSL_ENUM_CRLS_METHODDEF #define _SSL_ENUM_CRLS_METHODDEF #endif /* !defined(_SSL_ENUM_CRLS_METHODDEF) */ -/*[clinic end generated code: output=3d42305ed0ad162a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=84e1fd89aff9b0f7 input=a9049054013a1b77]*/ From webhook-mailer at python.org Fri Feb 23 21:35:30 2018 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Sat, 24 Feb 2018 02:35:30 -0000 Subject: [Python-checkins] bpo-32916: IDLE: Change `str` to `code` in pyparse (GH-5830) Message-ID: https://github.com/python/cpython/commit/c29c03a34a9f3c82704b66f323ce5ea9dc89c8af commit: c29c03a34a9f3c82704b66f323ce5ea9dc89c8af branch: master author: Cheryl Sabella committer: Terry Jan Reedy date: 2018-02-23T21:35:27-05:00 summary: bpo-32916: IDLE: Change `str` to `code` in pyparse (GH-5830) Adjust tests and user modules to match. files: A Misc/NEWS.d/next/IDLE/2018-02-23-07-32-36.bpo-32916.4MsQ5F.rst M Lib/idlelib/editor.py M Lib/idlelib/hyperparser.py M Lib/idlelib/idle_test/test_pyparse.py M Lib/idlelib/pyparse.py diff --git a/Lib/idlelib/editor.py b/Lib/idlelib/editor.py index b51c45c97e50..ab9c7e615ef0 100644 --- a/Lib/idlelib/editor.py +++ b/Lib/idlelib/editor.py @@ -1302,7 +1302,7 @@ def newline_and_indent_event(self, event): startat = max(lno - context, 1) startatindex = repr(startat) + ".0" rawtext = text.get(startatindex, "insert") - y.set_str(rawtext) + y.set_code(rawtext) bod = y.find_good_parse_start( self.context_use_ps1, self._build_char_in_string_func(startatindex)) @@ -1316,7 +1316,7 @@ def newline_and_indent_event(self, event): else: startatindex = "1.0" rawtext = text.get(startatindex, "insert") - y.set_str(rawtext) + y.set_code(rawtext) y.set_lo(0) c = y.get_continuation_type() diff --git a/Lib/idlelib/hyperparser.py b/Lib/idlelib/hyperparser.py index 450a709c09bb..a42665bb6328 100644 --- a/Lib/idlelib/hyperparser.py +++ b/Lib/idlelib/hyperparser.py @@ -44,7 +44,7 @@ def index2line(index): # at end. We add a space so that index won't be at end # of line, so that its status will be the same as the # char before it, if should. - parser.set_str(text.get(startatindex, stopatindex)+' \n') + parser.set_code(text.get(startatindex, stopatindex)+' \n') bod = parser.find_good_parse_start( editwin._build_char_in_string_func(startatindex)) if bod is not None or startat == 1: @@ -60,12 +60,12 @@ def index2line(index): # We add the newline because PyParse requires it. We add a # space so that index won't be at end of line, so that its # status will be the same as the char before it, if should. - parser.set_str(text.get(startatindex, stopatindex)+' \n') + parser.set_code(text.get(startatindex, stopatindex)+' \n') parser.set_lo(0) # We want what the parser has, minus the last newline and space. - self.rawtext = parser.str[:-2] - # Parser.str apparently preserves the statement we are in, so + self.rawtext = parser.code[:-2] + # Parser.code apparently preserves the statement we are in, so # that stopatindex can be used to synchronize the string with # the text box indices. self.stopatindex = stopatindex diff --git a/Lib/idlelib/idle_test/test_pyparse.py b/Lib/idlelib/idle_test/test_pyparse.py index c45815b36ff2..c7b645caa6a8 100644 --- a/Lib/idlelib/idle_test/test_pyparse.py +++ b/Lib/idlelib/idle_test/test_pyparse.py @@ -62,32 +62,32 @@ def test_init(self): self.assertEqual(self.parser.indentwidth, 4) self.assertEqual(self.parser.tabwidth, 4) - def test_set_str(self): + def test_set_code(self): eq = self.assertEqual p = self.parser - setstr = p.set_str + setcode = p.set_code # Not empty and doesn't end with newline. with self.assertRaises(AssertionError): - setstr('a') + setcode('a') tests = ('', 'a\n') for string in tests: with self.subTest(string=string): - setstr(string) - eq(p.str, string) + setcode(string) + eq(p.code, string) eq(p.study_level, 0) def test_find_good_parse_start(self): eq = self.assertEqual p = self.parser - setstr = p.set_str + setcode = p.set_code start = p.find_good_parse_start # Split def across lines. - setstr('"""This is a module docstring"""\n' + setcode('"""This is a module docstring"""\n' 'class C():\n' ' def __init__(self, a,\n' ' b=True):\n' @@ -117,7 +117,7 @@ def test_find_good_parse_start(self): # Code without extra line break in def line - mostly returns the same # values. - setstr('"""This is a module docstring"""\n' + setcode('"""This is a module docstring"""\n' 'class C():\n' ' def __init__(self, a, b=True):\n' ' pass\n' @@ -138,19 +138,19 @@ def test_set_lo(self): ' pass\n' ) p = self.parser - p.set_str(code) + p.set_code(code) # Previous character is not a newline. with self.assertRaises(AssertionError): p.set_lo(5) - # A value of 0 doesn't change self.str. + # A value of 0 doesn't change self.code. p.set_lo(0) - self.assertEqual(p.str, code) + self.assertEqual(p.code, code) # An index that is preceded by a newline. p.set_lo(44) - self.assertEqual(p.str, code[44:]) + self.assertEqual(p.code, code[44:]) def test_tran(self): self.assertEqual('\t a([{b}])b"c\'d\n'.translate(self.parser._tran), @@ -159,7 +159,7 @@ def test_tran(self): def test_study1(self): eq = self.assertEqual p = self.parser - setstr = p.set_str + setcode = p.set_code study = p._study1 (NONE, BACKSLASH, FIRST, NEXT, BRACKET) = range(5) @@ -197,7 +197,7 @@ def test_study1(self): for test in tests: with self.subTest(string=test.string): - setstr(test.string) # resets study_level + setcode(test.string) # resets study_level study() eq(p.study_level, 1) eq(p.goodlines, test.goodlines) @@ -209,7 +209,7 @@ def test_study1(self): def test_get_continuation_type(self): eq = self.assertEqual p = self.parser - setstr = p.set_str + setcode = p.set_code gettype = p.get_continuation_type (NONE, BACKSLASH, FIRST, NEXT, BRACKET) = range(5) @@ -224,13 +224,13 @@ def test_get_continuation_type(self): for test in tests: with self.subTest(string=test.string): - setstr(test.string) + setcode(test.string) eq(gettype(), test.continuation) def test_study2(self): eq = self.assertEqual p = self.parser - setstr = p.set_str + setcode = p.set_code study = p._study2 TestInfo = namedtuple('TestInfo', ['string', 'start', 'end', 'lastch', @@ -276,7 +276,7 @@ def test_study2(self): for test in tests: with self.subTest(string=test.string): - setstr(test.string) + setcode(test.string) study() eq(p.study_level, 2) eq(p.stmt_start, test.start) @@ -291,7 +291,7 @@ def test_study2(self): def test_get_num_lines_in_stmt(self): eq = self.assertEqual p = self.parser - setstr = p.set_str + setcode = p.set_code getlines = p.get_num_lines_in_stmt TestInfo = namedtuple('TestInfo', ['string', 'lines']) @@ -307,19 +307,19 @@ def test_get_num_lines_in_stmt(self): ) # Blank string doesn't have enough elements in goodlines. - setstr('') + setcode('') with self.assertRaises(IndexError): getlines() for test in tests: with self.subTest(string=test.string): - setstr(test.string) + setcode(test.string) eq(getlines(), test.lines) def test_compute_bracket_indent(self): eq = self.assertEqual p = self.parser - setstr = p.set_str + setcode = p.set_code indent = p.compute_bracket_indent TestInfo = namedtuple('TestInfo', ['string', 'spaces']) @@ -340,18 +340,18 @@ def test_compute_bracket_indent(self): ) # Must be C_BRACKET continuation type. - setstr('def function1(self, a, b):\n') + setcode('def function1(self, a, b):\n') with self.assertRaises(AssertionError): indent() for test in tests: - setstr(test.string) + setcode(test.string) eq(indent(), test.spaces) def test_compute_backslash_indent(self): eq = self.assertEqual p = self.parser - setstr = p.set_str + setcode = p.set_code indent = p.compute_backslash_indent # Must be C_BACKSLASH continuation type. @@ -361,7 +361,7 @@ def test_compute_backslash_indent(self): ) for string in errors: with self.subTest(string=string): - setstr(string) + setcode(string) with self.assertRaises(AssertionError): indent() @@ -384,13 +384,13 @@ def test_compute_backslash_indent(self): ) for test in tests: with self.subTest(string=test.string): - setstr(test.string) + setcode(test.string) eq(indent(), test.spaces) def test_get_base_indent_string(self): eq = self.assertEqual p = self.parser - setstr = p.set_str + setcode = p.set_code baseindent = p.get_base_indent_string TestInfo = namedtuple('TestInfo', ['string', 'indent']) @@ -405,14 +405,14 @@ def test_get_base_indent_string(self): for test in tests: with self.subTest(string=test.string): - setstr(test.string) + setcode(test.string) eq(baseindent(), test.indent) def test_is_block_opener(self): yes = self.assertTrue no = self.assertFalse p = self.parser - setstr = p.set_str + setcode = p.set_code opener = p.is_block_opener TestInfo = namedtuple('TestInfo', ['string', 'assert_']) @@ -433,14 +433,14 @@ def test_is_block_opener(self): for test in tests: with self.subTest(string=test.string): - setstr(test.string) + setcode(test.string) test.assert_(opener()) def test_is_block_closer(self): yes = self.assertTrue no = self.assertFalse p = self.parser - setstr = p.set_str + setcode = p.set_code closer = p.is_block_closer TestInfo = namedtuple('TestInfo', ['string', 'assert_']) @@ -462,13 +462,13 @@ def test_is_block_closer(self): for test in tests: with self.subTest(string=test.string): - setstr(test.string) + setcode(test.string) test.assert_(closer()) def test_get_last_stmt_bracketing(self): eq = self.assertEqual p = self.parser - setstr = p.set_str + setcode = p.set_code bracketing = p.get_last_stmt_bracketing TestInfo = namedtuple('TestInfo', ['string', 'bracket']) @@ -489,7 +489,7 @@ def test_get_last_stmt_bracketing(self): for test in tests: with self.subTest(string=test.string): - setstr(test.string) + setcode(test.string) eq(bracketing(), test.bracket) diff --git a/Lib/idlelib/pyparse.py b/Lib/idlelib/pyparse.py index 93607dc5bcd0..443d198d1efe 100644 --- a/Lib/idlelib/pyparse.py +++ b/Lib/idlelib/pyparse.py @@ -149,9 +149,9 @@ def __init__(self, indentwidth, tabwidth): self.indentwidth = indentwidth self.tabwidth = tabwidth - def set_str(self, s): + def set_code(self, s): assert len(s) == 0 or s[-1] == '\n' - self.str = s + self.code = s self.study_level = 0 def find_good_parse_start(self, is_char_in_string=None, @@ -168,7 +168,7 @@ def find_good_parse_start(self, is_char_in_string=None, function, meaning that when it says "no", it's absolutely guaranteed that the char is not in a string. """ - str, pos = self.str, None + code, pos = self.code, None if not is_char_in_string: # no clue -- make the caller pass everything @@ -177,13 +177,13 @@ def find_good_parse_start(self, is_char_in_string=None, # Peek back from the end for a good place to start, # but don't try too often; pos will be left None, or # bumped to a legitimate synch point. - limit = len(str) + limit = len(code) for tries in range(5): - i = str.rfind(":\n", 0, limit) + i = code.rfind(":\n", 0, limit) if i < 0: break - i = str.rfind('\n', 0, i) + 1 # start of colon line (-1+1=0) - m = _synchre(str, i, limit) + i = code.rfind('\n', 0, i) + 1 # start of colon line (-1+1=0) + m = _synchre(code, i, limit) if m and not is_char_in_string(m.start()): pos = m.start() break @@ -197,7 +197,7 @@ def find_good_parse_start(self, is_char_in_string=None, # going to have to parse the whole thing to be sure, so # give it one last try from the start, but stop wasting # time here regardless of the outcome. - m = _synchre(str) + m = _synchre(code) if m and not is_char_in_string(m.start()): pos = m.start() return pos @@ -206,7 +206,7 @@ def find_good_parse_start(self, is_char_in_string=None, # matches. i = pos + 1 while 1: - m = _synchre(str, i) + m = _synchre(code, i) if m: s, i = m.span() if not is_char_in_string(s): @@ -220,9 +220,9 @@ def set_lo(self, lo): Intended to be called with the result of find_good_parse_start(). """ - assert lo == 0 or self.str[lo-1] == '\n' + assert lo == 0 or self.code[lo-1] == '\n' if lo > 0: - self.str = self.str[lo:] + self.code = self.code[lo:] # Build a translation table to map uninteresting chars to 'x', open # brackets to '(', close brackets to ')' while preserving quotes, @@ -249,13 +249,13 @@ def _study1(self): # to "(", all close brackets to ")", then collapse runs of # uninteresting characters. This can cut the number of chars # by a factor of 10-40, and so greatly speed the following loop. - str = self.str - str = str.translate(self._tran) - str = str.replace('xxxxxxxx', 'x') - str = str.replace('xxxx', 'x') - str = str.replace('xx', 'x') - str = str.replace('xx', 'x') - str = str.replace('\nx', '\n') + code = self.code + code = code.translate(self._tran) + code = code.replace('xxxxxxxx', 'x') + code = code.replace('xxxx', 'x') + code = code.replace('xx', 'x') + code = code.replace('xx', 'x') + code = code.replace('\nx', '\n') # Replacing x\n with \n would be incorrect because # x may be preceded by a backslash. @@ -266,9 +266,9 @@ def _study1(self): level = lno = 0 # level is nesting level; lno is line number self.goodlines = goodlines = [0] push_good = goodlines.append - i, n = 0, len(str) + i, n = 0, len(code) while i < n: - ch = str[i] + ch = code[i] i = i+1 # cases are checked in decreasing order of frequency @@ -295,19 +295,19 @@ def _study1(self): if ch == '"' or ch == "'": # consume the string quote = ch - if str[i-1:i+2] == quote * 3: + if code[i-1:i+2] == quote * 3: quote = quote * 3 firstlno = lno w = len(quote) - 1 i = i+w while i < n: - ch = str[i] + ch = code[i] i = i+1 if ch == 'x': continue - if str[i-1:i+w] == quote: + if code[i-1:i+w] == quote: i = i+w break @@ -322,7 +322,7 @@ def _study1(self): if ch == '\\': assert i < n - if str[i] == '\n': + if code[i] == '\n': lno = lno + 1 i = i+1 continue @@ -333,7 +333,7 @@ def _study1(self): # didn't break out of the loop, so we're still # inside a string if (lno - 1) == firstlno: - # before the previous \n in str, we were in the first + # before the previous \n in code, we were in the first # line of the string continuation = C_STRING_FIRST_LINE else: @@ -342,13 +342,13 @@ def _study1(self): if ch == '#': # consume the comment - i = str.find('\n', i) + i = code.find('\n', i) assert i >= 0 continue assert ch == '\\' assert i < n - if str[i] == '\n': + if code[i] == '\n': lno = lno + 1 if i+1 == n: continuation = C_BACKSLASH @@ -397,9 +397,9 @@ def _study2(self): self.study_level = 2 # Set p and q to slice indices of last interesting stmt. - str, goodlines = self.str, self.goodlines + code, goodlines = self.code, self.goodlines i = len(goodlines) - 1 # Index of newest line. - p = len(str) # End of goodlines[i] + p = len(code) # End of goodlines[i] while i: assert p # Make p be the index of the stmt at line number goodlines[i]. @@ -407,10 +407,10 @@ def _study2(self): q = p for nothing in range(goodlines[i-1], goodlines[i]): # tricky: sets p to 0 if no preceding newline - p = str.rfind('\n', 0, p-1) + 1 - # The stmt str[p:q] isn't a continuation, but may be blank + p = code.rfind('\n', 0, p-1) + 1 + # The stmt code[p:q] isn't a continuation, but may be blank # or a non-indenting comment line. - if _junkre(str, p): + if _junkre(code, p): i = i-1 else: break @@ -428,21 +428,21 @@ def _study2(self): bracketing = [(p, 0)] while p < q: # suck up all except ()[]{}'"#\\ - m = _chew_ordinaryre(str, p, q) + m = _chew_ordinaryre(code, p, q) if m: # we skipped at least one boring char newp = m.end() # back up over totally boring whitespace i = newp - 1 # index of last boring char - while i >= p and str[i] in " \t\n": + while i >= p and code[i] in " \t\n": i = i-1 if i >= p: - lastch = str[i] + lastch = code[i] p = newp if p >= q: break - ch = str[p] + ch = code[p] if ch in "([{": push_stack(p) @@ -469,14 +469,14 @@ def _study2(self): # have to. bracketing.append((p, len(stack)+1)) lastch = ch - p = _match_stringre(str, p, q).end() + p = _match_stringre(code, p, q).end() bracketing.append((p, len(stack))) continue if ch == '#': # consume comment and trailing newline bracketing.append((p, len(stack)+1)) - p = str.find('\n', p, q) + 1 + p = code.find('\n', p, q) + 1 assert p > 0 bracketing.append((p, len(stack))) continue @@ -484,9 +484,9 @@ def _study2(self): assert ch == '\\' p = p+1 # beyond backslash assert p < q - if str[p] != '\n': + if code[p] != '\n': # the program is invalid, but can't complain - lastch = ch + str[p] + lastch = ch + code[p] p = p+1 # beyond escaped char # end while p < q: @@ -503,28 +503,28 @@ def compute_bracket_indent(self): self._study2() assert self.continuation == C_BRACKET j = self.lastopenbracketpos - str = self.str - n = len(str) - origi = i = str.rfind('\n', 0, j) + 1 + code = self.code + n = len(code) + origi = i = code.rfind('\n', 0, j) + 1 j = j+1 # one beyond open bracket # find first list item; set i to start of its line while j < n: - m = _itemre(str, j) + m = _itemre(code, j) if m: j = m.end() - 1 # index of first interesting char extra = 0 break else: # this line is junk; advance to next line - i = j = str.find('\n', j) + 1 + i = j = code.find('\n', j) + 1 else: # nothing interesting follows the bracket; # reproduce the bracket line's indentation + a level j = i = origi - while str[j] in " \t": + while code[j] in " \t": j = j+1 extra = self.indentwidth - return len(str[i:j].expandtabs(self.tabwidth)) + extra + return len(code[i:j].expandtabs(self.tabwidth)) + extra def get_num_lines_in_stmt(self): """Return number of physical lines in last stmt. @@ -544,18 +544,18 @@ def compute_backslash_indent(self): """ self._study2() assert self.continuation == C_BACKSLASH - str = self.str + code = self.code i = self.stmt_start - while str[i] in " \t": + while code[i] in " \t": i = i+1 startpos = i # See whether the initial line starts an assignment stmt; i.e., # look for an = operator - endpos = str.find('\n', startpos) + 1 + endpos = code.find('\n', startpos) + 1 found = level = 0 while i < endpos: - ch = str[i] + ch = code[i] if ch in "([{": level = level + 1 i = i+1 @@ -564,14 +564,14 @@ def compute_backslash_indent(self): level = level - 1 i = i+1 elif ch == '"' or ch == "'": - i = _match_stringre(str, i, endpos).end() + i = _match_stringre(code, i, endpos).end() elif ch == '#': # This line is unreachable because the # makes a comment of # everything after it. break elif level == 0 and ch == '=' and \ - (i == 0 or str[i-1] not in "=<>!") and \ - str[i+1] != '=': + (i == 0 or code[i-1] not in "=<>!") and \ + code[i+1] != '=': found = 1 break else: @@ -581,16 +581,16 @@ def compute_backslash_indent(self): # found a legit =, but it may be the last interesting # thing on the line i = i+1 # move beyond the = - found = re.match(r"\s*\\", str[i:endpos]) is None + found = re.match(r"\s*\\", code[i:endpos]) is None if not found: # oh well ... settle for moving beyond the first chunk # of non-whitespace chars i = startpos - while str[i] not in " \t\n": + while code[i] not in " \t\n": i = i+1 - return len(str[self.stmt_start:i].expandtabs(\ + return len(code[self.stmt_start:i].expandtabs(\ self.tabwidth)) + 1 def get_base_indent_string(self): @@ -600,10 +600,10 @@ def get_base_indent_string(self): self._study2() i, n = self.stmt_start, self.stmt_end j = i - str = self.str - while j < n and str[j] in " \t": + code = self.code + while j < n and code[j] in " \t": j = j + 1 - return str[i:j] + return code[i:j] def is_block_opener(self): "Return True if the last interesting statemtent opens a block." @@ -613,7 +613,7 @@ def is_block_opener(self): def is_block_closer(self): "Return True if the last interesting statement closes a block." self._study2() - return _closere(self.str, self.stmt_start) is not None + return _closere(self.code, self.stmt_start) is not None def get_last_stmt_bracketing(self): """Return bracketing structure of the last interesting statement. diff --git a/Misc/NEWS.d/next/IDLE/2018-02-23-07-32-36.bpo-32916.4MsQ5F.rst b/Misc/NEWS.d/next/IDLE/2018-02-23-07-32-36.bpo-32916.4MsQ5F.rst new file mode 100644 index 000000000000..0832944f1621 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2018-02-23-07-32-36.bpo-32916.4MsQ5F.rst @@ -0,0 +1 @@ +Change ``str`` to ``code`` in pyparse. From webhook-mailer at python.org Fri Feb 23 21:59:56 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 24 Feb 2018 02:59:56 -0000 Subject: [Python-checkins] bpo-32916: IDLE: Change `str` to `code` in pyparse (GH-5830) Message-ID: https://github.com/python/cpython/commit/f409c9988e72eff7c0378ab5578f5edecb8b1855 commit: f409c9988e72eff7c0378ab5578f5edecb8b1855 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-23T18:59:53-08:00 summary: bpo-32916: IDLE: Change `str` to `code` in pyparse (GH-5830) Adjust tests and user modules to match. (cherry picked from commit c29c03a34a9f3c82704b66f323ce5ea9dc89c8af) Co-authored-by: Cheryl Sabella files: A Misc/NEWS.d/next/IDLE/2018-02-23-07-32-36.bpo-32916.4MsQ5F.rst M Lib/idlelib/editor.py M Lib/idlelib/hyperparser.py M Lib/idlelib/idle_test/test_pyparse.py M Lib/idlelib/pyparse.py diff --git a/Lib/idlelib/editor.py b/Lib/idlelib/editor.py index b51c45c97e50..ab9c7e615ef0 100644 --- a/Lib/idlelib/editor.py +++ b/Lib/idlelib/editor.py @@ -1302,7 +1302,7 @@ def newline_and_indent_event(self, event): startat = max(lno - context, 1) startatindex = repr(startat) + ".0" rawtext = text.get(startatindex, "insert") - y.set_str(rawtext) + y.set_code(rawtext) bod = y.find_good_parse_start( self.context_use_ps1, self._build_char_in_string_func(startatindex)) @@ -1316,7 +1316,7 @@ def newline_and_indent_event(self, event): else: startatindex = "1.0" rawtext = text.get(startatindex, "insert") - y.set_str(rawtext) + y.set_code(rawtext) y.set_lo(0) c = y.get_continuation_type() diff --git a/Lib/idlelib/hyperparser.py b/Lib/idlelib/hyperparser.py index 450a709c09bb..a42665bb6328 100644 --- a/Lib/idlelib/hyperparser.py +++ b/Lib/idlelib/hyperparser.py @@ -44,7 +44,7 @@ def index2line(index): # at end. We add a space so that index won't be at end # of line, so that its status will be the same as the # char before it, if should. - parser.set_str(text.get(startatindex, stopatindex)+' \n') + parser.set_code(text.get(startatindex, stopatindex)+' \n') bod = parser.find_good_parse_start( editwin._build_char_in_string_func(startatindex)) if bod is not None or startat == 1: @@ -60,12 +60,12 @@ def index2line(index): # We add the newline because PyParse requires it. We add a # space so that index won't be at end of line, so that its # status will be the same as the char before it, if should. - parser.set_str(text.get(startatindex, stopatindex)+' \n') + parser.set_code(text.get(startatindex, stopatindex)+' \n') parser.set_lo(0) # We want what the parser has, minus the last newline and space. - self.rawtext = parser.str[:-2] - # Parser.str apparently preserves the statement we are in, so + self.rawtext = parser.code[:-2] + # Parser.code apparently preserves the statement we are in, so # that stopatindex can be used to synchronize the string with # the text box indices. self.stopatindex = stopatindex diff --git a/Lib/idlelib/idle_test/test_pyparse.py b/Lib/idlelib/idle_test/test_pyparse.py index c45815b36ff2..c7b645caa6a8 100644 --- a/Lib/idlelib/idle_test/test_pyparse.py +++ b/Lib/idlelib/idle_test/test_pyparse.py @@ -62,32 +62,32 @@ def test_init(self): self.assertEqual(self.parser.indentwidth, 4) self.assertEqual(self.parser.tabwidth, 4) - def test_set_str(self): + def test_set_code(self): eq = self.assertEqual p = self.parser - setstr = p.set_str + setcode = p.set_code # Not empty and doesn't end with newline. with self.assertRaises(AssertionError): - setstr('a') + setcode('a') tests = ('', 'a\n') for string in tests: with self.subTest(string=string): - setstr(string) - eq(p.str, string) + setcode(string) + eq(p.code, string) eq(p.study_level, 0) def test_find_good_parse_start(self): eq = self.assertEqual p = self.parser - setstr = p.set_str + setcode = p.set_code start = p.find_good_parse_start # Split def across lines. - setstr('"""This is a module docstring"""\n' + setcode('"""This is a module docstring"""\n' 'class C():\n' ' def __init__(self, a,\n' ' b=True):\n' @@ -117,7 +117,7 @@ def test_find_good_parse_start(self): # Code without extra line break in def line - mostly returns the same # values. - setstr('"""This is a module docstring"""\n' + setcode('"""This is a module docstring"""\n' 'class C():\n' ' def __init__(self, a, b=True):\n' ' pass\n' @@ -138,19 +138,19 @@ def test_set_lo(self): ' pass\n' ) p = self.parser - p.set_str(code) + p.set_code(code) # Previous character is not a newline. with self.assertRaises(AssertionError): p.set_lo(5) - # A value of 0 doesn't change self.str. + # A value of 0 doesn't change self.code. p.set_lo(0) - self.assertEqual(p.str, code) + self.assertEqual(p.code, code) # An index that is preceded by a newline. p.set_lo(44) - self.assertEqual(p.str, code[44:]) + self.assertEqual(p.code, code[44:]) def test_tran(self): self.assertEqual('\t a([{b}])b"c\'d\n'.translate(self.parser._tran), @@ -159,7 +159,7 @@ def test_tran(self): def test_study1(self): eq = self.assertEqual p = self.parser - setstr = p.set_str + setcode = p.set_code study = p._study1 (NONE, BACKSLASH, FIRST, NEXT, BRACKET) = range(5) @@ -197,7 +197,7 @@ def test_study1(self): for test in tests: with self.subTest(string=test.string): - setstr(test.string) # resets study_level + setcode(test.string) # resets study_level study() eq(p.study_level, 1) eq(p.goodlines, test.goodlines) @@ -209,7 +209,7 @@ def test_study1(self): def test_get_continuation_type(self): eq = self.assertEqual p = self.parser - setstr = p.set_str + setcode = p.set_code gettype = p.get_continuation_type (NONE, BACKSLASH, FIRST, NEXT, BRACKET) = range(5) @@ -224,13 +224,13 @@ def test_get_continuation_type(self): for test in tests: with self.subTest(string=test.string): - setstr(test.string) + setcode(test.string) eq(gettype(), test.continuation) def test_study2(self): eq = self.assertEqual p = self.parser - setstr = p.set_str + setcode = p.set_code study = p._study2 TestInfo = namedtuple('TestInfo', ['string', 'start', 'end', 'lastch', @@ -276,7 +276,7 @@ def test_study2(self): for test in tests: with self.subTest(string=test.string): - setstr(test.string) + setcode(test.string) study() eq(p.study_level, 2) eq(p.stmt_start, test.start) @@ -291,7 +291,7 @@ def test_study2(self): def test_get_num_lines_in_stmt(self): eq = self.assertEqual p = self.parser - setstr = p.set_str + setcode = p.set_code getlines = p.get_num_lines_in_stmt TestInfo = namedtuple('TestInfo', ['string', 'lines']) @@ -307,19 +307,19 @@ def test_get_num_lines_in_stmt(self): ) # Blank string doesn't have enough elements in goodlines. - setstr('') + setcode('') with self.assertRaises(IndexError): getlines() for test in tests: with self.subTest(string=test.string): - setstr(test.string) + setcode(test.string) eq(getlines(), test.lines) def test_compute_bracket_indent(self): eq = self.assertEqual p = self.parser - setstr = p.set_str + setcode = p.set_code indent = p.compute_bracket_indent TestInfo = namedtuple('TestInfo', ['string', 'spaces']) @@ -340,18 +340,18 @@ def test_compute_bracket_indent(self): ) # Must be C_BRACKET continuation type. - setstr('def function1(self, a, b):\n') + setcode('def function1(self, a, b):\n') with self.assertRaises(AssertionError): indent() for test in tests: - setstr(test.string) + setcode(test.string) eq(indent(), test.spaces) def test_compute_backslash_indent(self): eq = self.assertEqual p = self.parser - setstr = p.set_str + setcode = p.set_code indent = p.compute_backslash_indent # Must be C_BACKSLASH continuation type. @@ -361,7 +361,7 @@ def test_compute_backslash_indent(self): ) for string in errors: with self.subTest(string=string): - setstr(string) + setcode(string) with self.assertRaises(AssertionError): indent() @@ -384,13 +384,13 @@ def test_compute_backslash_indent(self): ) for test in tests: with self.subTest(string=test.string): - setstr(test.string) + setcode(test.string) eq(indent(), test.spaces) def test_get_base_indent_string(self): eq = self.assertEqual p = self.parser - setstr = p.set_str + setcode = p.set_code baseindent = p.get_base_indent_string TestInfo = namedtuple('TestInfo', ['string', 'indent']) @@ -405,14 +405,14 @@ def test_get_base_indent_string(self): for test in tests: with self.subTest(string=test.string): - setstr(test.string) + setcode(test.string) eq(baseindent(), test.indent) def test_is_block_opener(self): yes = self.assertTrue no = self.assertFalse p = self.parser - setstr = p.set_str + setcode = p.set_code opener = p.is_block_opener TestInfo = namedtuple('TestInfo', ['string', 'assert_']) @@ -433,14 +433,14 @@ def test_is_block_opener(self): for test in tests: with self.subTest(string=test.string): - setstr(test.string) + setcode(test.string) test.assert_(opener()) def test_is_block_closer(self): yes = self.assertTrue no = self.assertFalse p = self.parser - setstr = p.set_str + setcode = p.set_code closer = p.is_block_closer TestInfo = namedtuple('TestInfo', ['string', 'assert_']) @@ -462,13 +462,13 @@ def test_is_block_closer(self): for test in tests: with self.subTest(string=test.string): - setstr(test.string) + setcode(test.string) test.assert_(closer()) def test_get_last_stmt_bracketing(self): eq = self.assertEqual p = self.parser - setstr = p.set_str + setcode = p.set_code bracketing = p.get_last_stmt_bracketing TestInfo = namedtuple('TestInfo', ['string', 'bracket']) @@ -489,7 +489,7 @@ def test_get_last_stmt_bracketing(self): for test in tests: with self.subTest(string=test.string): - setstr(test.string) + setcode(test.string) eq(bracketing(), test.bracket) diff --git a/Lib/idlelib/pyparse.py b/Lib/idlelib/pyparse.py index 93607dc5bcd0..443d198d1efe 100644 --- a/Lib/idlelib/pyparse.py +++ b/Lib/idlelib/pyparse.py @@ -149,9 +149,9 @@ def __init__(self, indentwidth, tabwidth): self.indentwidth = indentwidth self.tabwidth = tabwidth - def set_str(self, s): + def set_code(self, s): assert len(s) == 0 or s[-1] == '\n' - self.str = s + self.code = s self.study_level = 0 def find_good_parse_start(self, is_char_in_string=None, @@ -168,7 +168,7 @@ def find_good_parse_start(self, is_char_in_string=None, function, meaning that when it says "no", it's absolutely guaranteed that the char is not in a string. """ - str, pos = self.str, None + code, pos = self.code, None if not is_char_in_string: # no clue -- make the caller pass everything @@ -177,13 +177,13 @@ def find_good_parse_start(self, is_char_in_string=None, # Peek back from the end for a good place to start, # but don't try too often; pos will be left None, or # bumped to a legitimate synch point. - limit = len(str) + limit = len(code) for tries in range(5): - i = str.rfind(":\n", 0, limit) + i = code.rfind(":\n", 0, limit) if i < 0: break - i = str.rfind('\n', 0, i) + 1 # start of colon line (-1+1=0) - m = _synchre(str, i, limit) + i = code.rfind('\n', 0, i) + 1 # start of colon line (-1+1=0) + m = _synchre(code, i, limit) if m and not is_char_in_string(m.start()): pos = m.start() break @@ -197,7 +197,7 @@ def find_good_parse_start(self, is_char_in_string=None, # going to have to parse the whole thing to be sure, so # give it one last try from the start, but stop wasting # time here regardless of the outcome. - m = _synchre(str) + m = _synchre(code) if m and not is_char_in_string(m.start()): pos = m.start() return pos @@ -206,7 +206,7 @@ def find_good_parse_start(self, is_char_in_string=None, # matches. i = pos + 1 while 1: - m = _synchre(str, i) + m = _synchre(code, i) if m: s, i = m.span() if not is_char_in_string(s): @@ -220,9 +220,9 @@ def set_lo(self, lo): Intended to be called with the result of find_good_parse_start(). """ - assert lo == 0 or self.str[lo-1] == '\n' + assert lo == 0 or self.code[lo-1] == '\n' if lo > 0: - self.str = self.str[lo:] + self.code = self.code[lo:] # Build a translation table to map uninteresting chars to 'x', open # brackets to '(', close brackets to ')' while preserving quotes, @@ -249,13 +249,13 @@ def _study1(self): # to "(", all close brackets to ")", then collapse runs of # uninteresting characters. This can cut the number of chars # by a factor of 10-40, and so greatly speed the following loop. - str = self.str - str = str.translate(self._tran) - str = str.replace('xxxxxxxx', 'x') - str = str.replace('xxxx', 'x') - str = str.replace('xx', 'x') - str = str.replace('xx', 'x') - str = str.replace('\nx', '\n') + code = self.code + code = code.translate(self._tran) + code = code.replace('xxxxxxxx', 'x') + code = code.replace('xxxx', 'x') + code = code.replace('xx', 'x') + code = code.replace('xx', 'x') + code = code.replace('\nx', '\n') # Replacing x\n with \n would be incorrect because # x may be preceded by a backslash. @@ -266,9 +266,9 @@ def _study1(self): level = lno = 0 # level is nesting level; lno is line number self.goodlines = goodlines = [0] push_good = goodlines.append - i, n = 0, len(str) + i, n = 0, len(code) while i < n: - ch = str[i] + ch = code[i] i = i+1 # cases are checked in decreasing order of frequency @@ -295,19 +295,19 @@ def _study1(self): if ch == '"' or ch == "'": # consume the string quote = ch - if str[i-1:i+2] == quote * 3: + if code[i-1:i+2] == quote * 3: quote = quote * 3 firstlno = lno w = len(quote) - 1 i = i+w while i < n: - ch = str[i] + ch = code[i] i = i+1 if ch == 'x': continue - if str[i-1:i+w] == quote: + if code[i-1:i+w] == quote: i = i+w break @@ -322,7 +322,7 @@ def _study1(self): if ch == '\\': assert i < n - if str[i] == '\n': + if code[i] == '\n': lno = lno + 1 i = i+1 continue @@ -333,7 +333,7 @@ def _study1(self): # didn't break out of the loop, so we're still # inside a string if (lno - 1) == firstlno: - # before the previous \n in str, we were in the first + # before the previous \n in code, we were in the first # line of the string continuation = C_STRING_FIRST_LINE else: @@ -342,13 +342,13 @@ def _study1(self): if ch == '#': # consume the comment - i = str.find('\n', i) + i = code.find('\n', i) assert i >= 0 continue assert ch == '\\' assert i < n - if str[i] == '\n': + if code[i] == '\n': lno = lno + 1 if i+1 == n: continuation = C_BACKSLASH @@ -397,9 +397,9 @@ def _study2(self): self.study_level = 2 # Set p and q to slice indices of last interesting stmt. - str, goodlines = self.str, self.goodlines + code, goodlines = self.code, self.goodlines i = len(goodlines) - 1 # Index of newest line. - p = len(str) # End of goodlines[i] + p = len(code) # End of goodlines[i] while i: assert p # Make p be the index of the stmt at line number goodlines[i]. @@ -407,10 +407,10 @@ def _study2(self): q = p for nothing in range(goodlines[i-1], goodlines[i]): # tricky: sets p to 0 if no preceding newline - p = str.rfind('\n', 0, p-1) + 1 - # The stmt str[p:q] isn't a continuation, but may be blank + p = code.rfind('\n', 0, p-1) + 1 + # The stmt code[p:q] isn't a continuation, but may be blank # or a non-indenting comment line. - if _junkre(str, p): + if _junkre(code, p): i = i-1 else: break @@ -428,21 +428,21 @@ def _study2(self): bracketing = [(p, 0)] while p < q: # suck up all except ()[]{}'"#\\ - m = _chew_ordinaryre(str, p, q) + m = _chew_ordinaryre(code, p, q) if m: # we skipped at least one boring char newp = m.end() # back up over totally boring whitespace i = newp - 1 # index of last boring char - while i >= p and str[i] in " \t\n": + while i >= p and code[i] in " \t\n": i = i-1 if i >= p: - lastch = str[i] + lastch = code[i] p = newp if p >= q: break - ch = str[p] + ch = code[p] if ch in "([{": push_stack(p) @@ -469,14 +469,14 @@ def _study2(self): # have to. bracketing.append((p, len(stack)+1)) lastch = ch - p = _match_stringre(str, p, q).end() + p = _match_stringre(code, p, q).end() bracketing.append((p, len(stack))) continue if ch == '#': # consume comment and trailing newline bracketing.append((p, len(stack)+1)) - p = str.find('\n', p, q) + 1 + p = code.find('\n', p, q) + 1 assert p > 0 bracketing.append((p, len(stack))) continue @@ -484,9 +484,9 @@ def _study2(self): assert ch == '\\' p = p+1 # beyond backslash assert p < q - if str[p] != '\n': + if code[p] != '\n': # the program is invalid, but can't complain - lastch = ch + str[p] + lastch = ch + code[p] p = p+1 # beyond escaped char # end while p < q: @@ -503,28 +503,28 @@ def compute_bracket_indent(self): self._study2() assert self.continuation == C_BRACKET j = self.lastopenbracketpos - str = self.str - n = len(str) - origi = i = str.rfind('\n', 0, j) + 1 + code = self.code + n = len(code) + origi = i = code.rfind('\n', 0, j) + 1 j = j+1 # one beyond open bracket # find first list item; set i to start of its line while j < n: - m = _itemre(str, j) + m = _itemre(code, j) if m: j = m.end() - 1 # index of first interesting char extra = 0 break else: # this line is junk; advance to next line - i = j = str.find('\n', j) + 1 + i = j = code.find('\n', j) + 1 else: # nothing interesting follows the bracket; # reproduce the bracket line's indentation + a level j = i = origi - while str[j] in " \t": + while code[j] in " \t": j = j+1 extra = self.indentwidth - return len(str[i:j].expandtabs(self.tabwidth)) + extra + return len(code[i:j].expandtabs(self.tabwidth)) + extra def get_num_lines_in_stmt(self): """Return number of physical lines in last stmt. @@ -544,18 +544,18 @@ def compute_backslash_indent(self): """ self._study2() assert self.continuation == C_BACKSLASH - str = self.str + code = self.code i = self.stmt_start - while str[i] in " \t": + while code[i] in " \t": i = i+1 startpos = i # See whether the initial line starts an assignment stmt; i.e., # look for an = operator - endpos = str.find('\n', startpos) + 1 + endpos = code.find('\n', startpos) + 1 found = level = 0 while i < endpos: - ch = str[i] + ch = code[i] if ch in "([{": level = level + 1 i = i+1 @@ -564,14 +564,14 @@ def compute_backslash_indent(self): level = level - 1 i = i+1 elif ch == '"' or ch == "'": - i = _match_stringre(str, i, endpos).end() + i = _match_stringre(code, i, endpos).end() elif ch == '#': # This line is unreachable because the # makes a comment of # everything after it. break elif level == 0 and ch == '=' and \ - (i == 0 or str[i-1] not in "=<>!") and \ - str[i+1] != '=': + (i == 0 or code[i-1] not in "=<>!") and \ + code[i+1] != '=': found = 1 break else: @@ -581,16 +581,16 @@ def compute_backslash_indent(self): # found a legit =, but it may be the last interesting # thing on the line i = i+1 # move beyond the = - found = re.match(r"\s*\\", str[i:endpos]) is None + found = re.match(r"\s*\\", code[i:endpos]) is None if not found: # oh well ... settle for moving beyond the first chunk # of non-whitespace chars i = startpos - while str[i] not in " \t\n": + while code[i] not in " \t\n": i = i+1 - return len(str[self.stmt_start:i].expandtabs(\ + return len(code[self.stmt_start:i].expandtabs(\ self.tabwidth)) + 1 def get_base_indent_string(self): @@ -600,10 +600,10 @@ def get_base_indent_string(self): self._study2() i, n = self.stmt_start, self.stmt_end j = i - str = self.str - while j < n and str[j] in " \t": + code = self.code + while j < n and code[j] in " \t": j = j + 1 - return str[i:j] + return code[i:j] def is_block_opener(self): "Return True if the last interesting statemtent opens a block." @@ -613,7 +613,7 @@ def is_block_opener(self): def is_block_closer(self): "Return True if the last interesting statement closes a block." self._study2() - return _closere(self.str, self.stmt_start) is not None + return _closere(self.code, self.stmt_start) is not None def get_last_stmt_bracketing(self): """Return bracketing structure of the last interesting statement. diff --git a/Misc/NEWS.d/next/IDLE/2018-02-23-07-32-36.bpo-32916.4MsQ5F.rst b/Misc/NEWS.d/next/IDLE/2018-02-23-07-32-36.bpo-32916.4MsQ5F.rst new file mode 100644 index 000000000000..0832944f1621 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2018-02-23-07-32-36.bpo-32916.4MsQ5F.rst @@ -0,0 +1 @@ +Change ``str`` to ``code`` in pyparse. From webhook-mailer at python.org Fri Feb 23 22:16:03 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 24 Feb 2018 03:16:03 -0000 Subject: [Python-checkins] bpo-32916: IDLE: Change `str` to `code` in pyparse (GH-5830) Message-ID: https://github.com/python/cpython/commit/cd2112f0b9ce3d1a8cff61c16a9208115fb1dbf4 commit: cd2112f0b9ce3d1a8cff61c16a9208115fb1dbf4 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-23T19:16:00-08:00 summary: bpo-32916: IDLE: Change `str` to `code` in pyparse (GH-5830) Adjust tests and user modules to match. (cherry picked from commit c29c03a34a9f3c82704b66f323ce5ea9dc89c8af) Co-authored-by: Cheryl Sabella files: A Misc/NEWS.d/next/IDLE/2018-02-23-07-32-36.bpo-32916.4MsQ5F.rst M Lib/idlelib/editor.py M Lib/idlelib/hyperparser.py M Lib/idlelib/idle_test/test_pyparse.py M Lib/idlelib/pyparse.py diff --git a/Lib/idlelib/editor.py b/Lib/idlelib/editor.py index b51c45c97e50..ab9c7e615ef0 100644 --- a/Lib/idlelib/editor.py +++ b/Lib/idlelib/editor.py @@ -1302,7 +1302,7 @@ def newline_and_indent_event(self, event): startat = max(lno - context, 1) startatindex = repr(startat) + ".0" rawtext = text.get(startatindex, "insert") - y.set_str(rawtext) + y.set_code(rawtext) bod = y.find_good_parse_start( self.context_use_ps1, self._build_char_in_string_func(startatindex)) @@ -1316,7 +1316,7 @@ def newline_and_indent_event(self, event): else: startatindex = "1.0" rawtext = text.get(startatindex, "insert") - y.set_str(rawtext) + y.set_code(rawtext) y.set_lo(0) c = y.get_continuation_type() diff --git a/Lib/idlelib/hyperparser.py b/Lib/idlelib/hyperparser.py index 450a709c09bb..a42665bb6328 100644 --- a/Lib/idlelib/hyperparser.py +++ b/Lib/idlelib/hyperparser.py @@ -44,7 +44,7 @@ def index2line(index): # at end. We add a space so that index won't be at end # of line, so that its status will be the same as the # char before it, if should. - parser.set_str(text.get(startatindex, stopatindex)+' \n') + parser.set_code(text.get(startatindex, stopatindex)+' \n') bod = parser.find_good_parse_start( editwin._build_char_in_string_func(startatindex)) if bod is not None or startat == 1: @@ -60,12 +60,12 @@ def index2line(index): # We add the newline because PyParse requires it. We add a # space so that index won't be at end of line, so that its # status will be the same as the char before it, if should. - parser.set_str(text.get(startatindex, stopatindex)+' \n') + parser.set_code(text.get(startatindex, stopatindex)+' \n') parser.set_lo(0) # We want what the parser has, minus the last newline and space. - self.rawtext = parser.str[:-2] - # Parser.str apparently preserves the statement we are in, so + self.rawtext = parser.code[:-2] + # Parser.code apparently preserves the statement we are in, so # that stopatindex can be used to synchronize the string with # the text box indices. self.stopatindex = stopatindex diff --git a/Lib/idlelib/idle_test/test_pyparse.py b/Lib/idlelib/idle_test/test_pyparse.py index c45815b36ff2..c7b645caa6a8 100644 --- a/Lib/idlelib/idle_test/test_pyparse.py +++ b/Lib/idlelib/idle_test/test_pyparse.py @@ -62,32 +62,32 @@ def test_init(self): self.assertEqual(self.parser.indentwidth, 4) self.assertEqual(self.parser.tabwidth, 4) - def test_set_str(self): + def test_set_code(self): eq = self.assertEqual p = self.parser - setstr = p.set_str + setcode = p.set_code # Not empty and doesn't end with newline. with self.assertRaises(AssertionError): - setstr('a') + setcode('a') tests = ('', 'a\n') for string in tests: with self.subTest(string=string): - setstr(string) - eq(p.str, string) + setcode(string) + eq(p.code, string) eq(p.study_level, 0) def test_find_good_parse_start(self): eq = self.assertEqual p = self.parser - setstr = p.set_str + setcode = p.set_code start = p.find_good_parse_start # Split def across lines. - setstr('"""This is a module docstring"""\n' + setcode('"""This is a module docstring"""\n' 'class C():\n' ' def __init__(self, a,\n' ' b=True):\n' @@ -117,7 +117,7 @@ def test_find_good_parse_start(self): # Code without extra line break in def line - mostly returns the same # values. - setstr('"""This is a module docstring"""\n' + setcode('"""This is a module docstring"""\n' 'class C():\n' ' def __init__(self, a, b=True):\n' ' pass\n' @@ -138,19 +138,19 @@ def test_set_lo(self): ' pass\n' ) p = self.parser - p.set_str(code) + p.set_code(code) # Previous character is not a newline. with self.assertRaises(AssertionError): p.set_lo(5) - # A value of 0 doesn't change self.str. + # A value of 0 doesn't change self.code. p.set_lo(0) - self.assertEqual(p.str, code) + self.assertEqual(p.code, code) # An index that is preceded by a newline. p.set_lo(44) - self.assertEqual(p.str, code[44:]) + self.assertEqual(p.code, code[44:]) def test_tran(self): self.assertEqual('\t a([{b}])b"c\'d\n'.translate(self.parser._tran), @@ -159,7 +159,7 @@ def test_tran(self): def test_study1(self): eq = self.assertEqual p = self.parser - setstr = p.set_str + setcode = p.set_code study = p._study1 (NONE, BACKSLASH, FIRST, NEXT, BRACKET) = range(5) @@ -197,7 +197,7 @@ def test_study1(self): for test in tests: with self.subTest(string=test.string): - setstr(test.string) # resets study_level + setcode(test.string) # resets study_level study() eq(p.study_level, 1) eq(p.goodlines, test.goodlines) @@ -209,7 +209,7 @@ def test_study1(self): def test_get_continuation_type(self): eq = self.assertEqual p = self.parser - setstr = p.set_str + setcode = p.set_code gettype = p.get_continuation_type (NONE, BACKSLASH, FIRST, NEXT, BRACKET) = range(5) @@ -224,13 +224,13 @@ def test_get_continuation_type(self): for test in tests: with self.subTest(string=test.string): - setstr(test.string) + setcode(test.string) eq(gettype(), test.continuation) def test_study2(self): eq = self.assertEqual p = self.parser - setstr = p.set_str + setcode = p.set_code study = p._study2 TestInfo = namedtuple('TestInfo', ['string', 'start', 'end', 'lastch', @@ -276,7 +276,7 @@ def test_study2(self): for test in tests: with self.subTest(string=test.string): - setstr(test.string) + setcode(test.string) study() eq(p.study_level, 2) eq(p.stmt_start, test.start) @@ -291,7 +291,7 @@ def test_study2(self): def test_get_num_lines_in_stmt(self): eq = self.assertEqual p = self.parser - setstr = p.set_str + setcode = p.set_code getlines = p.get_num_lines_in_stmt TestInfo = namedtuple('TestInfo', ['string', 'lines']) @@ -307,19 +307,19 @@ def test_get_num_lines_in_stmt(self): ) # Blank string doesn't have enough elements in goodlines. - setstr('') + setcode('') with self.assertRaises(IndexError): getlines() for test in tests: with self.subTest(string=test.string): - setstr(test.string) + setcode(test.string) eq(getlines(), test.lines) def test_compute_bracket_indent(self): eq = self.assertEqual p = self.parser - setstr = p.set_str + setcode = p.set_code indent = p.compute_bracket_indent TestInfo = namedtuple('TestInfo', ['string', 'spaces']) @@ -340,18 +340,18 @@ def test_compute_bracket_indent(self): ) # Must be C_BRACKET continuation type. - setstr('def function1(self, a, b):\n') + setcode('def function1(self, a, b):\n') with self.assertRaises(AssertionError): indent() for test in tests: - setstr(test.string) + setcode(test.string) eq(indent(), test.spaces) def test_compute_backslash_indent(self): eq = self.assertEqual p = self.parser - setstr = p.set_str + setcode = p.set_code indent = p.compute_backslash_indent # Must be C_BACKSLASH continuation type. @@ -361,7 +361,7 @@ def test_compute_backslash_indent(self): ) for string in errors: with self.subTest(string=string): - setstr(string) + setcode(string) with self.assertRaises(AssertionError): indent() @@ -384,13 +384,13 @@ def test_compute_backslash_indent(self): ) for test in tests: with self.subTest(string=test.string): - setstr(test.string) + setcode(test.string) eq(indent(), test.spaces) def test_get_base_indent_string(self): eq = self.assertEqual p = self.parser - setstr = p.set_str + setcode = p.set_code baseindent = p.get_base_indent_string TestInfo = namedtuple('TestInfo', ['string', 'indent']) @@ -405,14 +405,14 @@ def test_get_base_indent_string(self): for test in tests: with self.subTest(string=test.string): - setstr(test.string) + setcode(test.string) eq(baseindent(), test.indent) def test_is_block_opener(self): yes = self.assertTrue no = self.assertFalse p = self.parser - setstr = p.set_str + setcode = p.set_code opener = p.is_block_opener TestInfo = namedtuple('TestInfo', ['string', 'assert_']) @@ -433,14 +433,14 @@ def test_is_block_opener(self): for test in tests: with self.subTest(string=test.string): - setstr(test.string) + setcode(test.string) test.assert_(opener()) def test_is_block_closer(self): yes = self.assertTrue no = self.assertFalse p = self.parser - setstr = p.set_str + setcode = p.set_code closer = p.is_block_closer TestInfo = namedtuple('TestInfo', ['string', 'assert_']) @@ -462,13 +462,13 @@ def test_is_block_closer(self): for test in tests: with self.subTest(string=test.string): - setstr(test.string) + setcode(test.string) test.assert_(closer()) def test_get_last_stmt_bracketing(self): eq = self.assertEqual p = self.parser - setstr = p.set_str + setcode = p.set_code bracketing = p.get_last_stmt_bracketing TestInfo = namedtuple('TestInfo', ['string', 'bracket']) @@ -489,7 +489,7 @@ def test_get_last_stmt_bracketing(self): for test in tests: with self.subTest(string=test.string): - setstr(test.string) + setcode(test.string) eq(bracketing(), test.bracket) diff --git a/Lib/idlelib/pyparse.py b/Lib/idlelib/pyparse.py index 93607dc5bcd0..443d198d1efe 100644 --- a/Lib/idlelib/pyparse.py +++ b/Lib/idlelib/pyparse.py @@ -149,9 +149,9 @@ def __init__(self, indentwidth, tabwidth): self.indentwidth = indentwidth self.tabwidth = tabwidth - def set_str(self, s): + def set_code(self, s): assert len(s) == 0 or s[-1] == '\n' - self.str = s + self.code = s self.study_level = 0 def find_good_parse_start(self, is_char_in_string=None, @@ -168,7 +168,7 @@ def find_good_parse_start(self, is_char_in_string=None, function, meaning that when it says "no", it's absolutely guaranteed that the char is not in a string. """ - str, pos = self.str, None + code, pos = self.code, None if not is_char_in_string: # no clue -- make the caller pass everything @@ -177,13 +177,13 @@ def find_good_parse_start(self, is_char_in_string=None, # Peek back from the end for a good place to start, # but don't try too often; pos will be left None, or # bumped to a legitimate synch point. - limit = len(str) + limit = len(code) for tries in range(5): - i = str.rfind(":\n", 0, limit) + i = code.rfind(":\n", 0, limit) if i < 0: break - i = str.rfind('\n', 0, i) + 1 # start of colon line (-1+1=0) - m = _synchre(str, i, limit) + i = code.rfind('\n', 0, i) + 1 # start of colon line (-1+1=0) + m = _synchre(code, i, limit) if m and not is_char_in_string(m.start()): pos = m.start() break @@ -197,7 +197,7 @@ def find_good_parse_start(self, is_char_in_string=None, # going to have to parse the whole thing to be sure, so # give it one last try from the start, but stop wasting # time here regardless of the outcome. - m = _synchre(str) + m = _synchre(code) if m and not is_char_in_string(m.start()): pos = m.start() return pos @@ -206,7 +206,7 @@ def find_good_parse_start(self, is_char_in_string=None, # matches. i = pos + 1 while 1: - m = _synchre(str, i) + m = _synchre(code, i) if m: s, i = m.span() if not is_char_in_string(s): @@ -220,9 +220,9 @@ def set_lo(self, lo): Intended to be called with the result of find_good_parse_start(). """ - assert lo == 0 or self.str[lo-1] == '\n' + assert lo == 0 or self.code[lo-1] == '\n' if lo > 0: - self.str = self.str[lo:] + self.code = self.code[lo:] # Build a translation table to map uninteresting chars to 'x', open # brackets to '(', close brackets to ')' while preserving quotes, @@ -249,13 +249,13 @@ def _study1(self): # to "(", all close brackets to ")", then collapse runs of # uninteresting characters. This can cut the number of chars # by a factor of 10-40, and so greatly speed the following loop. - str = self.str - str = str.translate(self._tran) - str = str.replace('xxxxxxxx', 'x') - str = str.replace('xxxx', 'x') - str = str.replace('xx', 'x') - str = str.replace('xx', 'x') - str = str.replace('\nx', '\n') + code = self.code + code = code.translate(self._tran) + code = code.replace('xxxxxxxx', 'x') + code = code.replace('xxxx', 'x') + code = code.replace('xx', 'x') + code = code.replace('xx', 'x') + code = code.replace('\nx', '\n') # Replacing x\n with \n would be incorrect because # x may be preceded by a backslash. @@ -266,9 +266,9 @@ def _study1(self): level = lno = 0 # level is nesting level; lno is line number self.goodlines = goodlines = [0] push_good = goodlines.append - i, n = 0, len(str) + i, n = 0, len(code) while i < n: - ch = str[i] + ch = code[i] i = i+1 # cases are checked in decreasing order of frequency @@ -295,19 +295,19 @@ def _study1(self): if ch == '"' or ch == "'": # consume the string quote = ch - if str[i-1:i+2] == quote * 3: + if code[i-1:i+2] == quote * 3: quote = quote * 3 firstlno = lno w = len(quote) - 1 i = i+w while i < n: - ch = str[i] + ch = code[i] i = i+1 if ch == 'x': continue - if str[i-1:i+w] == quote: + if code[i-1:i+w] == quote: i = i+w break @@ -322,7 +322,7 @@ def _study1(self): if ch == '\\': assert i < n - if str[i] == '\n': + if code[i] == '\n': lno = lno + 1 i = i+1 continue @@ -333,7 +333,7 @@ def _study1(self): # didn't break out of the loop, so we're still # inside a string if (lno - 1) == firstlno: - # before the previous \n in str, we were in the first + # before the previous \n in code, we were in the first # line of the string continuation = C_STRING_FIRST_LINE else: @@ -342,13 +342,13 @@ def _study1(self): if ch == '#': # consume the comment - i = str.find('\n', i) + i = code.find('\n', i) assert i >= 0 continue assert ch == '\\' assert i < n - if str[i] == '\n': + if code[i] == '\n': lno = lno + 1 if i+1 == n: continuation = C_BACKSLASH @@ -397,9 +397,9 @@ def _study2(self): self.study_level = 2 # Set p and q to slice indices of last interesting stmt. - str, goodlines = self.str, self.goodlines + code, goodlines = self.code, self.goodlines i = len(goodlines) - 1 # Index of newest line. - p = len(str) # End of goodlines[i] + p = len(code) # End of goodlines[i] while i: assert p # Make p be the index of the stmt at line number goodlines[i]. @@ -407,10 +407,10 @@ def _study2(self): q = p for nothing in range(goodlines[i-1], goodlines[i]): # tricky: sets p to 0 if no preceding newline - p = str.rfind('\n', 0, p-1) + 1 - # The stmt str[p:q] isn't a continuation, but may be blank + p = code.rfind('\n', 0, p-1) + 1 + # The stmt code[p:q] isn't a continuation, but may be blank # or a non-indenting comment line. - if _junkre(str, p): + if _junkre(code, p): i = i-1 else: break @@ -428,21 +428,21 @@ def _study2(self): bracketing = [(p, 0)] while p < q: # suck up all except ()[]{}'"#\\ - m = _chew_ordinaryre(str, p, q) + m = _chew_ordinaryre(code, p, q) if m: # we skipped at least one boring char newp = m.end() # back up over totally boring whitespace i = newp - 1 # index of last boring char - while i >= p and str[i] in " \t\n": + while i >= p and code[i] in " \t\n": i = i-1 if i >= p: - lastch = str[i] + lastch = code[i] p = newp if p >= q: break - ch = str[p] + ch = code[p] if ch in "([{": push_stack(p) @@ -469,14 +469,14 @@ def _study2(self): # have to. bracketing.append((p, len(stack)+1)) lastch = ch - p = _match_stringre(str, p, q).end() + p = _match_stringre(code, p, q).end() bracketing.append((p, len(stack))) continue if ch == '#': # consume comment and trailing newline bracketing.append((p, len(stack)+1)) - p = str.find('\n', p, q) + 1 + p = code.find('\n', p, q) + 1 assert p > 0 bracketing.append((p, len(stack))) continue @@ -484,9 +484,9 @@ def _study2(self): assert ch == '\\' p = p+1 # beyond backslash assert p < q - if str[p] != '\n': + if code[p] != '\n': # the program is invalid, but can't complain - lastch = ch + str[p] + lastch = ch + code[p] p = p+1 # beyond escaped char # end while p < q: @@ -503,28 +503,28 @@ def compute_bracket_indent(self): self._study2() assert self.continuation == C_BRACKET j = self.lastopenbracketpos - str = self.str - n = len(str) - origi = i = str.rfind('\n', 0, j) + 1 + code = self.code + n = len(code) + origi = i = code.rfind('\n', 0, j) + 1 j = j+1 # one beyond open bracket # find first list item; set i to start of its line while j < n: - m = _itemre(str, j) + m = _itemre(code, j) if m: j = m.end() - 1 # index of first interesting char extra = 0 break else: # this line is junk; advance to next line - i = j = str.find('\n', j) + 1 + i = j = code.find('\n', j) + 1 else: # nothing interesting follows the bracket; # reproduce the bracket line's indentation + a level j = i = origi - while str[j] in " \t": + while code[j] in " \t": j = j+1 extra = self.indentwidth - return len(str[i:j].expandtabs(self.tabwidth)) + extra + return len(code[i:j].expandtabs(self.tabwidth)) + extra def get_num_lines_in_stmt(self): """Return number of physical lines in last stmt. @@ -544,18 +544,18 @@ def compute_backslash_indent(self): """ self._study2() assert self.continuation == C_BACKSLASH - str = self.str + code = self.code i = self.stmt_start - while str[i] in " \t": + while code[i] in " \t": i = i+1 startpos = i # See whether the initial line starts an assignment stmt; i.e., # look for an = operator - endpos = str.find('\n', startpos) + 1 + endpos = code.find('\n', startpos) + 1 found = level = 0 while i < endpos: - ch = str[i] + ch = code[i] if ch in "([{": level = level + 1 i = i+1 @@ -564,14 +564,14 @@ def compute_backslash_indent(self): level = level - 1 i = i+1 elif ch == '"' or ch == "'": - i = _match_stringre(str, i, endpos).end() + i = _match_stringre(code, i, endpos).end() elif ch == '#': # This line is unreachable because the # makes a comment of # everything after it. break elif level == 0 and ch == '=' and \ - (i == 0 or str[i-1] not in "=<>!") and \ - str[i+1] != '=': + (i == 0 or code[i-1] not in "=<>!") and \ + code[i+1] != '=': found = 1 break else: @@ -581,16 +581,16 @@ def compute_backslash_indent(self): # found a legit =, but it may be the last interesting # thing on the line i = i+1 # move beyond the = - found = re.match(r"\s*\\", str[i:endpos]) is None + found = re.match(r"\s*\\", code[i:endpos]) is None if not found: # oh well ... settle for moving beyond the first chunk # of non-whitespace chars i = startpos - while str[i] not in " \t\n": + while code[i] not in " \t\n": i = i+1 - return len(str[self.stmt_start:i].expandtabs(\ + return len(code[self.stmt_start:i].expandtabs(\ self.tabwidth)) + 1 def get_base_indent_string(self): @@ -600,10 +600,10 @@ def get_base_indent_string(self): self._study2() i, n = self.stmt_start, self.stmt_end j = i - str = self.str - while j < n and str[j] in " \t": + code = self.code + while j < n and code[j] in " \t": j = j + 1 - return str[i:j] + return code[i:j] def is_block_opener(self): "Return True if the last interesting statemtent opens a block." @@ -613,7 +613,7 @@ def is_block_opener(self): def is_block_closer(self): "Return True if the last interesting statement closes a block." self._study2() - return _closere(self.str, self.stmt_start) is not None + return _closere(self.code, self.stmt_start) is not None def get_last_stmt_bracketing(self): """Return bracketing structure of the last interesting statement. diff --git a/Misc/NEWS.d/next/IDLE/2018-02-23-07-32-36.bpo-32916.4MsQ5F.rst b/Misc/NEWS.d/next/IDLE/2018-02-23-07-32-36.bpo-32916.4MsQ5F.rst new file mode 100644 index 000000000000..0832944f1621 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2018-02-23-07-32-36.bpo-32916.4MsQ5F.rst @@ -0,0 +1 @@ +Change ``str`` to ``code`` in pyparse. From webhook-mailer at python.org Fri Feb 23 22:18:31 2018 From: webhook-mailer at python.org (Nathaniel J. Smith) Date: Sat, 24 Feb 2018 03:18:31 -0000 Subject: [Python-checkins] [bpo-28414] Make all hostnames in SSL module IDN A-labels (GH-5128) (GH-5843) Message-ID: https://github.com/python/cpython/commit/1c37e277190565f0e30fc9281caae4c899ac3b50 commit: 1c37e277190565f0e30fc9281caae4c899ac3b50 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Nathaniel J. Smith date: 2018-02-23T19:18:28-08:00 summary: [bpo-28414] Make all hostnames in SSL module IDN A-labels (GH-5128) (GH-5843) Previously, the ssl module stored international domain names (IDNs) as U-labels. This is problematic for a number of reasons -- for example, it made it impossible for users to use a different version of IDNA than the one built into Python. After this change, we always convert to A-labels as soon as possible, and use them for all internal processing. In particular, server_hostname attribute is now an A-label, and on the server side there's a new sni_callback that receives the SNI servername as an A-label rather than a U-label. (cherry picked from commit 11a1493bc4198f1def5e572049485779cf54dc57) Co-authored-by: Christian Heimes files: A Misc/NEWS.d/next/Security/2017-08-06-14-43-45.bpo-28414.mzZ6vD.rst M Doc/library/ssl.rst M Doc/whatsnew/3.7.rst M Lib/ssl.py M Lib/test/test_ssl.py M Modules/_ssl.c M Modules/clinic/_ssl.c.h diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 21da4f638713..4cad9f667c48 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -1268,6 +1268,12 @@ SSL sockets also have the following additional methods and attributes: .. versionadded:: 3.2 + .. versionchanged:: 3.7 + The attribute is now always ASCII text. When ``server_hostname`` is + an internationalized domain name (IDN), this attribute now stores the + A-label form (``"xn--pythn-mua.org"``), rather than the U-label form + (``"pyth?n.org"``). + .. attribute:: SSLSocket.session The :class:`SSLSession` for this SSL connection. The session is available @@ -1532,23 +1538,24 @@ to speed up repeated connections from the same clients. .. versionadded:: 3.3 -.. method:: SSLContext.set_servername_callback(server_name_callback) +.. attribute:: SSLContext.sni_callback Register a callback function that will be called after the TLS Client Hello handshake message has been received by the SSL/TLS server when the TLS client specifies a server name indication. The server name indication mechanism is specified in :rfc:`6066` section 3 - Server Name Indication. - Only one callback can be set per ``SSLContext``. If *server_name_callback* - is ``None`` then the callback is disabled. Calling this function a + Only one callback can be set per ``SSLContext``. If *sni_callback* + is set to ``None`` then the callback is disabled. Calling this function a subsequent time will disable the previously registered callback. - The callback function, *server_name_callback*, will be called with three + The callback function will be called with three arguments; the first being the :class:`ssl.SSLSocket`, the second is a string that represents the server name that the client is intending to communicate (or :const:`None` if the TLS Client Hello does not contain a server name) and the third argument is the original :class:`SSLContext`. The server name - argument is the IDNA decoded server name. + argument is text. For internationalized domain name, the server + name is an IDN A-label (``"xn--pythn-mua.org"``). A typical use of this callback is to change the :class:`ssl.SSLSocket`'s :attr:`SSLSocket.context` attribute to a new object of type @@ -1563,23 +1570,33 @@ to speed up repeated connections from the same clients. the TLS connection has progressed beyond the TLS Client Hello and therefore will not contain return meaningful values nor can they be called safely. - The *server_name_callback* function must return ``None`` to allow the + The *sni_callback* function must return ``None`` to allow the TLS negotiation to continue. If a TLS failure is required, a constant :const:`ALERT_DESCRIPTION_* ` can be returned. Other return values will result in a TLS fatal error with :const:`ALERT_DESCRIPTION_INTERNAL_ERROR`. - If there is an IDNA decoding error on the server name, the TLS connection - will terminate with an :const:`ALERT_DESCRIPTION_INTERNAL_ERROR` fatal TLS - alert message to the client. - - If an exception is raised from the *server_name_callback* function the TLS + If an exception is raised from the *sni_callback* function the TLS connection will terminate with a fatal TLS alert message :const:`ALERT_DESCRIPTION_HANDSHAKE_FAILURE`. This method will raise :exc:`NotImplementedError` if the OpenSSL library had OPENSSL_NO_TLSEXT defined when it was built. + .. versionadded:: 3.7 + +.. attribute:: SSLContext.set_servername_callback(server_name_callback) + + This is a legacy API retained for backwards compatibility. When possible, + you should use :attr:`sni_callback` instead. The given *server_name_callback* + is similar to *sni_callback*, except that when the server hostname is an + IDN-encoded internationalized domain name, the *server_name_callback* + receives a decoded U-label (``"pyth?n.org"``). + + If there is an decoding error on the server name, the TLS connection will + terminate with an :const:`ALERT_DESCRIPTION_INTERNAL_ERROR` fatal TLS + alert message to the client. + .. versionadded:: 3.4 .. method:: SSLContext.load_dh_params(dhfile) diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 2ca1eed2155e..ecb629336499 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -654,6 +654,14 @@ ciphers that have been blocked by OpenSSL security update. Default cipher suite selection can be configured on 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 +Nathaniel J. Smith and Christian Heimes in :issue:`28414`.) + + string ------ diff --git a/Lib/ssl.py b/Lib/ssl.py index b6161d0f178d..f2537698d303 100644 --- a/Lib/ssl.py +++ b/Lib/ssl.py @@ -355,13 +355,20 @@ def __new__(cls, protocol=PROTOCOL_TLS, *args, **kwargs): self = _SSLContext.__new__(cls, protocol) return self - def __init__(self, protocol=PROTOCOL_TLS): - self.protocol = protocol + def _encode_hostname(self, hostname): + if hostname is None: + return None + elif isinstance(hostname, str): + return hostname.encode('idna').decode('ascii') + else: + return hostname.decode('ascii') def wrap_socket(self, sock, server_side=False, do_handshake_on_connect=True, suppress_ragged_eofs=True, server_hostname=None, session=None): + # SSLSocket class handles server_hostname encoding before it calls + # ctx._wrap_socket() return self.sslsocket_class( sock=sock, server_side=server_side, @@ -374,8 +381,12 @@ def wrap_socket(self, sock, server_side=False, def wrap_bio(self, incoming, outgoing, server_side=False, server_hostname=None, session=None): - sslobj = self._wrap_bio(incoming, outgoing, server_side=server_side, - server_hostname=server_hostname) + # Need to encode server_hostname here because _wrap_bio() can only + # handle ASCII str. + sslobj = self._wrap_bio( + incoming, outgoing, server_side=server_side, + server_hostname=self._encode_hostname(server_hostname) + ) return self.sslobject_class(sslobj, session=session) def set_npn_protocols(self, npn_protocols): @@ -389,6 +400,19 @@ def set_npn_protocols(self, npn_protocols): self._set_npn_protocols(protos) + def set_servername_callback(self, server_name_callback): + if server_name_callback is None: + self.sni_callback = None + else: + if not callable(server_name_callback): + raise TypeError("not a callable object") + + def shim_cb(sslobj, servername, sslctx): + servername = self._encode_hostname(servername) + return server_name_callback(sslobj, servername, sslctx) + + self.sni_callback = shim_cb + def set_alpn_protocols(self, alpn_protocols): protos = bytearray() for protocol in alpn_protocols: @@ -447,6 +471,10 @@ def hostname_checks_common_name(self, value): def hostname_checks_common_name(self): return True + @property + def protocol(self): + return _SSLMethod(super().protocol) + @property def verify_flags(self): return VerifyFlags(super().verify_flags) @@ -749,7 +777,7 @@ def __init__(self, sock=None, keyfile=None, certfile=None, raise ValueError("check_hostname requires server_hostname") self._session = _session self.server_side = server_side - self.server_hostname = server_hostname + self.server_hostname = self._context._encode_hostname(server_hostname) self.do_handshake_on_connect = do_handshake_on_connect self.suppress_ragged_eofs = suppress_ragged_eofs if sock is not None: @@ -781,7 +809,7 @@ def __init__(self, sock=None, keyfile=None, certfile=None, # create the SSL object try: sslobj = self._context._wrap_socket(self, server_side, - server_hostname) + self.server_hostname) self._sslobj = SSLObject(sslobj, owner=self, session=self._session) if do_handshake_on_connect: diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index a253f51d2a44..a48eb890da43 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -1528,16 +1528,6 @@ def test_subclass(self): # For compatibility self.assertEqual(cm.exception.errno, ssl.SSL_ERROR_WANT_READ) - def test_bad_idna_in_server_hostname(self): - # Note: this test is testing some code that probably shouldn't exist - # in the first place, so if it starts failing at some point because - # you made the ssl module stop doing IDNA decoding then please feel - # free to remove it. The test was mainly added because this case used - # to cause memory corruption (see bpo-30594). - ctx = ssl.create_default_context() - with self.assertRaises(UnicodeError): - ctx.wrap_bio(ssl.MemoryBIO(), ssl.MemoryBIO(), - server_hostname="xn--.com") def test_bad_server_hostname(self): ctx = ssl.create_default_context() @@ -2634,10 +2624,10 @@ def test_check_hostname_idn(self): if support.verbose: sys.stdout.write("\n") - server_context = ssl.SSLContext(ssl.PROTOCOL_TLS) + server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) server_context.load_cert_chain(IDNSANSFILE) - context = ssl.SSLContext(ssl.PROTOCOL_TLS) + context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) context.verify_mode = ssl.CERT_REQUIRED context.check_hostname = True context.load_verify_locations(SIGNING_CA) @@ -2646,18 +2636,26 @@ def test_check_hostname_idn(self): # different ways idn_hostnames = [ ('k?nig.idn.pythontest.net', - 'k?nig.idn.pythontest.net',), + 'xn--knig-5qa.idn.pythontest.net'), ('xn--knig-5qa.idn.pythontest.net', 'xn--knig-5qa.idn.pythontest.net'), (b'xn--knig-5qa.idn.pythontest.net', - b'xn--knig-5qa.idn.pythontest.net'), + 'xn--knig-5qa.idn.pythontest.net'), ('k?nigsg??chen.idna2003.pythontest.net', - 'k?nigsg??chen.idna2003.pythontest.net'), + 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'), ('xn--knigsgsschen-lcb0w.idna2003.pythontest.net', 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'), (b'xn--knigsgsschen-lcb0w.idna2003.pythontest.net', - b'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'), + 'xn--knigsgsschen-lcb0w.idna2003.pythontest.net'), + + # ('k?nigsg??chen.idna2008.pythontest.net', + # 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'), + ('xn--knigsgchen-b4a3dun.idna2008.pythontest.net', + 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'), + (b'xn--knigsgchen-b4a3dun.idna2008.pythontest.net', + 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net'), + ] for server_hostname, expected_hostname in idn_hostnames: server = ThreadedEchoServer(context=server_context, chatty=True) @@ -2676,16 +2674,6 @@ def test_check_hostname_idn(self): s.getpeercert() self.assertEqual(s.server_hostname, expected_hostname) - # bug https://bugs.python.org/issue28414 - # IDNA 2008 deviations are broken - idna2008 = 'xn--knigsgchen-b4a3dun.idna2008.pythontest.net' - server = ThreadedEchoServer(context=server_context, chatty=True) - with server: - with self.assertRaises(UnicodeError): - with context.wrap_socket(socket.socket(), - server_hostname=idna2008) as s: - s.connect((HOST, server.port)) - # incorrect hostname should raise an exception server = ThreadedEchoServer(context=server_context, chatty=True) with server: diff --git a/Misc/NEWS.d/next/Security/2017-08-06-14-43-45.bpo-28414.mzZ6vD.rst b/Misc/NEWS.d/next/Security/2017-08-06-14-43-45.bpo-28414.mzZ6vD.rst new file mode 100644 index 000000000000..06528c93ee19 --- /dev/null +++ b/Misc/NEWS.d/next/Security/2017-08-06-14-43-45.bpo-28414.mzZ6vD.rst @@ -0,0 +1 @@ +The ssl module now allows users to perform their own IDN en/decoding when using SNI. diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 7545e91babdb..a0f8c1cb3244 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -337,13 +337,14 @@ typedef struct { unsigned int alpn_protocols_len; #endif #ifndef OPENSSL_NO_TLSEXT - PyObject *set_hostname; + PyObject *set_sni_cb; #endif int check_hostname; /* OpenSSL has no API to get hostflags from X509_VERIFY_PARAM* struct. * We have to maintain our own copy. OpenSSL's hostflags default to 0. */ unsigned int hostflags; + int protocol; } PySSLContext; typedef struct { @@ -407,8 +408,6 @@ class _ssl.SSLSession "PySSLSession *" "&PySSLSession_Type" static int PySSL_select(PySocketSockObject *s, int writing, _PyTime_t timeout); - -#define PySSLContext_Check(v) (Py_TYPE(v) == &PySSLContext_Type) #define PySSLSocket_Check(v) (Py_TYPE(v) == &PySSLSocket_Type) #define PySSLMemoryBIO_Check(v) (Py_TYPE(v) == &PySSLMemoryBIO_Type) #define PySSLSession_Check(v) (Py_TYPE(v) == &PySSLSession_Type) @@ -761,7 +760,7 @@ _ssl_configure_hostname(PySSLSocket *self, const char* server_hostname) ERR_clear_error(); } - hostname = PyUnicode_Decode(server_hostname, len, "idna", "strict"); + hostname = PyUnicode_Decode(server_hostname, len, "ascii", "strict"); if (hostname == NULL) { goto error; } @@ -1992,7 +1991,7 @@ PyDoc_STRVAR(PySSL_set_context_doc, "_setter_context(ctx)\n\ \ This changes the context associated with the SSLSocket. This is typically\n\ -used from within a callback function set by the set_servername_callback\n\ +used from within a callback function set by the sni_callback\n\ on the SSLContext to change the certificate information associated with the\n\ SSLSocket before the cryptographic exchange handshake messages\n"); @@ -2850,6 +2849,7 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version) } self->ctx = ctx; self->hostflags = X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS; + self->protocol = proto_version; #if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG) self->npn_protocols = NULL; #endif @@ -2857,7 +2857,7 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version) self->alpn_protocols = NULL; #endif #ifndef OPENSSL_NO_TLSEXT - self->set_hostname = NULL; + self->set_sni_cb = NULL; #endif /* Don't check host name by default */ if (proto_version == PY_SSL_VERSION_TLS_CLIENT) { @@ -2968,7 +2968,7 @@ static int context_traverse(PySSLContext *self, visitproc visit, void *arg) { #ifndef OPENSSL_NO_TLSEXT - Py_VISIT(self->set_hostname); + Py_VISIT(self->set_sni_cb); #endif return 0; } @@ -2977,7 +2977,7 @@ static int context_clear(PySSLContext *self) { #ifndef OPENSSL_NO_TLSEXT - Py_CLEAR(self->set_hostname); + Py_CLEAR(self->set_sni_cb); #endif return 0; } @@ -3354,6 +3354,10 @@ set_check_hostname(PySSLContext *self, PyObject *arg, void *c) return 0; } +static PyObject * +get_protocol(PySSLContext *self, void *c) { + return PyLong_FromLong(self->protocol); +} typedef struct { PyThreadState *thread_state; @@ -3818,9 +3822,9 @@ _ssl__SSLContext__wrap_socket_impl(PySSLContext *self, PyObject *sock, PyObject *res; /* server_hostname is either None (or absent), or to be encoded - using the idna encoding. */ + as IDN A-label (ASCII str). */ if (hostname_obj != Py_None) { - if (!PyArg_Parse(hostname_obj, "et", "idna", &hostname)) + if (!PyArg_Parse(hostname_obj, "es", "ascii", &hostname)) return NULL; } @@ -3851,9 +3855,9 @@ _ssl__SSLContext__wrap_bio_impl(PySSLContext *self, PySSLMemoryBIO *incoming, PyObject *res; /* server_hostname is either None (or absent), or to be encoded - using the idna encoding. */ + as IDN A-label (ASCII str). */ if (hostname_obj != Py_None) { - if (!PyArg_Parse(hostname_obj, "et", "idna", &hostname)) + if (!PyArg_Parse(hostname_obj, "es", "ascii", &hostname)) return NULL; } @@ -3967,15 +3971,13 @@ _servername_callback(SSL *s, int *al, void *args) int ret; PySSLContext *ssl_ctx = (PySSLContext *) args; PySSLSocket *ssl; - PyObject *servername_o; - PyObject *servername_idna; PyObject *result; /* The high-level ssl.SSLSocket object */ PyObject *ssl_socket; const char *servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name); PyGILState_STATE gstate = PyGILState_Ensure(); - if (ssl_ctx->set_hostname == NULL) { + if (ssl_ctx->set_sni_cb == NULL) { /* remove race condition in this the call back while if removing the * callback is in progress */ PyGILState_Release(gstate); @@ -4005,35 +4007,46 @@ _servername_callback(SSL *s, int *al, void *args) goto error; if (servername == NULL) { - result = PyObject_CallFunctionObjArgs(ssl_ctx->set_hostname, ssl_socket, + result = PyObject_CallFunctionObjArgs(ssl_ctx->set_sni_cb, ssl_socket, Py_None, ssl_ctx, NULL); } else { - servername_o = PyBytes_FromString(servername); - if (servername_o == NULL) { + PyObject *servername_bytes; + PyObject *servername_str; + + servername_bytes = PyBytes_FromString(servername); + if (servername_bytes == NULL) { PyErr_WriteUnraisable((PyObject *) ssl_ctx); goto error; } - servername_idna = PyUnicode_FromEncodedObject(servername_o, "idna", NULL); - if (servername_idna == NULL) { - PyErr_WriteUnraisable(servername_o); - Py_DECREF(servername_o); + /* server_hostname was encoded to an A-label by our caller; put it + * back into a str object, but still as an A-label (bpo-28414) + */ + servername_str = PyUnicode_FromEncodedObject(servername_bytes, "ascii", NULL); + Py_DECREF(servername_bytes); + if (servername_str == NULL) { + PyErr_WriteUnraisable(servername_bytes); goto error; } - Py_DECREF(servername_o); - result = PyObject_CallFunctionObjArgs(ssl_ctx->set_hostname, ssl_socket, - servername_idna, ssl_ctx, NULL); - Py_DECREF(servername_idna); + result = PyObject_CallFunctionObjArgs( + ssl_ctx->set_sni_cb, ssl_socket, servername_str, + ssl_ctx, NULL); + Py_DECREF(servername_str); } Py_DECREF(ssl_socket); if (result == NULL) { - PyErr_WriteUnraisable(ssl_ctx->set_hostname); + PyErr_WriteUnraisable(ssl_ctx->set_sni_cb); *al = SSL_AD_HANDSHAKE_FAILURE; ret = SSL_TLSEXT_ERR_ALERT_FATAL; } else { - if (result != Py_None) { + /* Result may be None, a SSLContext or an integer + * None and SSLContext are OK, integer or other values are an error. + */ + if (result == Py_None) { + ret = SSL_TLSEXT_ERR_OK; + } else { *al = (int) PyLong_AsLong(result); if (PyErr_Occurred()) { PyErr_WriteUnraisable(result); @@ -4041,9 +4054,6 @@ _servername_callback(SSL *s, int *al, void *args) } ret = SSL_TLSEXT_ERR_ALERT_FATAL; } - else { - ret = SSL_TLSEXT_ERR_OK; - } Py_DECREF(result); } @@ -4059,49 +4069,59 @@ _servername_callback(SSL *s, int *al, void *args) } #endif -/*[clinic input] -_ssl._SSLContext.set_servername_callback - method as cb: object - / - -Set a callback that will be called when a server name is provided by the SSL/TLS client in the SNI extension. - -If the argument is None then the callback is disabled. The method is called -with the SSLSocket, the server name as a string, and the SSLContext object. -See RFC 6066 for details of the SNI extension. -[clinic start generated code]*/ - static PyObject * -_ssl__SSLContext_set_servername_callback(PySSLContext *self, PyObject *cb) -/*[clinic end generated code: output=3439a1b2d5d3b7ea input=a2a83620197d602b]*/ +get_sni_callback(PySSLContext *self, void *c) { + PyObject *cb = self->set_sni_cb; + if (cb == NULL) { + Py_RETURN_NONE; + } + Py_INCREF(cb); + return cb; +} + +static int +set_sni_callback(PySSLContext *self, PyObject *arg, void *c) +{ + if (self->protocol == PY_SSL_VERSION_TLS_CLIENT) { + PyErr_SetString(PyExc_ValueError, + "sni_callback cannot be set on TLS_CLIENT context"); + return -1; + } #if HAVE_SNI && !defined(OPENSSL_NO_TLSEXT) - Py_CLEAR(self->set_hostname); - if (cb == Py_None) { + Py_CLEAR(self->set_sni_cb); + if (arg == Py_None) { SSL_CTX_set_tlsext_servername_callback(self->ctx, NULL); } else { - if (!PyCallable_Check(cb)) { + if (!PyCallable_Check(arg)) { SSL_CTX_set_tlsext_servername_callback(self->ctx, NULL); PyErr_SetString(PyExc_TypeError, "not a callable object"); - return NULL; + return -1; } - Py_INCREF(cb); - self->set_hostname = cb; + Py_INCREF(arg); + self->set_sni_cb = arg; SSL_CTX_set_tlsext_servername_callback(self->ctx, _servername_callback); SSL_CTX_set_tlsext_servername_arg(self->ctx, self); } - Py_RETURN_NONE; + return 0; #else PyErr_SetString(PyExc_NotImplementedError, "The TLS extension servername callback, " "SSL_CTX_set_tlsext_servername_callback, " "is not in the current OpenSSL library."); - return NULL; + return -1; #endif } +PyDoc_STRVAR(PySSLContext_sni_callback_doc, +"Set a callback that will be called when a server name is provided by the SSL/TLS client in the SNI extension.\n\ +\n\ +If the argument is None then the callback is disabled. The method is called\n\ +with the SSLSocket, the server name as a string, and the SSLContext object.\n\ +See RFC 6066 for details of the SNI extension."); + /*[clinic input] _ssl._SSLContext.cert_store_stats @@ -4217,8 +4237,12 @@ static PyGetSetDef context_getsetlist[] = { (setter) set_check_hostname, NULL}, {"_host_flags", (getter) get_host_flags, (setter) set_host_flags, NULL}, + {"sni_callback", (getter) get_sni_callback, + (setter) set_sni_callback, PySSLContext_sni_callback_doc}, {"options", (getter) get_options, (setter) set_options, NULL}, + {"protocol", (getter) get_protocol, + NULL, NULL}, {"verify_flags", (getter) get_verify_flags, (setter) set_verify_flags, NULL}, {"verify_mode", (getter) get_verify_mode, @@ -4238,7 +4262,6 @@ static struct PyMethodDef context_methods[] = { _SSL__SSLCONTEXT_SESSION_STATS_METHODDEF _SSL__SSLCONTEXT_SET_DEFAULT_VERIFY_PATHS_METHODDEF _SSL__SSLCONTEXT_SET_ECDH_CURVE_METHODDEF - _SSL__SSLCONTEXT_SET_SERVERNAME_CALLBACK_METHODDEF _SSL__SSLCONTEXT_CERT_STORE_STATS_METHODDEF _SSL__SSLCONTEXT_GET_CA_CERTS_METHODDEF _SSL__SSLCONTEXT_GET_CIPHERS_METHODDEF diff --git a/Modules/clinic/_ssl.c.h b/Modules/clinic/_ssl.c.h index 32743e710f59..d1a9afcd1d1e 100644 --- a/Modules/clinic/_ssl.c.h +++ b/Modules/clinic/_ssl.c.h @@ -650,19 +650,6 @@ PyDoc_STRVAR(_ssl__SSLContext_set_ecdh_curve__doc__, #endif /* !defined(OPENSSL_NO_ECDH) */ -PyDoc_STRVAR(_ssl__SSLContext_set_servername_callback__doc__, -"set_servername_callback($self, method, /)\n" -"--\n" -"\n" -"Set a callback that will be called when a server name is provided by the SSL/TLS client in the SNI extension.\n" -"\n" -"If the argument is None then the callback is disabled. The method is called\n" -"with the SSLSocket, the server name as a string, and the SSLContext object.\n" -"See RFC 6066 for details of the SNI extension."); - -#define _SSL__SSLCONTEXT_SET_SERVERNAME_CALLBACK_METHODDEF \ - {"set_servername_callback", (PyCFunction)_ssl__SSLContext_set_servername_callback, METH_O, _ssl__SSLContext_set_servername_callback__doc__}, - PyDoc_STRVAR(_ssl__SSLContext_cert_store_stats__doc__, "cert_store_stats($self, /)\n" "--\n" @@ -1168,4 +1155,4 @@ _ssl_enum_crls(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje #ifndef _SSL_ENUM_CRLS_METHODDEF #define _SSL_ENUM_CRLS_METHODDEF #endif /* !defined(_SSL_ENUM_CRLS_METHODDEF) */ -/*[clinic end generated code: output=3d42305ed0ad162a input=a9049054013a1b77]*/ +/*[clinic end generated code: output=84e1fd89aff9b0f7 input=a9049054013a1b77]*/ From solipsis at pitrou.net Sat Feb 24 04:14:20 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 24 Feb 2018 09:14:20 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=7 Message-ID: <20180224091420.1.A99340BA543B13F6@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_asyncio leaked [0, 0, 3] memory blocks, sum=3 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/reflogFiUsod', '--timeout', '7200'] From webhook-mailer at python.org Sat Feb 24 08:35:59 2018 From: webhook-mailer at python.org (Christian Heimes) Date: Sat, 24 Feb 2018 13:35:59 -0000 Subject: [Python-checkins] bpo-32819: Simplify and improve ssl.match_hostname (#5620) Message-ID: https://github.com/python/cpython/commit/aef1283ba428e33397d87cee3c54a5110861552d commit: aef1283ba428e33397d87cee3c54a5110861552d branch: master author: Christian Heimes committer: GitHub date: 2018-02-24T14:35:56+01:00 summary: bpo-32819: Simplify and improve ssl.match_hostname (#5620) ssl.match_hostname() has been simplified and no longer depends on re and ipaddress module for wildcard and IP addresses. Error reporting for invalid wildcards has been improved. Signed-off-by: Christian Heimes files: A Misc/NEWS.d/next/Library/2018-02-11-15-54-41.bpo-32819.ZTRX2Q.rst M Lib/ssl.py M Lib/test/test_ssl.py diff --git a/Lib/ssl.py b/Lib/ssl.py index f2537698d303..ecdbb7076283 100644 --- a/Lib/ssl.py +++ b/Lib/ssl.py @@ -90,8 +90,6 @@ ALERT_DESCRIPTION_UNKNOWN_PSK_IDENTITY """ -import ipaddress -import re import sys import os from collections import namedtuple @@ -160,6 +158,7 @@ from socket import socket, AF_INET, SOCK_STREAM, create_connection from socket import SOL_SOCKET, SO_TYPE +import socket as _socket import base64 # for DER-to-PEM translation import errno import warnings @@ -183,55 +182,75 @@ def _dnsname_match(dn, hostname): """Matching according to RFC 6125, section 6.4.3 - http://tools.ietf.org/html/rfc6125#section-6.4.3 + - Hostnames are compared lower case. + - For IDNA, both dn and hostname must be encoded as IDN A-label (ACE). + - Partial wildcards like 'www*.example.org', multiple wildcards, sole + wildcard or wildcards in labels other then the left-most label are not + supported and a CertificateError is raised. + - A wildcard must match at least one character. """ - pats = [] if not dn: return False - leftmost, *remainder = dn.split(r'.') + wildcards = dn.count('*') + # speed up common case w/o wildcards + if not wildcards: + return dn.lower() == hostname.lower() + + if wildcards > 1: + raise CertificateError( + "too many wildcards in certificate DNS name: {!r}.".format(dn)) - wildcards = leftmost.count('*') - if wildcards == 1 and len(leftmost) > 1: + dn_leftmost, sep, dn_remainder = dn.partition('.') + + if '*' in dn_remainder: # Only match wildcard in leftmost segment. raise CertificateError( - "wildcard can only be present in the leftmost segment: " + repr(dn)) + "wildcard can only be present in the leftmost label: " + "{!r}.".format(dn)) - if wildcards > 1: - # Issue #17980: avoid denials of service by refusing more - # than one wildcard per fragment. A survey of established - # policy among SSL implementations showed it to be a - # reasonable choice. + if not sep: + # no right side raise CertificateError( - "too many wildcards in certificate DNS name: " + repr(dn)) + "sole wildcard without additional labels are not support: " + "{!r}.".format(dn)) - # speed up common case w/o wildcards - if not wildcards: - return dn.lower() == hostname.lower() + if dn_leftmost != '*': + # no partial wildcard matching + raise CertificateError( + "partial wildcards in leftmost label are not supported: " + "{!r}.".format(dn)) - # RFC 6125, section 6.4.3, subitem 1. - # The client SHOULD NOT attempt to match a presented identifier in which - # the wildcard character comprises a label other than the left-most label. - if leftmost == '*': - # When '*' is a fragment by itself, it matches a non-empty dotless - # fragment. - pats.append('[^.]+') - elif leftmost.startswith('xn--') or hostname.startswith('xn--'): - # RFC 6125, section 6.4.3, subitem 3. - # The client SHOULD NOT attempt to match a presented identifier - # where the wildcard character is embedded within an A-label or - # U-label of an internationalized domain name. - pats.append(re.escape(leftmost)) - else: - # Otherwise, '*' matches any dotless string, e.g. www* - pats.append(re.escape(leftmost).replace(r'\*', '[^.]*')) + hostname_leftmost, sep, hostname_remainder = hostname.partition('.') + if not hostname_leftmost or not sep: + # wildcard must match at least one char + return False + return dn_remainder.lower() == hostname_remainder.lower() - # add the remaining fragments, ignore any wildcards - for frag in remainder: - pats.append(re.escape(frag)) - pat = re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE) - return pat.match(hostname) +def _inet_paton(ipname): + """Try to convert an IP address to packed binary form + + Supports IPv4 addresses on all platforms and IPv6 on platforms with IPv6 + support. + """ + # inet_aton() also accepts strings like '1' + if ipname.count('.') == 3: + try: + return _socket.inet_aton(ipname) + except OSError: + pass + + try: + return _socket.inet_pton(_socket.AF_INET6, ipname) + except OSError: + raise ValueError("{!r} is neither an IPv4 nor an IP6 " + "address.".format(ipname)) + except AttributeError: + # AF_INET6 not available + pass + + raise ValueError("{!r} is not an IPv4 address.".format(ipname)) def _ipaddress_match(ipname, host_ip): @@ -241,14 +260,19 @@ def _ipaddress_match(ipname, host_ip): (section 1.7.2 - "Out of Scope"). """ # OpenSSL may add a trailing newline to a subjectAltName's IP address - ip = ipaddress.ip_address(ipname.rstrip()) + ip = _inet_paton(ipname.rstrip()) return ip == host_ip def match_hostname(cert, hostname): """Verify that *cert* (in decoded format as returned by SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 and RFC 6125 - rules are followed, but IP addresses are not accepted for *hostname*. + rules are followed. + + The function matches IP addresses rather than dNSNames if hostname is a + valid ipaddress string. IPv4 addresses are supported on all platforms. + IPv6 addresses are supported on platforms with IPv6 support (AF_INET6 + and inet_pton). CertificateError is raised on failure. On success, the function returns nothing. @@ -258,7 +282,7 @@ def match_hostname(cert, hostname): "SSL socket or SSL context with either " "CERT_OPTIONAL or CERT_REQUIRED") try: - host_ip = ipaddress.ip_address(hostname) + host_ip = _inet_paton(hostname) except ValueError: # Not an IP address (common case) host_ip = None diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index a48eb890da43..7aa112335cdb 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -622,14 +622,16 @@ def fail(cert, hostname): fail(cert, 'example.net') # -- IPv6 matching -- - cert = {'subject': ((('commonName', 'example.com'),),), - 'subjectAltName': (('DNS', 'example.com'), - ('IP Address', '2001:0:0:0:0:0:0:CAFE\n'), - ('IP Address', '2003:0:0:0:0:0:0:BABA\n'))} - ok(cert, '2001::cafe') - ok(cert, '2003::baba') - fail(cert, '2003::bebe') - fail(cert, 'example.net') + if hasattr(socket, 'AF_INET6'): + cert = {'subject': ((('commonName', 'example.com'),),), + 'subjectAltName': ( + ('DNS', 'example.com'), + ('IP Address', '2001:0:0:0:0:0:0:CAFE\n'), + ('IP Address', '2003:0:0:0:0:0:0:BABA\n'))} + ok(cert, '2001::cafe') + ok(cert, '2003::baba') + fail(cert, '2003::bebe') + fail(cert, 'example.net') # -- Miscellaneous -- @@ -665,14 +667,45 @@ def fail(cert, hostname): # Issue #17980: avoid denials of service by refusing more than one # wildcard per fragment. - cert = {'subject': ((('commonName', 'a*b.com'),),)} - fail(cert, 'axxb.com') - cert = {'subject': ((('commonName', 'a*b.co*'),),)} - fail(cert, 'axxb.com') - cert = {'subject': ((('commonName', 'a*b*.com'),),)} - with self.assertRaises(ssl.CertificateError) as cm: - ssl.match_hostname(cert, 'axxbxxc.com') - self.assertIn("too many wildcards", str(cm.exception)) + cert = {'subject': ((('commonName', 'a*b.example.com'),),)} + with self.assertRaisesRegex( + ssl.CertificateError, + "partial wildcards in leftmost label are not supported"): + ssl.match_hostname(cert, 'axxb.example.com') + + cert = {'subject': ((('commonName', 'www.*.example.com'),),)} + with self.assertRaisesRegex( + ssl.CertificateError, + "wildcard can only be present in the leftmost label"): + ssl.match_hostname(cert, 'www.sub.example.com') + + cert = {'subject': ((('commonName', 'a*b*.example.com'),),)} + with self.assertRaisesRegex( + ssl.CertificateError, + "too many wildcards"): + ssl.match_hostname(cert, 'axxbxxc.example.com') + + cert = {'subject': ((('commonName', '*'),),)} + with self.assertRaisesRegex( + ssl.CertificateError, + "sole wildcard without additional labels are not support"): + ssl.match_hostname(cert, 'host') + + cert = {'subject': ((('commonName', '*.com'),),)} + with self.assertRaisesRegex( + ssl.CertificateError, + r"hostname 'com' doesn't match '\*.com'"): + ssl.match_hostname(cert, 'com') + + # extra checks for _inet_paton() + for invalid in ['1', '', '1.2.3', '256.0.0.1', '127.0.0.1/24']: + with self.assertRaises(ValueError): + ssl._inet_paton(invalid) + for ipaddr in ['127.0.0.1', '192.168.0.1']: + self.assertTrue(ssl._inet_paton(ipaddr)) + if hasattr(socket, 'AF_INET6'): + for ipaddr in ['::1', '2001:db8:85a3::8a2e:370:7334']: + self.assertTrue(ssl._inet_paton(ipaddr)) def test_server_side(self): # server_hostname doesn't work for server sockets diff --git a/Misc/NEWS.d/next/Library/2018-02-11-15-54-41.bpo-32819.ZTRX2Q.rst b/Misc/NEWS.d/next/Library/2018-02-11-15-54-41.bpo-32819.ZTRX2Q.rst new file mode 100644 index 000000000000..7d57bf697826 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-11-15-54-41.bpo-32819.ZTRX2Q.rst @@ -0,0 +1,3 @@ +ssl.match_hostname() has been simplified and no longer depends on re and +ipaddress module for wildcard and IP addresses. Error reporting for invalid +wildcards has been improved. From webhook-mailer at python.org Sat Feb 24 09:06:49 2018 From: webhook-mailer at python.org (Christian Heimes) Date: Sat, 24 Feb 2018 14:06:49 -0000 Subject: [Python-checkins] [3.7] bpo-32819: Simplify and improve ssl.match_hostname (GH-5620) (#5847) Message-ID: https://github.com/python/cpython/commit/46632f4d3c1f3aef875d2ada750a298ab0510992 commit: 46632f4d3c1f3aef875d2ada750a298ab0510992 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Christian Heimes date: 2018-02-24T15:06:46+01:00 summary: [3.7] bpo-32819: Simplify and improve ssl.match_hostname (GH-5620) (#5847) ssl.match_hostname() has been simplified and no longer depends on re and ipaddress module for wildcard and IP addresses. Error reporting for invalid wildcards has been improved. Signed-off-by: Christian Heimes (cherry picked from commit aef1283ba428e33397d87cee3c54a5110861552d) Co-authored-by: Christian Heimes files: A Misc/NEWS.d/next/Library/2018-02-11-15-54-41.bpo-32819.ZTRX2Q.rst M Lib/ssl.py M Lib/test/test_ssl.py diff --git a/Lib/ssl.py b/Lib/ssl.py index f2537698d303..ecdbb7076283 100644 --- a/Lib/ssl.py +++ b/Lib/ssl.py @@ -90,8 +90,6 @@ ALERT_DESCRIPTION_UNKNOWN_PSK_IDENTITY """ -import ipaddress -import re import sys import os from collections import namedtuple @@ -160,6 +158,7 @@ from socket import socket, AF_INET, SOCK_STREAM, create_connection from socket import SOL_SOCKET, SO_TYPE +import socket as _socket import base64 # for DER-to-PEM translation import errno import warnings @@ -183,55 +182,75 @@ def _dnsname_match(dn, hostname): """Matching according to RFC 6125, section 6.4.3 - http://tools.ietf.org/html/rfc6125#section-6.4.3 + - Hostnames are compared lower case. + - For IDNA, both dn and hostname must be encoded as IDN A-label (ACE). + - Partial wildcards like 'www*.example.org', multiple wildcards, sole + wildcard or wildcards in labels other then the left-most label are not + supported and a CertificateError is raised. + - A wildcard must match at least one character. """ - pats = [] if not dn: return False - leftmost, *remainder = dn.split(r'.') + wildcards = dn.count('*') + # speed up common case w/o wildcards + if not wildcards: + return dn.lower() == hostname.lower() + + if wildcards > 1: + raise CertificateError( + "too many wildcards in certificate DNS name: {!r}.".format(dn)) - wildcards = leftmost.count('*') - if wildcards == 1 and len(leftmost) > 1: + dn_leftmost, sep, dn_remainder = dn.partition('.') + + if '*' in dn_remainder: # Only match wildcard in leftmost segment. raise CertificateError( - "wildcard can only be present in the leftmost segment: " + repr(dn)) + "wildcard can only be present in the leftmost label: " + "{!r}.".format(dn)) - if wildcards > 1: - # Issue #17980: avoid denials of service by refusing more - # than one wildcard per fragment. A survey of established - # policy among SSL implementations showed it to be a - # reasonable choice. + if not sep: + # no right side raise CertificateError( - "too many wildcards in certificate DNS name: " + repr(dn)) + "sole wildcard without additional labels are not support: " + "{!r}.".format(dn)) - # speed up common case w/o wildcards - if not wildcards: - return dn.lower() == hostname.lower() + if dn_leftmost != '*': + # no partial wildcard matching + raise CertificateError( + "partial wildcards in leftmost label are not supported: " + "{!r}.".format(dn)) - # RFC 6125, section 6.4.3, subitem 1. - # The client SHOULD NOT attempt to match a presented identifier in which - # the wildcard character comprises a label other than the left-most label. - if leftmost == '*': - # When '*' is a fragment by itself, it matches a non-empty dotless - # fragment. - pats.append('[^.]+') - elif leftmost.startswith('xn--') or hostname.startswith('xn--'): - # RFC 6125, section 6.4.3, subitem 3. - # The client SHOULD NOT attempt to match a presented identifier - # where the wildcard character is embedded within an A-label or - # U-label of an internationalized domain name. - pats.append(re.escape(leftmost)) - else: - # Otherwise, '*' matches any dotless string, e.g. www* - pats.append(re.escape(leftmost).replace(r'\*', '[^.]*')) + hostname_leftmost, sep, hostname_remainder = hostname.partition('.') + if not hostname_leftmost or not sep: + # wildcard must match at least one char + return False + return dn_remainder.lower() == hostname_remainder.lower() - # add the remaining fragments, ignore any wildcards - for frag in remainder: - pats.append(re.escape(frag)) - pat = re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE) - return pat.match(hostname) +def _inet_paton(ipname): + """Try to convert an IP address to packed binary form + + Supports IPv4 addresses on all platforms and IPv6 on platforms with IPv6 + support. + """ + # inet_aton() also accepts strings like '1' + if ipname.count('.') == 3: + try: + return _socket.inet_aton(ipname) + except OSError: + pass + + try: + return _socket.inet_pton(_socket.AF_INET6, ipname) + except OSError: + raise ValueError("{!r} is neither an IPv4 nor an IP6 " + "address.".format(ipname)) + except AttributeError: + # AF_INET6 not available + pass + + raise ValueError("{!r} is not an IPv4 address.".format(ipname)) def _ipaddress_match(ipname, host_ip): @@ -241,14 +260,19 @@ def _ipaddress_match(ipname, host_ip): (section 1.7.2 - "Out of Scope"). """ # OpenSSL may add a trailing newline to a subjectAltName's IP address - ip = ipaddress.ip_address(ipname.rstrip()) + ip = _inet_paton(ipname.rstrip()) return ip == host_ip def match_hostname(cert, hostname): """Verify that *cert* (in decoded format as returned by SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 and RFC 6125 - rules are followed, but IP addresses are not accepted for *hostname*. + rules are followed. + + The function matches IP addresses rather than dNSNames if hostname is a + valid ipaddress string. IPv4 addresses are supported on all platforms. + IPv6 addresses are supported on platforms with IPv6 support (AF_INET6 + and inet_pton). CertificateError is raised on failure. On success, the function returns nothing. @@ -258,7 +282,7 @@ def match_hostname(cert, hostname): "SSL socket or SSL context with either " "CERT_OPTIONAL or CERT_REQUIRED") try: - host_ip = ipaddress.ip_address(hostname) + host_ip = _inet_paton(hostname) except ValueError: # Not an IP address (common case) host_ip = None diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index a48eb890da43..7aa112335cdb 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -622,14 +622,16 @@ def fail(cert, hostname): fail(cert, 'example.net') # -- IPv6 matching -- - cert = {'subject': ((('commonName', 'example.com'),),), - 'subjectAltName': (('DNS', 'example.com'), - ('IP Address', '2001:0:0:0:0:0:0:CAFE\n'), - ('IP Address', '2003:0:0:0:0:0:0:BABA\n'))} - ok(cert, '2001::cafe') - ok(cert, '2003::baba') - fail(cert, '2003::bebe') - fail(cert, 'example.net') + if hasattr(socket, 'AF_INET6'): + cert = {'subject': ((('commonName', 'example.com'),),), + 'subjectAltName': ( + ('DNS', 'example.com'), + ('IP Address', '2001:0:0:0:0:0:0:CAFE\n'), + ('IP Address', '2003:0:0:0:0:0:0:BABA\n'))} + ok(cert, '2001::cafe') + ok(cert, '2003::baba') + fail(cert, '2003::bebe') + fail(cert, 'example.net') # -- Miscellaneous -- @@ -665,14 +667,45 @@ def fail(cert, hostname): # Issue #17980: avoid denials of service by refusing more than one # wildcard per fragment. - cert = {'subject': ((('commonName', 'a*b.com'),),)} - fail(cert, 'axxb.com') - cert = {'subject': ((('commonName', 'a*b.co*'),),)} - fail(cert, 'axxb.com') - cert = {'subject': ((('commonName', 'a*b*.com'),),)} - with self.assertRaises(ssl.CertificateError) as cm: - ssl.match_hostname(cert, 'axxbxxc.com') - self.assertIn("too many wildcards", str(cm.exception)) + cert = {'subject': ((('commonName', 'a*b.example.com'),),)} + with self.assertRaisesRegex( + ssl.CertificateError, + "partial wildcards in leftmost label are not supported"): + ssl.match_hostname(cert, 'axxb.example.com') + + cert = {'subject': ((('commonName', 'www.*.example.com'),),)} + with self.assertRaisesRegex( + ssl.CertificateError, + "wildcard can only be present in the leftmost label"): + ssl.match_hostname(cert, 'www.sub.example.com') + + cert = {'subject': ((('commonName', 'a*b*.example.com'),),)} + with self.assertRaisesRegex( + ssl.CertificateError, + "too many wildcards"): + ssl.match_hostname(cert, 'axxbxxc.example.com') + + cert = {'subject': ((('commonName', '*'),),)} + with self.assertRaisesRegex( + ssl.CertificateError, + "sole wildcard without additional labels are not support"): + ssl.match_hostname(cert, 'host') + + cert = {'subject': ((('commonName', '*.com'),),)} + with self.assertRaisesRegex( + ssl.CertificateError, + r"hostname 'com' doesn't match '\*.com'"): + ssl.match_hostname(cert, 'com') + + # extra checks for _inet_paton() + for invalid in ['1', '', '1.2.3', '256.0.0.1', '127.0.0.1/24']: + with self.assertRaises(ValueError): + ssl._inet_paton(invalid) + for ipaddr in ['127.0.0.1', '192.168.0.1']: + self.assertTrue(ssl._inet_paton(ipaddr)) + if hasattr(socket, 'AF_INET6'): + for ipaddr in ['::1', '2001:db8:85a3::8a2e:370:7334']: + self.assertTrue(ssl._inet_paton(ipaddr)) def test_server_side(self): # server_hostname doesn't work for server sockets diff --git a/Misc/NEWS.d/next/Library/2018-02-11-15-54-41.bpo-32819.ZTRX2Q.rst b/Misc/NEWS.d/next/Library/2018-02-11-15-54-41.bpo-32819.ZTRX2Q.rst new file mode 100644 index 000000000000..7d57bf697826 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-11-15-54-41.bpo-32819.ZTRX2Q.rst @@ -0,0 +1,3 @@ +ssl.match_hostname() has been simplified and no longer depends on re and +ipaddress module for wildcard and IP addresses. Error reporting for invalid +wildcards has been improved. From webhook-mailer at python.org Sat Feb 24 11:55:54 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Sat, 24 Feb 2018 16:55:54 -0000 Subject: [Python-checkins] bpo-31966: Fixed WindowsConsoleIO.write() for writing empty data. (GH-5754) Message-ID: https://github.com/python/cpython/commit/42c35d9c0c8175332f50fbe034a001fe52f057b9 commit: 42c35d9c0c8175332f50fbe034a001fe52f057b9 branch: master author: Serhiy Storchaka committer: GitHub date: 2018-02-24T18:55:51+02:00 summary: bpo-31966: Fixed WindowsConsoleIO.write() for writing empty data. (GH-5754) files: A Misc/NEWS.d/next/Windows/2018-02-19-13-54-42.bpo-31966._Q3HPb.rst M Lib/test/test_winconsoleio.py M Modules/_io/winconsoleio.c diff --git a/Lib/test/test_winconsoleio.py b/Lib/test/test_winconsoleio.py index 656483cf1621..a78fa4d7d919 100644 --- a/Lib/test/test_winconsoleio.py +++ b/Lib/test/test_winconsoleio.py @@ -121,6 +121,10 @@ def test_conout_path(self): else: self.assertNotIsInstance(f, ConIO) + def test_write_empty_data(self): + with ConIO('CONOUT$', 'w') as f: + self.assertEqual(f.write(b''), 0) + def assertStdinRoundTrip(self, text): stdin = open('CONIN$', 'r') old_stdin = sys.stdin diff --git a/Misc/NEWS.d/next/Windows/2018-02-19-13-54-42.bpo-31966._Q3HPb.rst b/Misc/NEWS.d/next/Windows/2018-02-19-13-54-42.bpo-31966._Q3HPb.rst new file mode 100644 index 000000000000..042a4d835abf --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2018-02-19-13-54-42.bpo-31966._Q3HPb.rst @@ -0,0 +1 @@ +Fixed WindowsConsoleIO.write() for writing empty data. diff --git a/Modules/_io/winconsoleio.c b/Modules/_io/winconsoleio.c index 30d1c767afcf..b85c11b3405a 100644 --- a/Modules/_io/winconsoleio.c +++ b/Modules/_io/winconsoleio.c @@ -964,6 +964,9 @@ _io__WindowsConsoleIO_write_impl(winconsoleio *self, Py_buffer *b) if (!self->writable) return err_mode("writing"); + if (!b->len) { + return PyLong_FromLong(0); + } if (b->len > BUFMAX) len = BUFMAX; else From webhook-mailer at python.org Sat Feb 24 12:39:21 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 24 Feb 2018 17:39:21 -0000 Subject: [Python-checkins] bpo-31966: Fixed WindowsConsoleIO.write() for writing empty data. (GH-5754) Message-ID: https://github.com/python/cpython/commit/e49bf0f353a968cddc4d8e6ea668b9d2d116e2ac commit: e49bf0f353a968cddc4d8e6ea668b9d2d116e2ac branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-24T09:39:18-08:00 summary: bpo-31966: Fixed WindowsConsoleIO.write() for writing empty data. (GH-5754) (cherry picked from commit 42c35d9c0c8175332f50fbe034a001fe52f057b9) Co-authored-by: Serhiy Storchaka files: A Misc/NEWS.d/next/Windows/2018-02-19-13-54-42.bpo-31966._Q3HPb.rst M Lib/test/test_winconsoleio.py M Modules/_io/winconsoleio.c diff --git a/Lib/test/test_winconsoleio.py b/Lib/test/test_winconsoleio.py index 656483cf1621..a78fa4d7d919 100644 --- a/Lib/test/test_winconsoleio.py +++ b/Lib/test/test_winconsoleio.py @@ -121,6 +121,10 @@ def test_conout_path(self): else: self.assertNotIsInstance(f, ConIO) + def test_write_empty_data(self): + with ConIO('CONOUT$', 'w') as f: + self.assertEqual(f.write(b''), 0) + def assertStdinRoundTrip(self, text): stdin = open('CONIN$', 'r') old_stdin = sys.stdin diff --git a/Misc/NEWS.d/next/Windows/2018-02-19-13-54-42.bpo-31966._Q3HPb.rst b/Misc/NEWS.d/next/Windows/2018-02-19-13-54-42.bpo-31966._Q3HPb.rst new file mode 100644 index 000000000000..042a4d835abf --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2018-02-19-13-54-42.bpo-31966._Q3HPb.rst @@ -0,0 +1 @@ +Fixed WindowsConsoleIO.write() for writing empty data. diff --git a/Modules/_io/winconsoleio.c b/Modules/_io/winconsoleio.c index 30d1c767afcf..b85c11b3405a 100644 --- a/Modules/_io/winconsoleio.c +++ b/Modules/_io/winconsoleio.c @@ -964,6 +964,9 @@ _io__WindowsConsoleIO_write_impl(winconsoleio *self, Py_buffer *b) if (!self->writable) return err_mode("writing"); + if (!b->len) { + return PyLong_FromLong(0); + } if (b->len > BUFMAX) len = BUFMAX; else From webhook-mailer at python.org Sat Feb 24 12:43:08 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sat, 24 Feb 2018 17:43:08 -0000 Subject: [Python-checkins] bpo-31966: Fixed WindowsConsoleIO.write() for writing empty data. (GH-5754) Message-ID: https://github.com/python/cpython/commit/980790eee0c804061a49b8ad7373e4669b48f2ec commit: 980790eee0c804061a49b8ad7373e4669b48f2ec branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-24T09:43:05-08:00 summary: bpo-31966: Fixed WindowsConsoleIO.write() for writing empty data. (GH-5754) (cherry picked from commit 42c35d9c0c8175332f50fbe034a001fe52f057b9) Co-authored-by: Serhiy Storchaka files: A Misc/NEWS.d/next/Windows/2018-02-19-13-54-42.bpo-31966._Q3HPb.rst M Lib/test/test_winconsoleio.py M Modules/_io/winconsoleio.c diff --git a/Lib/test/test_winconsoleio.py b/Lib/test/test_winconsoleio.py index 656483cf1621..a78fa4d7d919 100644 --- a/Lib/test/test_winconsoleio.py +++ b/Lib/test/test_winconsoleio.py @@ -121,6 +121,10 @@ def test_conout_path(self): else: self.assertNotIsInstance(f, ConIO) + def test_write_empty_data(self): + with ConIO('CONOUT$', 'w') as f: + self.assertEqual(f.write(b''), 0) + def assertStdinRoundTrip(self, text): stdin = open('CONIN$', 'r') old_stdin = sys.stdin diff --git a/Misc/NEWS.d/next/Windows/2018-02-19-13-54-42.bpo-31966._Q3HPb.rst b/Misc/NEWS.d/next/Windows/2018-02-19-13-54-42.bpo-31966._Q3HPb.rst new file mode 100644 index 000000000000..042a4d835abf --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2018-02-19-13-54-42.bpo-31966._Q3HPb.rst @@ -0,0 +1 @@ +Fixed WindowsConsoleIO.write() for writing empty data. diff --git a/Modules/_io/winconsoleio.c b/Modules/_io/winconsoleio.c index 5cf3f070d825..0d1b0926baee 100644 --- a/Modules/_io/winconsoleio.c +++ b/Modules/_io/winconsoleio.c @@ -981,6 +981,9 @@ _io__WindowsConsoleIO_write_impl(winconsoleio *self, Py_buffer *b) if (!self->writable) return err_mode("writing"); + if (!b->len) { + return PyLong_FromLong(0); + } if (b->len > BUFMAX) len = BUFMAX; else From webhook-mailer at python.org Sat Feb 24 14:30:47 2018 From: webhook-mailer at python.org (Ned Deily) Date: Sat, 24 Feb 2018 19:30:47 -0000 Subject: [Python-checkins] bpo-32931: fix macOS 10.9+ installer c++ compiler name (#5855) Message-ID: https://github.com/python/cpython/commit/acd7163c0a0674b2fb6cc0178d52cf90c953fbae commit: acd7163c0a0674b2fb6cc0178d52cf90c953fbae branch: master author: Ned Deily committer: GitHub date: 2018-02-24T14:30:44-05:00 summary: bpo-32931: fix macOS 10.9+ installer c++ compiler name (#5855) files: M Mac/BuildScript/build-installer.py diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index 1a7080c18f1b..bacdbfb0feba 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -161,7 +161,7 @@ def getTargetCompilers(): '10.5': ('gcc', 'g++'), '10.6': ('gcc', 'g++'), } - return target_cc_map.get(DEPTARGET, ('gcc', 'gcc++') ) + return target_cc_map.get(DEPTARGET, ('gcc', 'g++') ) CC, CXX = getTargetCompilers() From webhook-mailer at python.org Sat Feb 24 14:59:13 2018 From: webhook-mailer at python.org (Benjamin Peterson) Date: Sat, 24 Feb 2018 19:59:13 -0000 Subject: [Python-checkins] remove vestigal locking from obmalloc (GH-5805) Message-ID: https://github.com/python/cpython/commit/b18f8bc1a77193c372d79afa79b284028a2842d7 commit: b18f8bc1a77193c372d79afa79b284028a2842d7 branch: master author: Benjamin Peterson committer: GitHub date: 2018-02-24T11:59:10-08:00 summary: remove vestigal locking from obmalloc (GH-5805) obmalloc has (empty) macros for locking in the allocator. These aren't needed in CPython; we rely on the GIL. files: M Objects/obmalloc.c diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c index 0e485d62114d..eb7cbfca157c 100644 --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -849,30 +849,6 @@ static int running_on_valgrind = -1; /*==========================================================================*/ -/* - * Locking - * - * To reduce lock contention, it would probably be better to refine the - * crude function locking with per size class locking. I'm not positive - * however, whether it's worth switching to such locking policy because - * of the performance penalty it might introduce. - * - * The following macros describe the simplest (should also be the fastest) - * lock object on a particular platform and the init/fini/lock/unlock - * operations on it. The locks defined here are not expected to be recursive - * because it is assumed that they will always be called in the order: - * INIT, [LOCK, UNLOCK]*, FINI. - */ - -/* - * Python's threads are serialized, so object malloc locking is disabled. - */ -#define SIMPLELOCK_DECL(lock) /* simple lock declaration */ -#define SIMPLELOCK_INIT(lock) /* allocate (if needed) and initialize */ -#define SIMPLELOCK_FINI(lock) /* free/destroy an existing lock */ -#define SIMPLELOCK_LOCK(lock) /* acquire released lock */ -#define SIMPLELOCK_UNLOCK(lock) /* release acquired lock */ - /* When you say memory, my mind reasons in terms of (pointers to) blocks */ typedef uint8_t block; @@ -944,15 +920,6 @@ struct arena_object { /*==========================================================================*/ -/* - * This malloc lock - */ -SIMPLELOCK_DECL(_malloc_lock) -#define LOCK() SIMPLELOCK_LOCK(_malloc_lock) -#define UNLOCK() SIMPLELOCK_UNLOCK(_malloc_lock) -#define LOCK_INIT() SIMPLELOCK_INIT(_malloc_lock) -#define LOCK_FINI() SIMPLELOCK_FINI(_malloc_lock) - /* * Pool table -- headed, circular, doubly-linked lists of partially used pools. @@ -1381,7 +1348,6 @@ pymalloc_alloc(void *ctx, void **ptr_p, size_t nbytes) return 0; } - LOCK(); /* * Most frequent paths first */ @@ -1537,13 +1503,11 @@ pymalloc_alloc(void *ctx, void **ptr_p, size_t nbytes) goto init_pool; success: - UNLOCK(); assert(bp != NULL); *ptr_p = (void *)bp; return 1; failed: - UNLOCK(); return 0; } @@ -1612,8 +1576,6 @@ pymalloc_free(void *ctx, void *p) } /* We allocated this address. */ - LOCK(); - /* Link p to the start of the pool's freeblock list. Since * the pool had at least the p block outstanding, the pool * wasn't empty (so it's already in a usedpools[] list, or @@ -1798,7 +1760,6 @@ pymalloc_free(void *ctx, void *p) goto success; success: - UNLOCK(); return 1; } From webhook-mailer at python.org Sat Feb 24 14:59:27 2018 From: webhook-mailer at python.org (Ned Deily) Date: Sat, 24 Feb 2018 19:59:27 -0000 Subject: [Python-checkins] [3.7] bpo-32931: fix macOS 10.9+ installer c++ compiler name (GH-5856) Message-ID: https://github.com/python/cpython/commit/d24c5a068c1831a8579a5915f44ae3b4344aba43 commit: d24c5a068c1831a8579a5915f44ae3b4344aba43 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Ned Deily date: 2018-02-24T14:59:25-05:00 summary: [3.7] bpo-32931: fix macOS 10.9+ installer c++ compiler name (GH-5856) (cherry picked from commit acd7163c0a0674b2fb6cc0178d52cf90c953fbae) 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 1a7080c18f1b..bacdbfb0feba 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -161,7 +161,7 @@ def getTargetCompilers(): '10.5': ('gcc', 'g++'), '10.6': ('gcc', 'g++'), } - return target_cc_map.get(DEPTARGET, ('gcc', 'gcc++') ) + return target_cc_map.get(DEPTARGET, ('gcc', 'g++') ) CC, CXX = getTargetCompilers() From webhook-mailer at python.org Sat Feb 24 15:11:00 2018 From: webhook-mailer at python.org (Christian Heimes) Date: Sat, 24 Feb 2018 20:11:00 -0000 Subject: [Python-checkins] bpo-24334: Cleanup SSLSocket (#5252) Message-ID: https://github.com/python/cpython/commit/141c5e8c2437a9fed95a04c81e400ef725592a17 commit: 141c5e8c2437a9fed95a04c81e400ef725592a17 branch: master author: Christian Heimes committer: GitHub date: 2018-02-24T21:10:57+01:00 summary: bpo-24334: Cleanup SSLSocket (#5252) * The SSLSocket is no longer implemented on top of SSLObject to avoid an extra level of indirection. * Owner and session are now handled in the internal constructor. * _ssl._SSLSocket now uses the same method names as SSLSocket and SSLObject. * Channel binding type check is now handled in C code. Channel binding is always available. The patch also changes the signature of SSLObject.__init__(). In my opinion it's fine. A SSLObject is not a user-constructable object. SSLContext.wrap_bio() is the only valid factory. files: A Misc/NEWS.d/next/Library/2018-01-20-23-17-25.bpo-24334.GZuQLv.rst M Lib/ssl.py M Lib/test/test_ssl.py M Modules/_ssl.c M Modules/clinic/_ssl.c.h diff --git a/Lib/ssl.py b/Lib/ssl.py index ecdbb7076283..94ea35e358a3 100644 --- a/Lib/ssl.py +++ b/Lib/ssl.py @@ -166,10 +166,7 @@ socket_error = OSError # keep that public name in module namespace -if _ssl.HAS_TLS_UNIQUE: - CHANNEL_BINDING_TYPES = ['tls-unique'] -else: - CHANNEL_BINDING_TYPES = [] +CHANNEL_BINDING_TYPES = ['tls-unique'] HAS_NEVER_CHECK_COMMON_NAME = hasattr(_ssl, 'HOSTFLAG_NEVER_CHECK_SUBJECT') @@ -407,11 +404,11 @@ def wrap_bio(self, incoming, outgoing, server_side=False, server_hostname=None, session=None): # Need to encode server_hostname here because _wrap_bio() can only # handle ASCII str. - sslobj = self._wrap_bio( + return self.sslobject_class( incoming, outgoing, server_side=server_side, - server_hostname=self._encode_hostname(server_hostname) + server_hostname=self._encode_hostname(server_hostname), + session=session, _context=self, ) - return self.sslobject_class(sslobj, session=session) def set_npn_protocols(self, npn_protocols): protos = bytearray() @@ -616,12 +613,13 @@ class SSLObject: * The ``do_handshake_on_connect`` and ``suppress_ragged_eofs`` machinery. """ - def __init__(self, sslobj, owner=None, session=None): - self._sslobj = sslobj - # Note: _sslobj takes a weak reference to owner - self._sslobj.owner = owner or self - if session is not None: - self._sslobj.session = session + def __init__(self, incoming, outgoing, server_side=False, + server_hostname=None, session=None, _context=None): + self._sslobj = _context._wrap_bio( + incoming, outgoing, server_side=server_side, + server_hostname=server_hostname, + owner=self, session=session + ) @property def context(self): @@ -684,7 +682,7 @@ def getpeercert(self, binary_form=False): Return None if no certificate was provided, {} if a certificate was provided, but not validated. """ - return self._sslobj.peer_certificate(binary_form) + return self._sslobj.getpeercert(binary_form) def selected_npn_protocol(self): """Return the currently selected NPN protocol as a string, or ``None`` @@ -732,13 +730,7 @@ def get_channel_binding(self, cb_type="tls-unique"): """Get channel binding data for current connection. Raise ValueError if the requested `cb_type` is not supported. Return bytes of the data or None if the data is not available (e.g. before the handshake).""" - if cb_type not in CHANNEL_BINDING_TYPES: - raise ValueError("Unsupported channel binding type") - if cb_type != "tls-unique": - raise NotImplementedError( - "{0} channel binding type not implemented" - .format(cb_type)) - return self._sslobj.tls_unique_cb() + return self._sslobj.get_channel_binding(cb_type) def version(self): """Return a string identifying the protocol version used by the @@ -832,10 +824,10 @@ def __init__(self, sock=None, keyfile=None, certfile=None, if connected: # create the SSL object try: - sslobj = self._context._wrap_socket(self, server_side, - self.server_hostname) - self._sslobj = SSLObject(sslobj, owner=self, - session=self._session) + self._sslobj = self._context._wrap_socket( + self, server_side, self.server_hostname, + owner=self, session=self._session, + ) if do_handshake_on_connect: timeout = self.gettimeout() if timeout == 0.0: @@ -895,10 +887,13 @@ def read(self, len=1024, buffer=None): Return zero-length string on EOF.""" self._checkClosed() - if not self._sslobj: + if self._sslobj is None: raise ValueError("Read on closed or unwrapped SSL socket.") try: - return self._sslobj.read(len, buffer) + if buffer is not None: + return self._sslobj.read(len, buffer) + else: + return self._sslobj.read(len) except SSLError as x: if x.args[0] == SSL_ERROR_EOF and self.suppress_ragged_eofs: if buffer is not None: @@ -913,7 +908,7 @@ def write(self, data): number of bytes of DATA actually transmitted.""" self._checkClosed() - if not self._sslobj: + if self._sslobj is None: raise ValueError("Write on closed or unwrapped SSL socket.") return self._sslobj.write(data) @@ -929,41 +924,42 @@ def getpeercert(self, binary_form=False): def selected_npn_protocol(self): self._checkClosed() - if not self._sslobj or not _ssl.HAS_NPN: + if self._sslobj is None or not _ssl.HAS_NPN: return None else: return self._sslobj.selected_npn_protocol() def selected_alpn_protocol(self): self._checkClosed() - if not self._sslobj or not _ssl.HAS_ALPN: + if self._sslobj is None or not _ssl.HAS_ALPN: return None else: return self._sslobj.selected_alpn_protocol() def cipher(self): self._checkClosed() - if not self._sslobj: + if self._sslobj is None: return None else: return self._sslobj.cipher() def shared_ciphers(self): self._checkClosed() - if not self._sslobj: + if self._sslobj is None: return None - return self._sslobj.shared_ciphers() + else: + return self._sslobj.shared_ciphers() def compression(self): self._checkClosed() - if not self._sslobj: + if self._sslobj is None: return None else: return self._sslobj.compression() def send(self, data, flags=0): self._checkClosed() - if self._sslobj: + if self._sslobj is not None: if flags != 0: raise ValueError( "non-zero flags not allowed in calls to send() on %s" % @@ -974,7 +970,7 @@ def send(self, data, flags=0): def sendto(self, data, flags_or_addr, addr=None): self._checkClosed() - if self._sslobj: + if self._sslobj is not None: raise ValueError("sendto not allowed on instances of %s" % self.__class__) elif addr is None: @@ -990,7 +986,7 @@ def sendmsg(self, *args, **kwargs): def sendall(self, data, flags=0): self._checkClosed() - if self._sslobj: + if self._sslobj is not None: if flags != 0: raise ValueError( "non-zero flags not allowed in calls to sendall() on %s" % @@ -1008,15 +1004,15 @@ def sendfile(self, file, offset=0, count=None): """Send a file, possibly by using os.sendfile() if this is a clear-text socket. Return the total number of bytes sent. """ - if self._sslobj is None: + if self._sslobj is not None: + return self._sendfile_use_send(file, offset, count) + else: # os.sendfile() works with plain sockets only return super().sendfile(file, offset, count) - else: - return self._sendfile_use_send(file, offset, count) def recv(self, buflen=1024, flags=0): self._checkClosed() - if self._sslobj: + if self._sslobj is not None: if flags != 0: raise ValueError( "non-zero flags not allowed in calls to recv() on %s" % @@ -1031,7 +1027,7 @@ def recv_into(self, buffer, nbytes=None, flags=0): nbytes = len(buffer) elif nbytes is None: nbytes = 1024 - if self._sslobj: + if self._sslobj is not None: if flags != 0: raise ValueError( "non-zero flags not allowed in calls to recv_into() on %s" % @@ -1042,7 +1038,7 @@ def recv_into(self, buffer, nbytes=None, flags=0): def recvfrom(self, buflen=1024, flags=0): self._checkClosed() - if self._sslobj: + if self._sslobj is not None: raise ValueError("recvfrom not allowed on instances of %s" % self.__class__) else: @@ -1050,7 +1046,7 @@ def recvfrom(self, buflen=1024, flags=0): def recvfrom_into(self, buffer, nbytes=None, flags=0): self._checkClosed() - if self._sslobj: + if self._sslobj is not None: raise ValueError("recvfrom_into not allowed on instances of %s" % self.__class__) else: @@ -1066,7 +1062,7 @@ def recvmsg_into(self, *args, **kwargs): def pending(self): self._checkClosed() - if self._sslobj: + if self._sslobj is not None: return self._sslobj.pending() else: return 0 @@ -1078,7 +1074,7 @@ def shutdown(self, how): def unwrap(self): if self._sslobj: - s = self._sslobj.unwrap() + s = self._sslobj.shutdown() self._sslobj = None return s else: @@ -1096,6 +1092,11 @@ def do_handshake(self, block=False): if timeout == 0.0 and block: self.settimeout(None) self._sslobj.do_handshake() + if self.context.check_hostname: + if not self.server_hostname: + raise ValueError("check_hostname needs server_hostname " + "argument") + match_hostname(self.getpeercert(), self.server_hostname) finally: self.settimeout(timeout) @@ -1104,11 +1105,12 @@ def _real_connect(self, addr, connect_ex): raise ValueError("can't connect in server-side mode") # Here we assume that the socket is client-side, and not # connected at the time of the call. We connect it, then wrap it. - if self._connected: + if self._connected or self._sslobj is not None: raise ValueError("attempt to connect already-connected SSLSocket!") - sslobj = self.context._wrap_socket(self, False, self.server_hostname) - self._sslobj = SSLObject(sslobj, owner=self, - session=self._session) + self._sslobj = self.context._wrap_socket( + self, False, self.server_hostname, + owner=self, session=self._session + ) try: if connect_ex: rc = super().connect_ex(addr) @@ -1151,18 +1153,24 @@ def get_channel_binding(self, cb_type="tls-unique"): if the requested `cb_type` is not supported. Return bytes of the data or None if the data is not available (e.g. before the handshake). """ - if self._sslobj is None: + if self._sslobj is not None: + return self._sslobj.get_channel_binding(cb_type) + else: + if cb_type not in CHANNEL_BINDING_TYPES: + raise ValueError( + "{0} channel binding type not implemented".format(cb_type) + ) return None - return self._sslobj.get_channel_binding(cb_type) def version(self): """ Return a string identifying the protocol version used by the current SSL channel, or None if there is no established channel. """ - if self._sslobj is None: + if self._sslobj is not None: + return self._sslobj.version() + else: return None - return self._sslobj.version() # Python does not support forward declaration of types. diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 7aa112335cdb..3f2c50b7795a 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -455,6 +455,8 @@ def test_wrapped_unconnected(self): self.assertRaises(OSError, ss.recvfrom_into, bytearray(b'x'), 1) self.assertRaises(OSError, ss.send, b'x') self.assertRaises(OSError, ss.sendto, b'x', ('0.0.0.0', 0)) + self.assertRaises(NotImplementedError, ss.sendmsg, + [b'x'], (), 0, ('0.0.0.0', 0)) def test_timeout(self): # Issue #8524: when creating an SSL socket, the timeout of the @@ -3381,11 +3383,13 @@ def test_version_basic(self): chatty=False) as server: with context.wrap_socket(socket.socket()) as s: self.assertIs(s.version(), None) + self.assertIs(s._sslobj, None) s.connect((HOST, server.port)) if ssl.OPENSSL_VERSION_INFO >= (1, 0, 2): self.assertEqual(s.version(), 'TLSv1.2') else: # 0.9.8 to 1.0.1 self.assertIn(s.version(), ('TLSv1', 'TLSv1.2')) + self.assertIs(s._sslobj, None) self.assertIs(s.version(), None) @unittest.skipUnless(ssl.HAS_TLSv1_3, diff --git a/Misc/NEWS.d/next/Library/2018-01-20-23-17-25.bpo-24334.GZuQLv.rst b/Misc/NEWS.d/next/Library/2018-01-20-23-17-25.bpo-24334.GZuQLv.rst new file mode 100644 index 000000000000..2b4877fad7e1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-01-20-23-17-25.bpo-24334.GZuQLv.rst @@ -0,0 +1,4 @@ +Internal implementation details of ssl module were cleaned up. The SSLSocket +has one less layer of indirection. Owner and session information are now +handled by the SSLSocket and SSLObject constructor. Channel binding +implementation has been simplified. diff --git a/Modules/_ssl.c b/Modules/_ssl.c index a0f8c1cb3244..2136cbdeae47 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -408,6 +408,8 @@ class _ssl.SSLSession "PySSLSession *" "&PySSLSession_Type" static int PySSL_select(PySocketSockObject *s, int writing, _PyTime_t timeout); +static int PySSL_set_owner(PySSLSocket *, PyObject *, void *); +static int PySSL_set_session(PySSLSocket *, PyObject *, void *); #define PySSLSocket_Check(v) (Py_TYPE(v) == &PySSLSocket_Type) #define PySSLMemoryBIO_Check(v) (Py_TYPE(v) == &PySSLMemoryBIO_Type) #define PySSLSession_Check(v) (Py_TYPE(v) == &PySSLSession_Type) @@ -799,6 +801,7 @@ static PySSLSocket * newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock, enum py_ssl_server_or_client socket_type, char *server_hostname, + PyObject *owner, PyObject *session, PySSLMemoryBIO *inbio, PySSLMemoryBIO *outbio) { PySSLSocket *self; @@ -875,6 +878,18 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock, return NULL; } } + if (owner && owner != Py_None) { + if (PySSL_set_owner(self, owner, NULL) == -1) { + Py_DECREF(self); + return NULL; + } + } + if (session && session != Py_None) { + if (PySSL_set_session(self, session, NULL) == -1) { + Py_DECREF(self); + return NULL; + } + } return self; } @@ -1677,7 +1692,7 @@ _ssl__test_decode_cert_impl(PyObject *module, PyObject *path) /*[clinic input] -_ssl._SSLSocket.peer_certificate +_ssl._SSLSocket.getpeercert der as binary_mode: bool = False / @@ -1693,8 +1708,8 @@ return the certificate even if it wasn't validated. [clinic start generated code]*/ static PyObject * -_ssl__SSLSocket_peer_certificate_impl(PySSLSocket *self, int binary_mode) -/*[clinic end generated code: output=f0dc3e4d1d818a1d input=8281bd1d193db843]*/ +_ssl__SSLSocket_getpeercert_impl(PySSLSocket *self, int binary_mode) +/*[clinic end generated code: output=1f0ab66dfb693c88 input=c0fbe802e57629b7]*/ { int verification; X509 *peer_cert; @@ -2395,13 +2410,11 @@ _ssl__SSLSocket_read_impl(PySSLSocket *self, int len, int group_right_1, _ssl._SSLSocket.shutdown Does the SSL shutdown handshake with the remote end. - -Returns the underlying socket object. [clinic start generated code]*/ static PyObject * _ssl__SSLSocket_shutdown_impl(PySSLSocket *self) -/*[clinic end generated code: output=ca1aa7ed9d25ca42 input=ede2cc1a2ddf0ee4]*/ +/*[clinic end generated code: output=ca1aa7ed9d25ca42 input=11d39e69b0a2bf4a]*/ { int err, sockstate, nonblocking; int zeros = 0; @@ -2506,37 +2519,48 @@ _ssl__SSLSocket_shutdown_impl(PySSLSocket *self) } /*[clinic input] -_ssl._SSLSocket.tls_unique_cb +_ssl._SSLSocket.get_channel_binding + cb_type: str = "tls-unique" -Returns the 'tls-unique' channel binding data, as defined by RFC 5929. +Get channel binding data for current connection. -If the TLS handshake is not yet complete, None is returned. +Raise ValueError if the requested `cb_type` is not supported. Return bytes +of the data or None if the data is not available (e.g. before the handshake). +Only 'tls-unique' channel binding data from RFC 5929 is supported. [clinic start generated code]*/ static PyObject * -_ssl__SSLSocket_tls_unique_cb_impl(PySSLSocket *self) -/*[clinic end generated code: output=f3a832d603f586af input=439525c7b3d8d34d]*/ +_ssl__SSLSocket_get_channel_binding_impl(PySSLSocket *self, + const char *cb_type) +/*[clinic end generated code: output=34bac9acb6a61d31 input=08b7e43b99c17d41]*/ { - PyObject *retval = NULL; char buf[PySSL_CB_MAXLEN]; size_t len; - if (SSL_session_reused(self->ssl) ^ !self->socket_type) { - /* if session is resumed XOR we are the client */ - len = SSL_get_finished(self->ssl, buf, PySSL_CB_MAXLEN); + if (strcmp(cb_type, "tls-unique") == 0) { + if (SSL_session_reused(self->ssl) ^ !self->socket_type) { + /* if session is resumed XOR we are the client */ + len = SSL_get_finished(self->ssl, buf, PySSL_CB_MAXLEN); + } + else { + /* if a new session XOR we are the server */ + len = SSL_get_peer_finished(self->ssl, buf, PySSL_CB_MAXLEN); + } } else { - /* if a new session XOR we are the server */ - len = SSL_get_peer_finished(self->ssl, buf, PySSL_CB_MAXLEN); + PyErr_Format( + PyExc_ValueError, + "'%s' channel binding type not implemented", + cb_type + ); + return NULL; } /* It cannot be negative in current OpenSSL version as of July 2011 */ if (len == 0) Py_RETURN_NONE; - retval = PyBytes_FromStringAndSize(buf, len); - - return retval; + return PyBytes_FromStringAndSize(buf, len); } #ifdef OPENSSL_VERSION_1_1 @@ -2706,7 +2730,8 @@ static PyMethodDef PySSLMethods[] = { _SSL__SSLSOCKET_WRITE_METHODDEF _SSL__SSLSOCKET_READ_METHODDEF _SSL__SSLSOCKET_PENDING_METHODDEF - _SSL__SSLSOCKET_PEER_CERTIFICATE_METHODDEF + _SSL__SSLSOCKET_GETPEERCERT_METHODDEF + _SSL__SSLSOCKET_GET_CHANNEL_BINDING_METHODDEF _SSL__SSLSOCKET_CIPHER_METHODDEF _SSL__SSLSOCKET_SHARED_CIPHERS_METHODDEF _SSL__SSLSOCKET_VERSION_METHODDEF @@ -2714,7 +2739,6 @@ static PyMethodDef PySSLMethods[] = { _SSL__SSLSOCKET_SELECTED_ALPN_PROTOCOL_METHODDEF _SSL__SSLSOCKET_COMPRESSION_METHODDEF _SSL__SSLSOCKET_SHUTDOWN_METHODDEF - _SSL__SSLSOCKET_TLS_UNIQUE_CB_METHODDEF {NULL, NULL} }; @@ -3810,13 +3834,17 @@ _ssl._SSLContext._wrap_socket sock: object(subclass_of="PySocketModule.Sock_Type") server_side: int server_hostname as hostname_obj: object = None + * + owner: object = None + session: object = None [clinic start generated code]*/ static PyObject * _ssl__SSLContext__wrap_socket_impl(PySSLContext *self, PyObject *sock, - int server_side, PyObject *hostname_obj) -/*[clinic end generated code: output=6973e4b60995e933 input=83859b9156ddfc63]*/ + int server_side, PyObject *hostname_obj, + PyObject *owner, PyObject *session) +/*[clinic end generated code: output=f103f238633940b4 input=957d5006183d1894]*/ { char *hostname = NULL; PyObject *res; @@ -3830,6 +3858,7 @@ _ssl__SSLContext__wrap_socket_impl(PySSLContext *self, PyObject *sock, res = (PyObject *) newPySSLSocket(self, (PySocketSockObject *)sock, server_side, hostname, + owner, session, NULL, NULL); if (hostname != NULL) PyMem_Free(hostname); @@ -3842,14 +3871,18 @@ _ssl._SSLContext._wrap_bio outgoing: object(subclass_of="&PySSLMemoryBIO_Type", type="PySSLMemoryBIO *") server_side: int server_hostname as hostname_obj: object = None + * + owner: object = None + session: object = None [clinic start generated code]*/ static PyObject * _ssl__SSLContext__wrap_bio_impl(PySSLContext *self, PySSLMemoryBIO *incoming, PySSLMemoryBIO *outgoing, int server_side, - PyObject *hostname_obj) -/*[clinic end generated code: output=4fe4ba75ad95940d input=17725ecdac0bf220]*/ + PyObject *hostname_obj, PyObject *owner, + PyObject *session) +/*[clinic end generated code: output=5c5d6d9b41f99332 input=8cf22f4d586ac56a]*/ { char *hostname = NULL; PyObject *res; @@ -3862,6 +3895,7 @@ _ssl__SSLContext__wrap_bio_impl(PySSLContext *self, PySSLMemoryBIO *incoming, } res = (PyObject *) newPySSLSocket(self, NULL, server_side, hostname, + owner, session, incoming, outgoing); PyMem_Free(hostname); @@ -5663,10 +5697,6 @@ PyInit__ssl(void) Py_INCREF(r); PyModule_AddObject(m, "HAS_SNI", r); - r = Py_True; - Py_INCREF(r); - PyModule_AddObject(m, "HAS_TLS_UNIQUE", r); - #ifdef OPENSSL_NO_ECDH r = Py_False; #else diff --git a/Modules/clinic/_ssl.c.h b/Modules/clinic/_ssl.c.h index d1a9afcd1d1e..5b6c4af11fb7 100644 --- a/Modules/clinic/_ssl.c.h +++ b/Modules/clinic/_ssl.c.h @@ -45,8 +45,8 @@ _ssl__test_decode_cert(PyObject *module, PyObject *arg) return return_value; } -PyDoc_STRVAR(_ssl__SSLSocket_peer_certificate__doc__, -"peer_certificate($self, der=False, /)\n" +PyDoc_STRVAR(_ssl__SSLSocket_getpeercert__doc__, +"getpeercert($self, der=False, /)\n" "--\n" "\n" "Returns the certificate for the peer.\n" @@ -59,23 +59,23 @@ PyDoc_STRVAR(_ssl__SSLSocket_peer_certificate__doc__, "peer certificate, or None if no certificate was provided. This will\n" "return the certificate even if it wasn\'t validated."); -#define _SSL__SSLSOCKET_PEER_CERTIFICATE_METHODDEF \ - {"peer_certificate", (PyCFunction)_ssl__SSLSocket_peer_certificate, METH_FASTCALL, _ssl__SSLSocket_peer_certificate__doc__}, +#define _SSL__SSLSOCKET_GETPEERCERT_METHODDEF \ + {"getpeercert", (PyCFunction)_ssl__SSLSocket_getpeercert, METH_FASTCALL, _ssl__SSLSocket_getpeercert__doc__}, static PyObject * -_ssl__SSLSocket_peer_certificate_impl(PySSLSocket *self, int binary_mode); +_ssl__SSLSocket_getpeercert_impl(PySSLSocket *self, int binary_mode); static PyObject * -_ssl__SSLSocket_peer_certificate(PySSLSocket *self, PyObject *const *args, Py_ssize_t nargs) +_ssl__SSLSocket_getpeercert(PySSLSocket *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int binary_mode = 0; - if (!_PyArg_ParseStack(args, nargs, "|p:peer_certificate", + if (!_PyArg_ParseStack(args, nargs, "|p:getpeercert", &binary_mode)) { goto exit; } - return_value = _ssl__SSLSocket_peer_certificate_impl(self, binary_mode); + return_value = _ssl__SSLSocket_getpeercert_impl(self, binary_mode); exit: return return_value; @@ -293,9 +293,7 @@ PyDoc_STRVAR(_ssl__SSLSocket_shutdown__doc__, "shutdown($self, /)\n" "--\n" "\n" -"Does the SSL shutdown handshake with the remote end.\n" -"\n" -"Returns the underlying socket object."); +"Does the SSL shutdown handshake with the remote end."); #define _SSL__SSLSOCKET_SHUTDOWN_METHODDEF \ {"shutdown", (PyCFunction)_ssl__SSLSocket_shutdown, METH_NOARGS, _ssl__SSLSocket_shutdown__doc__}, @@ -309,24 +307,39 @@ _ssl__SSLSocket_shutdown(PySSLSocket *self, PyObject *Py_UNUSED(ignored)) return _ssl__SSLSocket_shutdown_impl(self); } -PyDoc_STRVAR(_ssl__SSLSocket_tls_unique_cb__doc__, -"tls_unique_cb($self, /)\n" +PyDoc_STRVAR(_ssl__SSLSocket_get_channel_binding__doc__, +"get_channel_binding($self, /, cb_type=\'tls-unique\')\n" "--\n" "\n" -"Returns the \'tls-unique\' channel binding data, as defined by RFC 5929.\n" +"Get channel binding data for current connection.\n" "\n" -"If the TLS handshake is not yet complete, None is returned."); +"Raise ValueError if the requested `cb_type` is not supported. Return bytes\n" +"of the data or None if the data is not available (e.g. before the handshake).\n" +"Only \'tls-unique\' channel binding data from RFC 5929 is supported."); -#define _SSL__SSLSOCKET_TLS_UNIQUE_CB_METHODDEF \ - {"tls_unique_cb", (PyCFunction)_ssl__SSLSocket_tls_unique_cb, METH_NOARGS, _ssl__SSLSocket_tls_unique_cb__doc__}, +#define _SSL__SSLSOCKET_GET_CHANNEL_BINDING_METHODDEF \ + {"get_channel_binding", (PyCFunction)_ssl__SSLSocket_get_channel_binding, METH_FASTCALL|METH_KEYWORDS, _ssl__SSLSocket_get_channel_binding__doc__}, static PyObject * -_ssl__SSLSocket_tls_unique_cb_impl(PySSLSocket *self); +_ssl__SSLSocket_get_channel_binding_impl(PySSLSocket *self, + const char *cb_type); static PyObject * -_ssl__SSLSocket_tls_unique_cb(PySSLSocket *self, PyObject *Py_UNUSED(ignored)) +_ssl__SSLSocket_get_channel_binding(PySSLSocket *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { - return _ssl__SSLSocket_tls_unique_cb_impl(self); + PyObject *return_value = NULL; + static const char * const _keywords[] = {"cb_type", NULL}; + static _PyArg_Parser _parser = {"|s:get_channel_binding", _keywords, 0}; + const char *cb_type = "tls-unique"; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &cb_type)) { + goto exit; + } + return_value = _ssl__SSLSocket_get_channel_binding_impl(self, cb_type); + +exit: + return return_value; } static PyObject * @@ -538,7 +551,8 @@ PyDoc_STRVAR(_ssl__SSLContext_load_dh_params__doc__, {"load_dh_params", (PyCFunction)_ssl__SSLContext_load_dh_params, METH_O, _ssl__SSLContext_load_dh_params__doc__}, PyDoc_STRVAR(_ssl__SSLContext__wrap_socket__doc__, -"_wrap_socket($self, /, sock, server_side, server_hostname=None)\n" +"_wrap_socket($self, /, sock, server_side, server_hostname=None, *,\n" +" owner=None, session=None)\n" "--\n" "\n"); @@ -547,23 +561,26 @@ PyDoc_STRVAR(_ssl__SSLContext__wrap_socket__doc__, static PyObject * _ssl__SSLContext__wrap_socket_impl(PySSLContext *self, PyObject *sock, - int server_side, PyObject *hostname_obj); + int server_side, PyObject *hostname_obj, + PyObject *owner, PyObject *session); static PyObject * _ssl__SSLContext__wrap_socket(PySSLContext *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; - static const char * const _keywords[] = {"sock", "server_side", "server_hostname", NULL}; - static _PyArg_Parser _parser = {"O!i|O:_wrap_socket", _keywords, 0}; + static const char * const _keywords[] = {"sock", "server_side", "server_hostname", "owner", "session", NULL}; + static _PyArg_Parser _parser = {"O!i|O$OO:_wrap_socket", _keywords, 0}; PyObject *sock; int server_side; PyObject *hostname_obj = Py_None; + PyObject *owner = Py_None; + PyObject *session = Py_None; if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, - PySocketModule.Sock_Type, &sock, &server_side, &hostname_obj)) { + PySocketModule.Sock_Type, &sock, &server_side, &hostname_obj, &owner, &session)) { goto exit; } - return_value = _ssl__SSLContext__wrap_socket_impl(self, sock, server_side, hostname_obj); + return_value = _ssl__SSLContext__wrap_socket_impl(self, sock, server_side, hostname_obj, owner, session); exit: return return_value; @@ -571,7 +588,7 @@ _ssl__SSLContext__wrap_socket(PySSLContext *self, PyObject *const *args, Py_ssiz PyDoc_STRVAR(_ssl__SSLContext__wrap_bio__doc__, "_wrap_bio($self, /, incoming, outgoing, server_side,\n" -" server_hostname=None)\n" +" server_hostname=None, *, owner=None, session=None)\n" "--\n" "\n"); @@ -581,24 +598,27 @@ PyDoc_STRVAR(_ssl__SSLContext__wrap_bio__doc__, static PyObject * _ssl__SSLContext__wrap_bio_impl(PySSLContext *self, PySSLMemoryBIO *incoming, PySSLMemoryBIO *outgoing, int server_side, - PyObject *hostname_obj); + PyObject *hostname_obj, PyObject *owner, + PyObject *session); static PyObject * _ssl__SSLContext__wrap_bio(PySSLContext *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; - static const char * const _keywords[] = {"incoming", "outgoing", "server_side", "server_hostname", NULL}; - static _PyArg_Parser _parser = {"O!O!i|O:_wrap_bio", _keywords, 0}; + static const char * const _keywords[] = {"incoming", "outgoing", "server_side", "server_hostname", "owner", "session", NULL}; + static _PyArg_Parser _parser = {"O!O!i|O$OO:_wrap_bio", _keywords, 0}; PySSLMemoryBIO *incoming; PySSLMemoryBIO *outgoing; int server_side; PyObject *hostname_obj = Py_None; + PyObject *owner = Py_None; + PyObject *session = Py_None; if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, - &PySSLMemoryBIO_Type, &incoming, &PySSLMemoryBIO_Type, &outgoing, &server_side, &hostname_obj)) { + &PySSLMemoryBIO_Type, &incoming, &PySSLMemoryBIO_Type, &outgoing, &server_side, &hostname_obj, &owner, &session)) { goto exit; } - return_value = _ssl__SSLContext__wrap_bio_impl(self, incoming, outgoing, server_side, hostname_obj); + return_value = _ssl__SSLContext__wrap_bio_impl(self, incoming, outgoing, server_side, hostname_obj, owner, session); exit: return return_value; @@ -1155,4 +1175,4 @@ _ssl_enum_crls(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje #ifndef _SSL_ENUM_CRLS_METHODDEF #define _SSL_ENUM_CRLS_METHODDEF #endif /* !defined(_SSL_ENUM_CRLS_METHODDEF) */ -/*[clinic end generated code: output=84e1fd89aff9b0f7 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d987411caeb106e7 input=a9049054013a1b77]*/ From webhook-mailer at python.org Sat Feb 24 15:51:59 2018 From: webhook-mailer at python.org (Christian Heimes) Date: Sat, 24 Feb 2018 20:51:59 -0000 Subject: [Python-checkins] [3.7] bpo-24334: Cleanup SSLSocket (GH-5252) (#5857) Message-ID: https://github.com/python/cpython/commit/8fa8478ddeba0870da1152f0a2985c8a7eeb9fd1 commit: 8fa8478ddeba0870da1152f0a2985c8a7eeb9fd1 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Christian Heimes date: 2018-02-24T21:51:56+01:00 summary: [3.7] bpo-24334: Cleanup SSLSocket (GH-5252) (#5857) * The SSLSocket is no longer implemented on top of SSLObject to avoid an extra level of indirection. * Owner and session are now handled in the internal constructor. * _ssl._SSLSocket now uses the same method names as SSLSocket and SSLObject. * Channel binding type check is now handled in C code. Channel binding is always available. The patch also changes the signature of SSLObject.__init__(). In my opinion it's fine. A SSLObject is not a user-constructable object. SSLContext.wrap_bio() is the only valid factory. (cherry picked from commit 141c5e8c2437a9fed95a04c81e400ef725592a17) Co-authored-by: Christian Heimes files: A Misc/NEWS.d/next/Library/2018-01-20-23-17-25.bpo-24334.GZuQLv.rst M Lib/ssl.py M Lib/test/test_ssl.py M Modules/_ssl.c M Modules/clinic/_ssl.c.h diff --git a/Lib/ssl.py b/Lib/ssl.py index ecdbb7076283..94ea35e358a3 100644 --- a/Lib/ssl.py +++ b/Lib/ssl.py @@ -166,10 +166,7 @@ socket_error = OSError # keep that public name in module namespace -if _ssl.HAS_TLS_UNIQUE: - CHANNEL_BINDING_TYPES = ['tls-unique'] -else: - CHANNEL_BINDING_TYPES = [] +CHANNEL_BINDING_TYPES = ['tls-unique'] HAS_NEVER_CHECK_COMMON_NAME = hasattr(_ssl, 'HOSTFLAG_NEVER_CHECK_SUBJECT') @@ -407,11 +404,11 @@ def wrap_bio(self, incoming, outgoing, server_side=False, server_hostname=None, session=None): # Need to encode server_hostname here because _wrap_bio() can only # handle ASCII str. - sslobj = self._wrap_bio( + return self.sslobject_class( incoming, outgoing, server_side=server_side, - server_hostname=self._encode_hostname(server_hostname) + server_hostname=self._encode_hostname(server_hostname), + session=session, _context=self, ) - return self.sslobject_class(sslobj, session=session) def set_npn_protocols(self, npn_protocols): protos = bytearray() @@ -616,12 +613,13 @@ class SSLObject: * The ``do_handshake_on_connect`` and ``suppress_ragged_eofs`` machinery. """ - def __init__(self, sslobj, owner=None, session=None): - self._sslobj = sslobj - # Note: _sslobj takes a weak reference to owner - self._sslobj.owner = owner or self - if session is not None: - self._sslobj.session = session + def __init__(self, incoming, outgoing, server_side=False, + server_hostname=None, session=None, _context=None): + self._sslobj = _context._wrap_bio( + incoming, outgoing, server_side=server_side, + server_hostname=server_hostname, + owner=self, session=session + ) @property def context(self): @@ -684,7 +682,7 @@ def getpeercert(self, binary_form=False): Return None if no certificate was provided, {} if a certificate was provided, but not validated. """ - return self._sslobj.peer_certificate(binary_form) + return self._sslobj.getpeercert(binary_form) def selected_npn_protocol(self): """Return the currently selected NPN protocol as a string, or ``None`` @@ -732,13 +730,7 @@ def get_channel_binding(self, cb_type="tls-unique"): """Get channel binding data for current connection. Raise ValueError if the requested `cb_type` is not supported. Return bytes of the data or None if the data is not available (e.g. before the handshake).""" - if cb_type not in CHANNEL_BINDING_TYPES: - raise ValueError("Unsupported channel binding type") - if cb_type != "tls-unique": - raise NotImplementedError( - "{0} channel binding type not implemented" - .format(cb_type)) - return self._sslobj.tls_unique_cb() + return self._sslobj.get_channel_binding(cb_type) def version(self): """Return a string identifying the protocol version used by the @@ -832,10 +824,10 @@ def __init__(self, sock=None, keyfile=None, certfile=None, if connected: # create the SSL object try: - sslobj = self._context._wrap_socket(self, server_side, - self.server_hostname) - self._sslobj = SSLObject(sslobj, owner=self, - session=self._session) + self._sslobj = self._context._wrap_socket( + self, server_side, self.server_hostname, + owner=self, session=self._session, + ) if do_handshake_on_connect: timeout = self.gettimeout() if timeout == 0.0: @@ -895,10 +887,13 @@ def read(self, len=1024, buffer=None): Return zero-length string on EOF.""" self._checkClosed() - if not self._sslobj: + if self._sslobj is None: raise ValueError("Read on closed or unwrapped SSL socket.") try: - return self._sslobj.read(len, buffer) + if buffer is not None: + return self._sslobj.read(len, buffer) + else: + return self._sslobj.read(len) except SSLError as x: if x.args[0] == SSL_ERROR_EOF and self.suppress_ragged_eofs: if buffer is not None: @@ -913,7 +908,7 @@ def write(self, data): number of bytes of DATA actually transmitted.""" self._checkClosed() - if not self._sslobj: + if self._sslobj is None: raise ValueError("Write on closed or unwrapped SSL socket.") return self._sslobj.write(data) @@ -929,41 +924,42 @@ def getpeercert(self, binary_form=False): def selected_npn_protocol(self): self._checkClosed() - if not self._sslobj or not _ssl.HAS_NPN: + if self._sslobj is None or not _ssl.HAS_NPN: return None else: return self._sslobj.selected_npn_protocol() def selected_alpn_protocol(self): self._checkClosed() - if not self._sslobj or not _ssl.HAS_ALPN: + if self._sslobj is None or not _ssl.HAS_ALPN: return None else: return self._sslobj.selected_alpn_protocol() def cipher(self): self._checkClosed() - if not self._sslobj: + if self._sslobj is None: return None else: return self._sslobj.cipher() def shared_ciphers(self): self._checkClosed() - if not self._sslobj: + if self._sslobj is None: return None - return self._sslobj.shared_ciphers() + else: + return self._sslobj.shared_ciphers() def compression(self): self._checkClosed() - if not self._sslobj: + if self._sslobj is None: return None else: return self._sslobj.compression() def send(self, data, flags=0): self._checkClosed() - if self._sslobj: + if self._sslobj is not None: if flags != 0: raise ValueError( "non-zero flags not allowed in calls to send() on %s" % @@ -974,7 +970,7 @@ def send(self, data, flags=0): def sendto(self, data, flags_or_addr, addr=None): self._checkClosed() - if self._sslobj: + if self._sslobj is not None: raise ValueError("sendto not allowed on instances of %s" % self.__class__) elif addr is None: @@ -990,7 +986,7 @@ def sendmsg(self, *args, **kwargs): def sendall(self, data, flags=0): self._checkClosed() - if self._sslobj: + if self._sslobj is not None: if flags != 0: raise ValueError( "non-zero flags not allowed in calls to sendall() on %s" % @@ -1008,15 +1004,15 @@ def sendfile(self, file, offset=0, count=None): """Send a file, possibly by using os.sendfile() if this is a clear-text socket. Return the total number of bytes sent. """ - if self._sslobj is None: + if self._sslobj is not None: + return self._sendfile_use_send(file, offset, count) + else: # os.sendfile() works with plain sockets only return super().sendfile(file, offset, count) - else: - return self._sendfile_use_send(file, offset, count) def recv(self, buflen=1024, flags=0): self._checkClosed() - if self._sslobj: + if self._sslobj is not None: if flags != 0: raise ValueError( "non-zero flags not allowed in calls to recv() on %s" % @@ -1031,7 +1027,7 @@ def recv_into(self, buffer, nbytes=None, flags=0): nbytes = len(buffer) elif nbytes is None: nbytes = 1024 - if self._sslobj: + if self._sslobj is not None: if flags != 0: raise ValueError( "non-zero flags not allowed in calls to recv_into() on %s" % @@ -1042,7 +1038,7 @@ def recv_into(self, buffer, nbytes=None, flags=0): def recvfrom(self, buflen=1024, flags=0): self._checkClosed() - if self._sslobj: + if self._sslobj is not None: raise ValueError("recvfrom not allowed on instances of %s" % self.__class__) else: @@ -1050,7 +1046,7 @@ def recvfrom(self, buflen=1024, flags=0): def recvfrom_into(self, buffer, nbytes=None, flags=0): self._checkClosed() - if self._sslobj: + if self._sslobj is not None: raise ValueError("recvfrom_into not allowed on instances of %s" % self.__class__) else: @@ -1066,7 +1062,7 @@ def recvmsg_into(self, *args, **kwargs): def pending(self): self._checkClosed() - if self._sslobj: + if self._sslobj is not None: return self._sslobj.pending() else: return 0 @@ -1078,7 +1074,7 @@ def shutdown(self, how): def unwrap(self): if self._sslobj: - s = self._sslobj.unwrap() + s = self._sslobj.shutdown() self._sslobj = None return s else: @@ -1096,6 +1092,11 @@ def do_handshake(self, block=False): if timeout == 0.0 and block: self.settimeout(None) self._sslobj.do_handshake() + if self.context.check_hostname: + if not self.server_hostname: + raise ValueError("check_hostname needs server_hostname " + "argument") + match_hostname(self.getpeercert(), self.server_hostname) finally: self.settimeout(timeout) @@ -1104,11 +1105,12 @@ def _real_connect(self, addr, connect_ex): raise ValueError("can't connect in server-side mode") # Here we assume that the socket is client-side, and not # connected at the time of the call. We connect it, then wrap it. - if self._connected: + if self._connected or self._sslobj is not None: raise ValueError("attempt to connect already-connected SSLSocket!") - sslobj = self.context._wrap_socket(self, False, self.server_hostname) - self._sslobj = SSLObject(sslobj, owner=self, - session=self._session) + self._sslobj = self.context._wrap_socket( + self, False, self.server_hostname, + owner=self, session=self._session + ) try: if connect_ex: rc = super().connect_ex(addr) @@ -1151,18 +1153,24 @@ def get_channel_binding(self, cb_type="tls-unique"): if the requested `cb_type` is not supported. Return bytes of the data or None if the data is not available (e.g. before the handshake). """ - if self._sslobj is None: + if self._sslobj is not None: + return self._sslobj.get_channel_binding(cb_type) + else: + if cb_type not in CHANNEL_BINDING_TYPES: + raise ValueError( + "{0} channel binding type not implemented".format(cb_type) + ) return None - return self._sslobj.get_channel_binding(cb_type) def version(self): """ Return a string identifying the protocol version used by the current SSL channel, or None if there is no established channel. """ - if self._sslobj is None: + if self._sslobj is not None: + return self._sslobj.version() + else: return None - return self._sslobj.version() # Python does not support forward declaration of types. diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 7aa112335cdb..3f2c50b7795a 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -455,6 +455,8 @@ def test_wrapped_unconnected(self): self.assertRaises(OSError, ss.recvfrom_into, bytearray(b'x'), 1) self.assertRaises(OSError, ss.send, b'x') self.assertRaises(OSError, ss.sendto, b'x', ('0.0.0.0', 0)) + self.assertRaises(NotImplementedError, ss.sendmsg, + [b'x'], (), 0, ('0.0.0.0', 0)) def test_timeout(self): # Issue #8524: when creating an SSL socket, the timeout of the @@ -3381,11 +3383,13 @@ def test_version_basic(self): chatty=False) as server: with context.wrap_socket(socket.socket()) as s: self.assertIs(s.version(), None) + self.assertIs(s._sslobj, None) s.connect((HOST, server.port)) if ssl.OPENSSL_VERSION_INFO >= (1, 0, 2): self.assertEqual(s.version(), 'TLSv1.2') else: # 0.9.8 to 1.0.1 self.assertIn(s.version(), ('TLSv1', 'TLSv1.2')) + self.assertIs(s._sslobj, None) self.assertIs(s.version(), None) @unittest.skipUnless(ssl.HAS_TLSv1_3, diff --git a/Misc/NEWS.d/next/Library/2018-01-20-23-17-25.bpo-24334.GZuQLv.rst b/Misc/NEWS.d/next/Library/2018-01-20-23-17-25.bpo-24334.GZuQLv.rst new file mode 100644 index 000000000000..2b4877fad7e1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-01-20-23-17-25.bpo-24334.GZuQLv.rst @@ -0,0 +1,4 @@ +Internal implementation details of ssl module were cleaned up. The SSLSocket +has one less layer of indirection. Owner and session information are now +handled by the SSLSocket and SSLObject constructor. Channel binding +implementation has been simplified. diff --git a/Modules/_ssl.c b/Modules/_ssl.c index a0f8c1cb3244..2136cbdeae47 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -408,6 +408,8 @@ class _ssl.SSLSession "PySSLSession *" "&PySSLSession_Type" static int PySSL_select(PySocketSockObject *s, int writing, _PyTime_t timeout); +static int PySSL_set_owner(PySSLSocket *, PyObject *, void *); +static int PySSL_set_session(PySSLSocket *, PyObject *, void *); #define PySSLSocket_Check(v) (Py_TYPE(v) == &PySSLSocket_Type) #define PySSLMemoryBIO_Check(v) (Py_TYPE(v) == &PySSLMemoryBIO_Type) #define PySSLSession_Check(v) (Py_TYPE(v) == &PySSLSession_Type) @@ -799,6 +801,7 @@ static PySSLSocket * newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock, enum py_ssl_server_or_client socket_type, char *server_hostname, + PyObject *owner, PyObject *session, PySSLMemoryBIO *inbio, PySSLMemoryBIO *outbio) { PySSLSocket *self; @@ -875,6 +878,18 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock, return NULL; } } + if (owner && owner != Py_None) { + if (PySSL_set_owner(self, owner, NULL) == -1) { + Py_DECREF(self); + return NULL; + } + } + if (session && session != Py_None) { + if (PySSL_set_session(self, session, NULL) == -1) { + Py_DECREF(self); + return NULL; + } + } return self; } @@ -1677,7 +1692,7 @@ _ssl__test_decode_cert_impl(PyObject *module, PyObject *path) /*[clinic input] -_ssl._SSLSocket.peer_certificate +_ssl._SSLSocket.getpeercert der as binary_mode: bool = False / @@ -1693,8 +1708,8 @@ return the certificate even if it wasn't validated. [clinic start generated code]*/ static PyObject * -_ssl__SSLSocket_peer_certificate_impl(PySSLSocket *self, int binary_mode) -/*[clinic end generated code: output=f0dc3e4d1d818a1d input=8281bd1d193db843]*/ +_ssl__SSLSocket_getpeercert_impl(PySSLSocket *self, int binary_mode) +/*[clinic end generated code: output=1f0ab66dfb693c88 input=c0fbe802e57629b7]*/ { int verification; X509 *peer_cert; @@ -2395,13 +2410,11 @@ _ssl__SSLSocket_read_impl(PySSLSocket *self, int len, int group_right_1, _ssl._SSLSocket.shutdown Does the SSL shutdown handshake with the remote end. - -Returns the underlying socket object. [clinic start generated code]*/ static PyObject * _ssl__SSLSocket_shutdown_impl(PySSLSocket *self) -/*[clinic end generated code: output=ca1aa7ed9d25ca42 input=ede2cc1a2ddf0ee4]*/ +/*[clinic end generated code: output=ca1aa7ed9d25ca42 input=11d39e69b0a2bf4a]*/ { int err, sockstate, nonblocking; int zeros = 0; @@ -2506,37 +2519,48 @@ _ssl__SSLSocket_shutdown_impl(PySSLSocket *self) } /*[clinic input] -_ssl._SSLSocket.tls_unique_cb +_ssl._SSLSocket.get_channel_binding + cb_type: str = "tls-unique" -Returns the 'tls-unique' channel binding data, as defined by RFC 5929. +Get channel binding data for current connection. -If the TLS handshake is not yet complete, None is returned. +Raise ValueError if the requested `cb_type` is not supported. Return bytes +of the data or None if the data is not available (e.g. before the handshake). +Only 'tls-unique' channel binding data from RFC 5929 is supported. [clinic start generated code]*/ static PyObject * -_ssl__SSLSocket_tls_unique_cb_impl(PySSLSocket *self) -/*[clinic end generated code: output=f3a832d603f586af input=439525c7b3d8d34d]*/ +_ssl__SSLSocket_get_channel_binding_impl(PySSLSocket *self, + const char *cb_type) +/*[clinic end generated code: output=34bac9acb6a61d31 input=08b7e43b99c17d41]*/ { - PyObject *retval = NULL; char buf[PySSL_CB_MAXLEN]; size_t len; - if (SSL_session_reused(self->ssl) ^ !self->socket_type) { - /* if session is resumed XOR we are the client */ - len = SSL_get_finished(self->ssl, buf, PySSL_CB_MAXLEN); + if (strcmp(cb_type, "tls-unique") == 0) { + if (SSL_session_reused(self->ssl) ^ !self->socket_type) { + /* if session is resumed XOR we are the client */ + len = SSL_get_finished(self->ssl, buf, PySSL_CB_MAXLEN); + } + else { + /* if a new session XOR we are the server */ + len = SSL_get_peer_finished(self->ssl, buf, PySSL_CB_MAXLEN); + } } else { - /* if a new session XOR we are the server */ - len = SSL_get_peer_finished(self->ssl, buf, PySSL_CB_MAXLEN); + PyErr_Format( + PyExc_ValueError, + "'%s' channel binding type not implemented", + cb_type + ); + return NULL; } /* It cannot be negative in current OpenSSL version as of July 2011 */ if (len == 0) Py_RETURN_NONE; - retval = PyBytes_FromStringAndSize(buf, len); - - return retval; + return PyBytes_FromStringAndSize(buf, len); } #ifdef OPENSSL_VERSION_1_1 @@ -2706,7 +2730,8 @@ static PyMethodDef PySSLMethods[] = { _SSL__SSLSOCKET_WRITE_METHODDEF _SSL__SSLSOCKET_READ_METHODDEF _SSL__SSLSOCKET_PENDING_METHODDEF - _SSL__SSLSOCKET_PEER_CERTIFICATE_METHODDEF + _SSL__SSLSOCKET_GETPEERCERT_METHODDEF + _SSL__SSLSOCKET_GET_CHANNEL_BINDING_METHODDEF _SSL__SSLSOCKET_CIPHER_METHODDEF _SSL__SSLSOCKET_SHARED_CIPHERS_METHODDEF _SSL__SSLSOCKET_VERSION_METHODDEF @@ -2714,7 +2739,6 @@ static PyMethodDef PySSLMethods[] = { _SSL__SSLSOCKET_SELECTED_ALPN_PROTOCOL_METHODDEF _SSL__SSLSOCKET_COMPRESSION_METHODDEF _SSL__SSLSOCKET_SHUTDOWN_METHODDEF - _SSL__SSLSOCKET_TLS_UNIQUE_CB_METHODDEF {NULL, NULL} }; @@ -3810,13 +3834,17 @@ _ssl._SSLContext._wrap_socket sock: object(subclass_of="PySocketModule.Sock_Type") server_side: int server_hostname as hostname_obj: object = None + * + owner: object = None + session: object = None [clinic start generated code]*/ static PyObject * _ssl__SSLContext__wrap_socket_impl(PySSLContext *self, PyObject *sock, - int server_side, PyObject *hostname_obj) -/*[clinic end generated code: output=6973e4b60995e933 input=83859b9156ddfc63]*/ + int server_side, PyObject *hostname_obj, + PyObject *owner, PyObject *session) +/*[clinic end generated code: output=f103f238633940b4 input=957d5006183d1894]*/ { char *hostname = NULL; PyObject *res; @@ -3830,6 +3858,7 @@ _ssl__SSLContext__wrap_socket_impl(PySSLContext *self, PyObject *sock, res = (PyObject *) newPySSLSocket(self, (PySocketSockObject *)sock, server_side, hostname, + owner, session, NULL, NULL); if (hostname != NULL) PyMem_Free(hostname); @@ -3842,14 +3871,18 @@ _ssl._SSLContext._wrap_bio outgoing: object(subclass_of="&PySSLMemoryBIO_Type", type="PySSLMemoryBIO *") server_side: int server_hostname as hostname_obj: object = None + * + owner: object = None + session: object = None [clinic start generated code]*/ static PyObject * _ssl__SSLContext__wrap_bio_impl(PySSLContext *self, PySSLMemoryBIO *incoming, PySSLMemoryBIO *outgoing, int server_side, - PyObject *hostname_obj) -/*[clinic end generated code: output=4fe4ba75ad95940d input=17725ecdac0bf220]*/ + PyObject *hostname_obj, PyObject *owner, + PyObject *session) +/*[clinic end generated code: output=5c5d6d9b41f99332 input=8cf22f4d586ac56a]*/ { char *hostname = NULL; PyObject *res; @@ -3862,6 +3895,7 @@ _ssl__SSLContext__wrap_bio_impl(PySSLContext *self, PySSLMemoryBIO *incoming, } res = (PyObject *) newPySSLSocket(self, NULL, server_side, hostname, + owner, session, incoming, outgoing); PyMem_Free(hostname); @@ -5663,10 +5697,6 @@ PyInit__ssl(void) Py_INCREF(r); PyModule_AddObject(m, "HAS_SNI", r); - r = Py_True; - Py_INCREF(r); - PyModule_AddObject(m, "HAS_TLS_UNIQUE", r); - #ifdef OPENSSL_NO_ECDH r = Py_False; #else diff --git a/Modules/clinic/_ssl.c.h b/Modules/clinic/_ssl.c.h index d1a9afcd1d1e..5b6c4af11fb7 100644 --- a/Modules/clinic/_ssl.c.h +++ b/Modules/clinic/_ssl.c.h @@ -45,8 +45,8 @@ _ssl__test_decode_cert(PyObject *module, PyObject *arg) return return_value; } -PyDoc_STRVAR(_ssl__SSLSocket_peer_certificate__doc__, -"peer_certificate($self, der=False, /)\n" +PyDoc_STRVAR(_ssl__SSLSocket_getpeercert__doc__, +"getpeercert($self, der=False, /)\n" "--\n" "\n" "Returns the certificate for the peer.\n" @@ -59,23 +59,23 @@ PyDoc_STRVAR(_ssl__SSLSocket_peer_certificate__doc__, "peer certificate, or None if no certificate was provided. This will\n" "return the certificate even if it wasn\'t validated."); -#define _SSL__SSLSOCKET_PEER_CERTIFICATE_METHODDEF \ - {"peer_certificate", (PyCFunction)_ssl__SSLSocket_peer_certificate, METH_FASTCALL, _ssl__SSLSocket_peer_certificate__doc__}, +#define _SSL__SSLSOCKET_GETPEERCERT_METHODDEF \ + {"getpeercert", (PyCFunction)_ssl__SSLSocket_getpeercert, METH_FASTCALL, _ssl__SSLSocket_getpeercert__doc__}, static PyObject * -_ssl__SSLSocket_peer_certificate_impl(PySSLSocket *self, int binary_mode); +_ssl__SSLSocket_getpeercert_impl(PySSLSocket *self, int binary_mode); static PyObject * -_ssl__SSLSocket_peer_certificate(PySSLSocket *self, PyObject *const *args, Py_ssize_t nargs) +_ssl__SSLSocket_getpeercert(PySSLSocket *self, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; int binary_mode = 0; - if (!_PyArg_ParseStack(args, nargs, "|p:peer_certificate", + if (!_PyArg_ParseStack(args, nargs, "|p:getpeercert", &binary_mode)) { goto exit; } - return_value = _ssl__SSLSocket_peer_certificate_impl(self, binary_mode); + return_value = _ssl__SSLSocket_getpeercert_impl(self, binary_mode); exit: return return_value; @@ -293,9 +293,7 @@ PyDoc_STRVAR(_ssl__SSLSocket_shutdown__doc__, "shutdown($self, /)\n" "--\n" "\n" -"Does the SSL shutdown handshake with the remote end.\n" -"\n" -"Returns the underlying socket object."); +"Does the SSL shutdown handshake with the remote end."); #define _SSL__SSLSOCKET_SHUTDOWN_METHODDEF \ {"shutdown", (PyCFunction)_ssl__SSLSocket_shutdown, METH_NOARGS, _ssl__SSLSocket_shutdown__doc__}, @@ -309,24 +307,39 @@ _ssl__SSLSocket_shutdown(PySSLSocket *self, PyObject *Py_UNUSED(ignored)) return _ssl__SSLSocket_shutdown_impl(self); } -PyDoc_STRVAR(_ssl__SSLSocket_tls_unique_cb__doc__, -"tls_unique_cb($self, /)\n" +PyDoc_STRVAR(_ssl__SSLSocket_get_channel_binding__doc__, +"get_channel_binding($self, /, cb_type=\'tls-unique\')\n" "--\n" "\n" -"Returns the \'tls-unique\' channel binding data, as defined by RFC 5929.\n" +"Get channel binding data for current connection.\n" "\n" -"If the TLS handshake is not yet complete, None is returned."); +"Raise ValueError if the requested `cb_type` is not supported. Return bytes\n" +"of the data or None if the data is not available (e.g. before the handshake).\n" +"Only \'tls-unique\' channel binding data from RFC 5929 is supported."); -#define _SSL__SSLSOCKET_TLS_UNIQUE_CB_METHODDEF \ - {"tls_unique_cb", (PyCFunction)_ssl__SSLSocket_tls_unique_cb, METH_NOARGS, _ssl__SSLSocket_tls_unique_cb__doc__}, +#define _SSL__SSLSOCKET_GET_CHANNEL_BINDING_METHODDEF \ + {"get_channel_binding", (PyCFunction)_ssl__SSLSocket_get_channel_binding, METH_FASTCALL|METH_KEYWORDS, _ssl__SSLSocket_get_channel_binding__doc__}, static PyObject * -_ssl__SSLSocket_tls_unique_cb_impl(PySSLSocket *self); +_ssl__SSLSocket_get_channel_binding_impl(PySSLSocket *self, + const char *cb_type); static PyObject * -_ssl__SSLSocket_tls_unique_cb(PySSLSocket *self, PyObject *Py_UNUSED(ignored)) +_ssl__SSLSocket_get_channel_binding(PySSLSocket *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { - return _ssl__SSLSocket_tls_unique_cb_impl(self); + PyObject *return_value = NULL; + static const char * const _keywords[] = {"cb_type", NULL}; + static _PyArg_Parser _parser = {"|s:get_channel_binding", _keywords, 0}; + const char *cb_type = "tls-unique"; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &cb_type)) { + goto exit; + } + return_value = _ssl__SSLSocket_get_channel_binding_impl(self, cb_type); + +exit: + return return_value; } static PyObject * @@ -538,7 +551,8 @@ PyDoc_STRVAR(_ssl__SSLContext_load_dh_params__doc__, {"load_dh_params", (PyCFunction)_ssl__SSLContext_load_dh_params, METH_O, _ssl__SSLContext_load_dh_params__doc__}, PyDoc_STRVAR(_ssl__SSLContext__wrap_socket__doc__, -"_wrap_socket($self, /, sock, server_side, server_hostname=None)\n" +"_wrap_socket($self, /, sock, server_side, server_hostname=None, *,\n" +" owner=None, session=None)\n" "--\n" "\n"); @@ -547,23 +561,26 @@ PyDoc_STRVAR(_ssl__SSLContext__wrap_socket__doc__, static PyObject * _ssl__SSLContext__wrap_socket_impl(PySSLContext *self, PyObject *sock, - int server_side, PyObject *hostname_obj); + int server_side, PyObject *hostname_obj, + PyObject *owner, PyObject *session); static PyObject * _ssl__SSLContext__wrap_socket(PySSLContext *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; - static const char * const _keywords[] = {"sock", "server_side", "server_hostname", NULL}; - static _PyArg_Parser _parser = {"O!i|O:_wrap_socket", _keywords, 0}; + static const char * const _keywords[] = {"sock", "server_side", "server_hostname", "owner", "session", NULL}; + static _PyArg_Parser _parser = {"O!i|O$OO:_wrap_socket", _keywords, 0}; PyObject *sock; int server_side; PyObject *hostname_obj = Py_None; + PyObject *owner = Py_None; + PyObject *session = Py_None; if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, - PySocketModule.Sock_Type, &sock, &server_side, &hostname_obj)) { + PySocketModule.Sock_Type, &sock, &server_side, &hostname_obj, &owner, &session)) { goto exit; } - return_value = _ssl__SSLContext__wrap_socket_impl(self, sock, server_side, hostname_obj); + return_value = _ssl__SSLContext__wrap_socket_impl(self, sock, server_side, hostname_obj, owner, session); exit: return return_value; @@ -571,7 +588,7 @@ _ssl__SSLContext__wrap_socket(PySSLContext *self, PyObject *const *args, Py_ssiz PyDoc_STRVAR(_ssl__SSLContext__wrap_bio__doc__, "_wrap_bio($self, /, incoming, outgoing, server_side,\n" -" server_hostname=None)\n" +" server_hostname=None, *, owner=None, session=None)\n" "--\n" "\n"); @@ -581,24 +598,27 @@ PyDoc_STRVAR(_ssl__SSLContext__wrap_bio__doc__, static PyObject * _ssl__SSLContext__wrap_bio_impl(PySSLContext *self, PySSLMemoryBIO *incoming, PySSLMemoryBIO *outgoing, int server_side, - PyObject *hostname_obj); + PyObject *hostname_obj, PyObject *owner, + PyObject *session); static PyObject * _ssl__SSLContext__wrap_bio(PySSLContext *self, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; - static const char * const _keywords[] = {"incoming", "outgoing", "server_side", "server_hostname", NULL}; - static _PyArg_Parser _parser = {"O!O!i|O:_wrap_bio", _keywords, 0}; + static const char * const _keywords[] = {"incoming", "outgoing", "server_side", "server_hostname", "owner", "session", NULL}; + static _PyArg_Parser _parser = {"O!O!i|O$OO:_wrap_bio", _keywords, 0}; PySSLMemoryBIO *incoming; PySSLMemoryBIO *outgoing; int server_side; PyObject *hostname_obj = Py_None; + PyObject *owner = Py_None; + PyObject *session = Py_None; if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, - &PySSLMemoryBIO_Type, &incoming, &PySSLMemoryBIO_Type, &outgoing, &server_side, &hostname_obj)) { + &PySSLMemoryBIO_Type, &incoming, &PySSLMemoryBIO_Type, &outgoing, &server_side, &hostname_obj, &owner, &session)) { goto exit; } - return_value = _ssl__SSLContext__wrap_bio_impl(self, incoming, outgoing, server_side, hostname_obj); + return_value = _ssl__SSLContext__wrap_bio_impl(self, incoming, outgoing, server_side, hostname_obj, owner, session); exit: return return_value; @@ -1155,4 +1175,4 @@ _ssl_enum_crls(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje #ifndef _SSL_ENUM_CRLS_METHODDEF #define _SSL_ENUM_CRLS_METHODDEF #endif /* !defined(_SSL_ENUM_CRLS_METHODDEF) */ -/*[clinic end generated code: output=84e1fd89aff9b0f7 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=d987411caeb106e7 input=a9049054013a1b77]*/ From webhook-mailer at python.org Sat Feb 24 16:12:43 2018 From: webhook-mailer at python.org (Christian Heimes) Date: Sat, 24 Feb 2018 21:12:43 -0000 Subject: [Python-checkins] bpo-30622: Improve NPN support detection (#5859) Message-ID: https://github.com/python/cpython/commit/6cdb7954b0a578d899e4b78b868ea59eef08480a commit: 6cdb7954b0a578d899e4b78b868ea59eef08480a branch: master author: Christian Heimes committer: GitHub date: 2018-02-24T22:12:40+01:00 summary: bpo-30622: Improve NPN support detection (#5859) The ssl module now detects missing NPN support in LibreSSL. Co-Authored-By: Bernard Spil Signed-off-by: Christian Heimes files: A Misc/NEWS.d/next/Library/2018-02-24-21-40-42.bpo-30622.dQjxSe.rst M Doc/library/ssl.rst M Modules/_ssl.c M Modules/clinic/_ssl.c.h diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 4cad9f667c48..7371024dce4e 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -2434,6 +2434,23 @@ successful call of :func:`~ssl.RAND_add`, :func:`~ssl.RAND_bytes` or :func:`~ssl.RAND_pseudo_bytes` is sufficient. +.. ssl-libressl: + +LibreSSL support +---------------- + +LibreSSL is a fork of OpenSSL 1.0.1. The ssl module has limited support for +LibreSSL. Some features are not available when the ssl module is compiled +with LibreSSL. + +* LibreSSL >= 2.6.1 no longer supports NPN. The methods + :meth:`SSLContext.set_npn_protocols` and + :meth:`SSLSocket.selected_npn_protocol` are not available. +* :meth:`SSLContext.set_default_verify_paths` ignores the env vars + :envvar:`SSL_CERT_FILE` and :envvar:`SSL_CERT_PATH` although + :func:`get_default_verify_paths` still reports them. + + .. seealso:: Class :class:`socket.socket` diff --git a/Misc/NEWS.d/next/Library/2018-02-24-21-40-42.bpo-30622.dQjxSe.rst b/Misc/NEWS.d/next/Library/2018-02-24-21-40-42.bpo-30622.dQjxSe.rst new file mode 100644 index 000000000000..bcb659b24dd3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-24-21-40-42.bpo-30622.dQjxSe.rst @@ -0,0 +1 @@ +The ssl module now detects missing NPN support in LibreSSL. diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 2136cbdeae47..ed6b7a835a94 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -160,6 +160,19 @@ static void _PySSLFixErrno(void) { # define HAVE_ALPN #endif +/* We cannot rely on OPENSSL_NO_NEXTPROTONEG because LibreSSL 2.6.1 dropped + * NPN support but did not set OPENSSL_NO_NEXTPROTONEG for compatibility + * reasons. The check for TLSEXT_TYPE_next_proto_neg works with + * OpenSSL 1.0.1+ and LibreSSL. + */ +#ifdef OPENSSL_NO_NEXTPROTONEG +# define HAVE_NPN 0 +#elif defined(TLSEXT_TYPE_next_proto_neg) +# define HAVE_NPN 1 +#else +# define HAVE_NPN 0 +# endif + #ifndef INVALID_SOCKET /* MS defines this */ #define INVALID_SOCKET (-1) #endif @@ -328,7 +341,7 @@ static unsigned int _ssl_locks_count = 0; typedef struct { PyObject_HEAD SSL_CTX *ctx; -#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG) +#ifdef HAVE_NPN unsigned char *npn_protocols; int npn_protocols_len; #endif @@ -1909,7 +1922,7 @@ _ssl__SSLSocket_version_impl(PySSLSocket *self) return PyUnicode_FromString(version); } -#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG) +#ifdef HAVE_NPN /*[clinic input] _ssl._SSLSocket.selected_npn_protocol [clinic start generated code]*/ @@ -2874,7 +2887,7 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version) self->ctx = ctx; self->hostflags = X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS; self->protocol = proto_version; -#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG) +#ifdef HAVE_NPN self->npn_protocols = NULL; #endif #ifdef HAVE_ALPN @@ -3013,7 +3026,7 @@ context_dealloc(PySSLContext *self) PyObject_GC_UnTrack(self); context_clear(self); SSL_CTX_free(self->ctx); -#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG) +#ifdef HAVE_NPN PyMem_FREE(self->npn_protocols); #endif #ifdef HAVE_ALPN @@ -3091,7 +3104,7 @@ _ssl__SSLContext_get_ciphers_impl(PySSLContext *self) #endif -#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG) || defined(HAVE_ALPN) +#if defined(HAVE_NPN) || defined(HAVE_ALPN) static int do_protocol_selection(int alpn, unsigned char **out, unsigned char *outlen, const unsigned char *server_protocols, unsigned int server_protocols_len, @@ -3117,7 +3130,7 @@ do_protocol_selection(int alpn, unsigned char **out, unsigned char *outlen, } #endif -#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG) +#ifdef HAVE_NPN /* this callback gets passed to SSL_CTX_set_next_protos_advertise_cb */ static int _advertiseNPN_cb(SSL *s, @@ -3160,7 +3173,7 @@ _ssl__SSLContext__set_npn_protocols_impl(PySSLContext *self, Py_buffer *protos) /*[clinic end generated code: output=72b002c3324390c6 input=319fcb66abf95bd7]*/ { -#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG) +#ifdef HAVE_NPN PyMem_Free(self->npn_protocols); self->npn_protocols = PyMem_Malloc(protos->len); if (self->npn_protocols == NULL) @@ -5705,7 +5718,7 @@ PyInit__ssl(void) Py_INCREF(r); PyModule_AddObject(m, "HAS_ECDH", r); -#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG) +#ifdef HAVE_NPN r = Py_True; #else r = Py_False; diff --git a/Modules/clinic/_ssl.c.h b/Modules/clinic/_ssl.c.h index 5b6c4af11fb7..1ee1bfb21d3e 100644 --- a/Modules/clinic/_ssl.c.h +++ b/Modules/clinic/_ssl.c.h @@ -132,7 +132,7 @@ _ssl__SSLSocket_version(PySSLSocket *self, PyObject *Py_UNUSED(ignored)) return _ssl__SSLSocket_version_impl(self); } -#if (defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)) +#if defined(HAVE_NPN) PyDoc_STRVAR(_ssl__SSLSocket_selected_npn_protocol__doc__, "selected_npn_protocol($self, /)\n" @@ -151,7 +151,7 @@ _ssl__SSLSocket_selected_npn_protocol(PySSLSocket *self, PyObject *Py_UNUSED(ign return _ssl__SSLSocket_selected_npn_protocol_impl(self); } -#endif /* (defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)) */ +#endif /* defined(HAVE_NPN) */ #if defined(HAVE_ALPN) @@ -1175,4 +1175,4 @@ _ssl_enum_crls(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje #ifndef _SSL_ENUM_CRLS_METHODDEF #define _SSL_ENUM_CRLS_METHODDEF #endif /* !defined(_SSL_ENUM_CRLS_METHODDEF) */ -/*[clinic end generated code: output=d987411caeb106e7 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=a00fef6a470cfc2c input=a9049054013a1b77]*/ From webhook-mailer at python.org Sat Feb 24 17:04:29 2018 From: webhook-mailer at python.org (Christian Heimes) Date: Sat, 24 Feb 2018 22:04:29 -0000 Subject: [Python-checkins] [3.7] bpo-30622: Improve NPN support detection (GH-5859) (#5860) Message-ID: https://github.com/python/cpython/commit/01d9c23e470d708b922a1085347404000e985c0f commit: 01d9c23e470d708b922a1085347404000e985c0f branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Christian Heimes date: 2018-02-24T23:04:27+01:00 summary: [3.7] bpo-30622: Improve NPN support detection (GH-5859) (#5860) The ssl module now detects missing NPN support in LibreSSL. Co-Authored-By: Bernard Spil Signed-off-by: Christian Heimes (cherry picked from commit 6cdb7954b0a578d899e4b78b868ea59eef08480a) Co-authored-by: Christian Heimes files: A Misc/NEWS.d/next/Library/2018-02-24-21-40-42.bpo-30622.dQjxSe.rst M Doc/library/ssl.rst M Modules/_ssl.c M Modules/clinic/_ssl.c.h diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 4cad9f667c48..7371024dce4e 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -2434,6 +2434,23 @@ successful call of :func:`~ssl.RAND_add`, :func:`~ssl.RAND_bytes` or :func:`~ssl.RAND_pseudo_bytes` is sufficient. +.. ssl-libressl: + +LibreSSL support +---------------- + +LibreSSL is a fork of OpenSSL 1.0.1. The ssl module has limited support for +LibreSSL. Some features are not available when the ssl module is compiled +with LibreSSL. + +* LibreSSL >= 2.6.1 no longer supports NPN. The methods + :meth:`SSLContext.set_npn_protocols` and + :meth:`SSLSocket.selected_npn_protocol` are not available. +* :meth:`SSLContext.set_default_verify_paths` ignores the env vars + :envvar:`SSL_CERT_FILE` and :envvar:`SSL_CERT_PATH` although + :func:`get_default_verify_paths` still reports them. + + .. seealso:: Class :class:`socket.socket` diff --git a/Misc/NEWS.d/next/Library/2018-02-24-21-40-42.bpo-30622.dQjxSe.rst b/Misc/NEWS.d/next/Library/2018-02-24-21-40-42.bpo-30622.dQjxSe.rst new file mode 100644 index 000000000000..bcb659b24dd3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-24-21-40-42.bpo-30622.dQjxSe.rst @@ -0,0 +1 @@ +The ssl module now detects missing NPN support in LibreSSL. diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 2136cbdeae47..ed6b7a835a94 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -160,6 +160,19 @@ static void _PySSLFixErrno(void) { # define HAVE_ALPN #endif +/* We cannot rely on OPENSSL_NO_NEXTPROTONEG because LibreSSL 2.6.1 dropped + * NPN support but did not set OPENSSL_NO_NEXTPROTONEG for compatibility + * reasons. The check for TLSEXT_TYPE_next_proto_neg works with + * OpenSSL 1.0.1+ and LibreSSL. + */ +#ifdef OPENSSL_NO_NEXTPROTONEG +# define HAVE_NPN 0 +#elif defined(TLSEXT_TYPE_next_proto_neg) +# define HAVE_NPN 1 +#else +# define HAVE_NPN 0 +# endif + #ifndef INVALID_SOCKET /* MS defines this */ #define INVALID_SOCKET (-1) #endif @@ -328,7 +341,7 @@ static unsigned int _ssl_locks_count = 0; typedef struct { PyObject_HEAD SSL_CTX *ctx; -#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG) +#ifdef HAVE_NPN unsigned char *npn_protocols; int npn_protocols_len; #endif @@ -1909,7 +1922,7 @@ _ssl__SSLSocket_version_impl(PySSLSocket *self) return PyUnicode_FromString(version); } -#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG) +#ifdef HAVE_NPN /*[clinic input] _ssl._SSLSocket.selected_npn_protocol [clinic start generated code]*/ @@ -2874,7 +2887,7 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version) self->ctx = ctx; self->hostflags = X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS; self->protocol = proto_version; -#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG) +#ifdef HAVE_NPN self->npn_protocols = NULL; #endif #ifdef HAVE_ALPN @@ -3013,7 +3026,7 @@ context_dealloc(PySSLContext *self) PyObject_GC_UnTrack(self); context_clear(self); SSL_CTX_free(self->ctx); -#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG) +#ifdef HAVE_NPN PyMem_FREE(self->npn_protocols); #endif #ifdef HAVE_ALPN @@ -3091,7 +3104,7 @@ _ssl__SSLContext_get_ciphers_impl(PySSLContext *self) #endif -#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG) || defined(HAVE_ALPN) +#if defined(HAVE_NPN) || defined(HAVE_ALPN) static int do_protocol_selection(int alpn, unsigned char **out, unsigned char *outlen, const unsigned char *server_protocols, unsigned int server_protocols_len, @@ -3117,7 +3130,7 @@ do_protocol_selection(int alpn, unsigned char **out, unsigned char *outlen, } #endif -#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG) +#ifdef HAVE_NPN /* this callback gets passed to SSL_CTX_set_next_protos_advertise_cb */ static int _advertiseNPN_cb(SSL *s, @@ -3160,7 +3173,7 @@ _ssl__SSLContext__set_npn_protocols_impl(PySSLContext *self, Py_buffer *protos) /*[clinic end generated code: output=72b002c3324390c6 input=319fcb66abf95bd7]*/ { -#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG) +#ifdef HAVE_NPN PyMem_Free(self->npn_protocols); self->npn_protocols = PyMem_Malloc(protos->len); if (self->npn_protocols == NULL) @@ -5705,7 +5718,7 @@ PyInit__ssl(void) Py_INCREF(r); PyModule_AddObject(m, "HAS_ECDH", r); -#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG) +#ifdef HAVE_NPN r = Py_True; #else r = Py_False; diff --git a/Modules/clinic/_ssl.c.h b/Modules/clinic/_ssl.c.h index 5b6c4af11fb7..1ee1bfb21d3e 100644 --- a/Modules/clinic/_ssl.c.h +++ b/Modules/clinic/_ssl.c.h @@ -132,7 +132,7 @@ _ssl__SSLSocket_version(PySSLSocket *self, PyObject *Py_UNUSED(ignored)) return _ssl__SSLSocket_version_impl(self); } -#if (defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)) +#if defined(HAVE_NPN) PyDoc_STRVAR(_ssl__SSLSocket_selected_npn_protocol__doc__, "selected_npn_protocol($self, /)\n" @@ -151,7 +151,7 @@ _ssl__SSLSocket_selected_npn_protocol(PySSLSocket *self, PyObject *Py_UNUSED(ign return _ssl__SSLSocket_selected_npn_protocol_impl(self); } -#endif /* (defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)) */ +#endif /* defined(HAVE_NPN) */ #if defined(HAVE_ALPN) @@ -1175,4 +1175,4 @@ _ssl_enum_crls(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje #ifndef _SSL_ENUM_CRLS_METHODDEF #define _SSL_ENUM_CRLS_METHODDEF #endif /* !defined(_SSL_ENUM_CRLS_METHODDEF) */ -/*[clinic end generated code: output=d987411caeb106e7 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=a00fef6a470cfc2c input=a9049054013a1b77]*/ From webhook-mailer at python.org Sat Feb 24 18:45:27 2018 From: webhook-mailer at python.org (Christian Heimes) Date: Sat, 24 Feb 2018 23:45:27 -0000 Subject: [Python-checkins] bpo-31518: Change TLS protocol for Debian (#3660) Message-ID: https://github.com/python/cpython/commit/aab225840360719516eca55a7a69cfee45aee2af commit: aab225840360719516eca55a7a69cfee45aee2af branch: 3.6 author: Christian Heimes committer: GitHub date: 2018-02-25T00:45:24+01:00 summary: bpo-31518: Change TLS protocol for Debian (#3660) Debian Unstable has disabled TLS 1.0 and 1.1 for SSLv23_METHOD(). Change TLS/SSL protocol of some tests to PROTOCOL_TLS or PROTOCOL_TLSv1_2 to make them pass on Debian. Signed-off-by: Christian Heimes files: A Misc/NEWS.d/next/Tests/2017-09-19-20-48-50.bpo-31518.KwTMMz.rst M Lib/test/test_ftplib.py M Lib/test/test_httplib.py M Lib/test/test_poplib.py M Lib/test/test_ssl.py M Lib/test/test_urllib2_localnet.py diff --git a/Lib/test/test_ftplib.py b/Lib/test/test_ftplib.py index b593313db095..44dd73aecaca 100644 --- a/Lib/test/test_ftplib.py +++ b/Lib/test/test_ftplib.py @@ -908,11 +908,11 @@ def test_auth_ssl(self): self.client.auth() self.assertRaises(ValueError, self.client.auth) finally: - self.client.ssl_version = ssl.PROTOCOL_TLSv1 + self.client.ssl_version = ssl.PROTOCOL_TLS def test_context(self): self.client.quit() - ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) + ctx = ssl.SSLContext(ssl.PROTOCOL_TLS) self.assertRaises(ValueError, ftplib.FTP_TLS, keyfile=CERTFILE, context=ctx) self.assertRaises(ValueError, ftplib.FTP_TLS, certfile=CERTFILE, @@ -941,7 +941,7 @@ def test_ccc(self): def test_check_hostname(self): self.client.quit() - ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) + ctx = ssl.SSLContext(ssl.PROTOCOL_TLS) ctx.verify_mode = ssl.CERT_REQUIRED ctx.check_hostname = True ctx.load_verify_locations(CAFILE) diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py index 68f6946a3a12..64d6e43537b3 100644 --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -1583,7 +1583,7 @@ def test_networked_good_cert(self): import ssl support.requires('network') with support.transient_internet('self-signed.pythontest.net'): - context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) + context = ssl.SSLContext(ssl.PROTOCOL_TLS) context.verify_mode = ssl.CERT_REQUIRED context.load_verify_locations(CERT_selfsigned_pythontestdotnet) h = client.HTTPSConnection('self-signed.pythontest.net', 443, context=context) @@ -1599,7 +1599,7 @@ def test_networked_bad_cert(self): import ssl support.requires('network') with support.transient_internet('self-signed.pythontest.net'): - context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) + context = ssl.SSLContext(ssl.PROTOCOL_TLS) context.verify_mode = ssl.CERT_REQUIRED context.load_verify_locations(CERT_localhost) h = client.HTTPSConnection('self-signed.pythontest.net', 443, context=context) @@ -1620,7 +1620,7 @@ def test_local_good_hostname(self): # The (valid) cert validates the HTTP hostname import ssl server = self.make_server(CERT_localhost) - context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) + context = ssl.SSLContext(ssl.PROTOCOL_TLS) context.verify_mode = ssl.CERT_REQUIRED context.load_verify_locations(CERT_localhost) h = client.HTTPSConnection('localhost', server.port, context=context) @@ -1634,7 +1634,7 @@ def test_local_bad_hostname(self): # The (valid) cert doesn't validate the HTTP hostname import ssl server = self.make_server(CERT_fakehostname) - context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) + context = ssl.SSLContext(ssl.PROTOCOL_TLS) context.verify_mode = ssl.CERT_REQUIRED context.check_hostname = True context.load_verify_locations(CERT_fakehostname) diff --git a/Lib/test/test_poplib.py b/Lib/test/test_poplib.py index 1269199423c0..608eac57f35c 100644 --- a/Lib/test/test_poplib.py +++ b/Lib/test/test_poplib.py @@ -352,7 +352,7 @@ def test_stls(self): @requires_ssl def test_stls_context(self): expected = b'+OK Begin TLS negotiation' - ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) + ctx = ssl.SSLContext(ssl.PROTOCOL_TLS) ctx.load_verify_locations(CAFILE) ctx.verify_mode = ssl.CERT_REQUIRED ctx.check_hostname = True @@ -392,7 +392,7 @@ def test__all__(self): self.assertIn('POP3_SSL', poplib.__all__) def test_context(self): - ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) + ctx = ssl.SSLContext(ssl.PROTOCOL_TLS) self.assertRaises(ValueError, poplib.POP3_SSL, self.server.host, self.server.port, keyfile=CERTFILE, context=ctx) self.assertRaises(ValueError, poplib.POP3_SSL, self.server.host, diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index daffaf7af879..8dd3b4145078 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -1689,7 +1689,7 @@ def test_get_ca_certs_capath(self): @needs_sni def test_context_setget(self): # Check that the context of a connected socket can be replaced. - ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLSv1) + ctx1 = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) ctx2 = ssl.SSLContext(ssl.PROTOCOL_SSLv23) s = socket.socket(socket.AF_INET) with ctx1.wrap_socket(s) as ss: @@ -1986,7 +1986,7 @@ def __init__(self, certificate=None, ssl_version=None, else: self.context = ssl.SSLContext(ssl_version if ssl_version is not None - else ssl.PROTOCOL_TLSv1) + else ssl.PROTOCOL_TLS) self.context.verify_mode = (certreqs if certreqs is not None else ssl.CERT_NONE) if cacerts: diff --git a/Lib/test/test_urllib2_localnet.py b/Lib/test/test_urllib2_localnet.py index f83f9ccb7867..9d9ec8726d8a 100644 --- a/Lib/test/test_urllib2_localnet.py +++ b/Lib/test/test_urllib2_localnet.py @@ -598,7 +598,7 @@ def test_https_sni(self): def cb_sni(ssl_sock, server_name, initial_context): nonlocal sni_name sni_name = server_name - context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) + context = ssl.SSLContext(ssl.PROTOCOL_TLS) context.set_servername_callback(cb_sni) handler = self.start_https_server(context=context, certfile=CERT_localhost) context = ssl.create_default_context(cafile=CERT_localhost) diff --git a/Misc/NEWS.d/next/Tests/2017-09-19-20-48-50.bpo-31518.KwTMMz.rst b/Misc/NEWS.d/next/Tests/2017-09-19-20-48-50.bpo-31518.KwTMMz.rst new file mode 100644 index 000000000000..7378df074733 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2017-09-19-20-48-50.bpo-31518.KwTMMz.rst @@ -0,0 +1,3 @@ +Debian Unstable has disabled TLS 1.0 and 1.1 for SSLv23_METHOD(). Change +TLS/SSL protocol of some tests to PROTOCOL_TLS or PROTOCOL_TLSv1_2 to make +them pass on Debian. From webhook-mailer at python.org Sat Feb 24 18:45:56 2018 From: webhook-mailer at python.org (Christian Heimes) Date: Sat, 24 Feb 2018 23:45:56 -0000 Subject: [Python-checkins] bpo-31518: Change TLS protocol for Debian (#3661) Message-ID: https://github.com/python/cpython/commit/8d4d17399fb82801eaaca5beeb97a19908b40222 commit: 8d4d17399fb82801eaaca5beeb97a19908b40222 branch: 2.7 author: Christian Heimes committer: GitHub date: 2018-02-25T00:45:53+01:00 summary: bpo-31518: Change TLS protocol for Debian (#3661) Debian Unstable has disabled TLS 1.0 and 1.1 for SSLv23_METHOD(). Change TLS/SSL protocol of some tests to PROTOCOL_TLS or PROTOCOL_TLSv1_2 to make them pass on Debian. Signed-off-by: Christian Heimes files: A Misc/NEWS.d/next/Tests/2017-09-19-20-48-50.bpo-31518.KwTMMz.rst M Lib/test/test_ftplib.py M Lib/test/test_httplib.py M Lib/test/test_ssl.py M Lib/test/test_urllib2_localnet.py diff --git a/Lib/test/test_ftplib.py b/Lib/test/test_ftplib.py index fdfa31387cb4..e728aa70f9ea 100644 --- a/Lib/test/test_ftplib.py +++ b/Lib/test/test_ftplib.py @@ -710,11 +710,11 @@ def test_auth_ssl(self): self.client.auth() self.assertRaises(ValueError, self.client.auth) finally: - self.client.ssl_version = ssl.PROTOCOL_TLSv1 + self.client.ssl_version = ssl.PROTOCOL_TLS def test_context(self): self.client.quit() - ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) + ctx = ssl.SSLContext(ssl.PROTOCOL_TLS) self.assertRaises(ValueError, ftplib.FTP_TLS, keyfile=CERTFILE, context=ctx) self.assertRaises(ValueError, ftplib.FTP_TLS, certfile=CERTFILE, @@ -739,7 +739,7 @@ def test_context(self): def test_check_hostname(self): self.client.quit() - ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) + ctx = ssl.SSLContext(ssl.PROTOCOL_TLS) ctx.verify_mode = ssl.CERT_REQUIRED ctx.check_hostname = True ctx.load_verify_locations(CAFILE) diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py index 7e8b058e8b0f..44ffac703688 100644 --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -860,7 +860,7 @@ def test_networked_good_cert(self): import ssl test_support.requires('network') with test_support.transient_internet('self-signed.pythontest.net'): - context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) + context = ssl.SSLContext(ssl.PROTOCOL_TLS) context.verify_mode = ssl.CERT_REQUIRED context.load_verify_locations(CERT_selfsigned_pythontestdotnet) h = httplib.HTTPSConnection('self-signed.pythontest.net', 443, context=context) @@ -874,7 +874,7 @@ def test_networked_bad_cert(self): import ssl test_support.requires('network') with test_support.transient_internet('self-signed.pythontest.net'): - context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) + context = ssl.SSLContext(ssl.PROTOCOL_TLS) context.verify_mode = ssl.CERT_REQUIRED context.load_verify_locations(CERT_localhost) h = httplib.HTTPSConnection('self-signed.pythontest.net', 443, context=context) @@ -895,7 +895,7 @@ def test_local_good_hostname(self): # The (valid) cert validates the HTTP hostname import ssl server = self.make_server(CERT_localhost) - context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) + context = ssl.SSLContext(ssl.PROTOCOL_TLS) context.verify_mode = ssl.CERT_REQUIRED context.load_verify_locations(CERT_localhost) h = httplib.HTTPSConnection('localhost', server.port, context=context) @@ -907,7 +907,7 @@ def test_local_bad_hostname(self): # The (valid) cert doesn't validate the HTTP hostname import ssl server = self.make_server(CERT_fakehostname) - context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) + context = ssl.SSLContext(ssl.PROTOCOL_TLS) context.verify_mode = ssl.CERT_REQUIRED context.check_hostname = True context.load_verify_locations(CERT_fakehostname) diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index cfc03e343c7d..f172520011f4 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -1774,7 +1774,7 @@ def __init__(self, certificate=None, ssl_version=None, else: self.context = ssl.SSLContext(ssl_version if ssl_version is not None - else ssl.PROTOCOL_TLSv1) + else ssl.PROTOCOL_TLS) self.context.verify_mode = (certreqs if certreqs is not None else ssl.CERT_NONE) if cacerts: diff --git a/Lib/test/test_urllib2_localnet.py b/Lib/test/test_urllib2_localnet.py index 061233f9f2f2..932b57223a56 100644 --- a/Lib/test/test_urllib2_localnet.py +++ b/Lib/test/test_urllib2_localnet.py @@ -577,7 +577,7 @@ def test_https_sni(self): sni_name = [None] def cb_sni(ssl_sock, server_name, initial_context): sni_name[0] = server_name - context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) + context = ssl.SSLContext(ssl.PROTOCOL_TLS) context.set_servername_callback(cb_sni) handler = self.start_https_server(context=context, certfile=CERT_localhost) context = ssl.create_default_context(cafile=CERT_localhost) diff --git a/Misc/NEWS.d/next/Tests/2017-09-19-20-48-50.bpo-31518.KwTMMz.rst b/Misc/NEWS.d/next/Tests/2017-09-19-20-48-50.bpo-31518.KwTMMz.rst new file mode 100644 index 000000000000..7378df074733 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2017-09-19-20-48-50.bpo-31518.KwTMMz.rst @@ -0,0 +1,3 @@ +Debian Unstable has disabled TLS 1.0 and 1.1 for SSLv23_METHOD(). Change +TLS/SSL protocol of some tests to PROTOCOL_TLS or PROTOCOL_TLSv1_2 to make +them pass on Debian. From webhook-mailer at python.org Sat Feb 24 22:04:43 2018 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Sun, 25 Feb 2018 03:04:43 -0000 Subject: [Python-checkins] bpo-17232: Clarify docs for -O and -OO command line options (#5839) Message-ID: https://github.com/python/cpython/commit/186b606d8a2ea4fd51b7286813302c8e8c7006cc commit: 186b606d8a2ea4fd51b7286813302c8e8c7006cc branch: master author: Cheryl Sabella committer: Terry Jan Reedy date: 2018-02-24T22:04:40-05:00 summary: bpo-17232: Clarify docs for -O and -OO command line options (#5839) The 'optimization' is for space in the executable file, not for run time. files: A Misc/NEWS.d/next/Documentation/2018-02-23-12-48-03.bpo-17232.tmuTKL.rst M Doc/using/cmdline.rst M Misc/python.man M Modules/main.c diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst index 1e9ed6e645a2..21ba0b5cebc6 100644 --- a/Doc/using/cmdline.rst +++ b/Doc/using/cmdline.rst @@ -260,12 +260,23 @@ Miscellaneous options .. cmdoption:: -O - Turn on basic optimizations. See also :envvar:`PYTHONOPTIMIZE`. + Remove assert statements and any code conditional on the value of + :const:`__debug__`. Augment the filename for compiled + (:term:`bytecode`) files by adding ``.opt-1`` before the ``.pyc`` + extension (see :pep:`488`). See also :envvar:`PYTHONOPTIMIZE`. + + .. versionchanged:: 3.5 + Modify ``.pyc`` filenames according to :pep:`488`. .. cmdoption:: -OO - Discard docstrings in addition to the :option:`-O` optimizations. + Do :option:`-O` and also discard docstrings. Augment the filename + for compiled (:term:`bytecode`) files by adding ``.opt-2`` before the + ``.pyc`` extension (see :pep:`488`). + + .. versionchanged:: 3.5 + Modify ``.pyc`` filenames according to :pep:`488`. .. cmdoption:: -q diff --git a/Misc/NEWS.d/next/Documentation/2018-02-23-12-48-03.bpo-17232.tmuTKL.rst b/Misc/NEWS.d/next/Documentation/2018-02-23-12-48-03.bpo-17232.tmuTKL.rst new file mode 100644 index 000000000000..5c14e91b3919 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2018-02-23-12-48-03.bpo-17232.tmuTKL.rst @@ -0,0 +1 @@ +Clarify docs for -O and -OO. Patch by Terry Reedy. diff --git a/Misc/python.man b/Misc/python.man index 0f38c5b12cea..a0084f84d04e 100644 --- a/Misc/python.man +++ b/Misc/python.man @@ -164,10 +164,13 @@ for the named module and runs the corresponding file as a script. .TP .B \-O -Turn on basic optimizations. Given twice, causes docstrings to be discarded. +Remove assert statements and any code conditional on the value of +__debug__; augment the filename for compiled (bytecode) files by +adding .opt-1 before the .pyc extension. .TP .B \-OO -Discard docstrings in addition to the \fB-O\fP optimizations. +Do \fB-O\fP and also discard docstrings; change the filename for +compiled (bytecode) files by adding .opt-2 before the .pyc extension. .TP .B \-q Do not print the version and copyright messages. These messages are diff --git a/Modules/main.c b/Modules/main.c index 1ce075f98e36..f6b51043007b 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -96,8 +96,10 @@ static const char usage_2[] = "\ if stdin does not appear to be a terminal; also PYTHONINSPECT=x\n\ -I : isolate Python from the user's environment (implies -E and -s)\n\ -m mod : run library module as a script (terminates option list)\n\ --O : optimize generated bytecode slightly; also PYTHONOPTIMIZE=x\n\ --OO : remove doc-strings in addition to the -O optimizations\n\ +-O : remove assert and __debug__-dependent statements; add .opt-1 before\n\ + .pyc extension; also PYTHONOPTIMIZE=x\n\ +-OO : do -O changes and also discard docstrings; add .opt-2 before\n\ + .pyc extension\n\ -q : don't print version and copyright messages on interactive startup\n\ -s : don't add user site directory to sys.path; also PYTHONNOUSERSITE\n\ -S : don't imply 'import site' on initialization\n\ From webhook-mailer at python.org Sat Feb 24 22:24:11 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sun, 25 Feb 2018 03:24:11 -0000 Subject: [Python-checkins] bpo-17232: Clarify docs for -O and -OO command line options (GH-5839) Message-ID: https://github.com/python/cpython/commit/b5655f3d187084579ff389dbd8734742a8b66cbc commit: b5655f3d187084579ff389dbd8734742a8b66cbc branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-24T19:24:08-08:00 summary: bpo-17232: Clarify docs for -O and -OO command line options (GH-5839) The 'optimization' is for space in the executable file, not for run time. (cherry picked from commit 186b606d8a2ea4fd51b7286813302c8e8c7006cc) Co-authored-by: Cheryl Sabella files: A Misc/NEWS.d/next/Documentation/2018-02-23-12-48-03.bpo-17232.tmuTKL.rst M Doc/using/cmdline.rst M Misc/python.man M Modules/main.c diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst index 1e9ed6e645a2..21ba0b5cebc6 100644 --- a/Doc/using/cmdline.rst +++ b/Doc/using/cmdline.rst @@ -260,12 +260,23 @@ Miscellaneous options .. cmdoption:: -O - Turn on basic optimizations. See also :envvar:`PYTHONOPTIMIZE`. + Remove assert statements and any code conditional on the value of + :const:`__debug__`. Augment the filename for compiled + (:term:`bytecode`) files by adding ``.opt-1`` before the ``.pyc`` + extension (see :pep:`488`). See also :envvar:`PYTHONOPTIMIZE`. + + .. versionchanged:: 3.5 + Modify ``.pyc`` filenames according to :pep:`488`. .. cmdoption:: -OO - Discard docstrings in addition to the :option:`-O` optimizations. + Do :option:`-O` and also discard docstrings. Augment the filename + for compiled (:term:`bytecode`) files by adding ``.opt-2`` before the + ``.pyc`` extension (see :pep:`488`). + + .. versionchanged:: 3.5 + Modify ``.pyc`` filenames according to :pep:`488`. .. cmdoption:: -q diff --git a/Misc/NEWS.d/next/Documentation/2018-02-23-12-48-03.bpo-17232.tmuTKL.rst b/Misc/NEWS.d/next/Documentation/2018-02-23-12-48-03.bpo-17232.tmuTKL.rst new file mode 100644 index 000000000000..5c14e91b3919 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2018-02-23-12-48-03.bpo-17232.tmuTKL.rst @@ -0,0 +1 @@ +Clarify docs for -O and -OO. Patch by Terry Reedy. diff --git a/Misc/python.man b/Misc/python.man index 0f38c5b12cea..a0084f84d04e 100644 --- a/Misc/python.man +++ b/Misc/python.man @@ -164,10 +164,13 @@ for the named module and runs the corresponding file as a script. .TP .B \-O -Turn on basic optimizations. Given twice, causes docstrings to be discarded. +Remove assert statements and any code conditional on the value of +__debug__; augment the filename for compiled (bytecode) files by +adding .opt-1 before the .pyc extension. .TP .B \-OO -Discard docstrings in addition to the \fB-O\fP optimizations. +Do \fB-O\fP and also discard docstrings; change the filename for +compiled (bytecode) files by adding .opt-2 before the .pyc extension. .TP .B \-q Do not print the version and copyright messages. These messages are diff --git a/Modules/main.c b/Modules/main.c index 1ce075f98e36..f6b51043007b 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -96,8 +96,10 @@ static const char usage_2[] = "\ if stdin does not appear to be a terminal; also PYTHONINSPECT=x\n\ -I : isolate Python from the user's environment (implies -E and -s)\n\ -m mod : run library module as a script (terminates option list)\n\ --O : optimize generated bytecode slightly; also PYTHONOPTIMIZE=x\n\ --OO : remove doc-strings in addition to the -O optimizations\n\ +-O : remove assert and __debug__-dependent statements; add .opt-1 before\n\ + .pyc extension; also PYTHONOPTIMIZE=x\n\ +-OO : do -O changes and also discard docstrings; add .opt-2 before\n\ + .pyc extension\n\ -q : don't print version and copyright messages on interactive startup\n\ -s : don't add user site directory to sys.path; also PYTHONNOUSERSITE\n\ -S : don't imply 'import site' on initialization\n\ From webhook-mailer at python.org Sat Feb 24 22:46:19 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sun, 25 Feb 2018 03:46:19 -0000 Subject: [Python-checkins] bpo-17232: Clarify docs for -O and -OO command line options (GH-5839) Message-ID: https://github.com/python/cpython/commit/fc9471a888f373aedff3c118ae9a6cbf2037bd7c commit: fc9471a888f373aedff3c118ae9a6cbf2037bd7c branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-24T19:46:16-08:00 summary: bpo-17232: Clarify docs for -O and -OO command line options (GH-5839) The 'optimization' is for space in the executable file, not for run time. (cherry picked from commit 186b606d8a2ea4fd51b7286813302c8e8c7006cc) Co-authored-by: Cheryl Sabella files: A Misc/NEWS.d/next/Documentation/2018-02-23-12-48-03.bpo-17232.tmuTKL.rst M Doc/using/cmdline.rst M Misc/python.man M Modules/main.c diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst index 9ffb71496316..8463ad9f2fe7 100644 --- a/Doc/using/cmdline.rst +++ b/Doc/using/cmdline.rst @@ -246,12 +246,23 @@ Miscellaneous options .. cmdoption:: -O - Turn on basic optimizations. See also :envvar:`PYTHONOPTIMIZE`. + Remove assert statements and any code conditional on the value of + :const:`__debug__`. Augment the filename for compiled + (:term:`bytecode`) files by adding ``.opt-1`` before the ``.pyc`` + extension (see :pep:`488`). See also :envvar:`PYTHONOPTIMIZE`. + + .. versionchanged:: 3.5 + Modify ``.pyc`` filenames according to :pep:`488`. .. cmdoption:: -OO - Discard docstrings in addition to the :option:`-O` optimizations. + Do :option:`-O` and also discard docstrings. Augment the filename + for compiled (:term:`bytecode`) files by adding ``.opt-2`` before the + ``.pyc`` extension (see :pep:`488`). + + .. versionchanged:: 3.5 + Modify ``.pyc`` filenames according to :pep:`488`. .. cmdoption:: -q diff --git a/Misc/NEWS.d/next/Documentation/2018-02-23-12-48-03.bpo-17232.tmuTKL.rst b/Misc/NEWS.d/next/Documentation/2018-02-23-12-48-03.bpo-17232.tmuTKL.rst new file mode 100644 index 000000000000..5c14e91b3919 --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2018-02-23-12-48-03.bpo-17232.tmuTKL.rst @@ -0,0 +1 @@ +Clarify docs for -O and -OO. Patch by Terry Reedy. diff --git a/Misc/python.man b/Misc/python.man index 075b974e9049..ad3ea6a431f5 100644 --- a/Misc/python.man +++ b/Misc/python.man @@ -156,10 +156,13 @@ for the named module and runs the corresponding file as a script. .TP .B \-O -Turn on basic optimizations. Given twice, causes docstrings to be discarded. +Remove assert statements and any code conditional on the value of +__debug__; augment the filename for compiled (bytecode) files by +adding .opt-1 before the .pyc extension. .TP .B \-OO -Discard docstrings in addition to the \fB-O\fP optimizations. +Do \fB-O\fP and also discard docstrings; change the filename for +compiled (bytecode) files by adding .opt-2 before the .pyc extension. .TP .B \-q Do not print the version and copyright messages. These messages are diff --git a/Modules/main.c b/Modules/main.c index 3ac405c0bd91..585d6965dd36 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -64,8 +64,10 @@ static const char usage_2[] = "\ if stdin does not appear to be a terminal; also PYTHONINSPECT=x\n\ -I : isolate Python from the user's environment (implies -E and -s)\n\ -m mod : run library module as a script (terminates option list)\n\ --O : optimize generated bytecode slightly; also PYTHONOPTIMIZE=x\n\ --OO : remove doc-strings in addition to the -O optimizations\n\ +-O : remove assert and __debug__-dependent statements; add .opt-1 before\n\ + .pyc extension; also PYTHONOPTIMIZE=x\n\ +-OO : do -O changes and also discard docstrings; add .opt-2 before\n\ + .pyc extension\n\ -q : don't print version and copyright messages on interactive startup\n\ -s : don't add user site directory to sys.path; also PYTHONNOUSERSITE\n\ -S : don't imply 'import site' on initialization\n\ From webhook-mailer at python.org Sun Feb 25 03:47:05 2018 From: webhook-mailer at python.org (Christian Heimes) Date: Sun, 25 Feb 2018 08:47:05 -0000 Subject: [Python-checkins] bpo-32185: Don't send IP in SNI TLS extension (#5865) Message-ID: https://github.com/python/cpython/commit/e9370a47389903bb72badc95032ec84a0ebbf8cc commit: e9370a47389903bb72badc95032ec84a0ebbf8cc branch: 3.6 author: Christian Heimes committer: GitHub date: 2018-02-25T09:47:02+01:00 summary: bpo-32185: Don't send IP in SNI TLS extension (#5865) The SSL module no longer sends IP addresses in SNI TLS extension on platforms with OpenSSL 1.0.2+ or inet_pton. Signed-off-by: Christian Heimes files: A Misc/NEWS.d/next/Library/2017-12-20-09-25-10.bpo-32185.IL0cMt.rst M Modules/_ssl.c diff --git a/Misc/NEWS.d/next/Library/2017-12-20-09-25-10.bpo-32185.IL0cMt.rst b/Misc/NEWS.d/next/Library/2017-12-20-09-25-10.bpo-32185.IL0cMt.rst new file mode 100644 index 000000000000..bfb2533b5dcf --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-20-09-25-10.bpo-32185.IL0cMt.rst @@ -0,0 +1,2 @@ +The SSL module no longer sends IP addresses in SNI TLS extension on +platforms with OpenSSL 1.0.2+ or inet_pton. diff --git a/Modules/_ssl.c b/Modules/_ssl.c index df8c6a7d96d8..e8cffef14de0 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -55,6 +55,11 @@ static PySocketModule_APIObject PySocketModule; #include #endif +#ifndef MS_WINDOWS +/* inet_pton */ +#include +#endif + /* Don't warn about deprecated functions */ #ifdef __GNUC__ #pragma GCC diagnostic ignored "-Wdeprecated-declarations" @@ -667,8 +672,41 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock, SSL_set_mode(self->ssl, mode); #if HAVE_SNI - if (server_hostname != NULL) - SSL_set_tlsext_host_name(self->ssl, server_hostname); + if (server_hostname != NULL) { +/* Don't send SNI for IP addresses. We cannot simply use inet_aton() and + * inet_pton() here. inet_aton() may be linked weakly and inet_pton() isn't + * available on all platforms. Use OpenSSL's IP address parser. It's + * available since 1.0.2 and LibreSSL since at least 2.3.0. */ + int send_sni = 1; +#if OPENSSL_VERSION_NUMBER >= 0x10200000L + ASN1_OCTET_STRING *ip = a2i_IPADDRESS(server_hostname); + if (ip == NULL) { + send_sni = 1; + ERR_clear_error(); + } else { + send_sni = 0; + ASN1_OCTET_STRING_free(ip); + } +#elif defined(HAVE_INET_PTON) +#ifdef ENABLE_IPV6 + char packed[Py_MAX(sizeof(struct in_addr), sizeof(struct in6_addr))]; +#else + char packed[sizeof(struct in_addr)]; +#endif /* ENABLE_IPV6 */ + if (inet_pton(AF_INET, server_hostname, packed)) { + send_sni = 0; +#ifdef ENABLE_IPV6 + } else if(inet_pton(AF_INET6, server_hostname, packed)) { + send_sni = 0; +#endif /* ENABLE_IPV6 */ + } else { + send_sni = 1; + } +#endif /* HAVE_INET_PTON */ + if (send_sni) { + SSL_set_tlsext_host_name(self->ssl, server_hostname); + } + } #endif /* If the socket is in non-blocking mode or timeout mode, set the BIO From webhook-mailer at python.org Sun Feb 25 03:48:04 2018 From: webhook-mailer at python.org (Christian Heimes) Date: Sun, 25 Feb 2018 08:48:04 -0000 Subject: [Python-checkins] bpo-25404: SSLContext.load_dh_params() non-ASCII path (GH-3459) Message-ID: https://github.com/python/cpython/commit/6e8f395001b026daea047cf225dcca5a973ae824 commit: 6e8f395001b026daea047cf225dcca5a973ae824 branch: 2.7 author: Christian Heimes committer: GitHub date: 2018-02-25T09:48:02+01:00 summary: bpo-25404: SSLContext.load_dh_params() non-ASCII path (GH-3459) SSLContext.load_dh_params() now supports non-ASCII path. Signed-off-by: Christian Heimes files: A Misc/NEWS.d/next/Library/2017-09-08-11-04-10.bpo-25404.pXetCl.rst M Lib/test/test_ssl.py M Modules/_ssl.c diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index f172520011f4..b59fe73f04c7 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -14,7 +14,7 @@ import os import errno import pprint -import tempfile +import shutil import urllib2 import traceback import weakref @@ -1000,6 +1000,10 @@ def test_load_dh_params(self): self.assertEqual(cm.exception.errno, errno.ENOENT) 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') + shutil.copy(DHFILE, fname) + ctx.load_dh_params(fname) @skip_if_broken_ubuntu_ssl def test_session_stats(self): diff --git a/Misc/NEWS.d/next/Library/2017-09-08-11-04-10.bpo-25404.pXetCl.rst b/Misc/NEWS.d/next/Library/2017-09-08-11-04-10.bpo-25404.pXetCl.rst new file mode 100644 index 000000000000..f816d7a0e874 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-09-08-11-04-10.bpo-25404.pXetCl.rst @@ -0,0 +1 @@ +SSLContext.load_dh_params() now supports non-ASCII path. diff --git a/Modules/_ssl.c b/Modules/_ssl.c index f70af266731a..ec61a700b042 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -2983,13 +2983,25 @@ load_dh_params(PySSLContext *self, PyObject *filepath) { BIO *bio; DH *dh; - char *path = PyBytes_AsString(filepath); - if (!path) { - return NULL; + PyObject *filepath_bytes = NULL; + + if (PyString_Check(filepath)) { + Py_INCREF(filepath); + filepath_bytes = filepath; + } else { + PyObject *u = PyUnicode_FromObject(filepath); + if (!u) + return NULL; + filepath_bytes = PyUnicode_AsEncodedString( + u, Py_FileSystemDefaultEncoding, NULL); + Py_DECREF(u); + if (!filepath_bytes) + return NULL; } - bio = BIO_new_file(path, "r"); + bio = BIO_new_file(PyBytes_AS_STRING(filepath_bytes), "r"); if (bio == NULL) { + Py_DECREF(filepath_bytes); ERR_clear_error(); PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, filepath); return NULL; @@ -2998,6 +3010,7 @@ load_dh_params(PySSLContext *self, PyObject *filepath) PySSL_BEGIN_ALLOW_THREADS dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); BIO_free(bio); + Py_DECREF(filepath_bytes); PySSL_END_ALLOW_THREADS if (dh == NULL) { if (errno != 0) { From webhook-mailer at python.org Sun Feb 25 03:49:34 2018 From: webhook-mailer at python.org (Christian Heimes) Date: Sun, 25 Feb 2018 08:49:34 -0000 Subject: [Python-checkins] bpo-31809: test secp ECDH curves (#4036) Message-ID: https://github.com/python/cpython/commit/b7b9225831a729bff84eb7c43bad138416b994fe commit: b7b9225831a729bff84eb7c43bad138416b994fe branch: master author: Christian Heimes committer: GitHub date: 2018-02-25T09:49:31+01:00 summary: bpo-31809: test secp ECDH curves (#4036) Add tests to verify connection with secp384r1 ECDH curves. files: A Misc/NEWS.d/next/Tests/2017-10-18-18-07-45.bpo-31809.KlQrkE.rst M Lib/test/test_ssl.py diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 3f2c50b7795a..3b34fc0e0033 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -143,6 +143,21 @@ def have_verify_flags(): # 0.9.8 or higher return ssl.OPENSSL_VERSION_INFO >= (0, 9, 8, 0, 15) +def _have_secp_curves(): + if not ssl.HAS_ECDH: + return False + ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) + try: + ctx.set_ecdh_curve("secp384r1") + except ValueError: + return False + else: + return True + + +HAVE_SECP_CURVES = _have_secp_curves() + + def utc_offset(): #NOTE: ignore issues like #1647654 # local time = utc time + utc offset if time.daylight and time.localtime().tm_isdst > 0: @@ -3523,6 +3538,43 @@ def test_dh_params(self): if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts: self.fail("Non-DH cipher: " + cipher[0]) + @unittest.skipUnless(HAVE_SECP_CURVES, "needs secp384r1 curve support") + def test_ecdh_curve(self): + # server secp384r1, client auto + client_context, server_context, hostname = testing_context() + server_context.set_ecdh_curve("secp384r1") + server_context.set_ciphers("ECDHE:!eNULL:!aNULL") + server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 + stats = server_params_test(client_context, server_context, + chatty=True, connectionchatty=True, + sni_name=hostname) + + # server auto, client secp384r1 + client_context, server_context, hostname = testing_context() + client_context.set_ecdh_curve("secp384r1") + server_context.set_ciphers("ECDHE:!eNULL:!aNULL") + server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 + stats = server_params_test(client_context, server_context, + chatty=True, connectionchatty=True, + sni_name=hostname) + + # server / client curve mismatch + client_context, server_context, hostname = testing_context() + client_context.set_ecdh_curve("prime256v1") + server_context.set_ecdh_curve("secp384r1") + server_context.set_ciphers("ECDHE:!eNULL:!aNULL") + server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 + try: + stats = server_params_test(client_context, server_context, + chatty=True, connectionchatty=True, + sni_name=hostname) + except ssl.SSLError: + pass + else: + # OpenSSL 1.0.2 does not fail although it should. + if IS_OPENSSL_1_1: + self.fail("mismatch curve did not fail") + def test_selected_alpn_protocol(self): # selected_alpn_protocol() is None unless ALPN is used. client_context, server_context, hostname = testing_context() diff --git a/Misc/NEWS.d/next/Tests/2017-10-18-18-07-45.bpo-31809.KlQrkE.rst b/Misc/NEWS.d/next/Tests/2017-10-18-18-07-45.bpo-31809.KlQrkE.rst new file mode 100644 index 000000000000..8a48508b8c1f --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2017-10-18-18-07-45.bpo-31809.KlQrkE.rst @@ -0,0 +1 @@ +Add tests to verify connection with secp ECDH curves. From solipsis at pitrou.net Sun Feb 25 04:10:32 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 25 Feb 2018 09:10:32 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=4 Message-ID: <20180225091032.1.A044EC092C126FC6@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/reflogjkFnkF', '--timeout', '7200'] From webhook-mailer at python.org Sun Feb 25 04:16:40 2018 From: webhook-mailer at python.org (Christian Heimes) Date: Sun, 25 Feb 2018 09:16:40 -0000 Subject: [Python-checkins] [2.7] bpo-32185: Don't send IP in SNI TLS extension (GH-5865) (#5871) Message-ID: https://github.com/python/cpython/commit/a5c9112300ecd492ed6cc9759dc8028766401f61 commit: a5c9112300ecd492ed6cc9759dc8028766401f61 branch: 2.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Christian Heimes date: 2018-02-25T10:16:37+01:00 summary: [2.7] bpo-32185: Don't send IP in SNI TLS extension (GH-5865) (#5871) The SSL module no longer sends IP addresses in SNI TLS extension on platforms with OpenSSL 1.0.2+ or inet_pton. Signed-off-by: Christian Heimes (cherry picked from commit e9370a47389903bb72badc95032ec84a0ebbf8cc) Co-authored-by: Christian Heimes files: A Misc/NEWS.d/next/Library/2017-12-20-09-25-10.bpo-32185.IL0cMt.rst M Modules/_ssl.c diff --git a/Misc/NEWS.d/next/Library/2017-12-20-09-25-10.bpo-32185.IL0cMt.rst b/Misc/NEWS.d/next/Library/2017-12-20-09-25-10.bpo-32185.IL0cMt.rst new file mode 100644 index 000000000000..bfb2533b5dcf --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-20-09-25-10.bpo-32185.IL0cMt.rst @@ -0,0 +1,2 @@ +The SSL module no longer sends IP addresses in SNI TLS extension on +platforms with OpenSSL 1.0.2+ or inet_pton. diff --git a/Modules/_ssl.c b/Modules/_ssl.c index ec61a700b042..f09f9c9ea2f2 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -52,6 +52,11 @@ #include #endif +#ifndef MS_WINDOWS +/* inet_pton */ +#include +#endif + /* Don't warn about deprecated functions */ #ifdef __GNUC__ #pragma GCC diagnostic ignored "-Wdeprecated-declarations" @@ -575,8 +580,41 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock, SSL_set_mode(self->ssl, mode); #if HAVE_SNI - if (server_hostname != NULL) - SSL_set_tlsext_host_name(self->ssl, server_hostname); + if (server_hostname != NULL) { +/* Don't send SNI for IP addresses. We cannot simply use inet_aton() and + * inet_pton() here. inet_aton() may be linked weakly and inet_pton() isn't + * available on all platforms. Use OpenSSL's IP address parser. It's + * available since 1.0.2 and LibreSSL since at least 2.3.0. */ + int send_sni = 1; +#if OPENSSL_VERSION_NUMBER >= 0x10200000L + ASN1_OCTET_STRING *ip = a2i_IPADDRESS(server_hostname); + if (ip == NULL) { + send_sni = 1; + ERR_clear_error(); + } else { + send_sni = 0; + ASN1_OCTET_STRING_free(ip); + } +#elif defined(HAVE_INET_PTON) +#ifdef ENABLE_IPV6 + char packed[Py_MAX(sizeof(struct in_addr), sizeof(struct in6_addr))]; +#else + char packed[sizeof(struct in_addr)]; +#endif /* ENABLE_IPV6 */ + if (inet_pton(AF_INET, server_hostname, packed)) { + send_sni = 0; +#ifdef ENABLE_IPV6 + } else if(inet_pton(AF_INET6, server_hostname, packed)) { + send_sni = 0; +#endif /* ENABLE_IPV6 */ + } else { + send_sni = 1; + } +#endif /* HAVE_INET_PTON */ + if (send_sni) { + SSL_set_tlsext_host_name(self->ssl, server_hostname); + } + } #endif /* If the socket is in non-blocking mode or timeout mode, set the BIO From webhook-mailer at python.org Sun Feb 25 04:20:50 2018 From: webhook-mailer at python.org (Christian Heimes) Date: Sun, 25 Feb 2018 09:20:50 -0000 Subject: [Python-checkins] [3.6] bpo-30622: Improve NPN support detection (GH-5859) (#5861) Message-ID: https://github.com/python/cpython/commit/48707a1baf4fd553fbc4516d9080cb3968af21aa commit: 48707a1baf4fd553fbc4516d9080cb3968af21aa branch: 3.6 author: Christian Heimes committer: GitHub date: 2018-02-25T10:20:47+01:00 summary: [3.6] bpo-30622: Improve NPN support detection (GH-5859) (#5861) The ssl module now detects missing NPN support in LibreSSL. Co-Authored-By: Bernard Spil Signed-off-by: Christian Heimes . (cherry picked from commit 6cdb7954b0a578d899e4b78b868ea59eef08480a) Co-authored-by: Christian Heimes files: A Misc/NEWS.d/next/Library/2018-02-24-21-40-42.bpo-30622.dQjxSe.rst M Doc/library/ssl.rst M Modules/_ssl.c M Modules/clinic/_ssl.c.h diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 1c9e597306a9..fc68e3071436 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -2320,6 +2320,23 @@ successful call of :func:`~ssl.RAND_add`, :func:`~ssl.RAND_bytes` or :func:`~ssl.RAND_pseudo_bytes` is sufficient. +.. ssl-libressl: + +LibreSSL support +---------------- + +LibreSSL is a fork of OpenSSL 1.0.1. The ssl module has limited support for +LibreSSL. Some features are not available when the ssl module is compiled +with LibreSSL. + +* LibreSSL >= 2.6.1 no longer supports NPN. The methods + :meth:`SSLContext.set_npn_protocols` and + :meth:`SSLSocket.selected_npn_protocol` are not available. +* :meth:`SSLContext.set_default_verify_paths` ignores the env vars + :envvar:`SSL_CERT_FILE` and :envvar:`SSL_CERT_PATH` although + :func:`get_default_verify_paths` still reports them. + + .. seealso:: Class :class:`socket.socket` diff --git a/Misc/NEWS.d/next/Library/2018-02-24-21-40-42.bpo-30622.dQjxSe.rst b/Misc/NEWS.d/next/Library/2018-02-24-21-40-42.bpo-30622.dQjxSe.rst new file mode 100644 index 000000000000..bcb659b24dd3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-24-21-40-42.bpo-30622.dQjxSe.rst @@ -0,0 +1 @@ +The ssl module now detects missing NPN support in LibreSSL. diff --git a/Modules/_ssl.c b/Modules/_ssl.c index e8cffef14de0..ad4915bb6903 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -130,6 +130,19 @@ struct py_ssl_library_code { # define HAVE_ALPN #endif +/* We cannot rely on OPENSSL_NO_NEXTPROTONEG because LibreSSL 2.6.1 dropped + * NPN support but did not set OPENSSL_NO_NEXTPROTONEG for compatibility + * reasons. The check for TLSEXT_TYPE_next_proto_neg works with + * OpenSSL 1.0.1+ and LibreSSL. + */ +#ifdef OPENSSL_NO_NEXTPROTONEG +# define HAVE_NPN 0 +#elif defined(TLSEXT_TYPE_next_proto_neg) +# define HAVE_NPN 1 +#else +# define HAVE_NPN 0 +# endif + #ifndef INVALID_SOCKET /* MS defines this */ #define INVALID_SOCKET (-1) #endif @@ -284,7 +297,7 @@ static unsigned int _ssl_locks_count = 0; typedef struct { PyObject_HEAD SSL_CTX *ctx; -#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG) +#ifdef HAVE_NPN unsigned char *npn_protocols; int npn_protocols_len; #endif @@ -1776,7 +1789,7 @@ _ssl__SSLSocket_version_impl(PySSLSocket *self) return PyUnicode_FromString(version); } -#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG) +#ifdef HAVE_NPN /*[clinic input] _ssl._SSLSocket.selected_npn_protocol [clinic start generated code]*/ @@ -2729,7 +2742,7 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version) return NULL; } self->ctx = ctx; -#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG) +#ifdef HAVE_NPN self->npn_protocols = NULL; #endif #ifdef HAVE_ALPN @@ -2864,7 +2877,7 @@ context_dealloc(PySSLContext *self) PyObject_GC_UnTrack(self); context_clear(self); SSL_CTX_free(self->ctx); -#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG) +#ifdef HAVE_NPN PyMem_FREE(self->npn_protocols); #endif #ifdef HAVE_ALPN @@ -2942,7 +2955,7 @@ _ssl__SSLContext_get_ciphers_impl(PySSLContext *self) #endif -#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG) || defined(HAVE_ALPN) +#if defined(HAVE_NPN) || defined(HAVE_ALPN) static int do_protocol_selection(int alpn, unsigned char **out, unsigned char *outlen, const unsigned char *server_protocols, unsigned int server_protocols_len, @@ -2968,7 +2981,7 @@ do_protocol_selection(int alpn, unsigned char **out, unsigned char *outlen, } #endif -#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG) +#ifdef HAVE_NPN /* this callback gets passed to SSL_CTX_set_next_protos_advertise_cb */ static int _advertiseNPN_cb(SSL *s, @@ -3011,7 +3024,7 @@ _ssl__SSLContext__set_npn_protocols_impl(PySSLContext *self, Py_buffer *protos) /*[clinic end generated code: output=72b002c3324390c6 input=319fcb66abf95bd7]*/ { -#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG) +#ifdef HAVE_NPN PyMem_Free(self->npn_protocols); self->npn_protocols = PyMem_Malloc(protos->len); if (self->npn_protocols == NULL) @@ -5481,7 +5494,7 @@ PyInit__ssl(void) Py_INCREF(r); PyModule_AddObject(m, "HAS_ECDH", r); -#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG) +#ifdef HAVE_NPN r = Py_True; #else r = Py_False; diff --git a/Modules/clinic/_ssl.c.h b/Modules/clinic/_ssl.c.h index 6f748903f4eb..750ad684573f 100644 --- a/Modules/clinic/_ssl.c.h +++ b/Modules/clinic/_ssl.c.h @@ -132,7 +132,7 @@ _ssl__SSLSocket_version(PySSLSocket *self, PyObject *Py_UNUSED(ignored)) return _ssl__SSLSocket_version_impl(self); } -#if (defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)) +#if defined(HAVE_NPN) PyDoc_STRVAR(_ssl__SSLSocket_selected_npn_protocol__doc__, "selected_npn_protocol($self, /)\n" @@ -151,7 +151,7 @@ _ssl__SSLSocket_selected_npn_protocol(PySSLSocket *self, PyObject *Py_UNUSED(ign return _ssl__SSLSocket_selected_npn_protocol_impl(self); } -#endif /* (defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)) */ +#endif /* defined(HAVE_NPN) */ #if defined(HAVE_ALPN) @@ -1168,4 +1168,4 @@ _ssl_enum_crls(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kw #ifndef _SSL_ENUM_CRLS_METHODDEF #define _SSL_ENUM_CRLS_METHODDEF #endif /* !defined(_SSL_ENUM_CRLS_METHODDEF) */ -/*[clinic end generated code: output=a8b184655068c238 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=3d801e1145e7a94e input=a9049054013a1b77]*/ From webhook-mailer at python.org Sun Feb 25 04:21:06 2018 From: webhook-mailer at python.org (Christian Heimes) Date: Sun, 25 Feb 2018 09:21:06 -0000 Subject: [Python-checkins] [2.7] bpo-30622: Improve NPN support detection (GH-5859) (#5863) Message-ID: https://github.com/python/cpython/commit/3d87f4cf9c19da9fe8ae8f91f5bb86e642b74a50 commit: 3d87f4cf9c19da9fe8ae8f91f5bb86e642b74a50 branch: 2.7 author: Christian Heimes committer: GitHub date: 2018-02-25T10:21:03+01:00 summary: [2.7] bpo-30622: Improve NPN support detection (GH-5859) (#5863) The ssl module now detects missing NPN support in LibreSSL. Co-Authored-By: Bernard Spil Signed-off-by: Christian Heimes . (cherry picked from commit 6cdb7954b0a578d899e4b78b868ea59eef08480a) Co-authored-by: Christian Heimes files: A Misc/NEWS.d/next/Library/2018-02-24-21-40-42.bpo-30622.dQjxSe.rst M Doc/library/ssl.rst M Modules/_ssl.c diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 0ac06fa166f6..89b9ff3621f7 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -1808,6 +1808,23 @@ successful call of :func:`~ssl.RAND_add`, :func:`~ssl.RAND_bytes` or :func:`~ssl.RAND_pseudo_bytes` is sufficient. +.. ssl-libressl: + +LibreSSL support +---------------- + +LibreSSL is a fork of OpenSSL 1.0.1. The ssl module has limited support for +LibreSSL. Some features are not available when the ssl module is compiled +with LibreSSL. + +* LibreSSL >= 2.6.1 no longer supports NPN. The methods + :meth:`SSLContext.set_npn_protocols` and + :meth:`SSLSocket.selected_npn_protocol` are not available. +* :meth:`SSLContext.set_default_verify_paths` ignores the env vars + :envvar:`SSL_CERT_FILE` and :envvar:`SSL_CERT_PATH` although + :func:`get_default_verify_paths` still reports them. + + .. seealso:: Class :class:`socket.socket` diff --git a/Misc/NEWS.d/next/Library/2018-02-24-21-40-42.bpo-30622.dQjxSe.rst b/Misc/NEWS.d/next/Library/2018-02-24-21-40-42.bpo-30622.dQjxSe.rst new file mode 100644 index 000000000000..bcb659b24dd3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-24-21-40-42.bpo-30622.dQjxSe.rst @@ -0,0 +1 @@ +The ssl module now detects missing NPN support in LibreSSL. diff --git a/Modules/_ssl.c b/Modules/_ssl.c index f09f9c9ea2f2..af66a581e15a 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -127,6 +127,19 @@ struct py_ssl_library_code { # define HAVE_ALPN #endif +/* We cannot rely on OPENSSL_NO_NEXTPROTONEG because LibreSSL 2.6.1 dropped + * NPN support but did not set OPENSSL_NO_NEXTPROTONEG for compatibility + * reasons. The check for TLSEXT_TYPE_next_proto_neg works with + * OpenSSL 1.0.1+ and LibreSSL. + */ +#ifdef OPENSSL_NO_NEXTPROTONEG +# define HAVE_NPN 0 +#elif defined(TLSEXT_TYPE_next_proto_neg) +# define HAVE_NPN 1 +#else +# define HAVE_NPN 0 +# endif + #ifndef INVALID_SOCKET /* MS defines this */ #define INVALID_SOCKET (-1) #endif @@ -285,7 +298,7 @@ static unsigned int _ssl_locks_count = 0; typedef struct { PyObject_HEAD SSL_CTX *ctx; -#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG) +#ifdef HAVE_NPN unsigned char *npn_protocols; int npn_protocols_len; #endif @@ -2195,7 +2208,7 @@ context_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return NULL; } self->ctx = ctx; -#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG) +#ifdef HAVE_NPN self->npn_protocols = NULL; #endif #ifdef HAVE_ALPN @@ -2273,7 +2286,7 @@ context_dealloc(PySSLContext *self) PyObject_GC_UnTrack(self); context_clear(self); SSL_CTX_free(self->ctx); -#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG) +#ifdef HAVE_NPN PyMem_FREE(self->npn_protocols); #endif #ifdef HAVE_ALPN @@ -2303,7 +2316,7 @@ set_ciphers(PySSLContext *self, PyObject *args) Py_RETURN_NONE; } -#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG) || defined(HAVE_ALPN) +#if defined(HAVE_NPN) || defined(HAVE_ALPN) static int do_protocol_selection(int alpn, unsigned char **out, unsigned char *outlen, const unsigned char *server_protocols, unsigned int server_protocols_len, @@ -2329,7 +2342,7 @@ do_protocol_selection(int alpn, unsigned char **out, unsigned char *outlen, } #endif -#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG) +#ifdef HAVE_NPN /* this callback gets passed to SSL_CTX_set_next_protos_advertise_cb */ static int _advertiseNPN_cb(SSL *s, @@ -2364,7 +2377,7 @@ _selectNPN_cb(SSL *s, static PyObject * _set_npn_protocols(PySSLContext *self, PyObject *args) { -#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG) +#ifdef HAVE_NPN Py_buffer protos; if (!PyArg_ParseTuple(args, "s*:set_npn_protocols", &protos)) @@ -4373,7 +4386,7 @@ init_ssl(void) Py_INCREF(r); PyModule_AddObject(m, "HAS_ECDH", r); -#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG) +#ifdef HAVE_NPN r = Py_True; #else r = Py_False; From webhook-mailer at python.org Sun Feb 25 04:22:17 2018 From: webhook-mailer at python.org (Christian Heimes) Date: Sun, 25 Feb 2018 09:22:17 -0000 Subject: [Python-checkins] bpo-32647: Link ctypes extension with libdl. (#5550) Message-ID: https://github.com/python/cpython/commit/5bb9692575f10f4a7c7f1c2c0c70956baf6d5c23 commit: 5bb9692575f10f4a7c7f1c2c0c70956baf6d5c23 branch: master author: Christian Heimes committer: GitHub date: 2018-02-25T10:22:14+01:00 summary: bpo-32647: Link ctypes extension with libdl. (#5550) The ctypes module used to depend on indirect linking for dlopen. The shared extension is now explicitly linked against libdl on platforms with dl. Signed-off-by: Christian Heimes files: A Misc/NEWS.d/next/Library/2018-02-05-13-31-42.bpo-32647.ktmfR_.rst M setup.py diff --git a/Misc/NEWS.d/next/Library/2018-02-05-13-31-42.bpo-32647.ktmfR_.rst b/Misc/NEWS.d/next/Library/2018-02-05-13-31-42.bpo-32647.ktmfR_.rst new file mode 100644 index 000000000000..04fc0247bcde --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-05-13-31-42.bpo-32647.ktmfR_.rst @@ -0,0 +1,2 @@ +The ctypes module used to depend on indirect linking for dlopen. The shared +extension is now explicitly linked against libdl on platforms with dl. diff --git a/setup.py b/setup.py index f4f6e4fdb1f0..8536c350fe3a 100644 --- a/setup.py +++ b/setup.py @@ -2005,6 +2005,10 @@ def detect_ctypes(self, inc_dirs, lib_dirs): ext.libraries.append(ffi_lib) self.use_system_libffi = True + if sysconfig.get_config_var('HAVE_LIBDL'): + # for dlopen, see bpo-32647 + ext.libraries.append('dl') + def _decimal_ext(self): extra_compile_args = [] undef_macros = [] From webhook-mailer at python.org Sun Feb 25 04:56:14 2018 From: webhook-mailer at python.org (Christian Heimes) Date: Sun, 25 Feb 2018 09:56:14 -0000 Subject: [Python-checkins] [3.7] bpo-31809: test secp ECDH curves (GH-4036) (#5872) Message-ID: https://github.com/python/cpython/commit/ff7528f089b60f8372c658f3bc3b14b059114da9 commit: ff7528f089b60f8372c658f3bc3b14b059114da9 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Christian Heimes date: 2018-02-25T10:56:11+01:00 summary: [3.7] bpo-31809: test secp ECDH curves (GH-4036) (#5872) Add tests to verify connection with secp384r1 ECDH curves. (cherry picked from commit b7b9225831a729bff84eb7c43bad138416b994fe) Co-authored-by: Christian Heimes files: A Misc/NEWS.d/next/Tests/2017-10-18-18-07-45.bpo-31809.KlQrkE.rst M Lib/test/test_ssl.py diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 3f2c50b7795a..3b34fc0e0033 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -143,6 +143,21 @@ def have_verify_flags(): # 0.9.8 or higher return ssl.OPENSSL_VERSION_INFO >= (0, 9, 8, 0, 15) +def _have_secp_curves(): + if not ssl.HAS_ECDH: + return False + ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) + try: + ctx.set_ecdh_curve("secp384r1") + except ValueError: + return False + else: + return True + + +HAVE_SECP_CURVES = _have_secp_curves() + + def utc_offset(): #NOTE: ignore issues like #1647654 # local time = utc time + utc offset if time.daylight and time.localtime().tm_isdst > 0: @@ -3523,6 +3538,43 @@ def test_dh_params(self): if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts: self.fail("Non-DH cipher: " + cipher[0]) + @unittest.skipUnless(HAVE_SECP_CURVES, "needs secp384r1 curve support") + def test_ecdh_curve(self): + # server secp384r1, client auto + client_context, server_context, hostname = testing_context() + server_context.set_ecdh_curve("secp384r1") + server_context.set_ciphers("ECDHE:!eNULL:!aNULL") + server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 + stats = server_params_test(client_context, server_context, + chatty=True, connectionchatty=True, + sni_name=hostname) + + # server auto, client secp384r1 + client_context, server_context, hostname = testing_context() + client_context.set_ecdh_curve("secp384r1") + server_context.set_ciphers("ECDHE:!eNULL:!aNULL") + server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 + stats = server_params_test(client_context, server_context, + chatty=True, connectionchatty=True, + sni_name=hostname) + + # server / client curve mismatch + client_context, server_context, hostname = testing_context() + client_context.set_ecdh_curve("prime256v1") + server_context.set_ecdh_curve("secp384r1") + server_context.set_ciphers("ECDHE:!eNULL:!aNULL") + server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 + try: + stats = server_params_test(client_context, server_context, + chatty=True, connectionchatty=True, + sni_name=hostname) + except ssl.SSLError: + pass + else: + # OpenSSL 1.0.2 does not fail although it should. + if IS_OPENSSL_1_1: + self.fail("mismatch curve did not fail") + def test_selected_alpn_protocol(self): # selected_alpn_protocol() is None unless ALPN is used. client_context, server_context, hostname = testing_context() diff --git a/Misc/NEWS.d/next/Tests/2017-10-18-18-07-45.bpo-31809.KlQrkE.rst b/Misc/NEWS.d/next/Tests/2017-10-18-18-07-45.bpo-31809.KlQrkE.rst new file mode 100644 index 000000000000..8a48508b8c1f --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2017-10-18-18-07-45.bpo-31809.KlQrkE.rst @@ -0,0 +1 @@ +Add tests to verify connection with secp ECDH curves. From webhook-mailer at python.org Sun Feb 25 06:31:21 2018 From: webhook-mailer at python.org (Christian Heimes) Date: Sun, 25 Feb 2018 11:31:21 -0000 Subject: [Python-checkins] [2.7] bpo-32647: Link ctypes extension with libdl. (GH-5550) (#5877) Message-ID: https://github.com/python/cpython/commit/4bb9b9aea04b1a96632da1b30a58fb31cbe6ec92 commit: 4bb9b9aea04b1a96632da1b30a58fb31cbe6ec92 branch: 2.7 author: Christian Heimes committer: GitHub date: 2018-02-25T12:31:17+01:00 summary: [2.7] bpo-32647: Link ctypes extension with libdl. (GH-5550) (#5877) The ctypes module used to depend on indirect linking for dlopen. The shared extension is now explicitly linked against libdl on platforms with dl. Signed-off-by: Christian Heimes . (cherry picked from commit 5bb9692575f10f4a7c7f1c2c0c70956baf6d5c23) Co-authored-by: Christian Heimes files: A Misc/NEWS.d/next/Library/2018-02-05-13-31-42.bpo-32647.ktmfR_.rst M setup.py diff --git a/Misc/NEWS.d/next/Library/2018-02-05-13-31-42.bpo-32647.ktmfR_.rst b/Misc/NEWS.d/next/Library/2018-02-05-13-31-42.bpo-32647.ktmfR_.rst new file mode 100644 index 000000000000..04fc0247bcde --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-05-13-31-42.bpo-32647.ktmfR_.rst @@ -0,0 +1,2 @@ +The ctypes module used to depend on indirect linking for dlopen. The shared +extension is now explicitly linked against libdl on platforms with dl. diff --git a/setup.py b/setup.py index c1366c8436ad..33cecc687573 100644 --- a/setup.py +++ b/setup.py @@ -2149,6 +2149,10 @@ def detect_ctypes(self, inc_dirs, lib_dirs): ext.libraries.append(ffi_lib) self.use_system_libffi = True + if sysconfig.get_config_var('HAVE_LIBDL'): + # for dlopen, see bpo-32647 + ext.libraries.append('dl') + def _detect_nis(self, inc_dirs, lib_dirs): if host_platform in {'win32', 'cygwin', 'qnx6'}: return None From webhook-mailer at python.org Sun Feb 25 06:31:36 2018 From: webhook-mailer at python.org (Christian Heimes) Date: Sun, 25 Feb 2018 11:31:36 -0000 Subject: [Python-checkins] bpo-30622: Fix NPN for OpenSSL 1.1.1-pre1 (#5876) Message-ID: https://github.com/python/cpython/commit/29eab55309b9f78b79074d26db16a44e7841c639 commit: 29eab55309b9f78b79074d26db16a44e7841c639 branch: master author: Christian Heimes committer: GitHub date: 2018-02-25T12:31:33+01:00 summary: bpo-30622: Fix NPN for OpenSSL 1.1.1-pre1 (#5876) Signed-off-by: Christian Heimes files: M Modules/_ssl.c M Modules/clinic/_ssl.c.h diff --git a/Modules/_ssl.c b/Modules/_ssl.c index ed6b7a835a94..52695fe39c71 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -157,21 +157,26 @@ static void _PySSLFixErrno(void) { #endif #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation -# define HAVE_ALPN +# define HAVE_ALPN 1 +#else +# define HAVE_ALPN 0 #endif /* We cannot rely on OPENSSL_NO_NEXTPROTONEG because LibreSSL 2.6.1 dropped * NPN support but did not set OPENSSL_NO_NEXTPROTONEG for compatibility * reasons. The check for TLSEXT_TYPE_next_proto_neg works with * OpenSSL 1.0.1+ and LibreSSL. + * OpenSSL 1.1.1-pre1 dropped NPN but still has TLSEXT_TYPE_next_proto_neg. */ #ifdef OPENSSL_NO_NEXTPROTONEG -# define HAVE_NPN 0 +# define HAVE_NPN 0 +#elif (OPENSSL_VERSION_NUMBER >= 0x10101000L) && !defined(LIBRESSL_VERSION_NUMBER) +# define HAVE_NPN 0 #elif defined(TLSEXT_TYPE_next_proto_neg) -# define HAVE_NPN 1 +# define HAVE_NPN 1 #else -# define HAVE_NPN 0 -# endif +# define HAVE_NPN 0 +#endif #ifndef INVALID_SOCKET /* MS defines this */ #define INVALID_SOCKET (-1) @@ -341,11 +346,11 @@ static unsigned int _ssl_locks_count = 0; typedef struct { PyObject_HEAD SSL_CTX *ctx; -#ifdef HAVE_NPN +#if HAVE_NPN unsigned char *npn_protocols; int npn_protocols_len; #endif -#ifdef HAVE_ALPN +#if HAVE_ALPN unsigned char *alpn_protocols; unsigned int alpn_protocols_len; #endif @@ -1922,7 +1927,7 @@ _ssl__SSLSocket_version_impl(PySSLSocket *self) return PyUnicode_FromString(version); } -#ifdef HAVE_NPN +#if HAVE_NPN /*[clinic input] _ssl._SSLSocket.selected_npn_protocol [clinic start generated code]*/ @@ -1943,7 +1948,7 @@ _ssl__SSLSocket_selected_npn_protocol_impl(PySSLSocket *self) } #endif -#ifdef HAVE_ALPN +#if HAVE_ALPN /*[clinic input] _ssl._SSLSocket.selected_alpn_protocol [clinic start generated code]*/ @@ -2887,10 +2892,10 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version) self->ctx = ctx; self->hostflags = X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS; self->protocol = proto_version; -#ifdef HAVE_NPN +#if HAVE_NPN self->npn_protocols = NULL; #endif -#ifdef HAVE_ALPN +#if HAVE_ALPN self->alpn_protocols = NULL; #endif #ifndef OPENSSL_NO_TLSEXT @@ -3026,10 +3031,10 @@ context_dealloc(PySSLContext *self) PyObject_GC_UnTrack(self); context_clear(self); SSL_CTX_free(self->ctx); -#ifdef HAVE_NPN +#if HAVE_NPN PyMem_FREE(self->npn_protocols); #endif -#ifdef HAVE_ALPN +#if HAVE_ALPN PyMem_FREE(self->alpn_protocols); #endif Py_TYPE(self)->tp_free(self); @@ -3104,7 +3109,7 @@ _ssl__SSLContext_get_ciphers_impl(PySSLContext *self) #endif -#if defined(HAVE_NPN) || defined(HAVE_ALPN) +#if HAVE_NPN || HAVE_ALPN static int do_protocol_selection(int alpn, unsigned char **out, unsigned char *outlen, const unsigned char *server_protocols, unsigned int server_protocols_len, @@ -3130,7 +3135,7 @@ do_protocol_selection(int alpn, unsigned char **out, unsigned char *outlen, } #endif -#ifdef HAVE_NPN +#if HAVE_NPN /* this callback gets passed to SSL_CTX_set_next_protos_advertise_cb */ static int _advertiseNPN_cb(SSL *s, @@ -3173,7 +3178,7 @@ _ssl__SSLContext__set_npn_protocols_impl(PySSLContext *self, Py_buffer *protos) /*[clinic end generated code: output=72b002c3324390c6 input=319fcb66abf95bd7]*/ { -#ifdef HAVE_NPN +#if HAVE_NPN PyMem_Free(self->npn_protocols); self->npn_protocols = PyMem_Malloc(protos->len); if (self->npn_protocols == NULL) @@ -3198,7 +3203,7 @@ _ssl__SSLContext__set_npn_protocols_impl(PySSLContext *self, #endif } -#ifdef HAVE_ALPN +#if HAVE_ALPN static int _selectALPN_cb(SSL *s, const unsigned char **out, unsigned char *outlen, @@ -3223,7 +3228,7 @@ _ssl__SSLContext__set_alpn_protocols_impl(PySSLContext *self, Py_buffer *protos) /*[clinic end generated code: output=87599a7f76651a9b input=9bba964595d519be]*/ { -#ifdef HAVE_ALPN +#if HAVE_ALPN if ((size_t)protos->len > UINT_MAX) { PyErr_Format(PyExc_OverflowError, "protocols longer than %d bytes", UINT_MAX); @@ -5718,7 +5723,7 @@ PyInit__ssl(void) Py_INCREF(r); PyModule_AddObject(m, "HAS_ECDH", r); -#ifdef HAVE_NPN +#if HAVE_NPN r = Py_True; #else r = Py_False; @@ -5726,7 +5731,7 @@ PyInit__ssl(void) Py_INCREF(r); PyModule_AddObject(m, "HAS_NPN", r); -#ifdef HAVE_ALPN +#if HAVE_ALPN r = Py_True; #else r = Py_False; diff --git a/Modules/clinic/_ssl.c.h b/Modules/clinic/_ssl.c.h index 1ee1bfb21d3e..5ba34eca594f 100644 --- a/Modules/clinic/_ssl.c.h +++ b/Modules/clinic/_ssl.c.h @@ -132,7 +132,7 @@ _ssl__SSLSocket_version(PySSLSocket *self, PyObject *Py_UNUSED(ignored)) return _ssl__SSLSocket_version_impl(self); } -#if defined(HAVE_NPN) +#if (HAVE_NPN) PyDoc_STRVAR(_ssl__SSLSocket_selected_npn_protocol__doc__, "selected_npn_protocol($self, /)\n" @@ -151,9 +151,9 @@ _ssl__SSLSocket_selected_npn_protocol(PySSLSocket *self, PyObject *Py_UNUSED(ign return _ssl__SSLSocket_selected_npn_protocol_impl(self); } -#endif /* defined(HAVE_NPN) */ +#endif /* (HAVE_NPN) */ -#if defined(HAVE_ALPN) +#if (HAVE_ALPN) PyDoc_STRVAR(_ssl__SSLSocket_selected_alpn_protocol__doc__, "selected_alpn_protocol($self, /)\n" @@ -172,7 +172,7 @@ _ssl__SSLSocket_selected_alpn_protocol(PySSLSocket *self, PyObject *Py_UNUSED(ig return _ssl__SSLSocket_selected_alpn_protocol_impl(self); } -#endif /* defined(HAVE_ALPN) */ +#endif /* (HAVE_ALPN) */ PyDoc_STRVAR(_ssl__SSLSocket_compression__doc__, "compression($self, /)\n" @@ -1175,4 +1175,4 @@ _ssl_enum_crls(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje #ifndef _SSL_ENUM_CRLS_METHODDEF #define _SSL_ENUM_CRLS_METHODDEF #endif /* !defined(_SSL_ENUM_CRLS_METHODDEF) */ -/*[clinic end generated code: output=a00fef6a470cfc2c input=a9049054013a1b77]*/ +/*[clinic end generated code: output=e2417fee28666f7c input=a9049054013a1b77]*/ From webhook-mailer at python.org Sun Feb 25 07:07:27 2018 From: webhook-mailer at python.org (Christian Heimes) Date: Sun, 25 Feb 2018 12:07:27 -0000 Subject: [Python-checkins] [3.7] bpo-32647: Link ctypes extension with libdl. (GH-5550) (#5874) Message-ID: https://github.com/python/cpython/commit/4cb373359d5ff29b222b10207516d294f3a54ad8 commit: 4cb373359d5ff29b222b10207516d294f3a54ad8 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Christian Heimes date: 2018-02-25T13:07:24+01:00 summary: [3.7] bpo-32647: Link ctypes extension with libdl. (GH-5550) (#5874) The ctypes module used to depend on indirect linking for dlopen. The shared extension is now explicitly linked against libdl on platforms with dl. Signed-off-by: Christian Heimes (cherry picked from commit 5bb9692575f10f4a7c7f1c2c0c70956baf6d5c23) Co-authored-by: Christian Heimes files: A Misc/NEWS.d/next/Library/2018-02-05-13-31-42.bpo-32647.ktmfR_.rst M setup.py diff --git a/Misc/NEWS.d/next/Library/2018-02-05-13-31-42.bpo-32647.ktmfR_.rst b/Misc/NEWS.d/next/Library/2018-02-05-13-31-42.bpo-32647.ktmfR_.rst new file mode 100644 index 000000000000..04fc0247bcde --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-05-13-31-42.bpo-32647.ktmfR_.rst @@ -0,0 +1,2 @@ +The ctypes module used to depend on indirect linking for dlopen. The shared +extension is now explicitly linked against libdl on platforms with dl. diff --git a/setup.py b/setup.py index f4f6e4fdb1f0..8536c350fe3a 100644 --- a/setup.py +++ b/setup.py @@ -2005,6 +2005,10 @@ def detect_ctypes(self, inc_dirs, lib_dirs): ext.libraries.append(ffi_lib) self.use_system_libffi = True + if sysconfig.get_config_var('HAVE_LIBDL'): + # for dlopen, see bpo-32647 + ext.libraries.append('dl') + def _decimal_ext(self): extra_compile_args = [] undef_macros = [] From webhook-mailer at python.org Sun Feb 25 07:07:39 2018 From: webhook-mailer at python.org (Christian Heimes) Date: Sun, 25 Feb 2018 12:07:39 -0000 Subject: [Python-checkins] [3.6] bpo-32647: Link ctypes extension with libdl. (GH-5550) (#5875) Message-ID: https://github.com/python/cpython/commit/192bff4e2d196b8933829923ca1db77d8dee67e2 commit: 192bff4e2d196b8933829923ca1db77d8dee67e2 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Christian Heimes date: 2018-02-25T13:07:36+01:00 summary: [3.6] bpo-32647: Link ctypes extension with libdl. (GH-5550) (#5875) The ctypes module used to depend on indirect linking for dlopen. The shared extension is now explicitly linked against libdl on platforms with dl. Signed-off-by: Christian Heimes (cherry picked from commit 5bb9692575f10f4a7c7f1c2c0c70956baf6d5c23) Co-authored-by: Christian Heimes files: A Misc/NEWS.d/next/Library/2018-02-05-13-31-42.bpo-32647.ktmfR_.rst M setup.py diff --git a/Misc/NEWS.d/next/Library/2018-02-05-13-31-42.bpo-32647.ktmfR_.rst b/Misc/NEWS.d/next/Library/2018-02-05-13-31-42.bpo-32647.ktmfR_.rst new file mode 100644 index 000000000000..04fc0247bcde --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-05-13-31-42.bpo-32647.ktmfR_.rst @@ -0,0 +1,2 @@ +The ctypes module used to depend on indirect linking for dlopen. The shared +extension is now explicitly linked against libdl on platforms with dl. diff --git a/setup.py b/setup.py index 1ec58aa37924..49193f67a611 100644 --- a/setup.py +++ b/setup.py @@ -2089,6 +2089,10 @@ def detect_ctypes(self, inc_dirs, lib_dirs): ext.libraries.append(ffi_lib) self.use_system_libffi = True + if sysconfig.get_config_var('HAVE_LIBDL'): + # for dlopen, see bpo-32647 + ext.libraries.append('dl') + def _decimal_ext(self): extra_compile_args = [] undef_macros = [] From webhook-mailer at python.org Sun Feb 25 07:08:08 2018 From: webhook-mailer at python.org (Christian Heimes) Date: Sun, 25 Feb 2018 12:08:08 -0000 Subject: [Python-checkins] Fix ssl module, Python 2.7 doesn't have Py_MAX (#5878) Message-ID: https://github.com/python/cpython/commit/439956a149f8a3eb44646498c63b2ef3337d5f3d commit: 439956a149f8a3eb44646498c63b2ef3337d5f3d branch: 2.7 author: Christian Heimes committer: GitHub date: 2018-02-25T13:08:05+01:00 summary: Fix ssl module, Python 2.7 doesn't have Py_MAX (#5878) Signed-off-by: Christian Heimes files: M Modules/_ssl.c diff --git a/Modules/_ssl.c b/Modules/_ssl.c index af66a581e15a..f9ed94dee1e1 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -610,7 +610,8 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock, } #elif defined(HAVE_INET_PTON) #ifdef ENABLE_IPV6 - char packed[Py_MAX(sizeof(struct in_addr), sizeof(struct in6_addr))]; + #define PySSL_MAX(x, y) (((x) > (y)) ? (x) : (y)) + char packed[PySSL_MAX(sizeof(struct in_addr), sizeof(struct in6_addr))]; #else char packed[sizeof(struct in_addr)]; #endif /* ENABLE_IPV6 */ From webhook-mailer at python.org Sun Feb 25 07:18:46 2018 From: webhook-mailer at python.org (Christian Heimes) Date: Sun, 25 Feb 2018 12:18:46 -0000 Subject: [Python-checkins] [3.7] bpo-30622: Fix NPN for OpenSSL 1.1.1-pre1 (GH-5876) (#5880) Message-ID: https://github.com/python/cpython/commit/961774184eb950e2547ab0d42653439adc735924 commit: 961774184eb950e2547ab0d42653439adc735924 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Christian Heimes date: 2018-02-25T13:18:43+01:00 summary: [3.7] bpo-30622: Fix NPN for OpenSSL 1.1.1-pre1 (GH-5876) (#5880) Signed-off-by: Christian Heimes (cherry picked from commit 29eab55309b9f78b79074d26db16a44e7841c639) Co-authored-by: Christian Heimes files: M Modules/_ssl.c M Modules/clinic/_ssl.c.h diff --git a/Modules/_ssl.c b/Modules/_ssl.c index ed6b7a835a94..52695fe39c71 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -157,21 +157,26 @@ static void _PySSLFixErrno(void) { #endif #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation -# define HAVE_ALPN +# define HAVE_ALPN 1 +#else +# define HAVE_ALPN 0 #endif /* We cannot rely on OPENSSL_NO_NEXTPROTONEG because LibreSSL 2.6.1 dropped * NPN support but did not set OPENSSL_NO_NEXTPROTONEG for compatibility * reasons. The check for TLSEXT_TYPE_next_proto_neg works with * OpenSSL 1.0.1+ and LibreSSL. + * OpenSSL 1.1.1-pre1 dropped NPN but still has TLSEXT_TYPE_next_proto_neg. */ #ifdef OPENSSL_NO_NEXTPROTONEG -# define HAVE_NPN 0 +# define HAVE_NPN 0 +#elif (OPENSSL_VERSION_NUMBER >= 0x10101000L) && !defined(LIBRESSL_VERSION_NUMBER) +# define HAVE_NPN 0 #elif defined(TLSEXT_TYPE_next_proto_neg) -# define HAVE_NPN 1 +# define HAVE_NPN 1 #else -# define HAVE_NPN 0 -# endif +# define HAVE_NPN 0 +#endif #ifndef INVALID_SOCKET /* MS defines this */ #define INVALID_SOCKET (-1) @@ -341,11 +346,11 @@ static unsigned int _ssl_locks_count = 0; typedef struct { PyObject_HEAD SSL_CTX *ctx; -#ifdef HAVE_NPN +#if HAVE_NPN unsigned char *npn_protocols; int npn_protocols_len; #endif -#ifdef HAVE_ALPN +#if HAVE_ALPN unsigned char *alpn_protocols; unsigned int alpn_protocols_len; #endif @@ -1922,7 +1927,7 @@ _ssl__SSLSocket_version_impl(PySSLSocket *self) return PyUnicode_FromString(version); } -#ifdef HAVE_NPN +#if HAVE_NPN /*[clinic input] _ssl._SSLSocket.selected_npn_protocol [clinic start generated code]*/ @@ -1943,7 +1948,7 @@ _ssl__SSLSocket_selected_npn_protocol_impl(PySSLSocket *self) } #endif -#ifdef HAVE_ALPN +#if HAVE_ALPN /*[clinic input] _ssl._SSLSocket.selected_alpn_protocol [clinic start generated code]*/ @@ -2887,10 +2892,10 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version) self->ctx = ctx; self->hostflags = X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS; self->protocol = proto_version; -#ifdef HAVE_NPN +#if HAVE_NPN self->npn_protocols = NULL; #endif -#ifdef HAVE_ALPN +#if HAVE_ALPN self->alpn_protocols = NULL; #endif #ifndef OPENSSL_NO_TLSEXT @@ -3026,10 +3031,10 @@ context_dealloc(PySSLContext *self) PyObject_GC_UnTrack(self); context_clear(self); SSL_CTX_free(self->ctx); -#ifdef HAVE_NPN +#if HAVE_NPN PyMem_FREE(self->npn_protocols); #endif -#ifdef HAVE_ALPN +#if HAVE_ALPN PyMem_FREE(self->alpn_protocols); #endif Py_TYPE(self)->tp_free(self); @@ -3104,7 +3109,7 @@ _ssl__SSLContext_get_ciphers_impl(PySSLContext *self) #endif -#if defined(HAVE_NPN) || defined(HAVE_ALPN) +#if HAVE_NPN || HAVE_ALPN static int do_protocol_selection(int alpn, unsigned char **out, unsigned char *outlen, const unsigned char *server_protocols, unsigned int server_protocols_len, @@ -3130,7 +3135,7 @@ do_protocol_selection(int alpn, unsigned char **out, unsigned char *outlen, } #endif -#ifdef HAVE_NPN +#if HAVE_NPN /* this callback gets passed to SSL_CTX_set_next_protos_advertise_cb */ static int _advertiseNPN_cb(SSL *s, @@ -3173,7 +3178,7 @@ _ssl__SSLContext__set_npn_protocols_impl(PySSLContext *self, Py_buffer *protos) /*[clinic end generated code: output=72b002c3324390c6 input=319fcb66abf95bd7]*/ { -#ifdef HAVE_NPN +#if HAVE_NPN PyMem_Free(self->npn_protocols); self->npn_protocols = PyMem_Malloc(protos->len); if (self->npn_protocols == NULL) @@ -3198,7 +3203,7 @@ _ssl__SSLContext__set_npn_protocols_impl(PySSLContext *self, #endif } -#ifdef HAVE_ALPN +#if HAVE_ALPN static int _selectALPN_cb(SSL *s, const unsigned char **out, unsigned char *outlen, @@ -3223,7 +3228,7 @@ _ssl__SSLContext__set_alpn_protocols_impl(PySSLContext *self, Py_buffer *protos) /*[clinic end generated code: output=87599a7f76651a9b input=9bba964595d519be]*/ { -#ifdef HAVE_ALPN +#if HAVE_ALPN if ((size_t)protos->len > UINT_MAX) { PyErr_Format(PyExc_OverflowError, "protocols longer than %d bytes", UINT_MAX); @@ -5718,7 +5723,7 @@ PyInit__ssl(void) Py_INCREF(r); PyModule_AddObject(m, "HAS_ECDH", r); -#ifdef HAVE_NPN +#if HAVE_NPN r = Py_True; #else r = Py_False; @@ -5726,7 +5731,7 @@ PyInit__ssl(void) Py_INCREF(r); PyModule_AddObject(m, "HAS_NPN", r); -#ifdef HAVE_ALPN +#if HAVE_ALPN r = Py_True; #else r = Py_False; diff --git a/Modules/clinic/_ssl.c.h b/Modules/clinic/_ssl.c.h index 1ee1bfb21d3e..5ba34eca594f 100644 --- a/Modules/clinic/_ssl.c.h +++ b/Modules/clinic/_ssl.c.h @@ -132,7 +132,7 @@ _ssl__SSLSocket_version(PySSLSocket *self, PyObject *Py_UNUSED(ignored)) return _ssl__SSLSocket_version_impl(self); } -#if defined(HAVE_NPN) +#if (HAVE_NPN) PyDoc_STRVAR(_ssl__SSLSocket_selected_npn_protocol__doc__, "selected_npn_protocol($self, /)\n" @@ -151,9 +151,9 @@ _ssl__SSLSocket_selected_npn_protocol(PySSLSocket *self, PyObject *Py_UNUSED(ign return _ssl__SSLSocket_selected_npn_protocol_impl(self); } -#endif /* defined(HAVE_NPN) */ +#endif /* (HAVE_NPN) */ -#if defined(HAVE_ALPN) +#if (HAVE_ALPN) PyDoc_STRVAR(_ssl__SSLSocket_selected_alpn_protocol__doc__, "selected_alpn_protocol($self, /)\n" @@ -172,7 +172,7 @@ _ssl__SSLSocket_selected_alpn_protocol(PySSLSocket *self, PyObject *Py_UNUSED(ig return _ssl__SSLSocket_selected_alpn_protocol_impl(self); } -#endif /* defined(HAVE_ALPN) */ +#endif /* (HAVE_ALPN) */ PyDoc_STRVAR(_ssl__SSLSocket_compression__doc__, "compression($self, /)\n" @@ -1175,4 +1175,4 @@ _ssl_enum_crls(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObje #ifndef _SSL_ENUM_CRLS_METHODDEF #define _SSL_ENUM_CRLS_METHODDEF #endif /* !defined(_SSL_ENUM_CRLS_METHODDEF) */ -/*[clinic end generated code: output=a00fef6a470cfc2c input=a9049054013a1b77]*/ +/*[clinic end generated code: output=e2417fee28666f7c input=a9049054013a1b77]*/ From webhook-mailer at python.org Sun Feb 25 08:28:58 2018 From: webhook-mailer at python.org (Christian Heimes) Date: Sun, 25 Feb 2018 13:28:58 -0000 Subject: [Python-checkins] [2.7] bpo-30622: Fix NPN for OpenSSL 1.1.1-pre1 (GH-5876) (#5882) Message-ID: https://github.com/python/cpython/commit/df1732a4734190fefc8814687895fc1168716c37 commit: df1732a4734190fefc8814687895fc1168716c37 branch: 2.7 author: Christian Heimes committer: GitHub date: 2018-02-25T14:28:55+01:00 summary: [2.7] bpo-30622: Fix NPN for OpenSSL 1.1.1-pre1 (GH-5876) (#5882) Signed-off-by: Christian Heimes . (cherry picked from commit 29eab55309b9f78b79074d26db16a44e7841c639) Co-authored-by: Christian Heimes files: M Modules/_ssl.c diff --git a/Modules/_ssl.c b/Modules/_ssl.c index f9ed94dee1e1..da8b20f54f35 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -123,22 +123,27 @@ struct py_ssl_library_code { #endif /* ALPN added in OpenSSL 1.0.2 */ -#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined(OPENSSL_NO_TLSEXT) -# define HAVE_ALPN +#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation +# define HAVE_ALPN 1 +#else +# define HAVE_ALPN 0 #endif /* We cannot rely on OPENSSL_NO_NEXTPROTONEG because LibreSSL 2.6.1 dropped * NPN support but did not set OPENSSL_NO_NEXTPROTONEG for compatibility * reasons. The check for TLSEXT_TYPE_next_proto_neg works with * OpenSSL 1.0.1+ and LibreSSL. + * OpenSSL 1.1.1-pre1 dropped NPN but still has TLSEXT_TYPE_next_proto_neg. */ #ifdef OPENSSL_NO_NEXTPROTONEG -# define HAVE_NPN 0 +# define HAVE_NPN 0 +#elif (OPENSSL_VERSION_NUMBER >= 0x10101000L) && !defined(LIBRESSL_VERSION_NUMBER) +# define HAVE_NPN 0 #elif defined(TLSEXT_TYPE_next_proto_neg) -# define HAVE_NPN 1 +# define HAVE_NPN 1 #else -# define HAVE_NPN 0 -# endif +# define HAVE_NPN 0 +#endif #ifndef INVALID_SOCKET /* MS defines this */ #define INVALID_SOCKET (-1) @@ -298,11 +303,11 @@ static unsigned int _ssl_locks_count = 0; typedef struct { PyObject_HEAD SSL_CTX *ctx; -#ifdef HAVE_NPN +#if HAVE_NPN unsigned char *npn_protocols; int npn_protocols_len; #endif -#ifdef HAVE_ALPN +#if HAVE_ALPN unsigned char *alpn_protocols; int alpn_protocols_len; #endif @@ -1586,7 +1591,7 @@ static PyObject *PySSL_selected_npn_protocol(PySSLSocket *self) { } #endif -#ifdef HAVE_ALPN +#if HAVE_ALPN static PyObject *PySSL_selected_alpn_protocol(PySSLSocket *self) { const unsigned char *out; unsigned int outlen; @@ -2103,7 +2108,7 @@ static PyMethodDef PySSLMethods[] = { #ifdef OPENSSL_NPN_NEGOTIATED {"selected_npn_protocol", (PyCFunction)PySSL_selected_npn_protocol, METH_NOARGS}, #endif -#ifdef HAVE_ALPN +#if HAVE_ALPN {"selected_alpn_protocol", (PyCFunction)PySSL_selected_alpn_protocol, METH_NOARGS}, #endif {"compression", (PyCFunction)PySSL_compression, METH_NOARGS}, @@ -2209,10 +2214,10 @@ context_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return NULL; } self->ctx = ctx; -#ifdef HAVE_NPN +#if HAVE_NPN self->npn_protocols = NULL; #endif -#ifdef HAVE_ALPN +#if HAVE_ALPN self->alpn_protocols = NULL; #endif #ifndef OPENSSL_NO_TLSEXT @@ -2287,10 +2292,10 @@ context_dealloc(PySSLContext *self) PyObject_GC_UnTrack(self); context_clear(self); SSL_CTX_free(self->ctx); -#ifdef HAVE_NPN +#if HAVE_NPN PyMem_FREE(self->npn_protocols); #endif -#ifdef HAVE_ALPN +#if HAVE_ALPN PyMem_FREE(self->alpn_protocols); #endif Py_TYPE(self)->tp_free(self); @@ -2317,7 +2322,7 @@ set_ciphers(PySSLContext *self, PyObject *args) Py_RETURN_NONE; } -#if defined(HAVE_NPN) || defined(HAVE_ALPN) +#if HAVE_NPN || HAVE_ALPN static int do_protocol_selection(int alpn, unsigned char **out, unsigned char *outlen, const unsigned char *server_protocols, unsigned int server_protocols_len, @@ -2343,7 +2348,7 @@ do_protocol_selection(int alpn, unsigned char **out, unsigned char *outlen, } #endif -#ifdef HAVE_NPN +#if HAVE_NPN /* this callback gets passed to SSL_CTX_set_next_protos_advertise_cb */ static int _advertiseNPN_cb(SSL *s, @@ -2378,7 +2383,7 @@ _selectNPN_cb(SSL *s, static PyObject * _set_npn_protocols(PySSLContext *self, PyObject *args) { -#ifdef HAVE_NPN +#if HAVE_NPN Py_buffer protos; if (!PyArg_ParseTuple(args, "s*:set_npn_protocols", &protos)) @@ -2414,7 +2419,7 @@ _set_npn_protocols(PySSLContext *self, PyObject *args) #endif } -#ifdef HAVE_ALPN +#if HAVE_ALPN static int _selectALPN_cb(SSL *s, const unsigned char **out, unsigned char *outlen, @@ -2431,7 +2436,7 @@ _selectALPN_cb(SSL *s, static PyObject * _set_alpn_protocols(PySSLContext *self, PyObject *args) { -#ifdef HAVE_ALPN +#if HAVE_ALPN Py_buffer protos; if (!PyArg_ParseTuple(args, "s*:set_npn_protocols", &protos)) @@ -4387,7 +4392,7 @@ init_ssl(void) Py_INCREF(r); PyModule_AddObject(m, "HAS_ECDH", r); -#ifdef HAVE_NPN +#if HAVE_NPN r = Py_True; #else r = Py_False; @@ -4395,7 +4400,7 @@ init_ssl(void) Py_INCREF(r); PyModule_AddObject(m, "HAS_NPN", r); -#ifdef HAVE_ALPN +#if HAVE_ALPN r = Py_True; #else r = Py_False; From webhook-mailer at python.org Sun Feb 25 08:29:03 2018 From: webhook-mailer at python.org (Christian Heimes) Date: Sun, 25 Feb 2018 13:29:03 -0000 Subject: [Python-checkins] [3.6] bpo-30622: Fix NPN for OpenSSL 1.1.1-pre1 (GH-5876) (#5881) Message-ID: https://github.com/python/cpython/commit/a79591cfb81dde65bb2f891d62de0161c23a4ff4 commit: a79591cfb81dde65bb2f891d62de0161c23a4ff4 branch: 3.6 author: Christian Heimes committer: GitHub date: 2018-02-25T14:29:00+01:00 summary: [3.6] bpo-30622: Fix NPN for OpenSSL 1.1.1-pre1 (GH-5876) (#5881) Signed-off-by: Christian Heimes . (cherry picked from commit 29eab55309b9f78b79074d26db16a44e7841c639) Co-authored-by: Christian Heimes files: M Modules/_ssl.c M Modules/clinic/_ssl.c.h diff --git a/Modules/_ssl.c b/Modules/_ssl.c index ad4915bb6903..2fe696daa5e1 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -127,21 +127,26 @@ struct py_ssl_library_code { #endif #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation -# define HAVE_ALPN +# define HAVE_ALPN 1 +#else +# define HAVE_ALPN 0 #endif /* We cannot rely on OPENSSL_NO_NEXTPROTONEG because LibreSSL 2.6.1 dropped * NPN support but did not set OPENSSL_NO_NEXTPROTONEG for compatibility * reasons. The check for TLSEXT_TYPE_next_proto_neg works with * OpenSSL 1.0.1+ and LibreSSL. + * OpenSSL 1.1.1-pre1 dropped NPN but still has TLSEXT_TYPE_next_proto_neg. */ #ifdef OPENSSL_NO_NEXTPROTONEG -# define HAVE_NPN 0 +# define HAVE_NPN 0 +#elif (OPENSSL_VERSION_NUMBER >= 0x10101000L) && !defined(LIBRESSL_VERSION_NUMBER) +# define HAVE_NPN 0 #elif defined(TLSEXT_TYPE_next_proto_neg) -# define HAVE_NPN 1 +# define HAVE_NPN 1 #else -# define HAVE_NPN 0 -# endif +# define HAVE_NPN 0 +#endif #ifndef INVALID_SOCKET /* MS defines this */ #define INVALID_SOCKET (-1) @@ -297,11 +302,11 @@ static unsigned int _ssl_locks_count = 0; typedef struct { PyObject_HEAD SSL_CTX *ctx; -#ifdef HAVE_NPN +#if HAVE_NPN unsigned char *npn_protocols; int npn_protocols_len; #endif -#ifdef HAVE_ALPN +#if HAVE_ALPN unsigned char *alpn_protocols; int alpn_protocols_len; #endif @@ -1789,7 +1794,7 @@ _ssl__SSLSocket_version_impl(PySSLSocket *self) return PyUnicode_FromString(version); } -#ifdef HAVE_NPN +#if HAVE_NPN /*[clinic input] _ssl._SSLSocket.selected_npn_protocol [clinic start generated code]*/ @@ -1810,7 +1815,7 @@ _ssl__SSLSocket_selected_npn_protocol_impl(PySSLSocket *self) } #endif -#ifdef HAVE_ALPN +#if HAVE_ALPN /*[clinic input] _ssl._SSLSocket.selected_alpn_protocol [clinic start generated code]*/ @@ -2745,7 +2750,7 @@ _ssl__SSLContext_impl(PyTypeObject *type, int proto_version) #ifdef HAVE_NPN self->npn_protocols = NULL; #endif -#ifdef HAVE_ALPN +#if HAVE_ALPN self->alpn_protocols = NULL; #endif #ifndef OPENSSL_NO_TLSEXT @@ -2877,10 +2882,10 @@ context_dealloc(PySSLContext *self) PyObject_GC_UnTrack(self); context_clear(self); SSL_CTX_free(self->ctx); -#ifdef HAVE_NPN +#if HAVE_NPN PyMem_FREE(self->npn_protocols); #endif -#ifdef HAVE_ALPN +#if HAVE_ALPN PyMem_FREE(self->alpn_protocols); #endif Py_TYPE(self)->tp_free(self); @@ -2955,7 +2960,7 @@ _ssl__SSLContext_get_ciphers_impl(PySSLContext *self) #endif -#if defined(HAVE_NPN) || defined(HAVE_ALPN) +#if HAVE_NPN || HAVE_ALPN static int do_protocol_selection(int alpn, unsigned char **out, unsigned char *outlen, const unsigned char *server_protocols, unsigned int server_protocols_len, @@ -2981,7 +2986,7 @@ do_protocol_selection(int alpn, unsigned char **out, unsigned char *outlen, } #endif -#ifdef HAVE_NPN +#if HAVE_NPN /* this callback gets passed to SSL_CTX_set_next_protos_advertise_cb */ static int _advertiseNPN_cb(SSL *s, @@ -3024,7 +3029,7 @@ _ssl__SSLContext__set_npn_protocols_impl(PySSLContext *self, Py_buffer *protos) /*[clinic end generated code: output=72b002c3324390c6 input=319fcb66abf95bd7]*/ { -#ifdef HAVE_NPN +#if HAVE_NPN PyMem_Free(self->npn_protocols); self->npn_protocols = PyMem_Malloc(protos->len); if (self->npn_protocols == NULL) @@ -3049,7 +3054,7 @@ _ssl__SSLContext__set_npn_protocols_impl(PySSLContext *self, #endif } -#ifdef HAVE_ALPN +#if HAVE_ALPN static int _selectALPN_cb(SSL *s, const unsigned char **out, unsigned char *outlen, @@ -3074,7 +3079,7 @@ _ssl__SSLContext__set_alpn_protocols_impl(PySSLContext *self, Py_buffer *protos) /*[clinic end generated code: output=87599a7f76651a9b input=9bba964595d519be]*/ { -#ifdef HAVE_ALPN +#if HAVE_ALPN if ((size_t)protos->len > UINT_MAX) { PyErr_Format(PyExc_OverflowError, "protocols longer than %d bytes", UINT_MAX); @@ -5494,7 +5499,7 @@ PyInit__ssl(void) Py_INCREF(r); PyModule_AddObject(m, "HAS_ECDH", r); -#ifdef HAVE_NPN +#if HAVE_NPN r = Py_True; #else r = Py_False; @@ -5502,7 +5507,7 @@ PyInit__ssl(void) Py_INCREF(r); PyModule_AddObject(m, "HAS_NPN", r); -#ifdef HAVE_ALPN +#if HAVE_ALPN r = Py_True; #else r = Py_False; diff --git a/Modules/clinic/_ssl.c.h b/Modules/clinic/_ssl.c.h index 750ad684573f..eabe2aa06686 100644 --- a/Modules/clinic/_ssl.c.h +++ b/Modules/clinic/_ssl.c.h @@ -132,7 +132,7 @@ _ssl__SSLSocket_version(PySSLSocket *self, PyObject *Py_UNUSED(ignored)) return _ssl__SSLSocket_version_impl(self); } -#if defined(HAVE_NPN) +#if (HAVE_NPN) PyDoc_STRVAR(_ssl__SSLSocket_selected_npn_protocol__doc__, "selected_npn_protocol($self, /)\n" @@ -151,9 +151,9 @@ _ssl__SSLSocket_selected_npn_protocol(PySSLSocket *self, PyObject *Py_UNUSED(ign return _ssl__SSLSocket_selected_npn_protocol_impl(self); } -#endif /* defined(HAVE_NPN) */ +#endif /* (HAVE_NPN) */ -#if defined(HAVE_ALPN) +#if (HAVE_ALPN) PyDoc_STRVAR(_ssl__SSLSocket_selected_alpn_protocol__doc__, "selected_alpn_protocol($self, /)\n" @@ -172,7 +172,7 @@ _ssl__SSLSocket_selected_alpn_protocol(PySSLSocket *self, PyObject *Py_UNUSED(ig return _ssl__SSLSocket_selected_alpn_protocol_impl(self); } -#endif /* defined(HAVE_ALPN) */ +#endif /* (HAVE_ALPN) */ PyDoc_STRVAR(_ssl__SSLSocket_compression__doc__, "compression($self, /)\n" @@ -1168,4 +1168,4 @@ _ssl_enum_crls(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kw #ifndef _SSL_ENUM_CRLS_METHODDEF #define _SSL_ENUM_CRLS_METHODDEF #endif /* !defined(_SSL_ENUM_CRLS_METHODDEF) */ -/*[clinic end generated code: output=3d801e1145e7a94e input=a9049054013a1b77]*/ +/*[clinic end generated code: output=c79fb0dfd3c90784 input=a9049054013a1b77]*/ From webhook-mailer at python.org Sun Feb 25 10:03:43 2018 From: webhook-mailer at python.org (Alex Gaynor) Date: Sun, 25 Feb 2018 15:03:43 -0000 Subject: [Python-checkins] Delete a broken threading.local example (#5870) Message-ID: https://github.com/python/cpython/commit/5fb632e83136399bad9427ee23ec8b771695290a commit: 5fb632e83136399bad9427ee23ec8b771695290a branch: master author: Aaron Gallagher committer: Alex Gaynor date: 2018-02-25T10:03:40-05:00 summary: Delete a broken threading.local example (#5870) This code never did anything correct or useful. The class attribute will never be affected, and the condition will never be true. files: M Lib/_threading_local.py diff --git a/Lib/_threading_local.py b/Lib/_threading_local.py index 4ec4828144b7..245bd0ac91b7 100644 --- a/Lib/_threading_local.py +++ b/Lib/_threading_local.py @@ -56,11 +56,7 @@ >>> class MyLocal(local): ... number = 2 - ... initialized = False ... def __init__(self, **kw): - ... if self.initialized: - ... raise SystemError('__init__ called too many times') - ... self.initialized = True ... self.__dict__.update(kw) ... def squared(self): ... return self.number ** 2 @@ -97,7 +93,7 @@ >>> thread.start() >>> thread.join() >>> log - [[('color', 'red'), ('initialized', True)], 11] + [[('color', 'red')], 11] without affecting this thread's data: From webhook-mailer at python.org Sun Feb 25 10:23:28 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sun, 25 Feb 2018 15:23:28 -0000 Subject: [Python-checkins] Delete a broken threading.local example (GH-5870) Message-ID: https://github.com/python/cpython/commit/83f4394e4e3b3d228a9d2bcddf1de5dc5632b8fc commit: 83f4394e4e3b3d228a9d2bcddf1de5dc5632b8fc branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-25T07:23:25-08:00 summary: Delete a broken threading.local example (GH-5870) This code never did anything correct or useful. The class attribute will never be affected, and the condition will never be true. (cherry picked from commit 5fb632e83136399bad9427ee23ec8b771695290a) Co-authored-by: Aaron Gallagher files: M Lib/_threading_local.py diff --git a/Lib/_threading_local.py b/Lib/_threading_local.py index 4ec4828144b7..245bd0ac91b7 100644 --- a/Lib/_threading_local.py +++ b/Lib/_threading_local.py @@ -56,11 +56,7 @@ >>> class MyLocal(local): ... number = 2 - ... initialized = False ... def __init__(self, **kw): - ... if self.initialized: - ... raise SystemError('__init__ called too many times') - ... self.initialized = True ... self.__dict__.update(kw) ... def squared(self): ... return self.number ** 2 @@ -97,7 +93,7 @@ >>> thread.start() >>> thread.join() >>> log - [[('color', 'red'), ('initialized', True)], 11] + [[('color', 'red')], 11] without affecting this thread's data: From webhook-mailer at python.org Sun Feb 25 10:34:57 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sun, 25 Feb 2018 15:34:57 -0000 Subject: [Python-checkins] Delete a broken threading.local example (GH-5870) Message-ID: https://github.com/python/cpython/commit/07c13eee79852296a4bc732037012c424a087369 commit: 07c13eee79852296a4bc732037012c424a087369 branch: 2.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-25T07:34:46-08:00 summary: Delete a broken threading.local example (GH-5870) This code never did anything correct or useful. The class attribute will never be affected, and the condition will never be true. (cherry picked from commit 5fb632e83136399bad9427ee23ec8b771695290a) Co-authored-by: Aaron Gallagher files: M Lib/_threading_local.py diff --git a/Lib/_threading_local.py b/Lib/_threading_local.py index 09a3515bdb92..1480329fde8b 100644 --- a/Lib/_threading_local.py +++ b/Lib/_threading_local.py @@ -57,11 +57,7 @@ >>> class MyLocal(local): ... number = 2 - ... initialized = False ... def __init__(self, **kw): - ... if self.initialized: - ... raise SystemError('__init__ called too many times') - ... self.initialized = True ... self.__dict__.update(kw) ... def squared(self): ... return self.number ** 2 @@ -98,7 +94,7 @@ >>> thread.start() >>> thread.join() >>> log - [[('color', 'red'), ('initialized', True)], 11] + [[('color', 'red')], 11] without affecting this thread's data: From webhook-mailer at python.org Sun Feb 25 10:56:59 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sun, 25 Feb 2018 15:56:59 -0000 Subject: [Python-checkins] Delete a broken threading.local example (GH-5870) Message-ID: https://github.com/python/cpython/commit/8f2bcab92345dd8e51b6afd5308899292c3911e9 commit: 8f2bcab92345dd8e51b6afd5308899292c3911e9 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-25T07:56:56-08:00 summary: Delete a broken threading.local example (GH-5870) This code never did anything correct or useful. The class attribute will never be affected, and the condition will never be true. (cherry picked from commit 5fb632e83136399bad9427ee23ec8b771695290a) Co-authored-by: Aaron Gallagher files: M Lib/_threading_local.py diff --git a/Lib/_threading_local.py b/Lib/_threading_local.py index 4ec4828144b7..245bd0ac91b7 100644 --- a/Lib/_threading_local.py +++ b/Lib/_threading_local.py @@ -56,11 +56,7 @@ >>> class MyLocal(local): ... number = 2 - ... initialized = False ... def __init__(self, **kw): - ... if self.initialized: - ... raise SystemError('__init__ called too many times') - ... self.initialized = True ... self.__dict__.update(kw) ... def squared(self): ... return self.number ** 2 @@ -97,7 +93,7 @@ >>> thread.start() >>> thread.join() >>> log - [[('color', 'red'), ('initialized', True)], 11] + [[('color', 'red')], 11] without affecting this thread's data: From webhook-mailer at python.org Sun Feb 25 11:32:17 2018 From: webhook-mailer at python.org (Andrew Svetlov) Date: Sun, 25 Feb 2018 16:32:17 -0000 Subject: [Python-checkins] bpo-32622: Native sendfile on windows (#5565) Message-ID: https://github.com/python/cpython/commit/a19fb3c6aaa7632410d1d9dcb395d7101d124da4 commit: a19fb3c6aaa7632410d1d9dcb395d7101d124da4 branch: master author: Andrew Svetlov committer: GitHub date: 2018-02-25T19:32:14+03:00 summary: bpo-32622: Native sendfile on windows (#5565) * Support sendfile on Windows Proactor event loop naively. files: A Misc/NEWS.d/next/Library/2018-02-06-17-58-15.bpo-32622.AE0Jz7.rst M Lib/asyncio/proactor_events.py M Lib/asyncio/windows_events.py M Lib/test/test_asyncio/test_events.py M Lib/test/test_asyncio/test_proactor_events.py M Lib/test/test_asyncio/test_unix_events.py M Modules/overlapped.c diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py index 10ca6f8967fb..b675c8200ce3 100644 --- a/Lib/asyncio/proactor_events.py +++ b/Lib/asyncio/proactor_events.py @@ -6,11 +6,14 @@ __all__ = 'BaseProactorEventLoop', +import io +import os import socket import warnings from . import base_events from . import constants +from . import events from . import futures from . import protocols from . import sslproto @@ -107,6 +110,11 @@ def _fatal_error(self, exc, message='Fatal error on pipe transport'): self._force_close(exc) def _force_close(self, exc): + if self._empty_waiter is not None: + if exc is None: + self._empty_waiter.set_result(None) + else: + self._empty_waiter.set_exception(exc) if self._closing: return self._closing = True @@ -327,6 +335,10 @@ class _ProactorBaseWritePipeTransport(_ProactorBasePipeTransport, _start_tls_compatible = True + def __init__(self, *args, **kw): + super().__init__(*args, **kw) + self._empty_waiter = None + def write(self, data): if not isinstance(data, (bytes, bytearray, memoryview)): raise TypeError( @@ -334,6 +346,8 @@ def write(self, data): f"not {type(data).__name__}") if self._eof_written: raise RuntimeError('write_eof() already called') + if self._empty_waiter is not None: + raise RuntimeError('unable to write; sendfile is in progress') if not data: return @@ -393,6 +407,8 @@ def _loop_writing(self, f=None, data=None): self._maybe_pause_protocol() else: self._write_fut.add_done_callback(self._loop_writing) + if self._empty_waiter is not None and self._write_fut is None: + self._empty_waiter.set_result(None) except ConnectionResetError as exc: self._force_close(exc) except OSError as exc: @@ -407,6 +423,17 @@ def write_eof(self): def abort(self): self._force_close(None) + def _make_empty_waiter(self): + if self._empty_waiter is not None: + raise RuntimeError("Empty waiter is already set") + self._empty_waiter = self._loop.create_future() + if self._write_fut is None: + self._empty_waiter.set_result(None) + return self._empty_waiter + + def _reset_empty_waiter(self): + self._empty_waiter = None + class _ProactorWritePipeTransport(_ProactorBaseWritePipeTransport): def __init__(self, *args, **kw): @@ -447,7 +474,7 @@ class _ProactorSocketTransport(_ProactorReadPipeTransport, transports.Transport): """Transport for connected sockets.""" - _sendfile_compatible = constants._SendfileMode.FALLBACK + _sendfile_compatible = constants._SendfileMode.TRY_NATIVE def _set_extra(self, sock): self._extra['socket'] = sock @@ -556,6 +583,47 @@ def close(self): async def sock_accept(self, sock): return await self._proactor.accept(sock) + async def _sock_sendfile_native(self, sock, file, offset, count): + try: + fileno = file.fileno() + except (AttributeError, io.UnsupportedOperation) as err: + raise events.SendfileNotAvailableError("not a regular file") + try: + fsize = os.fstat(fileno).st_size + except OSError as err: + raise events.SendfileNotAvailableError("not a regular file") + blocksize = count if count else fsize + if not blocksize: + return 0 # empty file + + blocksize = min(blocksize, 0xffff_ffff) + end_pos = min(offset + count, fsize) if count else fsize + offset = min(offset, fsize) + total_sent = 0 + try: + while True: + blocksize = min(end_pos - offset, blocksize) + if blocksize <= 0: + return total_sent + await self._proactor.sendfile(sock, file, offset, blocksize) + offset += blocksize + total_sent += blocksize + finally: + if total_sent > 0: + file.seek(offset) + + async def _sendfile_native(self, transp, file, offset, count): + resume_reading = transp.is_reading() + transp.pause_reading() + await transp._make_empty_waiter() + try: + return await self.sock_sendfile(transp._sock, file, offset, count, + fallback=False) + finally: + transp._reset_empty_waiter() + if resume_reading: + transp.resume_reading() + def _close_self_pipe(self): if self._self_reading_future is not None: self._self_reading_future.cancel() diff --git a/Lib/asyncio/windows_events.py b/Lib/asyncio/windows_events.py index f91fcddb2aad..d22edec51efc 100644 --- a/Lib/asyncio/windows_events.py +++ b/Lib/asyncio/windows_events.py @@ -4,6 +4,7 @@ import _winapi import errno import math +import msvcrt import socket import struct import weakref @@ -527,6 +528,27 @@ def finish_connect(trans, key, ov): return self._register(ov, conn, finish_connect) + def sendfile(self, sock, file, offset, count): + self._register_with_iocp(sock) + ov = _overlapped.Overlapped(NULL) + offset_low = offset & 0xffff_ffff + offset_high = (offset >> 32) & 0xffff_ffff + ov.TransmitFile(sock.fileno(), + msvcrt.get_osfhandle(file.fileno()), + offset_low, offset_high, + count, 0, 0) + + def finish_sendfile(trans, key, ov): + try: + return ov.getresult() + except OSError as exc: + if exc.winerror in (_overlapped.ERROR_NETNAME_DELETED, + _overlapped.ERROR_OPERATION_ABORTED): + raise ConnectionResetError(*exc.args) + else: + raise + return self._register(ov, sock, finish_sendfile) + def accept_pipe(self, pipe): self._register_with_iocp(pipe) ov = _overlapped.Overlapped(NULL) diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index f5995974c683..6accbdae8b3e 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -15,6 +15,7 @@ ssl = None import subprocess import sys +import tempfile import threading import time import errno @@ -2092,22 +2093,7 @@ def test_subprocess_shell_invalid_args(self): self.loop.run_until_complete(connect(shell=False)) -class MySendfileProto(MyBaseProto): - - def __init__(self, loop=None, close_after=0): - super().__init__(loop) - self.data = bytearray() - self.close_after = close_after - - def data_received(self, data): - self.data.extend(data) - super().data_received(data) - if self.close_after and self.nbytes >= self.close_after: - self.transport.close() - - -class SendfileMixin: - # Note: sendfile via SSL transport is equal to sendfile fallback +class SendfileBase: DATA = b"12345abcde" * 160 * 1024 # 160 KiB @@ -2130,9 +2116,134 @@ def setUp(self): def run_loop(self, coro): return self.loop.run_until_complete(coro) - def prepare(self, *, is_ssl=False, close_after=0): + +class SockSendfileMixin(SendfileBase): + + class MyProto(asyncio.Protocol): + + def __init__(self, loop): + self.started = False + self.closed = False + self.data = bytearray() + self.fut = loop.create_future() + self.transport = None + + def connection_made(self, transport): + self.started = True + self.transport = transport + + def data_received(self, data): + self.data.extend(data) + + def connection_lost(self, exc): + self.closed = True + self.fut.set_result(None) + + async def wait_closed(self): + await self.fut + + 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 + + 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.run_loop(self.loop.sock_connect(sock, ('127.0.0.1', port))) + + def cleanup(): + if proto.transport is not None: + # can be None if the task was cancelled before + # connection_made callback + proto.transport.close() + self.run_loop(proto.wait_closed()) + + server.close() + self.run_loop(server.wait_closed()) + + self.addCleanup(cleanup) + + return sock, proto + + def test_sock_sendfile_success(self): + sock, proto = self.prepare_socksendfile() + ret = self.run_loop(self.loop.sock_sendfile(sock, self.file)) + sock.close() + self.run_loop(proto.wait_closed()) + + self.assertEqual(ret, len(self.DATA)) + self.assertEqual(proto.data, self.DATA) + self.assertEqual(self.file.tell(), len(self.DATA)) + + def test_sock_sendfile_with_offset_and_count(self): + sock, proto = self.prepare_socksendfile() + ret = self.run_loop(self.loop.sock_sendfile(sock, self.file, + 1000, 2000)) + sock.close() + self.run_loop(proto.wait_closed()) + + self.assertEqual(proto.data, self.DATA[1000:3000]) + self.assertEqual(self.file.tell(), 3000) + self.assertEqual(ret, 2000) + + def test_sock_sendfile_zero_size(self): + sock, proto = self.prepare_socksendfile() + with tempfile.TemporaryFile() as f: + ret = self.run_loop(self.loop.sock_sendfile(sock, f, + 0, None)) + sock.close() + self.run_loop(proto.wait_closed()) + + self.assertEqual(ret, 0) + self.assertEqual(self.file.tell(), 0) + + def test_sock_sendfile_mix_with_regular_send(self): + buf = b'1234567890' * 1024 * 1024 # 10 MB + 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)) + self.run_loop(self.loop.sock_sendall(sock, buf)) + sock.close() + self.run_loop(proto.wait_closed()) + + self.assertEqual(ret, len(self.DATA)) + expected = buf + self.DATA + buf + self.assertEqual(proto.data, expected) + self.assertEqual(self.file.tell(), len(self.DATA)) + + +class SendfileMixin(SendfileBase): + + class MySendfileProto(MyBaseProto): + + def __init__(self, loop=None, close_after=0): + super().__init__(loop) + self.data = bytearray() + self.close_after = close_after + + def data_received(self, data): + self.data.extend(data) + super().data_received(data) + if self.close_after and self.nbytes >= self.close_after: + self.transport.close() + + + # Note: sendfile via SSL transport is equal to sendfile fallback + + def prepare_sendfile(self, *, is_ssl=False, close_after=0): port = support.find_unused_port() - srv_proto = MySendfileProto(loop=self.loop, close_after=close_after) + srv_proto = self.MySendfileProto(loop=self.loop, + close_after=close_after) if is_ssl: if not ssl: self.skipTest("No ssl module") @@ -2156,7 +2267,7 @@ def prepare(self, *, is_ssl=False, close_after=0): # 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 = MySendfileProto(loop=self.loop) + 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)) @@ -2189,7 +2300,7 @@ def test_sendfile_not_supported(self): tr.close() def test_sendfile(self): - srv_proto, cli_proto = self.prepare() + srv_proto, cli_proto = self.prepare_sendfile() ret = self.run_loop( self.loop.sendfile(cli_proto.transport, self.file)) cli_proto.transport.close() @@ -2200,7 +2311,7 @@ def test_sendfile(self): self.assertEqual(self.file.tell(), len(self.DATA)) def test_sendfile_force_fallback(self): - srv_proto, cli_proto = self.prepare() + srv_proto, cli_proto = self.prepare_sendfile() def sendfile_native(transp, file, offset, count): # to raise SendfileNotAvailableError @@ -2222,7 +2333,7 @@ def test_sendfile_force_unsupported_native(self): if sys.platform == 'win32': if isinstance(self.loop, asyncio.ProactorEventLoop): self.skipTest("Fails on proactor event loop") - srv_proto, cli_proto = self.prepare() + srv_proto, cli_proto = self.prepare_sendfile() def sendfile_native(transp, file, offset, count): # to raise SendfileNotAvailableError @@ -2243,7 +2354,7 @@ def sendfile_native(transp, file, offset, count): self.assertEqual(self.file.tell(), 0) def test_sendfile_ssl(self): - srv_proto, cli_proto = self.prepare(is_ssl=True) + srv_proto, cli_proto = self.prepare_sendfile(is_ssl=True) ret = self.run_loop( self.loop.sendfile(cli_proto.transport, self.file)) cli_proto.transport.close() @@ -2254,7 +2365,7 @@ def test_sendfile_ssl(self): self.assertEqual(self.file.tell(), len(self.DATA)) def test_sendfile_for_closing_transp(self): - srv_proto, cli_proto = self.prepare() + srv_proto, cli_proto = self.prepare_sendfile() cli_proto.transport.close() with self.assertRaisesRegex(RuntimeError, "is closing"): self.run_loop(self.loop.sendfile(cli_proto.transport, self.file)) @@ -2263,7 +2374,7 @@ def test_sendfile_for_closing_transp(self): self.assertEqual(self.file.tell(), 0) def test_sendfile_pre_and_post_data(self): - srv_proto, cli_proto = self.prepare() + srv_proto, cli_proto = self.prepare_sendfile() PREFIX = b'zxcvbnm' * 1024 SUFFIX = b'0987654321' * 1024 cli_proto.transport.write(PREFIX) @@ -2277,7 +2388,7 @@ def test_sendfile_pre_and_post_data(self): self.assertEqual(self.file.tell(), len(self.DATA)) def test_sendfile_ssl_pre_and_post_data(self): - srv_proto, cli_proto = self.prepare(is_ssl=True) + srv_proto, cli_proto = self.prepare_sendfile(is_ssl=True) PREFIX = b'zxcvbnm' * 1024 SUFFIX = b'0987654321' * 1024 cli_proto.transport.write(PREFIX) @@ -2291,7 +2402,7 @@ def test_sendfile_ssl_pre_and_post_data(self): self.assertEqual(self.file.tell(), len(self.DATA)) def test_sendfile_partial(self): - srv_proto, cli_proto = self.prepare() + srv_proto, cli_proto = self.prepare_sendfile() ret = self.run_loop( self.loop.sendfile(cli_proto.transport, self.file, 1000, 100)) cli_proto.transport.close() @@ -2302,7 +2413,7 @@ def test_sendfile_partial(self): self.assertEqual(self.file.tell(), 1100) def test_sendfile_ssl_partial(self): - srv_proto, cli_proto = self.prepare(is_ssl=True) + srv_proto, cli_proto = self.prepare_sendfile(is_ssl=True) ret = self.run_loop( self.loop.sendfile(cli_proto.transport, self.file, 1000, 100)) cli_proto.transport.close() @@ -2313,7 +2424,8 @@ def test_sendfile_ssl_partial(self): self.assertEqual(self.file.tell(), 1100) def test_sendfile_close_peer_after_receiving(self): - srv_proto, cli_proto = self.prepare(close_after=len(self.DATA)) + srv_proto, cli_proto = self.prepare_sendfile( + close_after=len(self.DATA)) ret = self.run_loop( self.loop.sendfile(cli_proto.transport, self.file)) cli_proto.transport.close() @@ -2324,8 +2436,8 @@ def test_sendfile_close_peer_after_receiving(self): self.assertEqual(self.file.tell(), len(self.DATA)) def test_sendfile_ssl_close_peer_after_receiving(self): - srv_proto, cli_proto = self.prepare(is_ssl=True, - close_after=len(self.DATA)) + srv_proto, cli_proto = self.prepare_sendfile( + is_ssl=True, close_after=len(self.DATA)) ret = self.run_loop( self.loop.sendfile(cli_proto.transport, self.file)) self.run_loop(srv_proto.done) @@ -2335,7 +2447,7 @@ def test_sendfile_ssl_close_peer_after_receiving(self): self.assertEqual(self.file.tell(), len(self.DATA)) def test_sendfile_close_peer_in_middle_of_receiving(self): - srv_proto, cli_proto = self.prepare(close_after=1024) + srv_proto, cli_proto = self.prepare_sendfile(close_after=1024) with self.assertRaises(ConnectionError): self.run_loop( self.loop.sendfile(cli_proto.transport, self.file)) @@ -2345,6 +2457,7 @@ def test_sendfile_close_peer_in_middle_of_receiving(self): srv_proto.nbytes) self.assertTrue(1024 <= self.file.tell() < len(self.DATA), self.file.tell()) + self.assertTrue(cli_proto.transport.is_closing()) def test_sendfile_fallback_close_peer_in_middle_of_receiving(self): @@ -2355,7 +2468,7 @@ def sendfile_native(transp, file, offset, count): self.loop._sendfile_native = sendfile_native - srv_proto, cli_proto = self.prepare(close_after=1024) + srv_proto, cli_proto = self.prepare_sendfile(close_after=1024) with self.assertRaises(ConnectionError): self.run_loop( self.loop.sendfile(cli_proto.transport, self.file)) @@ -2369,7 +2482,7 @@ def sendfile_native(transp, file, offset, count): @unittest.skipIf(not hasattr(os, 'sendfile'), "Don't have native sendfile support") def test_sendfile_prevents_bare_write(self): - srv_proto, cli_proto = self.prepare() + srv_proto, cli_proto = self.prepare_sendfile() fut = self.loop.create_future() async def coro(): @@ -2397,6 +2510,7 @@ def test_sendfile_no_fallback_for_fallback_transport(self): class SelectEventLoopTests(EventLoopTestsMixin, SendfileMixin, + SockSendfileMixin, test_utils.TestCase): def create_event_loop(self): @@ -2404,6 +2518,7 @@ def create_event_loop(self): class ProactorEventLoopTests(EventLoopTestsMixin, SendfileMixin, + SockSendfileMixin, SubprocessTestsMixin, test_utils.TestCase): @@ -2431,7 +2546,9 @@ def test_remove_fds_after_closing(self): else: import selectors - class UnixEventLoopTestsMixin(EventLoopTestsMixin, SendfileMixin): + class UnixEventLoopTestsMixin(EventLoopTestsMixin, + SendfileMixin, + SockSendfileMixin): def setUp(self): super().setUp() watcher = asyncio.SafeChildWatcher() diff --git a/Lib/test/test_asyncio/test_proactor_events.py b/Lib/test/test_asyncio/test_proactor_events.py index f627dfce0e17..98e698983eab 100644 --- a/Lib/test/test_asyncio/test_proactor_events.py +++ b/Lib/test/test_asyncio/test_proactor_events.py @@ -1,14 +1,18 @@ """Tests for proactor_events.py""" +import io import socket import unittest +import sys from unittest import mock import asyncio +from asyncio import events from asyncio.proactor_events import BaseProactorEventLoop from asyncio.proactor_events import _ProactorSocketTransport from asyncio.proactor_events import _ProactorWritePipeTransport from asyncio.proactor_events import _ProactorDuplexPipeTransport +from test import support from test.test_asyncio import utils as test_utils @@ -775,5 +779,117 @@ def test_stop_serving(self): self.assertFalse(future2.cancel.called) + at unittest.skipIf(sys.platform != 'win32', + 'Proactor is supported on Windows only') +class ProactorEventLoopUnixSockSendfileTests(test_utils.TestCase): + DATA = b"12345abcde" * 16 * 1024 # 160 KiB + + class MyProto(asyncio.Protocol): + + def __init__(self, loop): + self.started = False + self.closed = False + self.data = bytearray() + self.fut = loop.create_future() + self.transport = None + + def connection_made(self, transport): + self.started = True + self.transport = transport + + def data_received(self, data): + self.data.extend(data) + + def connection_lost(self, exc): + self.closed = True + self.fut.set_result(None) + + async def wait_closed(self): + await self.fut + + @classmethod + def setUpClass(cls): + with open(support.TESTFN, 'wb') as fp: + fp.write(cls.DATA) + super().setUpClass() + + @classmethod + def tearDownClass(cls): + support.unlink(support.TESTFN) + super().tearDownClass() + + def setUp(self): + self.loop = asyncio.ProactorEventLoop() + self.set_event_loop(self.loop) + self.addCleanup(self.loop.close) + self.file = open(support.TESTFN, 'rb') + self.addCleanup(self.file.close) + super().setUp() + + 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 + + def run_loop(self, coro): + return self.loop.run_until_complete(coro) + + def prepare(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(('127.0.0.1', port)) + server = self.run_loop(self.loop.create_server( + lambda: proto, sock=srv_sock)) + self.run_loop(self.loop.sock_connect(sock, srv_sock.getsockname())) + + def cleanup(): + if proto.transport is not None: + # can be None if the task was cancelled before + # connection_made callback + proto.transport.close() + self.run_loop(proto.wait_closed()) + + server.close() + self.run_loop(server.wait_closed()) + + self.addCleanup(cleanup) + + return sock, proto + + def test_sock_sendfile_not_a_file(self): + sock, proto = self.prepare() + f = object() + with self.assertRaisesRegex(events.SendfileNotAvailableError, + "not a regular file"): + self.run_loop(self.loop._sock_sendfile_native(sock, f, + 0, None)) + self.assertEqual(self.file.tell(), 0) + + def test_sock_sendfile_iobuffer(self): + sock, proto = self.prepare() + f = io.BytesIO() + with self.assertRaisesRegex(events.SendfileNotAvailableError, + "not a regular file"): + self.run_loop(self.loop._sock_sendfile_native(sock, f, + 0, None)) + self.assertEqual(self.file.tell(), 0) + + def test_sock_sendfile_not_regular_file(self): + sock, proto = self.prepare() + f = mock.Mock() + f.fileno.return_value = -1 + with self.assertRaisesRegex(events.SendfileNotAvailableError, + "not a regular file"): + self.run_loop(self.loop._sock_sendfile_native(sock, f, + 0, None)) + self.assertEqual(self.file.tell(), 0) + + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_asyncio/test_unix_events.py b/Lib/test/test_asyncio/test_unix_events.py index 5bd76d30d2db..104f99593797 100644 --- a/Lib/test/test_asyncio/test_unix_events.py +++ b/Lib/test/test_asyncio/test_unix_events.py @@ -466,10 +466,13 @@ def setUp(self): self.addCleanup(self.file.close) super().setUp() - def make_socket(self, blocking=False): + def make_socket(self, cleanup=True): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.setblocking(blocking) - self.addCleanup(sock.close) + 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 def run_loop(self, coro): @@ -479,8 +482,10 @@ def prepare(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, support.HOST, port)) + lambda: proto, sock=srv_sock)) self.run_loop(self.loop.sock_connect(sock, (support.HOST, port))) def cleanup(): @@ -497,27 +502,6 @@ def cleanup(): return sock, proto - def test_sock_sendfile_success(self): - sock, proto = self.prepare() - ret = self.run_loop(self.loop.sock_sendfile(sock, self.file)) - sock.close() - self.run_loop(proto.wait_closed()) - - self.assertEqual(ret, len(self.DATA)) - self.assertEqual(proto.data, self.DATA) - self.assertEqual(self.file.tell(), len(self.DATA)) - - def test_sock_sendfile_with_offset_and_count(self): - sock, proto = self.prepare() - ret = self.run_loop(self.loop.sock_sendfile(sock, self.file, - 1000, 2000)) - sock.close() - self.run_loop(proto.wait_closed()) - - self.assertEqual(proto.data, self.DATA[1000:3000]) - self.assertEqual(self.file.tell(), 3000) - self.assertEqual(ret, 2000) - def test_sock_sendfile_not_available(self): sock, proto = self.prepare() with mock.patch('asyncio.unix_events.os', spec=[]): @@ -555,36 +539,6 @@ def test_sock_sendfile_not_regular_file(self): 0, None)) self.assertEqual(self.file.tell(), 0) - def test_sock_sendfile_zero_size(self): - sock, proto = self.prepare() - fname = support.TESTFN + '.suffix' - with open(fname, 'wb') as f: - pass # make zero sized file - f = open(fname, 'rb') - self.addCleanup(f.close) - self.addCleanup(support.unlink, fname) - ret = self.run_loop(self.loop._sock_sendfile_native(sock, f, - 0, None)) - sock.close() - self.run_loop(proto.wait_closed()) - - self.assertEqual(ret, 0) - self.assertEqual(self.file.tell(), 0) - - def test_sock_sendfile_mix_with_regular_send(self): - buf = b'1234567890' * 1024 * 1024 # 10 MB - sock, proto = self.prepare() - self.run_loop(self.loop.sock_sendall(sock, buf)) - ret = self.run_loop(self.loop.sock_sendfile(sock, self.file)) - self.run_loop(self.loop.sock_sendall(sock, buf)) - sock.close() - self.run_loop(proto.wait_closed()) - - self.assertEqual(ret, len(self.DATA)) - expected = buf + self.DATA + buf - self.assertEqual(proto.data, expected) - self.assertEqual(self.file.tell(), len(self.DATA)) - def test_sock_sendfile_cancel1(self): sock, proto = self.prepare() diff --git a/Misc/NEWS.d/next/Library/2018-02-06-17-58-15.bpo-32622.AE0Jz7.rst b/Misc/NEWS.d/next/Library/2018-02-06-17-58-15.bpo-32622.AE0Jz7.rst new file mode 100644 index 000000000000..456a6dc55959 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-06-17-58-15.bpo-32622.AE0Jz7.rst @@ -0,0 +1 @@ +Implement native fast sendfile for Windows proactor event loop. diff --git a/Modules/overlapped.c b/Modules/overlapped.c index 447a337fdd1f..ae7cddadd02d 100644 --- a/Modules/overlapped.c +++ b/Modules/overlapped.c @@ -39,7 +39,7 @@ enum {TYPE_NONE, TYPE_NOT_STARTED, TYPE_READ, TYPE_READINTO, TYPE_WRITE, TYPE_ACCEPT, TYPE_CONNECT, TYPE_DISCONNECT, TYPE_CONNECT_NAMED_PIPE, - TYPE_WAIT_NAMED_PIPE_AND_CONNECT}; + TYPE_WAIT_NAMED_PIPE_AND_CONNECT, TYPE_TRANSMIT_FILE}; typedef struct { PyObject_HEAD @@ -89,6 +89,7 @@ SetFromWindowsErr(DWORD err) static LPFN_ACCEPTEX Py_AcceptEx = NULL; static LPFN_CONNECTEX Py_ConnectEx = NULL; static LPFN_DISCONNECTEX Py_DisconnectEx = NULL; +static LPFN_TRANSMITFILE Py_TransmitFile = NULL; static BOOL (CALLBACK *Py_CancelIoEx)(HANDLE, LPOVERLAPPED) = NULL; #define GET_WSA_POINTER(s, x) \ @@ -102,6 +103,7 @@ initialize_function_pointers(void) GUID GuidAcceptEx = WSAID_ACCEPTEX; GUID GuidConnectEx = WSAID_CONNECTEX; GUID GuidDisconnectEx = WSAID_DISCONNECTEX; + GUID GuidTransmitFile = WSAID_TRANSMITFILE; HINSTANCE hKernel32; SOCKET s; DWORD dwBytes; @@ -114,7 +116,8 @@ initialize_function_pointers(void) if (!GET_WSA_POINTER(s, AcceptEx) || !GET_WSA_POINTER(s, ConnectEx) || - !GET_WSA_POINTER(s, DisconnectEx)) + !GET_WSA_POINTER(s, DisconnectEx) || + !GET_WSA_POINTER(s, TransmitFile)) { closesocket(s); SetFromWindowsErr(WSAGetLastError()); @@ -1194,6 +1197,61 @@ Overlapped_DisconnectEx(OverlappedObject *self, PyObject *args) } } +PyDoc_STRVAR( + Overlapped_TransmitFile_doc, + "TransmitFile(socket, file, offset, offset_high, " + "count_to_write, count_per_send, flags) " + "-> Overlapped[None]\n\n" + "Transmit file data over a connected socket."); + +static PyObject * +Overlapped_TransmitFile(OverlappedObject *self, PyObject *args) +{ + SOCKET Socket; + HANDLE File; + DWORD offset; + DWORD offset_high; + DWORD count_to_write; + DWORD count_per_send; + DWORD flags; + BOOL ret; + DWORD err; + + if (!PyArg_ParseTuple(args, + F_HANDLE F_HANDLE F_DWORD F_DWORD + F_DWORD F_DWORD F_DWORD, + &Socket, &File, &offset, &offset_high, + &count_to_write, &count_per_send, + &flags)) + return NULL; + + if (self->type != TYPE_NONE) { + PyErr_SetString(PyExc_ValueError, "operation already attempted"); + return NULL; + } + + self->type = TYPE_TRANSMIT_FILE; + self->handle = (HANDLE)Socket; + self->overlapped.Offset = offset; + self->overlapped.OffsetHigh = offset_high; + + Py_BEGIN_ALLOW_THREADS + ret = Py_TransmitFile(Socket, File, count_to_write, count_per_send, + &self->overlapped, + NULL, flags); + Py_END_ALLOW_THREADS + + self->error = err = ret ? ERROR_SUCCESS : WSAGetLastError(); + switch (err) { + case ERROR_SUCCESS: + case ERROR_IO_PENDING: + Py_RETURN_NONE; + default: + self->type = TYPE_NOT_STARTED; + return SetFromWindowsErr(err); + } +} + PyDoc_STRVAR( Overlapped_ConnectNamedPipe_doc, "ConnectNamedPipe(handle) -> Overlapped[None]\n\n" @@ -1303,6 +1361,8 @@ static PyMethodDef Overlapped_methods[] = { METH_VARARGS, Overlapped_ConnectEx_doc}, {"DisconnectEx", (PyCFunction) Overlapped_DisconnectEx, METH_VARARGS, Overlapped_DisconnectEx_doc}, + {"TransmitFile", (PyCFunction) Overlapped_TransmitFile, + METH_VARARGS, Overlapped_TransmitFile_doc}, {"ConnectNamedPipe", (PyCFunction) Overlapped_ConnectNamedPipe, METH_VARARGS, Overlapped_ConnectNamedPipe_doc}, {NULL} From webhook-mailer at python.org Sun Feb 25 11:56:33 2018 From: webhook-mailer at python.org (Eric V. Smith) Date: Sun, 25 Feb 2018 16:56:33 -0000 Subject: [Python-checkins] Exhaustively test dataclass hashing when no hash= value is provided. This is in anticipation of changing how non-default hashing is handled. (GH-5834) (GH-5889) Message-ID: https://github.com/python/cpython/commit/b6b6669cfd186f3ed1706c6d65ed83c31759a0ea commit: b6b6669cfd186f3ed1706c6d65ed83c31759a0ea branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Eric V. Smith date: 2018-02-25T11:56:30-05:00 summary: Exhaustively test dataclass hashing when no hash= value is provided. This is in anticipation of changing how non-default hashing is handled. (GH-5834) (GH-5889) (cherry picked from commit 718070db26b35da4aedc03088c58558a833ccf6e) Co-authored-by: Eric V. Smith files: M Lib/test/test_dataclasses.py diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index 736bc490867b..9752f5502c7d 100755 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -2393,6 +2393,79 @@ def __eq__(self, other): self.assertNotEqual(C(1), C(1)) self.assertEqual(hash(C(1)), hash(C(1.0))) + def test_hash_no_args(self): + # Test dataclasses with no hash= argument. This exists to + # make sure that when hash is changed, the default hashability + # keeps working. + + class Base: + def __hash__(self): + return 301 + + # If frozen or eq is None, then use the default value (do not + # specify any value in the deecorator). + for frozen, eq, base, expected in [ + (None, None, object, 'unhashable'), + (None, None, Base, 'unhashable'), + (None, False, object, 'object'), + (None, False, Base, 'base'), + (None, True, object, 'unhashable'), + (None, True, Base, 'unhashable'), + (False, None, object, 'unhashable'), + (False, None, Base, 'unhashable'), + (False, False, object, 'object'), + (False, False, Base, 'base'), + (False, True, object, 'unhashable'), + (False, True, Base, 'unhashable'), + (True, None, object, 'tuple'), + (True, None, Base, 'tuple'), + (True, False, object, 'object'), + (True, False, Base, 'base'), + (True, True, object, 'tuple'), + (True, True, Base, 'tuple'), + ]: + + with self.subTest(frozen=frozen, eq=eq, base=base, expected=expected): + # First, create the class. + if frozen is None and eq is None: + @dataclass + class C(base): + i: int + elif frozen is None: + @dataclass(eq=eq) + class C(base): + i: int + elif eq is None: + @dataclass(frozen=frozen) + class C(base): + i: int + else: + @dataclass(frozen=frozen, eq=eq) + class C(base): + i: int + + # Now, make sure it hashes as expected. + if expected == 'unhashable': + c = C(10) + with self.assertRaisesRegex(TypeError, 'unhashable type'): + hash(c) + + elif expected == 'base': + self.assertEqual(hash(C(10)), 301) + + elif expected == 'object': + # I'm not sure what test to use here. object's + # hash isn't based on id(), so calling hash() + # won't tell us much. So, just check the function + # used is object's. + self.assertIs(C.__hash__, object.__hash__) + + elif expected == 'tuple': + self.assertEqual(hash(C(42)), hash((42,))) + + else: + assert False, f'unknown value for expected={expected!r}' + if __name__ == '__main__': unittest.main() From tjreedy at udel.edu Sun Feb 25 13:36:56 2018 From: tjreedy at udel.edu (Terry Reedy) Date: Sun, 25 Feb 2018 13:36:56 -0500 Subject: [Python-checkins] Exhaustively test dataclass hashing when no hash= value is provided. This is in anticipation of changing how non-default hashing is handled. (GH-5834) (GH-5889) In-Reply-To: <3zqB222XPWzFrJk@mail.python.org> References: <3zqB222XPWzFrJk@mail.python.org> Message-ID: <74f40a59-0c4a-3e76-8506-16b79394039c@udel.edu> On 2/25/2018 11:56 AM, Eric V. Smith wrote: > + # specify any value in the deecorator). I fixed this through the web interface. The CI now knows that a comment change does not need testing. I could not request a review from ericvsmith though. tjr From eric at trueblade.com Sun Feb 25 13:49:27 2018 From: eric at trueblade.com (Eric V. Smith) Date: Sun, 25 Feb 2018 13:49:27 -0500 Subject: [Python-checkins] Exhaustively test dataclass hashing when no hash= value is provided. This is in anticipation of changing how non-default hashing is handled. (GH-5834) (GH-5889) In-Reply-To: <74f40a59-0c4a-3e76-8506-16b79394039c@udel.edu> References: <3zqB222XPWzFrJk@mail.python.org> <74f40a59-0c4a-3e76-8506-16b79394039c@udel.edu> Message-ID: <045c7e1b-df86-0128-5b3b-e5811ab7a25c@trueblade.com> Thanks. Do you know if this gets backported to 3.7? Eric. On 2/25/2018 1:36 PM, Terry Reedy wrote: > On 2/25/2018 11:56 AM, Eric V. Smith wrote: > >> +??????? # specify any value in the deecorator). > > I fixed this through the web interface.? The CI now knows that a comment > change does not need testing.? I could not request a review from > ericvsmith though. > > tjr > > > _______________________________________________ > Python-checkins mailing list > Python-checkins at python.org > https://mail.python.org/mailman/listinfo/python-checkins From webhook-mailer at python.org Sun Feb 25 14:06:04 2018 From: webhook-mailer at python.org (Mariatta) Date: Sun, 25 Feb 2018 19:06:04 -0000 Subject: [Python-checkins] bpo-25059: Clarify the print separator usage in tutorial (GH-5879) Message-ID: https://github.com/python/cpython/commit/84c4b0cc67ceb4b70842b78c718b6e8214874d6a commit: 84c4b0cc67ceb4b70842b78c718b6e8214874d6a branch: master author: Cheryl Sabella committer: Mariatta date: 2018-02-25T11:06:01-08:00 summary: bpo-25059: Clarify the print separator usage in tutorial (GH-5879) By default `print` adds spaces between its arguments. files: M Doc/tutorial/inputoutput.rst diff --git a/Doc/tutorial/inputoutput.rst b/Doc/tutorial/inputoutput.rst index 74d7bad42a12..d5531029d064 100644 --- a/Doc/tutorial/inputoutput.rst +++ b/Doc/tutorial/inputoutput.rst @@ -100,7 +100,7 @@ Here are two ways to write a table of squares and cubes:: 10 100 1000 (Note that in the first example, one space between each column was added by the -way :func:`print` works: it always adds spaces between its arguments.) +way :func:`print` works: by default it adds spaces between its arguments.) This example demonstrates the :meth:`str.rjust` method of string objects, which right-justifies a string in a field of a given width by padding From webhook-mailer at python.org Sun Feb 25 14:11:15 2018 From: webhook-mailer at python.org (Mariatta) Date: Sun, 25 Feb 2018 19:11:15 -0000 Subject: [Python-checkins] bpo-31454: Include information about "import X as Y" in Modules tutorial (GH-4041) Message-ID: https://github.com/python/cpython/commit/fbee88244e8921afdb29fde51a9a010a8ae18277 commit: fbee88244e8921afdb29fde51a9a010a8ae18277 branch: master author: Mario Corchero committer: Mariatta date: 2018-02-25T11:11:12-08:00 summary: bpo-31454: Include information about "import X as Y" in Modules tutorial (GH-4041) files: M Doc/tutorial/modules.rst diff --git a/Doc/tutorial/modules.rst b/Doc/tutorial/modules.rst index 2be03ac6ae30..584d4fd72ea8 100644 --- a/Doc/tutorial/modules.rst +++ b/Doc/tutorial/modules.rst @@ -112,6 +112,25 @@ Note that in general the practice of importing ``*`` from a module or package is frowned upon, since it often causes poorly readable code. However, it is okay to use it to save typing in interactive sessions. +If the module name is followed by :keyword:`as`, then the name +following :keyword:`as` is bound directly to the imported module. + +:: + + >>> import fibo as fib + >>> fib.fib(500) + 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 + +This is effectively importing the module in the same way that ``import fibo`` +will do, with the only difference of it being available as ``fib``. + +It can also be used when utilising :keyword:`from` with similar effects:: + + >>> from fibo import fib as fibonacci + >>> fibonacci(500) + 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 + + .. note:: For efficiency reasons, each module is only imported once per interpreter From webhook-mailer at python.org Sun Feb 25 14:13:36 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sun, 25 Feb 2018 19:13:36 -0000 Subject: [Python-checkins] bpo-25059: Clarify the print separator usage in tutorial (GH-5879) Message-ID: https://github.com/python/cpython/commit/ddf2485103c1e56ba4f290641247dfa07fcbe7f3 commit: ddf2485103c1e56ba4f290641247dfa07fcbe7f3 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-25T11:13:33-08:00 summary: bpo-25059: Clarify the print separator usage in tutorial (GH-5879) By default `print` adds spaces between its arguments. (cherry picked from commit 84c4b0cc67ceb4b70842b78c718b6e8214874d6a) Co-authored-by: Cheryl Sabella files: M Doc/tutorial/inputoutput.rst diff --git a/Doc/tutorial/inputoutput.rst b/Doc/tutorial/inputoutput.rst index 74d7bad42a12..d5531029d064 100644 --- a/Doc/tutorial/inputoutput.rst +++ b/Doc/tutorial/inputoutput.rst @@ -100,7 +100,7 @@ Here are two ways to write a table of squares and cubes:: 10 100 1000 (Note that in the first example, one space between each column was added by the -way :func:`print` works: it always adds spaces between its arguments.) +way :func:`print` works: by default it adds spaces between its arguments.) This example demonstrates the :meth:`str.rjust` method of string objects, which right-justifies a string in a field of a given width by padding From webhook-mailer at python.org Sun Feb 25 14:21:18 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sun, 25 Feb 2018 19:21:18 -0000 Subject: [Python-checkins] bpo-25059: Clarify the print separator usage in tutorial (GH-5879) Message-ID: https://github.com/python/cpython/commit/b9678d3aa156996947655ed66b554f6307b29546 commit: b9678d3aa156996947655ed66b554f6307b29546 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-25T11:21:15-08:00 summary: bpo-25059: Clarify the print separator usage in tutorial (GH-5879) By default `print` adds spaces between its arguments. (cherry picked from commit 84c4b0cc67ceb4b70842b78c718b6e8214874d6a) Co-authored-by: Cheryl Sabella files: M Doc/tutorial/inputoutput.rst diff --git a/Doc/tutorial/inputoutput.rst b/Doc/tutorial/inputoutput.rst index 74d7bad42a12..d5531029d064 100644 --- a/Doc/tutorial/inputoutput.rst +++ b/Doc/tutorial/inputoutput.rst @@ -100,7 +100,7 @@ Here are two ways to write a table of squares and cubes:: 10 100 1000 (Note that in the first example, one space between each column was added by the -way :func:`print` works: it always adds spaces between its arguments.) +way :func:`print` works: by default it adds spaces between its arguments.) This example demonstrates the :meth:`str.rjust` method of string objects, which right-justifies a string in a field of a given width by padding From webhook-mailer at python.org Sun Feb 25 14:33:16 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sun, 25 Feb 2018 19:33:16 -0000 Subject: [Python-checkins] bpo-31454: Include information about "import X as Y" in Modules tutorial (GH-4041) Message-ID: https://github.com/python/cpython/commit/5a07608d0855e4104e4070328155b52010dec4e7 commit: 5a07608d0855e4104e4070328155b52010dec4e7 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-25T11:33:14-08:00 summary: bpo-31454: Include information about "import X as Y" in Modules tutorial (GH-4041) (cherry picked from commit fbee88244e8921afdb29fde51a9a010a8ae18277) Co-authored-by: Mario Corchero files: M Doc/tutorial/modules.rst diff --git a/Doc/tutorial/modules.rst b/Doc/tutorial/modules.rst index 1e3d5c01a47a..8c263182dabb 100644 --- a/Doc/tutorial/modules.rst +++ b/Doc/tutorial/modules.rst @@ -112,6 +112,25 @@ Note that in general the practice of importing ``*`` from a module or package is frowned upon, since it often causes poorly readable code. However, it is okay to use it to save typing in interactive sessions. +If the module name is followed by :keyword:`as`, then the name +following :keyword:`as` is bound directly to the imported module. + +:: + + >>> import fibo as fib + >>> fib.fib(500) + 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 + +This is effectively importing the module in the same way that ``import fibo`` +will do, with the only difference of it being available as ``fib``. + +It can also be used when utilising :keyword:`from` with similar effects:: + + >>> from fibo import fib as fibonacci + >>> fibonacci(500) + 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 + + .. note:: For efficiency reasons, each module is only imported once per interpreter From webhook-mailer at python.org Sun Feb 25 14:35:55 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sun, 25 Feb 2018 19:35:55 -0000 Subject: [Python-checkins] bpo-31454: Include information about "import X as Y" in Modules tutorial (GH-4041) Message-ID: https://github.com/python/cpython/commit/e48e6499bbad56f7cc665efa25ae4847f51dbc38 commit: e48e6499bbad56f7cc665efa25ae4847f51dbc38 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-25T11:35:52-08:00 summary: bpo-31454: Include information about "import X as Y" in Modules tutorial (GH-4041) (cherry picked from commit fbee88244e8921afdb29fde51a9a010a8ae18277) Co-authored-by: Mario Corchero files: M Doc/tutorial/modules.rst diff --git a/Doc/tutorial/modules.rst b/Doc/tutorial/modules.rst index 2be03ac6ae30..584d4fd72ea8 100644 --- a/Doc/tutorial/modules.rst +++ b/Doc/tutorial/modules.rst @@ -112,6 +112,25 @@ Note that in general the practice of importing ``*`` from a module or package is frowned upon, since it often causes poorly readable code. However, it is okay to use it to save typing in interactive sessions. +If the module name is followed by :keyword:`as`, then the name +following :keyword:`as` is bound directly to the imported module. + +:: + + >>> import fibo as fib + >>> fib.fib(500) + 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 + +This is effectively importing the module in the same way that ``import fibo`` +will do, with the only difference of it being available as ``fib``. + +It can also be used when utilising :keyword:`from` with similar effects:: + + >>> from fibo import fib as fibonacci + >>> fibonacci(500) + 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 + + .. note:: For efficiency reasons, each module is only imported once per interpreter From webhook-mailer at python.org Sun Feb 25 14:38:27 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sun, 25 Feb 2018 19:38:27 -0000 Subject: [Python-checkins] bpo-31454: Include information about "import X as Y" in Modules tutorial (GH-4041) Message-ID: https://github.com/python/cpython/commit/76349471adfa4366a92438c88fd05a0e1e94c59b commit: 76349471adfa4366a92438c88fd05a0e1e94c59b branch: 2.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-25T11:38:24-08:00 summary: bpo-31454: Include information about "import X as Y" in Modules tutorial (GH-4041) (cherry picked from commit fbee88244e8921afdb29fde51a9a010a8ae18277) Co-authored-by: Mario Corchero files: M Doc/tutorial/modules.rst diff --git a/Doc/tutorial/modules.rst b/Doc/tutorial/modules.rst index 6fb4ffda2b84..ec3bd9c53d2e 100644 --- a/Doc/tutorial/modules.rst +++ b/Doc/tutorial/modules.rst @@ -108,6 +108,25 @@ Note that in general the practice of importing ``*`` from a module or package is frowned upon, since it often causes poorly readable code. However, it is okay to use it to save typing in interactive sessions. +If the module name is followed by :keyword:`as`, then the name +following :keyword:`as` is bound directly to the imported module. + +:: + + >>> import fibo as fib + >>> fib.fib(500) + 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 + +This is effectively importing the module in the same way that ``import fibo`` +will do, with the only difference of it being available as ``fib``. + +It can also be used when utilising :keyword:`from` with similar effects:: + + >>> from fibo import fib as fibonacci + >>> fibonacci(500) + 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 + + .. note:: For efficiency reasons, each module is only imported once per interpreter From tjreedy at udel.edu Sun Feb 25 15:38:20 2018 From: tjreedy at udel.edu (Terry Reedy) Date: Sun, 25 Feb 2018 15:38:20 -0500 Subject: [Python-checkins] Exhaustively test dataclass hashing when no hash= value is provided. This is in anticipation of changing how non-default hashing is handled. (GH-5834) (GH-5889) In-Reply-To: <045c7e1b-df86-0128-5b3b-e5811ab7a25c@trueblade.com> References: <3zqB222XPWzFrJk@mail.python.org> <74f40a59-0c4a-3e76-8506-16b79394039c@udel.edu> <045c7e1b-df86-0128-5b3b-e5811ab7a25c@trueblade.com> Message-ID: On 2/25/2018 1:49 PM, Eric V. Smith wrote: > On 2/25/2018 1:36 PM, Terry Reedy wrote: >> On 2/25/2018 11:56 AM, Eric V. Smith wrote: >> >>> +??????? # specify any value in the deecorator). >> >> I fixed this through the web interface. Let's say I tried to. It seems that I misunderstood button labels and only changed my fork. >>? The CI now knows that a >> comment change does not need testing. Wrong. There is no CI for my fork ;-). >> I could not request a review from ericvsmith though. I made new PR against python/cpython https://github.com/python/cpython/pull/5899 and it auto requested review from you. I will leave this for you to merge or not. > Thanks. Do you know if this gets backported to 3.7? It will if you add backport-37 label. I have not seen a backport for the original. -Terry From webhook-mailer at python.org Sun Feb 25 15:49:05 2018 From: webhook-mailer at python.org (Mariatta) Date: Sun, 25 Feb 2018 20:49:05 -0000 Subject: [Python-checkins] Update PR template file, don't reference bpo 12345 (GH-5897) Message-ID: https://github.com/python/cpython/commit/9c17e3a1987004b8bcfbe423953aad84493a7984 commit: 9c17e3a1987004b8bcfbe423953aad84493a7984 branch: master author: Mariatta committer: GitHub date: 2018-02-25T12:49:02-08:00 summary: Update PR template file, don't reference bpo 12345 (GH-5897) Fixes https://github.com/python/core-workflow/issues/223 files: M .github/PULL_REQUEST_TEMPLATE.md diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 9040474860c5..917791eb287f 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -9,7 +9,6 @@ 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. -If your PR is for issue 12345 in the bug tracker, then the bpo number is bpo-12345. Most PRs will require an issue number. Trivial changes, like fixing a typo, do not need an issue. From webhook-mailer at python.org Sun Feb 25 15:50:29 2018 From: webhook-mailer at python.org (Mariatta) Date: Sun, 25 Feb 2018 20:50:29 -0000 Subject: [Python-checkins] [2.7] bpo-25059: Clarify the print separator usage in tutorial (GH-5879) Message-ID: https://github.com/python/cpython/commit/b7c1a94f94305d82fc77f833fd68cc8616991bd4 commit: b7c1a94f94305d82fc77f833fd68cc8616991bd4 branch: 2.7 author: Cheryl Sabella committer: Mariatta date: 2018-02-25T12:50:26-08:00 summary: [2.7] bpo-25059: Clarify the print separator usage in tutorial (GH-5879) By default `print` adds spaces between its arguments. (cherry picked from commit 84c4b0cc67ceb4b70842b78c718b6e8214874d6a) files: M Doc/tutorial/inputoutput.rst diff --git a/Doc/tutorial/inputoutput.rst b/Doc/tutorial/inputoutput.rst index d6c3cb6ac81b..78d6ba31e0ba 100644 --- a/Doc/tutorial/inputoutput.rst +++ b/Doc/tutorial/inputoutput.rst @@ -101,7 +101,7 @@ Here are two ways to write a table of squares and cubes:: 10 100 1000 (Note that in the first example, one space between each column was added by the -way :keyword:`print` works: it always adds spaces between its arguments.) +way :keyword:`print` works: by default it adds spaces between its arguments.) This example demonstrates the :meth:`str.rjust` method of string objects, which right-justifies a string in a field of a given width by padding From webhook-mailer at python.org Sun Feb 25 16:19:58 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sun, 25 Feb 2018 21:19:58 -0000 Subject: [Python-checkins] bpo-32500: Correct the documentation for PySequence_Size() and PySequence_Length() (GH-5767) Message-ID: https://github.com/python/cpython/commit/139e64694f546982a8cc801dda30670abadb8d06 commit: 139e64694f546982a8cc801dda30670abadb8d06 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-25T13:19:55-08:00 summary: bpo-32500: Correct the documentation for PySequence_Size() and PySequence_Length() (GH-5767) Dropped the part that says: "For objects that do not provide sequence protocol". (cherry picked from commit 7a1e1786f98ad49caa157dcdf14ada9d0b07d0fd) Co-authored-by: Zackery Spytz files: M Doc/c-api/sequence.rst diff --git a/Doc/c-api/sequence.rst b/Doc/c-api/sequence.rst index f1825f079be4..81f8557ea6e6 100644 --- a/Doc/c-api/sequence.rst +++ b/Doc/c-api/sequence.rst @@ -17,9 +17,8 @@ Sequence Protocol .. index:: builtin: len - Returns the number of objects in sequence *o* on success, and ``-1`` on failure. - For objects that do not provide sequence protocol, this is equivalent to the - Python expression ``len(o)``. + Returns the number of objects in sequence *o* on success, and ``-1`` on + failure. This is equivalent to the Python expression ``len(o)``. .. c:function:: PyObject* PySequence_Concat(PyObject *o1, PyObject *o2) From webhook-mailer at python.org Sun Feb 25 16:22:46 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Sun, 25 Feb 2018 21:22:46 -0000 Subject: [Python-checkins] bpo-32500: Correct the documentation for PySequence_Size() and PySequence_Length() (GH-5767) Message-ID: https://github.com/python/cpython/commit/ecaa372f74eeb6c032791c520af6b23e527d335f commit: ecaa372f74eeb6c032791c520af6b23e527d335f branch: 2.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-25T13:22:43-08:00 summary: bpo-32500: Correct the documentation for PySequence_Size() and PySequence_Length() (GH-5767) Dropped the part that says: "For objects that do not provide sequence protocol". (cherry picked from commit 7a1e1786f98ad49caa157dcdf14ada9d0b07d0fd) Co-authored-by: Zackery Spytz files: M Doc/c-api/sequence.rst diff --git a/Doc/c-api/sequence.rst b/Doc/c-api/sequence.rst index d82a7b0556c0..d95ef2398cc5 100644 --- a/Doc/c-api/sequence.rst +++ b/Doc/c-api/sequence.rst @@ -17,9 +17,8 @@ Sequence Protocol .. index:: builtin: len - Returns the number of objects in sequence *o* on success, and ``-1`` on failure. - For objects that do not provide sequence protocol, this is equivalent to the - Python expression ``len(o)``. + Returns the number of objects in sequence *o* on success, and ``-1`` on + failure. This is equivalent to the Python expression ``len(o)``. .. versionchanged:: 2.5 These functions returned an :c:type:`int` type. This might require From webhook-mailer at python.org Sun Feb 25 21:30:20 2018 From: webhook-mailer at python.org (Eric V. Smith) Date: Mon, 26 Feb 2018 02:30:20 -0000 Subject: [Python-checkins] bpo-32929: Dataclasses: Change the tri-state hash parameter to the boolean unsafe_hash. (#5891) Message-ID: https://github.com/python/cpython/commit/dbf9cff48a4ad0fd58e1c623ce1f36c3dd3d5f38 commit: dbf9cff48a4ad0fd58e1c623ce1f36c3dd3d5f38 branch: master author: Eric V. Smith committer: GitHub date: 2018-02-25T21:30:17-05:00 summary: bpo-32929: Dataclasses: Change the tri-state hash parameter to the boolean unsafe_hash. (#5891) unsafe_hash=False is now the default. It is the same behavior as the old hash=None parameter. unsafe_hash=True will try to add __hash__. If it already exists, TypeError is raised. files: A Misc/NEWS.d/next/Library/2018-02-25-13-47-48.bpo-32929.X2gTDH.rst M Lib/dataclasses.py M Lib/test/test_dataclasses.py diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index fb279cd30517..db92b10960d5 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -20,11 +20,11 @@ # 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=, 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. +# 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: # +=========+=========================================+ @@ -34,11 +34,6 @@ # +---------+-----------------------------------------+ # | add | Generated method is added. | # +---------+-----------------------------------------+ -# | add* | Generated method is added only if the | -# | | existing attribute is None and if the | -# | | user supplied a __eq__ method in the | -# | | class definition. | -# +---------+-----------------------------------------+ # | raise | TypeError is raised. | # +---------+-----------------------------------------+ # | None | Attribute is set to None. | @@ -115,43 +110,36 @@ # __hash__ -# +------------------- hash= parameter -# | +----------- eq= parameter -# | | +--- frozen= parameter -# | | | -# v v v | | | -# | no | yes | <--- class has __hash__ in __dict__? -# +=========+=======+=======+========+========+ -# | 1 None | False | False | | | No __eq__, use the base class __hash__ -# +---------+-------+-------+--------+--------+ -# | 2 None | False | True | | | No __eq__, use the base class __hash__ -# +---------+-------+-------+--------+--------+ -# | 3 None | True | False | None | | <-- the default, not hashable -# +---------+-------+-------+--------+--------+ -# | 4 None | True | True | add | add* | Frozen, so hashable -# +---------+-------+-------+--------+--------+ -# | 5 False | False | False | | | -# +---------+-------+-------+--------+--------+ -# | 6 False | False | True | | | -# +---------+-------+-------+--------+--------+ -# | 7 False | True | False | | | -# +---------+-------+-------+--------+--------+ -# | 8 False | True | True | | | -# +---------+-------+-------+--------+--------+ -# | 9 True | False | False | add | add* | Has no __eq__, but hashable -# +---------+-------+-------+--------+--------+ -# |10 True | False | True | add | add* | Has no __eq__, but hashable -# +---------+-------+-------+--------+--------+ -# |11 True | True | False | add | add* | Not frozen, but hashable -# +---------+-------+-------+--------+--------+ -# |12 True | True | True | add | add* | Frozen, so hashable -# +=========+=======+=======+========+========+ +# +------------------- unsafe_hash= parameter +# | +----------- eq= parameter +# | | +--- frozen= parameter +# | | | +# v v v | | | +# | no | yes | <--- class has explicitly defined __hash__ +# +=======+=======+=======+========+========+ +# | False | False | False | | | No __eq__, use the base class __hash__ +# +-------+-------+-------+--------+--------+ +# | False | False | True | | | No __eq__, use the base class __hash__ +# +-------+-------+-------+--------+--------+ +# | False | True | False | None | | <-- the default, not hashable +# +-------+-------+-------+--------+--------+ +# | False | True | True | add | | Frozen, so hashable, allows override +# +-------+-------+-------+--------+--------+ +# | True | False | False | add | raise | Has no __eq__, but hashable +# +-------+-------+-------+--------+--------+ +# | True | False | True | add | raise | Has no __eq__, but hashable +# +-------+-------+-------+--------+--------+ +# | True | True | False | add | raise | Not frozen, but hashable +# +-------+-------+-------+--------+--------+ +# | 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. # Note that a class may have already __hash__=None if it specified an # __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. @@ -557,7 +545,45 @@ def _set_new_attribute(cls, name, value): return False -def _process_class(cls, repr, eq, order, hash, init, frozen): +# 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. +# Actions: +# '': Do nothing. +# 'none': Set __hash__ to None. +# 'add': Always add a generated __hash__function. +# 'exception': Raise an exception. +# +# +-------------------------------------- unsafe_hash? +# | +------------------------------- eq? +# | | +------------------------ frozen? +# | | | +---------------- has-explicit-hash? +# | | | | +# | | | | +------- action +# | | | | | +# v v v v v +_hash_action = {(False, False, False, False): (''), + (False, False, False, True ): (''), + (False, False, True, False): (''), + (False, False, True, True ): (''), + (False, True, False, False): ('none'), + (False, True, False, True ): (''), + (False, True, True, False): ('add'), + (False, True, True, True ): (''), + (True, False, False, False): ('add'), + (True, False, False, True ): ('exception'), + (True, False, True, False): ('add'), + (True, False, True, True ): ('exception'), + (True, True, False, False): ('add'), + (True, True, False, True ): ('exception'), + (True, True, True, False): ('add'), + (True, True, True, True ): ('exception'), + } +# See https://bugs.python.org/issue32929#msg312829 for an if-statement +# version of this table. + + +def _process_class(cls, repr, eq, order, unsafe_hash, init, 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 @@ -605,8 +631,14 @@ def _process_class(cls, repr, eq, order, hash, init, frozen): # be inherited down. is_frozen = frozen or cls.__setattr__ is _frozen_setattr - # Was this class defined with an __eq__? Used in __hash__ logic. - auto_hash_test= '__eq__' in cls.__dict__ and getattr(cls.__dict__, '__hash__', MISSING) is None + # 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. + 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. @@ -661,7 +693,7 @@ def _process_class(cls, repr, eq, order, hash, init, frozen): if _set_new_attribute(cls, name, _cmp_fn(name, op, self_tuple, other_tuple)): raise TypeError(f'Cannot overwrite attribute {name} ' - f'in {cls.__name__}. Consider using ' + f'in class {cls.__name__}. Consider using ' 'functools.total_ordering') if is_frozen: @@ -669,40 +701,30 @@ def _process_class(cls, repr, eq, order, hash, init, frozen): ('__delattr__', _frozen_delattr)]: if _set_new_attribute(cls, name, fn): raise TypeError(f'Cannot overwrite attribute {name} ' - f'in {cls.__name__}') + f'in class {cls.__name__}') # Decide if/how we're going to create a hash function. - # TODO: Move this table to module scope, so it's not recreated - # all the time. - generate_hash = {(None, False, False): ('', ''), - (None, False, True): ('', ''), - (None, True, False): ('none', ''), - (None, True, True): ('fn', 'fn-x'), - (False, False, False): ('', ''), - (False, False, True): ('', ''), - (False, True, False): ('', ''), - (False, True, True): ('', ''), - (True, False, False): ('fn', 'fn-x'), - (True, False, True): ('fn', 'fn-x'), - (True, True, False): ('fn', 'fn-x'), - (True, True, True): ('fn', 'fn-x'), - }[None if hash is None else bool(hash), # Force bool() if not None. - bool(eq), - bool(frozen)]['__hash__' in cls.__dict__] + hash_action = _hash_action[bool(unsafe_hash), + bool(eq), + bool(frozen), + has_explicit_hash] + # No need to call _set_new_attribute here, since we already know if # we're overwriting a __hash__ or not. - if generate_hash == '': + if hash_action == '': # Do nothing. pass - elif generate_hash == 'none': + elif hash_action == 'none': cls.__hash__ = None - elif generate_hash in ('fn', 'fn-x'): - if generate_hash == 'fn' or auto_hash_test: - flds = [f for f in field_list - if (f.compare if f.hash is None else f.hash)] - cls.__hash__ = _hash_fn(flds) + elif hash_action == 'add': + flds = [f for f in field_list if (f.compare if f.hash is None else f.hash)] + cls.__hash__ = _hash_fn(flds) + elif hash_action == 'exception': + # Raise an exception. + raise TypeError(f'Cannot overwrite attribute __hash__ ' + f'in class {cls.__name__}') else: - assert False, f"can't get here: {generate_hash}" + assert False, f"can't get here: {hash_action}" if not getattr(cls, '__doc__'): # Create a class doc-string. @@ -716,7 +738,7 @@ def _process_class(cls, repr, eq, order, hash, init, frozen): # 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, - hash=None, frozen=False): + unsafe_hash=None, frozen=False): """Returns the same class as was passed in, with dunder methods added based on the fields defined in the class. @@ -724,13 +746,13 @@ def dataclass(_cls=None, *, init=True, repr=True, eq=True, order=False, If init is true, an __init__() method is added to the class. If repr is true, a __repr__() method is added. If order is true, rich - comparison dunder methods are added. If hash is true, a __hash__() - method function is added. If frozen is true, fields may not be - assigned to after instance creation. + comparison dunder methods are added. If unsafe_hash is true, a + __hash__() method function is added. If frozen is true, fields may + not be assigned to after instance creation. """ def wrap(cls): - return _process_class(cls, repr, eq, order, hash, init, frozen) + return _process_class(cls, repr, eq, order, unsafe_hash, init, frozen) # See if we're being called as @dataclass or @dataclass(). if _cls is None: @@ -793,6 +815,7 @@ class C: raise TypeError("asdict() should be called on dataclass instances") return _asdict_inner(obj, dict_factory) + def _asdict_inner(obj, dict_factory): if _is_dataclass_instance(obj): result = [] @@ -832,6 +855,7 @@ class C: raise TypeError("astuple() should be called on dataclass instances") return _astuple_inner(obj, tuple_factory) + def _astuple_inner(obj, tuple_factory): if _is_dataclass_instance(obj): result = [] @@ -849,7 +873,8 @@ def _astuple_inner(obj, tuple_factory): def make_dataclass(cls_name, fields, *, bases=(), namespace=None, init=True, - repr=True, eq=True, order=False, hash=None, frozen=False): + repr=True, eq=True, order=False, unsafe_hash=None, + frozen=False): """Return a new dynamically created dataclass. The dataclass name will be 'cls_name'. 'fields' is an iterable @@ -869,7 +894,7 @@ class C(Base): For the bases and namespace parameters, see the builtin type() function. - The parameters init, repr, eq, order, hash, and frozen are passed to + The parameters init, repr, eq, order, unsafe_hash, and frozen are passed to dataclass(). """ @@ -894,7 +919,8 @@ class C(Base): namespace['__annotations__'] = anns cls = type(cls_name, bases, namespace) return dataclass(cls, init=init, repr=repr, eq=eq, order=order, - hash=hash, frozen=frozen) + unsafe_hash=unsafe_hash, frozen=frozen) + def replace(obj, **changes): """Return a new object replacing specified fields with new values. diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index 9752f5502c7d..ea019ae847b2 100755 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -83,32 +83,59 @@ class B: class C(B): x: int = 0 - def test_overwriting_hash(self): + def test_overwrite_hash(self): + # Test that declaring this class isn't an error. It should + # use the user-provided __hash__. @dataclass(frozen=True) class C: x: int def __hash__(self): - pass + return 301 + self.assertEqual(hash(C(100)), 301) - @dataclass(frozen=True,hash=False) + # Test that declaring this class isn't an error. It should + # use the generated __hash__. + @dataclass(frozen=True) class C: x: int - def __hash__(self): - return 600 - self.assertEqual(hash(C(0)), 600) + def __eq__(self, other): + return False + self.assertEqual(hash(C(100)), hash((100,))) - @dataclass(frozen=True) + # But this one should generate an exception, because with + # unsafe_hash=True, it's an error to have a __hash__ defined. + with self.assertRaisesRegex(TypeError, + 'Cannot overwrite attribute __hash__'): + @dataclass(unsafe_hash=True) + class C: + def __hash__(self): + pass + + # Creating this class should not generate an exception, + # because even though __hash__ exists before @dataclass is + # called, (due to __eq__ being defined), since it's None + # that's okay. + @dataclass(unsafe_hash=True) class C: x: int - def __hash__(self): + def __eq__(self): pass + # The generated hash function works as we'd expect. + self.assertEqual(hash(C(10)), hash((10,))) + + # Creating this class should generate an exception, because + # __hash__ exists and is not None, which it would be if it had + # been auto-generated do due __eq__ being defined. + with self.assertRaisesRegex(TypeError, + 'Cannot overwrite attribute __hash__'): + @dataclass(unsafe_hash=True) + class C: + x: int + def __eq__(self): + pass + def __hash__(self): + pass - @dataclass(frozen=True, hash=False) - class C: - x: int - def __hash__(self): - return 600 - self.assertEqual(hash(C(0)), 600) def test_overwrite_fields_in_derived_class(self): # Note that x from C1 replaces x in Base, but the order remains @@ -294,19 +321,6 @@ class C(B): "not supported between instances of 'B' and 'C'"): fn(B(0), C(0)) - def test_0_field_hash(self): - @dataclass(hash=True) - class C: - pass - self.assertEqual(hash(C()), hash(())) - - def test_1_field_hash(self): - @dataclass(hash=True) - class C: - x: int - self.assertEqual(hash(C(4)), hash((4,))) - self.assertEqual(hash(C(42)), hash((42,))) - def test_eq_order(self): # Test combining eq and order. for (eq, order, result ) in [ @@ -407,25 +421,25 @@ def test_hash_field_rules(self): # Test all 6 cases of: # hash=True/False/None # compare=True/False - for (hash_val, compare, result ) in [ + for (hash_, compare, result ) in [ (True, False, 'field' ), (True, True, 'field' ), (False, False, 'absent'), (False, True, 'absent'), (None, False, 'absent'), (None, True, 'field' ), - ]: - with self.subTest(hash_val=hash_val, compare=compare): - @dataclass(hash=True) + ]: + with self.subTest(hash=hash_, compare=compare): + @dataclass(unsafe_hash=True) class C: - x: int = field(compare=compare, hash=hash_val, default=5) + x: int = field(compare=compare, hash=hash_, default=5) if result == 'field': # __hash__ contains the field. - self.assertEqual(C(5).__hash__(), hash((5,))) + self.assertEqual(hash(C(5)), hash((5,))) elif result == 'absent': # The field is not present in the hash. - self.assertEqual(C(5).__hash__(), hash(())) + self.assertEqual(hash(C(5)), hash(())) else: assert False, f'unknown result {result!r}' @@ -737,7 +751,7 @@ class C: validate_class(C) # Now repeat with __hash__. - @dataclass(frozen=True, hash=True) + @dataclass(frozen=True, unsafe_hash=True) class C: i: int j: str @@ -1107,7 +1121,7 @@ class C: self.assertEqual(C().x, []) # hash - @dataclass(hash=True) + @dataclass(unsafe_hash=True) class C: x: list = field(default_factory=list, hash=False) self.assertEqual(astuple(C()), ([],)) @@ -2242,28 +2256,13 @@ def __ge__(self): pass class TestHash(unittest.TestCase): - def test_hash(self): - @dataclass(hash=True) + def test_unsafe_hash(self): + @dataclass(unsafe_hash=True) class C: x: int y: str self.assertEqual(hash(C(1, 'foo')), hash((1, 'foo'))) - def test_hash_false(self): - @dataclass(hash=False) - class C: - x: int - y: str - self.assertNotEqual(hash(C(1, 'foo')), hash((1, 'foo'))) - - def test_hash_none(self): - @dataclass(hash=None) - class C: - x: int - with self.assertRaisesRegex(TypeError, - "unhashable type: 'C'"): - hash(C(1)) - def test_hash_rules(self): def non_bool(value): # Map to something else that's True, but not a bool. @@ -2273,89 +2272,73 @@ def non_bool(value): return (3,) return 0 - def test(case, hash, eq, frozen, with_hash, result): - with self.subTest(case=case, hash=hash, eq=eq, frozen=frozen): - if with_hash: - @dataclass(hash=hash, eq=eq, frozen=frozen) - class C: - def __hash__(self): - return 0 - else: - @dataclass(hash=hash, eq=eq, frozen=frozen) - class C: - pass + def test(case, unsafe_hash, eq, frozen, with_hash, result): + with self.subTest(case=case, unsafe_hash=unsafe_hash, eq=eq, + frozen=frozen): + if result != 'exception': + if with_hash: + @dataclass(unsafe_hash=unsafe_hash, eq=eq, frozen=frozen) + class C: + def __hash__(self): + return 0 + else: + @dataclass(unsafe_hash=unsafe_hash, eq=eq, frozen=frozen) + class C: + pass # See if the result matches what's expected. - if result in ('fn', 'fn-x'): + if result == 'fn': # __hash__ contains the function we generated. self.assertIn('__hash__', C.__dict__) self.assertIsNotNone(C.__dict__['__hash__']) - if result == 'fn-x': - # This is the "auto-hash test" case. We - # should overwrite __hash__ iff there's an - # __eq__ and if __hash__=None. - - # There are two ways of getting __hash__=None: - # explicitely, and by defining __eq__. If - # __eq__ is defined, python will add __hash__ - # when the class is created. - @dataclass(hash=hash, eq=eq, frozen=frozen) - class C: - def __eq__(self, other): pass - __hash__ = None - - # Hash should be overwritten (non-None). - self.assertIsNotNone(C.__dict__['__hash__']) - - # Same test as above, but we don't provide - # __hash__, it will implicitely set to None. - @dataclass(hash=hash, eq=eq, frozen=frozen) - class C: - def __eq__(self, other): pass - - # Hash should be overwritten (non-None). - self.assertIsNotNone(C.__dict__['__hash__']) - elif result == '': # __hash__ is not present in our class. if not with_hash: self.assertNotIn('__hash__', C.__dict__) + elif result == 'none': # __hash__ is set to None. self.assertIn('__hash__', C.__dict__) self.assertIsNone(C.__dict__['__hash__']) + + elif result == 'exception': + # Creating the class should cause an exception. + # This only happens with with_hash==True. + assert(with_hash) + with self.assertRaisesRegex(TypeError, 'Cannot overwrite attribute __hash__'): + @dataclass(unsafe_hash=unsafe_hash, eq=eq, frozen=frozen) + class C: + def __hash__(self): + return 0 + else: assert False, f'unknown result {result!r}' - # There are 12 cases of: - # hash=True/False/None + # There are 8 cases of: + # unsafe_hash=True/False # eq=True/False # frozen=True/False # And for each of these, a different result if # __hash__ is defined or not. - for case, (hash, eq, frozen, result_no, result_yes) in enumerate([ - (None, False, False, '', ''), - (None, False, True, '', ''), - (None, True, False, 'none', ''), - (None, True, True, 'fn', 'fn-x'), - (False, False, False, '', ''), - (False, False, True, '', ''), - (False, True, False, '', ''), - (False, True, True, '', ''), - (True, False, False, 'fn', 'fn-x'), - (True, False, True, 'fn', 'fn-x'), - (True, True, False, 'fn', 'fn-x'), - (True, True, True, 'fn', 'fn-x'), - ], 1): - test(case, hash, eq, frozen, False, result_no) - test(case, hash, eq, frozen, True, result_yes) + for case, (unsafe_hash, eq, frozen, res_no_defined_hash, res_defined_hash) in enumerate([ + (False, False, False, '', ''), + (False, False, True, '', ''), + (False, True, False, 'none', ''), + (False, True, True, 'fn', ''), + (True, False, False, 'fn', 'exception'), + (True, False, True, 'fn', 'exception'), + (True, True, False, 'fn', 'exception'), + (True, True, True, 'fn', 'exception'), + ], 1): + test(case, unsafe_hash, eq, frozen, False, res_no_defined_hash) + test(case, unsafe_hash, eq, frozen, True, res_defined_hash) # Test non-bool truth values, too. This is just to # make sure the data-driven table in the decorator # handles non-bool values. - test(case, non_bool(hash), non_bool(eq), non_bool(frozen), False, result_no) - test(case, non_bool(hash), non_bool(eq), non_bool(frozen), True, result_yes) + test(case, non_bool(unsafe_hash), non_bool(eq), non_bool(frozen), False, res_no_defined_hash) + test(case, non_bool(unsafe_hash), non_bool(eq), non_bool(frozen), True, res_defined_hash) def test_eq_only(self): @@ -2373,8 +2356,8 @@ def __eq__(self, other): self.assertNotEqual(C(1), C(4)) # And make sure things work in this case if we specify - # hash=True. - @dataclass(hash=True) + # unsafe_hash=True. + @dataclass(unsafe_hash=True) class C: i: int def __eq__(self, other): @@ -2384,7 +2367,7 @@ def __eq__(self, other): # And check that the classes __eq__ is being used, despite # specifying eq=True. - @dataclass(hash=True, eq=True) + @dataclass(unsafe_hash=True, eq=True) class C: i: int def __eq__(self, other): @@ -2393,10 +2376,35 @@ def __eq__(self, other): self.assertNotEqual(C(1), C(1)) self.assertEqual(hash(C(1)), hash(C(1.0))) + def test_0_field_hash(self): + @dataclass(frozen=True) + class C: + pass + self.assertEqual(hash(C()), hash(())) + + @dataclass(unsafe_hash=True) + class C: + pass + self.assertEqual(hash(C()), hash(())) + + def test_1_field_hash(self): + @dataclass(frozen=True) + class C: + x: int + self.assertEqual(hash(C(4)), hash((4,))) + self.assertEqual(hash(C(42)), hash((42,))) + + @dataclass(unsafe_hash=True) + class C: + x: int + self.assertEqual(hash(C(4)), hash((4,))) + self.assertEqual(hash(C(42)), hash((42,))) + def test_hash_no_args(self): # Test dataclasses with no hash= argument. This exists to - # make sure that when hash is changed, the default hashability - # keeps working. + # make sure that if the @dataclass parameter name is changed + # or the non-default hashing behavior changes, the default + # hashability keeps working the same way. class Base: def __hash__(self): diff --git a/Misc/NEWS.d/next/Library/2018-02-25-13-47-48.bpo-32929.X2gTDH.rst b/Misc/NEWS.d/next/Library/2018-02-25-13-47-48.bpo-32929.X2gTDH.rst new file mode 100644 index 000000000000..b8a470cbf280 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-25-13-47-48.bpo-32929.X2gTDH.rst @@ -0,0 +1,6 @@ +Remove the tri-state parameter "hash", and add the boolean "unsafe_hash". If +unsafe_hash is True, add a __hash__ function, but if a __hash__ exists, +raise TypeError. If unsafe_hash is False, add a __hash__ based on the +values of eq= and frozen=. The unsafe_hash=False behavior is the same as +the old hash=None behavior. unsafe_hash=False is the default, just as +hash=None used to be. From webhook-mailer at python.org Sun Feb 25 21:38:21 2018 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Mon, 26 Feb 2018 02:38:21 -0000 Subject: [Python-checkins] Fix 'deecorator' typo in test/test_dataclasses (GH-5899) Message-ID: https://github.com/python/cpython/commit/973cae07d6ce7f5a93bd9cd3bcb724a96cfe14e9 commit: 973cae07d6ce7f5a93bd9cd3bcb724a96cfe14e9 branch: master author: Terry Jan Reedy committer: GitHub date: 2018-02-25T21:38:18-05:00 summary: Fix 'deecorator' typo in test/test_dataclasses (GH-5899) files: M Lib/test/test_dataclasses.py diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index ea019ae847b2..582cb3459f5d 100755 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -2411,7 +2411,7 @@ def __hash__(self): return 301 # If frozen or eq is None, then use the default value (do not - # specify any value in the deecorator). + # specify any value in the decorator). for frozen, eq, base, expected in [ (None, None, object, 'unhashable'), (None, None, Base, 'unhashable'), From webhook-mailer at python.org Sun Feb 25 22:09:08 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 26 Feb 2018 03:09:08 -0000 Subject: [Python-checkins] Fix 'deecorator' typo in test/test_dataclasses (GH-5899) Message-ID: https://github.com/python/cpython/commit/1a5790689f134881d8e7cc8b1ac45121468823c6 commit: 1a5790689f134881d8e7cc8b1ac45121468823c6 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-25T19:09:05-08:00 summary: Fix 'deecorator' typo in test/test_dataclasses (GH-5899) (cherry picked from commit 973cae07d6ce7f5a93bd9cd3bcb724a96cfe14e9) Co-authored-by: Terry Jan Reedy files: M Lib/test/test_dataclasses.py diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index 9752f5502c7d..c24af7fc79c4 100755 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -2403,7 +2403,7 @@ def __hash__(self): return 301 # If frozen or eq is None, then use the default value (do not - # specify any value in the deecorator). + # specify any value in the decorator). for frozen, eq, base, expected in [ (None, None, object, 'unhashable'), (None, None, Base, 'unhashable'), From solipsis at pitrou.net Mon Feb 26 04:13:04 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Mon, 26 Feb 2018 09:13:04 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=7 Message-ID: <20180226091304.1.F711E22929915675@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_asyncio leaked [3, 0, 0] memory blocks, sum=3 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/reflog4Plsn6', '--timeout', '7200'] From webhook-mailer at python.org Mon Feb 26 04:43:45 2018 From: webhook-mailer at python.org (Eric V. Smith) Date: Mon, 26 Feb 2018 09:43:45 -0000 Subject: [Python-checkins] bpo-32929: Dataclasses: Change the tri-state hash parameter to the boolean unsafe_hash. (GH-5891) (GH-5902) Message-ID: https://github.com/python/cpython/commit/4cffe2f66b581fa7538f6de884d54a5c7364d8e0 commit: 4cffe2f66b581fa7538f6de884d54a5c7364d8e0 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Eric V. Smith date: 2018-02-26T04:43:35-05:00 summary: bpo-32929: Dataclasses: Change the tri-state hash parameter to the boolean unsafe_hash. (GH-5891) (GH-5902) unsafe_hash=False is now the default. It is the same behavior as the old hash=None parameter. unsafe_hash=True will try to add __hash__. If it already exists, TypeError is raised. (cherry picked from commit dbf9cff48a4ad0fd58e1c623ce1f36c3dd3d5f38) Co-authored-by: Eric V. Smith files: A Misc/NEWS.d/next/Library/2018-02-25-13-47-48.bpo-32929.X2gTDH.rst M Lib/dataclasses.py M Lib/test/test_dataclasses.py diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index fb279cd30517..db92b10960d5 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -20,11 +20,11 @@ # 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=, 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. +# 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: # +=========+=========================================+ @@ -34,11 +34,6 @@ # +---------+-----------------------------------------+ # | add | Generated method is added. | # +---------+-----------------------------------------+ -# | add* | Generated method is added only if the | -# | | existing attribute is None and if the | -# | | user supplied a __eq__ method in the | -# | | class definition. | -# +---------+-----------------------------------------+ # | raise | TypeError is raised. | # +---------+-----------------------------------------+ # | None | Attribute is set to None. | @@ -115,43 +110,36 @@ # __hash__ -# +------------------- hash= parameter -# | +----------- eq= parameter -# | | +--- frozen= parameter -# | | | -# v v v | | | -# | no | yes | <--- class has __hash__ in __dict__? -# +=========+=======+=======+========+========+ -# | 1 None | False | False | | | No __eq__, use the base class __hash__ -# +---------+-------+-------+--------+--------+ -# | 2 None | False | True | | | No __eq__, use the base class __hash__ -# +---------+-------+-------+--------+--------+ -# | 3 None | True | False | None | | <-- the default, not hashable -# +---------+-------+-------+--------+--------+ -# | 4 None | True | True | add | add* | Frozen, so hashable -# +---------+-------+-------+--------+--------+ -# | 5 False | False | False | | | -# +---------+-------+-------+--------+--------+ -# | 6 False | False | True | | | -# +---------+-------+-------+--------+--------+ -# | 7 False | True | False | | | -# +---------+-------+-------+--------+--------+ -# | 8 False | True | True | | | -# +---------+-------+-------+--------+--------+ -# | 9 True | False | False | add | add* | Has no __eq__, but hashable -# +---------+-------+-------+--------+--------+ -# |10 True | False | True | add | add* | Has no __eq__, but hashable -# +---------+-------+-------+--------+--------+ -# |11 True | True | False | add | add* | Not frozen, but hashable -# +---------+-------+-------+--------+--------+ -# |12 True | True | True | add | add* | Frozen, so hashable -# +=========+=======+=======+========+========+ +# +------------------- unsafe_hash= parameter +# | +----------- eq= parameter +# | | +--- frozen= parameter +# | | | +# v v v | | | +# | no | yes | <--- class has explicitly defined __hash__ +# +=======+=======+=======+========+========+ +# | False | False | False | | | No __eq__, use the base class __hash__ +# +-------+-------+-------+--------+--------+ +# | False | False | True | | | No __eq__, use the base class __hash__ +# +-------+-------+-------+--------+--------+ +# | False | True | False | None | | <-- the default, not hashable +# +-------+-------+-------+--------+--------+ +# | False | True | True | add | | Frozen, so hashable, allows override +# +-------+-------+-------+--------+--------+ +# | True | False | False | add | raise | Has no __eq__, but hashable +# +-------+-------+-------+--------+--------+ +# | True | False | True | add | raise | Has no __eq__, but hashable +# +-------+-------+-------+--------+--------+ +# | True | True | False | add | raise | Not frozen, but hashable +# +-------+-------+-------+--------+--------+ +# | 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. # Note that a class may have already __hash__=None if it specified an # __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. @@ -557,7 +545,45 @@ def _set_new_attribute(cls, name, value): return False -def _process_class(cls, repr, eq, order, hash, init, frozen): +# 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. +# Actions: +# '': Do nothing. +# 'none': Set __hash__ to None. +# 'add': Always add a generated __hash__function. +# 'exception': Raise an exception. +# +# +-------------------------------------- unsafe_hash? +# | +------------------------------- eq? +# | | +------------------------ frozen? +# | | | +---------------- has-explicit-hash? +# | | | | +# | | | | +------- action +# | | | | | +# v v v v v +_hash_action = {(False, False, False, False): (''), + (False, False, False, True ): (''), + (False, False, True, False): (''), + (False, False, True, True ): (''), + (False, True, False, False): ('none'), + (False, True, False, True ): (''), + (False, True, True, False): ('add'), + (False, True, True, True ): (''), + (True, False, False, False): ('add'), + (True, False, False, True ): ('exception'), + (True, False, True, False): ('add'), + (True, False, True, True ): ('exception'), + (True, True, False, False): ('add'), + (True, True, False, True ): ('exception'), + (True, True, True, False): ('add'), + (True, True, True, True ): ('exception'), + } +# See https://bugs.python.org/issue32929#msg312829 for an if-statement +# version of this table. + + +def _process_class(cls, repr, eq, order, unsafe_hash, init, 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 @@ -605,8 +631,14 @@ def _process_class(cls, repr, eq, order, hash, init, frozen): # be inherited down. is_frozen = frozen or cls.__setattr__ is _frozen_setattr - # Was this class defined with an __eq__? Used in __hash__ logic. - auto_hash_test= '__eq__' in cls.__dict__ and getattr(cls.__dict__, '__hash__', MISSING) is None + # 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. + 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. @@ -661,7 +693,7 @@ def _process_class(cls, repr, eq, order, hash, init, frozen): if _set_new_attribute(cls, name, _cmp_fn(name, op, self_tuple, other_tuple)): raise TypeError(f'Cannot overwrite attribute {name} ' - f'in {cls.__name__}. Consider using ' + f'in class {cls.__name__}. Consider using ' 'functools.total_ordering') if is_frozen: @@ -669,40 +701,30 @@ def _process_class(cls, repr, eq, order, hash, init, frozen): ('__delattr__', _frozen_delattr)]: if _set_new_attribute(cls, name, fn): raise TypeError(f'Cannot overwrite attribute {name} ' - f'in {cls.__name__}') + f'in class {cls.__name__}') # Decide if/how we're going to create a hash function. - # TODO: Move this table to module scope, so it's not recreated - # all the time. - generate_hash = {(None, False, False): ('', ''), - (None, False, True): ('', ''), - (None, True, False): ('none', ''), - (None, True, True): ('fn', 'fn-x'), - (False, False, False): ('', ''), - (False, False, True): ('', ''), - (False, True, False): ('', ''), - (False, True, True): ('', ''), - (True, False, False): ('fn', 'fn-x'), - (True, False, True): ('fn', 'fn-x'), - (True, True, False): ('fn', 'fn-x'), - (True, True, True): ('fn', 'fn-x'), - }[None if hash is None else bool(hash), # Force bool() if not None. - bool(eq), - bool(frozen)]['__hash__' in cls.__dict__] + hash_action = _hash_action[bool(unsafe_hash), + bool(eq), + bool(frozen), + has_explicit_hash] + # No need to call _set_new_attribute here, since we already know if # we're overwriting a __hash__ or not. - if generate_hash == '': + if hash_action == '': # Do nothing. pass - elif generate_hash == 'none': + elif hash_action == 'none': cls.__hash__ = None - elif generate_hash in ('fn', 'fn-x'): - if generate_hash == 'fn' or auto_hash_test: - flds = [f for f in field_list - if (f.compare if f.hash is None else f.hash)] - cls.__hash__ = _hash_fn(flds) + elif hash_action == 'add': + flds = [f for f in field_list if (f.compare if f.hash is None else f.hash)] + cls.__hash__ = _hash_fn(flds) + elif hash_action == 'exception': + # Raise an exception. + raise TypeError(f'Cannot overwrite attribute __hash__ ' + f'in class {cls.__name__}') else: - assert False, f"can't get here: {generate_hash}" + assert False, f"can't get here: {hash_action}" if not getattr(cls, '__doc__'): # Create a class doc-string. @@ -716,7 +738,7 @@ def _process_class(cls, repr, eq, order, hash, init, frozen): # 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, - hash=None, frozen=False): + unsafe_hash=None, frozen=False): """Returns the same class as was passed in, with dunder methods added based on the fields defined in the class. @@ -724,13 +746,13 @@ def dataclass(_cls=None, *, init=True, repr=True, eq=True, order=False, If init is true, an __init__() method is added to the class. If repr is true, a __repr__() method is added. If order is true, rich - comparison dunder methods are added. If hash is true, a __hash__() - method function is added. If frozen is true, fields may not be - assigned to after instance creation. + comparison dunder methods are added. If unsafe_hash is true, a + __hash__() method function is added. If frozen is true, fields may + not be assigned to after instance creation. """ def wrap(cls): - return _process_class(cls, repr, eq, order, hash, init, frozen) + return _process_class(cls, repr, eq, order, unsafe_hash, init, frozen) # See if we're being called as @dataclass or @dataclass(). if _cls is None: @@ -793,6 +815,7 @@ class C: raise TypeError("asdict() should be called on dataclass instances") return _asdict_inner(obj, dict_factory) + def _asdict_inner(obj, dict_factory): if _is_dataclass_instance(obj): result = [] @@ -832,6 +855,7 @@ class C: raise TypeError("astuple() should be called on dataclass instances") return _astuple_inner(obj, tuple_factory) + def _astuple_inner(obj, tuple_factory): if _is_dataclass_instance(obj): result = [] @@ -849,7 +873,8 @@ def _astuple_inner(obj, tuple_factory): def make_dataclass(cls_name, fields, *, bases=(), namespace=None, init=True, - repr=True, eq=True, order=False, hash=None, frozen=False): + repr=True, eq=True, order=False, unsafe_hash=None, + frozen=False): """Return a new dynamically created dataclass. The dataclass name will be 'cls_name'. 'fields' is an iterable @@ -869,7 +894,7 @@ class C(Base): For the bases and namespace parameters, see the builtin type() function. - The parameters init, repr, eq, order, hash, and frozen are passed to + The parameters init, repr, eq, order, unsafe_hash, and frozen are passed to dataclass(). """ @@ -894,7 +919,8 @@ class C(Base): namespace['__annotations__'] = anns cls = type(cls_name, bases, namespace) return dataclass(cls, init=init, repr=repr, eq=eq, order=order, - hash=hash, frozen=frozen) + unsafe_hash=unsafe_hash, frozen=frozen) + def replace(obj, **changes): """Return a new object replacing specified fields with new values. diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index c24af7fc79c4..582cb3459f5d 100755 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -83,32 +83,59 @@ class B: class C(B): x: int = 0 - def test_overwriting_hash(self): + def test_overwrite_hash(self): + # Test that declaring this class isn't an error. It should + # use the user-provided __hash__. @dataclass(frozen=True) class C: x: int def __hash__(self): - pass + return 301 + self.assertEqual(hash(C(100)), 301) - @dataclass(frozen=True,hash=False) + # Test that declaring this class isn't an error. It should + # use the generated __hash__. + @dataclass(frozen=True) class C: x: int - def __hash__(self): - return 600 - self.assertEqual(hash(C(0)), 600) + def __eq__(self, other): + return False + self.assertEqual(hash(C(100)), hash((100,))) - @dataclass(frozen=True) + # But this one should generate an exception, because with + # unsafe_hash=True, it's an error to have a __hash__ defined. + with self.assertRaisesRegex(TypeError, + 'Cannot overwrite attribute __hash__'): + @dataclass(unsafe_hash=True) + class C: + def __hash__(self): + pass + + # Creating this class should not generate an exception, + # because even though __hash__ exists before @dataclass is + # called, (due to __eq__ being defined), since it's None + # that's okay. + @dataclass(unsafe_hash=True) class C: x: int - def __hash__(self): + def __eq__(self): pass + # The generated hash function works as we'd expect. + self.assertEqual(hash(C(10)), hash((10,))) + + # Creating this class should generate an exception, because + # __hash__ exists and is not None, which it would be if it had + # been auto-generated do due __eq__ being defined. + with self.assertRaisesRegex(TypeError, + 'Cannot overwrite attribute __hash__'): + @dataclass(unsafe_hash=True) + class C: + x: int + def __eq__(self): + pass + def __hash__(self): + pass - @dataclass(frozen=True, hash=False) - class C: - x: int - def __hash__(self): - return 600 - self.assertEqual(hash(C(0)), 600) def test_overwrite_fields_in_derived_class(self): # Note that x from C1 replaces x in Base, but the order remains @@ -294,19 +321,6 @@ class C(B): "not supported between instances of 'B' and 'C'"): fn(B(0), C(0)) - def test_0_field_hash(self): - @dataclass(hash=True) - class C: - pass - self.assertEqual(hash(C()), hash(())) - - def test_1_field_hash(self): - @dataclass(hash=True) - class C: - x: int - self.assertEqual(hash(C(4)), hash((4,))) - self.assertEqual(hash(C(42)), hash((42,))) - def test_eq_order(self): # Test combining eq and order. for (eq, order, result ) in [ @@ -407,25 +421,25 @@ def test_hash_field_rules(self): # Test all 6 cases of: # hash=True/False/None # compare=True/False - for (hash_val, compare, result ) in [ + for (hash_, compare, result ) in [ (True, False, 'field' ), (True, True, 'field' ), (False, False, 'absent'), (False, True, 'absent'), (None, False, 'absent'), (None, True, 'field' ), - ]: - with self.subTest(hash_val=hash_val, compare=compare): - @dataclass(hash=True) + ]: + with self.subTest(hash=hash_, compare=compare): + @dataclass(unsafe_hash=True) class C: - x: int = field(compare=compare, hash=hash_val, default=5) + x: int = field(compare=compare, hash=hash_, default=5) if result == 'field': # __hash__ contains the field. - self.assertEqual(C(5).__hash__(), hash((5,))) + self.assertEqual(hash(C(5)), hash((5,))) elif result == 'absent': # The field is not present in the hash. - self.assertEqual(C(5).__hash__(), hash(())) + self.assertEqual(hash(C(5)), hash(())) else: assert False, f'unknown result {result!r}' @@ -737,7 +751,7 @@ class C: validate_class(C) # Now repeat with __hash__. - @dataclass(frozen=True, hash=True) + @dataclass(frozen=True, unsafe_hash=True) class C: i: int j: str @@ -1107,7 +1121,7 @@ class C: self.assertEqual(C().x, []) # hash - @dataclass(hash=True) + @dataclass(unsafe_hash=True) class C: x: list = field(default_factory=list, hash=False) self.assertEqual(astuple(C()), ([],)) @@ -2242,28 +2256,13 @@ def __ge__(self): pass class TestHash(unittest.TestCase): - def test_hash(self): - @dataclass(hash=True) + def test_unsafe_hash(self): + @dataclass(unsafe_hash=True) class C: x: int y: str self.assertEqual(hash(C(1, 'foo')), hash((1, 'foo'))) - def test_hash_false(self): - @dataclass(hash=False) - class C: - x: int - y: str - self.assertNotEqual(hash(C(1, 'foo')), hash((1, 'foo'))) - - def test_hash_none(self): - @dataclass(hash=None) - class C: - x: int - with self.assertRaisesRegex(TypeError, - "unhashable type: 'C'"): - hash(C(1)) - def test_hash_rules(self): def non_bool(value): # Map to something else that's True, but not a bool. @@ -2273,89 +2272,73 @@ def non_bool(value): return (3,) return 0 - def test(case, hash, eq, frozen, with_hash, result): - with self.subTest(case=case, hash=hash, eq=eq, frozen=frozen): - if with_hash: - @dataclass(hash=hash, eq=eq, frozen=frozen) - class C: - def __hash__(self): - return 0 - else: - @dataclass(hash=hash, eq=eq, frozen=frozen) - class C: - pass + def test(case, unsafe_hash, eq, frozen, with_hash, result): + with self.subTest(case=case, unsafe_hash=unsafe_hash, eq=eq, + frozen=frozen): + if result != 'exception': + if with_hash: + @dataclass(unsafe_hash=unsafe_hash, eq=eq, frozen=frozen) + class C: + def __hash__(self): + return 0 + else: + @dataclass(unsafe_hash=unsafe_hash, eq=eq, frozen=frozen) + class C: + pass # See if the result matches what's expected. - if result in ('fn', 'fn-x'): + if result == 'fn': # __hash__ contains the function we generated. self.assertIn('__hash__', C.__dict__) self.assertIsNotNone(C.__dict__['__hash__']) - if result == 'fn-x': - # This is the "auto-hash test" case. We - # should overwrite __hash__ iff there's an - # __eq__ and if __hash__=None. - - # There are two ways of getting __hash__=None: - # explicitely, and by defining __eq__. If - # __eq__ is defined, python will add __hash__ - # when the class is created. - @dataclass(hash=hash, eq=eq, frozen=frozen) - class C: - def __eq__(self, other): pass - __hash__ = None - - # Hash should be overwritten (non-None). - self.assertIsNotNone(C.__dict__['__hash__']) - - # Same test as above, but we don't provide - # __hash__, it will implicitely set to None. - @dataclass(hash=hash, eq=eq, frozen=frozen) - class C: - def __eq__(self, other): pass - - # Hash should be overwritten (non-None). - self.assertIsNotNone(C.__dict__['__hash__']) - elif result == '': # __hash__ is not present in our class. if not with_hash: self.assertNotIn('__hash__', C.__dict__) + elif result == 'none': # __hash__ is set to None. self.assertIn('__hash__', C.__dict__) self.assertIsNone(C.__dict__['__hash__']) + + elif result == 'exception': + # Creating the class should cause an exception. + # This only happens with with_hash==True. + assert(with_hash) + with self.assertRaisesRegex(TypeError, 'Cannot overwrite attribute __hash__'): + @dataclass(unsafe_hash=unsafe_hash, eq=eq, frozen=frozen) + class C: + def __hash__(self): + return 0 + else: assert False, f'unknown result {result!r}' - # There are 12 cases of: - # hash=True/False/None + # There are 8 cases of: + # unsafe_hash=True/False # eq=True/False # frozen=True/False # And for each of these, a different result if # __hash__ is defined or not. - for case, (hash, eq, frozen, result_no, result_yes) in enumerate([ - (None, False, False, '', ''), - (None, False, True, '', ''), - (None, True, False, 'none', ''), - (None, True, True, 'fn', 'fn-x'), - (False, False, False, '', ''), - (False, False, True, '', ''), - (False, True, False, '', ''), - (False, True, True, '', ''), - (True, False, False, 'fn', 'fn-x'), - (True, False, True, 'fn', 'fn-x'), - (True, True, False, 'fn', 'fn-x'), - (True, True, True, 'fn', 'fn-x'), - ], 1): - test(case, hash, eq, frozen, False, result_no) - test(case, hash, eq, frozen, True, result_yes) + for case, (unsafe_hash, eq, frozen, res_no_defined_hash, res_defined_hash) in enumerate([ + (False, False, False, '', ''), + (False, False, True, '', ''), + (False, True, False, 'none', ''), + (False, True, True, 'fn', ''), + (True, False, False, 'fn', 'exception'), + (True, False, True, 'fn', 'exception'), + (True, True, False, 'fn', 'exception'), + (True, True, True, 'fn', 'exception'), + ], 1): + test(case, unsafe_hash, eq, frozen, False, res_no_defined_hash) + test(case, unsafe_hash, eq, frozen, True, res_defined_hash) # Test non-bool truth values, too. This is just to # make sure the data-driven table in the decorator # handles non-bool values. - test(case, non_bool(hash), non_bool(eq), non_bool(frozen), False, result_no) - test(case, non_bool(hash), non_bool(eq), non_bool(frozen), True, result_yes) + test(case, non_bool(unsafe_hash), non_bool(eq), non_bool(frozen), False, res_no_defined_hash) + test(case, non_bool(unsafe_hash), non_bool(eq), non_bool(frozen), True, res_defined_hash) def test_eq_only(self): @@ -2373,8 +2356,8 @@ def __eq__(self, other): self.assertNotEqual(C(1), C(4)) # And make sure things work in this case if we specify - # hash=True. - @dataclass(hash=True) + # unsafe_hash=True. + @dataclass(unsafe_hash=True) class C: i: int def __eq__(self, other): @@ -2384,7 +2367,7 @@ def __eq__(self, other): # And check that the classes __eq__ is being used, despite # specifying eq=True. - @dataclass(hash=True, eq=True) + @dataclass(unsafe_hash=True, eq=True) class C: i: int def __eq__(self, other): @@ -2393,10 +2376,35 @@ def __eq__(self, other): self.assertNotEqual(C(1), C(1)) self.assertEqual(hash(C(1)), hash(C(1.0))) + def test_0_field_hash(self): + @dataclass(frozen=True) + class C: + pass + self.assertEqual(hash(C()), hash(())) + + @dataclass(unsafe_hash=True) + class C: + pass + self.assertEqual(hash(C()), hash(())) + + def test_1_field_hash(self): + @dataclass(frozen=True) + class C: + x: int + self.assertEqual(hash(C(4)), hash((4,))) + self.assertEqual(hash(C(42)), hash((42,))) + + @dataclass(unsafe_hash=True) + class C: + x: int + self.assertEqual(hash(C(4)), hash((4,))) + self.assertEqual(hash(C(42)), hash((42,))) + def test_hash_no_args(self): # Test dataclasses with no hash= argument. This exists to - # make sure that when hash is changed, the default hashability - # keeps working. + # make sure that if the @dataclass parameter name is changed + # or the non-default hashing behavior changes, the default + # hashability keeps working the same way. class Base: def __hash__(self): diff --git a/Misc/NEWS.d/next/Library/2018-02-25-13-47-48.bpo-32929.X2gTDH.rst b/Misc/NEWS.d/next/Library/2018-02-25-13-47-48.bpo-32929.X2gTDH.rst new file mode 100644 index 000000000000..b8a470cbf280 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-25-13-47-48.bpo-32929.X2gTDH.rst @@ -0,0 +1,6 @@ +Remove the tri-state parameter "hash", and add the boolean "unsafe_hash". If +unsafe_hash is True, add a __hash__ function, but if a __hash__ exists, +raise TypeError. If unsafe_hash is False, add a __hash__ based on the +values of eq= and frozen=. The unsafe_hash=False behavior is the same as +the old hash=None behavior. unsafe_hash=False is the default, just as +hash=None used to be. From webhook-mailer at python.org Mon Feb 26 09:02:31 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Mon, 26 Feb 2018 14:02:31 -0000 Subject: [Python-checkins] bpo-32922: dbm.open() now encodes filename with the filesystem encoding. (GH-5832) Message-ID: https://github.com/python/cpython/commit/6f600ff1734ca2fdcdd37a809adf8130f0d8cc4e commit: 6f600ff1734ca2fdcdd37a809adf8130f0d8cc4e branch: master author: Serhiy Storchaka committer: GitHub date: 2018-02-26T16:02:22+02:00 summary: bpo-32922: dbm.open() now encodes filename with the filesystem encoding. (GH-5832) files: A Misc/NEWS.d/next/Library/2018-02-23-19-12-04.bpo-32922.u-xe0B.rst M Lib/test/test_dbm_dumb.py M Lib/test/test_dbm_gnu.py M Lib/test/test_dbm_ndbm.py M Modules/_dbmmodule.c M Modules/_gdbmmodule.c M Modules/clinic/_dbmmodule.c.h M Modules/clinic/_gdbmmodule.c.h diff --git a/Lib/test/test_dbm_dumb.py b/Lib/test/test_dbm_dumb.py index 21f29af05d28..652a355d990b 100644 --- a/Lib/test/test_dbm_dumb.py +++ b/Lib/test/test_dbm_dumb.py @@ -281,6 +281,21 @@ def test_readonly_files(self): self.assertEqual(sorted(f.keys()), sorted(self._dict)) f.close() # don't write + @unittest.skipUnless(support.TESTFN_NONASCII, + 'requires OS support of non-ASCII encodings') + def test_nonascii_filename(self): + filename = support.TESTFN_NONASCII + for suffix in ['.dir', '.dat', '.bak']: + self.addCleanup(support.unlink, filename + suffix) + with dumbdbm.open(filename, 'c') as db: + db[b'key'] = b'value' + self.assertTrue(os.path.exists(filename + '.dat')) + self.assertTrue(os.path.exists(filename + '.dir')) + with dumbdbm.open(filename, 'r') as db: + self.assertEqual(list(db.keys()), [b'key']) + self.assertTrue(b'key' in db) + self.assertEqual(db[b'key'], b'value') + def tearDown(self): _delete_files() diff --git a/Lib/test/test_dbm_gnu.py b/Lib/test/test_dbm_gnu.py index 304b33286978..d96df9284806 100644 --- a/Lib/test/test_dbm_gnu.py +++ b/Lib/test/test_dbm_gnu.py @@ -2,7 +2,7 @@ gdbm = support.import_module("dbm.gnu") #skip if not supported import unittest import os -from test.support import TESTFN, unlink +from test.support import TESTFN, TESTFN_NONASCII, unlink filename = TESTFN @@ -93,5 +93,39 @@ def test_context_manager(self): self.assertEqual(str(cm.exception), "GDBM object has already been closed") + def test_bytes(self): + with gdbm.open(filename, 'c') as db: + db[b'bytes key \xbd'] = b'bytes value \xbd' + with gdbm.open(filename, 'r') as db: + self.assertEqual(list(db.keys()), [b'bytes key \xbd']) + self.assertTrue(b'bytes key \xbd' in db) + self.assertEqual(db[b'bytes key \xbd'], b'bytes value \xbd') + + def test_unicode(self): + with gdbm.open(filename, 'c') as db: + db['Unicode key \U0001f40d'] = 'Unicode value \U0001f40d' + with gdbm.open(filename, 'r') as db: + self.assertEqual(list(db.keys()), ['Unicode key \U0001f40d'.encode()]) + self.assertTrue('Unicode key \U0001f40d'.encode() in db) + self.assertTrue('Unicode key \U0001f40d' in db) + self.assertEqual(db['Unicode key \U0001f40d'.encode()], + 'Unicode value \U0001f40d'.encode()) + self.assertEqual(db['Unicode key \U0001f40d'], + 'Unicode value \U0001f40d'.encode()) + + @unittest.skipUnless(TESTFN_NONASCII, + 'requires OS support of non-ASCII encodings') + def test_nonascii_filename(self): + filename = TESTFN_NONASCII + self.addCleanup(unlink, filename) + with gdbm.open(filename, 'c') as db: + db[b'key'] = b'value' + self.assertTrue(os.path.exists(filename)) + with gdbm.open(filename, 'r') as db: + self.assertEqual(list(db.keys()), [b'key']) + self.assertTrue(b'key' in db) + self.assertEqual(db[b'key'], b'value') + + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_dbm_ndbm.py b/Lib/test/test_dbm_ndbm.py index 49f4426e4cb9..fb7d0e8281e3 100644 --- a/Lib/test/test_dbm_ndbm.py +++ b/Lib/test/test_dbm_ndbm.py @@ -1,5 +1,6 @@ from test import support support.import_module("dbm.ndbm") #skip if not supported +import os import unittest import dbm.ndbm from dbm.ndbm import error @@ -47,6 +48,42 @@ def test_context_manager(self): self.assertEqual(str(cm.exception), "DBM object has already been closed") + def test_bytes(self): + with dbm.ndbm.open(self.filename, 'c') as db: + db[b'bytes key \xbd'] = b'bytes value \xbd' + with dbm.ndbm.open(self.filename, 'r') as db: + self.assertEqual(list(db.keys()), [b'bytes key \xbd']) + self.assertTrue(b'bytes key \xbd' in db) + self.assertEqual(db[b'bytes key \xbd'], b'bytes value \xbd') + + def test_unicode(self): + with dbm.ndbm.open(self.filename, 'c') as db: + db['Unicode key \U0001f40d'] = 'Unicode value \U0001f40d' + with dbm.ndbm.open(self.filename, 'r') as db: + self.assertEqual(list(db.keys()), ['Unicode key \U0001f40d'.encode()]) + self.assertTrue('Unicode key \U0001f40d'.encode() in db) + self.assertTrue('Unicode key \U0001f40d' in db) + self.assertEqual(db['Unicode key \U0001f40d'.encode()], + 'Unicode value \U0001f40d'.encode()) + self.assertEqual(db['Unicode key \U0001f40d'], + 'Unicode value \U0001f40d'.encode()) + + @unittest.skipUnless(support.TESTFN_NONASCII, + 'requires OS support of non-ASCII encodings') + def test_nonascii_filename(self): + filename = support.TESTFN_NONASCII + for suffix in ['', '.pag', '.dir', '.db']: + self.addCleanup(support.unlink, filename + suffix) + with dbm.ndbm.open(filename, 'c') as db: + db[b'key'] = b'value' + self.assertTrue(any(os.path.exists(filename + suffix) + for suffix in ['', '.pag', '.dir', '.db'])) + with dbm.ndbm.open(filename, 'r') as db: + self.assertEqual(list(db.keys()), [b'key']) + self.assertTrue(b'key' in db) + self.assertEqual(db[b'key'], b'value') + + if __name__ == '__main__': unittest.main() diff --git a/Misc/NEWS.d/next/Library/2018-02-23-19-12-04.bpo-32922.u-xe0B.rst b/Misc/NEWS.d/next/Library/2018-02-23-19-12-04.bpo-32922.u-xe0B.rst new file mode 100644 index 000000000000..412e588586c0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-23-19-12-04.bpo-32922.u-xe0B.rst @@ -0,0 +1,2 @@ +dbm.open() now encodes filename with the filesystem encoding rather than +default encoding. diff --git a/Modules/_dbmmodule.c b/Modules/_dbmmodule.c index 7e1344177b5d..8afd92cf3ca8 100644 --- a/Modules/_dbmmodule.c +++ b/Modules/_dbmmodule.c @@ -412,7 +412,7 @@ static PyTypeObject Dbmtype = { _dbm.open as dbmopen - filename: str + filename: unicode The filename to open. flags: str="r" @@ -429,9 +429,9 @@ Return a database object. [clinic start generated code]*/ static PyObject * -dbmopen_impl(PyObject *module, const char *filename, const char *flags, +dbmopen_impl(PyObject *module, PyObject *filename, const char *flags, int mode) -/*[clinic end generated code: output=5fade8cf16e0755f input=226334bade5764e6]*/ +/*[clinic end generated code: output=9527750f5df90764 input=376a9d903a50df59]*/ { int iflags; @@ -450,7 +450,20 @@ dbmopen_impl(PyObject *module, const char *filename, const char *flags, "arg 2 to open should be 'r', 'w', 'c', or 'n'"); return NULL; } - return newdbmobject(filename, iflags, mode); + + PyObject *filenamebytes = PyUnicode_EncodeFSDefault(filename); + if (filenamebytes == NULL) { + return NULL; + } + const char *name = PyBytes_AS_STRING(filenamebytes); + if (strlen(name) != (size_t)PyBytes_GET_SIZE(filenamebytes)) { + Py_DECREF(filenamebytes); + PyErr_SetString(PyExc_ValueError, "embedded null character"); + return NULL; + } + PyObject *self = newdbmobject(name, iflags, mode); + Py_DECREF(filenamebytes); + return self; } static PyMethodDef dbmmodule_methods[] = { diff --git a/Modules/_gdbmmodule.c b/Modules/_gdbmmodule.c index 12d973b5cee3..9996d8c26fb7 100644 --- a/Modules/_gdbmmodule.c +++ b/Modules/_gdbmmodule.c @@ -527,7 +527,7 @@ static PyTypeObject Dbmtype = { /*[clinic input] _gdbm.open as dbmopen - filename as name: str + filename: unicode flags: str="r" mode: int(py_default="0o666") = 0o666 / @@ -557,8 +557,9 @@ when the database has to be created. It defaults to octal 0o666. [clinic start generated code]*/ static PyObject * -dbmopen_impl(PyObject *module, const char *name, const char *flags, int mode) -/*[clinic end generated code: output=31aa1bafdf5da688 input=55563cd60e51984a]*/ +dbmopen_impl(PyObject *module, PyObject *filename, const char *flags, + int mode) +/*[clinic end generated code: output=9527750f5df90764 input=3be0b0875974b928]*/ { int iflags; @@ -606,7 +607,19 @@ dbmopen_impl(PyObject *module, const char *name, const char *flags, int mode) } } - return newdbmobject(name, iflags, mode); + PyObject *filenamebytes = PyUnicode_EncodeFSDefault(filename); + if (filenamebytes == NULL) { + return NULL; + } + const char *name = PyBytes_AS_STRING(filenamebytes); + if (strlen(name) != (size_t)PyBytes_GET_SIZE(filenamebytes)) { + Py_DECREF(filenamebytes); + PyErr_SetString(PyExc_ValueError, "embedded null character"); + return NULL; + } + PyObject *self = newdbmobject(name, iflags, mode); + Py_DECREF(filenamebytes); + return self; } static const char dbmmodule_open_flags[] = "rwcn" diff --git a/Modules/clinic/_dbmmodule.c.h b/Modules/clinic/_dbmmodule.c.h index 63d5b1a41fbf..0f831c9eec72 100644 --- a/Modules/clinic/_dbmmodule.c.h +++ b/Modules/clinic/_dbmmodule.c.h @@ -121,18 +121,18 @@ PyDoc_STRVAR(dbmopen__doc__, {"open", (PyCFunction)dbmopen, METH_FASTCALL, dbmopen__doc__}, static PyObject * -dbmopen_impl(PyObject *module, const char *filename, const char *flags, +dbmopen_impl(PyObject *module, PyObject *filename, const char *flags, int mode); static PyObject * dbmopen(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - const char *filename; + PyObject *filename; const char *flags = "r"; int mode = 438; - if (!_PyArg_ParseStack(args, nargs, "s|si:open", + if (!_PyArg_ParseStack(args, nargs, "U|si:open", &filename, &flags, &mode)) { goto exit; } @@ -141,4 +141,4 @@ dbmopen(PyObject *module, PyObject *const *args, Py_ssize_t nargs) exit: return return_value; } -/*[clinic end generated code: output=8ce71abac849155f input=a9049054013a1b77]*/ +/*[clinic end generated code: output=5c858b4080a011a4 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_gdbmmodule.c.h b/Modules/clinic/_gdbmmodule.c.h index 2222967aaa50..7bdc4321df29 100644 --- a/Modules/clinic/_gdbmmodule.c.h +++ b/Modules/clinic/_gdbmmodule.c.h @@ -234,23 +234,24 @@ PyDoc_STRVAR(dbmopen__doc__, {"open", (PyCFunction)dbmopen, METH_FASTCALL, dbmopen__doc__}, static PyObject * -dbmopen_impl(PyObject *module, const char *name, const char *flags, int mode); +dbmopen_impl(PyObject *module, PyObject *filename, const char *flags, + int mode); static PyObject * dbmopen(PyObject *module, PyObject *const *args, Py_ssize_t nargs) { PyObject *return_value = NULL; - const char *name; + PyObject *filename; const char *flags = "r"; int mode = 438; - if (!_PyArg_ParseStack(args, nargs, "s|si:open", - &name, &flags, &mode)) { + if (!_PyArg_ParseStack(args, nargs, "U|si:open", + &filename, &flags, &mode)) { goto exit; } - return_value = dbmopen_impl(module, name, flags, mode); + return_value = dbmopen_impl(module, filename, flags, mode); exit: return return_value; } -/*[clinic end generated code: output=dc0aca8c00055d02 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=dec05ff9c5aeaeae input=a9049054013a1b77]*/ From webhook-mailer at python.org Mon Feb 26 09:42:03 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 26 Feb 2018 14:42:03 -0000 Subject: [Python-checkins] bpo-18533: Avoid RecursionError from repr() of recursive dictview (GH-4823) Message-ID: https://github.com/python/cpython/commit/fbf7aac36bd1017bc87964b5d17dce0e101ff2d6 commit: fbf7aac36bd1017bc87964b5d17dce0e101ff2d6 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-26T06:42:00-08:00 summary: bpo-18533: Avoid RecursionError from repr() of recursive dictview (GH-4823) dictview_repr(): Use a Py_ReprEnter() / Py_ReprLeave() pair to check for recursion, and produce "..." if so. test_recursive_repr(): Check for the string rather than a RecursionError. (Test cannot be any tighter as contents are implementation-dependent.) test_deeply_nested_repr(): Add new test, replacing the original test_recursive_repr(). It checks that a RecursionError is raised in the case of a non-recursive but deeply nested structure. (Very similar to what test_repr_deep() in test/test_dict.py does for a normal dict.) OrderedDictTests: Add new test case, to test behavior on OrderedDict instances containing their own values() or items(). (cherry picked from commit d7773d92bd11640a8c950d6c36a9cef1cee36f96) files: A Misc/NEWS.d/next/Core and Builtins/2017-12-13-16-46-23.bpo-18533.Dlk8d7.rst M Lib/test/test_dictviews.py M Lib/test/test_ordered_dict.py M Objects/dictobject.c diff --git a/Lib/test/test_dictviews.py b/Lib/test/test_dictviews.py index 49a9e9c007bf..0807476327d8 100644 --- a/Lib/test/test_dictviews.py +++ b/Lib/test/test_dictviews.py @@ -1,6 +1,7 @@ import collections import copy import pickle +import sys import unittest class DictSetTest(unittest.TestCase): @@ -202,6 +203,20 @@ def test_items_set_operations(self): def test_recursive_repr(self): d = {} d[42] = d.values() + r = repr(d) + # Cannot perform a stronger test, as the contents of the repr + # are implementation-dependent. All we can say is that we + # want a str result, not an exception of any sort. + self.assertIsInstance(r, str) + d[42] = d.items() + r = repr(d) + # Again. + self.assertIsInstance(r, str) + + def test_deeply_nested_repr(self): + d = {} + for i in range(sys.getrecursionlimit() + 100): + d = {42: d.values()} self.assertRaises(RecursionError, repr, d) def test_copy(self): diff --git a/Lib/test/test_ordered_dict.py b/Lib/test/test_ordered_dict.py index 93f812a530f6..b396426eb153 100644 --- a/Lib/test/test_ordered_dict.py +++ b/Lib/test/test_ordered_dict.py @@ -355,6 +355,20 @@ def test_repr_recursive(self): self.assertEqual(repr(od), "OrderedDict([('a', None), ('b', None), ('c', None), ('x', ...)])") + def test_repr_recursive_values(self): + OrderedDict = self.OrderedDict + od = OrderedDict() + od[42] = od.values() + r = repr(od) + # Cannot perform a stronger test, as the contents of the repr + # are implementation-dependent. All we can say is that we + # want a str result, not an exception of any sort. + self.assertIsInstance(r, str) + od[42] = od.items() + r = repr(od) + # Again. + self.assertIsInstance(r, str) + def test_setdefault(self): OrderedDict = self.OrderedDict pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-12-13-16-46-23.bpo-18533.Dlk8d7.rst b/Misc/NEWS.d/next/Core and Builtins/2017-12-13-16-46-23.bpo-18533.Dlk8d7.rst new file mode 100644 index 000000000000..a33eff5c7059 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-12-13-16-46-23.bpo-18533.Dlk8d7.rst @@ -0,0 +1,3 @@ +``repr()`` on a dict containing its own ``values()`` or ``items()`` no +longer raises ``RecursionError``; OrderedDict similarly. Instead, use +``...``, as for other recursive structures. Patch by Ben North. diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 690ef3bd2b3a..8862be81482d 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -3948,14 +3948,22 @@ static PyObject * dictview_repr(_PyDictViewObject *dv) { PyObject *seq; - PyObject *result; + PyObject *result = NULL; + Py_ssize_t rc; + rc = Py_ReprEnter((PyObject *)dv); + if (rc != 0) { + return rc > 0 ? PyUnicode_FromString("...") : NULL; + } seq = PySequence_List((PyObject *)dv); - if (seq == NULL) - return NULL; - + if (seq == NULL) { + goto Done; + } result = PyUnicode_FromFormat("%s(%R)", Py_TYPE(dv)->tp_name, seq); Py_DECREF(seq); + +Done: + Py_ReprLeave((PyObject *)dv); return result; } From webhook-mailer at python.org Mon Feb 26 09:50:14 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Mon, 26 Feb 2018 14:50:14 -0000 Subject: [Python-checkins] Revert unneccessary changes made in bpo-30296 and apply other improvements. (GH-2624) Message-ID: https://github.com/python/cpython/commit/3f2e6f15d64d81633b1fc0b308afc0d6e9026b61 commit: 3f2e6f15d64d81633b1fc0b308afc0d6e9026b61 branch: master author: Serhiy Storchaka committer: GitHub date: 2018-02-26T16:50:11+02:00 summary: Revert unneccessary changes made in bpo-30296 and apply other improvements. (GH-2624) files: M Lib/logging/config.py M Lib/pstats.py M Lib/turtle.py M Lib/urllib/request.py diff --git a/Lib/logging/config.py b/Lib/logging/config.py index 7927e7618777..1b0facaf6269 100644 --- a/Lib/logging/config.py +++ b/Lib/logging/config.py @@ -460,7 +460,7 @@ def configure_custom(self, config): c = self.resolve(c) props = config.pop('.', None) # Check for valid identifiers - kwargs = dict((k, config[k]) for k in config if valid_ident(k)) + kwargs = {k: config[k] for k in config if valid_ident(k)} result = c(**kwargs) if props: for name, value in props.items(): @@ -723,7 +723,7 @@ def configure_handler(self, config): config['address'] = self.as_tuple(config['address']) factory = klass props = config.pop('.', None) - kwargs = dict((k, config[k]) for k in config if valid_ident(k)) + kwargs = {k: config[k] for k in config if valid_ident(k)} try: result = factory(**kwargs) except TypeError as te: diff --git a/Lib/pstats.py b/Lib/pstats.py index 1b57d26b5a5c..ded5ae59f7da 100644 --- a/Lib/pstats.py +++ b/Lib/pstats.py @@ -530,7 +530,7 @@ def add_callers(target, source): if func in new_callers: if isinstance(caller, tuple): # format used by cProfile - new_callers[func] = tuple(i[0] + i[1] for i in zip(caller, new_callers[func])) + new_callers[func] = tuple(i + j for i, j in zip(caller, new_callers[func])) else: # format used by profile new_callers[func] += caller diff --git a/Lib/turtle.py b/Lib/turtle.py index 8909fe914e74..9db564b7eb8b 100644 --- a/Lib/turtle.py +++ b/Lib/turtle.py @@ -3839,7 +3839,7 @@ def write_docstringdict(filename="turtle_docstringdict"): docsdict[key] = eval(key).__doc__ with open("%s.py" % filename,"w") as f: - keys = sorted(x for x in docsdict.keys() + keys = sorted(x for x in docsdict if x.split('.')[1] not in _alias_list) f.write('docsdict = {\n\n') for key in keys[:-1]: diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py index 2b769421c56a..5b962f7dc20b 100644 --- a/Lib/urllib/request.py +++ b/Lib/urllib/request.py @@ -1286,7 +1286,8 @@ def do_open(self, http_class, req, **http_conn_args): h.set_debuglevel(self._debuglevel) headers = dict(req.unredirected_hdrs) - headers.update((k, v) for k, v in req.headers.items() if k not in headers) + headers.update({k: v for k, v in req.headers.items() + if k not in headers}) # TODO(jhylton): Should this be redesigned to handle # persistent connections? From webhook-mailer at python.org Mon Feb 26 13:10:39 2018 From: webhook-mailer at python.org (Steve Dower) Date: Mon, 26 Feb 2018 18:10:39 -0000 Subject: [Python-checkins] bpo-32394: Remove some TCP options on old version Windows. (GH-5523) Message-ID: https://github.com/python/cpython/commit/19e7d48ce89422091f9af93038b9fee075d46e9e commit: 19e7d48ce89422091f9af93038b9fee075d46e9e branch: master author: animalize committer: Steve Dower date: 2018-02-26T10:10:36-08:00 summary: bpo-32394: Remove some TCP options on old version Windows. (GH-5523) files: A Misc/NEWS.d/next/Library/2018-02-10-13-51-56.bpo-32394.dFM9SI.rst M Doc/library/socket.rst M Lib/test/test_socket.py M Modules/socketmodule.c diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst index 04042ffdf1ac..4ce966981eba 100644 --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -320,9 +320,16 @@ Constants ``SO_DOMAIN``, ``SO_PROTOCOL``, ``SO_PEERSEC``, ``SO_PASSSEC``, ``TCP_USER_TIMEOUT``, ``TCP_CONGESTION`` were added. + .. versionchanged:: 3.6.5 + On Windows, ``TCP_FASTOPEN``, ``TCP_KEEPCNT`` appear if run-time Windows + supports. + .. versionchanged:: 3.7 ``TCP_NOTSENT_LOWAT`` was added. + On Windows, ``TCP_KEEPIDLE``, ``TCP_KEEPINTVL`` appear if run-time Windows + supports. + .. data:: AF_CAN PF_CAN SOL_CAN_* diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index b0e1b7471ee2..bff1dc2d0638 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -5945,6 +5945,27 @@ def test_sendmsg_afalg_args(self): with self.assertRaises(TypeError): sock.sendmsg_afalg(op=socket.ALG_OP_ENCRYPT, assoclen=-1) + at unittest.skipUnless(sys.platform.startswith("win"), "requires Windows") +class TestMSWindowsTCPFlags(unittest.TestCase): + knownTCPFlags = { + # avaliable since long time ago + 'TCP_MAXSEG', + 'TCP_NODELAY', + # available starting with Windows 10 1607 + 'TCP_FASTOPEN', + # available starting with Windows 10 1703 + 'TCP_KEEPCNT', + # available starting with Windows 10 1709 + 'TCP_KEEPIDLE', + 'TCP_KEEPINTVL' + } + + def test_new_tcp_flags(self): + provided = [s for s in dir(socket) if s.startswith('TCP')] + unknown = [s for s in provided if s not in self.knownTCPFlags] + + self.assertEqual([], unknown, + "New TCP flags were discovered. See bpo-32394 for more information") def test_main(): tests = [GeneralModuleTests, BasicTCPTest, TCPCloserTest, TCPTimeoutTest, @@ -6005,6 +6026,7 @@ def test_main(): SendfileUsingSendTest, SendfileUsingSendfileTest, ]) + tests.append(TestMSWindowsTCPFlags) thread_info = support.threading_setup() support.run_unittest(*tests) diff --git a/Misc/NEWS.d/next/Library/2018-02-10-13-51-56.bpo-32394.dFM9SI.rst b/Misc/NEWS.d/next/Library/2018-02-10-13-51-56.bpo-32394.dFM9SI.rst new file mode 100644 index 000000000000..ee5807619a93 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-10-13-51-56.bpo-32394.dFM9SI.rst @@ -0,0 +1,2 @@ +socket: Remove TCP_FASTOPEN,TCP_KEEPCNT,TCP_KEEPIDLE,TCP_KEEPINTVL flags on +older version Windows during run-time. diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index aa715bf95d76..c7a07512026b 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -305,6 +305,70 @@ if_indextoname(index) -- return the corresponding interface name\n\ /* Provides the IsWindows7SP1OrGreater() function */ #include +/* remove some flags on older version Windows during run-time. + https://msdn.microsoft.com/en-us/library/windows/desktop/ms738596.aspx */ +typedef struct { + DWORD build_number; /* available starting with this Win10 BuildNumber */ + const char flag_name[20]; +} FlagRuntimeInfo; + +/* IMPORTANT: make sure the list ordered by descending build_number */ +static FlagRuntimeInfo win_runtime_flags[] = { + /* available starting with Windows 10 1709 */ + {16299, "TCP_KEEPIDLE"}, + {16299, "TCP_KEEPINTVL"}, + /* available starting with Windows 10 1703 */ + {15063, "TCP_KEEPCNT"}, + /* available starting with Windows 10 1607 */ + {14393, "TCP_FASTOPEN"} +}; + +static void +remove_unusable_flags(PyObject *m) +{ + PyObject *dict; + OSVERSIONINFOEX info; + DWORDLONG dwlConditionMask; + + dict = PyModule_GetDict(m); + if (dict == NULL) { + return; + } + + /* set to Windows 10, except BuildNumber. */ + memset(&info, 0, sizeof(info)); + info.dwOSVersionInfoSize = sizeof(info); + info.dwMajorVersion = 10; + info.dwMinorVersion = 0; + + /* set Condition Mask */ + dwlConditionMask = 0; + VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL); + VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL); + VER_SET_CONDITION(dwlConditionMask, VER_BUILDNUMBER, VER_GREATER_EQUAL); + + for (int i=0; i @@ -7890,5 +7954,11 @@ PyInit__socket(void) #if defined(USE_GETHOSTBYNAME_LOCK) || defined(USE_GETADDRINFO_LOCK) netdb_lock = PyThread_allocate_lock(); #endif + +#ifdef MS_WINDOWS + /* remove some flags on older version Windows during run-time */ + remove_unusable_flags(m); +#endif + return m; } From webhook-mailer at python.org Mon Feb 26 13:13:54 2018 From: webhook-mailer at python.org (Steve Dower) Date: Mon, 26 Feb 2018 18:13:54 -0000 Subject: [Python-checkins] [3.6] bpo-32394: Remove some TCP options on older version Windows. (GH-5585) Message-ID: https://github.com/python/cpython/commit/1278c21f5234477aab21531773d65ca7ebd1b81f commit: 1278c21f5234477aab21531773d65ca7ebd1b81f branch: 3.6 author: animalize committer: Steve Dower date: 2018-02-26T10:13:51-08:00 summary: [3.6] bpo-32394: Remove some TCP options on older version Windows. (GH-5585) files: A Misc/NEWS.d/next/Library/2018-02-08-08-18-26.bpo-32394.6E_7X7.rst M Doc/library/socket.rst M Lib/test/test_socket.py M Modules/socketmodule.c diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst index 678e32ce57f1..512c38e785d2 100644 --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -303,6 +303,10 @@ Constants ``SO_DOMAIN``, ``SO_PROTOCOL``, ``SO_PEERSEC``, ``SO_PASSSEC``, ``TCP_USER_TIMEOUT``, ``TCP_CONGESTION`` were added. + .. versionchanged:: 3.6.5 + On Windows, ``TCP_FASTOPEN``, ``TCP_KEEPCNT`` appear if run-time Windows + supports. + .. data:: AF_CAN PF_CAN SOL_CAN_* diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index 00237626d6c4..faa4868587cd 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -5583,6 +5583,24 @@ def test_sendmsg_afalg_args(self): with self.assertRaises(TypeError): sock.sendmsg_afalg(op=socket.ALG_OP_ENCRYPT, assoclen=-1) + at unittest.skipUnless(sys.platform.startswith("win"), "requires Windows") +class TestMSWindowsTCPFlags(unittest.TestCase): + knownTCPFlags = { + # avaliable since long time ago + 'TCP_MAXSEG', + 'TCP_NODELAY', + # available starting with Windows 10 1607 + 'TCP_FASTOPEN', + # available starting with Windows 10 1703 + 'TCP_KEEPCNT', + } + + def test_new_tcp_flags(self): + provided = [s for s in dir(socket) if s.startswith('TCP')] + unknown = [s for s in provided if s not in self.knownTCPFlags] + + self.assertEqual([], unknown, + "New TCP flags were discovered. See bpo-32394 for more information") def test_main(): tests = [GeneralModuleTests, BasicTCPTest, TCPCloserTest, TCPTimeoutTest, @@ -5639,6 +5657,7 @@ def test_main(): SendfileUsingSendTest, SendfileUsingSendfileTest, ]) + tests.append(TestMSWindowsTCPFlags) thread_info = support.threading_setup() support.run_unittest(*tests) diff --git a/Misc/NEWS.d/next/Library/2018-02-08-08-18-26.bpo-32394.6E_7X7.rst b/Misc/NEWS.d/next/Library/2018-02-08-08-18-26.bpo-32394.6E_7X7.rst new file mode 100644 index 000000000000..f7fb42d8e7a3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-08-08-18-26.bpo-32394.6E_7X7.rst @@ -0,0 +1,2 @@ +socket: Remove TCP_FASTOPEN, TCP_KEEPCNT flags on older version Windows +during run-time. diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index 8d9915a42f5b..b455021c2fd4 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -317,6 +317,67 @@ if_indextoname(index) -- return the corresponding interface name\n\ #include #endif +/* remove some flags on older version Windows during run-time. + https://msdn.microsoft.com/en-us/library/windows/desktop/ms738596.aspx */ +typedef struct { + DWORD build_number; /* available starting with this Win10 BuildNumber */ + const char flag_name[20]; +} FlagRuntimeInfo; + +/* IMPORTANT: make sure the list ordered by descending build_number */ +static FlagRuntimeInfo win_runtime_flags[] = { + /* available starting with Windows 10 1703 */ + {15063, "TCP_KEEPCNT"}, + /* available starting with Windows 10 1607 */ + {14393, "TCP_FASTOPEN"} +}; + +static void +remove_unusable_flags(PyObject *m) +{ + PyObject *dict; + OSVERSIONINFOEX info; + DWORDLONG dwlConditionMask; + + dict = PyModule_GetDict(m); + if (dict == NULL) { + return; + } + + /* set to Windows 10, except BuildNumber. */ + memset(&info, 0, sizeof(info)); + info.dwOSVersionInfoSize = sizeof(info); + info.dwMajorVersion = 10; + info.dwMinorVersion = 0; + + /* set Condition Mask */ + dwlConditionMask = 0; + VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL); + VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL); + VER_SET_CONDITION(dwlConditionMask, VER_BUILDNUMBER, VER_GREATER_EQUAL); + + for (int i=0; i @@ -7694,6 +7755,12 @@ PyInit__socket(void) #if defined(USE_GETHOSTBYNAME_LOCK) || defined(USE_GETADDRINFO_LOCK) netdb_lock = PyThread_allocate_lock(); #endif + +#ifdef MS_WINDOWS + /* removes some flags on older version Windows during run-time */ + remove_unusable_flags(m); +#endif + return m; } From webhook-mailer at python.org Mon Feb 26 13:36:26 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 26 Feb 2018 18:36:26 -0000 Subject: [Python-checkins] bpo-32394: Remove some TCP options on old version Windows. (GH-5523) Message-ID: https://github.com/python/cpython/commit/53d3f8a89971bac3d2f454ff9f923066ecc3a6d9 commit: 53d3f8a89971bac3d2f454ff9f923066ecc3a6d9 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-26T10:36:17-08:00 summary: bpo-32394: Remove some TCP options on old version Windows. (GH-5523) (cherry picked from commit 19e7d48ce89422091f9af93038b9fee075d46e9e) Co-authored-by: animalize files: A Misc/NEWS.d/next/Library/2018-02-10-13-51-56.bpo-32394.dFM9SI.rst M Doc/library/socket.rst M Lib/test/test_socket.py M Modules/socketmodule.c diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst index 04042ffdf1ac..4ce966981eba 100644 --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -320,9 +320,16 @@ Constants ``SO_DOMAIN``, ``SO_PROTOCOL``, ``SO_PEERSEC``, ``SO_PASSSEC``, ``TCP_USER_TIMEOUT``, ``TCP_CONGESTION`` were added. + .. versionchanged:: 3.6.5 + On Windows, ``TCP_FASTOPEN``, ``TCP_KEEPCNT`` appear if run-time Windows + supports. + .. versionchanged:: 3.7 ``TCP_NOTSENT_LOWAT`` was added. + On Windows, ``TCP_KEEPIDLE``, ``TCP_KEEPINTVL`` appear if run-time Windows + supports. + .. data:: AF_CAN PF_CAN SOL_CAN_* diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index b0e1b7471ee2..bff1dc2d0638 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -5945,6 +5945,27 @@ def test_sendmsg_afalg_args(self): with self.assertRaises(TypeError): sock.sendmsg_afalg(op=socket.ALG_OP_ENCRYPT, assoclen=-1) + at unittest.skipUnless(sys.platform.startswith("win"), "requires Windows") +class TestMSWindowsTCPFlags(unittest.TestCase): + knownTCPFlags = { + # avaliable since long time ago + 'TCP_MAXSEG', + 'TCP_NODELAY', + # available starting with Windows 10 1607 + 'TCP_FASTOPEN', + # available starting with Windows 10 1703 + 'TCP_KEEPCNT', + # available starting with Windows 10 1709 + 'TCP_KEEPIDLE', + 'TCP_KEEPINTVL' + } + + def test_new_tcp_flags(self): + provided = [s for s in dir(socket) if s.startswith('TCP')] + unknown = [s for s in provided if s not in self.knownTCPFlags] + + self.assertEqual([], unknown, + "New TCP flags were discovered. See bpo-32394 for more information") def test_main(): tests = [GeneralModuleTests, BasicTCPTest, TCPCloserTest, TCPTimeoutTest, @@ -6005,6 +6026,7 @@ def test_main(): SendfileUsingSendTest, SendfileUsingSendfileTest, ]) + tests.append(TestMSWindowsTCPFlags) thread_info = support.threading_setup() support.run_unittest(*tests) diff --git a/Misc/NEWS.d/next/Library/2018-02-10-13-51-56.bpo-32394.dFM9SI.rst b/Misc/NEWS.d/next/Library/2018-02-10-13-51-56.bpo-32394.dFM9SI.rst new file mode 100644 index 000000000000..ee5807619a93 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-10-13-51-56.bpo-32394.dFM9SI.rst @@ -0,0 +1,2 @@ +socket: Remove TCP_FASTOPEN,TCP_KEEPCNT,TCP_KEEPIDLE,TCP_KEEPINTVL flags on +older version Windows during run-time. diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index c1b24c153e2b..c264d33b0b0f 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -305,6 +305,70 @@ if_indextoname(index) -- return the corresponding interface name\n\ /* Provides the IsWindows7SP1OrGreater() function */ #include +/* remove some flags on older version Windows during run-time. + https://msdn.microsoft.com/en-us/library/windows/desktop/ms738596.aspx */ +typedef struct { + DWORD build_number; /* available starting with this Win10 BuildNumber */ + const char flag_name[20]; +} FlagRuntimeInfo; + +/* IMPORTANT: make sure the list ordered by descending build_number */ +static FlagRuntimeInfo win_runtime_flags[] = { + /* available starting with Windows 10 1709 */ + {16299, "TCP_KEEPIDLE"}, + {16299, "TCP_KEEPINTVL"}, + /* available starting with Windows 10 1703 */ + {15063, "TCP_KEEPCNT"}, + /* available starting with Windows 10 1607 */ + {14393, "TCP_FASTOPEN"} +}; + +static void +remove_unusable_flags(PyObject *m) +{ + PyObject *dict; + OSVERSIONINFOEX info; + DWORDLONG dwlConditionMask; + + dict = PyModule_GetDict(m); + if (dict == NULL) { + return; + } + + /* set to Windows 10, except BuildNumber. */ + memset(&info, 0, sizeof(info)); + info.dwOSVersionInfoSize = sizeof(info); + info.dwMajorVersion = 10; + info.dwMinorVersion = 0; + + /* set Condition Mask */ + dwlConditionMask = 0; + VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL); + VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL); + VER_SET_CONDITION(dwlConditionMask, VER_BUILDNUMBER, VER_GREATER_EQUAL); + + for (int i=0; i @@ -7890,5 +7954,11 @@ PyInit__socket(void) #if defined(USE_GETHOSTBYNAME_LOCK) || defined(USE_GETADDRINFO_LOCK) netdb_lock = PyThread_allocate_lock(); #endif + +#ifdef MS_WINDOWS + /* remove some flags on older version Windows during run-time */ + remove_unusable_flags(m); +#endif + return m; } From webhook-mailer at python.org Mon Feb 26 14:23:33 2018 From: webhook-mailer at python.org (Barry Warsaw) Date: Mon, 26 Feb 2018 19:23:33 -0000 Subject: [Python-checkins] Revert "[3.6] bpo-32303 - Consistency fixes for namespace loaders (GH-5481) (#5504)" (#5911) Message-ID: https://github.com/python/cpython/commit/86ea85134645c75783936ca4b5c6269cb8ac4634 commit: 86ea85134645c75783936ca4b5c6269cb8ac4634 branch: 3.6 author: Barry Warsaw committer: GitHub date: 2018-02-26T11:23:24-08:00 summary: Revert "[3.6] bpo-32303 - Consistency fixes for namespace loaders (GH-5481) (#5504)" (#5911) This reverts commit a71397fb6603d0fe673acd7765c74699cd28fe7b. files: D Misc/NEWS.d/next/Core and Builtins/2018-02-01-10-16-28.bpo-32303.VsvhSl.rst D Misc/NEWS.d/next/Core and Builtins/2018-02-01-10-56-41.bpo-32305.dkU9Qa.rst M Doc/library/importlib.rst M Lib/importlib/_bootstrap.py M Lib/importlib/_bootstrap_external.py M Lib/test/test_importlib/test_api.py M Lib/test/test_importlib/test_namespace_pkgs.py M Python/importlib.h M Python/importlib_external.h diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst index 34156135715f..d194362fb003 100644 --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -1077,7 +1077,7 @@ find and load modules. Name of the place from which the module is loaded, e.g. "builtin" for built-in modules and the filename for modules loaded from source. Normally "origin" should be set, but it may be ``None`` (the default) - which indicates it is unspecified (e.g. for namespace packages). + which indicates it is unspecified. .. attribute:: submodule_search_locations diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py index dfcdb99463cf..e2343dd43080 100644 --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -522,18 +522,6 @@ def _init_module_attrs(spec, module, *, override=False): loader = _NamespaceLoader.__new__(_NamespaceLoader) loader._path = spec.submodule_search_locations - spec.loader = loader - # While the docs say that module.__file__ is not set for - # built-in modules, and the code below will avoid setting it if - # spec.has_location is false, this is incorrect for namespace - # packages. Namespace packages have no location, but their - # __spec__.origin is None, and thus their module.__file__ - # should also be None for consistency. While a bit of a hack, - # this is the best place to ensure this consistency. - # - # See # https://docs.python.org/3/library/importlib.html#importlib.abc.Loader.load_module - # and bpo-32305 - module.__file__ = None try: module.__loader__ = loader except AttributeError: diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index 62da085f876e..9feec50842c7 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -1160,9 +1160,9 @@ def find_spec(cls, fullname, path=None, target=None): elif spec.loader is None: namespace_path = spec.submodule_search_locations if namespace_path: - # We found at least one namespace path. Return a spec which - # can create the namespace package. - spec.origin = None + # We found at least one namespace path. Return a + # spec which can create the namespace package. + spec.origin = 'namespace' spec.submodule_search_locations = _NamespacePath(fullname, namespace_path, cls._get_spec) return spec else: diff --git a/Lib/test/test_importlib/test_api.py b/Lib/test/test_importlib/test_api.py index 446ed6c6fbb1..b0a94aaff5b3 100644 --- a/Lib/test/test_importlib/test_api.py +++ b/Lib/test/test_importlib/test_api.py @@ -307,7 +307,6 @@ def test_reload_namespace_changed(self): expected = {'__name__': name, '__package__': name, '__doc__': None, - '__file__': None, } os.mkdir(name) with open(bad_path, 'w') as init_file: @@ -319,9 +318,8 @@ def test_reload_namespace_changed(self): spec = ns.pop('__spec__') ns.pop('__builtins__', None) # An implementation detail. self.assertEqual(spec.name, name) - self.assertIsNotNone(spec.loader) - self.assertIsNotNone(loader) - self.assertEqual(spec.loader, loader) + self.assertIs(spec.loader, None) + self.assertIsNot(loader, None) self.assertEqual(set(path), set([os.path.dirname(bad_path)])) with self.assertRaises(AttributeError): diff --git a/Lib/test/test_importlib/test_namespace_pkgs.py b/Lib/test/test_importlib/test_namespace_pkgs.py index 8e4b5d66fecc..e37d8a18f4ac 100644 --- a/Lib/test/test_importlib/test_namespace_pkgs.py +++ b/Lib/test/test_importlib/test_namespace_pkgs.py @@ -317,21 +317,5 @@ def test_dynamic_path(self): self.assertEqual(foo.two.attr, 'portion2 foo two') -class LoaderTests(NamespacePackageTest): - paths = ['portion1'] - - def test_namespace_loader_consistency(self): - # bpo-32303 - import foo - self.assertEqual(foo.__loader__, foo.__spec__.loader) - self.assertIsNotNone(foo.__loader__) - - def test_namespace_origin_consistency(self): - # bpo-32305 - import foo - self.assertIsNone(foo.__spec__.origin) - self.assertIsNone(foo.__file__) - - if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-02-01-10-16-28.bpo-32303.VsvhSl.rst b/Misc/NEWS.d/next/Core and Builtins/2018-02-01-10-16-28.bpo-32303.VsvhSl.rst deleted file mode 100644 index b84448fb25a1..000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2018-02-01-10-16-28.bpo-32303.VsvhSl.rst +++ /dev/null @@ -1 +0,0 @@ -Make sure ``__spec__.loader`` matches ``__loader__`` for namespace packages. diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-02-01-10-56-41.bpo-32305.dkU9Qa.rst b/Misc/NEWS.d/next/Core and Builtins/2018-02-01-10-56-41.bpo-32305.dkU9Qa.rst deleted file mode 100644 index 204d74a49754..000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2018-02-01-10-56-41.bpo-32305.dkU9Qa.rst +++ /dev/null @@ -1,2 +0,0 @@ -For namespace packages, ensure that both ``__file__`` and -``__spec__.origin`` are set to None. diff --git a/Python/importlib.h b/Python/importlib.h index 2996b624fd69..191197b83852 100644 --- a/Python/importlib.h +++ b/Python/importlib.h @@ -863,961 +863,960 @@ const unsigned char _Py_M__importlib[] = { 14,1,20,1,6,1,6,1,114,129,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,59,0,0,0,67,0,0,0,115, - 226,1,0,0,124,2,115,20,116,0,124,1,100,1,100,0, + 212,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, + 124,1,100,2,100,0,131,3,100,0,107,8,114,166,124,0, + 106,4,125,3,124,3,100,0,107,8,114,134,124,0,106,5, + 100,0,107,9,114,134,116,6,100,0,107,8,114,110,116,7, 130,1,116,6,106,8,125,4,124,4,106,9,124,4,131,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,86, - 0,0,0,218,11,95,95,112,97,99,107,97,103,101,95,95, - 114,128,0,0,0,114,93,0,0,0,114,126,0,0,0,41, - 21,114,6,0,0,0,114,15,0,0,0,114,1,0,0,0, - 114,91,0,0,0,114,94,0,0,0,114,107,0,0,0,114, - 116,0,0,0,114,117,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,93,0,0,0, - 114,86,0,0,0,114,120,0,0,0,114,131,0,0,0,114, - 90,0,0,0,114,128,0,0,0,114,114,0,0,0,114,104, - 0,0,0,114,113,0,0,0,114,126,0,0,0,41,5,114, - 83,0,0,0,114,84,0,0,0,114,130,0,0,0,114,94, - 0,0,0,114,132,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,134,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,106,2,124,0,131,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,94,0,0, - 0,114,135,0,0,0,114,71,0,0,0,114,16,0,0,0, - 114,15,0,0,0,114,134,0,0,0,41,2,114,83,0,0, - 0,114,84,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,137,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,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,106,3,124,1,131, - 1,83,0,100,4,106,3,124,1,124,0,106,2,131,2,83, - 0,110,36,124,0,106,4,114,86,100,5,106,3,124,1,124, - 0,106,1,131,2,83,0,100,6,106,3,124,0,106,0,124, - 0,106,1,131,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,88,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,104,0,0,0,114,94,0,0,0,114,38, - 0,0,0,114,114,0,0,0,41,2,114,83,0,0,0,114, - 15,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, - 0,0,0,114,92,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,92,0,0,0,99,2,0,0,0,0,0,0,0,4, - 0,0,0,12,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,106,4,124,2,131,1,124,1,107,9,114,54, - 100,1,106,5,124,2,131,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,106,11,124,2,131,1,1,0, - 110,12,124,0,106,7,106,12,124,1,131,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,130,0,0,0,114,136,0,0, - 0,41,13,114,15,0,0,0,114,42,0,0,0,114,14,0, - 0,0,114,80,0,0,0,114,30,0,0,0,114,38,0,0, - 0,114,71,0,0,0,114,94,0,0,0,114,107,0,0,0, - 114,134,0,0,0,114,4,0,0,0,218,11,108,111,97,100, - 95,109,111,100,117,108,101,114,136,0,0,0,41,4,114,83, - 0,0,0,114,84,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,81,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,81,0, - 0,0,99,1,0,0,0,0,0,0,0,2,0,0,0,27, - 0,0,0,67,0,0,0,115,206,0,0,0,124,0,106,0, - 106,1,124,0,106,2,131,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, - 106,11,100,4,131,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,86,0, - 0,0,114,131,0,0,0,114,128,0,0,0,114,118,0,0, - 0,114,19,0,0,0,114,90,0,0,0,41,13,114,94,0, - 0,0,114,138,0,0,0,114,15,0,0,0,114,14,0,0, - 0,114,80,0,0,0,114,6,0,0,0,114,86,0,0,0, - 114,91,0,0,0,114,1,0,0,0,114,131,0,0,0,114, - 4,0,0,0,114,119,0,0,0,114,90,0,0,0,41,2, - 114,83,0,0,0,114,84,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,140,0,0,0,99,1,0,0,0,0, - 0,0,0,2,0,0,0,11,0,0,0,67,0,0,0,115, - 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,106,8,124,1, - 131,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,136,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,94,0,0,0, - 114,4,0,0,0,114,140,0,0,0,114,137,0,0,0,114, - 97,0,0,0,114,107,0,0,0,114,71,0,0,0,114,15, - 0,0,0,114,136,0,0,0,114,14,0,0,0,114,80,0, - 0,0,41,2,114,83,0,0,0,114,84,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,141,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,141,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,82,0,0,0,174,2,0,0,115,4,0,0,0, - 0,9,12,1,114,82,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,2,0,0, - 0,67,0,0,0,115,12,0,0,0,100,1,106,0,124,0, - 106,1,131,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,84,0,0,0,114,10,0,0,0,114, - 10,0,0,0,114,11,0,0,0,114,87,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,106, - 1,124,1,131,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,104,0,0, - 0,41,3,114,49,0,0,0,90,10,105,115,95,98,117,105, - 108,116,105,110,114,79,0,0,0,41,4,218,3,99,108,115, - 114,72,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,3,0,0,0,67,0,0,0, - 115,30,0,0,0,124,0,106,0,124,1,124,2,131,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,146,0,0,0,114,94, - 0,0,0,41,4,114,143,0,0,0,114,72,0,0,0,114, - 144,0,0,0,114,83,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,106,4,124,1,106,0,131, - 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,70,0,0,0,114,71,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,83,0,0,0,114,10,0,0,0,114, - 10,0,0,0,114,11,0,0,0,114,135,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,84,0,0,0,114,10,0,0,0,114,10, - 0,0,0,114,11,0,0,0,114,136,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,143,0,0,0,114,72,0, + 125,3,124,0,106,5,124,3,95,10,121,10,124,3,124,1, + 95,11,87,0,110,20,4,0,116,3,107,10,114,164,1,0, + 1,0,1,0,89,0,110,2,88,0,124,2,115,186,116,0, + 124,1,100,3,100,0,131,3,100,0,107,8,114,220,121,12, + 124,0,106,12,124,1,95,13,87,0,110,20,4,0,116,3, + 107,10,114,218,1,0,1,0,1,0,89,0,110,2,88,0, + 121,10,124,0,124,1,95,14,87,0,110,20,4,0,116,3, + 107,10,114,250,1,0,1,0,1,0,89,0,110,2,88,0, + 124,2,144,1,115,20,116,0,124,1,100,4,100,0,131,3, + 100,0,107,8,144,1,114,68,124,0,106,5,100,0,107,9, + 144,1,114,68,121,12,124,0,106,5,124,1,95,15,87,0, + 110,22,4,0,116,3,107,10,144,1,114,66,1,0,1,0, + 1,0,89,0,110,2,88,0,124,0,106,16,144,1,114,208, + 124,2,144,1,115,100,116,0,124,1,100,5,100,0,131,3, + 100,0,107,8,144,1,114,136,121,12,124,0,106,17,124,1, + 95,18,87,0,110,22,4,0,116,3,107,10,144,1,114,134, + 1,0,1,0,1,0,89,0,110,2,88,0,124,2,144,1, + 115,160,116,0,124,1,100,6,100,0,131,3,100,0,107,8, + 144,1,114,208,124,0,106,19,100,0,107,9,144,1,114,208, + 121,12,124,0,106,19,124,1,95,20,87,0,110,22,4,0, + 116,3,107,10,144,1,114,206,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,86,0,0,0,218,11,95,95,112,97,99,107,97,103,101, + 95,95,114,128,0,0,0,114,93,0,0,0,114,126,0,0, + 0,41,21,114,6,0,0,0,114,15,0,0,0,114,1,0, + 0,0,114,91,0,0,0,114,94,0,0,0,114,107,0,0, + 0,114,116,0,0,0,114,117,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,86,0, + 0,0,114,120,0,0,0,114,131,0,0,0,114,90,0,0, + 0,114,128,0,0,0,114,114,0,0,0,114,104,0,0,0, + 114,93,0,0,0,114,113,0,0,0,114,126,0,0,0,41, + 5,114,83,0,0,0,114,84,0,0,0,114,130,0,0,0, + 114,94,0,0,0,114,132,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,92,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,2,1,10,1,14,1,6,2,20,1,2,1, + 12,1,14,1,6,2,2,1,10,1,14,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,134,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,106,2,124,0,131,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,94,0,0,0,114, + 135,0,0,0,114,71,0,0,0,114,16,0,0,0,114,15, + 0,0,0,114,134,0,0,0,41,2,114,83,0,0,0,114, + 84,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,52,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,137,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,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,106,3,124,1,131,1,83, + 0,100,4,106,3,124,1,124,0,106,2,131,2,83,0,110, + 36,124,0,106,4,114,86,100,5,106,3,124,1,124,0,106, + 1,131,2,83,0,100,6,106,3,124,0,106,0,124,0,106, + 1,131,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,88,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,104,0,0,0,114,94,0,0,0,114,38,0,0, + 0,114,114,0,0,0,41,2,114,83,0,0,0,114,15,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, + 0,114,92,0,0,0,69,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, + 92,0,0,0,99,2,0,0,0,0,0,0,0,4,0,0, + 0,12,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,106,4,124,2,131,1,124,1,107,9,114,54,100,1, + 106,5,124,2,131,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,106,11,124,2,131,1,1,0,110,12, + 124,0,106,7,106,12,124,1,131,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,130,0,0,0,114,136,0,0,0,41, + 13,114,15,0,0,0,114,42,0,0,0,114,14,0,0,0, + 114,80,0,0,0,114,30,0,0,0,114,38,0,0,0,114, + 71,0,0,0,114,94,0,0,0,114,107,0,0,0,114,134, + 0,0,0,114,4,0,0,0,218,11,108,111,97,100,95,109, + 111,100,117,108,101,114,136,0,0,0,41,4,114,83,0,0, + 0,114,84,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, + 81,0,0,0,86,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,81,0,0,0, + 99,1,0,0,0,0,0,0,0,2,0,0,0,27,0,0, + 0,67,0,0,0,115,206,0,0,0,124,0,106,0,106,1, + 124,0,106,2,131,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,106,11, + 100,4,131,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,86,0,0,0, + 114,131,0,0,0,114,128,0,0,0,114,118,0,0,0,114, + 19,0,0,0,114,90,0,0,0,41,13,114,94,0,0,0, + 114,138,0,0,0,114,15,0,0,0,114,14,0,0,0,114, + 80,0,0,0,114,6,0,0,0,114,86,0,0,0,114,91, + 0,0,0,114,1,0,0,0,114,131,0,0,0,114,4,0, + 0,0,114,119,0,0,0,114,90,0,0,0,41,2,114,83, + 0,0,0,114,84,0,0,0,114,10,0,0,0,114,10,0, + 0,0,114,11,0,0,0,218,25,95,108,111,97,100,95,98, + 97,99,107,119,97,114,100,95,99,111,109,112,97,116,105,98, + 108,101,110,2,0,0,115,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,140,0,0,0,99,1,0,0,0,0,0,0, + 0,2,0,0,0,11,0,0,0,67,0,0,0,115,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,106,8,124,1,131,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,136,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,94,0,0,0,114,4, + 0,0,0,114,140,0,0,0,114,137,0,0,0,114,97,0, + 0,0,114,107,0,0,0,114,71,0,0,0,114,15,0,0, + 0,114,136,0,0,0,114,14,0,0,0,114,80,0,0,0, + 41,2,114,83,0,0,0,114,84,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,139,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,141,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,141,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,82,0,0,0,162,2,0,0,115,4,0,0,0,0,9, + 12,1,114,82,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,2,0,0,0,67, + 0,0,0,115,12,0,0,0,100,1,106,0,124,0,106,1, + 131,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,84,0,0,0,114,10,0,0,0,114,10,0, + 0,0,114,11,0,0,0,114,87,0,0,0,186,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,106,1,124, + 1,131,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,104,0,0,0,41, + 3,114,49,0,0,0,90,10,105,115,95,98,117,105,108,116, + 105,110,114,79,0,0,0,41,4,218,3,99,108,115,114,72, + 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,195,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,3,0,0,0,67,0,0,0,115,30, + 0,0,0,124,0,106,0,124,1,124,2,131,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,146,0,0,0,114,94,0,0, + 0,41,4,114,143,0,0,0,114,72,0,0,0,114,144,0, + 0,0,114,83,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,204,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,106,4,124,1,106,0,131,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, - 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,143,0,0,0,114,72,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, + 41,1,114,15,0,0,0,41,8,114,15,0,0,0,114,14, + 0,0,0,114,70,0,0,0,114,71,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,83,0,0,0,114,10,0,0,0,114,10,0, + 0,0,114,11,0,0,0,114,135,0,0,0,216,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,84,0,0,0,114,10,0,0,0,114,10,0,0, + 0,114,11,0,0,0,114,136,0,0,0,224,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,143,0,0,0,114,72,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,229,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,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,143,0,0, - 0,114,72,0,0,0,114,10,0,0,0,114,10,0,0,0, - 114,11,0,0,0,114,106,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,87,0,0, - 0,218,11,99,108,97,115,115,109,101,116,104,111,100,114,146, - 0,0,0,114,147,0,0,0,114,135,0,0,0,114,136,0, - 0,0,114,75,0,0,0,114,148,0,0,0,114,149,0,0, - 0,114,106,0,0,0,114,85,0,0,0,114,138,0,0,0, - 114,10,0,0,0,114,10,0,0,0,114,10,0,0,0,114, - 11,0,0,0,114,142,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,142,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,2,0,0,0,67,0, - 0,0,115,12,0,0,0,100,1,106,0,124,0,106,1,131, - 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,87,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,106,1,124,1,131, - 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,104,0,0,0,41,3,114,49,0, - 0,0,114,76,0,0,0,114,79,0,0,0,41,4,114,143, - 0,0,0,114,72,0,0,0,114,144,0,0,0,114,145,0, - 0,0,114,10,0,0,0,114,10,0,0,0,114,11,0,0, - 0,114,146,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,2,0,0,0, - 67,0,0,0,115,18,0,0,0,116,0,106,1,124,1,131, - 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, + 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,143,0,0,0,114,72,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,235,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,143,0,0,0,114, + 72,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, + 0,0,0,114,106,0,0,0,241,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,87,0,0,0,218, + 11,99,108,97,115,115,109,101,116,104,111,100,114,146,0,0, + 0,114,147,0,0,0,114,135,0,0,0,114,136,0,0,0, + 114,75,0,0,0,114,148,0,0,0,114,149,0,0,0,114, + 106,0,0,0,114,85,0,0,0,114,138,0,0,0,114,10, + 0,0,0,114,10,0,0,0,114,10,0,0,0,114,11,0, + 0,0,114,142,0,0,0,177,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,142, + 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,2,0,0,0,67,0,0,0, + 115,12,0,0,0,100,1,106,0,124,0,106,1,131,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,87,0,0,0,3,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,106,1,124,1,131,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,104,0,0,0,41,3,114,49,0,0,0, + 114,76,0,0,0,114,79,0,0,0,41,4,114,143,0,0, + 0,114,72,0,0,0,114,144,0,0,0,114,145,0,0,0, + 114,10,0,0,0,114,10,0,0,0,114,11,0,0,0,114, + 146,0,0,0,12,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,2,0,0,0,67,0, + 0,0,115,18,0,0,0,116,0,106,1,124,1,131,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,76,0,0,0,41,3,114,143,0,0,0,114,72, + 0,0,0,114,144,0,0,0,114,10,0,0,0,114,10,0, + 0,0,114,11,0,0,0,114,147,0,0,0,19,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,143,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,28,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, + 106,3,124,1,131,1,115,36,116,4,100,1,106,5,124,1, + 131,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, + 90,0,0,0,114,15,0,0,0,114,49,0,0,0,114,76, + 0,0,0,114,71,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,84,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,136,0,0,0,32,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,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,76,0,0,0,41,3,114,143,0,0,0, - 114,72,0,0,0,114,144,0,0,0,114,10,0,0,0,114, - 10,0,0,0,114,11,0,0,0,114,147,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,143,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,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,106,3,124,1,131,1,115,36,116,4,100,1,106,5, - 124,1,131,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,90,0,0,0,114,15,0,0,0,114,49,0,0,0, - 114,76,0,0,0,114,71,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,84,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,136,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,85,0,0,0,41,2,114,143,0,0,0,114,72, - 0,0,0,114,10,0,0,0,114,10,0,0,0,114,11,0, - 0,0,114,138,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,2,0,0,0,67, - 0,0,0,115,10,0,0,0,116,0,106,1,124,1,131,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,154,0,0,0,41, + 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,85,0,0,0,41,2,114,143,0,0,0,114,72,0,0, + 0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, + 114,138,0,0,0,41,3,0,0,115,2,0,0,0,0,7, + 122,26,70,114,111,122,101,110,73,109,112,111,114,116,101,114, + 46,108,111,97,100,95,109,111,100,117,108,101,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,116,0,106,1,124,1,131,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,154,0,0,0,41,2,114, + 143,0,0,0,114,72,0,0,0,114,10,0,0,0,114,10, + 0,0,0,114,11,0,0,0,114,148,0,0,0,50,3,0, + 0,115,2,0,0,0,0,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,143,0,0,0,114,72,0,0,0,114,10,0,0,0, - 114,10,0,0,0,114,11,0,0,0,114,148,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,143,0,0,0,114,72,0,0,0,114,10,0, - 0,0,114,10,0,0,0,114,11,0,0,0,114,149,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,2,0,0,0,67,0,0,0,115,10,0,0, - 0,116,0,106,1,124,1,131,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,143,0,0,0,114,72, - 0,0,0,114,10,0,0,0,114,10,0,0,0,114,11,0, - 0,0,114,106,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,150,0,0,0,114, - 87,0,0,0,114,151,0,0,0,114,146,0,0,0,114,147, - 0,0,0,114,135,0,0,0,114,136,0,0,0,114,138,0, - 0,0,114,78,0,0,0,114,148,0,0,0,114,149,0,0, - 0,114,106,0,0,0,114,10,0,0,0,114,10,0,0,0, - 114,10,0,0,0,114,11,0,0,0,114,152,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,152,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, + 114,10,0,0,0,114,11,0,0,0,114,149,0,0,0,56, + 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,2,0,0,0,67,0,0,0,115,10,0,0,0,116, + 0,106,1,124,1,131,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,143,0,0,0,114,72,0,0, + 0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, + 114,106,0,0,0,62,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,150,0,0,0,114,87,0, + 0,0,114,151,0,0,0,114,146,0,0,0,114,147,0,0, + 0,114,135,0,0,0,114,136,0,0,0,114,138,0,0,0, + 114,78,0,0,0,114,148,0,0,0,114,149,0,0,0,114, + 106,0,0,0,114,10,0,0,0,114,10,0,0,0,114,10, + 0,0,0,114,11,0,0,0,114,152,0,0,0,250,2,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,152,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,1,0,0,0, + 67,0,0,0,115,12,0,0,0,116,0,106,1,131,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,99,1,0,0,0,0,0,0,0,1,0,0,0,1,0, - 0,0,67,0,0,0,115,12,0,0,0,116,0,106,1,131, - 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,1,0,0,0,67,0,0,0,115,12,0,0,0,116,0, - 106,1,131,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,157,0,0,0,83,3,0,0,115,6,0,0, - 0,8,2,4,2,8,4,114,157,0,0,0,99,3,0,0, - 0,0,0,0,0,5,0,0,0,4,0,0,0,67,0,0, - 0,115,64,0,0,0,124,1,106,0,100,1,124,2,100,2, - 24,0,131,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,106,3,124,4,124,0,131,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,118,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,163,0,0,0,99, - 3,0,0,0,0,0,0,0,4,0,0,0,3,0,0,0, - 67,0,0,0,115,34,0,0,0,124,0,106,0,124,1,124, - 2,131,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,147,0,0,0,114,79,0,0,0,41,4,218,6,102,105, - 110,100,101,114,114,15,0,0,0,114,144,0,0,0,114,94, - 0,0,0,114,10,0,0,0,114,10,0,0,0,114,11,0, - 0,0,218,17,95,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,165,0,0,0,99,3,0,0,0, - 0,0,0,0,10,0,0,0,27,0,0,0,67,0,0,0, - 115,242,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,106,4,100,3,116,5,131,2,1,0,124,0,116,0,106, - 6,107,6,125,4,120,188,124,3,68,0,93,176,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,12,0,114, - 226,124,0,116,0,106,6,107,6,114,226,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,206,1,0,1,0,1,0,124, - 7,83,0,88,0,124,9,100,1,107,8,114,220,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,71,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,80,0,0,0,114,157,0,0, - 0,114,146,0,0,0,114,91,0,0,0,114,165,0,0,0, - 114,90,0,0,0,41,10,114,15,0,0,0,114,144,0,0, - 0,114,145,0,0,0,114,166,0,0,0,90,9,105,115,95, - 114,101,108,111,97,100,114,164,0,0,0,114,146,0,0,0, - 114,83,0,0,0,114,84,0,0,0,114,90,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,16,1,10,1,2,1,10,1,14,4,6, - 2,8,1,4,2,6,2,8,2,114,170,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,110,0,0,0,116,0,124,0,116,1,131,2, - 115,28,116,2,100,1,106,3,116,4,124,0,131,1,131,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,12,0, - 114,106,124,2,100,2,107,2,114,106,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,160,0,0,0,114,71,0,0,0,41, - 3,114,15,0,0,0,114,161,0,0,0,114,162,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,14,1,114,174,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,12,0,0,0,67,0,0,0,115, - 220,0,0,0,100,0,125,2,124,0,106,0,100,1,131,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,106,7,124,0, - 124,3,131,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, - 106,7,124,0,131,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,106,0,100,1, - 131,1,100,5,25,0,124,7,131,3,1,0,124,7,83,0, - 41,6,78,114,118,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,119,0,0,0,114,14,0,0,0,114,80, - 0,0,0,114,59,0,0,0,114,128,0,0,0,114,91,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,170,0,0,0,114,141,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,144,0,0,0,114,120,0,0,0,90, - 13,112,97,114,101,110,116,95,109,111,100,117,108,101,114,139, - 0,0,0,114,83,0,0,0,114,84,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,179,0,0,0,99,2,0, - 0,0,0,0,0,0,4,0,0,0,11,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,106,3,124,0,116,4,131,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,106,6,124,0,131,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,80,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,179,0,0,0,114, - 38,0,0,0,114,177,0,0,0,114,57,0,0,0,41,4, - 114,15,0,0,0,114,178,0,0,0,114,84,0,0,0,114, - 68,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,181,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,174, - 0,0,0,114,163,0,0,0,114,181,0,0,0,218,11,95, - 103,99,100,95,105,109,112,111,114,116,41,3,114,15,0,0, - 0,114,161,0,0,0,114,162,0,0,0,114,10,0,0,0, - 114,10,0,0,0,114,11,0,0,0,114,182,0,0,0,226, - 3,0,0,115,8,0,0,0,0,9,12,1,8,1,12,1, - 114,182,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,17, - 0,0,0,67,0,0,0,115,236,0,0,0,116,0,124,0, - 100,1,131,2,114,232,120,220,124,1,68,0,93,212,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,122,124,3,12,0,114,228,116,0,124,0,100,7,131,2, - 114,228,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,106,8,124,0,106,3,124,4,131,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,226,1,0,125,7,1,0,122,38,124,7, - 106,11,124,6,107,2,114,208,116,12,106,13,106,14,124,6, - 116,15,131,2,100,11,107,9,114,208,119,16,130,0,87,0, - 89,0,100,11,100,11,125,7,126,7,88,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,128,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,183,0,0,0,122,5,123,125,46,123, - 125,78,41,16,114,4,0,0,0,114,171,0,0,0,114,172, - 0,0,0,114,1,0,0,0,114,173,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,185,0,0,0,114,38,0,0,0,114,59, - 0,0,0,114,177,0,0,0,114,15,0,0,0,114,14,0, - 0,0,114,80,0,0,0,114,30,0,0,0,114,180,0,0, - 0,41,8,114,84,0,0,0,218,8,102,114,111,109,108,105, - 115,116,114,178,0,0,0,114,183,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,186,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,16,1,10,1,10,1,10,1,14,1,2, - 1,14,1,16,4,10,1,18,1,2,1,24,1,114,186,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,106,0, - 100,1,131,1,125,1,124,0,106,0,100,2,131,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,106,5, - 100,12,131,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,131,0,0,0,114,90, - 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,128,0,0,0,114,118,0,0,0,114,19,0,0, - 0,41,6,114,30,0,0,0,114,120,0,0,0,114,167,0, - 0,0,114,168,0,0,0,114,169,0,0,0,114,119,0,0, - 0,41,3,218,7,103,108,111,98,97,108,115,114,161,0,0, - 0,114,83,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, - 192,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,106,2,100,3,131,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,106,2,100,3,131,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,118,0,0,0,41,8,114, - 182,0,0,0,114,192,0,0,0,218,9,112,97,114,116,105, - 116,105,111,110,114,159,0,0,0,114,14,0,0,0,114,80, - 0,0,0,114,1,0,0,0,114,186,0,0,0,41,9,114, - 15,0,0,0,114,191,0,0,0,218,6,108,111,99,97,108, - 115,114,187,0,0,0,114,162,0,0,0,114,84,0,0,0, - 90,8,103,108,111,98,97,108,115,95,114,161,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,195,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,106,1,124,0,131,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,142,0,0,0, - 114,146,0,0,0,114,71,0,0,0,114,141,0,0,0,41, - 2,114,15,0,0,0,114,83,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, - 196,0,0,0,99,2,0,0,0,0,0,0,0,12,0,0, - 0,12,0,0,0,67,0,0,0,115,244,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,106,4,131,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,106,8, - 124,3,131,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,5,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,121,12,116,13,100,2,131,1, - 125,10,87,0,110,24,4,0,116,15,107,10,114,206,1,0, - 1,0,1,0,100,3,125,10,89,0,110,2,88,0,116,14, - 124,7,100,2,124,10,131,3,1,0,116,13,100,4,131,1, - 125,11,116,14,124,7,100,4,124,11,131,3,1,0,100,3, - 83,0,41,6,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, - 114,167,0,0,0,114,20,0,0,0,78,114,56,0,0,0, - 41,1,114,167,0,0,0,41,16,114,49,0,0,0,114,14, - 0,0,0,114,13,0,0,0,114,80,0,0,0,218,5,105, - 116,101,109,115,114,171,0,0,0,114,70,0,0,0,114,142, - 0,0,0,114,76,0,0,0,114,152,0,0,0,114,129,0, - 0,0,114,134,0,0,0,114,1,0,0,0,114,196,0,0, - 0,114,5,0,0,0,114,71,0,0,0,41,12,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,84,0,0,0,114,94,0, - 0,0,114,83,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,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,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,50,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,16,3,2,1,12,1,14,2,10,1,12, - 3,8,1,114,200,0,0,0,99,2,0,0,0,0,0,0, - 0,3,0,0,0,3,0,0,0,67,0,0,0,115,66,0, - 0,0,116,0,124,0,124,1,131,2,1,0,116,1,106,2, - 106,3,116,4,131,1,1,0,116,1,106,2,106,3,116,5, - 131,1,1,0,100,1,100,2,108,6,125,2,124,2,97,7, - 124,2,106,8,116,1,106,9,116,10,25,0,131,1,1,0, - 100,2,83,0,41,3,122,50,73,110,115,116,97,108,108,32, - 105,109,112,111,114,116,108,105,98,32,97,115,32,116,104,101, - 32,105,109,112,108,101,109,101,110,116,97,116,105,111,110,32, - 111,102,32,105,109,112,111,114,116,46,114,19,0,0,0,78, - 41,11,114,200,0,0,0,114,14,0,0,0,114,166,0,0, - 0,114,110,0,0,0,114,142,0,0,0,114,152,0,0,0, - 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,116,0,0, - 0,218,8,95,105,110,115,116,97,108,108,114,80,0,0,0, - 114,1,0,0,0,41,3,114,198,0,0,0,114,199,0,0, - 0,114,201,0,0,0,114,10,0,0,0,114,10,0,0,0, - 114,11,0,0,0,114,202,0,0,0,139,4,0,0,115,12, - 0,0,0,0,2,10,2,12,1,12,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,50,114,3,0,0,0,114,116,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,69,0,0,0, - 114,75,0,0,0,114,78,0,0,0,114,85,0,0,0,114, - 96,0,0,0,114,97,0,0,0,114,103,0,0,0,114,79, - 0,0,0,114,129,0,0,0,114,134,0,0,0,114,137,0, - 0,0,114,92,0,0,0,114,81,0,0,0,114,140,0,0, - 0,114,141,0,0,0,114,82,0,0,0,114,142,0,0,0, - 114,152,0,0,0,114,157,0,0,0,114,163,0,0,0,114, - 165,0,0,0,114,170,0,0,0,114,174,0,0,0,90,15, - 95,69,82,82,95,77,83,71,95,80,82,69,70,73,88,114, - 176,0,0,0,114,179,0,0,0,218,6,111,98,106,101,99, - 116,114,180,0,0,0,114,181,0,0,0,114,182,0,0,0, - 114,186,0,0,0,114,192,0,0,0,114,195,0,0,0,114, - 196,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,94,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,18,35,8, - 7,8,47, + 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,75,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,1, + 0,0,0,67,0,0,0,115,12,0,0,0,116,0,106,1, + 131,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,79,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,157,0,0,0,71,3,0,0,115,6,0,0,0,8, + 2,4,2,8,4,114,157,0,0,0,99,3,0,0,0,0, + 0,0,0,5,0,0,0,4,0,0,0,67,0,0,0,115, + 64,0,0,0,124,1,106,0,100,1,124,2,100,2,24,0, + 131,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,106,3,124,4,124,0,131,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,118,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,84,3,0,0,115,10,0,0,0,0,2, + 16,1,12,1,8,1,8,1,114,163,0,0,0,99,3,0, + 0,0,0,0,0,0,4,0,0,0,3,0,0,0,67,0, + 0,0,115,34,0,0,0,124,0,106,0,124,1,124,2,131, + 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,147, + 0,0,0,114,79,0,0,0,41,4,218,6,102,105,110,100, + 101,114,114,15,0,0,0,114,144,0,0,0,114,94,0,0, + 0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, + 218,17,95,102,105,110,100,95,115,112,101,99,95,108,101,103, + 97,99,121,93,3,0,0,115,8,0,0,0,0,3,12,1, + 8,1,4,1,114,165,0,0,0,99,3,0,0,0,0,0, + 0,0,10,0,0,0,27,0,0,0,67,0,0,0,115,242, + 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,106, + 4,100,3,116,5,131,2,1,0,124,0,116,0,106,6,107, + 6,125,4,120,188,124,3,68,0,93,176,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,12,0,114,226,124, + 0,116,0,106,6,107,6,114,226,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,206,1,0,1,0,1,0,124,7,83, + 0,88,0,124,9,100,1,107,8,114,220,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,71,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,80,0,0,0,114,157,0,0,0,114, + 146,0,0,0,114,91,0,0,0,114,165,0,0,0,114,90, + 0,0,0,41,10,114,15,0,0,0,114,144,0,0,0,114, + 145,0,0,0,114,166,0,0,0,90,9,105,115,95,114,101, + 108,111,97,100,114,164,0,0,0,114,146,0,0,0,114,83, + 0,0,0,114,84,0,0,0,114,90,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,102,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,16,1,10,1,2,1,10,1,14,4,6,2,8, + 1,4,2,6,2,8,2,114,170,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,110,0,0,0,116,0,124,0,116,1,131,2,115,28, + 116,2,100,1,106,3,116,4,124,0,131,1,131,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,12,0,114,106, + 124,2,100,2,107,2,114,106,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,160,0,0,0,114,71,0,0,0,41,3,114, + 15,0,0,0,114,161,0,0,0,114,162,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,149,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,14,1,114,174,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,12,0,0,0,67,0,0,0,115,220,0, + 0,0,100,0,125,2,124,0,106,0,100,1,131,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,106,7,124,0,124,3, + 131,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,106,7, + 124,0,131,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,106,0,100,1,131,1, + 100,5,25,0,124,7,131,3,1,0,124,7,83,0,41,6, + 78,114,118,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,119,0,0,0,114,14,0,0,0,114,80,0,0, + 0,114,59,0,0,0,114,128,0,0,0,114,91,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,170,0,0,0,114,141,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,144,0,0,0,114,120,0,0,0,90,13,112, + 97,114,101,110,116,95,109,111,100,117,108,101,114,139,0,0, + 0,114,83,0,0,0,114,84,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,168,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,179,0,0,0,99,2,0,0,0, + 0,0,0,0,4,0,0,0,11,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,106,3,124,0,116,4,131,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,106,6,124,0,131,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,80, + 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,179,0,0,0,114,38,0, + 0,0,114,177,0,0,0,114,57,0,0,0,41,4,114,15, + 0,0,0,114,178,0,0,0,114,84,0,0,0,114,68,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,198,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,181, + 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,174,0,0, + 0,114,163,0,0,0,114,181,0,0,0,218,11,95,103,99, + 100,95,105,109,112,111,114,116,41,3,114,15,0,0,0,114, + 161,0,0,0,114,162,0,0,0,114,10,0,0,0,114,10, + 0,0,0,114,11,0,0,0,114,182,0,0,0,214,3,0, + 0,115,8,0,0,0,0,9,12,1,8,1,12,1,114,182, + 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,17,0,0, + 0,67,0,0,0,115,236,0,0,0,116,0,124,0,100,1, + 131,2,114,232,120,220,124,1,68,0,93,212,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,122, + 124,3,12,0,114,228,116,0,124,0,100,7,131,2,114,228, + 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, + 106,8,124,0,106,3,124,4,131,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,226,1,0,125,7,1,0,122,38,124,7,106,11, + 124,6,107,2,114,208,116,12,106,13,106,14,124,6,116,15, + 131,2,100,11,107,9,114,208,119,16,130,0,87,0,89,0, + 100,11,100,11,125,7,126,7,88,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,128,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,183,0,0,0,122,5,123,125,46,123,125,78, + 41,16,114,4,0,0,0,114,171,0,0,0,114,172,0,0, + 0,114,1,0,0,0,114,173,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,185,0,0,0,114,38,0,0,0,114,59,0,0, + 0,114,177,0,0,0,114,15,0,0,0,114,14,0,0,0, + 114,80,0,0,0,114,30,0,0,0,114,180,0,0,0,41, + 8,114,84,0,0,0,218,8,102,114,111,109,108,105,115,116, + 114,178,0,0,0,114,183,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,186,0,0,0,229,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,16,1,10,1,10,1,10,1,14,1,2,1,14, + 1,16,4,10,1,18,1,2,1,24,1,114,186,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,106,0,100,1, + 131,1,125,1,124,0,106,0,100,2,131,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,106,5,100,12, + 131,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,131,0,0,0,114,90,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,128,0,0,0,114,118,0,0,0,114,19,0,0,0,41, + 6,114,30,0,0,0,114,120,0,0,0,114,167,0,0,0, + 114,168,0,0,0,114,169,0,0,0,114,119,0,0,0,41, + 3,218,7,103,108,111,98,97,108,115,114,161,0,0,0,114, + 83,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,11,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,192,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,106,2,100,3,131,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,106,2,100,3,131,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,118,0,0,0,41,8,114,182,0, + 0,0,114,192,0,0,0,218,9,112,97,114,116,105,116,105, + 111,110,114,159,0,0,0,114,14,0,0,0,114,80,0,0, + 0,114,1,0,0,0,114,186,0,0,0,41,9,114,15,0, + 0,0,114,191,0,0,0,218,6,108,111,99,97,108,115,114, + 187,0,0,0,114,162,0,0,0,114,84,0,0,0,90,8, + 103,108,111,98,97,108,115,95,114,161,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,38,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,195,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,106,1,124,0,131,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,142,0,0,0,114,146, + 0,0,0,114,71,0,0,0,114,141,0,0,0,41,2,114, + 15,0,0,0,114,83,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,73,4,0,0, + 115,8,0,0,0,0,1,10,1,8,1,12,1,114,196,0, + 0,0,99,2,0,0,0,0,0,0,0,12,0,0,0,12, + 0,0,0,67,0,0,0,115,244,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,106,4,131,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,106,8,124,3, + 131,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,5,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,121,12,116,13,100,2,131,1,125,10, + 87,0,110,24,4,0,116,15,107,10,114,206,1,0,1,0, + 1,0,100,3,125,10,89,0,110,2,88,0,116,14,124,7, + 100,2,124,10,131,3,1,0,116,13,100,4,131,1,125,11, + 116,14,124,7,100,4,124,11,131,3,1,0,100,3,83,0, + 41,6,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,114,167, + 0,0,0,114,20,0,0,0,78,114,56,0,0,0,41,1, + 114,167,0,0,0,41,16,114,49,0,0,0,114,14,0,0, + 0,114,13,0,0,0,114,80,0,0,0,218,5,105,116,101, + 109,115,114,171,0,0,0,114,70,0,0,0,114,142,0,0, + 0,114,76,0,0,0,114,152,0,0,0,114,129,0,0,0, + 114,134,0,0,0,114,1,0,0,0,114,196,0,0,0,114, + 5,0,0,0,114,71,0,0,0,41,12,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,84,0,0,0,114,94,0,0,0, + 114,83,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, + 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,114, + 10,0,0,0,114,10,0,0,0,114,11,0,0,0,218,6, + 95,115,101,116,117,112,80,4,0,0,115,50,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,16,3,2,1,12,1,14,2,10,1,12,3,8, + 1,114,200,0,0,0,99,2,0,0,0,0,0,0,0,3, + 0,0,0,3,0,0,0,67,0,0,0,115,66,0,0,0, + 116,0,124,0,124,1,131,2,1,0,116,1,106,2,106,3, + 116,4,131,1,1,0,116,1,106,2,106,3,116,5,131,1, + 1,0,100,1,100,2,108,6,125,2,124,2,97,7,124,2, + 106,8,116,1,106,9,116,10,25,0,131,1,1,0,100,2, + 83,0,41,3,122,50,73,110,115,116,97,108,108,32,105,109, + 112,111,114,116,108,105,98,32,97,115,32,116,104,101,32,105, + 109,112,108,101,109,101,110,116,97,116,105,111,110,32,111,102, + 32,105,109,112,111,114,116,46,114,19,0,0,0,78,41,11, + 114,200,0,0,0,114,14,0,0,0,114,166,0,0,0,114, + 110,0,0,0,114,142,0,0,0,114,152,0,0,0,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,116,0,0,0,218, + 8,95,105,110,115,116,97,108,108,114,80,0,0,0,114,1, + 0,0,0,41,3,114,198,0,0,0,114,199,0,0,0,114, + 201,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, + 0,0,0,114,202,0,0,0,127,4,0,0,115,12,0,0, + 0,0,2,10,2,12,1,12,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,50,114,3,0,0,0,114,116,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,69,0,0,0,114,75, + 0,0,0,114,78,0,0,0,114,85,0,0,0,114,96,0, + 0,0,114,97,0,0,0,114,103,0,0,0,114,79,0,0, + 0,114,129,0,0,0,114,134,0,0,0,114,137,0,0,0, + 114,92,0,0,0,114,81,0,0,0,114,140,0,0,0,114, + 141,0,0,0,114,82,0,0,0,114,142,0,0,0,114,152, + 0,0,0,114,157,0,0,0,114,163,0,0,0,114,165,0, + 0,0,114,170,0,0,0,114,174,0,0,0,90,15,95,69, + 82,82,95,77,83,71,95,80,82,69,70,73,88,114,176,0, + 0,0,114,179,0,0,0,218,6,111,98,106,101,99,116,114, + 180,0,0,0,114,181,0,0,0,114,182,0,0,0,114,186, + 0,0,0,114,192,0,0,0,114,195,0,0,0,114,196,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,94, + 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, + 60,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,18,35,8,7,8, + 47, }; diff --git a/Python/importlib_external.h b/Python/importlib_external.h index a4a20c8efc7c..886aa68009ec 100644 --- a/Python/importlib_external.h +++ b/Python/importlib_external.h @@ -1931,9 +1931,9 @@ const unsigned char _Py_M__importlib_external[] = { 114,14,116,0,106,1,125,2,124,0,106,2,124,1,124,2, 124,3,131,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, + 125,5,124,5,114,86,100,2,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, + 100,1,83,0,110,4,124,4,83,0,100,1,83,0,41,3, 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, @@ -1943,491 +1943,491 @@ const unsigned char _Py_M__importlib_external[] = { 97,116,104,95,104,111,111,107,115,32,97,110,100,32,115,121, 115,46,112,97,116,104,95,105,109,112,111,114,116,101,114,95, 99,97,99,104,101,46,10,32,32,32,32,32,32,32,32,78, - 41,7,114,8,0,0,0,114,37,0,0,0,114,4,1,0, - 0,114,124,0,0,0,114,154,0,0,0,114,156,0,0,0, - 114,227,0,0,0,41,6,114,168,0,0,0,114,123,0,0, - 0,114,37,0,0,0,114,177,0,0,0,114,162,0,0,0, - 114,3,1,0,0,114,4,0,0,0,114,4,0,0,0,114, - 6,0,0,0,114,178,0,0,0,125,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,3, - 0,0,0,67,0,0,0,115,30,0,0,0,124,0,106,0, - 124,1,124,2,131,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,178,0,0,0, - 114,124,0,0,0,41,4,114,168,0,0,0,114,123,0,0, - 0,114,37,0,0,0,114,162,0,0,0,114,4,0,0,0, - 114,4,0,0,0,114,6,0,0,0,114,179,0,0,0,149, - 4,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,109,0,0,0,114,108,0,0,0,114,110, - 0,0,0,114,111,0,0,0,114,180,0,0,0,114,249,0, - 0,0,114,254,0,0,0,114,0,1,0,0,114,1,1,0, - 0,114,4,1,0,0,114,178,0,0,0,114,179,0,0,0, - 114,4,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 6,0,0,0,114,248,0,0,0,31,4,0,0,115,22,0, - 0,0,8,2,4,2,12,8,12,13,12,22,12,15,2,1, - 12,31,2,1,12,23,2,1,114,248,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,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,5,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,106,0,135,0,102, - 1,100,1,100,2,132,8,124,4,68,0,131,1,131,1,1, - 0,113,10,87,0,124,3,124,0,95,1,124,1,112,58,100, - 3,124,0,95,2,100,6,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, - 7,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,4,0,0,0,41,2,114,24,0,0,0,114,222,0,0, - 0,41,1,114,124,0,0,0,114,4,0,0,0,114,6,0, - 0,0,114,224,0,0,0,178,4,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,61,0,0,0,114, - 31,0,0,0,78,114,91,0,0,0,41,7,114,147,0,0, - 0,218,8,95,108,111,97,100,101,114,115,114,37,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,104,0,0,0,114,37,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,164,0,0,0,114,4, - 0,0,0,41,1,114,124,0,0,0,114,6,0,0,0,114, - 182,0,0,0,172,4,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, + 90,9,110,97,109,101,115,112,97,99,101,41,7,114,8,0, + 0,0,114,37,0,0,0,114,4,1,0,0,114,124,0,0, + 0,114,154,0,0,0,114,156,0,0,0,114,227,0,0,0, + 41,6,114,168,0,0,0,114,123,0,0,0,114,37,0,0, + 0,114,177,0,0,0,114,162,0,0,0,114,3,1,0,0, + 114,4,0,0,0,114,4,0,0,0,114,6,0,0,0,114, + 178,0,0,0,125,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,3,0,0,0,67,0, + 0,0,115,30,0,0,0,124,0,106,0,124,1,124,2,131, + 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,178,0,0,0,114,124,0,0,0, + 41,4,114,168,0,0,0,114,123,0,0,0,114,37,0,0, + 0,114,162,0,0,0,114,4,0,0,0,114,4,0,0,0, + 114,6,0,0,0,114,179,0,0,0,149,4,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, + 109,0,0,0,114,108,0,0,0,114,110,0,0,0,114,111, + 0,0,0,114,180,0,0,0,114,249,0,0,0,114,254,0, + 0,0,114,0,1,0,0,114,1,1,0,0,114,4,1,0, + 0,114,178,0,0,0,114,179,0,0,0,114,4,0,0,0, + 114,4,0,0,0,114,4,0,0,0,114,6,0,0,0,114, + 248,0,0,0,31,4,0,0,115,22,0,0,0,8,2,4, + 2,12,8,12,13,12,22,12,15,2,1,12,31,2,1,12, + 23,2,1,114,248,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,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,5,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,106,0,135,0,102,1,100,1,100,2, + 132,8,124,4,68,0,131,1,131,1,1,0,113,10,87,0, + 124,3,124,0,95,1,124,1,112,58,100,3,124,0,95,2, + 100,6,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,7,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,4,0,0,0, + 41,2,114,24,0,0,0,114,222,0,0,0,41,1,114,124, + 0,0,0,114,4,0,0,0,114,6,0,0,0,114,224,0, + 0,0,178,4,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,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,3,124,0, - 95,0,100,2,83,0,41,4,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,31,0,0,0,78,114, - 91,0,0,0,41,1,114,7,1,0,0,41,1,114,104,0, - 0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,0, - 0,114,249,0,0,0,186,4,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,2,0,0,0, - 67,0,0,0,115,42,0,0,0,124,0,106,0,124,1,131, - 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, - 178,0,0,0,114,124,0,0,0,114,154,0,0,0,41,3, - 114,104,0,0,0,114,123,0,0,0,114,162,0,0,0,114, - 4,0,0,0,114,4,0,0,0,114,6,0,0,0,114,121, - 0,0,0,192,4,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,124,0,0,0,114,154,0,0,0,41, - 1,114,165,0,0,0,41,7,114,104,0,0,0,114,163,0, - 0,0,114,123,0,0,0,114,37,0,0,0,90,4,115,109, - 115,108,114,177,0,0,0,114,124,0,0,0,114,4,0,0, - 0,114,4,0,0,0,114,6,0,0,0,114,4,1,0,0, - 204,4,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,15,0,0,0,67,0,0,0,115,98,1,0,0, - 100,1,125,3,124,1,106,0,100,2,131,1,100,3,25,0, - 125,4,121,24,116,1,124,0,106,2,112,34,116,3,106,4, - 131,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,10,125,5,89,0, - 110,2,88,0,124,5,124,0,106,7,107,3,114,92,124,0, - 106,8,131,0,1,0,124,5,124,0,95,7,116,9,131,0, - 114,114,124,0,106,10,125,6,124,4,106,11,131,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,106,16,124,10, - 124,1,124,12,124,8,103,1,124,2,131,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, - 106,16,124,10,124,1,124,12,100,8,124,2,131,5,83,0, - 113,226,87,0,124,3,144,1,114,94,116,18,106,19,100,9, - 124,8,131,2,1,0,116,18,106,20,124,1,100,8,131,2, - 125,13,124,8,103,1,124,13,95,21,124,13,83,0,100,8, - 83,0,41,11,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,61,0,0,0,114,59,0,0,0, - 114,31,0,0,0,114,182,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,114,91, - 0,0,0,41,22,114,34,0,0,0,114,41,0,0,0,114, - 37,0,0,0,114,3,0,0,0,114,47,0,0,0,114,216, - 0,0,0,114,42,0,0,0,114,7,1,0,0,218,11,95, - 102,105,108,108,95,99,97,99,104,101,114,7,0,0,0,114, - 10,1,0,0,114,92,0,0,0,114,9,1,0,0,114,30, - 0,0,0,114,6,1,0,0,114,46,0,0,0,114,4,1, - 0,0,114,48,0,0,0,114,118,0,0,0,114,133,0,0, - 0,114,158,0,0,0,114,154,0,0,0,41,14,114,104,0, - 0,0,114,123,0,0,0,114,177,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,130,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,222,0,0, - 0,114,163,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,162,0,0,0,114,4,0,0,0,114,4,0,0,0,114, - 6,0,0,0,114,178,0,0,0,209,4,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,13,0,0,0,67, - 0,0,0,115,194,0,0,0,124,0,106,0,125,1,121,22, - 116,1,106,2,124,1,112,22,116,1,106,3,131,0,131,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,106,9,100,1,131,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,106,12, - 100,2,131,1,92,3,125,5,125,6,125,7,124,6,114,138, - 100,3,106,13,124,5,124,7,106,14,131,0,131,2,125,8, - 110,4,124,5,125,8,124,3,106,15,124,8,131,1,1,0, - 113,96,87,0,124,3,124,0,95,11,116,7,106,8,106,9, - 116,16,131,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,61,0,0,0,122,5,123,125, - 46,123,125,99,1,0,0,0,0,0,0,0,2,0,0,0, - 3,0,0,0,83,0,0,0,115,20,0,0,0,104,0,124, - 0,93,12,125,1,124,1,106,0,131,0,146,2,113,4,83, - 0,114,4,0,0,0,41,1,114,92,0,0,0,41,2,114, - 24,0,0,0,90,2,102,110,114,4,0,0,0,114,4,0, - 0,0,114,6,0,0,0,250,9,60,115,101,116,99,111,109, - 112,62,30,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,37,0,0,0, - 114,3,0,0,0,90,7,108,105,115,116,100,105,114,114,47, - 0,0,0,114,255,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,8,0, - 0,0,114,9,0,0,0,114,10,0,0,0,114,8,1,0, - 0,114,9,1,0,0,114,87,0,0,0,114,50,0,0,0, - 114,92,0,0,0,218,3,97,100,100,114,11,0,0,0,114, - 10,1,0,0,41,9,114,104,0,0,0,114,37,0,0,0, - 90,8,99,111,110,116,101,110,116,115,90,21,108,111,119,101, - 114,95,115,117,102,102,105,120,95,99,111,110,116,101,110,116, - 115,114,244,0,0,0,114,102,0,0,0,114,234,0,0,0, - 114,222,0,0,0,90,8,110,101,119,95,110,97,109,101,114, - 4,0,0,0,114,4,0,0,0,114,6,0,0,0,114,12, - 1,0,0,1,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,37,0,0, - 0,41,2,114,48,0,0,0,114,103,0,0,0,41,1,114, - 37,0,0,0,41,2,114,168,0,0,0,114,11,1,0,0, - 114,4,0,0,0,114,6,0,0,0,218,24,112,97,116,104, - 95,104,111,111,107,95,102,111,114,95,70,105,108,101,70,105, - 110,100,101,114,42,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,4,0,0,0, - 41,3,114,168,0,0,0,114,11,1,0,0,114,17,1,0, - 0,114,4,0,0,0,41,2,114,168,0,0,0,114,11,1, - 0,0,114,6,0,0,0,218,9,112,97,116,104,95,104,111, - 111,107,32,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,2,0,0,0,67,0,0,0,115,12,0,0,0,100, - 1,106,0,124,0,106,1,131,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,50,0,0,0,114,37,0,0,0,41,1,114,104, - 0,0,0,114,4,0,0,0,114,4,0,0,0,114,6,0, - 0,0,114,243,0,0,0,50,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,109,0,0, - 0,114,108,0,0,0,114,110,0,0,0,114,111,0,0,0, - 114,182,0,0,0,114,249,0,0,0,114,127,0,0,0,114, - 179,0,0,0,114,121,0,0,0,114,4,1,0,0,114,178, - 0,0,0,114,12,1,0,0,114,180,0,0,0,114,18,1, - 0,0,114,243,0,0,0,114,4,0,0,0,114,4,0,0, - 0,114,4,0,0,0,114,6,0,0,0,114,5,1,0,0, - 163,4,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,5,1, - 0,0,99,4,0,0,0,0,0,0,0,6,0,0,0,11, - 0,0,0,67,0,0,0,115,146,0,0,0,124,0,106,0, - 100,1,131,1,125,4,124,0,106,0,100,2,131,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,124,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,124,0,0,0, - 114,220,0,0,0,114,215,0,0,0,114,165,0,0,0,218, - 9,69,120,99,101,112,116,105,111,110,41,6,90,2,110,115, - 114,102,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,124,0,0,0,114, - 162,0,0,0,114,4,0,0,0,114,4,0,0,0,114,6, - 0,0,0,218,14,95,102,105,120,95,117,112,95,109,111,100, - 117,108,101,56,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,23, - 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,106,2,131,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,221,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,215,0,0,0,114,88,0,0,0, - 114,220,0,0,0,114,78,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,4,0,0,0,114, - 4,0,0,0,114,6,0,0,0,114,159,0,0,0,79,5, - 0,0,115,8,0,0,0,0,5,12,1,8,1,8,1,114, - 159,0,0,0,99,1,0,0,0,0,0,0,0,12,0,0, - 0,12,0,0,0,67,0,0,0,115,188,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,26,68,0,93,48, - 125,2,124,2,116,1,106,3,107,7,114,58,116,0,106,5, - 124,2,131,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,5,100,6,103,1,102,2,100,7,100,8,100,6, - 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,9,100,10,132,0,124,6, - 68,0,131,1,131,1,115,142,116,8,130,1,124,6,100,11, - 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, - 106,5,124,5,131,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,12,131,1,130,1, - 116,6,124,1,100,13,124,8,131,3,1,0,116,6,124,1, - 100,14,124,7,131,3,1,0,116,6,124,1,100,15,100,16, - 106,10,124,6,131,1,131,3,1,0,121,14,116,0,106,5, - 100,17,131,1,125,9,87,0,110,26,4,0,116,9,107,10, - 144,1,114,52,1,0,1,0,1,0,100,18,125,9,89,0, - 110,2,88,0,116,6,124,1,100,17,124,9,131,3,1,0, - 116,0,106,5,100,19,131,1,125,10,116,6,124,1,100,19, - 124,10,131,3,1,0,124,5,100,7,107,2,144,1,114,120, - 116,0,106,5,100,20,131,1,125,11,116,6,124,1,100,21, - 124,11,131,3,1,0,116,6,124,1,100,22,116,11,131,0, - 131,3,1,0,116,12,106,13,116,2,106,14,131,0,131,1, - 1,0,124,5,100,7,107,2,144,1,114,184,116,15,106,16, - 100,23,131,1,1,0,100,24,116,12,107,6,144,1,114,184, - 100,25,116,17,95,18,100,18,83,0,41,27,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,114,52,0,0,0, - 114,63,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,31,0,0,0, - 78,41,1,114,33,0,0,0,41,2,114,24,0,0,0,114, - 81,0,0,0,114,4,0,0,0,114,4,0,0,0,114,6, - 0,0,0,114,224,0,0,0,115,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,62, - 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,3,0,0,0,114,27,0,0,0,114,23,0, - 0,0,114,32,0,0,0,90,7,95,116,104,114,101,97,100, - 78,90,8,95,119,101,97,107,114,101,102,90,6,119,105,110, - 114,101,103,114,167,0,0,0,114,7,0,0,0,122,4,46, - 112,121,119,122,6,95,100,46,112,121,100,84,41,4,114,52, - 0,0,0,114,63,0,0,0,114,25,1,0,0,114,140,0, - 0,0,41,19,114,118,0,0,0,114,8,0,0,0,114,143, - 0,0,0,114,236,0,0,0,114,109,0,0,0,90,18,95, - 98,117,105,108,116,105,110,95,102,114,111,109,95,110,97,109, - 101,114,113,0,0,0,218,3,97,108,108,218,14,65,115,115, - 101,114,116,105,111,110,69,114,114,111,114,114,103,0,0,0, - 114,28,0,0,0,114,13,0,0,0,114,226,0,0,0,114, - 147,0,0,0,114,24,1,0,0,114,88,0,0,0,114,161, - 0,0,0,114,166,0,0,0,114,170,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,23,0,0,0,114,27,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,4,0,0,0,114,4,0, - 0,0,114,6,0,0,0,218,6,95,115,101,116,117,112,90, - 5,0,0,115,82,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,2,1,14,1, - 16,2,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,31,1,0,0,99, - 1,0,0,0,0,0,0,0,2,0,0,0,3,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,106,4,116,5,106, - 6,124,1,142,0,103,1,131,1,1,0,116,2,106,7,106, - 8,116,9,131,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,31,1,0,0, - 114,159,0,0,0,114,8,0,0,0,114,253,0,0,0,114, - 147,0,0,0,114,5,1,0,0,114,18,1,0,0,218,9, - 109,101,116,97,95,112,97,116,104,114,161,0,0,0,114,248, - 0,0,0,41,2,114,30,1,0,0,90,17,115,117,112,112, - 111,114,116,101,100,95,108,111,97,100,101,114,115,114,4,0, - 0,0,114,4,0,0,0,114,6,0,0,0,218,8,95,105, - 110,115,116,97,108,108,158,5,0,0,115,8,0,0,0,0, - 2,8,1,6,1,20,1,114,33,1,0,0,41,1,114,0, - 0,0,0,41,2,114,1,0,0,0,114,2,0,0,0,41, - 1,114,49,0,0,0,41,1,78,41,3,78,78,78,41,3, - 78,78,78,41,2,114,62,0,0,0,114,62,0,0,0,41, - 1,78,41,1,78,41,58,114,111,0,0,0,114,12,0,0, - 0,90,37,95,67,65,83,69,95,73,78,83,69,78,83,73, - 84,73,86,69,95,80,76,65,84,70,79,82,77,83,95,66, - 89,84,69,83,95,75,69,89,114,11,0,0,0,114,13,0, - 0,0,114,19,0,0,0,114,21,0,0,0,114,30,0,0, - 0,114,40,0,0,0,114,41,0,0,0,114,45,0,0,0, - 114,46,0,0,0,114,48,0,0,0,114,58,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,17,0,0,0,114,132,0,0,0,114,16, - 0,0,0,114,20,0,0,0,90,17,95,82,65,87,95,77, - 65,71,73,67,95,78,85,77,66,69,82,114,77,0,0,0, - 114,76,0,0,0,114,88,0,0,0,114,78,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,83,0,0,0,114,89,0,0,0,114, - 95,0,0,0,114,99,0,0,0,114,101,0,0,0,114,120, - 0,0,0,114,127,0,0,0,114,139,0,0,0,114,145,0, - 0,0,114,148,0,0,0,114,153,0,0,0,218,6,111,98, - 106,101,99,116,114,160,0,0,0,114,165,0,0,0,114,166, - 0,0,0,114,181,0,0,0,114,191,0,0,0,114,207,0, - 0,0,114,215,0,0,0,114,220,0,0,0,114,226,0,0, - 0,114,221,0,0,0,114,227,0,0,0,114,246,0,0,0, - 114,248,0,0,0,114,5,1,0,0,114,23,1,0,0,114, - 159,0,0,0,114,31,1,0,0,114,33,1,0,0,114,4, - 0,0,0,114,4,0,0,0,114,4,0,0,0,114,6,0, - 0,0,218,8,60,109,111,100,117,108,101,62,8,0,0,0, - 115,108,0,0,0,4,16,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,123,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,10,55,10,12,10,10,8,14,6,3,4,1,14,67,14, - 64,14,29,16,110,14,41,18,45,18,16,4,3,18,53,14, - 60,14,42,14,127,0,5,14,127,0,22,10,23,8,11,8, - 68, + 95,95,46,60,108,111,99,97,108,115,62,46,60,103,101,110, + 101,120,112,114,62,114,61,0,0,0,114,31,0,0,0,78, + 114,91,0,0,0,41,7,114,147,0,0,0,218,8,95,108, + 111,97,100,101,114,115,114,37,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,104,0,0,0,114,37,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,164,0,0,0,114,4,0,0,0,41,1, + 114,124,0,0,0,114,6,0,0,0,114,182,0,0,0,172, + 4,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,3,124,0,95,0,100,2,83, + 0,41,4,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,31,0,0,0,78,114,91,0,0,0,41, + 1,114,7,1,0,0,41,1,114,104,0,0,0,114,4,0, + 0,0,114,4,0,0,0,114,6,0,0,0,114,249,0,0, + 0,186,4,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,2,0,0,0,67,0,0,0,115, + 42,0,0,0,124,0,106,0,124,1,131,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,178,0,0,0,114, + 124,0,0,0,114,154,0,0,0,41,3,114,104,0,0,0, + 114,123,0,0,0,114,162,0,0,0,114,4,0,0,0,114, + 4,0,0,0,114,6,0,0,0,114,121,0,0,0,192,4, + 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,124,0,0,0,114,154,0,0,0,41,1,114,165,0,0, + 0,41,7,114,104,0,0,0,114,163,0,0,0,114,123,0, + 0,0,114,37,0,0,0,90,4,115,109,115,108,114,177,0, + 0,0,114,124,0,0,0,114,4,0,0,0,114,4,0,0, + 0,114,6,0,0,0,114,4,1,0,0,204,4,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,15,0, + 0,0,67,0,0,0,115,98,1,0,0,100,1,125,3,124, + 1,106,0,100,2,131,1,100,3,25,0,125,4,121,24,116, + 1,124,0,106,2,112,34,116,3,106,4,131,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,10,125,5,89,0,110,2,88,0,124, + 5,124,0,106,7,107,3,114,92,124,0,106,8,131,0,1, + 0,124,5,124,0,95,7,116,9,131,0,114,114,124,0,106, + 10,125,6,124,4,106,11,131,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,106,16,124,10,124,1,124,12,124, + 8,103,1,124,2,131,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,106,16,124,10,124, + 1,124,12,100,8,124,2,131,5,83,0,113,226,87,0,124, + 3,144,1,114,94,116,18,106,19,100,9,124,8,131,2,1, + 0,116,18,106,20,124,1,100,8,131,2,125,13,124,8,103, + 1,124,13,95,21,124,13,83,0,100,8,83,0,41,11,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,61,0,0,0,114,59,0,0,0,114,31,0,0,0, + 114,182,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,114,91,0,0,0,41,22, + 114,34,0,0,0,114,41,0,0,0,114,37,0,0,0,114, + 3,0,0,0,114,47,0,0,0,114,216,0,0,0,114,42, + 0,0,0,114,7,1,0,0,218,11,95,102,105,108,108,95, + 99,97,99,104,101,114,7,0,0,0,114,10,1,0,0,114, + 92,0,0,0,114,9,1,0,0,114,30,0,0,0,114,6, + 1,0,0,114,46,0,0,0,114,4,1,0,0,114,48,0, + 0,0,114,118,0,0,0,114,133,0,0,0,114,158,0,0, + 0,114,154,0,0,0,41,14,114,104,0,0,0,114,123,0, + 0,0,114,177,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,130,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,222,0,0,0,114,163,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,162,0,0,0, + 114,4,0,0,0,114,4,0,0,0,114,6,0,0,0,114, + 178,0,0,0,209,4,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,13,0,0,0,67,0,0,0,115,194, + 0,0,0,124,0,106,0,125,1,121,22,116,1,106,2,124, + 1,112,22,116,1,106,3,131,0,131,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,106,9,100,1,131,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,106,12,100,2,131,1,92, + 3,125,5,125,6,125,7,124,6,114,138,100,3,106,13,124, + 5,124,7,106,14,131,0,131,2,125,8,110,4,124,5,125, + 8,124,3,106,15,124,8,131,1,1,0,113,96,87,0,124, + 3,124,0,95,11,116,7,106,8,106,9,116,16,131,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,61,0,0,0,122,5,123,125,46,123,125,99,1, + 0,0,0,0,0,0,0,2,0,0,0,3,0,0,0,83, + 0,0,0,115,20,0,0,0,104,0,124,0,93,12,125,1, + 124,1,106,0,131,0,146,2,113,4,83,0,114,4,0,0, + 0,41,1,114,92,0,0,0,41,2,114,24,0,0,0,90, + 2,102,110,114,4,0,0,0,114,4,0,0,0,114,6,0, + 0,0,250,9,60,115,101,116,99,111,109,112,62,30,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,37,0,0,0,114,3,0,0,0, + 90,7,108,105,115,116,100,105,114,114,47,0,0,0,114,255, + 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,8,0,0,0,114,9,0, + 0,0,114,10,0,0,0,114,8,1,0,0,114,9,1,0, + 0,114,87,0,0,0,114,50,0,0,0,114,92,0,0,0, + 218,3,97,100,100,114,11,0,0,0,114,10,1,0,0,41, + 9,114,104,0,0,0,114,37,0,0,0,90,8,99,111,110, + 116,101,110,116,115,90,21,108,111,119,101,114,95,115,117,102, + 102,105,120,95,99,111,110,116,101,110,116,115,114,244,0,0, + 0,114,102,0,0,0,114,234,0,0,0,114,222,0,0,0, + 90,8,110,101,119,95,110,97,109,101,114,4,0,0,0,114, + 4,0,0,0,114,6,0,0,0,114,12,1,0,0,1,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,37,0,0,0,41,2,114,48, + 0,0,0,114,103,0,0,0,41,1,114,37,0,0,0,41, + 2,114,168,0,0,0,114,11,1,0,0,114,4,0,0,0, + 114,6,0,0,0,218,24,112,97,116,104,95,104,111,111,107, + 95,102,111,114,95,70,105,108,101,70,105,110,100,101,114,42, + 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,4,0,0,0,41,3,114,168,0, + 0,0,114,11,1,0,0,114,17,1,0,0,114,4,0,0, + 0,41,2,114,168,0,0,0,114,11,1,0,0,114,6,0, + 0,0,218,9,112,97,116,104,95,104,111,111,107,32,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,2,0,0, + 0,67,0,0,0,115,12,0,0,0,100,1,106,0,124,0, + 106,1,131,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,50,0, + 0,0,114,37,0,0,0,41,1,114,104,0,0,0,114,4, + 0,0,0,114,4,0,0,0,114,6,0,0,0,114,243,0, + 0,0,50,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,109,0,0,0,114,108,0,0, + 0,114,110,0,0,0,114,111,0,0,0,114,182,0,0,0, + 114,249,0,0,0,114,127,0,0,0,114,179,0,0,0,114, + 121,0,0,0,114,4,1,0,0,114,178,0,0,0,114,12, + 1,0,0,114,180,0,0,0,114,18,1,0,0,114,243,0, + 0,0,114,4,0,0,0,114,4,0,0,0,114,4,0,0, + 0,114,6,0,0,0,114,5,1,0,0,163,4,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,5,1,0,0,99,4,0, + 0,0,0,0,0,0,6,0,0,0,11,0,0,0,67,0, + 0,0,115,146,0,0,0,124,0,106,0,100,1,131,1,125, + 4,124,0,106,0,100,2,131,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,124,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,124,0,0,0,114,220,0,0,0, + 114,215,0,0,0,114,165,0,0,0,218,9,69,120,99,101, + 112,116,105,111,110,41,6,90,2,110,115,114,102,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,124,0,0,0,114,162,0,0,0,114, + 4,0,0,0,114,4,0,0,0,114,6,0,0,0,218,14, + 95,102,105,120,95,117,112,95,109,111,100,117,108,101,56,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,23,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,106,2,131,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,221,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,215,0,0,0,114,88,0,0,0,114,220,0,0,0, + 114,78,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,4,0,0,0,114,4,0,0,0,114, + 6,0,0,0,114,159,0,0,0,79,5,0,0,115,8,0, + 0,0,0,5,12,1,8,1,8,1,114,159,0,0,0,99, + 1,0,0,0,0,0,0,0,12,0,0,0,12,0,0,0, + 67,0,0,0,115,188,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,26,68,0,93,48,125,2,124,2,116, + 1,106,3,107,7,114,58,116,0,106,5,124,2,131,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,5,100, + 6,103,1,102,2,100,7,100,8,100,6,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,9,100,10,132,0,124,6,68,0,131,1,131, + 1,115,142,116,8,130,1,124,6,100,11,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,106,5,124,5,131, + 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,12,131,1,130,1,116,6,124,1,100, + 13,124,8,131,3,1,0,116,6,124,1,100,14,124,7,131, + 3,1,0,116,6,124,1,100,15,100,16,106,10,124,6,131, + 1,131,3,1,0,121,14,116,0,106,5,100,17,131,1,125, + 9,87,0,110,26,4,0,116,9,107,10,144,1,114,52,1, + 0,1,0,1,0,100,18,125,9,89,0,110,2,88,0,116, + 6,124,1,100,17,124,9,131,3,1,0,116,0,106,5,100, + 19,131,1,125,10,116,6,124,1,100,19,124,10,131,3,1, + 0,124,5,100,7,107,2,144,1,114,120,116,0,106,5,100, + 20,131,1,125,11,116,6,124,1,100,21,124,11,131,3,1, + 0,116,6,124,1,100,22,116,11,131,0,131,3,1,0,116, + 12,106,13,116,2,106,14,131,0,131,1,1,0,124,5,100, + 7,107,2,144,1,114,184,116,15,106,16,100,23,131,1,1, + 0,100,24,116,12,107,6,144,1,114,184,100,25,116,17,95, + 18,100,18,83,0,41,27,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,114,52,0,0,0,114,63,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,31,0,0,0,78,41,1,114,33, + 0,0,0,41,2,114,24,0,0,0,114,81,0,0,0,114, + 4,0,0,0,114,4,0,0,0,114,6,0,0,0,114,224, + 0,0,0,115,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,62,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,3, + 0,0,0,114,27,0,0,0,114,23,0,0,0,114,32,0, + 0,0,90,7,95,116,104,114,101,97,100,78,90,8,95,119, + 101,97,107,114,101,102,90,6,119,105,110,114,101,103,114,167, + 0,0,0,114,7,0,0,0,122,4,46,112,121,119,122,6, + 95,100,46,112,121,100,84,41,4,114,52,0,0,0,114,63, + 0,0,0,114,25,1,0,0,114,140,0,0,0,41,19,114, + 118,0,0,0,114,8,0,0,0,114,143,0,0,0,114,236, + 0,0,0,114,109,0,0,0,90,18,95,98,117,105,108,116, + 105,110,95,102,114,111,109,95,110,97,109,101,114,113,0,0, + 0,218,3,97,108,108,218,14,65,115,115,101,114,116,105,111, + 110,69,114,114,111,114,114,103,0,0,0,114,28,0,0,0, + 114,13,0,0,0,114,226,0,0,0,114,147,0,0,0,114, + 24,1,0,0,114,88,0,0,0,114,161,0,0,0,114,166, + 0,0,0,114,170,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,23,0,0,0,114,27,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,4,0,0,0,114,4,0,0,0,114,6,0, + 0,0,218,6,95,115,101,116,117,112,90,5,0,0,115,82, + 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,2,1,14,1,16,2,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,31,1,0,0,99,1,0,0,0,0, + 0,0,0,2,0,0,0,3,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,106,4,116,5,106,6,124,1,142,0, + 103,1,131,1,1,0,116,2,106,7,106,8,116,9,131,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,31,1,0,0,114,159,0,0,0, + 114,8,0,0,0,114,253,0,0,0,114,147,0,0,0,114, + 5,1,0,0,114,18,1,0,0,218,9,109,101,116,97,95, + 112,97,116,104,114,161,0,0,0,114,248,0,0,0,41,2, + 114,30,1,0,0,90,17,115,117,112,112,111,114,116,101,100, + 95,108,111,97,100,101,114,115,114,4,0,0,0,114,4,0, + 0,0,114,6,0,0,0,218,8,95,105,110,115,116,97,108, + 108,158,5,0,0,115,8,0,0,0,0,2,8,1,6,1, + 20,1,114,33,1,0,0,41,1,114,0,0,0,0,41,2, + 114,1,0,0,0,114,2,0,0,0,41,1,114,49,0,0, + 0,41,1,78,41,3,78,78,78,41,3,78,78,78,41,2, + 114,62,0,0,0,114,62,0,0,0,41,1,78,41,1,78, + 41,58,114,111,0,0,0,114,12,0,0,0,90,37,95,67, + 65,83,69,95,73,78,83,69,78,83,73,84,73,86,69,95, + 80,76,65,84,70,79,82,77,83,95,66,89,84,69,83,95, + 75,69,89,114,11,0,0,0,114,13,0,0,0,114,19,0, + 0,0,114,21,0,0,0,114,30,0,0,0,114,40,0,0, + 0,114,41,0,0,0,114,45,0,0,0,114,46,0,0,0, + 114,48,0,0,0,114,58,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, + 17,0,0,0,114,132,0,0,0,114,16,0,0,0,114,20, + 0,0,0,90,17,95,82,65,87,95,77,65,71,73,67,95, + 78,85,77,66,69,82,114,77,0,0,0,114,76,0,0,0, + 114,88,0,0,0,114,78,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,83,0,0,0,114,89,0,0,0,114,95,0,0,0,114, + 99,0,0,0,114,101,0,0,0,114,120,0,0,0,114,127, + 0,0,0,114,139,0,0,0,114,145,0,0,0,114,148,0, + 0,0,114,153,0,0,0,218,6,111,98,106,101,99,116,114, + 160,0,0,0,114,165,0,0,0,114,166,0,0,0,114,181, + 0,0,0,114,191,0,0,0,114,207,0,0,0,114,215,0, + 0,0,114,220,0,0,0,114,226,0,0,0,114,221,0,0, + 0,114,227,0,0,0,114,246,0,0,0,114,248,0,0,0, + 114,5,1,0,0,114,23,1,0,0,114,159,0,0,0,114, + 31,1,0,0,114,33,1,0,0,114,4,0,0,0,114,4, + 0,0,0,114,4,0,0,0,114,6,0,0,0,218,8,60, + 109,111,100,117,108,101,62,8,0,0,0,115,108,0,0,0, + 4,16,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,123, + 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,10,55,10,12, + 10,10,8,14,6,3,4,1,14,67,14,64,14,29,16,110, + 14,41,18,45,18,16,4,3,18,53,14,60,14,42,14,127, + 0,5,14,127,0,22,10,23,8,11,8,68, }; From webhook-mailer at python.org Mon Feb 26 15:24:22 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Mon, 26 Feb 2018 20:24:22 -0000 Subject: [Python-checkins] Fix _socket module compilation on Cygwin. (GH-4137) (GH-4145) Message-ID: https://github.com/python/cpython/commit/e650fd362ee7753ca906e1d92121a165ce45ecb6 commit: e650fd362ee7753ca906e1d92121a165ce45ecb6 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Serhiy Storchaka date: 2018-02-26T22:24:18+02:00 summary: Fix _socket module compilation on Cygwin. (GH-4137) (GH-4145) (cherry picked from commit 63ae04461fb0cc93ca57cd151103a8dd295581d6) files: M Modules/socketmodule.c diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index b455021c2fd4..36920f7f8633 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -240,7 +240,7 @@ if_indextoname(index) -- return the corresponding interface name\n\ # include #endif -#if defined(__APPLE__) || defined(__NetBSD__) +#if defined(__APPLE__) || defined(__CYGWIN__) || defined(__NetBSD__) # include #endif From webhook-mailer at python.org Mon Feb 26 15:35:48 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Mon, 26 Feb 2018 20:35:48 -0000 Subject: [Python-checkins] bpo-32147: Improved perfomance of binascii.unhexlify(). (GH-4586) Message-ID: https://github.com/python/cpython/commit/6b5df906afe113dbe421d044322254cfd4747c9c commit: 6b5df906afe113dbe421d044322254cfd4747c9c branch: master author: Sergey Fedoseev committer: Serhiy Storchaka date: 2018-02-26T22:35:41+02:00 summary: bpo-32147: Improved perfomance of binascii.unhexlify(). (GH-4586) files: A Misc/NEWS.d/next/Library/2017-11-28-10-23-13.bpo-32147.PI2k1Y.rst M Lib/test/test_binascii.py M Misc/ACKS M Modules/binascii.c diff --git a/Lib/test/test_binascii.py b/Lib/test/test_binascii.py index 8fa57cdf1b0b..0997d9432bf6 100644 --- a/Lib/test/test_binascii.py +++ b/Lib/test/test_binascii.py @@ -198,6 +198,11 @@ def test_hex(self): self.assertEqual(s, u) self.assertRaises(binascii.Error, binascii.a2b_hex, t[:-1]) self.assertRaises(binascii.Error, binascii.a2b_hex, t[:-1] + b'q') + self.assertRaises(binascii.Error, binascii.a2b_hex, bytes([255, 255])) + self.assertRaises(binascii.Error, binascii.a2b_hex, b'0G') + self.assertRaises(binascii.Error, binascii.a2b_hex, b'0g') + self.assertRaises(binascii.Error, binascii.a2b_hex, b'G0') + self.assertRaises(binascii.Error, binascii.a2b_hex, b'g0') # Confirm that b2a_hex == hexlify and a2b_hex == unhexlify self.assertEqual(binascii.hexlify(self.type2test(s)), t) diff --git a/Misc/ACKS b/Misc/ACKS index dee022f2ff0a..e2addfc210b7 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -460,6 +460,7 @@ Michael Farrell Troy J. Farrell Jim Fasarakis-Hilliard Mark Favas +Sergey Fedoseev Boris Feld Thomas Fenzl Niels Ferguson diff --git a/Misc/NEWS.d/next/Library/2017-11-28-10-23-13.bpo-32147.PI2k1Y.rst b/Misc/NEWS.d/next/Library/2017-11-28-10-23-13.bpo-32147.PI2k1Y.rst new file mode 100644 index 000000000000..e02a97c5e9e6 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-11-28-10-23-13.bpo-32147.PI2k1Y.rst @@ -0,0 +1,2 @@ +:func:`binascii.unhexlify` is now up to 2 times faster. +Patch by Sergey Fedoseev. diff --git a/Modules/binascii.c b/Modules/binascii.c index 1af6b7f98f25..59e99282ae35 100644 --- a/Modules/binascii.c +++ b/Modules/binascii.c @@ -1130,21 +1130,6 @@ binascii_hexlify_impl(PyObject *module, Py_buffer *data) return _Py_strhex_bytes((const char *)data->buf, data->len); } -static int -to_int(int c) -{ - if (Py_ISDIGIT(c)) - return c - '0'; - else { - if (Py_ISUPPER(c)) - c = Py_TOLOWER(c); - if (c >= 'a' && c <= 'f') - return c - 'a' + 10; - } - return -1; -} - - /*[clinic input] binascii.a2b_hex @@ -1187,9 +1172,9 @@ binascii_a2b_hex_impl(PyObject *module, Py_buffer *hexstr) retbuf = PyBytes_AS_STRING(retval); for (i=j=0; i < arglen; i += 2) { - int top = to_int(Py_CHARMASK(argbuf[i])); - int bot = to_int(Py_CHARMASK(argbuf[i+1])); - if (top == -1 || bot == -1) { + unsigned int top = _PyLong_DigitValue[Py_CHARMASK(argbuf[i])]; + unsigned int bot = _PyLong_DigitValue[Py_CHARMASK(argbuf[i+1])]; + if (top >= 16 || bot >= 16) { PyErr_SetString(Error, "Non-hexadecimal digit found"); goto finally; @@ -1218,19 +1203,6 @@ binascii_unhexlify_impl(PyObject *module, Py_buffer *hexstr) return binascii_a2b_hex_impl(module, hexstr); } -static const int table_hex[128] = { - -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, - -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, - -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1, -1,-1,-1,-1, - -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1, - -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, - -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1, - -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1 -}; - -#define hexval(c) table_hex[(unsigned int)(c)] - #define MAXLINESIZE 76 @@ -1293,9 +1265,9 @@ binascii_a2b_qp_impl(PyObject *module, Py_buffer *data, int header) (ascii_data[in+1] >= 'a' && ascii_data[in+1] <= 'f') || (ascii_data[in+1] >= '0' && ascii_data[in+1] <= '9'))) { /* hexval */ - ch = hexval(ascii_data[in]) << 4; + ch = _PyLong_DigitValue[ascii_data[in]] << 4; in++; - ch |= hexval(ascii_data[in]); + ch |= _PyLong_DigitValue[ascii_data[in]]; in++; odata[out++] = ch; } From webhook-mailer at python.org Mon Feb 26 16:31:28 2018 From: webhook-mailer at python.org (Nick Coghlan) Date: Mon, 26 Feb 2018 21:31:28 -0000 Subject: [Python-checkins] bpo-32836: Remove obsolete code from symtable pass (GH-5680) Message-ID: https://github.com/python/cpython/commit/3a087beddd9f0955eb9080a6fd1499ff89ca74bf commit: 3a087beddd9f0955eb9080a6fd1499ff89ca74bf branch: master author: Nitish Chandra committer: Nick Coghlan date: 2018-02-27T07:31:20+10:00 summary: bpo-32836: Remove obsolete code from symtable pass (GH-5680) When comprehensions switched to using a nested scope, the old code for generating a temporary name to hold the accumulation target became redundant, but was never actually removed. Patch by Nitish Chandra. files: A Misc/NEWS.d/next/Core and Builtins/2018-02-14-12-35-47.bpo-32836.bThJnx.rst M Include/symtable.h M Python/symtable.c diff --git a/Include/symtable.h b/Include/symtable.h index 86ae3c28e878..007f88db40e7 100644 --- a/Include/symtable.h +++ b/Include/symtable.h @@ -60,7 +60,6 @@ typedef struct _symtable_entry { int ste_col_offset; /* offset of first line of block */ int ste_opt_lineno; /* lineno of last exec or import * */ int ste_opt_col_offset; /* offset of last exec or import * */ - int ste_tmpname; /* counter for listcomp temp vars */ struct symtable *ste_table; } PySTEntryObject; diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-02-14-12-35-47.bpo-32836.bThJnx.rst b/Misc/NEWS.d/next/Core and Builtins/2018-02-14-12-35-47.bpo-32836.bThJnx.rst new file mode 100644 index 000000000000..4eeb9aa2e52c --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-02-14-12-35-47.bpo-32836.bThJnx.rst @@ -0,0 +1 @@ +Don't use temporary variables in cases of list/dict/set comprehensions diff --git a/Python/symtable.c b/Python/symtable.c index ac14058fefd2..3e8c6f5dae30 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -69,7 +69,6 @@ ste_new(struct symtable *st, identifier name, _Py_block_ty block, ste->ste_varkeywords = 0; ste->ste_opt_lineno = 0; ste->ste_opt_col_offset = 0; - ste->ste_tmpname = 0; ste->ste_lineno = lineno; ste->ste_col_offset = col_offset; @@ -1082,24 +1081,6 @@ symtable_add_def(struct symtable *st, PyObject *name, int flag) } \ } -static int -symtable_new_tmpname(struct symtable *st) -{ - char tmpname[256]; - identifier tmp; - - PyOS_snprintf(tmpname, sizeof(tmpname), "_[%d]", - ++st->st_cur->ste_tmpname); - tmp = PyUnicode_InternFromString(tmpname); - if (!tmp) - return 0; - if (!symtable_add_def(st, tmp, DEF_LOCAL)) - return 0; - Py_DECREF(tmp); - return 1; -} - - static int symtable_record_directive(struct symtable *st, identifier name, stmt_ty s) { @@ -1723,7 +1704,6 @@ symtable_handle_comprehension(struct symtable *st, expr_ty e, expr_ty elt, expr_ty value) { int is_generator = (e->kind == GeneratorExp_kind); - int needs_tmp = !is_generator; comprehension_ty outermost = ((comprehension_ty) asdl_seq_GET(generators, 0)); /* Outermost iterator is evaluated in current scope */ @@ -1742,11 +1722,6 @@ symtable_handle_comprehension(struct symtable *st, expr_ty e, symtable_exit_block(st, (void *)e); return 0; } - /* Allocate temporary name if needed */ - if (needs_tmp && !symtable_new_tmpname(st)) { - symtable_exit_block(st, (void *)e); - return 0; - } VISIT(st, expr, outermost->target); VISIT_SEQ(st, expr, outermost->ifs); VISIT_SEQ_TAIL(st, comprehension, generators, 1); From webhook-mailer at python.org Mon Feb 26 17:35:22 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Mon, 26 Feb 2018 22:35:22 -0000 Subject: [Python-checkins] bpo-18533: Avoid RuntimeError from repr() of recursive dictview (#4823) (#5357) Message-ID: https://github.com/python/cpython/commit/c20c97f6122e7a99e46cbd6c9ac8cb2941a3bf7a commit: c20c97f6122e7a99e46cbd6c9ac8cb2941a3bf7a branch: 2.7 author: bennorth committer: Serhiy Storchaka date: 2018-02-27T00:35:03+02:00 summary: bpo-18533: Avoid RuntimeError from repr() of recursive dictview (#4823) (#5357) (cherry picked from commit d7773d92bd11640a8c950d6c36a9cef1cee36f96) files: A Misc/NEWS.d/next/Core and Builtins/2017-12-13-16-46-23.bpo-18533.Dlk8d7.rst M Lib/test/test_dictviews.py M Lib/test/test_ordered_dict.py M Objects/dictobject.c diff --git a/Lib/test/test_dictviews.py b/Lib/test/test_dictviews.py index b585bdd90203..1edeec55d077 100644 --- a/Lib/test/test_dictviews.py +++ b/Lib/test/test_dictviews.py @@ -1,5 +1,6 @@ import copy import pickle +import sys import unittest import collections from test import test_support @@ -169,6 +170,20 @@ def test_items_set_operations(self): def test_recursive_repr(self): d = {} d[42] = d.viewvalues() + r = repr(d) + # Cannot perform a stronger test, as the contents of the repr + # are implementation-dependent. All we can say is that we + # want a str result, not an exception of any sort. + self.assertIsInstance(r, str) + d[42] = d.viewitems() + r = repr(d) + # Again. + self.assertIsInstance(r, str) + + def test_deeply_nested_repr(self): + d = {} + for i in range(sys.getrecursionlimit() + 100): + d = {42: d.viewvalues()} self.assertRaises(RuntimeError, repr, d) def test_abc_registry(self): diff --git a/Lib/test/test_ordered_dict.py b/Lib/test/test_ordered_dict.py index 85e4841fbb4b..17326c5190c6 100644 --- a/Lib/test/test_ordered_dict.py +++ b/Lib/test/test_ordered_dict.py @@ -220,6 +220,19 @@ def test_repr_recursive(self): self.assertEqual(repr(od), "OrderedDict([('a', None), ('b', None), ('c', None), ('x', ...)])") + def test_repr_recursive_values(self): + od = OrderedDict() + od[42] = od.viewvalues() + r = repr(od) + # Cannot perform a stronger test, as the contents of the repr + # are implementation-dependent. All we can say is that we + # want a str result, not an exception of any sort. + self.assertIsInstance(r, str) + od[42] = od.viewitems() + r = repr(od) + # Again. + self.assertIsInstance(r, str) + def test_setdefault(self): pairs = [('c', 1), ('b', 2), ('a', 3), ('d', 4), ('e', 5), ('f', 6)] shuffle(pairs) diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-12-13-16-46-23.bpo-18533.Dlk8d7.rst b/Misc/NEWS.d/next/Core and Builtins/2017-12-13-16-46-23.bpo-18533.Dlk8d7.rst new file mode 100644 index 000000000000..2ffd5718d6ac --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2017-12-13-16-46-23.bpo-18533.Dlk8d7.rst @@ -0,0 +1,3 @@ +``repr()`` on a dict containing its own ``viewvalues()`` or +``viewitems()`` no longer raises ``RuntimeError``. Instead, use +``...``, as for other recursive structures. Patch by Ben North. diff --git a/Objects/dictobject.c b/Objects/dictobject.c index a792b2dfa210..c544ecd8c2d2 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -3005,21 +3005,29 @@ dictview_repr(dictviewobject *dv) { PyObject *seq; PyObject *seq_str; - PyObject *result; + PyObject *result = NULL; + Py_ssize_t rc; + rc = Py_ReprEnter((PyObject *)dv); + if (rc != 0) { + return rc > 0 ? PyString_FromString("...") : NULL; + } seq = PySequence_List((PyObject *)dv); - if (seq == NULL) - return NULL; - + if (seq == NULL) { + goto Done; + } seq_str = PyObject_Repr(seq); + Py_DECREF(seq); + if (seq_str == NULL) { - Py_DECREF(seq); - return NULL; + goto Done; } result = PyString_FromFormat("%s(%s)", Py_TYPE(dv)->tp_name, PyString_AS_STRING(seq_str)); Py_DECREF(seq_str); - Py_DECREF(seq); + +Done: + Py_ReprLeave((PyObject *)dv); return result; } From webhook-mailer at python.org Mon Feb 26 17:48:17 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Mon, 26 Feb 2018 22:48:17 -0000 Subject: [Python-checkins] bpo-32222: Fix pygettext skipping docstrings for funcs with arg typehints (GH-4745) Message-ID: https://github.com/python/cpython/commit/eee72d4778a5513038edd5236cdd87ccce2bc60a commit: eee72d4778a5513038edd5236cdd87ccce2bc60a branch: master author: Tobotimus committer: Serhiy Storchaka date: 2018-02-27T00:48:14+02:00 summary: bpo-32222: Fix pygettext skipping docstrings for funcs with arg typehints (GH-4745) files: A Misc/NEWS.d/next/Tools-Demos/2017-12-07-20-51-20.bpo-32222.hPBcGT.rst M Lib/test/test_tools/test_i18n.py M Tools/i18n/pygettext.py diff --git a/Lib/test/test_tools/test_i18n.py b/Lib/test/test_tools/test_i18n.py index 5c28baea7241..3c8be27a57b4 100644 --- a/Lib/test/test_tools/test_i18n.py +++ b/Lib/test/test_tools/test_i18n.py @@ -3,6 +3,7 @@ import os import sys import unittest +import textwrap from test.support.script_helper import assert_python_ok from test.test_tools import skip_if_missing, toolsdir @@ -28,6 +29,41 @@ def get_header(self, data): headers[key] = val.strip() return headers + def get_msgids(self, data): + """ utility: return all msgids in .po file as a list of strings """ + msgids = [] + reading_msgid = False + cur_msgid = [] + for line in data.split('\n'): + if reading_msgid: + if line.startswith('"'): + cur_msgid.append(line.strip('"')) + else: + msgids.append('\n'.join(cur_msgid)) + cur_msgid = [] + reading_msgid = False + continue + if line.startswith('msgid '): + line = line[len('msgid '):] + cur_msgid.append(line.strip('"')) + reading_msgid = True + else: + if reading_msgid: + msgids.append('\n'.join(cur_msgid)) + + return msgids + + def extract_docstrings_from_str(self, module_content): + """ utility: return all msgids extracted from module_content """ + filename = 'test_docstrings.py' + with temp_cwd(None) as cwd: + with open(filename, 'w') as fp: + fp.write(module_content) + assert_python_ok(self.script, '-D', filename) + with open('messages.pot') as fp: + data = fp.read() + return self.get_msgids(data) + def test_header(self): """Make sure the required fields are in the header, according to: http://www.gnu.org/software/gettext/manual/gettext.html#Header-Entry @@ -72,3 +108,55 @@ def test_POT_Creation_Date(self): # This will raise if the date format does not exactly match. datetime.strptime(creationDate, '%Y-%m-%d %H:%M%z') + + def test_funcdocstring_annotated_args(self): + """ Test docstrings for functions with annotated args """ + msgids = self.extract_docstrings_from_str(textwrap.dedent('''\ + def foo(bar: str): + """doc""" + ''')) + self.assertIn('doc', msgids) + + def test_funcdocstring_annotated_return(self): + """ Test docstrings for functions with annotated return type """ + msgids = self.extract_docstrings_from_str(textwrap.dedent('''\ + def foo(bar) -> str: + """doc""" + ''')) + self.assertIn('doc', msgids) + + def test_funcdocstring_defvalue_args(self): + """ Test docstring for functions with default arg values """ + msgids = self.extract_docstrings_from_str(textwrap.dedent('''\ + def foo(bar=()): + """doc""" + ''')) + self.assertIn('doc', msgids) + + def test_funcdocstring_multiple_funcs(self): + """ Test docstring extraction for multiple functions combining + annotated args, annotated return types and default arg values + """ + msgids = self.extract_docstrings_from_str(textwrap.dedent('''\ + def foo1(bar: tuple=()) -> str: + """doc1""" + + def foo2(bar: List[1:2]) -> (lambda x: x): + """doc2""" + + def foo3(bar: 'func'=lambda x: x) -> {1: 2}: + """doc3""" + ''')) + self.assertIn('doc1', msgids) + self.assertIn('doc2', msgids) + self.assertIn('doc3', msgids) + + def test_classdocstring_early_colon(self): + """ Test docstring extraction for a class with colons occuring within + the parentheses. + """ + msgids = self.extract_docstrings_from_str(textwrap.dedent('''\ + class D(L[1:2], F({1: 2}), metaclass=M(lambda x: x)): + """doc""" + ''')) + self.assertIn('doc', msgids) diff --git a/Misc/NEWS.d/next/Tools-Demos/2017-12-07-20-51-20.bpo-32222.hPBcGT.rst b/Misc/NEWS.d/next/Tools-Demos/2017-12-07-20-51-20.bpo-32222.hPBcGT.rst new file mode 100644 index 000000000000..b0b4c5e9357c --- /dev/null +++ b/Misc/NEWS.d/next/Tools-Demos/2017-12-07-20-51-20.bpo-32222.hPBcGT.rst @@ -0,0 +1,3 @@ +Fix pygettext not extracting docstrings for functions with type annotated +arguments. +Patch by Toby Harradine. diff --git a/Tools/i18n/pygettext.py b/Tools/i18n/pygettext.py index 8ef5ff8a3e72..0f0395a4fcab 100755 --- a/Tools/i18n/pygettext.py +++ b/Tools/i18n/pygettext.py @@ -320,6 +320,7 @@ def __init__(self, options): self.__lineno = -1 self.__freshmodule = 1 self.__curfile = None + self.__enclosurecount = 0 def __call__(self, ttype, tstring, stup, etup, line): # dispatch @@ -340,7 +341,7 @@ def __waiting(self, ttype, tstring, lineno): elif ttype not in (tokenize.COMMENT, tokenize.NL): self.__freshmodule = 0 return - # class docstring? + # class or func/method docstring? if ttype == tokenize.NAME and tstring in ('class', 'def'): self.__state = self.__suiteseen return @@ -348,9 +349,15 @@ def __waiting(self, ttype, tstring, lineno): self.__state = self.__keywordseen def __suiteseen(self, ttype, tstring, lineno): - # ignore anything until we see the colon - if ttype == tokenize.OP and tstring == ':': - self.__state = self.__suitedocstring + # skip over any enclosure pairs until we see the colon + if ttype == tokenize.OP: + if tstring == ':' and self.__enclosurecount == 0: + # we see a colon and we're not in an enclosure: end of def + self.__state = self.__suitedocstring + elif tstring in '([{': + self.__enclosurecount += 1 + elif tstring in ')]}': + self.__enclosurecount -= 1 def __suitedocstring(self, ttype, tstring, lineno): # ignore any intervening noise From webhook-mailer at python.org Mon Feb 26 18:23:30 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Mon, 26 Feb 2018 23:23:30 -0000 Subject: [Python-checkins] bpo-32222: Fix pygettext skipping docstrings for funcs with arg typehints (GH-4745) Message-ID: https://github.com/python/cpython/commit/51d95ffc2fb3337dc87277c9af25ecc9a01f991b commit: 51d95ffc2fb3337dc87277c9af25ecc9a01f991b branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-26T15:23:26-08:00 summary: bpo-32222: Fix pygettext skipping docstrings for funcs with arg typehints (GH-4745) (cherry picked from commit eee72d4778a5513038edd5236cdd87ccce2bc60a) Co-authored-by: Tobotimus files: A Misc/NEWS.d/next/Tools-Demos/2017-12-07-20-51-20.bpo-32222.hPBcGT.rst M Lib/test/test_tools/test_i18n.py M Tools/i18n/pygettext.py diff --git a/Lib/test/test_tools/test_i18n.py b/Lib/test/test_tools/test_i18n.py index 5c28baea7241..3c8be27a57b4 100644 --- a/Lib/test/test_tools/test_i18n.py +++ b/Lib/test/test_tools/test_i18n.py @@ -3,6 +3,7 @@ import os import sys import unittest +import textwrap from test.support.script_helper import assert_python_ok from test.test_tools import skip_if_missing, toolsdir @@ -28,6 +29,41 @@ def get_header(self, data): headers[key] = val.strip() return headers + def get_msgids(self, data): + """ utility: return all msgids in .po file as a list of strings """ + msgids = [] + reading_msgid = False + cur_msgid = [] + for line in data.split('\n'): + if reading_msgid: + if line.startswith('"'): + cur_msgid.append(line.strip('"')) + else: + msgids.append('\n'.join(cur_msgid)) + cur_msgid = [] + reading_msgid = False + continue + if line.startswith('msgid '): + line = line[len('msgid '):] + cur_msgid.append(line.strip('"')) + reading_msgid = True + else: + if reading_msgid: + msgids.append('\n'.join(cur_msgid)) + + return msgids + + def extract_docstrings_from_str(self, module_content): + """ utility: return all msgids extracted from module_content """ + filename = 'test_docstrings.py' + with temp_cwd(None) as cwd: + with open(filename, 'w') as fp: + fp.write(module_content) + assert_python_ok(self.script, '-D', filename) + with open('messages.pot') as fp: + data = fp.read() + return self.get_msgids(data) + def test_header(self): """Make sure the required fields are in the header, according to: http://www.gnu.org/software/gettext/manual/gettext.html#Header-Entry @@ -72,3 +108,55 @@ def test_POT_Creation_Date(self): # This will raise if the date format does not exactly match. datetime.strptime(creationDate, '%Y-%m-%d %H:%M%z') + + def test_funcdocstring_annotated_args(self): + """ Test docstrings for functions with annotated args """ + msgids = self.extract_docstrings_from_str(textwrap.dedent('''\ + def foo(bar: str): + """doc""" + ''')) + self.assertIn('doc', msgids) + + def test_funcdocstring_annotated_return(self): + """ Test docstrings for functions with annotated return type """ + msgids = self.extract_docstrings_from_str(textwrap.dedent('''\ + def foo(bar) -> str: + """doc""" + ''')) + self.assertIn('doc', msgids) + + def test_funcdocstring_defvalue_args(self): + """ Test docstring for functions with default arg values """ + msgids = self.extract_docstrings_from_str(textwrap.dedent('''\ + def foo(bar=()): + """doc""" + ''')) + self.assertIn('doc', msgids) + + def test_funcdocstring_multiple_funcs(self): + """ Test docstring extraction for multiple functions combining + annotated args, annotated return types and default arg values + """ + msgids = self.extract_docstrings_from_str(textwrap.dedent('''\ + def foo1(bar: tuple=()) -> str: + """doc1""" + + def foo2(bar: List[1:2]) -> (lambda x: x): + """doc2""" + + def foo3(bar: 'func'=lambda x: x) -> {1: 2}: + """doc3""" + ''')) + self.assertIn('doc1', msgids) + self.assertIn('doc2', msgids) + self.assertIn('doc3', msgids) + + def test_classdocstring_early_colon(self): + """ Test docstring extraction for a class with colons occuring within + the parentheses. + """ + msgids = self.extract_docstrings_from_str(textwrap.dedent('''\ + class D(L[1:2], F({1: 2}), metaclass=M(lambda x: x)): + """doc""" + ''')) + self.assertIn('doc', msgids) diff --git a/Misc/NEWS.d/next/Tools-Demos/2017-12-07-20-51-20.bpo-32222.hPBcGT.rst b/Misc/NEWS.d/next/Tools-Demos/2017-12-07-20-51-20.bpo-32222.hPBcGT.rst new file mode 100644 index 000000000000..b0b4c5e9357c --- /dev/null +++ b/Misc/NEWS.d/next/Tools-Demos/2017-12-07-20-51-20.bpo-32222.hPBcGT.rst @@ -0,0 +1,3 @@ +Fix pygettext not extracting docstrings for functions with type annotated +arguments. +Patch by Toby Harradine. diff --git a/Tools/i18n/pygettext.py b/Tools/i18n/pygettext.py index 8ef5ff8a3e72..0f0395a4fcab 100755 --- a/Tools/i18n/pygettext.py +++ b/Tools/i18n/pygettext.py @@ -320,6 +320,7 @@ def __init__(self, options): self.__lineno = -1 self.__freshmodule = 1 self.__curfile = None + self.__enclosurecount = 0 def __call__(self, ttype, tstring, stup, etup, line): # dispatch @@ -340,7 +341,7 @@ def __waiting(self, ttype, tstring, lineno): elif ttype not in (tokenize.COMMENT, tokenize.NL): self.__freshmodule = 0 return - # class docstring? + # class or func/method docstring? if ttype == tokenize.NAME and tstring in ('class', 'def'): self.__state = self.__suiteseen return @@ -348,9 +349,15 @@ def __waiting(self, ttype, tstring, lineno): self.__state = self.__keywordseen def __suiteseen(self, ttype, tstring, lineno): - # ignore anything until we see the colon - if ttype == tokenize.OP and tstring == ':': - self.__state = self.__suitedocstring + # skip over any enclosure pairs until we see the colon + if ttype == tokenize.OP: + if tstring == ':' and self.__enclosurecount == 0: + # we see a colon and we're not in an enclosure: end of def + self.__state = self.__suitedocstring + elif tstring in '([{': + self.__enclosurecount += 1 + elif tstring in ')]}': + self.__enclosurecount -= 1 def __suitedocstring(self, ttype, tstring, lineno): # ignore any intervening noise From webhook-mailer at python.org Mon Feb 26 19:00:01 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 27 Feb 2018 00:00:01 -0000 Subject: [Python-checkins] bpo-32222: Fix pygettext skipping docstrings for funcs with arg typehints (GH-4745) Message-ID: https://github.com/python/cpython/commit/ec5569b08efd28fdc032fb8b474f588633ddf6af commit: ec5569b08efd28fdc032fb8b474f588633ddf6af branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-26T15:59:55-08:00 summary: bpo-32222: Fix pygettext skipping docstrings for funcs with arg typehints (GH-4745) (cherry picked from commit eee72d4778a5513038edd5236cdd87ccce2bc60a) Co-authored-by: Tobotimus files: A Misc/NEWS.d/next/Tools-Demos/2017-12-07-20-51-20.bpo-32222.hPBcGT.rst M Lib/test/test_tools/test_i18n.py M Tools/i18n/pygettext.py diff --git a/Lib/test/test_tools/test_i18n.py b/Lib/test/test_tools/test_i18n.py index ce6f549879c7..5e7c4bffccde 100644 --- a/Lib/test/test_tools/test_i18n.py +++ b/Lib/test/test_tools/test_i18n.py @@ -2,6 +2,7 @@ import os import unittest +import textwrap from test.support.script_helper import assert_python_ok from test.test_tools import skip_if_missing, toolsdir @@ -27,6 +28,41 @@ def get_header(self, data): headers[key] = val.strip() return headers + def get_msgids(self, data): + """ utility: return all msgids in .po file as a list of strings """ + msgids = [] + reading_msgid = False + cur_msgid = [] + for line in data.split('\n'): + if reading_msgid: + if line.startswith('"'): + cur_msgid.append(line.strip('"')) + else: + msgids.append('\n'.join(cur_msgid)) + cur_msgid = [] + reading_msgid = False + continue + if line.startswith('msgid '): + line = line[len('msgid '):] + cur_msgid.append(line.strip('"')) + reading_msgid = True + else: + if reading_msgid: + msgids.append('\n'.join(cur_msgid)) + + return msgids + + def extract_docstrings_from_str(self, module_content): + """ utility: return all msgids extracted from module_content """ + filename = 'test_docstrings.py' + with temp_cwd(None) as cwd: + with open(filename, 'w') as fp: + fp.write(module_content) + assert_python_ok(self.script, '-D', filename) + with open('messages.pot') as fp: + data = fp.read() + return self.get_msgids(data) + def test_header(self): """Make sure the required fields are in the header, according to: http://www.gnu.org/software/gettext/manual/gettext.html#Header-Entry @@ -70,3 +106,55 @@ def test_POT_Creation_Date(self): # This will raise if the date format does not exactly match. datetime.strptime(creationDate, '%Y-%m-%d %H:%M%z') + + def test_funcdocstring_annotated_args(self): + """ Test docstrings for functions with annotated args """ + msgids = self.extract_docstrings_from_str(textwrap.dedent('''\ + def foo(bar: str): + """doc""" + ''')) + self.assertIn('doc', msgids) + + def test_funcdocstring_annotated_return(self): + """ Test docstrings for functions with annotated return type """ + msgids = self.extract_docstrings_from_str(textwrap.dedent('''\ + def foo(bar) -> str: + """doc""" + ''')) + self.assertIn('doc', msgids) + + def test_funcdocstring_defvalue_args(self): + """ Test docstring for functions with default arg values """ + msgids = self.extract_docstrings_from_str(textwrap.dedent('''\ + def foo(bar=()): + """doc""" + ''')) + self.assertIn('doc', msgids) + + def test_funcdocstring_multiple_funcs(self): + """ Test docstring extraction for multiple functions combining + annotated args, annotated return types and default arg values + """ + msgids = self.extract_docstrings_from_str(textwrap.dedent('''\ + def foo1(bar: tuple=()) -> str: + """doc1""" + + def foo2(bar: List[1:2]) -> (lambda x: x): + """doc2""" + + def foo3(bar: 'func'=lambda x: x) -> {1: 2}: + """doc3""" + ''')) + self.assertIn('doc1', msgids) + self.assertIn('doc2', msgids) + self.assertIn('doc3', msgids) + + def test_classdocstring_early_colon(self): + """ Test docstring extraction for a class with colons occuring within + the parentheses. + """ + msgids = self.extract_docstrings_from_str(textwrap.dedent('''\ + class D(L[1:2], F({1: 2}), metaclass=M(lambda x: x)): + """doc""" + ''')) + self.assertIn('doc', msgids) diff --git a/Misc/NEWS.d/next/Tools-Demos/2017-12-07-20-51-20.bpo-32222.hPBcGT.rst b/Misc/NEWS.d/next/Tools-Demos/2017-12-07-20-51-20.bpo-32222.hPBcGT.rst new file mode 100644 index 000000000000..b0b4c5e9357c --- /dev/null +++ b/Misc/NEWS.d/next/Tools-Demos/2017-12-07-20-51-20.bpo-32222.hPBcGT.rst @@ -0,0 +1,3 @@ +Fix pygettext not extracting docstrings for functions with type annotated +arguments. +Patch by Toby Harradine. diff --git a/Tools/i18n/pygettext.py b/Tools/i18n/pygettext.py index 8ef5ff8a3e72..0f0395a4fcab 100755 --- a/Tools/i18n/pygettext.py +++ b/Tools/i18n/pygettext.py @@ -320,6 +320,7 @@ def __init__(self, options): self.__lineno = -1 self.__freshmodule = 1 self.__curfile = None + self.__enclosurecount = 0 def __call__(self, ttype, tstring, stup, etup, line): # dispatch @@ -340,7 +341,7 @@ def __waiting(self, ttype, tstring, lineno): elif ttype not in (tokenize.COMMENT, tokenize.NL): self.__freshmodule = 0 return - # class docstring? + # class or func/method docstring? if ttype == tokenize.NAME and tstring in ('class', 'def'): self.__state = self.__suiteseen return @@ -348,9 +349,15 @@ def __waiting(self, ttype, tstring, lineno): self.__state = self.__keywordseen def __suiteseen(self, ttype, tstring, lineno): - # ignore anything until we see the colon - if ttype == tokenize.OP and tstring == ':': - self.__state = self.__suitedocstring + # skip over any enclosure pairs until we see the colon + if ttype == tokenize.OP: + if tstring == ':' and self.__enclosurecount == 0: + # we see a colon and we're not in an enclosure: end of def + self.__state = self.__suitedocstring + elif tstring in '([{': + self.__enclosurecount += 1 + elif tstring in ')]}': + self.__enclosurecount -= 1 def __suitedocstring(self, ttype, tstring, lineno): # ignore any intervening noise From webhook-mailer at python.org Mon Feb 26 19:50:19 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 27 Feb 2018 00:50:19 -0000 Subject: [Python-checkins] bpo-32713: Fix tarfile.itn for large/negative float values. (GH-5434) Message-ID: https://github.com/python/cpython/commit/a9a8a9814a52b3c92b3680f0b3a356116510ee18 commit: a9a8a9814a52b3c92b3680f0b3a356116510ee18 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-26T16:50:09-08:00 summary: bpo-32713: Fix tarfile.itn for large/negative float values. (GH-5434) (cherry picked from commit 72d9b2be36f091793ae7ffc5ad751f040c6e6ad3) Co-authored-by: Joffrey F files: A Misc/NEWS.d/next/Library/2018-02-26-13-16-36.bpo-32713.55yegW.rst M Lib/tarfile.py M Lib/test/test_tarfile.py diff --git a/Lib/tarfile.py b/Lib/tarfile.py index a24ee42abf82..85119a48a48b 100755 --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -200,8 +200,9 @@ def itn(n, digits=8, format=DEFAULT_FORMAT): # base-256 representation. This allows values up to (256**(digits-1))-1. # A 0o200 byte indicates a positive number, a 0o377 byte a negative # number. + n = int(n) if 0 <= n < 8 ** (digits - 1): - s = bytes("%0*o" % (digits - 1, int(n)), "ascii") + NUL + s = bytes("%0*o" % (digits - 1, n), "ascii") + NUL elif format == GNU_FORMAT and -256 ** (digits - 1) <= n < 256 ** (digits - 1): if n >= 0: s = bytearray([0o200]) diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py index b868326d5c74..7d2eec8a7ccf 100644 --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -2149,6 +2149,14 @@ def test_write_number_fields(self): self.assertEqual(tarfile.itn(-0x100000000000000), b"\xff\x00\x00\x00\x00\x00\x00\x00") + # Issue 32713: Test if itn() supports float values outside the + # non-GNU format range + self.assertEqual(tarfile.itn(-100.0, format=tarfile.GNU_FORMAT), + b"\xff\xff\xff\xff\xff\xff\xff\x9c") + self.assertEqual(tarfile.itn(8 ** 12 + 0.0, format=tarfile.GNU_FORMAT), + b"\x80\x00\x00\x10\x00\x00\x00\x00") + self.assertEqual(tarfile.nti(tarfile.itn(-0.1, format=tarfile.GNU_FORMAT)), 0) + def test_number_field_limits(self): with self.assertRaises(ValueError): tarfile.itn(-1, 8, tarfile.USTAR_FORMAT) diff --git a/Misc/NEWS.d/next/Library/2018-02-26-13-16-36.bpo-32713.55yegW.rst b/Misc/NEWS.d/next/Library/2018-02-26-13-16-36.bpo-32713.55yegW.rst new file mode 100644 index 000000000000..bb5d64a351cb --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-26-13-16-36.bpo-32713.55yegW.rst @@ -0,0 +1 @@ +Fixed tarfile.itn handling of out-of-bounds float values. Patch by Joffrey Fuhrer. From webhook-mailer at python.org Mon Feb 26 20:11:11 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 27 Feb 2018 01:11:11 -0000 Subject: [Python-checkins] bpo-32713: Fix tarfile.itn for large/negative float values. (GH-5434) Message-ID: https://github.com/python/cpython/commit/3f6c172b702dccc90d16db8faa14b4fabda63ff6 commit: 3f6c172b702dccc90d16db8faa14b4fabda63ff6 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-26T17:11:01-08:00 summary: bpo-32713: Fix tarfile.itn for large/negative float values. (GH-5434) (cherry picked from commit 72d9b2be36f091793ae7ffc5ad751f040c6e6ad3) Co-authored-by: Joffrey F files: A Misc/NEWS.d/next/Library/2018-02-26-13-16-36.bpo-32713.55yegW.rst M Lib/tarfile.py M Lib/test/test_tarfile.py diff --git a/Lib/tarfile.py b/Lib/tarfile.py index 631b69dcba4f..395b846ee2c4 100755 --- a/Lib/tarfile.py +++ b/Lib/tarfile.py @@ -202,8 +202,9 @@ def itn(n, digits=8, format=DEFAULT_FORMAT): # base-256 representation. This allows values up to (256**(digits-1))-1. # A 0o200 byte indicates a positive number, a 0o377 byte a negative # number. + n = int(n) if 0 <= n < 8 ** (digits - 1): - s = bytes("%0*o" % (digits - 1, int(n)), "ascii") + NUL + s = bytes("%0*o" % (digits - 1, n), "ascii") + NUL elif format == GNU_FORMAT and -256 ** (digits - 1) <= n < 256 ** (digits - 1): if n >= 0: s = bytearray([0o200]) diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py index fc7905542116..4cd7d5370f58 100644 --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py @@ -2146,6 +2146,14 @@ def test_write_number_fields(self): self.assertEqual(tarfile.itn(-0x100000000000000), b"\xff\x00\x00\x00\x00\x00\x00\x00") + # Issue 32713: Test if itn() supports float values outside the + # non-GNU format range + self.assertEqual(tarfile.itn(-100.0, format=tarfile.GNU_FORMAT), + b"\xff\xff\xff\xff\xff\xff\xff\x9c") + self.assertEqual(tarfile.itn(8 ** 12 + 0.0, format=tarfile.GNU_FORMAT), + b"\x80\x00\x00\x10\x00\x00\x00\x00") + self.assertEqual(tarfile.nti(tarfile.itn(-0.1, format=tarfile.GNU_FORMAT)), 0) + def test_number_field_limits(self): with self.assertRaises(ValueError): tarfile.itn(-1, 8, tarfile.USTAR_FORMAT) diff --git a/Misc/NEWS.d/next/Library/2018-02-26-13-16-36.bpo-32713.55yegW.rst b/Misc/NEWS.d/next/Library/2018-02-26-13-16-36.bpo-32713.55yegW.rst new file mode 100644 index 000000000000..bb5d64a351cb --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-26-13-16-36.bpo-32713.55yegW.rst @@ -0,0 +1 @@ +Fixed tarfile.itn handling of out-of-bounds float values. Patch by Joffrey Fuhrer. From webhook-mailer at python.org Mon Feb 26 20:38:37 2018 From: webhook-mailer at python.org (Eric V. Smith) Date: Tue, 27 Feb 2018 01:38:37 -0000 Subject: [Python-checkins] bpo-32960: For dataclasses, disallow inheriting frozen from non-frozen classes and vice-versa, (GH-5919) Message-ID: https://github.com/python/cpython/commit/2fa6b9eae07e2385e2acbf2e40093a21fb3a10c4 commit: 2fa6b9eae07e2385e2acbf2e40093a21fb3a10c4 branch: master author: Eric V. Smith committer: GitHub date: 2018-02-26T20:38:33-05:00 summary: bpo-32960: For dataclasses, disallow inheriting frozen from non-frozen classes and vice-versa, (GH-5919) This restriction will be relaxed at a future date. files: A Misc/NEWS.d/next/Library/2018-02-26-20-04-40.bpo-32960.48r0Ml.rst M Lib/dataclasses.py M Lib/test/test_dataclasses.py diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index db92b10960d5..54478fec93df 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -623,14 +623,21 @@ def _process_class(cls, repr, eq, order, unsafe_hash, init, frozen): else: setattr(cls, f.name, f.default) + # We're inheriting from a frozen dataclass, but we're not frozen. + if cls.__setattr__ is _frozen_setattr and not frozen: + raise TypeError('cannot inherit non-frozen dataclass from a ' + 'frozen one') + + # We're inheriting from a non-frozen dataclass, but we're frozen. + if (hasattr(cls, _MARKER) and cls.__setattr__ is not _frozen_setattr + and frozen): + raise TypeError('cannot inherit frozen dataclass from a ' + 'non-frozen one') + # Remember all of the fields on our class (including bases). This # marks this class as being a dataclass. setattr(cls, _MARKER, fields) - # We also need to check if a parent class is frozen: frozen has to - # be inherited down. - is_frozen = frozen or cls.__setattr__ is _frozen_setattr - # 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 @@ -654,7 +661,7 @@ def _process_class(cls, repr, eq, order, unsafe_hash, init, frozen): if f._field_type in (_FIELD, _FIELD_INITVAR)] _set_new_attribute(cls, '__init__', _init_fn(flds, - is_frozen, + frozen, has_post_init, # The name to use for the "self" param # in __init__. Use "self" if possible. @@ -696,7 +703,7 @@ def _process_class(cls, repr, eq, order, unsafe_hash, init, frozen): f'in class {cls.__name__}. Consider using ' 'functools.total_ordering') - if is_frozen: + if frozen: for name, fn in [('__setattr__', _frozen_setattr), ('__delattr__', _frozen_delattr)]: if _set_new_attribute(cls, name, fn): diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index 582cb3459f5d..46d485c0157b 100755 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -637,29 +637,6 @@ class C: y: int self.assertNotEqual(Point(1, 3), C(1, 3)) - def test_frozen(self): - @dataclass(frozen=True) - class C: - i: int - - c = C(10) - self.assertEqual(c.i, 10) - with self.assertRaises(FrozenInstanceError): - c.i = 5 - self.assertEqual(c.i, 10) - - # Check that a derived class is still frozen, even if not - # marked so. - @dataclass - class D(C): - pass - - d = D(20) - self.assertEqual(d.i, 20) - with self.assertRaises(FrozenInstanceError): - d.i = 5 - self.assertEqual(d.i, 20) - def test_not_tuple(self): # Test that some of the problems with namedtuple don't happen # here. @@ -2475,5 +2452,66 @@ class C(base): assert False, f'unknown value for expected={expected!r}' +class TestFrozen(unittest.TestCase): + def test_frozen(self): + @dataclass(frozen=True) + class C: + i: int + + c = C(10) + self.assertEqual(c.i, 10) + with self.assertRaises(FrozenInstanceError): + c.i = 5 + self.assertEqual(c.i, 10) + + def test_inherit(self): + @dataclass(frozen=True) + class C: + i: int + + @dataclass(frozen=True) + class D(C): + j: int + + d = D(0, 10) + with self.assertRaises(FrozenInstanceError): + d.i = 5 + self.assertEqual(d.i, 0) + + def test_inherit_from_nonfrozen_from_frozen(self): + @dataclass(frozen=True) + class C: + i: int + + with self.assertRaisesRegex(TypeError, + 'cannot inherit non-frozen dataclass from a frozen one'): + @dataclass + class D(C): + pass + + def test_inherit_from_frozen_from_nonfrozen(self): + @dataclass + class C: + i: int + + with self.assertRaisesRegex(TypeError, + 'cannot inherit frozen dataclass from a non-frozen one'): + @dataclass(frozen=True) + class D(C): + pass + + def test_inherit_from_normal_class(self): + class C: + pass + + @dataclass(frozen=True) + class D(C): + i: int + + d = D(10) + with self.assertRaises(FrozenInstanceError): + d.i = 5 + + if __name__ == '__main__': unittest.main() diff --git a/Misc/NEWS.d/next/Library/2018-02-26-20-04-40.bpo-32960.48r0Ml.rst b/Misc/NEWS.d/next/Library/2018-02-26-20-04-40.bpo-32960.48r0Ml.rst new file mode 100644 index 000000000000..4ad1fa17571d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-26-20-04-40.bpo-32960.48r0Ml.rst @@ -0,0 +1,3 @@ +For dataclasses, disallow inheriting frozen from non-frozen classes, and +also disallow inheriting non-frozen from frozen classes. This restriction +will be relaxed at a future date. From webhook-mailer at python.org Mon Feb 26 20:39:55 2018 From: webhook-mailer at python.org (Serhiy Storchaka) Date: Tue, 27 Feb 2018 01:39:55 -0000 Subject: [Python-checkins] [3.6] bpo-32922: dbm.open() now encodes filename with the filesystem encoding. (GH-5832). (GH-5906) Message-ID: https://github.com/python/cpython/commit/5bf74859fe253f0e8ff73ba699cd1a7e2dfbcea3 commit: 5bf74859fe253f0e8ff73ba699cd1a7e2dfbcea3 branch: 3.6 author: Serhiy Storchaka committer: GitHub date: 2018-02-27T03:39:53+02:00 summary: [3.6] bpo-32922: dbm.open() now encodes filename with the filesystem encoding. (GH-5832). (GH-5906) (cherry picked from commit 6f600ff1734ca2fdcdd37a809adf8130f0d8cc4e) Co-authored-by: Serhiy Storchaka files: A Misc/NEWS.d/next/Library/2018-02-23-19-12-04.bpo-32922.u-xe0B.rst M Lib/test/test_dbm_dumb.py M Lib/test/test_dbm_gnu.py M Lib/test/test_dbm_ndbm.py M Modules/_dbmmodule.c M Modules/_gdbmmodule.c M Modules/clinic/_dbmmodule.c.h M Modules/clinic/_gdbmmodule.c.h diff --git a/Lib/test/test_dbm_dumb.py b/Lib/test/test_dbm_dumb.py index df531d64e488..2606ba78eb55 100644 --- a/Lib/test/test_dbm_dumb.py +++ b/Lib/test/test_dbm_dumb.py @@ -275,6 +275,21 @@ def test_readonly_files(self): self.assertEqual(sorted(f.keys()), sorted(self._dict)) f.close() # don't write + @unittest.skipUnless(support.TESTFN_NONASCII, + 'requires OS support of non-ASCII encodings') + def test_nonascii_filename(self): + filename = support.TESTFN_NONASCII + for suffix in ['.dir', '.dat', '.bak']: + self.addCleanup(support.unlink, filename + suffix) + with dumbdbm.open(filename, 'c') as db: + db[b'key'] = b'value' + self.assertTrue(os.path.exists(filename + '.dat')) + self.assertTrue(os.path.exists(filename + '.dir')) + with dumbdbm.open(filename, 'r') as db: + self.assertEqual(list(db.keys()), [b'key']) + self.assertTrue(b'key' in db) + self.assertEqual(db[b'key'], b'value') + def tearDown(self): _delete_files() diff --git a/Lib/test/test_dbm_gnu.py b/Lib/test/test_dbm_gnu.py index 304b33286978..d96df9284806 100644 --- a/Lib/test/test_dbm_gnu.py +++ b/Lib/test/test_dbm_gnu.py @@ -2,7 +2,7 @@ gdbm = support.import_module("dbm.gnu") #skip if not supported import unittest import os -from test.support import TESTFN, unlink +from test.support import TESTFN, TESTFN_NONASCII, unlink filename = TESTFN @@ -93,5 +93,39 @@ def test_context_manager(self): self.assertEqual(str(cm.exception), "GDBM object has already been closed") + def test_bytes(self): + with gdbm.open(filename, 'c') as db: + db[b'bytes key \xbd'] = b'bytes value \xbd' + with gdbm.open(filename, 'r') as db: + self.assertEqual(list(db.keys()), [b'bytes key \xbd']) + self.assertTrue(b'bytes key \xbd' in db) + self.assertEqual(db[b'bytes key \xbd'], b'bytes value \xbd') + + def test_unicode(self): + with gdbm.open(filename, 'c') as db: + db['Unicode key \U0001f40d'] = 'Unicode value \U0001f40d' + with gdbm.open(filename, 'r') as db: + self.assertEqual(list(db.keys()), ['Unicode key \U0001f40d'.encode()]) + self.assertTrue('Unicode key \U0001f40d'.encode() in db) + self.assertTrue('Unicode key \U0001f40d' in db) + self.assertEqual(db['Unicode key \U0001f40d'.encode()], + 'Unicode value \U0001f40d'.encode()) + self.assertEqual(db['Unicode key \U0001f40d'], + 'Unicode value \U0001f40d'.encode()) + + @unittest.skipUnless(TESTFN_NONASCII, + 'requires OS support of non-ASCII encodings') + def test_nonascii_filename(self): + filename = TESTFN_NONASCII + self.addCleanup(unlink, filename) + with gdbm.open(filename, 'c') as db: + db[b'key'] = b'value' + self.assertTrue(os.path.exists(filename)) + with gdbm.open(filename, 'r') as db: + self.assertEqual(list(db.keys()), [b'key']) + self.assertTrue(b'key' in db) + self.assertEqual(db[b'key'], b'value') + + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_dbm_ndbm.py b/Lib/test/test_dbm_ndbm.py index 49f4426e4cb9..fb7d0e8281e3 100644 --- a/Lib/test/test_dbm_ndbm.py +++ b/Lib/test/test_dbm_ndbm.py @@ -1,5 +1,6 @@ from test import support support.import_module("dbm.ndbm") #skip if not supported +import os import unittest import dbm.ndbm from dbm.ndbm import error @@ -47,6 +48,42 @@ def test_context_manager(self): self.assertEqual(str(cm.exception), "DBM object has already been closed") + def test_bytes(self): + with dbm.ndbm.open(self.filename, 'c') as db: + db[b'bytes key \xbd'] = b'bytes value \xbd' + with dbm.ndbm.open(self.filename, 'r') as db: + self.assertEqual(list(db.keys()), [b'bytes key \xbd']) + self.assertTrue(b'bytes key \xbd' in db) + self.assertEqual(db[b'bytes key \xbd'], b'bytes value \xbd') + + def test_unicode(self): + with dbm.ndbm.open(self.filename, 'c') as db: + db['Unicode key \U0001f40d'] = 'Unicode value \U0001f40d' + with dbm.ndbm.open(self.filename, 'r') as db: + self.assertEqual(list(db.keys()), ['Unicode key \U0001f40d'.encode()]) + self.assertTrue('Unicode key \U0001f40d'.encode() in db) + self.assertTrue('Unicode key \U0001f40d' in db) + self.assertEqual(db['Unicode key \U0001f40d'.encode()], + 'Unicode value \U0001f40d'.encode()) + self.assertEqual(db['Unicode key \U0001f40d'], + 'Unicode value \U0001f40d'.encode()) + + @unittest.skipUnless(support.TESTFN_NONASCII, + 'requires OS support of non-ASCII encodings') + def test_nonascii_filename(self): + filename = support.TESTFN_NONASCII + for suffix in ['', '.pag', '.dir', '.db']: + self.addCleanup(support.unlink, filename + suffix) + with dbm.ndbm.open(filename, 'c') as db: + db[b'key'] = b'value' + self.assertTrue(any(os.path.exists(filename + suffix) + for suffix in ['', '.pag', '.dir', '.db'])) + with dbm.ndbm.open(filename, 'r') as db: + self.assertEqual(list(db.keys()), [b'key']) + self.assertTrue(b'key' in db) + self.assertEqual(db[b'key'], b'value') + + if __name__ == '__main__': unittest.main() diff --git a/Misc/NEWS.d/next/Library/2018-02-23-19-12-04.bpo-32922.u-xe0B.rst b/Misc/NEWS.d/next/Library/2018-02-23-19-12-04.bpo-32922.u-xe0B.rst new file mode 100644 index 000000000000..412e588586c0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-23-19-12-04.bpo-32922.u-xe0B.rst @@ -0,0 +1,2 @@ +dbm.open() now encodes filename with the filesystem encoding rather than +default encoding. diff --git a/Modules/_dbmmodule.c b/Modules/_dbmmodule.c index 804978a6ac59..842953679698 100644 --- a/Modules/_dbmmodule.c +++ b/Modules/_dbmmodule.c @@ -413,7 +413,7 @@ static PyTypeObject Dbmtype = { _dbm.open as dbmopen - filename: str + filename: unicode The filename to open. flags: str="r" @@ -430,9 +430,9 @@ Return a database object. [clinic start generated code]*/ static PyObject * -dbmopen_impl(PyObject *module, const char *filename, const char *flags, +dbmopen_impl(PyObject *module, PyObject *filename, const char *flags, int mode) -/*[clinic end generated code: output=5fade8cf16e0755f input=226334bade5764e6]*/ +/*[clinic end generated code: output=9527750f5df90764 input=376a9d903a50df59]*/ { int iflags; @@ -451,7 +451,20 @@ dbmopen_impl(PyObject *module, const char *filename, const char *flags, "arg 2 to open should be 'r', 'w', 'c', or 'n'"); return NULL; } - return newdbmobject(filename, iflags, mode); + + PyObject *filenamebytes = PyUnicode_EncodeFSDefault(filename); + if (filenamebytes == NULL) { + return NULL; + } + const char *name = PyBytes_AS_STRING(filenamebytes); + if (strlen(name) != (size_t)PyBytes_GET_SIZE(filenamebytes)) { + Py_DECREF(filenamebytes); + PyErr_SetString(PyExc_ValueError, "embedded null character"); + return NULL; + } + PyObject *self = newdbmobject(name, iflags, mode); + Py_DECREF(filenamebytes); + return self; } static PyMethodDef dbmmodule_methods[] = { diff --git a/Modules/_gdbmmodule.c b/Modules/_gdbmmodule.c index daae71dc8dca..a6ce35246483 100644 --- a/Modules/_gdbmmodule.c +++ b/Modules/_gdbmmodule.c @@ -532,7 +532,7 @@ static PyTypeObject Dbmtype = { /*[clinic input] _gdbm.open as dbmopen - filename as name: str + filename: unicode flags: str="r" mode: int(py_default="0o666") = 0o666 / @@ -562,8 +562,9 @@ when the database has to be created. It defaults to octal 0o666. [clinic start generated code]*/ static PyObject * -dbmopen_impl(PyObject *module, const char *name, const char *flags, int mode) -/*[clinic end generated code: output=31aa1bafdf5da688 input=55563cd60e51984a]*/ +dbmopen_impl(PyObject *module, PyObject *filename, const char *flags, + int mode) +/*[clinic end generated code: output=9527750f5df90764 input=3be0b0875974b928]*/ { int iflags; @@ -611,7 +612,19 @@ dbmopen_impl(PyObject *module, const char *name, const char *flags, int mode) } } - return newdbmobject(name, iflags, mode); + PyObject *filenamebytes = PyUnicode_EncodeFSDefault(filename); + if (filenamebytes == NULL) { + return NULL; + } + const char *name = PyBytes_AS_STRING(filenamebytes); + if (strlen(name) != (size_t)PyBytes_GET_SIZE(filenamebytes)) { + Py_DECREF(filenamebytes); + PyErr_SetString(PyExc_ValueError, "embedded null character"); + return NULL; + } + PyObject *self = newdbmobject(name, iflags, mode); + Py_DECREF(filenamebytes); + return self; } static const char dbmmodule_open_flags[] = "rwcn" diff --git a/Modules/clinic/_dbmmodule.c.h b/Modules/clinic/_dbmmodule.c.h index 06cf7e674114..7dd529a50c61 100644 --- a/Modules/clinic/_dbmmodule.c.h +++ b/Modules/clinic/_dbmmodule.c.h @@ -121,18 +121,18 @@ PyDoc_STRVAR(dbmopen__doc__, {"open", (PyCFunction)dbmopen, METH_VARARGS, dbmopen__doc__}, static PyObject * -dbmopen_impl(PyObject *module, const char *filename, const char *flags, +dbmopen_impl(PyObject *module, PyObject *filename, const char *flags, int mode); static PyObject * dbmopen(PyObject *module, PyObject *args) { PyObject *return_value = NULL; - const char *filename; + PyObject *filename; const char *flags = "r"; int mode = 438; - if (!PyArg_ParseTuple(args, "s|si:open", + if (!PyArg_ParseTuple(args, "U|si:open", &filename, &flags, &mode)) { goto exit; } @@ -141,4 +141,4 @@ dbmopen(PyObject *module, PyObject *args) exit: return return_value; } -/*[clinic end generated code: output=99adf966ef0475ff input=a9049054013a1b77]*/ +/*[clinic end generated code: output=001fabffcecb99f1 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/_gdbmmodule.c.h b/Modules/clinic/_gdbmmodule.c.h index fdd589c07a4e..1030d7059e6f 100644 --- a/Modules/clinic/_gdbmmodule.c.h +++ b/Modules/clinic/_gdbmmodule.c.h @@ -234,23 +234,24 @@ PyDoc_STRVAR(dbmopen__doc__, {"open", (PyCFunction)dbmopen, METH_VARARGS, dbmopen__doc__}, static PyObject * -dbmopen_impl(PyObject *module, const char *name, const char *flags, int mode); +dbmopen_impl(PyObject *module, PyObject *filename, const char *flags, + int mode); static PyObject * dbmopen(PyObject *module, PyObject *args) { PyObject *return_value = NULL; - const char *name; + PyObject *filename; const char *flags = "r"; int mode = 438; - if (!PyArg_ParseTuple(args, "s|si:open", - &name, &flags, &mode)) { + if (!PyArg_ParseTuple(args, "U|si:open", + &filename, &flags, &mode)) { goto exit; } - return_value = dbmopen_impl(module, name, flags, mode); + return_value = dbmopen_impl(module, filename, flags, mode); exit: return return_value; } -/*[clinic end generated code: output=ed0f5d4e3d79b80c input=a9049054013a1b77]*/ +/*[clinic end generated code: output=afb99364ac420d10 input=a9049054013a1b77]*/ From webhook-mailer at python.org Mon Feb 26 21:00:00 2018 From: webhook-mailer at python.org (Eric V. Smith) Date: Tue, 27 Feb 2018 02:00:00 -0000 Subject: [Python-checkins] bpo-32960: For dataclasses, disallow inheriting frozen from non-frozen classes and vice-versa, (GH-5919) (GH-5920) Message-ID: https://github.com/python/cpython/commit/a93e3dc236279692eaf50b91d358da5983983b14 commit: a93e3dc236279692eaf50b91d358da5983983b14 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Eric V. Smith date: 2018-02-26T20:59:55-05:00 summary: bpo-32960: For dataclasses, disallow inheriting frozen from non-frozen classes and vice-versa, (GH-5919) (GH-5920) This restriction will be relaxed at a future date. (cherry picked from commit 2fa6b9eae07e2385e2acbf2e40093a21fb3a10c4) Co-authored-by: Eric V. Smith files: A Misc/NEWS.d/next/Library/2018-02-26-20-04-40.bpo-32960.48r0Ml.rst M Lib/dataclasses.py M Lib/test/test_dataclasses.py diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py index db92b10960d5..54478fec93df 100644 --- a/Lib/dataclasses.py +++ b/Lib/dataclasses.py @@ -623,14 +623,21 @@ def _process_class(cls, repr, eq, order, unsafe_hash, init, frozen): else: setattr(cls, f.name, f.default) + # We're inheriting from a frozen dataclass, but we're not frozen. + if cls.__setattr__ is _frozen_setattr and not frozen: + raise TypeError('cannot inherit non-frozen dataclass from a ' + 'frozen one') + + # We're inheriting from a non-frozen dataclass, but we're frozen. + if (hasattr(cls, _MARKER) and cls.__setattr__ is not _frozen_setattr + and frozen): + raise TypeError('cannot inherit frozen dataclass from a ' + 'non-frozen one') + # Remember all of the fields on our class (including bases). This # marks this class as being a dataclass. setattr(cls, _MARKER, fields) - # We also need to check if a parent class is frozen: frozen has to - # be inherited down. - is_frozen = frozen or cls.__setattr__ is _frozen_setattr - # 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 @@ -654,7 +661,7 @@ def _process_class(cls, repr, eq, order, unsafe_hash, init, frozen): if f._field_type in (_FIELD, _FIELD_INITVAR)] _set_new_attribute(cls, '__init__', _init_fn(flds, - is_frozen, + frozen, has_post_init, # The name to use for the "self" param # in __init__. Use "self" if possible. @@ -696,7 +703,7 @@ def _process_class(cls, repr, eq, order, unsafe_hash, init, frozen): f'in class {cls.__name__}. Consider using ' 'functools.total_ordering') - if is_frozen: + if frozen: for name, fn in [('__setattr__', _frozen_setattr), ('__delattr__', _frozen_delattr)]: if _set_new_attribute(cls, name, fn): diff --git a/Lib/test/test_dataclasses.py b/Lib/test/test_dataclasses.py index 582cb3459f5d..46d485c0157b 100755 --- a/Lib/test/test_dataclasses.py +++ b/Lib/test/test_dataclasses.py @@ -637,29 +637,6 @@ class C: y: int self.assertNotEqual(Point(1, 3), C(1, 3)) - def test_frozen(self): - @dataclass(frozen=True) - class C: - i: int - - c = C(10) - self.assertEqual(c.i, 10) - with self.assertRaises(FrozenInstanceError): - c.i = 5 - self.assertEqual(c.i, 10) - - # Check that a derived class is still frozen, even if not - # marked so. - @dataclass - class D(C): - pass - - d = D(20) - self.assertEqual(d.i, 20) - with self.assertRaises(FrozenInstanceError): - d.i = 5 - self.assertEqual(d.i, 20) - def test_not_tuple(self): # Test that some of the problems with namedtuple don't happen # here. @@ -2475,5 +2452,66 @@ class C(base): assert False, f'unknown value for expected={expected!r}' +class TestFrozen(unittest.TestCase): + def test_frozen(self): + @dataclass(frozen=True) + class C: + i: int + + c = C(10) + self.assertEqual(c.i, 10) + with self.assertRaises(FrozenInstanceError): + c.i = 5 + self.assertEqual(c.i, 10) + + def test_inherit(self): + @dataclass(frozen=True) + class C: + i: int + + @dataclass(frozen=True) + class D(C): + j: int + + d = D(0, 10) + with self.assertRaises(FrozenInstanceError): + d.i = 5 + self.assertEqual(d.i, 0) + + def test_inherit_from_nonfrozen_from_frozen(self): + @dataclass(frozen=True) + class C: + i: int + + with self.assertRaisesRegex(TypeError, + 'cannot inherit non-frozen dataclass from a frozen one'): + @dataclass + class D(C): + pass + + def test_inherit_from_frozen_from_nonfrozen(self): + @dataclass + class C: + i: int + + with self.assertRaisesRegex(TypeError, + 'cannot inherit frozen dataclass from a non-frozen one'): + @dataclass(frozen=True) + class D(C): + pass + + def test_inherit_from_normal_class(self): + class C: + pass + + @dataclass(frozen=True) + class D(C): + i: int + + d = D(10) + with self.assertRaises(FrozenInstanceError): + d.i = 5 + + if __name__ == '__main__': unittest.main() diff --git a/Misc/NEWS.d/next/Library/2018-02-26-20-04-40.bpo-32960.48r0Ml.rst b/Misc/NEWS.d/next/Library/2018-02-26-20-04-40.bpo-32960.48r0Ml.rst new file mode 100644 index 000000000000..4ad1fa17571d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-26-20-04-40.bpo-32960.48r0Ml.rst @@ -0,0 +1,3 @@ +For dataclasses, disallow inheriting frozen from non-frozen classes, and +also disallow inheriting non-frozen from frozen classes. This restriction +will be relaxed at a future date. From webhook-mailer at python.org Tue Feb 27 02:55:42 2018 From: webhook-mailer at python.org (Christian Heimes) Date: Tue, 27 Feb 2018 07:55:42 -0000 Subject: [Python-checkins] bpo-32947: OpenSSL 1.1.1-pre1 / TLS 1.3 fixes (#5663) Message-ID: https://github.com/python/cpython/commit/05d9fe32a1245b9a798e49e0c1eb91f110935b69 commit: 05d9fe32a1245b9a798e49e0c1eb91f110935b69 branch: master author: Christian Heimes committer: GitHub date: 2018-02-27T08:55:39+01:00 summary: bpo-32947: OpenSSL 1.1.1-pre1 / TLS 1.3 fixes (#5663) * bpo-32947: OpenSSL 1.1.1-pre1 / TLS 1.3 fixes Misc fixes and workarounds for compatibility with OpenSSL 1.1.1-pre1 and TLS 1.3 support. With OpenSSL 1.1.1, Python negotiates TLS 1.3 by default. Some test cases only apply to TLS 1.2. Other tests currently fail because the threaded or async test servers stop after failure. I'm going to address these issues when OpenSSL 1.1.1 reaches beta. OpenSSL 1.1.1 has added a new option OP_ENABLE_MIDDLEBOX_COMPAT for TLS 1.3. The feature is enabled by default for maximum compatibility with broken middle boxes. Users should be able to disable the hack and CPython's test suite needs it to verify default options. Signed-off-by: Christian Heimes files: A Misc/NEWS.d/next/Library/2018-02-25-13-06-21.bpo-32947.mqStVW.rst M Doc/library/ssl.rst M Doc/whatsnew/3.7.rst 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 Modules/_ssl.c M Tools/ssl/multissltests.py diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 7371024dce4e..5d5232eda30c 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -831,6 +831,15 @@ Constants .. versionadded:: 3.3 +.. data:: OP_ENABLE_MIDDLEBOX_COMPAT + + Send dummy Change Cipher Spec (CCS) messages in TLS 1.3 handshake to make + a TLS 1.3 connection look more like a TLS 1.2 connection. + + This option is only available with OpenSSL 1.1.1 and later. + + .. versionadded:: 3.8 + .. data:: OP_NO_COMPRESSION Disable compression on the SSL channel. This is useful if the application diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index c924f6ddd471..10aed52eb486 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -669,6 +669,9 @@ 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`, +:issue:`20995`, :issue:`29136`, and :issue:`30622`) string ------ diff --git a/Lib/test/test_asyncio/utils.py b/Lib/test/test_asyncio/utils.py index 96dfe2f85b4d..711085fde5c5 100644 --- a/Lib/test/test_asyncio/utils.py +++ b/Lib/test/test_asyncio/utils.py @@ -74,6 +74,8 @@ 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 32aab047df85..1a8e2f91d386 100644 --- a/Lib/test/test_ftplib.py +++ b/Lib/test/test_ftplib.py @@ -312,6 +312,8 @@ 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, @@ -908,6 +910,8 @@ 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, @@ -940,6 +944,8 @@ 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) diff --git a/Lib/test/test_poplib.py b/Lib/test/test_poplib.py index 4d7a4394086a..fd0db798ee43 100644 --- a/Lib/test/test_poplib.py +++ b/Lib/test/test_poplib.py @@ -153,6 +153,8 @@ 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, @@ -356,6 +358,8 @@ 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) @@ -396,6 +400,8 @@ 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, diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 3b34fc0e0033..d978a9e1b0fe 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -30,7 +30,8 @@ PROTOCOLS = sorted(ssl._PROTOCOL_NAMES) HOST = support.HOST IS_LIBRESSL = ssl.OPENSSL_VERSION.startswith('LibreSSL') -IS_OPENSSL_1_1 = not IS_LIBRESSL and ssl.OPENSSL_VERSION_INFO >= (1, 1, 0) +IS_OPENSSL_1_1_0 = not IS_LIBRESSL and ssl.OPENSSL_VERSION_INFO >= (1, 1, 0) +IS_OPENSSL_1_1_1 = not IS_LIBRESSL and ssl.OPENSSL_VERSION_INFO >= (1, 1, 1) PY_SSL_DEFAULT_CIPHERS = sysconfig.get_config_var('PY_SSL_DEFAULT_CIPHERS') def data_file(*name): @@ -54,6 +55,7 @@ def data_file(*name): BYTES_CAPATH = os.fsencode(CAPATH) CAFILE_NEURONIO = data_file("capath", "4e1295a3.0") CAFILE_CACERT = data_file("capath", "5ed36f99.0") +WRONG_CERT = data_file("wrongcert.pem") CERTFILE_INFO = { 'issuer': ((('countryName', 'XY'),), @@ -124,6 +126,7 @@ def data_file(*name): OP_SINGLE_DH_USE = getattr(ssl, "OP_SINGLE_DH_USE", 0) OP_SINGLE_ECDH_USE = getattr(ssl, "OP_SINGLE_ECDH_USE", 0) OP_CIPHER_SERVER_PREFERENCE = getattr(ssl, "OP_CIPHER_SERVER_PREFERENCE", 0) +OP_ENABLE_MIDDLEBOX_COMPAT = getattr(ssl, "OP_ENABLE_MIDDLEBOX_COMPAT", 0) def handle_error(prefix): @@ -232,6 +235,7 @@ def testing_context(server_cert=SIGNED_CERTFILE): server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) server_context.load_cert_chain(server_cert) + client_context.load_verify_locations(SIGNING_CA) return client_context, server_context, hostname @@ -1016,7 +1020,8 @@ def test_options(self): default = (ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3) # SSLContext also enables these by default default |= (OP_NO_COMPRESSION | OP_CIPHER_SERVER_PREFERENCE | - OP_SINGLE_DH_USE | OP_SINGLE_ECDH_USE) + OP_SINGLE_DH_USE | OP_SINGLE_ECDH_USE | + OP_ENABLE_MIDDLEBOX_COMPAT) self.assertEqual(default, ctx.options) ctx.options |= ssl.OP_NO_TLSv1 self.assertEqual(default | ssl.OP_NO_TLSv1, ctx.options) @@ -1778,6 +1783,8 @@ 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) @@ -1787,6 +1794,8 @@ 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) @@ -2629,7 +2638,10 @@ 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('ECDHE:ECDSA:!NULL:!aRSA') + client_context.set_ciphers( + 'TLS13-AES-128-GCM-SHA256:TLS13-CHACHA20-POLY1305-SHA256:' + 'ECDHE:ECDSA:!NULL:!aRSA' + ) hostname = SIGNED_CERTFILE_ECC_HOSTNAME server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) @@ -2650,6 +2662,9 @@ def test_ecc_cert(self): def test_dual_rsa_ecc(self): client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) client_context.load_verify_locations(SIGNING_CA) + # TODO: fix TLSv1.3 once SSLContext can restrict signature + # algorithms. + client_context.options |= ssl.OP_NO_TLSv1_3 # only ECDSA certs client_context.set_ciphers('ECDHE:ECDSA:!NULL:!aRSA') hostname = SIGNED_CERTFILE_ECC_HOSTNAME @@ -2676,6 +2691,8 @@ 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 @@ -2738,15 +2755,22 @@ def test_wrong_cert(self): Launch a server with CERT_REQUIRED, and check that trying to connect to it with a wrong client certificate fails. """ - certfile = os.path.join(os.path.dirname(__file__) or os.curdir, - "wrongcert.pem") - server = ThreadedEchoServer(CERTFILE, - certreqs=ssl.CERT_REQUIRED, - cacerts=CERTFILE, chatty=False, - connectionchatty=False) + client_context, server_context, hostname = testing_context() + # load client cert + 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 + + server = ThreadedEchoServer( + context=server_context, chatty=True, connectionchatty=True, + ) + with server, \ - socket.socket() as sock, \ - test_wrap_socket(sock, certfile=certfile) as s: + client_context.wrap_socket(socket.socket(), + server_hostname=hostname) as s: try: # Expect either an SSL error about the server rejecting # the connection, or a low-level connection reset (which @@ -3400,7 +3424,9 @@ 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, 0, 2): + if ssl.OPENSSL_VERSION_INFO >= (1, 1, 1): + self.assertEqual(s.version(), 'TLSv1.3') + elif ssl.OPENSSL_VERSION_INFO >= (1, 0, 2): self.assertEqual(s.version(), 'TLSv1.2') else: # 0.9.8 to 1.0.1 self.assertIn(s.version(), ('TLSv1', 'TLSv1.2')) @@ -3412,18 +3438,18 @@ def test_version_basic(self): def test_tls1_3(self): context = ssl.SSLContext(ssl.PROTOCOL_TLS) context.load_cert_chain(CERTFILE) - # disable all but TLS 1.3 context.options |= ( ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 | ssl.OP_NO_TLSv1_2 ) with ThreadedEchoServer(context=context) as server: with context.wrap_socket(socket.socket()) as s: s.connect((HOST, server.port)) - self.assertIn(s.cipher()[0], [ + self.assertIn(s.cipher()[0], { 'TLS13-AES-256-GCM-SHA384', 'TLS13-CHACHA20-POLY1305-SHA256', 'TLS13-AES-128-GCM-SHA256', - ]) + }) + self.assertEqual(s.version(), 'TLSv1.3') @unittest.skipUnless(ssl.HAS_ECDH, "test requires ECDH-enabled OpenSSL") def test_default_ecdh_curve(self): @@ -3452,58 +3478,54 @@ def test_tls_unique_channel_binding(self): if support.verbose: sys.stdout.write("\n") - server = ThreadedEchoServer(CERTFILE, - certreqs=ssl.CERT_NONE, - ssl_version=ssl.PROTOCOL_TLS_SERVER, - cacerts=CERTFILE, + 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, connectionchatty=False) + with server: - s = test_wrap_socket(socket.socket(), - server_side=False, - certfile=CERTFILE, - ca_certs=CERTFILE, - cert_reqs=ssl.CERT_NONE, - ssl_version=ssl.PROTOCOL_TLS_CLIENT) - s.connect((HOST, server.port)) - # get the data - cb_data = s.get_channel_binding("tls-unique") - if support.verbose: - sys.stdout.write(" got channel binding data: {0!r}\n" - .format(cb_data)) - - # check if it is sane - self.assertIsNotNone(cb_data) - self.assertEqual(len(cb_data), 12) # True for TLSv1 - - # and compare with the peers version - s.write(b"CB tls-unique\n") - peer_data_repr = s.read().strip() - self.assertEqual(peer_data_repr, - repr(cb_data).encode("us-ascii")) - s.close() + with client_context.wrap_socket( + socket.socket(), + server_hostname=hostname) as s: + s.connect((HOST, server.port)) + # get the data + cb_data = s.get_channel_binding("tls-unique") + if support.verbose: + sys.stdout.write( + " got channel binding data: {0!r}\n".format(cb_data)) + + # check if it is sane + self.assertIsNotNone(cb_data) + self.assertEqual(len(cb_data), 12) # True for TLSv1 + + # and compare with the peers version + s.write(b"CB tls-unique\n") + peer_data_repr = s.read().strip() + self.assertEqual(peer_data_repr, + repr(cb_data).encode("us-ascii")) # now, again - s = test_wrap_socket(socket.socket(), - server_side=False, - certfile=CERTFILE, - ca_certs=CERTFILE, - cert_reqs=ssl.CERT_NONE, - ssl_version=ssl.PROTOCOL_TLS_CLIENT) - s.connect((HOST, server.port)) - new_cb_data = s.get_channel_binding("tls-unique") - if support.verbose: - sys.stdout.write(" got another channel binding data: {0!r}\n" - .format(new_cb_data)) - # is it really unique - self.assertNotEqual(cb_data, new_cb_data) - self.assertIsNotNone(cb_data) - 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, - repr(new_cb_data).encode("us-ascii")) - s.close() + with client_context.wrap_socket( + socket.socket(), + server_hostname=hostname) as s: + s.connect((HOST, server.port)) + new_cb_data = s.get_channel_binding("tls-unique") + if support.verbose: + sys.stdout.write( + "got another channel binding data: {0!r}\n".format( + new_cb_data) + ) + # is it really unique + self.assertNotEqual(cb_data, new_cb_data) + self.assertIsNotNone(cb_data) + 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, + repr(new_cb_data).encode("us-ascii")) def test_compression(self): client_context, server_context, hostname = testing_context() @@ -3528,8 +3550,11 @@ def test_compression_disabled(self): def test_dh_params(self): # Check we can get a connection with ephemeral Diffie-Hellman client_context, server_context, hostname = testing_context() + # test scenario needs TLS <= 1.2 + client_context.options |= ssl.OP_NO_TLSv1_3 server_context.load_dh_params(DHFILE) server_context.set_ciphers("kEDH") + server_context.options |= ssl.OP_NO_TLSv1_3 stats = server_params_test(client_context, server_context, chatty=True, connectionchatty=True, sni_name=hostname) @@ -3539,9 +3564,11 @@ def test_dh_params(self): self.fail("Non-DH cipher: " + cipher[0]) @unittest.skipUnless(HAVE_SECP_CURVES, "needs secp384r1 curve support") + @unittest.skipIf(IS_OPENSSL_1_1_1, "TODO: Test doesn't work on 1.1.1") def test_ecdh_curve(self): # server secp384r1, client auto client_context, server_context, hostname = testing_context() + server_context.set_ecdh_curve("secp384r1") server_context.set_ciphers("ECDHE:!eNULL:!aNULL") server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 @@ -3572,7 +3599,7 @@ def test_ecdh_curve(self): pass else: # OpenSSL 1.0.2 does not fail although it should. - if IS_OPENSSL_1_1: + if IS_OPENSSL_1_1_0: self.fail("mismatch curve did not fail") def test_selected_alpn_protocol(self): @@ -3616,7 +3643,7 @@ def test_alpn_protocols(self): except ssl.SSLError as e: stats = e - if (expected is None and IS_OPENSSL_1_1 + if (expected is None and IS_OPENSSL_1_1_0 and ssl.OPENSSL_VERSION_INFO < (1, 1, 0, 6)): # OpenSSL 1.1.0 to 1.1.0e raises handshake error self.assertIsInstance(stats, ssl.SSLError) @@ -3823,6 +3850,8 @@ def test_sendfile(self): def test_session(self): client_context, server_context, hostname = testing_context() + # TODO: sessions aren't compatible with TLSv1.3 yet + client_context.options |= ssl.OP_NO_TLSv1_3 # first connection without session stats = server_params_test(client_context, server_context, @@ -3881,7 +3910,7 @@ def test_session_handling(self): client_context, server_context, hostname = testing_context() client_context2, _, _ = testing_context() - # TODO: session reuse does not work with TLS 1.3 + # TODO: session reuse does not work with TLSv1.3 client_context.options |= ssl.OP_NO_TLSv1_3 client_context2.options |= ssl.OP_NO_TLSv1_3 diff --git a/Misc/NEWS.d/next/Library/2018-02-25-13-06-21.bpo-32947.mqStVW.rst b/Misc/NEWS.d/next/Library/2018-02-25-13-06-21.bpo-32947.mqStVW.rst new file mode 100644 index 000000000000..28de360c3671 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-25-13-06-21.bpo-32947.mqStVW.rst @@ -0,0 +1,2 @@ +Add OP_ENABLE_MIDDLEBOX_COMPAT and test workaround for TLSv1.3 for future +compatibility with OpenSSL 1.1.1. diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 52695fe39c71..f50823e6947a 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -5681,6 +5681,10 @@ PyInit__ssl(void) PyModule_AddIntConstant(m, "OP_NO_COMPRESSION", SSL_OP_NO_COMPRESSION); #endif +#ifdef SSL_OP_ENABLE_MIDDLEBOX_COMPAT + PyModule_AddIntConstant(m, "OP_ENABLE_MIDDLEBOX_COMPAT", + SSL_OP_ENABLE_MIDDLEBOX_COMPAT); +#endif #ifdef X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT PyModule_AddIntConstant(m, "HOSTFLAG_ALWAYS_CHECK_SUBJECT", diff --git a/Tools/ssl/multissltests.py b/Tools/ssl/multissltests.py index 75874cfca4d0..70913c7203b3 100755 --- a/Tools/ssl/multissltests.py +++ b/Tools/ssl/multissltests.py @@ -41,24 +41,20 @@ log = logging.getLogger("multissl") OPENSSL_OLD_VERSIONS = [ - # "0.9.8zh", - # "1.0.1u", + "1.0.2", ] OPENSSL_RECENT_VERSIONS = [ - "1.0.2", - "1.0.2m", - "1.1.0g", + "1.0.2n", + "1.1.0g", + "1.1.1-pre1", ] LIBRESSL_OLD_VERSIONS = [ - # "2.3.10", - # "2.4.5", ] LIBRESSL_RECENT_VERSIONS = [ - "2.5.3", - "2.5.5", + # "2.6.5", ] # store files in ../multissl From webhook-mailer at python.org Tue Feb 27 03:17:54 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 27 Feb 2018 08:17:54 -0000 Subject: [Python-checkins] bpo-32947: OpenSSL 1.1.1-pre1 / TLS 1.3 fixes (GH-5663) Message-ID: https://github.com/python/cpython/commit/2614ed4c6e4b32eafb683f2378ed20e87d42976d commit: 2614ed4c6e4b32eafb683f2378ed20e87d42976d branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-27T00:17:49-08:00 summary: bpo-32947: OpenSSL 1.1.1-pre1 / TLS 1.3 fixes (GH-5663) * bpo-32947: OpenSSL 1.1.1-pre1 / TLS 1.3 fixes Misc fixes and workarounds for compatibility with OpenSSL 1.1.1-pre1 and TLS 1.3 support. With OpenSSL 1.1.1, Python negotiates TLS 1.3 by default. Some test cases only apply to TLS 1.2. Other tests currently fail because the threaded or async test servers stop after failure. I'm going to address these issues when OpenSSL 1.1.1 reaches beta. OpenSSL 1.1.1 has added a new option OP_ENABLE_MIDDLEBOX_COMPAT for TLS 1.3. The feature is enabled by default for maximum compatibility with broken middle boxes. Users should be able to disable the hack and CPython's test suite needs it to verify default options. Signed-off-by: Christian Heimes (cherry picked from commit 05d9fe32a1245b9a798e49e0c1eb91f110935b69) Co-authored-by: Christian Heimes files: A Misc/NEWS.d/next/Library/2018-02-25-13-06-21.bpo-32947.mqStVW.rst M Doc/library/ssl.rst M Doc/whatsnew/3.7.rst 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 Modules/_ssl.c M Tools/ssl/multissltests.py diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 7371024dce4e..5d5232eda30c 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -831,6 +831,15 @@ Constants .. versionadded:: 3.3 +.. data:: OP_ENABLE_MIDDLEBOX_COMPAT + + Send dummy Change Cipher Spec (CCS) messages in TLS 1.3 handshake to make + a TLS 1.3 connection look more like a TLS 1.2 connection. + + This option is only available with OpenSSL 1.1.1 and later. + + .. versionadded:: 3.8 + .. data:: OP_NO_COMPRESSION Disable compression on the SSL channel. This is useful if the application diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index ecb629336499..4fad279d45e7 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -661,6 +661,9 @@ 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`, +:issue:`20995`, :issue:`29136`, and :issue:`30622`) string ------ diff --git a/Lib/test/test_asyncio/utils.py b/Lib/test/test_asyncio/utils.py index 96dfe2f85b4d..711085fde5c5 100644 --- a/Lib/test/test_asyncio/utils.py +++ b/Lib/test/test_asyncio/utils.py @@ -74,6 +74,8 @@ 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 32aab047df85..1a8e2f91d386 100644 --- a/Lib/test/test_ftplib.py +++ b/Lib/test/test_ftplib.py @@ -312,6 +312,8 @@ 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, @@ -908,6 +910,8 @@ 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, @@ -940,6 +944,8 @@ 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) diff --git a/Lib/test/test_poplib.py b/Lib/test/test_poplib.py index 4d7a4394086a..fd0db798ee43 100644 --- a/Lib/test/test_poplib.py +++ b/Lib/test/test_poplib.py @@ -153,6 +153,8 @@ 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, @@ -356,6 +358,8 @@ 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) @@ -396,6 +400,8 @@ 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, diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 3b34fc0e0033..d978a9e1b0fe 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -30,7 +30,8 @@ PROTOCOLS = sorted(ssl._PROTOCOL_NAMES) HOST = support.HOST IS_LIBRESSL = ssl.OPENSSL_VERSION.startswith('LibreSSL') -IS_OPENSSL_1_1 = not IS_LIBRESSL and ssl.OPENSSL_VERSION_INFO >= (1, 1, 0) +IS_OPENSSL_1_1_0 = not IS_LIBRESSL and ssl.OPENSSL_VERSION_INFO >= (1, 1, 0) +IS_OPENSSL_1_1_1 = not IS_LIBRESSL and ssl.OPENSSL_VERSION_INFO >= (1, 1, 1) PY_SSL_DEFAULT_CIPHERS = sysconfig.get_config_var('PY_SSL_DEFAULT_CIPHERS') def data_file(*name): @@ -54,6 +55,7 @@ def data_file(*name): BYTES_CAPATH = os.fsencode(CAPATH) CAFILE_NEURONIO = data_file("capath", "4e1295a3.0") CAFILE_CACERT = data_file("capath", "5ed36f99.0") +WRONG_CERT = data_file("wrongcert.pem") CERTFILE_INFO = { 'issuer': ((('countryName', 'XY'),), @@ -124,6 +126,7 @@ def data_file(*name): OP_SINGLE_DH_USE = getattr(ssl, "OP_SINGLE_DH_USE", 0) OP_SINGLE_ECDH_USE = getattr(ssl, "OP_SINGLE_ECDH_USE", 0) OP_CIPHER_SERVER_PREFERENCE = getattr(ssl, "OP_CIPHER_SERVER_PREFERENCE", 0) +OP_ENABLE_MIDDLEBOX_COMPAT = getattr(ssl, "OP_ENABLE_MIDDLEBOX_COMPAT", 0) def handle_error(prefix): @@ -232,6 +235,7 @@ def testing_context(server_cert=SIGNED_CERTFILE): server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) server_context.load_cert_chain(server_cert) + client_context.load_verify_locations(SIGNING_CA) return client_context, server_context, hostname @@ -1016,7 +1020,8 @@ def test_options(self): default = (ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3) # SSLContext also enables these by default default |= (OP_NO_COMPRESSION | OP_CIPHER_SERVER_PREFERENCE | - OP_SINGLE_DH_USE | OP_SINGLE_ECDH_USE) + OP_SINGLE_DH_USE | OP_SINGLE_ECDH_USE | + OP_ENABLE_MIDDLEBOX_COMPAT) self.assertEqual(default, ctx.options) ctx.options |= ssl.OP_NO_TLSv1 self.assertEqual(default | ssl.OP_NO_TLSv1, ctx.options) @@ -1778,6 +1783,8 @@ 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) @@ -1787,6 +1794,8 @@ 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) @@ -2629,7 +2638,10 @@ 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('ECDHE:ECDSA:!NULL:!aRSA') + client_context.set_ciphers( + 'TLS13-AES-128-GCM-SHA256:TLS13-CHACHA20-POLY1305-SHA256:' + 'ECDHE:ECDSA:!NULL:!aRSA' + ) hostname = SIGNED_CERTFILE_ECC_HOSTNAME server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) @@ -2650,6 +2662,9 @@ def test_ecc_cert(self): def test_dual_rsa_ecc(self): client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) client_context.load_verify_locations(SIGNING_CA) + # TODO: fix TLSv1.3 once SSLContext can restrict signature + # algorithms. + client_context.options |= ssl.OP_NO_TLSv1_3 # only ECDSA certs client_context.set_ciphers('ECDHE:ECDSA:!NULL:!aRSA') hostname = SIGNED_CERTFILE_ECC_HOSTNAME @@ -2676,6 +2691,8 @@ 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 @@ -2738,15 +2755,22 @@ def test_wrong_cert(self): Launch a server with CERT_REQUIRED, and check that trying to connect to it with a wrong client certificate fails. """ - certfile = os.path.join(os.path.dirname(__file__) or os.curdir, - "wrongcert.pem") - server = ThreadedEchoServer(CERTFILE, - certreqs=ssl.CERT_REQUIRED, - cacerts=CERTFILE, chatty=False, - connectionchatty=False) + client_context, server_context, hostname = testing_context() + # load client cert + 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 + + server = ThreadedEchoServer( + context=server_context, chatty=True, connectionchatty=True, + ) + with server, \ - socket.socket() as sock, \ - test_wrap_socket(sock, certfile=certfile) as s: + client_context.wrap_socket(socket.socket(), + server_hostname=hostname) as s: try: # Expect either an SSL error about the server rejecting # the connection, or a low-level connection reset (which @@ -3400,7 +3424,9 @@ 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, 0, 2): + if ssl.OPENSSL_VERSION_INFO >= (1, 1, 1): + self.assertEqual(s.version(), 'TLSv1.3') + elif ssl.OPENSSL_VERSION_INFO >= (1, 0, 2): self.assertEqual(s.version(), 'TLSv1.2') else: # 0.9.8 to 1.0.1 self.assertIn(s.version(), ('TLSv1', 'TLSv1.2')) @@ -3412,18 +3438,18 @@ def test_version_basic(self): def test_tls1_3(self): context = ssl.SSLContext(ssl.PROTOCOL_TLS) context.load_cert_chain(CERTFILE) - # disable all but TLS 1.3 context.options |= ( ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 | ssl.OP_NO_TLSv1_2 ) with ThreadedEchoServer(context=context) as server: with context.wrap_socket(socket.socket()) as s: s.connect((HOST, server.port)) - self.assertIn(s.cipher()[0], [ + self.assertIn(s.cipher()[0], { 'TLS13-AES-256-GCM-SHA384', 'TLS13-CHACHA20-POLY1305-SHA256', 'TLS13-AES-128-GCM-SHA256', - ]) + }) + self.assertEqual(s.version(), 'TLSv1.3') @unittest.skipUnless(ssl.HAS_ECDH, "test requires ECDH-enabled OpenSSL") def test_default_ecdh_curve(self): @@ -3452,58 +3478,54 @@ def test_tls_unique_channel_binding(self): if support.verbose: sys.stdout.write("\n") - server = ThreadedEchoServer(CERTFILE, - certreqs=ssl.CERT_NONE, - ssl_version=ssl.PROTOCOL_TLS_SERVER, - cacerts=CERTFILE, + 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, connectionchatty=False) + with server: - s = test_wrap_socket(socket.socket(), - server_side=False, - certfile=CERTFILE, - ca_certs=CERTFILE, - cert_reqs=ssl.CERT_NONE, - ssl_version=ssl.PROTOCOL_TLS_CLIENT) - s.connect((HOST, server.port)) - # get the data - cb_data = s.get_channel_binding("tls-unique") - if support.verbose: - sys.stdout.write(" got channel binding data: {0!r}\n" - .format(cb_data)) - - # check if it is sane - self.assertIsNotNone(cb_data) - self.assertEqual(len(cb_data), 12) # True for TLSv1 - - # and compare with the peers version - s.write(b"CB tls-unique\n") - peer_data_repr = s.read().strip() - self.assertEqual(peer_data_repr, - repr(cb_data).encode("us-ascii")) - s.close() + with client_context.wrap_socket( + socket.socket(), + server_hostname=hostname) as s: + s.connect((HOST, server.port)) + # get the data + cb_data = s.get_channel_binding("tls-unique") + if support.verbose: + sys.stdout.write( + " got channel binding data: {0!r}\n".format(cb_data)) + + # check if it is sane + self.assertIsNotNone(cb_data) + self.assertEqual(len(cb_data), 12) # True for TLSv1 + + # and compare with the peers version + s.write(b"CB tls-unique\n") + peer_data_repr = s.read().strip() + self.assertEqual(peer_data_repr, + repr(cb_data).encode("us-ascii")) # now, again - s = test_wrap_socket(socket.socket(), - server_side=False, - certfile=CERTFILE, - ca_certs=CERTFILE, - cert_reqs=ssl.CERT_NONE, - ssl_version=ssl.PROTOCOL_TLS_CLIENT) - s.connect((HOST, server.port)) - new_cb_data = s.get_channel_binding("tls-unique") - if support.verbose: - sys.stdout.write(" got another channel binding data: {0!r}\n" - .format(new_cb_data)) - # is it really unique - self.assertNotEqual(cb_data, new_cb_data) - self.assertIsNotNone(cb_data) - 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, - repr(new_cb_data).encode("us-ascii")) - s.close() + with client_context.wrap_socket( + socket.socket(), + server_hostname=hostname) as s: + s.connect((HOST, server.port)) + new_cb_data = s.get_channel_binding("tls-unique") + if support.verbose: + sys.stdout.write( + "got another channel binding data: {0!r}\n".format( + new_cb_data) + ) + # is it really unique + self.assertNotEqual(cb_data, new_cb_data) + self.assertIsNotNone(cb_data) + 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, + repr(new_cb_data).encode("us-ascii")) def test_compression(self): client_context, server_context, hostname = testing_context() @@ -3528,8 +3550,11 @@ def test_compression_disabled(self): def test_dh_params(self): # Check we can get a connection with ephemeral Diffie-Hellman client_context, server_context, hostname = testing_context() + # test scenario needs TLS <= 1.2 + client_context.options |= ssl.OP_NO_TLSv1_3 server_context.load_dh_params(DHFILE) server_context.set_ciphers("kEDH") + server_context.options |= ssl.OP_NO_TLSv1_3 stats = server_params_test(client_context, server_context, chatty=True, connectionchatty=True, sni_name=hostname) @@ -3539,9 +3564,11 @@ def test_dh_params(self): self.fail("Non-DH cipher: " + cipher[0]) @unittest.skipUnless(HAVE_SECP_CURVES, "needs secp384r1 curve support") + @unittest.skipIf(IS_OPENSSL_1_1_1, "TODO: Test doesn't work on 1.1.1") def test_ecdh_curve(self): # server secp384r1, client auto client_context, server_context, hostname = testing_context() + server_context.set_ecdh_curve("secp384r1") server_context.set_ciphers("ECDHE:!eNULL:!aNULL") server_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 @@ -3572,7 +3599,7 @@ def test_ecdh_curve(self): pass else: # OpenSSL 1.0.2 does not fail although it should. - if IS_OPENSSL_1_1: + if IS_OPENSSL_1_1_0: self.fail("mismatch curve did not fail") def test_selected_alpn_protocol(self): @@ -3616,7 +3643,7 @@ def test_alpn_protocols(self): except ssl.SSLError as e: stats = e - if (expected is None and IS_OPENSSL_1_1 + if (expected is None and IS_OPENSSL_1_1_0 and ssl.OPENSSL_VERSION_INFO < (1, 1, 0, 6)): # OpenSSL 1.1.0 to 1.1.0e raises handshake error self.assertIsInstance(stats, ssl.SSLError) @@ -3823,6 +3850,8 @@ def test_sendfile(self): def test_session(self): client_context, server_context, hostname = testing_context() + # TODO: sessions aren't compatible with TLSv1.3 yet + client_context.options |= ssl.OP_NO_TLSv1_3 # first connection without session stats = server_params_test(client_context, server_context, @@ -3881,7 +3910,7 @@ def test_session_handling(self): client_context, server_context, hostname = testing_context() client_context2, _, _ = testing_context() - # TODO: session reuse does not work with TLS 1.3 + # TODO: session reuse does not work with TLSv1.3 client_context.options |= ssl.OP_NO_TLSv1_3 client_context2.options |= ssl.OP_NO_TLSv1_3 diff --git a/Misc/NEWS.d/next/Library/2018-02-25-13-06-21.bpo-32947.mqStVW.rst b/Misc/NEWS.d/next/Library/2018-02-25-13-06-21.bpo-32947.mqStVW.rst new file mode 100644 index 000000000000..28de360c3671 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-25-13-06-21.bpo-32947.mqStVW.rst @@ -0,0 +1,2 @@ +Add OP_ENABLE_MIDDLEBOX_COMPAT and test workaround for TLSv1.3 for future +compatibility with OpenSSL 1.1.1. diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 52695fe39c71..f50823e6947a 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -5681,6 +5681,10 @@ PyInit__ssl(void) PyModule_AddIntConstant(m, "OP_NO_COMPRESSION", SSL_OP_NO_COMPRESSION); #endif +#ifdef SSL_OP_ENABLE_MIDDLEBOX_COMPAT + PyModule_AddIntConstant(m, "OP_ENABLE_MIDDLEBOX_COMPAT", + SSL_OP_ENABLE_MIDDLEBOX_COMPAT); +#endif #ifdef X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT PyModule_AddIntConstant(m, "HOSTFLAG_ALWAYS_CHECK_SUBJECT", diff --git a/Tools/ssl/multissltests.py b/Tools/ssl/multissltests.py index 75874cfca4d0..70913c7203b3 100755 --- a/Tools/ssl/multissltests.py +++ b/Tools/ssl/multissltests.py @@ -41,24 +41,20 @@ log = logging.getLogger("multissl") OPENSSL_OLD_VERSIONS = [ - # "0.9.8zh", - # "1.0.1u", + "1.0.2", ] OPENSSL_RECENT_VERSIONS = [ - "1.0.2", - "1.0.2m", - "1.1.0g", + "1.0.2n", + "1.1.0g", + "1.1.1-pre1", ] LIBRESSL_OLD_VERSIONS = [ - # "2.3.10", - # "2.4.5", ] LIBRESSL_RECENT_VERSIONS = [ - "2.5.3", - "2.5.5", + # "2.6.5", ] # store files in ../multissl From webhook-mailer at python.org Tue Feb 27 03:21:37 2018 From: webhook-mailer at python.org (Christian Heimes) Date: Tue, 27 Feb 2018 08:21:37 -0000 Subject: [Python-checkins] bpo-28124: deprecate ssl.wrap_socket() (#5888) Message-ID: https://github.com/python/cpython/commit/90f05a527c7d439f1d0cba80f2eb32e60ee20fc3 commit: 90f05a527c7d439f1d0cba80f2eb32e60ee20fc3 branch: master author: Christian Heimes committer: GitHub date: 2018-02-27T09:21:34+01:00 summary: bpo-28124: deprecate ssl.wrap_socket() (#5888) The ssl module function ssl.wrap_socket() has been de-emphasized and deprecated in favor of the more secure and efficient SSLContext.wrap_socket() method. Signed-off-by: Christian Heimes files: A Misc/NEWS.d/next/Documentation/2018-02-25-16-33-35.bpo-28124._uzkgq.rst M Doc/library/ssl.rst M Doc/whatsnew/3.7.rst diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 5d5232eda30c..4889a7130aae 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -59,6 +59,125 @@ by SSL sockets created through the :meth:`SSLContext.wrap_socket` method. Functions, Constants, and Exceptions ------------------------------------ + +Socket creation +^^^^^^^^^^^^^^^ + +Since Python 3.2 and 2.7.9, it is recommended to use the +:meth:`SSLContext.wrap_socket` of an :class:`SSLContext` instance to wrap +sockets as :class:`SSLSocket` objects. The helper functions +:func:`create_default_context` returns a new context with secure default +settings. The old :func:`wrap_socket` function is deprecated since it is +both inefficient and has no support for server name indication (SNI) and +hostname matching. + +Client socket example with default context and IPv4/IPv6 dual stack:: + + import socket + import ssl + + hostname = 'www.python.org' + context = ssl.create_default_context() + + with socket.create_connection((hostname, 443)) as sock: + with context.wrap_socket(sock, server_hostname=hostname) as ssock: + print(ssock.version()) + + +Client socket example with custom context and IPv4:: + + hostname = 'www.python.org' + # PROTOCOL_TLS_CLIENT requires valid cert chain and hostname + context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) + context.load_verify_locations('path/to/cabundle.pem') + + with socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) as sock: + with context.wrap_socket(sock, server_hostname=hostname) as ssock: + print(ssock.version()) + + +Server socket example listening on localhost IPv4:: + + context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) + context.load_cert_chain('/path/to/certchain.pem', '/path/to/private.key') + + with socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) as sock: + sock.bind(('127.0.0.1', 8443)) + sock.listen(5) + with context.wrap_socket(sock, server_side=True) as ssock: + conn, addr = ssock.accept() + ... + + +Context creation +^^^^^^^^^^^^^^^^ + +A convenience function helps create :class:`SSLContext` objects for common +purposes. + +.. function:: create_default_context(purpose=Purpose.SERVER_AUTH, cafile=None, capath=None, cadata=None) + + Return a new :class:`SSLContext` object with default settings for + the given *purpose*. The settings are chosen by the :mod:`ssl` module, + and usually represent a higher security level than when calling the + :class:`SSLContext` constructor directly. + + *cafile*, *capath*, *cadata* represent optional CA certificates to + trust for certificate verification, as in + :meth:`SSLContext.load_verify_locations`. If all three are + :const:`None`, this function can choose to trust the system's default + CA certificates instead. + + The settings are: :data:`PROTOCOL_TLS`, :data:`OP_NO_SSLv2`, and + :data:`OP_NO_SSLv3` with high encryption cipher suites without RC4 and + without unauthenticated cipher suites. Passing :data:`~Purpose.SERVER_AUTH` + as *purpose* sets :data:`~SSLContext.verify_mode` to :data:`CERT_REQUIRED` + and either loads CA certificates (when at least one of *cafile*, *capath* or + *cadata* is given) or uses :meth:`SSLContext.load_default_certs` to load + default CA certificates. + + .. note:: + The protocol, options, cipher and other settings may change to more + restrictive values anytime without prior deprecation. The values + represent a fair balance between compatibility and security. + + If your application needs specific settings, you should create a + :class:`SSLContext` and apply the settings yourself. + + .. note:: + If you find that when certain older clients or servers attempt to connect + with a :class:`SSLContext` created by this function that they get an error + stating "Protocol or cipher suite mismatch", it may be that they only + support SSL3.0 which this function excludes using the + :data:`OP_NO_SSLv3`. SSL3.0 is widely considered to be `completely broken + `_. If you still wish to continue to + use this function but still allow SSL 3.0 connections you can re-enable + them using:: + + ctx = ssl.create_default_context(Purpose.CLIENT_AUTH) + ctx.options &= ~ssl.OP_NO_SSLv3 + + .. versionadded:: 3.4 + + .. versionchanged:: 3.4.4 + + RC4 was dropped from the default cipher string. + + .. versionchanged:: 3.6 + + ChaCha20/Poly1305 was added to the default cipher string. + + 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 +^^^^^^^^^^ + .. exception:: SSLError Raised to signal an error from the underlying SSL implementation @@ -152,173 +271,6 @@ Functions, Constants, and Exceptions The exception is now an alias for :exc:`SSLCertVerificationError`. -Socket creation -^^^^^^^^^^^^^^^ - -The following function allows for standalone socket creation. Starting from -Python 3.2, it can be more flexible to use :meth:`SSLContext.wrap_socket` -instead. - -.. function:: wrap_socket(sock, keyfile=None, certfile=None, server_side=False, cert_reqs=CERT_NONE, ssl_version={see docs}, ca_certs=None, do_handshake_on_connect=True, suppress_ragged_eofs=True, ciphers=None) - - Takes an instance ``sock`` of :class:`socket.socket`, and returns an instance - of :class:`ssl.SSLSocket`, a subtype of :class:`socket.socket`, which wraps - the underlying socket in an SSL context. ``sock`` must be a - :data:`~socket.SOCK_STREAM` socket; other socket types are unsupported. - - For client-side sockets, the context construction is lazy; if the - underlying socket isn't connected yet, the context construction will be - performed after :meth:`connect` is called on the socket. For - server-side sockets, if the socket has no remote peer, it is assumed - to be a listening socket, and the server-side SSL wrapping is - automatically performed on client connections accepted via the - :meth:`accept` method. :func:`wrap_socket` may raise :exc:`SSLError`. - - The ``keyfile`` and ``certfile`` parameters specify optional files which - contain a certificate to be used to identify the local side of the - connection. See the discussion of :ref:`ssl-certificates` for more - information on how the certificate is stored in the ``certfile``. - - The parameter ``server_side`` is a boolean which identifies whether - server-side or client-side behavior is desired from this socket. - - The parameter ``cert_reqs`` specifies whether a certificate is required from - the other side of the connection, and whether it will be validated if - provided. It must be one of the three values :const:`CERT_NONE` - (certificates ignored), :const:`CERT_OPTIONAL` (not required, but validated - if provided), or :const:`CERT_REQUIRED` (required and validated). If the - value of this parameter is not :const:`CERT_NONE`, then the ``ca_certs`` - parameter must point to a file of CA certificates. - - The ``ca_certs`` file contains a set of concatenated "certification - authority" certificates, which are used to validate certificates passed from - the other end of the connection. See the discussion of - :ref:`ssl-certificates` for more information about how to arrange the - certificates in this file. - - The parameter ``ssl_version`` specifies which version of the SSL protocol to - use. Typically, the server chooses a particular protocol version, and the - client must adapt to the server's choice. Most of the versions are not - interoperable with the other versions. If not specified, the default is - :data:`PROTOCOL_TLS`; it provides the most compatibility with other - versions. - - Here's a table showing which versions in a client (down the side) can connect - to which versions in a server (along the top): - - .. table:: - - ======================== ============ ============ ============= ========= =========== =========== - *client* / **server** **SSLv2** **SSLv3** **TLS** [3]_ **TLSv1** **TLSv1.1** **TLSv1.2** - ------------------------ ------------ ------------ ------------- --------- ----------- ----------- - *SSLv2* yes no no [1]_ no no no - *SSLv3* no yes no [2]_ no no no - *TLS* (*SSLv23*) [3]_ no [1]_ no [2]_ yes yes yes yes - *TLSv1* no no yes yes no no - *TLSv1.1* no no yes no yes no - *TLSv1.2* no no yes no no yes - ======================== ============ ============ ============= ========= =========== =========== - - .. rubric:: Footnotes - .. [1] :class:`SSLContext` disables SSLv2 with :data:`OP_NO_SSLv2` by default. - .. [2] :class:`SSLContext` disables SSLv3 with :data:`OP_NO_SSLv3` by default. - .. [3] TLS 1.3 protocol will be available with :data:`PROTOCOL_TLS` in - OpenSSL >= 1.1.1. There is no dedicated PROTOCOL constant for just - TLS 1.3. - - .. note:: - - Which connections succeed will vary depending on the version of - OpenSSL. For example, before OpenSSL 1.0.0, an SSLv23 client - would always attempt SSLv2 connections. - - The *ciphers* parameter sets the available ciphers for this SSL object. - It should be a string in the `OpenSSL cipher list format - `_. - - The parameter ``do_handshake_on_connect`` specifies whether to do the SSL - handshake automatically after doing a :meth:`socket.connect`, or whether the - application program will call it explicitly, by invoking the - :meth:`SSLSocket.do_handshake` method. Calling - :meth:`SSLSocket.do_handshake` explicitly gives the program control over the - blocking behavior of the socket I/O involved in the handshake. - - The parameter ``suppress_ragged_eofs`` specifies how the - :meth:`SSLSocket.recv` method should signal unexpected EOF from the other end - of the connection. If specified as :const:`True` (the default), it returns a - normal EOF (an empty bytes object) in response to unexpected EOF errors - raised from the underlying socket; if :const:`False`, it will raise the - exceptions back to the caller. - - .. versionchanged:: 3.2 - New optional argument *ciphers*. - -Context creation -^^^^^^^^^^^^^^^^ - -A convenience function helps create :class:`SSLContext` objects for common -purposes. - -.. function:: create_default_context(purpose=Purpose.SERVER_AUTH, cafile=None, capath=None, cadata=None) - - Return a new :class:`SSLContext` object with default settings for - the given *purpose*. The settings are chosen by the :mod:`ssl` module, - and usually represent a higher security level than when calling the - :class:`SSLContext` constructor directly. - - *cafile*, *capath*, *cadata* represent optional CA certificates to - trust for certificate verification, as in - :meth:`SSLContext.load_verify_locations`. If all three are - :const:`None`, this function can choose to trust the system's default - CA certificates instead. - - The settings are: :data:`PROTOCOL_TLS`, :data:`OP_NO_SSLv2`, and - :data:`OP_NO_SSLv3` with high encryption cipher suites without RC4 and - without unauthenticated cipher suites. Passing :data:`~Purpose.SERVER_AUTH` - as *purpose* sets :data:`~SSLContext.verify_mode` to :data:`CERT_REQUIRED` - and either loads CA certificates (when at least one of *cafile*, *capath* or - *cadata* is given) or uses :meth:`SSLContext.load_default_certs` to load - default CA certificates. - - .. note:: - The protocol, options, cipher and other settings may change to more - restrictive values anytime without prior deprecation. The values - represent a fair balance between compatibility and security. - - If your application needs specific settings, you should create a - :class:`SSLContext` and apply the settings yourself. - - .. note:: - If you find that when certain older clients or servers attempt to connect - with a :class:`SSLContext` created by this function that they get an error - stating "Protocol or cipher suite mismatch", it may be that they only - support SSL3.0 which this function excludes using the - :data:`OP_NO_SSLv3`. SSL3.0 is widely considered to be `completely broken - `_. If you still wish to continue to - use this function but still allow SSL 3.0 connections you can re-enable - them using:: - - ctx = ssl.create_default_context(Purpose.CLIENT_AUTH) - ctx.options &= ~ssl.OP_NO_SSLv3 - - .. versionadded:: 3.4 - - .. versionchanged:: 3.4.4 - - RC4 was dropped from the default cipher string. - - .. versionchanged:: 3.6 - - ChaCha20/Poly1305 was added to the default cipher string. - - 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. - - Random generation ^^^^^^^^^^^^^^^^^ @@ -474,9 +426,10 @@ Certificate handling PEM-encoded string. If ``ssl_version`` is specified, uses that version of the SSL protocol to attempt to connect to the server. If ``ca_certs`` is specified, it should be a file containing a list of root certificates, the - same format as used for the same parameter in :func:`wrap_socket`. The call - will attempt to validate the server certificate against that set of root - certificates, and will fail if the validation attempt fails. + same format as used for the same parameter in + :meth:`SSLContext.wrap_socket`. The call will attempt to validate the + server certificate against that set of root certificates, and will fail + if the validation attempt fails. .. versionchanged:: 3.3 This function is now IPv6-compatible. @@ -552,6 +505,33 @@ Certificate handling .. versionadded:: 3.4 +.. function:: wrap_socket(sock, keyfile=None, certfile=None, \ + server_side=False, cert_reqs=CERT_NONE, ssl_version=PROTOCOL_TLS, \ + ca_certs=None, do_handshake_on_connect=True, \ + suppress_ragged_eofs=True, ciphers=None) + + Takes an instance ``sock`` of :class:`socket.socket`, and returns an instance + of :class:`ssl.SSLSocket`, a subtype of :class:`socket.socket`, which wraps + the underlying socket in an SSL context. ``sock`` must be a + :data:`~socket.SOCK_STREAM` socket; other socket types are unsupported. + + Internally, function creates a :class:`SSLContext` with protocol + *ssl_version* and :attr:`SSLContext.options` set to *cert_reqs*. If + parameters *keyfile*, *certfile*, *ca_certs* or *ciphers* are set, then + the values are passed to :meth:`SSLContext.load_cert_chain`, + :meth:`SSLContext.load_verify_locations`, and + :meth:`SSLContext.set_ciphers`. + + The arguments *server_side*, *do_handshake_on_connect*, and + *suppress_ragged_eofs* have the same meaning as + :meth:`SSLContext.wrap_socket`. + + .. deprecated:: 3.7 + + Since Python 3.2 and 2.7.9, it is recommended to use the + :meth:`SSLContext.wrap_socket` instead of :func:`wrap_socket`. The + top-level function is limited and creates an insecure client socket + without server name indication or hostname matching. Constants ^^^^^^^^^ @@ -1018,7 +998,7 @@ SSL Sockets the specification of normal, OS-level sockets. See especially the :ref:`notes on non-blocking sockets `. - Usually, :class:`SSLSocket` are not created directly, but using the + :class:`SSLSocket` are not created directly, but using the :meth:`SSLContext.wrap_socket` method. .. versionchanged:: 3.5 @@ -1257,7 +1237,7 @@ SSL sockets also have the following additional methods and attributes: .. attribute:: SSLSocket.context The :class:`SSLContext` object this SSL socket is tied to. If the SSL - socket was created using the top-level :func:`wrap_socket` function + socket was created using the deprecated :func:`wrap_socket` function (rather than :meth:`SSLContext.wrap_socket`), this is a custom context object created for this SSL socket. @@ -1310,9 +1290,36 @@ to speed up repeated connections from the same clients. .. class:: SSLContext(protocol=PROTOCOL_TLS) Create a new SSL context. You may pass *protocol* which must be one - of the ``PROTOCOL_*`` constants defined in this module. - :data:`PROTOCOL_TLS` is currently recommended for maximum - interoperability and default value. + of the ``PROTOCOL_*`` constants defined in this module. The parameter + specifies which version of the SSL protocol to use. Typically, the + server chooses a particular protocol version, and the client must adapt + to the server's choice. Most of the versions are not interoperable + with the other versions. If not specified, the default is + :data:`PROTOCOL_TLS`; it provides the most compatibility with other + versions. + + Here's a table showing which versions in a client (down the side) can connect + to which versions in a server (along the top): + + .. table:: + + ======================== ============ ============ ============= ========= =========== =========== + *client* / **server** **SSLv2** **SSLv3** **TLS** [3]_ **TLSv1** **TLSv1.1** **TLSv1.2** + ------------------------ ------------ ------------ ------------- --------- ----------- ----------- + *SSLv2* yes no no [1]_ no no no + *SSLv3* no yes no [2]_ no no no + *TLS* (*SSLv23*) [3]_ no [1]_ no [2]_ yes yes yes yes + *TLSv1* no no yes yes no no + *TLSv1.1* no no yes no yes no + *TLSv1.2* no no yes no no yes + ======================== ============ ============ ============= ========= =========== =========== + + .. rubric:: Footnotes + .. [1] :class:`SSLContext` disables SSLv2 with :data:`OP_NO_SSLv2` by default. + .. [2] :class:`SSLContext` disables SSLv3 with :data:`OP_NO_SSLv3` by default. + .. [3] TLS 1.3 protocol will be available with :data:`PROTOCOL_TLS` in + OpenSSL >= 1.1.1. There is no dedicated PROTOCOL constant for just + TLS 1.3. .. seealso:: :func:`create_default_context` lets the :mod:`ssl` module choose @@ -1645,14 +1652,21 @@ to speed up repeated connections from the same clients. server_hostname=None, session=None) Wrap an existing Python socket *sock* and return an instance of - :attr:`SSLContext.sslsocket_class` (default :class:`SSLSocket`). - *sock* must be a :data:`~socket.SOCK_STREAM` socket; other socket - types are unsupported. + :attr:`SSLContext.sslsocket_class` (default :class:`SSLSocket`). The + returned SSL socket is tied to the context, its settings and certificates. + *sock* must be a :data:`~socket.SOCK_STREAM` socket; other + socket types are unsupported. - The returned SSL socket is tied to the context, its settings and - certificates. The parameters *server_side*, *do_handshake_on_connect* - and *suppress_ragged_eofs* have the same meaning as in the top-level - :func:`wrap_socket` function. + The parameter ``server_side`` is a boolean which identifies whether + server-side or client-side behavior is desired from this socket. + + For client-side sockets, the context construction is lazy; if the + underlying socket isn't connected yet, the context construction will be + performed after :meth:`connect` is called on the socket. For + server-side sockets, if the socket has no remote peer, it is assumed + to be a listening socket, and the server-side SSL wrapping is + automatically performed on client connections accepted via the + :meth:`accept` method. The method may raise :exc:`SSLError`. On client connections, the optional parameter *server_hostname* specifies the hostname of the service which we are connecting to. This allows a @@ -1660,6 +1674,20 @@ to speed up repeated connections from the same clients. quite similarly to HTTP virtual hosts. Specifying *server_hostname* will raise a :exc:`ValueError` if *server_side* is true. + The parameter ``do_handshake_on_connect`` specifies whether to do the SSL + handshake automatically after doing a :meth:`socket.connect`, or whether the + application program will call it explicitly, by invoking the + :meth:`SSLSocket.do_handshake` method. Calling + :meth:`SSLSocket.do_handshake` explicitly gives the program control over the + blocking behavior of the socket I/O involved in the handshake. + + The parameter ``suppress_ragged_eofs`` specifies how the + :meth:`SSLSocket.recv` method should signal unexpected EOF from the other end + of the connection. If specified as :const:`True` (the default), it returns a + normal EOF (an empty bytes object) in response to unexpected EOF errors + raised from the underlying socket; if :const:`False`, it will raise the + exceptions back to the caller. + *session*, see :attr:`~SSLSocket.session`. .. versionchanged:: 3.5 diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 10aed52eb486..e25ff100a636 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -673,6 +673,11 @@ 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`) +:func:`~ssl.wrap_socket` is deprecated. Documentation has been updated to +recommend :meth:`~ssl.SSLContext.wrap_socket` instead. +(Contributed by Christian Heimes in :issue:`28124`.) + + string ------ diff --git a/Misc/NEWS.d/next/Documentation/2018-02-25-16-33-35.bpo-28124._uzkgq.rst b/Misc/NEWS.d/next/Documentation/2018-02-25-16-33-35.bpo-28124._uzkgq.rst new file mode 100644 index 000000000000..4f4ca001981d --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2018-02-25-16-33-35.bpo-28124._uzkgq.rst @@ -0,0 +1,3 @@ +The ssl module function ssl.wrap_socket() has been de-emphasized +and deprecated in favor of the more secure and efficient +SSLContext.wrap_socket() method. From solipsis at pitrou.net Tue Feb 27 04:10:28 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Tue, 27 Feb 2018 09:10:28 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=4 Message-ID: <20180227091028.1.FE62978F6A947D03@psf.io> results for 4243df51fe43 on branch "default" -------------------------------------------- test_collections leaked [7, 0, -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/reflogCYqzUc', '--timeout', '7200'] From webhook-mailer at python.org Tue Feb 27 04:17:33 2018 From: webhook-mailer at python.org (Christian Heimes) Date: Tue, 27 Feb 2018 09:17:33 -0000 Subject: [Python-checkins] bpo-32951: Disable SSLSocket/SSLObject constructor (#5864) Message-ID: https://github.com/python/cpython/commit/9d50ab563df6307cabbcc9883cb8c52c614b0f22 commit: 9d50ab563df6307cabbcc9883cb8c52c614b0f22 branch: master author: Christian Heimes committer: GitHub date: 2018-02-27T10:17:30+01:00 summary: bpo-32951: Disable SSLSocket/SSLObject constructor (#5864) Direct instantiation of SSLSocket and SSLObject objects is now prohibited. The constructors were never documented, tested, or designed as public constructors. The SSLSocket constructor had limitations. For example it was not possible to enabled hostname verification except was ssl_version=PROTOCOL_TLS_CLIENT with cert_reqs=CERT_REQUIRED. SSLContext.wrap_socket() and SSLContext.wrap_bio are the recommended API to construct SSLSocket and SSLObject instances. ssl.wrap_socket() is also deprecated. The only test case for direct instantiation was added a couple of days ago for IDNA testing. Signed-off-by: Christian Heimes files: A Misc/NEWS.d/next/Library/2018-02-25-18-22-01.bpo-32951.gHrCXq.rst M Doc/library/ssl.rst M Doc/whatsnew/3.7.rst M Lib/ssl.py M Lib/test/test_ssl.py diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 4889a7130aae..d18a505937a8 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -998,7 +998,7 @@ SSL Sockets the specification of normal, OS-level sockets. See especially the :ref:`notes on non-blocking sockets `. - :class:`SSLSocket` are not created directly, but using the + Instances of :class:`SSLSocket` must be created using the :meth:`SSLContext.wrap_socket` method. .. versionchanged:: 3.5 @@ -1013,6 +1013,11 @@ SSL Sockets It is deprecated to create a :class:`SSLSocket` instance directly, use :meth:`SSLContext.wrap_socket` to wrap a socket. + .. versionchanged:: 3.7 + :class:`SSLSocket` instances must to created with + :meth:`~SSLContext.wrap_socket`. In earlier versions, it was possible + to create instances directly. This was never documented or officially + supported. SSL sockets also have the following additional methods and attributes: @@ -2249,11 +2254,12 @@ provided. but does not provide any network IO itself. IO needs to be performed through separate "BIO" objects which are OpenSSL's IO abstraction layer. - An :class:`SSLObject` instance can be created using the - :meth:`~SSLContext.wrap_bio` method. This method will create the - :class:`SSLObject` instance and bind it to a pair of BIOs. The *incoming* - BIO is used to pass data from Python to the SSL protocol instance, while the - *outgoing* BIO is used to pass data the other way around. + This class has no public constructor. An :class:`SSLObject` instance + must be created using the :meth:`~SSLContext.wrap_bio` method. This + method will create the :class:`SSLObject` instance and bind it to a + pair of BIOs. The *incoming* BIO is used to pass data from Python to the + SSL protocol instance, while the *outgoing* BIO is used to pass data the + other way around. The following methods are available: @@ -2305,6 +2311,12 @@ provided. :meth:`~SSLContext.wrap_socket`. An :class:`SSLObject` is always created via an :class:`SSLContext`. + .. versionchanged:: 3.7 + :class:`SSLObject` instances must to created with + :meth:`~SSLContext.wrap_bio`. In earlier versions, it was possible to + create instances directly. This was never documented or officially + supported. + An SSLObject communicates with the outside world using memory buffers. The class :class:`MemoryBIO` provides a memory buffer that can be used for this purpose. It wraps an OpenSSL memory BIO (Basic IO) object: diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index e25ff100a636..2d62ffa5004c 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -677,6 +677,12 @@ OpenSSL 1.1.1. (Contributed by Christian Heimes in :issue:`32947`, recommend :meth:`~ssl.SSLContext.wrap_socket` instead. (Contributed by Christian Heimes in :issue:`28124`.) +: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 +:meth:`~ssl.SSLContext.wrap_socket` and :meth:`~ssl.SSLContext.wrap_bio`. +(Contributed by Christian Heimes in :issue:`32951`) + string ------ diff --git a/Lib/ssl.py b/Lib/ssl.py index 94ea35e358a3..75ebcc165a17 100644 --- a/Lib/ssl.py +++ b/Lib/ssl.py @@ -390,24 +390,24 @@ def wrap_socket(self, sock, server_side=False, server_hostname=None, session=None): # SSLSocket class handles server_hostname encoding before it calls # ctx._wrap_socket() - return self.sslsocket_class( + return self.sslsocket_class._create( sock=sock, server_side=server_side, do_handshake_on_connect=do_handshake_on_connect, suppress_ragged_eofs=suppress_ragged_eofs, server_hostname=server_hostname, - _context=self, - _session=session + context=self, + session=session ) def wrap_bio(self, incoming, outgoing, server_side=False, server_hostname=None, session=None): # Need to encode server_hostname here because _wrap_bio() can only # handle ASCII str. - return self.sslobject_class( + return self.sslobject_class._create( incoming, outgoing, server_side=server_side, server_hostname=self._encode_hostname(server_hostname), - session=session, _context=self, + session=session, context=self, ) def set_npn_protocols(self, npn_protocols): @@ -612,14 +612,23 @@ class SSLObject: * Any form of network IO incluging methods such as ``recv`` and ``send``. * The ``do_handshake_on_connect`` and ``suppress_ragged_eofs`` machinery. """ + def __init__(self, *args, **kwargs): + raise TypeError( + f"{self.__class__.__name__} does not have a public " + f"constructor. Instances are returned by SSLContext.wrap_bio()." + ) - def __init__(self, incoming, outgoing, server_side=False, - server_hostname=None, session=None, _context=None): - self._sslobj = _context._wrap_bio( + @classmethod + def _create(cls, incoming, outgoing, server_side=False, + server_hostname=None, session=None, context=None): + self = cls.__new__(cls) + sslobj = context._wrap_bio( incoming, outgoing, server_side=server_side, server_hostname=server_hostname, owner=self, session=session ) + self._sslobj = sslobj + return self @property def context(self): @@ -741,72 +750,48 @@ def version(self): class SSLSocket(socket): """This class implements a subtype of socket.socket that wraps the underlying OS socket in an SSL context when necessary, and - provides read and write methods over that channel.""" - - def __init__(self, sock=None, keyfile=None, certfile=None, - server_side=False, cert_reqs=CERT_NONE, - ssl_version=PROTOCOL_TLS, ca_certs=None, - do_handshake_on_connect=True, - family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None, - suppress_ragged_eofs=True, npn_protocols=None, ciphers=None, - server_hostname=None, - _context=None, _session=None): - - if _context: - self._context = _context - else: - if server_side and not certfile: - raise ValueError("certfile must be specified for server-side " - "operations") - if keyfile and not certfile: - raise ValueError("certfile must be specified") - if certfile and not keyfile: - keyfile = certfile - self._context = SSLContext(ssl_version) - self._context.verify_mode = cert_reqs - if ca_certs: - self._context.load_verify_locations(ca_certs) - if certfile: - self._context.load_cert_chain(certfile, keyfile) - if npn_protocols: - self._context.set_npn_protocols(npn_protocols) - if ciphers: - self._context.set_ciphers(ciphers) - self.keyfile = keyfile - self.certfile = certfile - self.cert_reqs = cert_reqs - self.ssl_version = ssl_version - self.ca_certs = ca_certs - self.ciphers = ciphers - # Can't use sock.type as other flags (such as SOCK_NONBLOCK) get - # mixed in. + provides read and write methods over that channel. """ + + def __init__(self, *args, **kwargs): + raise TypeError( + f"{self.__class__.__name__} does not have a public " + f"constructor. Instances are returned by " + f"SSLContext.wrap_socket()." + ) + + @classmethod + def _create(cls, sock, server_side=False, do_handshake_on_connect=True, + suppress_ragged_eofs=True, server_hostname=None, + context=None, session=None): if sock.getsockopt(SOL_SOCKET, SO_TYPE) != SOCK_STREAM: raise NotImplementedError("only stream sockets are supported") if server_side: if server_hostname: raise ValueError("server_hostname can only be specified " "in client mode") - if _session is not None: + if session is not None: raise ValueError("session can only be specified in " "client mode") - if self._context.check_hostname and not server_hostname: + if context.check_hostname and not server_hostname: raise ValueError("check_hostname requires server_hostname") - self._session = _session + + kwargs = dict( + family=sock.family, type=sock.type, proto=sock.proto, + fileno=sock.fileno() + ) + self = cls.__new__(cls, **kwargs) + super(SSLSocket, self).__init__(**kwargs) + self.settimeout(sock.gettimeout()) + sock.detach() + + self._context = context + self._session = session + self._closed = False + self._sslobj = None self.server_side = server_side - self.server_hostname = self._context._encode_hostname(server_hostname) + self.server_hostname = context._encode_hostname(server_hostname) self.do_handshake_on_connect = do_handshake_on_connect self.suppress_ragged_eofs = suppress_ragged_eofs - if sock is not None: - super().__init__(family=sock.family, - type=sock.type, - proto=sock.proto, - fileno=sock.fileno()) - self.settimeout(sock.gettimeout()) - sock.detach() - elif fileno is not None: - super().__init__(fileno=fileno) - else: - super().__init__(family=family, type=type, proto=proto) # See if we are connected try: @@ -818,8 +803,6 @@ def __init__(self, sock=None, keyfile=None, certfile=None, else: connected = True - self._closed = False - self._sslobj = None self._connected = connected if connected: # create the SSL object @@ -834,10 +817,10 @@ def __init__(self, sock=None, keyfile=None, certfile=None, # non-blocking raise ValueError("do_handshake_on_connect should not be specified for non-blocking sockets") self.do_handshake() - except (OSError, ValueError): self.close() raise + return self @property def context(self): @@ -1184,12 +1167,25 @@ def wrap_socket(sock, keyfile=None, certfile=None, do_handshake_on_connect=True, suppress_ragged_eofs=True, ciphers=None): - return SSLSocket(sock=sock, keyfile=keyfile, certfile=certfile, - server_side=server_side, cert_reqs=cert_reqs, - ssl_version=ssl_version, ca_certs=ca_certs, - do_handshake_on_connect=do_handshake_on_connect, - suppress_ragged_eofs=suppress_ragged_eofs, - ciphers=ciphers) + + if server_side and not certfile: + raise ValueError("certfile must be specified for server-side " + "operations") + if keyfile and not certfile: + raise ValueError("certfile must be specified") + context = SSLContext(ssl_version) + context.verify_mode = cert_reqs + if ca_certs: + context.load_verify_locations(ca_certs) + if certfile: + context.load_cert_chain(certfile, keyfile) + if ciphers: + context.set_ciphers(ciphers) + return context.wrap_socket( + sock=sock, server_side=server_side, + do_handshake_on_connect=do_handshake_on_connect, + suppress_ragged_eofs=suppress_ragged_eofs + ) # some utility functions diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index d978a9e1b0fe..ca2357e98e3e 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -263,6 +263,11 @@ def test_constants(self): ssl.OP_NO_TLSv1_2 self.assertEqual(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv23) + def test_private_init(self): + with self.assertRaisesRegex(TypeError, "public constructor"): + with socket.socket() as s: + ssl.SSLSocket(s) + def test_str_for_enums(self): # Make sure that the PROTOCOL_* constants have enum-like string # reprs. @@ -1657,6 +1662,13 @@ def test_error_types(self): self.assertRaises(TypeError, bio.write, 1) +class SSLObjectTests(unittest.TestCase): + def test_private_init(self): + bio = ssl.MemoryBIO() + with self.assertRaisesRegex(TypeError, "public constructor"): + ssl.SSLObject(bio, bio) + + class SimpleBackgroundTests(unittest.TestCase): """Tests that connect to a simple server running in the background""" @@ -2735,12 +2747,6 @@ def test_check_hostname_idn(self): self.assertEqual(s.server_hostname, expected_hostname) self.assertTrue(cert, "Can't get peer certificate.") - with ssl.SSLSocket(socket.socket(), - server_hostname=server_hostname) as s: - s.connect((HOST, server.port)) - s.getpeercert() - self.assertEqual(s.server_hostname, expected_hostname) - # incorrect hostname should raise an exception server = ThreadedEchoServer(context=server_context, chatty=True) with server: @@ -3999,7 +4005,7 @@ def test_main(verbose=False): tests = [ ContextTests, BasicSocketTests, SSLErrorTests, MemoryBIOTests, - SimpleBackgroundTests, ThreadedTests, + SSLObjectTests, SimpleBackgroundTests, ThreadedTests, ] if support.is_resource_enabled('network'): diff --git a/Misc/NEWS.d/next/Library/2018-02-25-18-22-01.bpo-32951.gHrCXq.rst b/Misc/NEWS.d/next/Library/2018-02-25-18-22-01.bpo-32951.gHrCXq.rst new file mode 100644 index 000000000000..9c038cf25979 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-25-18-22-01.bpo-32951.gHrCXq.rst @@ -0,0 +1,3 @@ +Direct instantiation of SSLSocket and SSLObject objects is now prohibited. +The constructors were never documented, tested, or designed as public +constructors. Users were suppose to use ssl.wrap_socket() or SSLContext. From webhook-mailer at python.org Tue Feb 27 04:45:33 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 27 Feb 2018 09:45:33 -0000 Subject: [Python-checkins] bpo-28124: deprecate ssl.wrap_socket() (GH-5888) Message-ID: https://github.com/python/cpython/commit/102d5204add249248d1a0fa1dd3f673e884b06b4 commit: 102d5204add249248d1a0fa1dd3f673e884b06b4 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-27T01:45:31-08:00 summary: bpo-28124: deprecate ssl.wrap_socket() (GH-5888) The ssl module function ssl.wrap_socket() has been de-emphasized and deprecated in favor of the more secure and efficient SSLContext.wrap_socket() method. Signed-off-by: Christian Heimes (cherry picked from commit 90f05a527c7d439f1d0cba80f2eb32e60ee20fc3) Co-authored-by: Christian Heimes files: A Misc/NEWS.d/next/Documentation/2018-02-25-16-33-35.bpo-28124._uzkgq.rst M Doc/library/ssl.rst M Doc/whatsnew/3.7.rst diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 5d5232eda30c..4889a7130aae 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -59,6 +59,125 @@ by SSL sockets created through the :meth:`SSLContext.wrap_socket` method. Functions, Constants, and Exceptions ------------------------------------ + +Socket creation +^^^^^^^^^^^^^^^ + +Since Python 3.2 and 2.7.9, it is recommended to use the +:meth:`SSLContext.wrap_socket` of an :class:`SSLContext` instance to wrap +sockets as :class:`SSLSocket` objects. The helper functions +:func:`create_default_context` returns a new context with secure default +settings. The old :func:`wrap_socket` function is deprecated since it is +both inefficient and has no support for server name indication (SNI) and +hostname matching. + +Client socket example with default context and IPv4/IPv6 dual stack:: + + import socket + import ssl + + hostname = 'www.python.org' + context = ssl.create_default_context() + + with socket.create_connection((hostname, 443)) as sock: + with context.wrap_socket(sock, server_hostname=hostname) as ssock: + print(ssock.version()) + + +Client socket example with custom context and IPv4:: + + hostname = 'www.python.org' + # PROTOCOL_TLS_CLIENT requires valid cert chain and hostname + context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) + context.load_verify_locations('path/to/cabundle.pem') + + with socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) as sock: + with context.wrap_socket(sock, server_hostname=hostname) as ssock: + print(ssock.version()) + + +Server socket example listening on localhost IPv4:: + + context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) + context.load_cert_chain('/path/to/certchain.pem', '/path/to/private.key') + + with socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) as sock: + sock.bind(('127.0.0.1', 8443)) + sock.listen(5) + with context.wrap_socket(sock, server_side=True) as ssock: + conn, addr = ssock.accept() + ... + + +Context creation +^^^^^^^^^^^^^^^^ + +A convenience function helps create :class:`SSLContext` objects for common +purposes. + +.. function:: create_default_context(purpose=Purpose.SERVER_AUTH, cafile=None, capath=None, cadata=None) + + Return a new :class:`SSLContext` object with default settings for + the given *purpose*. The settings are chosen by the :mod:`ssl` module, + and usually represent a higher security level than when calling the + :class:`SSLContext` constructor directly. + + *cafile*, *capath*, *cadata* represent optional CA certificates to + trust for certificate verification, as in + :meth:`SSLContext.load_verify_locations`. If all three are + :const:`None`, this function can choose to trust the system's default + CA certificates instead. + + The settings are: :data:`PROTOCOL_TLS`, :data:`OP_NO_SSLv2`, and + :data:`OP_NO_SSLv3` with high encryption cipher suites without RC4 and + without unauthenticated cipher suites. Passing :data:`~Purpose.SERVER_AUTH` + as *purpose* sets :data:`~SSLContext.verify_mode` to :data:`CERT_REQUIRED` + and either loads CA certificates (when at least one of *cafile*, *capath* or + *cadata* is given) or uses :meth:`SSLContext.load_default_certs` to load + default CA certificates. + + .. note:: + The protocol, options, cipher and other settings may change to more + restrictive values anytime without prior deprecation. The values + represent a fair balance between compatibility and security. + + If your application needs specific settings, you should create a + :class:`SSLContext` and apply the settings yourself. + + .. note:: + If you find that when certain older clients or servers attempt to connect + with a :class:`SSLContext` created by this function that they get an error + stating "Protocol or cipher suite mismatch", it may be that they only + support SSL3.0 which this function excludes using the + :data:`OP_NO_SSLv3`. SSL3.0 is widely considered to be `completely broken + `_. If you still wish to continue to + use this function but still allow SSL 3.0 connections you can re-enable + them using:: + + ctx = ssl.create_default_context(Purpose.CLIENT_AUTH) + ctx.options &= ~ssl.OP_NO_SSLv3 + + .. versionadded:: 3.4 + + .. versionchanged:: 3.4.4 + + RC4 was dropped from the default cipher string. + + .. versionchanged:: 3.6 + + ChaCha20/Poly1305 was added to the default cipher string. + + 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 +^^^^^^^^^^ + .. exception:: SSLError Raised to signal an error from the underlying SSL implementation @@ -152,173 +271,6 @@ Functions, Constants, and Exceptions The exception is now an alias for :exc:`SSLCertVerificationError`. -Socket creation -^^^^^^^^^^^^^^^ - -The following function allows for standalone socket creation. Starting from -Python 3.2, it can be more flexible to use :meth:`SSLContext.wrap_socket` -instead. - -.. function:: wrap_socket(sock, keyfile=None, certfile=None, server_side=False, cert_reqs=CERT_NONE, ssl_version={see docs}, ca_certs=None, do_handshake_on_connect=True, suppress_ragged_eofs=True, ciphers=None) - - Takes an instance ``sock`` of :class:`socket.socket`, and returns an instance - of :class:`ssl.SSLSocket`, a subtype of :class:`socket.socket`, which wraps - the underlying socket in an SSL context. ``sock`` must be a - :data:`~socket.SOCK_STREAM` socket; other socket types are unsupported. - - For client-side sockets, the context construction is lazy; if the - underlying socket isn't connected yet, the context construction will be - performed after :meth:`connect` is called on the socket. For - server-side sockets, if the socket has no remote peer, it is assumed - to be a listening socket, and the server-side SSL wrapping is - automatically performed on client connections accepted via the - :meth:`accept` method. :func:`wrap_socket` may raise :exc:`SSLError`. - - The ``keyfile`` and ``certfile`` parameters specify optional files which - contain a certificate to be used to identify the local side of the - connection. See the discussion of :ref:`ssl-certificates` for more - information on how the certificate is stored in the ``certfile``. - - The parameter ``server_side`` is a boolean which identifies whether - server-side or client-side behavior is desired from this socket. - - The parameter ``cert_reqs`` specifies whether a certificate is required from - the other side of the connection, and whether it will be validated if - provided. It must be one of the three values :const:`CERT_NONE` - (certificates ignored), :const:`CERT_OPTIONAL` (not required, but validated - if provided), or :const:`CERT_REQUIRED` (required and validated). If the - value of this parameter is not :const:`CERT_NONE`, then the ``ca_certs`` - parameter must point to a file of CA certificates. - - The ``ca_certs`` file contains a set of concatenated "certification - authority" certificates, which are used to validate certificates passed from - the other end of the connection. See the discussion of - :ref:`ssl-certificates` for more information about how to arrange the - certificates in this file. - - The parameter ``ssl_version`` specifies which version of the SSL protocol to - use. Typically, the server chooses a particular protocol version, and the - client must adapt to the server's choice. Most of the versions are not - interoperable with the other versions. If not specified, the default is - :data:`PROTOCOL_TLS`; it provides the most compatibility with other - versions. - - Here's a table showing which versions in a client (down the side) can connect - to which versions in a server (along the top): - - .. table:: - - ======================== ============ ============ ============= ========= =========== =========== - *client* / **server** **SSLv2** **SSLv3** **TLS** [3]_ **TLSv1** **TLSv1.1** **TLSv1.2** - ------------------------ ------------ ------------ ------------- --------- ----------- ----------- - *SSLv2* yes no no [1]_ no no no - *SSLv3* no yes no [2]_ no no no - *TLS* (*SSLv23*) [3]_ no [1]_ no [2]_ yes yes yes yes - *TLSv1* no no yes yes no no - *TLSv1.1* no no yes no yes no - *TLSv1.2* no no yes no no yes - ======================== ============ ============ ============= ========= =========== =========== - - .. rubric:: Footnotes - .. [1] :class:`SSLContext` disables SSLv2 with :data:`OP_NO_SSLv2` by default. - .. [2] :class:`SSLContext` disables SSLv3 with :data:`OP_NO_SSLv3` by default. - .. [3] TLS 1.3 protocol will be available with :data:`PROTOCOL_TLS` in - OpenSSL >= 1.1.1. There is no dedicated PROTOCOL constant for just - TLS 1.3. - - .. note:: - - Which connections succeed will vary depending on the version of - OpenSSL. For example, before OpenSSL 1.0.0, an SSLv23 client - would always attempt SSLv2 connections. - - The *ciphers* parameter sets the available ciphers for this SSL object. - It should be a string in the `OpenSSL cipher list format - `_. - - The parameter ``do_handshake_on_connect`` specifies whether to do the SSL - handshake automatically after doing a :meth:`socket.connect`, or whether the - application program will call it explicitly, by invoking the - :meth:`SSLSocket.do_handshake` method. Calling - :meth:`SSLSocket.do_handshake` explicitly gives the program control over the - blocking behavior of the socket I/O involved in the handshake. - - The parameter ``suppress_ragged_eofs`` specifies how the - :meth:`SSLSocket.recv` method should signal unexpected EOF from the other end - of the connection. If specified as :const:`True` (the default), it returns a - normal EOF (an empty bytes object) in response to unexpected EOF errors - raised from the underlying socket; if :const:`False`, it will raise the - exceptions back to the caller. - - .. versionchanged:: 3.2 - New optional argument *ciphers*. - -Context creation -^^^^^^^^^^^^^^^^ - -A convenience function helps create :class:`SSLContext` objects for common -purposes. - -.. function:: create_default_context(purpose=Purpose.SERVER_AUTH, cafile=None, capath=None, cadata=None) - - Return a new :class:`SSLContext` object with default settings for - the given *purpose*. The settings are chosen by the :mod:`ssl` module, - and usually represent a higher security level than when calling the - :class:`SSLContext` constructor directly. - - *cafile*, *capath*, *cadata* represent optional CA certificates to - trust for certificate verification, as in - :meth:`SSLContext.load_verify_locations`. If all three are - :const:`None`, this function can choose to trust the system's default - CA certificates instead. - - The settings are: :data:`PROTOCOL_TLS`, :data:`OP_NO_SSLv2`, and - :data:`OP_NO_SSLv3` with high encryption cipher suites without RC4 and - without unauthenticated cipher suites. Passing :data:`~Purpose.SERVER_AUTH` - as *purpose* sets :data:`~SSLContext.verify_mode` to :data:`CERT_REQUIRED` - and either loads CA certificates (when at least one of *cafile*, *capath* or - *cadata* is given) or uses :meth:`SSLContext.load_default_certs` to load - default CA certificates. - - .. note:: - The protocol, options, cipher and other settings may change to more - restrictive values anytime without prior deprecation. The values - represent a fair balance between compatibility and security. - - If your application needs specific settings, you should create a - :class:`SSLContext` and apply the settings yourself. - - .. note:: - If you find that when certain older clients or servers attempt to connect - with a :class:`SSLContext` created by this function that they get an error - stating "Protocol or cipher suite mismatch", it may be that they only - support SSL3.0 which this function excludes using the - :data:`OP_NO_SSLv3`. SSL3.0 is widely considered to be `completely broken - `_. If you still wish to continue to - use this function but still allow SSL 3.0 connections you can re-enable - them using:: - - ctx = ssl.create_default_context(Purpose.CLIENT_AUTH) - ctx.options &= ~ssl.OP_NO_SSLv3 - - .. versionadded:: 3.4 - - .. versionchanged:: 3.4.4 - - RC4 was dropped from the default cipher string. - - .. versionchanged:: 3.6 - - ChaCha20/Poly1305 was added to the default cipher string. - - 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. - - Random generation ^^^^^^^^^^^^^^^^^ @@ -474,9 +426,10 @@ Certificate handling PEM-encoded string. If ``ssl_version`` is specified, uses that version of the SSL protocol to attempt to connect to the server. If ``ca_certs`` is specified, it should be a file containing a list of root certificates, the - same format as used for the same parameter in :func:`wrap_socket`. The call - will attempt to validate the server certificate against that set of root - certificates, and will fail if the validation attempt fails. + same format as used for the same parameter in + :meth:`SSLContext.wrap_socket`. The call will attempt to validate the + server certificate against that set of root certificates, and will fail + if the validation attempt fails. .. versionchanged:: 3.3 This function is now IPv6-compatible. @@ -552,6 +505,33 @@ Certificate handling .. versionadded:: 3.4 +.. function:: wrap_socket(sock, keyfile=None, certfile=None, \ + server_side=False, cert_reqs=CERT_NONE, ssl_version=PROTOCOL_TLS, \ + ca_certs=None, do_handshake_on_connect=True, \ + suppress_ragged_eofs=True, ciphers=None) + + Takes an instance ``sock`` of :class:`socket.socket`, and returns an instance + of :class:`ssl.SSLSocket`, a subtype of :class:`socket.socket`, which wraps + the underlying socket in an SSL context. ``sock`` must be a + :data:`~socket.SOCK_STREAM` socket; other socket types are unsupported. + + Internally, function creates a :class:`SSLContext` with protocol + *ssl_version* and :attr:`SSLContext.options` set to *cert_reqs*. If + parameters *keyfile*, *certfile*, *ca_certs* or *ciphers* are set, then + the values are passed to :meth:`SSLContext.load_cert_chain`, + :meth:`SSLContext.load_verify_locations`, and + :meth:`SSLContext.set_ciphers`. + + The arguments *server_side*, *do_handshake_on_connect*, and + *suppress_ragged_eofs* have the same meaning as + :meth:`SSLContext.wrap_socket`. + + .. deprecated:: 3.7 + + Since Python 3.2 and 2.7.9, it is recommended to use the + :meth:`SSLContext.wrap_socket` instead of :func:`wrap_socket`. The + top-level function is limited and creates an insecure client socket + without server name indication or hostname matching. Constants ^^^^^^^^^ @@ -1018,7 +998,7 @@ SSL Sockets the specification of normal, OS-level sockets. See especially the :ref:`notes on non-blocking sockets `. - Usually, :class:`SSLSocket` are not created directly, but using the + :class:`SSLSocket` are not created directly, but using the :meth:`SSLContext.wrap_socket` method. .. versionchanged:: 3.5 @@ -1257,7 +1237,7 @@ SSL sockets also have the following additional methods and attributes: .. attribute:: SSLSocket.context The :class:`SSLContext` object this SSL socket is tied to. If the SSL - socket was created using the top-level :func:`wrap_socket` function + socket was created using the deprecated :func:`wrap_socket` function (rather than :meth:`SSLContext.wrap_socket`), this is a custom context object created for this SSL socket. @@ -1310,9 +1290,36 @@ to speed up repeated connections from the same clients. .. class:: SSLContext(protocol=PROTOCOL_TLS) Create a new SSL context. You may pass *protocol* which must be one - of the ``PROTOCOL_*`` constants defined in this module. - :data:`PROTOCOL_TLS` is currently recommended for maximum - interoperability and default value. + of the ``PROTOCOL_*`` constants defined in this module. The parameter + specifies which version of the SSL protocol to use. Typically, the + server chooses a particular protocol version, and the client must adapt + to the server's choice. Most of the versions are not interoperable + with the other versions. If not specified, the default is + :data:`PROTOCOL_TLS`; it provides the most compatibility with other + versions. + + Here's a table showing which versions in a client (down the side) can connect + to which versions in a server (along the top): + + .. table:: + + ======================== ============ ============ ============= ========= =========== =========== + *client* / **server** **SSLv2** **SSLv3** **TLS** [3]_ **TLSv1** **TLSv1.1** **TLSv1.2** + ------------------------ ------------ ------------ ------------- --------- ----------- ----------- + *SSLv2* yes no no [1]_ no no no + *SSLv3* no yes no [2]_ no no no + *TLS* (*SSLv23*) [3]_ no [1]_ no [2]_ yes yes yes yes + *TLSv1* no no yes yes no no + *TLSv1.1* no no yes no yes no + *TLSv1.2* no no yes no no yes + ======================== ============ ============ ============= ========= =========== =========== + + .. rubric:: Footnotes + .. [1] :class:`SSLContext` disables SSLv2 with :data:`OP_NO_SSLv2` by default. + .. [2] :class:`SSLContext` disables SSLv3 with :data:`OP_NO_SSLv3` by default. + .. [3] TLS 1.3 protocol will be available with :data:`PROTOCOL_TLS` in + OpenSSL >= 1.1.1. There is no dedicated PROTOCOL constant for just + TLS 1.3. .. seealso:: :func:`create_default_context` lets the :mod:`ssl` module choose @@ -1645,14 +1652,21 @@ to speed up repeated connections from the same clients. server_hostname=None, session=None) Wrap an existing Python socket *sock* and return an instance of - :attr:`SSLContext.sslsocket_class` (default :class:`SSLSocket`). - *sock* must be a :data:`~socket.SOCK_STREAM` socket; other socket - types are unsupported. + :attr:`SSLContext.sslsocket_class` (default :class:`SSLSocket`). The + returned SSL socket is tied to the context, its settings and certificates. + *sock* must be a :data:`~socket.SOCK_STREAM` socket; other + socket types are unsupported. - The returned SSL socket is tied to the context, its settings and - certificates. The parameters *server_side*, *do_handshake_on_connect* - and *suppress_ragged_eofs* have the same meaning as in the top-level - :func:`wrap_socket` function. + The parameter ``server_side`` is a boolean which identifies whether + server-side or client-side behavior is desired from this socket. + + For client-side sockets, the context construction is lazy; if the + underlying socket isn't connected yet, the context construction will be + performed after :meth:`connect` is called on the socket. For + server-side sockets, if the socket has no remote peer, it is assumed + to be a listening socket, and the server-side SSL wrapping is + automatically performed on client connections accepted via the + :meth:`accept` method. The method may raise :exc:`SSLError`. On client connections, the optional parameter *server_hostname* specifies the hostname of the service which we are connecting to. This allows a @@ -1660,6 +1674,20 @@ to speed up repeated connections from the same clients. quite similarly to HTTP virtual hosts. Specifying *server_hostname* will raise a :exc:`ValueError` if *server_side* is true. + The parameter ``do_handshake_on_connect`` specifies whether to do the SSL + handshake automatically after doing a :meth:`socket.connect`, or whether the + application program will call it explicitly, by invoking the + :meth:`SSLSocket.do_handshake` method. Calling + :meth:`SSLSocket.do_handshake` explicitly gives the program control over the + blocking behavior of the socket I/O involved in the handshake. + + The parameter ``suppress_ragged_eofs`` specifies how the + :meth:`SSLSocket.recv` method should signal unexpected EOF from the other end + of the connection. If specified as :const:`True` (the default), it returns a + normal EOF (an empty bytes object) in response to unexpected EOF errors + raised from the underlying socket; if :const:`False`, it will raise the + exceptions back to the caller. + *session*, see :attr:`~SSLSocket.session`. .. versionchanged:: 3.5 diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 4fad279d45e7..048e87dda12f 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -665,6 +665,11 @@ 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`) +:func:`~ssl.wrap_socket` is deprecated. Documentation has been updated to +recommend :meth:`~ssl.SSLContext.wrap_socket` instead. +(Contributed by Christian Heimes in :issue:`28124`.) + + string ------ diff --git a/Misc/NEWS.d/next/Documentation/2018-02-25-16-33-35.bpo-28124._uzkgq.rst b/Misc/NEWS.d/next/Documentation/2018-02-25-16-33-35.bpo-28124._uzkgq.rst new file mode 100644 index 000000000000..4f4ca001981d --- /dev/null +++ b/Misc/NEWS.d/next/Documentation/2018-02-25-16-33-35.bpo-28124._uzkgq.rst @@ -0,0 +1,3 @@ +The ssl module function ssl.wrap_socket() has been de-emphasized +and deprecated in favor of the more secure and efficient +SSLContext.wrap_socket() method. From webhook-mailer at python.org Tue Feb 27 05:17:35 2018 From: webhook-mailer at python.org (Christian Heimes) Date: Tue, 27 Feb 2018 10:17:35 -0000 Subject: [Python-checkins] [3.7] bpo-32951: Disable SSLSocket/SSLObject constructor (GH-5864) (#5925) Message-ID: https://github.com/python/cpython/commit/89c2051a554d2053ac87b0adbf11ed0f1bb65db3 commit: 89c2051a554d2053ac87b0adbf11ed0f1bb65db3 branch: 3.7 author: Christian Heimes committer: GitHub date: 2018-02-27T11:17:32+01:00 summary: [3.7] bpo-32951: Disable SSLSocket/SSLObject constructor (GH-5864) (#5925) Direct instantiation of SSLSocket and SSLObject objects is now prohibited. The constructors were never documented, tested, or designed as public constructors. The SSLSocket constructor had limitations. For example it was not possible to enabled hostname verification except was ssl_version=PROTOCOL_TLS_CLIENT with cert_reqs=CERT_REQUIRED. SSLContext.wrap_socket() and SSLContext.wrap_bio are the recommended API to construct SSLSocket and SSLObject instances. ssl.wrap_socket() is also deprecated. The only test case for direct instantiation was added a couple of days ago for IDNA testing. Signed-off-by: Christian Heimes (cherry picked from commit 9d50ab563df6307cabbcc9883cb8c52c614b0f22) Co-authored-by: Christian Heimes files: A Misc/NEWS.d/next/Library/2018-02-25-18-22-01.bpo-32951.gHrCXq.rst M Doc/library/ssl.rst M Doc/whatsnew/3.7.rst M Lib/ssl.py M Lib/test/test_ssl.py diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 4889a7130aae..d18a505937a8 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -998,7 +998,7 @@ SSL Sockets the specification of normal, OS-level sockets. See especially the :ref:`notes on non-blocking sockets `. - :class:`SSLSocket` are not created directly, but using the + Instances of :class:`SSLSocket` must be created using the :meth:`SSLContext.wrap_socket` method. .. versionchanged:: 3.5 @@ -1013,6 +1013,11 @@ SSL Sockets It is deprecated to create a :class:`SSLSocket` instance directly, use :meth:`SSLContext.wrap_socket` to wrap a socket. + .. versionchanged:: 3.7 + :class:`SSLSocket` instances must to created with + :meth:`~SSLContext.wrap_socket`. In earlier versions, it was possible + to create instances directly. This was never documented or officially + supported. SSL sockets also have the following additional methods and attributes: @@ -2249,11 +2254,12 @@ provided. but does not provide any network IO itself. IO needs to be performed through separate "BIO" objects which are OpenSSL's IO abstraction layer. - An :class:`SSLObject` instance can be created using the - :meth:`~SSLContext.wrap_bio` method. This method will create the - :class:`SSLObject` instance and bind it to a pair of BIOs. The *incoming* - BIO is used to pass data from Python to the SSL protocol instance, while the - *outgoing* BIO is used to pass data the other way around. + This class has no public constructor. An :class:`SSLObject` instance + must be created using the :meth:`~SSLContext.wrap_bio` method. This + method will create the :class:`SSLObject` instance and bind it to a + pair of BIOs. The *incoming* BIO is used to pass data from Python to the + SSL protocol instance, while the *outgoing* BIO is used to pass data the + other way around. The following methods are available: @@ -2305,6 +2311,12 @@ provided. :meth:`~SSLContext.wrap_socket`. An :class:`SSLObject` is always created via an :class:`SSLContext`. + .. versionchanged:: 3.7 + :class:`SSLObject` instances must to created with + :meth:`~SSLContext.wrap_bio`. In earlier versions, it was possible to + create instances directly. This was never documented or officially + supported. + An SSLObject communicates with the outside world using memory buffers. The class :class:`MemoryBIO` provides a memory buffer that can be used for this purpose. It wraps an OpenSSL memory BIO (Basic IO) object: diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 048e87dda12f..2e5e7c178b41 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -669,6 +669,12 @@ OpenSSL 1.1.1. (Contributed by Christian Heimes in :issue:`32947`, recommend :meth:`~ssl.SSLContext.wrap_socket` instead. (Contributed by Christian Heimes in :issue:`28124`.) +: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 +:meth:`~ssl.SSLContext.wrap_socket` and :meth:`~ssl.SSLContext.wrap_bio`. +(Contributed by Christian Heimes in :issue:`32951`) + string ------ diff --git a/Lib/ssl.py b/Lib/ssl.py index 94ea35e358a3..75ebcc165a17 100644 --- a/Lib/ssl.py +++ b/Lib/ssl.py @@ -390,24 +390,24 @@ def wrap_socket(self, sock, server_side=False, server_hostname=None, session=None): # SSLSocket class handles server_hostname encoding before it calls # ctx._wrap_socket() - return self.sslsocket_class( + return self.sslsocket_class._create( sock=sock, server_side=server_side, do_handshake_on_connect=do_handshake_on_connect, suppress_ragged_eofs=suppress_ragged_eofs, server_hostname=server_hostname, - _context=self, - _session=session + context=self, + session=session ) def wrap_bio(self, incoming, outgoing, server_side=False, server_hostname=None, session=None): # Need to encode server_hostname here because _wrap_bio() can only # handle ASCII str. - return self.sslobject_class( + return self.sslobject_class._create( incoming, outgoing, server_side=server_side, server_hostname=self._encode_hostname(server_hostname), - session=session, _context=self, + session=session, context=self, ) def set_npn_protocols(self, npn_protocols): @@ -612,14 +612,23 @@ class SSLObject: * Any form of network IO incluging methods such as ``recv`` and ``send``. * The ``do_handshake_on_connect`` and ``suppress_ragged_eofs`` machinery. """ + def __init__(self, *args, **kwargs): + raise TypeError( + f"{self.__class__.__name__} does not have a public " + f"constructor. Instances are returned by SSLContext.wrap_bio()." + ) - def __init__(self, incoming, outgoing, server_side=False, - server_hostname=None, session=None, _context=None): - self._sslobj = _context._wrap_bio( + @classmethod + def _create(cls, incoming, outgoing, server_side=False, + server_hostname=None, session=None, context=None): + self = cls.__new__(cls) + sslobj = context._wrap_bio( incoming, outgoing, server_side=server_side, server_hostname=server_hostname, owner=self, session=session ) + self._sslobj = sslobj + return self @property def context(self): @@ -741,72 +750,48 @@ def version(self): class SSLSocket(socket): """This class implements a subtype of socket.socket that wraps the underlying OS socket in an SSL context when necessary, and - provides read and write methods over that channel.""" - - def __init__(self, sock=None, keyfile=None, certfile=None, - server_side=False, cert_reqs=CERT_NONE, - ssl_version=PROTOCOL_TLS, ca_certs=None, - do_handshake_on_connect=True, - family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None, - suppress_ragged_eofs=True, npn_protocols=None, ciphers=None, - server_hostname=None, - _context=None, _session=None): - - if _context: - self._context = _context - else: - if server_side and not certfile: - raise ValueError("certfile must be specified for server-side " - "operations") - if keyfile and not certfile: - raise ValueError("certfile must be specified") - if certfile and not keyfile: - keyfile = certfile - self._context = SSLContext(ssl_version) - self._context.verify_mode = cert_reqs - if ca_certs: - self._context.load_verify_locations(ca_certs) - if certfile: - self._context.load_cert_chain(certfile, keyfile) - if npn_protocols: - self._context.set_npn_protocols(npn_protocols) - if ciphers: - self._context.set_ciphers(ciphers) - self.keyfile = keyfile - self.certfile = certfile - self.cert_reqs = cert_reqs - self.ssl_version = ssl_version - self.ca_certs = ca_certs - self.ciphers = ciphers - # Can't use sock.type as other flags (such as SOCK_NONBLOCK) get - # mixed in. + provides read and write methods over that channel. """ + + def __init__(self, *args, **kwargs): + raise TypeError( + f"{self.__class__.__name__} does not have a public " + f"constructor. Instances are returned by " + f"SSLContext.wrap_socket()." + ) + + @classmethod + def _create(cls, sock, server_side=False, do_handshake_on_connect=True, + suppress_ragged_eofs=True, server_hostname=None, + context=None, session=None): if sock.getsockopt(SOL_SOCKET, SO_TYPE) != SOCK_STREAM: raise NotImplementedError("only stream sockets are supported") if server_side: if server_hostname: raise ValueError("server_hostname can only be specified " "in client mode") - if _session is not None: + if session is not None: raise ValueError("session can only be specified in " "client mode") - if self._context.check_hostname and not server_hostname: + if context.check_hostname and not server_hostname: raise ValueError("check_hostname requires server_hostname") - self._session = _session + + kwargs = dict( + family=sock.family, type=sock.type, proto=sock.proto, + fileno=sock.fileno() + ) + self = cls.__new__(cls, **kwargs) + super(SSLSocket, self).__init__(**kwargs) + self.settimeout(sock.gettimeout()) + sock.detach() + + self._context = context + self._session = session + self._closed = False + self._sslobj = None self.server_side = server_side - self.server_hostname = self._context._encode_hostname(server_hostname) + self.server_hostname = context._encode_hostname(server_hostname) self.do_handshake_on_connect = do_handshake_on_connect self.suppress_ragged_eofs = suppress_ragged_eofs - if sock is not None: - super().__init__(family=sock.family, - type=sock.type, - proto=sock.proto, - fileno=sock.fileno()) - self.settimeout(sock.gettimeout()) - sock.detach() - elif fileno is not None: - super().__init__(fileno=fileno) - else: - super().__init__(family=family, type=type, proto=proto) # See if we are connected try: @@ -818,8 +803,6 @@ def __init__(self, sock=None, keyfile=None, certfile=None, else: connected = True - self._closed = False - self._sslobj = None self._connected = connected if connected: # create the SSL object @@ -834,10 +817,10 @@ def __init__(self, sock=None, keyfile=None, certfile=None, # non-blocking raise ValueError("do_handshake_on_connect should not be specified for non-blocking sockets") self.do_handshake() - except (OSError, ValueError): self.close() raise + return self @property def context(self): @@ -1184,12 +1167,25 @@ def wrap_socket(sock, keyfile=None, certfile=None, do_handshake_on_connect=True, suppress_ragged_eofs=True, ciphers=None): - return SSLSocket(sock=sock, keyfile=keyfile, certfile=certfile, - server_side=server_side, cert_reqs=cert_reqs, - ssl_version=ssl_version, ca_certs=ca_certs, - do_handshake_on_connect=do_handshake_on_connect, - suppress_ragged_eofs=suppress_ragged_eofs, - ciphers=ciphers) + + if server_side and not certfile: + raise ValueError("certfile must be specified for server-side " + "operations") + if keyfile and not certfile: + raise ValueError("certfile must be specified") + context = SSLContext(ssl_version) + context.verify_mode = cert_reqs + if ca_certs: + context.load_verify_locations(ca_certs) + if certfile: + context.load_cert_chain(certfile, keyfile) + if ciphers: + context.set_ciphers(ciphers) + return context.wrap_socket( + sock=sock, server_side=server_side, + do_handshake_on_connect=do_handshake_on_connect, + suppress_ragged_eofs=suppress_ragged_eofs + ) # some utility functions diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index d978a9e1b0fe..ca2357e98e3e 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -263,6 +263,11 @@ def test_constants(self): ssl.OP_NO_TLSv1_2 self.assertEqual(ssl.PROTOCOL_TLS, ssl.PROTOCOL_SSLv23) + def test_private_init(self): + with self.assertRaisesRegex(TypeError, "public constructor"): + with socket.socket() as s: + ssl.SSLSocket(s) + def test_str_for_enums(self): # Make sure that the PROTOCOL_* constants have enum-like string # reprs. @@ -1657,6 +1662,13 @@ def test_error_types(self): self.assertRaises(TypeError, bio.write, 1) +class SSLObjectTests(unittest.TestCase): + def test_private_init(self): + bio = ssl.MemoryBIO() + with self.assertRaisesRegex(TypeError, "public constructor"): + ssl.SSLObject(bio, bio) + + class SimpleBackgroundTests(unittest.TestCase): """Tests that connect to a simple server running in the background""" @@ -2735,12 +2747,6 @@ def test_check_hostname_idn(self): self.assertEqual(s.server_hostname, expected_hostname) self.assertTrue(cert, "Can't get peer certificate.") - with ssl.SSLSocket(socket.socket(), - server_hostname=server_hostname) as s: - s.connect((HOST, server.port)) - s.getpeercert() - self.assertEqual(s.server_hostname, expected_hostname) - # incorrect hostname should raise an exception server = ThreadedEchoServer(context=server_context, chatty=True) with server: @@ -3999,7 +4005,7 @@ def test_main(verbose=False): tests = [ ContextTests, BasicSocketTests, SSLErrorTests, MemoryBIOTests, - SimpleBackgroundTests, ThreadedTests, + SSLObjectTests, SimpleBackgroundTests, ThreadedTests, ] if support.is_resource_enabled('network'): diff --git a/Misc/NEWS.d/next/Library/2018-02-25-18-22-01.bpo-32951.gHrCXq.rst b/Misc/NEWS.d/next/Library/2018-02-25-18-22-01.bpo-32951.gHrCXq.rst new file mode 100644 index 000000000000..9c038cf25979 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-25-18-22-01.bpo-32951.gHrCXq.rst @@ -0,0 +1,3 @@ +Direct instantiation of SSLSocket and SSLObject objects is now prohibited. +The constructors were never documented, tested, or designed as public +constructors. Users were suppose to use ssl.wrap_socket() or SSLContext. From webhook-mailer at python.org Tue Feb 27 05:54:53 2018 From: webhook-mailer at python.org (Christian Heimes) Date: Tue, 27 Feb 2018 10:54:53 -0000 Subject: [Python-checkins] bpo-31453: Add setter for min/max protocol version (#5259) Message-ID: https://github.com/python/cpython/commit/698dde16f60729d9e3f53c23a4ddb8e5ffe818bf commit: 698dde16f60729d9e3f53c23a4ddb8e5ffe818bf branch: master author: Christian Heimes committer: GitHub date: 2018-02-27T11:54:43+01:00 summary: bpo-31453: Add setter for min/max protocol version (#5259) OpenSSL 1.1 has introduced a new API to set the minimum and maximum supported protocol version. The API is easier to use than the old OP_NO_TLS1 option flags, too. Since OpenSSL has no call to set minimum version to highest supported, the implementation emulate maximum_version = MINIMUM_SUPPORTED and minimum_version = MAXIMUM_SUPPORTED by figuring out the minumum and maximum supported version at compile time. Signed-off-by: Christian Heimes files: A Misc/NEWS.d/next/Library/2018-01-21-15-01-50.bpo-31453.cZiZBe.rst M Doc/library/ssl.rst M Doc/whatsnew/3.7.rst M Lib/ssl.py M Lib/test/test_ssl.py M Modules/_ssl.c diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index d18a505937a8..2b4bed413985 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -762,6 +762,11 @@ Constants .. versionadded:: 3.2 + .. deprecated:: 3.7 + The option is deprecated since OpenSSL 1.1.0, use the new + :attr:`SSLContext.minimum_version` and + :attr:`SSLContext.maximum_version` instead. + .. data:: OP_NO_TLSv1_1 Prevents a TLSv1.1 connection. This option is only applicable in conjunction @@ -770,6 +775,9 @@ Constants .. versionadded:: 3.4 + .. deprecated:: 3.7 + The option is deprecated since OpenSSL 1.1.0. + .. data:: OP_NO_TLSv1_2 Prevents a TLSv1.2 connection. This option is only applicable in conjunction @@ -778,6 +786,9 @@ Constants .. versionadded:: 3.4 + .. deprecated:: 3.7 + The option is deprecated since OpenSSL 1.1.0. + .. data:: OP_NO_TLSv1_3 Prevents a TLSv1.3 connection. This option is only applicable in conjunction @@ -788,6 +799,10 @@ Constants .. versionadded:: 3.7 + .. deprecated:: 3.7 + 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_CIPHER_SERVER_PREFERENCE Use the server's cipher ordering preference, rather than the client's. @@ -856,7 +871,7 @@ Constants .. data:: HAS_ECDH - Whether the OpenSSL library has built-in support for Elliptic Curve-based + Whether the OpenSSL library has built-in support for the Elliptic Curve-based Diffie-Hellman key exchange. This should be true unless the feature was explicitly disabled by the distributor. @@ -871,7 +886,7 @@ Constants .. data:: HAS_NPN - Whether the OpenSSL library has built-in support for *Next Protocol + Whether the OpenSSL library has built-in support for the *Next Protocol Negotiation* as described in the `Application Layer Protocol Negotiation `_. When true, you can use the :meth:`SSLContext.set_npn_protocols` method to advertise @@ -879,6 +894,36 @@ Constants .. versionadded:: 3.3 +.. data:: HAS_SSLv2 + + Whether the OpenSSL library has built-in support for the SSL 2.0 protocol. + + .. versionadded:: 3.7 + +.. data:: HAS_SSLv3 + + Whether the OpenSSL library has built-in support for the SSL 3.0 protocol. + + .. versionadded:: 3.7 + +.. data:: HAS_TLSv1 + + Whether the OpenSSL library has built-in support for the TLS 1.0 protocol. + + .. versionadded:: 3.7 + +.. data:: HAS_TLSv1_1 + + Whether the OpenSSL library has built-in support for the TLS 1.1 protocol. + + .. versionadded:: 3.7 + +.. data:: HAS_TLSv1_2 + + Whether the OpenSSL library has built-in support for the TLS 1.2 protocol. + + .. versionadded:: 3.7 + .. data:: HAS_TLSv1_3 Whether the OpenSSL library has built-in support for the TLS 1.3 protocol. @@ -965,6 +1010,27 @@ Constants .. versionadded:: 3.6 +.. class:: TLSVersion + + :class:`enum.IntEnum` collection of SSL and TLS versions for + :attr:`SSLContext.maximum_version` and :attr:`SSLContext.minimum_version`. + + .. versionadded:: 3.7 + +.. attribute:: TLSVersion.MINIMUM_SUPPORTED +.. attribute:: TLSVersion.MAXIMUM_SUPPORTED + + The minimum or maximum supported SSL or TLS version. These are magic + constants. Their values don't reflect the lowest and highest available + TLS/SSL versions. + +.. attribute:: TLSVersion.SSLv3 +.. attribute:: TLSVersion.TLSv1 +.. attribute:: TLSVersion.TLSv1_1 +.. attribute:: TLSVersion.TLSv1_2 +.. attribute:: TLSVersion.TLSv1_3 + + SSL 3.0 to TLS 1.3. SSL Sockets ----------- @@ -1788,6 +1854,37 @@ to speed up repeated connections from the same clients. This features requires OpenSSL 0.9.8f or newer. +.. attribute:: SSLContext.maximum_version + + A :class:`TLSVersion` enum member representing the highest supported + TLS version. The value defaults to :attr:`TLSVersion.MAXIMUM_SUPPORTED`. + The attribute is read-only for protocols other than :attr:`PROTOCOL_TLS`, + :attr:`PROTOCOL_TLS_CLIENT`, and :attr:`PROTOCOL_TLS_SERVER`. + + The attributes :attr:`~SSLContext.maximum_version`, + :attr:`~SSLContext.minimum_version` and + :attr:`SSLContext.options` all affect the supported SSL + and TLS versions of the context. The implementation does not prevent + invalid combination. For example a context with + :attr:`OP_NO_TLSv1_2` in :attr:`~SSLContext.options` and + :attr:`~SSLContext.maximum_version` set to :attr:`TLSVersion.TLSv1_2` + will not be able to establish a TLS 1.2 connection. + + .. note:: + + This attribute is not available unless the ssl module is compiled + with OpenSSL 1.1.0g or newer. + +.. attribute:: SSLContext.minimum_version + + Like :attr:`SSLContext.maximum_version` except it is the lowest + supported version or :attr:`TLSVersion.MINIMUM_SUPPORTED`. + + .. note:: + + This attribute is not available unless the ssl module is compiled + with OpenSSL 1.1.0g or newer. + .. attribute:: SSLContext.options An integer representing the set of SSL options enabled on this context. diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 2d62ffa5004c..fa2d472820c9 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -683,6 +683,11 @@ 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 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`. +(Contributed by Christian Heimes in :issue:`32609`.) string ------ diff --git a/Lib/ssl.py b/Lib/ssl.py index 75ebcc165a17..2db887354714 100644 --- a/Lib/ssl.py +++ b/Lib/ssl.py @@ -112,9 +112,11 @@ pass -from _ssl import HAS_SNI, HAS_ECDH, HAS_NPN, HAS_ALPN, HAS_TLSv1_3 -from _ssl import _DEFAULT_CIPHERS -from _ssl import _OPENSSL_API_VERSION +from _ssl import ( + HAS_SNI, HAS_ECDH, HAS_NPN, HAS_ALPN, HAS_SSLv2, HAS_SSLv3, HAS_TLSv1, + HAS_TLSv1_1, HAS_TLSv1_2, HAS_TLSv1_3 +) +from _ssl import _DEFAULT_CIPHERS, _OPENSSL_API_VERSION _IntEnum._convert( @@ -153,6 +155,16 @@ _SSLv2_IF_EXISTS = getattr(_SSLMethod, 'PROTOCOL_SSLv2', None) +class TLSVersion(_IntEnum): + MINIMUM_SUPPORTED = _ssl.PROTO_MINIMUM_SUPPORTED + SSLv3 = _ssl.PROTO_SSLv3 + TLSv1 = _ssl.PROTO_TLSv1 + TLSv1_1 = _ssl.PROTO_TLSv1_1 + TLSv1_2 = _ssl.PROTO_TLSv1_2 + TLSv1_3 = _ssl.PROTO_TLSv1_3 + MAXIMUM_SUPPORTED = _ssl.PROTO_MAXIMUM_SUPPORTED + + if sys.platform == "win32": from _ssl import enum_certificates, enum_crls @@ -467,6 +479,25 @@ def load_default_certs(self, purpose=Purpose.SERVER_AUTH): self._load_windows_store_certs(storename, purpose) self.set_default_verify_paths() + if hasattr(_SSLContext, 'minimum_version'): + @property + def minimum_version(self): + return TLSVersion(super().minimum_version) + + @minimum_version.setter + def minimum_version(self, value): + if value == TLSVersion.SSLv3: + self.options &= ~Options.OP_NO_SSLv3 + super(SSLContext, SSLContext).minimum_version.__set__(self, value) + + @property + def maximum_version(self): + return TLSVersion(super().maximum_version) + + @maximum_version.setter + def maximum_version(self, value): + super(SSLContext, SSLContext).maximum_version.__set__(self, value) + @property def options(self): return Options(super().options) diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index ca2357e98e3e..8d98b805b49a 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -1077,6 +1077,69 @@ def test_hostname_checks_common_name(self): with self.assertRaises(AttributeError): ctx.hostname_checks_common_name = True + @unittest.skipUnless(hasattr(ssl.SSLContext, 'minimum_version'), + "required OpenSSL 1.1.0g") + def test_min_max_version(self): + ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) + self.assertEqual( + ctx.minimum_version, ssl.TLSVersion.MINIMUM_SUPPORTED + ) + self.assertEqual( + ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED + ) + + ctx.minimum_version = ssl.TLSVersion.TLSv1_1 + ctx.maximum_version = ssl.TLSVersion.TLSv1_2 + self.assertEqual( + ctx.minimum_version, ssl.TLSVersion.TLSv1_1 + ) + self.assertEqual( + ctx.maximum_version, ssl.TLSVersion.TLSv1_2 + ) + + ctx.minimum_version = ssl.TLSVersion.MINIMUM_SUPPORTED + ctx.maximum_version = ssl.TLSVersion.TLSv1 + self.assertEqual( + ctx.minimum_version, ssl.TLSVersion.MINIMUM_SUPPORTED + ) + self.assertEqual( + ctx.maximum_version, ssl.TLSVersion.TLSv1 + ) + + ctx.maximum_version = ssl.TLSVersion.MAXIMUM_SUPPORTED + self.assertEqual( + ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED + ) + + ctx.maximum_version = ssl.TLSVersion.MINIMUM_SUPPORTED + self.assertIn( + ctx.maximum_version, + {ssl.TLSVersion.TLSv1, ssl.TLSVersion.SSLv3} + ) + + ctx.minimum_version = ssl.TLSVersion.MAXIMUM_SUPPORTED + self.assertIn( + ctx.minimum_version, + {ssl.TLSVersion.TLSv1_2, ssl.TLSVersion.TLSv1_3} + ) + + with self.assertRaises(ValueError): + ctx.minimum_version = 42 + + ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_1) + + self.assertEqual( + ctx.minimum_version, ssl.TLSVersion.MINIMUM_SUPPORTED + ) + self.assertEqual( + ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED + ) + with self.assertRaises(ValueError): + ctx.minimum_version = ssl.TLSVersion.MINIMUM_SUPPORTED + with self.assertRaises(ValueError): + ctx.maximum_version = ssl.TLSVersion.TLSv1 + + @unittest.skipUnless(have_verify_flags(), "verify_flags need OpenSSL > 0.9.8") def test_verify_flags(self): @@ -3457,6 +3520,60 @@ def test_tls1_3(self): }) self.assertEqual(s.version(), 'TLSv1.3') + @unittest.skipUnless(hasattr(ssl.SSLContext, 'minimum_version'), + "required OpenSSL 1.1.0g") + def test_min_max_version(self): + client_context, server_context, hostname = testing_context() + # client TLSv1.0 to 1.2 + client_context.minimum_version = ssl.TLSVersion.TLSv1 + client_context.maximum_version = ssl.TLSVersion.TLSv1_2 + # server only TLSv1.2 + server_context.minimum_version = ssl.TLSVersion.TLSv1_2 + server_context.maximum_version = ssl.TLSVersion.TLSv1_2 + + with ThreadedEchoServer(context=server_context) as server: + with client_context.wrap_socket(socket.socket(), + server_hostname=hostname) as s: + s.connect((HOST, server.port)) + self.assertEqual(s.version(), 'TLSv1.2') + + # client 1.0 to 1.2, server 1.0 to 1.1 + server_context.minimum_version = ssl.TLSVersion.TLSv1 + server_context.maximum_version = ssl.TLSVersion.TLSv1_1 + + with ThreadedEchoServer(context=server_context) as server: + with client_context.wrap_socket(socket.socket(), + server_hostname=hostname) as s: + s.connect((HOST, server.port)) + self.assertEqual(s.version(), 'TLSv1.1') + + # client 1.0, server 1.2 (mismatch) + server_context.minimum_version = ssl.TLSVersion.TLSv1_2 + server_context.maximum_version = ssl.TLSVersion.TLSv1_2 + client_context.minimum_version = ssl.TLSVersion.TLSv1 + client_context.maximum_version = ssl.TLSVersion.TLSv1 + with ThreadedEchoServer(context=server_context) as server: + with client_context.wrap_socket(socket.socket(), + server_hostname=hostname) as s: + with self.assertRaises(ssl.SSLError) as e: + s.connect((HOST, server.port)) + self.assertIn("alert", str(e.exception)) + + + @unittest.skipUnless(hasattr(ssl.SSLContext, 'minimum_version'), + "required OpenSSL 1.1.0g") + @unittest.skipUnless(ssl.HAS_SSLv3, "requires SSLv3 support") + def test_min_max_version_sslv3(self): + client_context, server_context, hostname = testing_context() + server_context.minimum_version = ssl.TLSVersion.SSLv3 + client_context.minimum_version = ssl.TLSVersion.SSLv3 + client_context.maximum_version = ssl.TLSVersion.SSLv3 + with ThreadedEchoServer(context=server_context) as server: + with client_context.wrap_socket(socket.socket(), + server_hostname=hostname) as s: + s.connect((HOST, server.port)) + self.assertEqual(s.version(), 'SSLv3') + @unittest.skipUnless(ssl.HAS_ECDH, "test requires ECDH-enabled OpenSSL") def test_default_ecdh_curve(self): # Issue #21015: elliptic curve-based Diffie Hellman key exchange diff --git a/Misc/NEWS.d/next/Library/2018-01-21-15-01-50.bpo-31453.cZiZBe.rst b/Misc/NEWS.d/next/Library/2018-01-21-15-01-50.bpo-31453.cZiZBe.rst new file mode 100644 index 000000000000..6d43dfd8207d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-01-21-15-01-50.bpo-31453.cZiZBe.rst @@ -0,0 +1,4 @@ +Add TLSVersion constants and SSLContext.maximum_version / minimum_version +attributes. The new API wraps OpenSSL 1.1 +https://www.openssl.org/docs/man1.1.0/ssl/SSL_CTX_set_min_proto_version.html +feature. diff --git a/Modules/_ssl.c b/Modules/_ssl.c index f50823e6947a..f9e061dfe01d 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -320,6 +320,53 @@ enum py_ssl_version { PY_SSL_VERSION_TLS_SERVER, }; +enum py_proto_version { + PY_PROTO_MINIMUM_SUPPORTED = -2, + PY_PROTO_SSLv3 = SSL3_VERSION, + PY_PROTO_TLSv1 = TLS1_VERSION, + PY_PROTO_TLSv1_1 = TLS1_1_VERSION, + PY_PROTO_TLSv1_2 = TLS1_2_VERSION, +#ifdef TLS1_3_VERSION + PY_PROTO_TLSv1_3 = TLS1_3_VERSION, +#else + PY_PROTO_TLSv1_3 = 0x304, +#endif + PY_PROTO_MAXIMUM_SUPPORTED = -1, + +/* OpenSSL has no dedicated API to set the minimum version to the maximum + * available version, and the other way around. We have to figure out the + * minimum and maximum available version on our own and hope for the best. + */ +#if defined(SSL3_VERSION) && !defined(OPENSSL_NO_SSL3) + PY_PROTO_MINIMUM_AVAILABLE = PY_PROTO_SSLv3, +#elif defined(TLS1_VERSION) && !defined(OPENSSL_NO_TLS1) + PY_PROTO_MINIMUM_AVAILABLE = PY_PROTO_TLSv1, +#elif defined(TLS1_1_VERSION) && !defined(OPENSSL_NO_TLS1_1) + PY_PROTO_MINIMUM_AVAILABLE = PY_PROTO_TLSv1_1, +#elif defined(TLS1_2_VERSION) && !defined(OPENSSL_NO_TLS1_2) + PY_PROTO_MINIMUM_AVAILABLE = PY_PROTO_TLSv1_2, +#elif defined(TLS1_3_VERSION) && !defined(OPENSSL_NO_TLS1_3) + PY_PROTO_MINIMUM_AVAILABLE = PY_PROTO_TLSv1_3, +#else + #error "PY_PROTO_MINIMUM_AVAILABLE not found" +#endif + +#if defined(TLS1_3_VERSION) && !defined(OPENSSL_NO_TLS1_3) + PY_PROTO_MAXIMUM_AVAILABLE = PY_PROTO_TLSv1_3, +#elif defined(TLS1_2_VERSION) && !defined(OPENSSL_NO_TLS1_2) + PY_PROTO_MAXIMUM_AVAILABLE = PY_PROTO_TLSv1_2, +#elif defined(TLS1_1_VERSION) && !defined(OPENSSL_NO_TLS1_1) + PY_PROTO_MAXIMUM_AVAILABLE = PY_PROTO_TLSv1_1, +#elif defined(TLS1_VERSION) && !defined(OPENSSL_NO_TLS1) + PY_PROTO_MAXIMUM_AVAILABLE = PY_PROTO_TLSv1, +#elif defined(SSL3_VERSION) && !defined(OPENSSL_NO_SSL3) + PY_PROTO_MAXIMUM_AVAILABLE = PY_PROTO_SSLv3, +#else + #error "PY_PROTO_MAXIMUM_AVAILABLE not found" +#endif +}; + + /* serves as a flag to see whether we've initialized the SSL thread support. */ /* 0 means no, greater than 0 means yes */ @@ -3323,6 +3370,106 @@ set_verify_flags(PySSLContext *self, PyObject *arg, void *c) return 0; } +/* Getter and setter for protocol version */ +#if defined(SSL_CTRL_GET_MAX_PROTO_VERSION) + + +static int +set_min_max_proto_version(PySSLContext *self, PyObject *arg, int what) +{ + long v; + int result; + + if (!PyArg_Parse(arg, "l", &v)) + return -1; + if (v > INT_MAX) { + PyErr_SetString(PyExc_OverflowError, "Option is too long"); + return -1; + } + + switch(self->protocol) { + case PY_SSL_VERSION_TLS_CLIENT: /* fall through */ + case PY_SSL_VERSION_TLS_SERVER: /* fall through */ + case PY_SSL_VERSION_TLS: + break; + default: + PyErr_SetString( + PyExc_ValueError, + "The context's protocol doesn't support modification of " + "highest and lowest version." + ); + return -1; + } + + if (what == 0) { + switch(v) { + case PY_PROTO_MINIMUM_SUPPORTED: + v = 0; + break; + case PY_PROTO_MAXIMUM_SUPPORTED: + /* Emulate max for set_min_proto_version */ + v = PY_PROTO_MAXIMUM_AVAILABLE; + break; + default: + break; + } + result = SSL_CTX_set_min_proto_version(self->ctx, v); + } + else { + switch(v) { + case PY_PROTO_MAXIMUM_SUPPORTED: + v = 0; + break; + case PY_PROTO_MINIMUM_SUPPORTED: + /* Emulate max for set_min_proto_version */ + v = PY_PROTO_MINIMUM_AVAILABLE; + break; + default: + break; + } + result = SSL_CTX_set_max_proto_version(self->ctx, v); + } + if (result == 0) { + PyErr_Format(PyExc_ValueError, + "Unsupported protocol version 0x%x", v); + return -1; + } + return 0; +} + +static PyObject * +get_minimum_version(PySSLContext *self, void *c) +{ + int v = SSL_CTX_ctrl(self->ctx, SSL_CTRL_GET_MIN_PROTO_VERSION, 0, NULL); + if (v == 0) { + v = PY_PROTO_MINIMUM_SUPPORTED; + } + return PyLong_FromLong(v); +} + +static int +set_minimum_version(PySSLContext *self, PyObject *arg, void *c) +{ + return set_min_max_proto_version(self, arg, 0); +} + +static PyObject * +get_maximum_version(PySSLContext *self, void *c) +{ + int v = SSL_CTX_ctrl(self->ctx, SSL_CTRL_GET_MAX_PROTO_VERSION, 0, NULL); + if (v == 0) { + v = PY_PROTO_MAXIMUM_SUPPORTED; + } + return PyLong_FromLong(v); +} + +static int +set_maximum_version(PySSLContext *self, PyObject *arg, void *c) +{ + return set_min_max_proto_version(self, arg, 1); +} +#endif /* SSL_CTRL_GET_MAX_PROTO_VERSION */ + static PyObject * get_options(PySSLContext *self, void *c) { @@ -4289,8 +4436,14 @@ static PyGetSetDef context_getsetlist[] = { (setter) set_check_hostname, NULL}, {"_host_flags", (getter) get_host_flags, (setter) set_host_flags, NULL}, +#if SSL_CTRL_GET_MAX_PROTO_VERSION + {"minimum_version", (getter) get_minimum_version, + (setter) set_minimum_version, NULL}, + {"maximum_version", (getter) get_maximum_version, + (setter) set_maximum_version, NULL}, +#endif {"sni_callback", (getter) get_sni_callback, - (setter) set_sni_callback, PySSLContext_sni_callback_doc}, + (setter) set_sni_callback, PySSLContext_sni_callback_doc}, {"options", (getter) get_options, (setter) set_options, NULL}, {"protocol", (getter) get_protocol, @@ -5711,45 +5864,82 @@ PyInit__ssl(void) X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS); #endif + /* protocol versions */ + PyModule_AddIntConstant(m, "PROTO_MINIMUM_SUPPORTED", + PY_PROTO_MINIMUM_SUPPORTED); + PyModule_AddIntConstant(m, "PROTO_MAXIMUM_SUPPORTED", + PY_PROTO_MAXIMUM_SUPPORTED); + PyModule_AddIntConstant(m, "PROTO_SSLv3", PY_PROTO_SSLv3); + PyModule_AddIntConstant(m, "PROTO_TLSv1", PY_PROTO_TLSv1); + PyModule_AddIntConstant(m, "PROTO_TLSv1_1", PY_PROTO_TLSv1_1); + PyModule_AddIntConstant(m, "PROTO_TLSv1_2", PY_PROTO_TLSv1_2); + PyModule_AddIntConstant(m, "PROTO_TLSv1_3", PY_PROTO_TLSv1_3); + +#define addbool(m, v, b) \ + Py_INCREF((b) ? Py_True : Py_False); \ + PyModule_AddObject((m), (v), (b) ? Py_True : Py_False); + #if HAVE_SNI - r = Py_True; + addbool(m, "HAS_SNI", 1); #else - r = Py_False; + addbool(m, "HAS_SNI", 0); #endif - Py_INCREF(r); - PyModule_AddObject(m, "HAS_SNI", r); -#ifdef OPENSSL_NO_ECDH - r = Py_False; + addbool(m, "HAS_TLS_UNIQUE", 1); + +#ifndef OPENSSL_NO_ECDH + addbool(m, "HAS_ECDH", 1); #else - r = Py_True; + addbool(m, "HAS_ECDH", 0); #endif - Py_INCREF(r); - PyModule_AddObject(m, "HAS_ECDH", r); #if HAVE_NPN - r = Py_True; + addbool(m, "HAS_NPN", 1); #else - r = Py_False; + addbool(m, "HAS_NPN", 0); #endif - Py_INCREF(r); - PyModule_AddObject(m, "HAS_NPN", r); #if HAVE_ALPN - r = Py_True; + addbool(m, "HAS_ALPN", 1); +#else + addbool(m, "HAS_ALPN", 0); +#endif + +#if defined(SSL2_VERSION) && !defined(OPENSSL_NO_SSL2) + addbool(m, "HAS_SSLv2", 1); +#else + addbool(m, "HAS_SSLv2", 0); +#endif + +#if defined(SSL3_VERSION) && !defined(OPENSSL_NO_SSL3) + addbool(m, "HAS_SSLv3", 1); +#else + addbool(m, "HAS_SSLv3", 0); +#endif + +#if defined(TLS1_VERSION) && !defined(OPENSSL_NO_TLS1) + addbool(m, "HAS_TLSv1", 1); +#else + addbool(m, "HAS_TLSv1", 0); +#endif + +#if defined(TLS1_1_VERSION) && !defined(OPENSSL_NO_TLS1_1) + addbool(m, "HAS_TLSv1_1", 1); +#else + addbool(m, "HAS_TLSv1_1", 0); +#endif + +#if defined(TLS1_2_VERSION) && !defined(OPENSSL_NO_TLS1_2) + addbool(m, "HAS_TLSv1_2", 1); #else - r = Py_False; + addbool(m, "HAS_TLSv1_2", 0); #endif - Py_INCREF(r); - PyModule_AddObject(m, "HAS_ALPN", r); #if defined(TLS1_3_VERSION) && !defined(OPENSSL_NO_TLS1_3) - r = Py_True; + addbool(m, "HAS_TLSv1_3", 1); #else - r = Py_False; + addbool(m, "HAS_TLSv1_3", 0); #endif - Py_INCREF(r); - PyModule_AddObject(m, "HAS_TLSv1_3", r); /* Mappings for error codes */ err_codes_to_names = PyDict_New(); From webhook-mailer at python.org Tue Feb 27 06:41:08 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 27 Feb 2018 11:41:08 -0000 Subject: [Python-checkins] bpo-31453: Add setter for min/max protocol version (GH-5259) Message-ID: https://github.com/python/cpython/commit/4c842b09209ccf1b4f853106b1f58bb888da02ef commit: 4c842b09209ccf1b4f853106b1f58bb888da02ef branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-27T03:41:04-08:00 summary: bpo-31453: Add setter for min/max protocol version (GH-5259) OpenSSL 1.1 has introduced a new API to set the minimum and maximum supported protocol version. The API is easier to use than the old OP_NO_TLS1 option flags, too. Since OpenSSL has no call to set minimum version to highest supported, the implementation emulate maximum_version = MINIMUM_SUPPORTED and minimum_version = MAXIMUM_SUPPORTED by figuring out the minumum and maximum supported version at compile time. Signed-off-by: Christian Heimes (cherry picked from commit 698dde16f60729d9e3f53c23a4ddb8e5ffe818bf) Co-authored-by: Christian Heimes files: A Misc/NEWS.d/next/Library/2018-01-21-15-01-50.bpo-31453.cZiZBe.rst M Doc/library/ssl.rst M Doc/whatsnew/3.7.rst M Lib/ssl.py M Lib/test/test_ssl.py M Modules/_ssl.c diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index d18a505937a8..2b4bed413985 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -762,6 +762,11 @@ Constants .. versionadded:: 3.2 + .. deprecated:: 3.7 + The option is deprecated since OpenSSL 1.1.0, use the new + :attr:`SSLContext.minimum_version` and + :attr:`SSLContext.maximum_version` instead. + .. data:: OP_NO_TLSv1_1 Prevents a TLSv1.1 connection. This option is only applicable in conjunction @@ -770,6 +775,9 @@ Constants .. versionadded:: 3.4 + .. deprecated:: 3.7 + The option is deprecated since OpenSSL 1.1.0. + .. data:: OP_NO_TLSv1_2 Prevents a TLSv1.2 connection. This option is only applicable in conjunction @@ -778,6 +786,9 @@ Constants .. versionadded:: 3.4 + .. deprecated:: 3.7 + The option is deprecated since OpenSSL 1.1.0. + .. data:: OP_NO_TLSv1_3 Prevents a TLSv1.3 connection. This option is only applicable in conjunction @@ -788,6 +799,10 @@ Constants .. versionadded:: 3.7 + .. deprecated:: 3.7 + 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_CIPHER_SERVER_PREFERENCE Use the server's cipher ordering preference, rather than the client's. @@ -856,7 +871,7 @@ Constants .. data:: HAS_ECDH - Whether the OpenSSL library has built-in support for Elliptic Curve-based + Whether the OpenSSL library has built-in support for the Elliptic Curve-based Diffie-Hellman key exchange. This should be true unless the feature was explicitly disabled by the distributor. @@ -871,7 +886,7 @@ Constants .. data:: HAS_NPN - Whether the OpenSSL library has built-in support for *Next Protocol + Whether the OpenSSL library has built-in support for the *Next Protocol Negotiation* as described in the `Application Layer Protocol Negotiation `_. When true, you can use the :meth:`SSLContext.set_npn_protocols` method to advertise @@ -879,6 +894,36 @@ Constants .. versionadded:: 3.3 +.. data:: HAS_SSLv2 + + Whether the OpenSSL library has built-in support for the SSL 2.0 protocol. + + .. versionadded:: 3.7 + +.. data:: HAS_SSLv3 + + Whether the OpenSSL library has built-in support for the SSL 3.0 protocol. + + .. versionadded:: 3.7 + +.. data:: HAS_TLSv1 + + Whether the OpenSSL library has built-in support for the TLS 1.0 protocol. + + .. versionadded:: 3.7 + +.. data:: HAS_TLSv1_1 + + Whether the OpenSSL library has built-in support for the TLS 1.1 protocol. + + .. versionadded:: 3.7 + +.. data:: HAS_TLSv1_2 + + Whether the OpenSSL library has built-in support for the TLS 1.2 protocol. + + .. versionadded:: 3.7 + .. data:: HAS_TLSv1_3 Whether the OpenSSL library has built-in support for the TLS 1.3 protocol. @@ -965,6 +1010,27 @@ Constants .. versionadded:: 3.6 +.. class:: TLSVersion + + :class:`enum.IntEnum` collection of SSL and TLS versions for + :attr:`SSLContext.maximum_version` and :attr:`SSLContext.minimum_version`. + + .. versionadded:: 3.7 + +.. attribute:: TLSVersion.MINIMUM_SUPPORTED +.. attribute:: TLSVersion.MAXIMUM_SUPPORTED + + The minimum or maximum supported SSL or TLS version. These are magic + constants. Their values don't reflect the lowest and highest available + TLS/SSL versions. + +.. attribute:: TLSVersion.SSLv3 +.. attribute:: TLSVersion.TLSv1 +.. attribute:: TLSVersion.TLSv1_1 +.. attribute:: TLSVersion.TLSv1_2 +.. attribute:: TLSVersion.TLSv1_3 + + SSL 3.0 to TLS 1.3. SSL Sockets ----------- @@ -1788,6 +1854,37 @@ to speed up repeated connections from the same clients. This features requires OpenSSL 0.9.8f or newer. +.. attribute:: SSLContext.maximum_version + + A :class:`TLSVersion` enum member representing the highest supported + TLS version. The value defaults to :attr:`TLSVersion.MAXIMUM_SUPPORTED`. + The attribute is read-only for protocols other than :attr:`PROTOCOL_TLS`, + :attr:`PROTOCOL_TLS_CLIENT`, and :attr:`PROTOCOL_TLS_SERVER`. + + The attributes :attr:`~SSLContext.maximum_version`, + :attr:`~SSLContext.minimum_version` and + :attr:`SSLContext.options` all affect the supported SSL + and TLS versions of the context. The implementation does not prevent + invalid combination. For example a context with + :attr:`OP_NO_TLSv1_2` in :attr:`~SSLContext.options` and + :attr:`~SSLContext.maximum_version` set to :attr:`TLSVersion.TLSv1_2` + will not be able to establish a TLS 1.2 connection. + + .. note:: + + This attribute is not available unless the ssl module is compiled + with OpenSSL 1.1.0g or newer. + +.. attribute:: SSLContext.minimum_version + + Like :attr:`SSLContext.maximum_version` except it is the lowest + supported version or :attr:`TLSVersion.MINIMUM_SUPPORTED`. + + .. note:: + + This attribute is not available unless the ssl module is compiled + with OpenSSL 1.1.0g or newer. + .. attribute:: SSLContext.options An integer representing the set of SSL options enabled on this context. diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index 2e5e7c178b41..d1eeec209e65 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -675,6 +675,11 @@ 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 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`. +(Contributed by Christian Heimes in :issue:`32609`.) string ------ diff --git a/Lib/ssl.py b/Lib/ssl.py index 75ebcc165a17..2db887354714 100644 --- a/Lib/ssl.py +++ b/Lib/ssl.py @@ -112,9 +112,11 @@ pass -from _ssl import HAS_SNI, HAS_ECDH, HAS_NPN, HAS_ALPN, HAS_TLSv1_3 -from _ssl import _DEFAULT_CIPHERS -from _ssl import _OPENSSL_API_VERSION +from _ssl import ( + HAS_SNI, HAS_ECDH, HAS_NPN, HAS_ALPN, HAS_SSLv2, HAS_SSLv3, HAS_TLSv1, + HAS_TLSv1_1, HAS_TLSv1_2, HAS_TLSv1_3 +) +from _ssl import _DEFAULT_CIPHERS, _OPENSSL_API_VERSION _IntEnum._convert( @@ -153,6 +155,16 @@ _SSLv2_IF_EXISTS = getattr(_SSLMethod, 'PROTOCOL_SSLv2', None) +class TLSVersion(_IntEnum): + MINIMUM_SUPPORTED = _ssl.PROTO_MINIMUM_SUPPORTED + SSLv3 = _ssl.PROTO_SSLv3 + TLSv1 = _ssl.PROTO_TLSv1 + TLSv1_1 = _ssl.PROTO_TLSv1_1 + TLSv1_2 = _ssl.PROTO_TLSv1_2 + TLSv1_3 = _ssl.PROTO_TLSv1_3 + MAXIMUM_SUPPORTED = _ssl.PROTO_MAXIMUM_SUPPORTED + + if sys.platform == "win32": from _ssl import enum_certificates, enum_crls @@ -467,6 +479,25 @@ def load_default_certs(self, purpose=Purpose.SERVER_AUTH): self._load_windows_store_certs(storename, purpose) self.set_default_verify_paths() + if hasattr(_SSLContext, 'minimum_version'): + @property + def minimum_version(self): + return TLSVersion(super().minimum_version) + + @minimum_version.setter + def minimum_version(self, value): + if value == TLSVersion.SSLv3: + self.options &= ~Options.OP_NO_SSLv3 + super(SSLContext, SSLContext).minimum_version.__set__(self, value) + + @property + def maximum_version(self): + return TLSVersion(super().maximum_version) + + @maximum_version.setter + def maximum_version(self, value): + super(SSLContext, SSLContext).maximum_version.__set__(self, value) + @property def options(self): return Options(super().options) diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index ca2357e98e3e..8d98b805b49a 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -1077,6 +1077,69 @@ def test_hostname_checks_common_name(self): with self.assertRaises(AttributeError): ctx.hostname_checks_common_name = True + @unittest.skipUnless(hasattr(ssl.SSLContext, 'minimum_version'), + "required OpenSSL 1.1.0g") + def test_min_max_version(self): + ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) + self.assertEqual( + ctx.minimum_version, ssl.TLSVersion.MINIMUM_SUPPORTED + ) + self.assertEqual( + ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED + ) + + ctx.minimum_version = ssl.TLSVersion.TLSv1_1 + ctx.maximum_version = ssl.TLSVersion.TLSv1_2 + self.assertEqual( + ctx.minimum_version, ssl.TLSVersion.TLSv1_1 + ) + self.assertEqual( + ctx.maximum_version, ssl.TLSVersion.TLSv1_2 + ) + + ctx.minimum_version = ssl.TLSVersion.MINIMUM_SUPPORTED + ctx.maximum_version = ssl.TLSVersion.TLSv1 + self.assertEqual( + ctx.minimum_version, ssl.TLSVersion.MINIMUM_SUPPORTED + ) + self.assertEqual( + ctx.maximum_version, ssl.TLSVersion.TLSv1 + ) + + ctx.maximum_version = ssl.TLSVersion.MAXIMUM_SUPPORTED + self.assertEqual( + ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED + ) + + ctx.maximum_version = ssl.TLSVersion.MINIMUM_SUPPORTED + self.assertIn( + ctx.maximum_version, + {ssl.TLSVersion.TLSv1, ssl.TLSVersion.SSLv3} + ) + + ctx.minimum_version = ssl.TLSVersion.MAXIMUM_SUPPORTED + self.assertIn( + ctx.minimum_version, + {ssl.TLSVersion.TLSv1_2, ssl.TLSVersion.TLSv1_3} + ) + + with self.assertRaises(ValueError): + ctx.minimum_version = 42 + + ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_1) + + self.assertEqual( + ctx.minimum_version, ssl.TLSVersion.MINIMUM_SUPPORTED + ) + self.assertEqual( + ctx.maximum_version, ssl.TLSVersion.MAXIMUM_SUPPORTED + ) + with self.assertRaises(ValueError): + ctx.minimum_version = ssl.TLSVersion.MINIMUM_SUPPORTED + with self.assertRaises(ValueError): + ctx.maximum_version = ssl.TLSVersion.TLSv1 + + @unittest.skipUnless(have_verify_flags(), "verify_flags need OpenSSL > 0.9.8") def test_verify_flags(self): @@ -3457,6 +3520,60 @@ def test_tls1_3(self): }) self.assertEqual(s.version(), 'TLSv1.3') + @unittest.skipUnless(hasattr(ssl.SSLContext, 'minimum_version'), + "required OpenSSL 1.1.0g") + def test_min_max_version(self): + client_context, server_context, hostname = testing_context() + # client TLSv1.0 to 1.2 + client_context.minimum_version = ssl.TLSVersion.TLSv1 + client_context.maximum_version = ssl.TLSVersion.TLSv1_2 + # server only TLSv1.2 + server_context.minimum_version = ssl.TLSVersion.TLSv1_2 + server_context.maximum_version = ssl.TLSVersion.TLSv1_2 + + with ThreadedEchoServer(context=server_context) as server: + with client_context.wrap_socket(socket.socket(), + server_hostname=hostname) as s: + s.connect((HOST, server.port)) + self.assertEqual(s.version(), 'TLSv1.2') + + # client 1.0 to 1.2, server 1.0 to 1.1 + server_context.minimum_version = ssl.TLSVersion.TLSv1 + server_context.maximum_version = ssl.TLSVersion.TLSv1_1 + + with ThreadedEchoServer(context=server_context) as server: + with client_context.wrap_socket(socket.socket(), + server_hostname=hostname) as s: + s.connect((HOST, server.port)) + self.assertEqual(s.version(), 'TLSv1.1') + + # client 1.0, server 1.2 (mismatch) + server_context.minimum_version = ssl.TLSVersion.TLSv1_2 + server_context.maximum_version = ssl.TLSVersion.TLSv1_2 + client_context.minimum_version = ssl.TLSVersion.TLSv1 + client_context.maximum_version = ssl.TLSVersion.TLSv1 + with ThreadedEchoServer(context=server_context) as server: + with client_context.wrap_socket(socket.socket(), + server_hostname=hostname) as s: + with self.assertRaises(ssl.SSLError) as e: + s.connect((HOST, server.port)) + self.assertIn("alert", str(e.exception)) + + + @unittest.skipUnless(hasattr(ssl.SSLContext, 'minimum_version'), + "required OpenSSL 1.1.0g") + @unittest.skipUnless(ssl.HAS_SSLv3, "requires SSLv3 support") + def test_min_max_version_sslv3(self): + client_context, server_context, hostname = testing_context() + server_context.minimum_version = ssl.TLSVersion.SSLv3 + client_context.minimum_version = ssl.TLSVersion.SSLv3 + client_context.maximum_version = ssl.TLSVersion.SSLv3 + with ThreadedEchoServer(context=server_context) as server: + with client_context.wrap_socket(socket.socket(), + server_hostname=hostname) as s: + s.connect((HOST, server.port)) + self.assertEqual(s.version(), 'SSLv3') + @unittest.skipUnless(ssl.HAS_ECDH, "test requires ECDH-enabled OpenSSL") def test_default_ecdh_curve(self): # Issue #21015: elliptic curve-based Diffie Hellman key exchange diff --git a/Misc/NEWS.d/next/Library/2018-01-21-15-01-50.bpo-31453.cZiZBe.rst b/Misc/NEWS.d/next/Library/2018-01-21-15-01-50.bpo-31453.cZiZBe.rst new file mode 100644 index 000000000000..6d43dfd8207d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-01-21-15-01-50.bpo-31453.cZiZBe.rst @@ -0,0 +1,4 @@ +Add TLSVersion constants and SSLContext.maximum_version / minimum_version +attributes. The new API wraps OpenSSL 1.1 +https://www.openssl.org/docs/man1.1.0/ssl/SSL_CTX_set_min_proto_version.html +feature. diff --git a/Modules/_ssl.c b/Modules/_ssl.c index f50823e6947a..f9e061dfe01d 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -320,6 +320,53 @@ enum py_ssl_version { PY_SSL_VERSION_TLS_SERVER, }; +enum py_proto_version { + PY_PROTO_MINIMUM_SUPPORTED = -2, + PY_PROTO_SSLv3 = SSL3_VERSION, + PY_PROTO_TLSv1 = TLS1_VERSION, + PY_PROTO_TLSv1_1 = TLS1_1_VERSION, + PY_PROTO_TLSv1_2 = TLS1_2_VERSION, +#ifdef TLS1_3_VERSION + PY_PROTO_TLSv1_3 = TLS1_3_VERSION, +#else + PY_PROTO_TLSv1_3 = 0x304, +#endif + PY_PROTO_MAXIMUM_SUPPORTED = -1, + +/* OpenSSL has no dedicated API to set the minimum version to the maximum + * available version, and the other way around. We have to figure out the + * minimum and maximum available version on our own and hope for the best. + */ +#if defined(SSL3_VERSION) && !defined(OPENSSL_NO_SSL3) + PY_PROTO_MINIMUM_AVAILABLE = PY_PROTO_SSLv3, +#elif defined(TLS1_VERSION) && !defined(OPENSSL_NO_TLS1) + PY_PROTO_MINIMUM_AVAILABLE = PY_PROTO_TLSv1, +#elif defined(TLS1_1_VERSION) && !defined(OPENSSL_NO_TLS1_1) + PY_PROTO_MINIMUM_AVAILABLE = PY_PROTO_TLSv1_1, +#elif defined(TLS1_2_VERSION) && !defined(OPENSSL_NO_TLS1_2) + PY_PROTO_MINIMUM_AVAILABLE = PY_PROTO_TLSv1_2, +#elif defined(TLS1_3_VERSION) && !defined(OPENSSL_NO_TLS1_3) + PY_PROTO_MINIMUM_AVAILABLE = PY_PROTO_TLSv1_3, +#else + #error "PY_PROTO_MINIMUM_AVAILABLE not found" +#endif + +#if defined(TLS1_3_VERSION) && !defined(OPENSSL_NO_TLS1_3) + PY_PROTO_MAXIMUM_AVAILABLE = PY_PROTO_TLSv1_3, +#elif defined(TLS1_2_VERSION) && !defined(OPENSSL_NO_TLS1_2) + PY_PROTO_MAXIMUM_AVAILABLE = PY_PROTO_TLSv1_2, +#elif defined(TLS1_1_VERSION) && !defined(OPENSSL_NO_TLS1_1) + PY_PROTO_MAXIMUM_AVAILABLE = PY_PROTO_TLSv1_1, +#elif defined(TLS1_VERSION) && !defined(OPENSSL_NO_TLS1) + PY_PROTO_MAXIMUM_AVAILABLE = PY_PROTO_TLSv1, +#elif defined(SSL3_VERSION) && !defined(OPENSSL_NO_SSL3) + PY_PROTO_MAXIMUM_AVAILABLE = PY_PROTO_SSLv3, +#else + #error "PY_PROTO_MAXIMUM_AVAILABLE not found" +#endif +}; + + /* serves as a flag to see whether we've initialized the SSL thread support. */ /* 0 means no, greater than 0 means yes */ @@ -3323,6 +3370,106 @@ set_verify_flags(PySSLContext *self, PyObject *arg, void *c) return 0; } +/* Getter and setter for protocol version */ +#if defined(SSL_CTRL_GET_MAX_PROTO_VERSION) + + +static int +set_min_max_proto_version(PySSLContext *self, PyObject *arg, int what) +{ + long v; + int result; + + if (!PyArg_Parse(arg, "l", &v)) + return -1; + if (v > INT_MAX) { + PyErr_SetString(PyExc_OverflowError, "Option is too long"); + return -1; + } + + switch(self->protocol) { + case PY_SSL_VERSION_TLS_CLIENT: /* fall through */ + case PY_SSL_VERSION_TLS_SERVER: /* fall through */ + case PY_SSL_VERSION_TLS: + break; + default: + PyErr_SetString( + PyExc_ValueError, + "The context's protocol doesn't support modification of " + "highest and lowest version." + ); + return -1; + } + + if (what == 0) { + switch(v) { + case PY_PROTO_MINIMUM_SUPPORTED: + v = 0; + break; + case PY_PROTO_MAXIMUM_SUPPORTED: + /* Emulate max for set_min_proto_version */ + v = PY_PROTO_MAXIMUM_AVAILABLE; + break; + default: + break; + } + result = SSL_CTX_set_min_proto_version(self->ctx, v); + } + else { + switch(v) { + case PY_PROTO_MAXIMUM_SUPPORTED: + v = 0; + break; + case PY_PROTO_MINIMUM_SUPPORTED: + /* Emulate max for set_min_proto_version */ + v = PY_PROTO_MINIMUM_AVAILABLE; + break; + default: + break; + } + result = SSL_CTX_set_max_proto_version(self->ctx, v); + } + if (result == 0) { + PyErr_Format(PyExc_ValueError, + "Unsupported protocol version 0x%x", v); + return -1; + } + return 0; +} + +static PyObject * +get_minimum_version(PySSLContext *self, void *c) +{ + int v = SSL_CTX_ctrl(self->ctx, SSL_CTRL_GET_MIN_PROTO_VERSION, 0, NULL); + if (v == 0) { + v = PY_PROTO_MINIMUM_SUPPORTED; + } + return PyLong_FromLong(v); +} + +static int +set_minimum_version(PySSLContext *self, PyObject *arg, void *c) +{ + return set_min_max_proto_version(self, arg, 0); +} + +static PyObject * +get_maximum_version(PySSLContext *self, void *c) +{ + int v = SSL_CTX_ctrl(self->ctx, SSL_CTRL_GET_MAX_PROTO_VERSION, 0, NULL); + if (v == 0) { + v = PY_PROTO_MAXIMUM_SUPPORTED; + } + return PyLong_FromLong(v); +} + +static int +set_maximum_version(PySSLContext *self, PyObject *arg, void *c) +{ + return set_min_max_proto_version(self, arg, 1); +} +#endif /* SSL_CTRL_GET_MAX_PROTO_VERSION */ + static PyObject * get_options(PySSLContext *self, void *c) { @@ -4289,8 +4436,14 @@ static PyGetSetDef context_getsetlist[] = { (setter) set_check_hostname, NULL}, {"_host_flags", (getter) get_host_flags, (setter) set_host_flags, NULL}, +#if SSL_CTRL_GET_MAX_PROTO_VERSION + {"minimum_version", (getter) get_minimum_version, + (setter) set_minimum_version, NULL}, + {"maximum_version", (getter) get_maximum_version, + (setter) set_maximum_version, NULL}, +#endif {"sni_callback", (getter) get_sni_callback, - (setter) set_sni_callback, PySSLContext_sni_callback_doc}, + (setter) set_sni_callback, PySSLContext_sni_callback_doc}, {"options", (getter) get_options, (setter) set_options, NULL}, {"protocol", (getter) get_protocol, @@ -5711,45 +5864,82 @@ PyInit__ssl(void) X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS); #endif + /* protocol versions */ + PyModule_AddIntConstant(m, "PROTO_MINIMUM_SUPPORTED", + PY_PROTO_MINIMUM_SUPPORTED); + PyModule_AddIntConstant(m, "PROTO_MAXIMUM_SUPPORTED", + PY_PROTO_MAXIMUM_SUPPORTED); + PyModule_AddIntConstant(m, "PROTO_SSLv3", PY_PROTO_SSLv3); + PyModule_AddIntConstant(m, "PROTO_TLSv1", PY_PROTO_TLSv1); + PyModule_AddIntConstant(m, "PROTO_TLSv1_1", PY_PROTO_TLSv1_1); + PyModule_AddIntConstant(m, "PROTO_TLSv1_2", PY_PROTO_TLSv1_2); + PyModule_AddIntConstant(m, "PROTO_TLSv1_3", PY_PROTO_TLSv1_3); + +#define addbool(m, v, b) \ + Py_INCREF((b) ? Py_True : Py_False); \ + PyModule_AddObject((m), (v), (b) ? Py_True : Py_False); + #if HAVE_SNI - r = Py_True; + addbool(m, "HAS_SNI", 1); #else - r = Py_False; + addbool(m, "HAS_SNI", 0); #endif - Py_INCREF(r); - PyModule_AddObject(m, "HAS_SNI", r); -#ifdef OPENSSL_NO_ECDH - r = Py_False; + addbool(m, "HAS_TLS_UNIQUE", 1); + +#ifndef OPENSSL_NO_ECDH + addbool(m, "HAS_ECDH", 1); #else - r = Py_True; + addbool(m, "HAS_ECDH", 0); #endif - Py_INCREF(r); - PyModule_AddObject(m, "HAS_ECDH", r); #if HAVE_NPN - r = Py_True; + addbool(m, "HAS_NPN", 1); #else - r = Py_False; + addbool(m, "HAS_NPN", 0); #endif - Py_INCREF(r); - PyModule_AddObject(m, "HAS_NPN", r); #if HAVE_ALPN - r = Py_True; + addbool(m, "HAS_ALPN", 1); +#else + addbool(m, "HAS_ALPN", 0); +#endif + +#if defined(SSL2_VERSION) && !defined(OPENSSL_NO_SSL2) + addbool(m, "HAS_SSLv2", 1); +#else + addbool(m, "HAS_SSLv2", 0); +#endif + +#if defined(SSL3_VERSION) && !defined(OPENSSL_NO_SSL3) + addbool(m, "HAS_SSLv3", 1); +#else + addbool(m, "HAS_SSLv3", 0); +#endif + +#if defined(TLS1_VERSION) && !defined(OPENSSL_NO_TLS1) + addbool(m, "HAS_TLSv1", 1); +#else + addbool(m, "HAS_TLSv1", 0); +#endif + +#if defined(TLS1_1_VERSION) && !defined(OPENSSL_NO_TLS1_1) + addbool(m, "HAS_TLSv1_1", 1); +#else + addbool(m, "HAS_TLSv1_1", 0); +#endif + +#if defined(TLS1_2_VERSION) && !defined(OPENSSL_NO_TLS1_2) + addbool(m, "HAS_TLSv1_2", 1); #else - r = Py_False; + addbool(m, "HAS_TLSv1_2", 0); #endif - Py_INCREF(r); - PyModule_AddObject(m, "HAS_ALPN", r); #if defined(TLS1_3_VERSION) && !defined(OPENSSL_NO_TLS1_3) - r = Py_True; + addbool(m, "HAS_TLSv1_3", 1); #else - r = Py_False; + addbool(m, "HAS_TLSv1_3", 0); #endif - Py_INCREF(r); - PyModule_AddObject(m, "HAS_TLSv1_3", r); /* Mappings for error codes */ err_codes_to_names = PyDict_New(); From webhook-mailer at python.org Tue Feb 27 14:41:33 2018 From: webhook-mailer at python.org (Alexander Belopolsky) Date: Tue, 27 Feb 2018 19:41:33 -0000 Subject: [Python-checkins] bpo-10381, bpo-32403: What's new entries for changes to datetime (gh-5814) Message-ID: https://github.com/python/cpython/commit/5bd04f964b4f1bcdbd0fa36de04f087c2db07cfe commit: 5bd04f964b4f1bcdbd0fa36de04f087c2db07cfe branch: master author: Paul Ganssle committer: Alexander Belopolsky date: 2018-02-27T14:41:30-05:00 summary: bpo-10381, bpo-32403: What's new entries for changes to datetime (gh-5814) * Add What's New entry for addition of datetime.timezone to the C API Closes bpo-10381 * Add what's new entry for date and datetime optimizations Closes bpo-32403 files: M Doc/whatsnew/3.7.rst diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index fa2d472820c9..46f4f13aab47 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -886,6 +886,11 @@ Optimizations 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 ======================= @@ -936,6 +941,11 @@ Build and C API Changes * 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`. + Other CPython Implementation Changes ==================================== From webhook-mailer at python.org Tue Feb 27 14:58:31 2018 From: webhook-mailer at python.org (Alexander Belopolsky) Date: Tue, 27 Feb 2018 19:58:31 -0000 Subject: [Python-checkins] bpo-10381, bpo-32403: What's new entries for changes to datetime (gh-5814) (gh-5929) Message-ID: https://github.com/python/cpython/commit/fff596f792a0752b0e571fa57809e5752aba6353 commit: fff596f792a0752b0e571fa57809e5752aba6353 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Alexander Belopolsky date: 2018-02-27T14:58:28-05:00 summary: bpo-10381, bpo-32403: What's new entries for changes to datetime (gh-5814) (gh-5929) * Add What's New entry for addition of datetime.timezone to the C API Closes bpo-10381 * Add what's new entry for date and datetime optimizations Closes bpo-32403 (cherry picked from commit 5bd04f964b4f1bcdbd0fa36de04f087c2db07cfe) Co-authored-by: Paul Ganssle files: M Doc/whatsnew/3.7.rst diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst index d1eeec209e65..8fa39abc6ace 100644 --- a/Doc/whatsnew/3.7.rst +++ b/Doc/whatsnew/3.7.rst @@ -878,6 +878,11 @@ Optimizations 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 ======================= @@ -928,6 +933,11 @@ Build and C API Changes * 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`. + Other CPython Implementation Changes ==================================== From webhook-mailer at python.org Tue Feb 27 15:40:40 2018 From: webhook-mailer at python.org (Antoine Pitrou) Date: Tue, 27 Feb 2018 20:40:40 -0000 Subject: [Python-checkins] bpo-31355: Travis-CI: re-enable macOS job (#5858) Message-ID: https://github.com/python/cpython/commit/d7687eb4b66c9f675b112eff1169326a1766c111 commit: d7687eb4b66c9f675b112eff1169326a1766c111 branch: master author: Antoine Pitrou committer: GitHub date: 2018-02-27T21:40:37+01:00 summary: bpo-31355: Travis-CI: re-enable macOS job (#5858) The long build queues that plagued macOS builds on Travis seem to be a thing of the past now. files: M .travis.yml M Tools/scripts/smelly.py diff --git a/.travis.yml b/.travis.yml index ab43318975fb..292b9c687638 100644 --- a/.travis.yml +++ b/.travis.yml @@ -52,6 +52,15 @@ matrix: - python -m pip install sphinx~=1.6.1 blurb script: - make check suspicious html SPHINXOPTS="-q -W -j4" + - os: osx + language: c + compiler: clang + # Testing under macOS is optional until testing stability has been demonstrated. + env: OPTIONAL=true + before_install: + # Python 3 is needed for Argument Clinic and multissl + - brew install xz python3 + - export PATH=$(brew --prefix)/bin:$(brew --prefix)/sbin:$PATH - os: linux language: c compiler: gcc @@ -76,9 +85,9 @@ before_install: - set -e - | # Check short-circuit conditions - if [ "${TESTING}" != "docs" ] + if [[ "${TESTING}" != "docs" ]] then - if [ "$TRAVIS_PULL_REQUEST" = "false" ] + if [[ "$TRAVIS_PULL_REQUEST" == "false" ]] then echo "Not a PR, doing full build." else @@ -101,7 +110,7 @@ before_install: install: - | # Install OpenSSL as necessary - if [ "${TESTING}" != "docs" ] + if [[ "${TESTING}" != "docs" ]] then # clang complains about unused-parameter a lot, redirect stderr python3 Tools/ssl/multissltests.py --steps=library \ diff --git a/Tools/scripts/smelly.py b/Tools/scripts/smelly.py index 212eedb30bc3..43d091654d2d 100755 --- a/Tools/scripts/smelly.py +++ b/Tools/scripts/smelly.py @@ -27,6 +27,11 @@ def get_exported_symbols(): def get_smelly_symbols(stdout): symbols = [] ignored_symtypes = set() + + allowed_prefixes = ('Py', '_Py') + if sys.platform == 'darwin': + allowed_prefixes += ('__Py',) + for line in stdout.splitlines(): # Split line '0000000000001b80 D PyTextIOWrapper_Type' if not line: @@ -47,7 +52,7 @@ def get_smelly_symbols(stdout): continue symbol = parts[-1] - if symbol.startswith(('Py', '_Py')): + if symbol.startswith(allowed_prefixes): continue symbol = '%s (type: %s)' % (symbol, symtype) symbols.append(symbol) From webhook-mailer at python.org Tue Feb 27 17:38:22 2018 From: webhook-mailer at python.org (Ned Deily) Date: Tue, 27 Feb 2018 22:38:22 -0000 Subject: [Python-checkins] bpo-32901: update macOS 10.9+ installer to Tcl/Tk 8.6.8 Message-ID: https://github.com/python/cpython/commit/9189e95d9c6691de18783b2e9213ec2dc18fd0c5 commit: 9189e95d9c6691de18783b2e9213ec2dc18fd0c5 branch: master author: Ned Deily committer: Ned Deily date: 2018-02-27T17:36:12-05:00 summary: bpo-32901: update macOS 10.9+ installer to Tcl/Tk 8.6.8 files: A Mac/BuildScript/tk868_on_10_8_10_9.patch A Misc/NEWS.d/next/macOS/2018-02-27-17-33-15.bpo-32901.hQu0w3.rst M Mac/BuildScript/build-installer.py diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index bacdbfb0feba..7f6228ba444f 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -225,9 +225,9 @@ def library_recipes(): if internalTk(): result.extend([ dict( - name="Tcl 8.6.7", - url="ftp://ftp.tcl.tk/pub/tcl//tcl8_6/tcl8.6.7-src.tar.gz", - checksum='5673aaf45b5de5d8dd80bb3daaeb8838', + name="Tcl 8.6.8", + url="ftp://ftp.tcl.tk/pub/tcl//tcl8_6/tcl8.6.8-src.tar.gz", + checksum='81656d3367af032e0ae6157eff134f89', buildDir="unix", configure_pre=[ '--enable-shared', @@ -241,9 +241,12 @@ def library_recipes(): }, ), dict( - name="Tk 8.6.7", - url="ftp://ftp.tcl.tk/pub/tcl//tcl8_6/tk8.6.7-src.tar.gz", - checksum='46ea9c0165c515d87393700f4891ab6f', + name="Tk 8.6.8", + url="ftp://ftp.tcl.tk/pub/tcl//tcl8_6/tk8.6.8-src.tar.gz", + checksum='5e0faecba458ee1386078fb228d008ba', + patches=[ + "tk868_on_10_8_10_9.patch", + ], buildDir="unix", configure_pre=[ '--enable-aqua', diff --git a/Mac/BuildScript/tk868_on_10_8_10_9.patch b/Mac/BuildScript/tk868_on_10_8_10_9.patch new file mode 100644 index 000000000000..8fe10604a68c --- /dev/null +++ b/Mac/BuildScript/tk868_on_10_8_10_9.patch @@ -0,0 +1,18 @@ +Fix build failure with +quartz variant on OS X 10.8 and 10.9. +Even though Gestalt was deprecated in OS X 10.8, it should work fine +through OS X 10.9, and its replacement NSOperatingSystemVersion was +not introduced until OS X 10.10. + +Patch from MacPorts project and reported upstream: +https://trac.macports.org/ticket/55649 +--- tk8.6.8/macosx/tkMacOSXXStubs.c.orig 2017-12-06 09:25:08.000000000 -0600 ++++ tk8.6.8-patched/macosx/tkMacOSXXStubs.c 2018-01-06 19:34:17.000000000 -0600 +@@ -175,7 +175,7 @@ + { + int major, minor, patch; + +-#if MAC_OS_X_VERSION_MIN_REQUIRED < 1080 ++#if MAC_OS_X_VERSION_MIN_REQUIRED < 101000 + Gestalt(gestaltSystemVersionMajor, (SInt32*)&major); + Gestalt(gestaltSystemVersionMinor, (SInt32*)&minor); + Gestalt(gestaltSystemVersionBugFix, (SInt32*)&patch); diff --git a/Misc/NEWS.d/next/macOS/2018-02-27-17-33-15.bpo-32901.hQu0w3.rst b/Misc/NEWS.d/next/macOS/2018-02-27-17-33-15.bpo-32901.hQu0w3.rst new file mode 100644 index 000000000000..73e69a9b7119 --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2018-02-27-17-33-15.bpo-32901.hQu0w3.rst @@ -0,0 +1 @@ +Update macOS 10.9+ installer to Tcl/Tk 8.6.8. From webhook-mailer at python.org Tue Feb 27 17:40:21 2018 From: webhook-mailer at python.org (Ned Deily) Date: Tue, 27 Feb 2018 22:40:21 -0000 Subject: [Python-checkins] Update macOS installer resources Message-ID: https://github.com/python/cpython/commit/cc5ac04c07097218477064a38d551f62fe682447 commit: cc5ac04c07097218477064a38d551f62fe682447 branch: master author: Ned Deily committer: Ned Deily date: 2018-02-27T17:39:50-05:00 summary: Update macOS installer resources files: M Mac/BuildScript/resources/ReadMe.rtf M Mac/BuildScript/resources/Welcome.rtf M Mac/BuildScript/scripts/postflight.documentation diff --git a/Mac/BuildScript/resources/ReadMe.rtf b/Mac/BuildScript/resources/ReadMe.rtf index cb005af7f051..aecbaa353cbf 100644 --- a/Mac/BuildScript/resources/ReadMe.rtf +++ b/Mac/BuildScript/resources/ReadMe.rtf @@ -5,7 +5,7 @@ \margl1440\margr1440\vieww13380\viewh14600\viewkind0 \pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0 -\f0\fs24 \cf0 This package will install Python $FULL_VERSION for Mac OS X $MACOSX_DEPLOYMENT_TARGET for the following architecture(s): $ARCHITECTURES.\ +\f0\fs24 \cf0 This package will install Python $FULL_VERSION for macOS $MACOSX_DEPLOYMENT_TARGET for the following architecture(s): $ARCHITECTURES.\ \ \pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\partightenfactor0 @@ -19,32 +19,18 @@ \b0 \ulnone \ \ For Python.3.7, python.org currently provides two installer variants for download: one that installs a -\i 64-bit/32-bit Intel -\i0 Python capable of running on -\i macOS 10.6 (Snow Leopard) -\i0 or later; and one that installs a \i 64-bit-only \i0 Python capable of running on \i macOS 10.9 (Mavericks) -\i0 or later. This ReadMe was installed with the +\i0 or later; and one that installs a +\i 64-bit/32-bit Intel +\i0 Python capable of running on +\i macOS 10.6 (Snow Leopard) +\i0 or later. (This ReadMe was installed with the \i $MACOSX_DEPLOYMENT_TARGET -\i0 variant. Use the 10.6 variant if you are running on macOS 10.6 through 10.8 or if you want to produce standalone applications that can run on systems from 10.6. If you are running on macOS 10.9 or later and if you have no need for compatibility with older systems, use the 10.9 variant. The Pythons installed by these installers are built with private copies of some third-party libraries not included with or newer than those in macOS itself. The list of these libraries varies by installer variant and is included at the end of the License.rtf file. +\i0 variant.) If you are running on macOS 10.9 or later and if you have no need for compatibility with older systems, use the 10.9 variant. Use the 10.6 variant if you are running on macOS 10.6 through 10.8 or if you want to produce standalone applications that can run on systems from 10.6. The Pythons installed by these installers are built with private copies of some third-party libraries not included with or newer than those in macOS itself. The list of these libraries varies by installer variant and is included at the end of the License.rtf file. \b \ul \ \ -Using IDLE or other Tk applications [NEW/CHANGED in 3.7.0b1] -\b0 \ulnone \ -\ -The 10.9+ installer variant comes with its own private version of Tcl/Tk 8.6. It does not use system-supplied or third-party supplied versions of Tcl/Tk.\ -\ -\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0 -\cf0 For the 10.6+ variant, you continue to need to install a newer third-party version of the -\i Tcl/Tk -\i0 8.5 (not 8.6) frameworks to use IDLE or other programs that use the Tkinter graphical user interface toolkit. Visit {\field{\*\fldinst{HYPERLINK "https://www.python.org/download/mac/tcltk/"}}{\fldrslt https://www.python.org/download/mac/tcltk/}} for current information about supported and recommended versions of -\i Tcl/Tk -\i0 for this version of Python and of macOS.\ -\pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0 - -\b \cf0 \ul \ulc0 \ Certificate verification and OpenSSL \{UPDATED in 3.7.0b1]\ \b0 \ulnone \ @@ -67,7 +53,19 @@ The bundled \f0 included with this installer has its own default certificate store for verifying download connections.\ \ -\b \ul Other changes\ +\b \ul Using IDLE or other Tk applications [NEW/CHANGED in 3.7.0b1] +\b0 \ulnone \ +\ +The 10.9+ installer variant comes with its own private version of Tcl/Tk 8.6. It does not use system-supplied or third-party supplied versions of Tcl/Tk.\ +\ +For the 10.6+ variant, you continue to need to install a newer third-party version of the +\i Tcl/Tk +\i0 8.5 (not 8.6) frameworks to use IDLE or other programs that use the Tkinter graphical user interface toolkit. Visit {\field{\*\fldinst{HYPERLINK "https://www.python.org/download/mac/tcltk/"}}{\fldrslt https://www.python.org/download/mac/tcltk/}} for current information about supported and recommended versions of +\i Tcl/Tk +\i0 for this version of Python and of macOS.\ + +\b \ul \ +Other changes\ \b0 \ulnone \ For other changes in this release, see the diff --git a/Mac/BuildScript/resources/Welcome.rtf b/Mac/BuildScript/resources/Welcome.rtf index 4908fed0eaa5..92a843077d78 100644 --- a/Mac/BuildScript/resources/Welcome.rtf +++ b/Mac/BuildScript/resources/Welcome.rtf @@ -8,12 +8,12 @@ \f0\fs24 \cf0 This package will install \b Python $FULL_VERSION \b0 for -\b Mac OS X $MACOSX_DEPLOYMENT_TARGET +\b macOS $MACOSX_DEPLOYMENT_TARGET \b0 .\ \ -\b Python for Mac OS X -\b0 consists of the Python programming language interpreter, plus a set of programs to allow easy access to it for Mac OS X users including an integrated development environment +\b Python for macOS +\b0 consists of the Python programming language interpreter, plus a set of programs to allow easy access to it for macOS users including an integrated development environment \b IDLE \b0 .\ \ @@ -24,13 +24,4 @@ \b NEW in 3.7.0b1: \b0 two installer variants (10.9+ 64-bit-only, 10.6+ 64-/32-bit), built-in Tcl/Tk 8.6 support in the 10.9+ variant (no additional third-party downloads!), OpenSSL 1.1.0g, and more!\ -\ - -\b IMPORTANT: -\b0 -\b IDLE -\b0 and other programs using the -\b tkinter -\b0 graphical user interface toolkit require specific versions of the -\b Tcl/Tk -\b0 platform independent windowing toolkit. Visit {\field{\*\fldinst{HYPERLINK "https://www.python.org/download/mac/tcltk/"}}{\fldrslt https://www.python.org/download/mac/tcltk/}} for current information on supported and recommended versions of Tcl/Tk for this version of Python and Mac OS X.} \ No newline at end of file +} \ No newline at end of file diff --git a/Mac/BuildScript/scripts/postflight.documentation b/Mac/BuildScript/scripts/postflight.documentation index b9f28a515215..3cbbc1bf10ca 100755 --- a/Mac/BuildScript/scripts/postflight.documentation +++ b/Mac/BuildScript/scripts/postflight.documentation @@ -12,6 +12,7 @@ SHARE_DOCDIR_TO_FWK="../../.." # make link in /Applications/Python m.n/ for Finder users if [ -d "${APPDIR}" ]; then ln -fhs "${FWK_DOCDIR}/index.html" "${APPDIR}/Python Documentation.html" + open "${APPDIR}" || true # open the applications folder fi # make share/doc link in framework for command line users From webhook-mailer at python.org Tue Feb 27 17:45:21 2018 From: webhook-mailer at python.org (Ned Deily) Date: Tue, 27 Feb 2018 22:45:21 -0000 Subject: [Python-checkins] bpo-32901: update macOS 10.9+ installer to Tcl/Tk 8.6.8 Message-ID: https://github.com/python/cpython/commit/a7edca7122cb952874e74d64d693c5b938c758cb commit: a7edca7122cb952874e74d64d693c5b938c758cb branch: 3.7 author: Ned Deily committer: Ned Deily date: 2018-02-27T17:43:53-05:00 summary: bpo-32901: update macOS 10.9+ installer to Tcl/Tk 8.6.8 files: A Mac/BuildScript/tk868_on_10_8_10_9.patch A Misc/NEWS.d/next/macOS/2018-02-27-17-33-15.bpo-32901.hQu0w3.rst M Mac/BuildScript/build-installer.py diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py index bacdbfb0feba..7f6228ba444f 100755 --- a/Mac/BuildScript/build-installer.py +++ b/Mac/BuildScript/build-installer.py @@ -225,9 +225,9 @@ def library_recipes(): if internalTk(): result.extend([ dict( - name="Tcl 8.6.7", - url="ftp://ftp.tcl.tk/pub/tcl//tcl8_6/tcl8.6.7-src.tar.gz", - checksum='5673aaf45b5de5d8dd80bb3daaeb8838', + name="Tcl 8.6.8", + url="ftp://ftp.tcl.tk/pub/tcl//tcl8_6/tcl8.6.8-src.tar.gz", + checksum='81656d3367af032e0ae6157eff134f89', buildDir="unix", configure_pre=[ '--enable-shared', @@ -241,9 +241,12 @@ def library_recipes(): }, ), dict( - name="Tk 8.6.7", - url="ftp://ftp.tcl.tk/pub/tcl//tcl8_6/tk8.6.7-src.tar.gz", - checksum='46ea9c0165c515d87393700f4891ab6f', + name="Tk 8.6.8", + url="ftp://ftp.tcl.tk/pub/tcl//tcl8_6/tk8.6.8-src.tar.gz", + checksum='5e0faecba458ee1386078fb228d008ba', + patches=[ + "tk868_on_10_8_10_9.patch", + ], buildDir="unix", configure_pre=[ '--enable-aqua', diff --git a/Mac/BuildScript/tk868_on_10_8_10_9.patch b/Mac/BuildScript/tk868_on_10_8_10_9.patch new file mode 100644 index 000000000000..8fe10604a68c --- /dev/null +++ b/Mac/BuildScript/tk868_on_10_8_10_9.patch @@ -0,0 +1,18 @@ +Fix build failure with +quartz variant on OS X 10.8 and 10.9. +Even though Gestalt was deprecated in OS X 10.8, it should work fine +through OS X 10.9, and its replacement NSOperatingSystemVersion was +not introduced until OS X 10.10. + +Patch from MacPorts project and reported upstream: +https://trac.macports.org/ticket/55649 +--- tk8.6.8/macosx/tkMacOSXXStubs.c.orig 2017-12-06 09:25:08.000000000 -0600 ++++ tk8.6.8-patched/macosx/tkMacOSXXStubs.c 2018-01-06 19:34:17.000000000 -0600 +@@ -175,7 +175,7 @@ + { + int major, minor, patch; + +-#if MAC_OS_X_VERSION_MIN_REQUIRED < 1080 ++#if MAC_OS_X_VERSION_MIN_REQUIRED < 101000 + Gestalt(gestaltSystemVersionMajor, (SInt32*)&major); + Gestalt(gestaltSystemVersionMinor, (SInt32*)&minor); + Gestalt(gestaltSystemVersionBugFix, (SInt32*)&patch); diff --git a/Misc/NEWS.d/next/macOS/2018-02-27-17-33-15.bpo-32901.hQu0w3.rst b/Misc/NEWS.d/next/macOS/2018-02-27-17-33-15.bpo-32901.hQu0w3.rst new file mode 100644 index 000000000000..73e69a9b7119 --- /dev/null +++ b/Misc/NEWS.d/next/macOS/2018-02-27-17-33-15.bpo-32901.hQu0w3.rst @@ -0,0 +1 @@ +Update macOS 10.9+ installer to Tcl/Tk 8.6.8. From webhook-mailer at python.org Tue Feb 27 18:03:50 2018 From: webhook-mailer at python.org (Ned Deily) Date: Tue, 27 Feb 2018 23:03:50 -0000 Subject: [Python-checkins] Revert "bpo-31961: subprocess now accepts path-like args (GH-4329)" (#5912) Message-ID: https://github.com/python/cpython/commit/be50a7b627d0aa37e08fa8e2d5568891f19903ce commit: be50a7b627d0aa37e08fa8e2d5568891f19903ce branch: master author: Serhiy Storchaka committer: Ned Deily date: 2018-02-27T18:03:46-05:00 summary: Revert "bpo-31961: subprocess now accepts path-like args (GH-4329)" (#5912) * Revert "bpo-31961: subprocess now accepts path-like args (GH-4329)" This reverts commit dd42cb71f2cb02f3a32f016137b12a146bc0d0e2. files: M Doc/library/subprocess.rst M Lib/subprocess.py M Lib/test/test_subprocess.py M Misc/NEWS.d/3.7.0b1.rst diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst index a22afe041850..db7a88af6bea 100644 --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -339,12 +339,12 @@ functions. the class uses the Windows ``CreateProcess()`` function. The arguments to :class:`Popen` are as follows. - *args* should be a sequence of program arguments or else a single string or - :term:`path-like object`. By default, the program to execute is the first - item in *args* if *args* is a sequence. If *args* is a string, the - interpretation is platform-dependent and described below. See the *shell* - and *executable* arguments for additional differences from the default - behavior. Unless otherwise stated, it is recommended to pass *args* as a sequence. + *args* should be a sequence of program arguments or else a single string. + By default, the program to execute is the first item in *args* if *args* is + a sequence. If *args* is a string, the interpretation is + platform-dependent and described below. See the *shell* and *executable* + arguments for additional differences from the default behavior. Unless + otherwise stated, it is recommended to pass *args* as a sequence. On POSIX, if *args* is a string, the string is interpreted as the name or path of the program to execute. However, this can only be done if not @@ -558,10 +558,6 @@ functions. Popen destructor now emits a :exc:`ResourceWarning` warning if the child process is still running. - .. versionchanged:: 3.7 - *args*, or the first element of *args* if *args* is a sequence, can now - be a :term:`path-like object`. - Exceptions ^^^^^^^^^^ diff --git a/Lib/subprocess.py b/Lib/subprocess.py index 2723bc9e4274..93635ee61f7e 100644 --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -1097,12 +1097,7 @@ def _execute_child(self, args, executable, preexec_fn, close_fds, assert not pass_fds, "pass_fds not supported on Windows." if not isinstance(args, str): - try: - args = os.fsdecode(args) # os.PathLike -> str - except TypeError: # not an os.PathLike, must be a sequence. - args = list(args) - args[0] = os.fsdecode(args[0]) # os.PathLike -> str - args = list2cmdline(args) + args = list2cmdline(args) # Process startup details if startupinfo is None: @@ -1374,10 +1369,7 @@ def _execute_child(self, args, executable, preexec_fn, close_fds, if isinstance(args, (str, bytes)): args = [args] else: - try: - args = list(args) - except TypeError: # os.PathLike instead of a sequence? - args = [os.fsencode(args)] # os.PathLike -> [str] + args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index b3ccb0de63a8..46cb5f117e84 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -1475,37 +1475,6 @@ def test_run_kwargs(self): env=newenv) self.assertEqual(cp.returncode, 33) - def test_run_with_pathlike_path(self): - # bpo-31961: test run(pathlike_object) - class Path: - def __fspath__(self): - # the name of a command that can be run without - # any argumenets that exit fast - return 'dir' if mswindows else 'ls' - - path = Path() - if mswindows: - res = subprocess.run(path, stdout=subprocess.DEVNULL, shell=True) - else: - res = subprocess.run(path, stdout=subprocess.DEVNULL) - - self.assertEqual(res.returncode, 0) - - def test_run_with_pathlike_path_and_arguments(self): - # bpo-31961: test run([pathlike_object, 'additional arguments']) - class Path: - def __fspath__(self): - # the name of a command that can be run without - # any argumenets that exits fast - return sys.executable - - path = Path() - - args = [path, '-c', 'import sys; sys.exit(57)'] - res = subprocess.run(args) - - self.assertEqual(res.returncode, 57) - def test_capture_output(self): cp = self.run_python(("import sys;" "sys.stdout.write('BDFL'); " diff --git a/Misc/NEWS.d/3.7.0b1.rst b/Misc/NEWS.d/3.7.0b1.rst index bd3a6111df0b..ec7b3c8ecf78 100644 --- a/Misc/NEWS.d/3.7.0b1.rst +++ b/Misc/NEWS.d/3.7.0b1.rst @@ -630,6 +630,7 @@ Add contextlib.AsyncExitStack. Patch by Alexander Mohr and Ilya Kulakov. .. nonce: x5Sv0R .. section: Library +*Removed in Python 3.7.0b2.* The *args* argument of subprocess.Popen can now be a :term:`path-like object`. If *args* is given as a sequence, it's first element can now be a :term:`path-like object` as well. From webhook-mailer at python.org Tue Feb 27 18:30:37 2018 From: webhook-mailer at python.org (Ned Deily) Date: Tue, 27 Feb 2018 23:30:37 -0000 Subject: [Python-checkins] Revert "bpo-31961: subprocess now accepts path-like args (GH-4329)" (GH-5912) (GH-5931) Message-ID: https://github.com/python/cpython/commit/b7dcae358e9d5a3ac9dafec9f6b64e9a66843ad8 commit: b7dcae358e9d5a3ac9dafec9f6b64e9a66843ad8 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: Ned Deily date: 2018-02-27T18:30:30-05:00 summary: Revert "bpo-31961: subprocess now accepts path-like args (GH-4329)" (GH-5912) (GH-5931) * Revert "bpo-31961: subprocess now accepts path-like args (GH-4329)" This reverts commit dd42cb71f2cb02f3a32f016137b12a146bc0d0e2. (cherry picked from commit be50a7b627d0aa37e08fa8e2d5568891f19903ce) Co-authored-by: Serhiy Storchaka files: M Doc/library/subprocess.rst M Lib/subprocess.py M Lib/test/test_subprocess.py M Misc/NEWS.d/3.7.0b1.rst diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst index a22afe041850..db7a88af6bea 100644 --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -339,12 +339,12 @@ functions. the class uses the Windows ``CreateProcess()`` function. The arguments to :class:`Popen` are as follows. - *args* should be a sequence of program arguments or else a single string or - :term:`path-like object`. By default, the program to execute is the first - item in *args* if *args* is a sequence. If *args* is a string, the - interpretation is platform-dependent and described below. See the *shell* - and *executable* arguments for additional differences from the default - behavior. Unless otherwise stated, it is recommended to pass *args* as a sequence. + *args* should be a sequence of program arguments or else a single string. + By default, the program to execute is the first item in *args* if *args* is + a sequence. If *args* is a string, the interpretation is + platform-dependent and described below. See the *shell* and *executable* + arguments for additional differences from the default behavior. Unless + otherwise stated, it is recommended to pass *args* as a sequence. On POSIX, if *args* is a string, the string is interpreted as the name or path of the program to execute. However, this can only be done if not @@ -558,10 +558,6 @@ functions. Popen destructor now emits a :exc:`ResourceWarning` warning if the child process is still running. - .. versionchanged:: 3.7 - *args*, or the first element of *args* if *args* is a sequence, can now - be a :term:`path-like object`. - Exceptions ^^^^^^^^^^ diff --git a/Lib/subprocess.py b/Lib/subprocess.py index 2723bc9e4274..93635ee61f7e 100644 --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -1097,12 +1097,7 @@ def _execute_child(self, args, executable, preexec_fn, close_fds, assert not pass_fds, "pass_fds not supported on Windows." if not isinstance(args, str): - try: - args = os.fsdecode(args) # os.PathLike -> str - except TypeError: # not an os.PathLike, must be a sequence. - args = list(args) - args[0] = os.fsdecode(args[0]) # os.PathLike -> str - args = list2cmdline(args) + args = list2cmdline(args) # Process startup details if startupinfo is None: @@ -1374,10 +1369,7 @@ def _execute_child(self, args, executable, preexec_fn, close_fds, if isinstance(args, (str, bytes)): args = [args] else: - try: - args = list(args) - except TypeError: # os.PathLike instead of a sequence? - args = [os.fsencode(args)] # os.PathLike -> [str] + args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index b3ccb0de63a8..46cb5f117e84 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -1475,37 +1475,6 @@ def test_run_kwargs(self): env=newenv) self.assertEqual(cp.returncode, 33) - def test_run_with_pathlike_path(self): - # bpo-31961: test run(pathlike_object) - class Path: - def __fspath__(self): - # the name of a command that can be run without - # any argumenets that exit fast - return 'dir' if mswindows else 'ls' - - path = Path() - if mswindows: - res = subprocess.run(path, stdout=subprocess.DEVNULL, shell=True) - else: - res = subprocess.run(path, stdout=subprocess.DEVNULL) - - self.assertEqual(res.returncode, 0) - - def test_run_with_pathlike_path_and_arguments(self): - # bpo-31961: test run([pathlike_object, 'additional arguments']) - class Path: - def __fspath__(self): - # the name of a command that can be run without - # any argumenets that exits fast - return sys.executable - - path = Path() - - args = [path, '-c', 'import sys; sys.exit(57)'] - res = subprocess.run(args) - - self.assertEqual(res.returncode, 57) - def test_capture_output(self): cp = self.run_python(("import sys;" "sys.stdout.write('BDFL'); " diff --git a/Misc/NEWS.d/3.7.0b1.rst b/Misc/NEWS.d/3.7.0b1.rst index bd3a6111df0b..ec7b3c8ecf78 100644 --- a/Misc/NEWS.d/3.7.0b1.rst +++ b/Misc/NEWS.d/3.7.0b1.rst @@ -630,6 +630,7 @@ Add contextlib.AsyncExitStack. Patch by Alexander Mohr and Ilya Kulakov. .. nonce: x5Sv0R .. section: Library +*Removed in Python 3.7.0b2.* The *args* argument of subprocess.Popen can now be a :term:`path-like object`. If *args* is given as a sequence, it's first element can now be a :term:`path-like object` as well. From webhook-mailer at python.org Tue Feb 27 18:36:24 2018 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Tue, 27 Feb 2018 23:36:24 -0000 Subject: [Python-checkins] bpo-30928: Update idlelib/NEWS.txt, possibly for 3.7.0b2 (GH-5932) Message-ID: https://github.com/python/cpython/commit/0954c9e9c8fbea452f56120df592f2061d3209c7 commit: 0954c9e9c8fbea452f56120df592f2061d3209c7 branch: master author: Terry Jan Reedy committer: GitHub date: 2018-02-27T18:36:21-05:00 summary: bpo-30928: Update idlelib/NEWS.txt, possibly for 3.7.0b2 (GH-5932) files: M Lib/idlelib/NEWS.txt diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index d616a740d5f5..c4aab2ee78b0 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -3,6 +3,22 @@ Released on 2018-06-18? ====================================== +bpo-32916: Change 'str' to 'code' in idlelib.pyparse and users. + +bpo-32905: Remove unused code in pyparse module. + +bpo-32874: IDLE - add pyparse tests with 97% coverage. + +bpo-32837: IDLE - require encoding argument for textview.view_file. +Using the system and place-dependent default encoding for open() +is a bad idea for IDLE's system and location-independent files. + +bpo-32826: Add "encoding=utf-8" to open() in IDLE's test_help_about. +GUI test test_file_buttons() only looks at initial ascii-only lines, +but failed on systems where open() defaults to 'ascii' because +readline() internally reads and decodes far enough ahead to encounter +a non-ascii character in CREDITS.txt. + bpo-32765: Update configdialog General tab create page docstring. Add new widgets to the widget list. From webhook-mailer at python.org Tue Feb 27 19:07:51 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 28 Feb 2018 00:07:51 -0000 Subject: [Python-checkins] bpo-30928: Update idlelib/NEWS.txt, possibly for 3.7.0b2 (GH-5932) Message-ID: https://github.com/python/cpython/commit/0ea49fc0bfa10205895f9fb78b4d6659b2946883 commit: 0ea49fc0bfa10205895f9fb78b4d6659b2946883 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-27T16:07:45-08:00 summary: bpo-30928: Update idlelib/NEWS.txt, possibly for 3.7.0b2 (GH-5932) (cherry picked from commit 0954c9e9c8fbea452f56120df592f2061d3209c7) Co-authored-by: Terry Jan Reedy files: M Lib/idlelib/NEWS.txt diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index d616a740d5f5..c4aab2ee78b0 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -3,6 +3,22 @@ Released on 2018-06-18? ====================================== +bpo-32916: Change 'str' to 'code' in idlelib.pyparse and users. + +bpo-32905: Remove unused code in pyparse module. + +bpo-32874: IDLE - add pyparse tests with 97% coverage. + +bpo-32837: IDLE - require encoding argument for textview.view_file. +Using the system and place-dependent default encoding for open() +is a bad idea for IDLE's system and location-independent files. + +bpo-32826: Add "encoding=utf-8" to open() in IDLE's test_help_about. +GUI test test_file_buttons() only looks at initial ascii-only lines, +but failed on systems where open() defaults to 'ascii' because +readline() internally reads and decodes far enough ahead to encounter +a non-ascii character in CREDITS.txt. + bpo-32765: Update configdialog General tab create page docstring. Add new widgets to the widget list. From webhook-mailer at python.org Tue Feb 27 19:31:33 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 28 Feb 2018 00:31:33 -0000 Subject: [Python-checkins] bpo-30928: Update idlelib/NEWS.txt, possibly for 3.7.0b2 (GH-5932) Message-ID: https://github.com/python/cpython/commit/8c65360dd0c1ea5b5d2e60a0694daf3f9df8f56b commit: 8c65360dd0c1ea5b5d2e60a0694daf3f9df8f56b branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-27T16:31:25-08:00 summary: bpo-30928: Update idlelib/NEWS.txt, possibly for 3.7.0b2 (GH-5932) (cherry picked from commit 0954c9e9c8fbea452f56120df592f2061d3209c7) Co-authored-by: Terry Jan Reedy files: M Lib/idlelib/NEWS.txt diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index d82fde26f28f..1ef8a617c4ad 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -3,6 +3,22 @@ Released on 2017-03-26? ====================================== +bpo-32916: Change 'str' to 'code' in idlelib.pyparse and users. + +bpo-32905: Remove unused code in pyparse module. + +bpo-32874: IDLE - add pyparse tests with 97% coverage. + +bpo-32837: IDLE - require encoding argument for textview.view_file. +Using the system and place-dependent default encoding for open() +is a bad idea for IDLE's system and location-independent files. + +bpo-32826: Add "encoding=utf-8" to open() in IDLE's test_help_about. +GUI test test_file_buttons() only looks at initial ascii-only lines, +but failed on systems where open() defaults to 'ascii' because +readline() internally reads and decodes far enough ahead to encounter +a non-ascii character in CREDITS.txt. + bpo-32765: Update configdialog General tab create page docstring. Add new widgets to the widget list. From webhook-mailer at python.org Wed Feb 28 00:04:10 2018 From: webhook-mailer at python.org (Ned Deily) Date: Wed, 28 Feb 2018 05:04:10 -0000 Subject: [Python-checkins] Update NEWS, docs, and patchlevel for 3.7.0b2 Message-ID: https://github.com/python/cpython/commit/b0ef5c979b0c4e1df2286ac734160d7560fcce2c commit: b0ef5c979b0c4e1df2286ac734160d7560fcce2c branch: 3.7 author: Ned Deily committer: Ned Deily date: 2018-02-27T19:49:18-05:00 summary: Update NEWS, docs, and patchlevel for 3.7.0b2 files: A Misc/NEWS.d/3.7.0b2.rst D Misc/NEWS.d/next/Build/2018-02-21-12-46-00.bpo-32898.M15bZh.rst D Misc/NEWS.d/next/Core and Builtins/2018-01-26-21-20-21.bpo-32583.Fh3fau.rst D Misc/NEWS.d/next/Core and Builtins/2018-01-29-14-36-37.bpo-32711.8hQFJP.rst D Misc/NEWS.d/next/Core and Builtins/2018-02-01-10-16-28.bpo-32303.VsvhSl.rst D Misc/NEWS.d/next/Core and Builtins/2018-02-01-10-56-41.bpo-32305.dkU9Qa.rst D Misc/NEWS.d/next/Core and Builtins/2018-02-02-08-50-46.bpo-31356.MNwUOQ.rst D Misc/NEWS.d/next/Core and Builtins/2018-02-20-21-53-48.bpo-32889.J6eWy5.rst D Misc/NEWS.d/next/Documentation/2018-01-25-14-23-12.bpo-31972.w1m_8r.rst D Misc/NEWS.d/next/Documentation/2018-02-02-07-41-57.bpo-32614.LSqzGw.rst D Misc/NEWS.d/next/Documentation/2018-02-03-06-11-37.bpo-8722.MPyVyj.rst D Misc/NEWS.d/next/Documentation/2018-02-10-12-48-38.bpo-11015.-gUf34.rst D Misc/NEWS.d/next/Documentation/2018-02-10-15-16-04.bpo-32800.FyrqCk.rst D Misc/NEWS.d/next/Documentation/2018-02-14-11-10-41.bpo-32436.TTJ2jb.rst D Misc/NEWS.d/next/Documentation/2018-02-23-12-48-03.bpo-17232.tmuTKL.rst D Misc/NEWS.d/next/Documentation/2018-02-25-16-33-35.bpo-28124._uzkgq.rst D Misc/NEWS.d/next/IDLE/2018-02-04-17-52-54.bpo-32765.qm0eCu.rst D Misc/NEWS.d/next/IDLE/2018-02-12-11-05-22.bpo-32826.IxNZrk.rst D Misc/NEWS.d/next/IDLE/2018-02-12-17-22-48.bpo-32837.-33QPl.rst D Misc/NEWS.d/next/IDLE/2018-02-19-10-56-41.bpo-32874.6pZ9Gv.rst D Misc/NEWS.d/next/IDLE/2018-02-22-00-09-27.bpo-32905.VlXj0x.rst D Misc/NEWS.d/next/IDLE/2018-02-23-07-32-36.bpo-32916.4MsQ5F.rst D Misc/NEWS.d/next/Library/2017-11-27-15-09-49.bpo-30693.yC4mJ7.rst D Misc/NEWS.d/next/Library/2017-11-27-15-09-49.bpo-30693.yC4mJ8.rst D Misc/NEWS.d/next/Library/2017-12-06-10-10-10.bpo-32221.ideco_.rst D Misc/NEWS.d/next/Library/2018-01-18-13-09-00.bpo-32585.qpeijr.rst D Misc/NEWS.d/next/Library/2018-01-18-23-34-17.bpo-31848.M2cldy.rst D Misc/NEWS.d/next/Library/2018-01-20-23-17-25.bpo-24334.GZuQLv.rst D Misc/NEWS.d/next/Library/2018-01-21-15-01-50.bpo-31453.cZiZBe.rst D Misc/NEWS.d/next/Library/2018-01-30-17-46-18.bpo-32727.aHVsRC.rst D Misc/NEWS.d/next/Library/2018-02-01-01-34-47.bpo-32734.gCV9AD.rst D Misc/NEWS.d/next/Library/2018-02-01-15-53-35.bpo-32691.VLWVTq.rst D Misc/NEWS.d/next/Library/2018-02-01-17-54-08.bpo-32741.KUvOPL.rst D Misc/NEWS.d/next/Library/2018-02-05-13-31-42.bpo-32647.ktmfR_.rst D Misc/NEWS.d/next/Library/2018-02-05-21-28-28.bpo-32777.C-wIXF.rst D Misc/NEWS.d/next/Library/2018-02-06-17-58-15.bpo-32622.AE0Jz7.rst D Misc/NEWS.d/next/Library/2018-02-07-19-12-10.bpo-32775.-T77_c.rst D Misc/NEWS.d/next/Library/2018-02-08-00-47-07.bpo-32792.NtyDb4.rst D Misc/NEWS.d/next/Library/2018-02-09-14-44-43.bpo-30157.lEiiAK.rst D Misc/NEWS.d/next/Library/2018-02-09-21-41-56.bpo-31787.owSZ2t.rst D Misc/NEWS.d/next/Library/2018-02-10-13-51-56.bpo-32394.dFM9SI.rst D Misc/NEWS.d/next/Library/2018-02-11-15-54-41.bpo-32819.ZTRX2Q.rst D Misc/NEWS.d/next/Library/2018-02-14-00-21-24.bpo-32841.bvHDOc.rst D Misc/NEWS.d/next/Library/2018-02-15-08-18-52.bpo-31333.4fF-gM.rst D Misc/NEWS.d/next/Library/2018-02-15-12-04-29.bpo-32852.HDqIxM.rst D Misc/NEWS.d/next/Library/2018-02-17-19-20-19.bpo-21060.S1Z-x6.rst D Misc/NEWS.d/next/Library/2018-02-18-13-04-59.bpo-25988.ACidKC.rst D Misc/NEWS.d/next/Library/2018-02-19-14-27-51.bpo-32556.CsRsgr.rst D Misc/NEWS.d/next/Library/2018-02-19-17-46-31.bpo-32859.kAT-Xp.rst D Misc/NEWS.d/next/Library/2018-02-23-19-12-04.bpo-32922.u-xe0B.rst D Misc/NEWS.d/next/Library/2018-02-24-21-40-42.bpo-30622.dQjxSe.rst D Misc/NEWS.d/next/Library/2018-02-25-13-06-21.bpo-32947.mqStVW.rst D Misc/NEWS.d/next/Library/2018-02-25-13-47-48.bpo-32929.X2gTDH.rst D Misc/NEWS.d/next/Library/2018-02-25-18-22-01.bpo-32951.gHrCXq.rst D Misc/NEWS.d/next/Library/2018-02-26-13-16-36.bpo-32713.55yegW.rst D Misc/NEWS.d/next/Library/2018-02-26-20-04-40.bpo-32960.48r0Ml.rst D Misc/NEWS.d/next/Security/2017-08-06-14-43-45.bpo-28414.mzZ6vD.rst D Misc/NEWS.d/next/Tests/2017-10-18-18-07-45.bpo-31809.KlQrkE.rst D Misc/NEWS.d/next/Tools-Demos/2017-12-07-20-51-20.bpo-32222.hPBcGT.rst D Misc/NEWS.d/next/Windows/2018-02-07-17-50-48.bpo-29248.Xzwj-6.rst D Misc/NEWS.d/next/Windows/2018-02-10-15-38-19.bpo-32370.kcKuct.rst D Misc/NEWS.d/next/Windows/2018-02-19-08-54-06.bpo-32457.vVP0Iz.rst D Misc/NEWS.d/next/Windows/2018-02-19-10-00-57.bpo-32409.nocuDg.rst D Misc/NEWS.d/next/Windows/2018-02-19-13-54-42.bpo-31966._Q3HPb.rst D Misc/NEWS.d/next/Windows/2018-02-23-00-47-13.bpo-32901.mGKz5_.rst D Misc/NEWS.d/next/macOS/2018-02-27-17-33-15.bpo-32901.hQu0w3.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 028740523255..49b493a418e0 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 1 +#define PY_RELEASE_SERIAL 2 /* Version as a string */ -#define PY_VERSION "3.7.0b1+" +#define PY_VERSION "3.7.0b2" /*--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 a979931e266c..ede9385886a4 100644 --- a/Lib/pydoc_data/topics.py +++ b/Lib/pydoc_data/topics.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Autogenerated by Sphinx on Tue Jan 30 18:36:07 2018 +# Autogenerated by Sphinx on Tue Feb 27 19:39:14 2018 topics = {'assert': 'The "assert" statement\n' '**********************\n' '\n' @@ -483,15 +483,19 @@ '\n' 'object.__getattr__(self, name)\n' '\n' - ' Called when an attribute lookup has not found the ' - 'attribute in the\n' - ' usual places (i.e. it is not an instance attribute ' - 'nor is it found\n' - ' in the class tree for "self"). "name" is the ' - 'attribute name. This\n' - ' method should return the (computed) attribute value ' - 'or raise an\n' - ' "AttributeError" exception.\n' + ' Called when the default attribute access fails with ' + 'an\n' + ' "AttributeError" (either "__getattribute__()" raises ' + 'an\n' + ' "AttributeError" because *name* is not an instance ' + 'attribute or an\n' + ' attribute in the class tree for "self"; or ' + '"__get__()" of a *name*\n' + ' property raises "AttributeError"). This method ' + 'should either\n' + ' return the (computed) attribute value or raise an ' + '"AttributeError"\n' + ' exception.\n' '\n' ' Note that if the attribute is found through the ' 'normal mechanism,\n' @@ -4718,9 +4722,9 @@ 'conversion] [":" format_spec] "}"\n' ' field_name ::= arg_name ("." attribute_name | ' '"[" element_index "]")*\n' - ' arg_name ::= [identifier | integer]\n' + ' arg_name ::= [identifier | digit+]\n' ' attribute_name ::= identifier\n' - ' element_index ::= integer | index_string\n' + ' element_index ::= digit+ | index_string\n' ' index_string ::= +\n' ' conversion ::= "r" | "s" | "a"\n' @@ -4879,9 +4883,9 @@ ' fill ::= \n' ' align ::= "<" | ">" | "=" | "^"\n' ' sign ::= "+" | "-" | " "\n' - ' width ::= integer\n' + ' width ::= digit+\n' ' grouping_option ::= "_" | ","\n' - ' precision ::= integer\n' + ' precision ::= digit+\n' ' type ::= "b" | "c" | "d" | "e" | "E" | "f" | ' '"F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%"\n' '\n' @@ -8057,15 +8061,17 @@ '\n' 'object.__getattr__(self, name)\n' '\n' - ' Called when an attribute lookup has not found the ' - 'attribute in the\n' - ' usual places (i.e. it is not an instance attribute nor is ' - 'it found\n' - ' in the class tree for "self"). "name" is the attribute ' - 'name. This\n' - ' method should return the (computed) attribute value or ' - 'raise an\n' - ' "AttributeError" exception.\n' + ' Called when the default attribute access fails with an\n' + ' "AttributeError" (either "__getattribute__()" raises an\n' + ' "AttributeError" because *name* is not an instance ' + 'attribute or an\n' + ' attribute in the class tree for "self"; or "__get__()" of ' + 'a *name*\n' + ' property raises "AttributeError"). This method should ' + 'either\n' + ' return the (computed) attribute value or raise an ' + '"AttributeError"\n' + ' exception.\n' '\n' ' Note that if the attribute is found through the normal ' 'mechanism,\n' @@ -11599,7 +11605,9 @@ '\n' ' Frame objects\n' ' Frame objects represent execution frames. They may occur in\n' - ' traceback objects (see below).\n' + ' traceback objects (see below), and are also passed to ' + 'registered\n' + ' trace functions.\n' '\n' ' Special read-only attributes: "f_back" is to the previous ' 'stack\n' @@ -11654,44 +11662,59 @@ ' New in version 3.4.\n' '\n' ' Traceback objects\n' - ' Traceback objects represent a stack trace of an exception. ' - 'A\n' - ' traceback object is created when an exception occurs. When ' + ' Traceback objects represent a stack trace of an ' + 'exception. A\n' + ' traceback object is implicitly created when an exception\n' + ' occurs, and may also be explicitly created by calling\n' + ' "types.TracebackType".\n' + '\n' + ' For implicitly created tracebacks, when the search for an\n' + ' exception handler unwinds the execution stack, at each\n' + ' unwound level a traceback object is inserted in front of ' 'the\n' - ' search for an exception handler unwinds the execution stack, ' - 'at\n' - ' each unwound level a traceback object is inserted in front ' - 'of\n' - ' the current traceback. When an exception handler is ' - 'entered,\n' - ' the stack trace is made available to the program. (See ' - 'section\n' - ' The try statement.) It is accessible as the third item of ' + ' current traceback. When an exception handler is entered, ' 'the\n' - ' tuple returned by "sys.exc_info()". When the program contains ' - 'no\n' - ' suitable handler, the stack trace is written (nicely ' - 'formatted)\n' - ' to the standard error stream; if the interpreter is ' - 'interactive,\n' - ' it is also made available to the user as ' - '"sys.last_traceback".\n' - '\n' - ' Special read-only attributes: "tb_next" is the next level in ' + ' stack trace is made available to the program. (See ' + 'section\n' + ' The try statement.) It is accessible as the third item of ' 'the\n' - ' stack trace (towards the frame where the exception occurred), ' - 'or\n' - ' "None" if there is no next level; "tb_frame" points to the\n' - ' execution frame of the current level; "tb_lineno" gives the ' - 'line\n' - ' number where the exception occurred; "tb_lasti" indicates ' + ' tuple returned by "sys.exc_info()", and as the\n' + ' "__traceback__" attribute of the caught exception.\n' + '\n' + ' When the program contains no suitable handler, the stack\n' + ' trace is written (nicely formatted) to the standard error\n' + ' stream; if the interpreter is interactive, it is also ' + 'made\n' + ' available to the user as "sys.last_traceback".\n' + '\n' + ' For explicitly created tracebacks, it is up to the creator ' + 'of\n' + ' the traceback to determine how the "tb_next" attributes\n' + ' should be linked to form a full stack trace.\n' + '\n' + ' Special read-only attributes: "tb_frame" points to the\n' + ' execution frame of the current level; "tb_lineno" gives ' 'the\n' - ' precise instruction. The line number and last instruction ' + ' line number where the exception occurred; "tb_lasti"\n' + ' indicates the precise instruction. The line number and ' + 'last\n' + ' instruction in the traceback may differ from the line ' + 'number\n' + ' of its frame object if the exception occurred in a "try"\n' + ' statement with no matching except clause or with a ' + 'finally\n' + ' clause.\n' + '\n' + ' Special writable attribute: "tb_next" is the next level ' 'in\n' - ' the traceback may differ from the line number of its frame\n' - ' object if the exception occurred in a "try" statement with ' - 'no\n' - ' matching except clause or with a finally clause.\n' + ' the stack trace (towards the frame where the exception\n' + ' occurred), or "None" if there is no next level.\n' + '\n' + ' Changed in version 3.7: Traceback objects can now be ' + 'explicitly\n' + ' instantiated from Python code, and the "tb_next" attribute ' + 'of\n' + ' existing instances can be updated.\n' '\n' ' Slice objects\n' ' Slice objects are used to represent slices for ' diff --git a/Misc/NEWS.d/3.7.0b2.rst b/Misc/NEWS.d/3.7.0b2.rst new file mode 100644 index 000000000000..fa659d5dccbc --- /dev/null +++ b/Misc/NEWS.d/3.7.0b2.rst @@ -0,0 +1,655 @@ +.. bpo: 28414 +.. date: 2017-08-06-14-43-45 +.. nonce: mzZ6vD +.. release date: 2018-02-27 +.. section: Security + +The ssl module now allows users to perform their own IDN en/decoding when +using SNI. + +.. + +.. bpo: 32889 +.. date: 2018-02-20-21-53-48 +.. nonce: J6eWy5 +.. section: Core and Builtins + +Update Valgrind suppression list to account for the rename of +``Py_ADDRESS_IN_RANG`` to ``address_in_range``. + +.. + +.. bpo: 31356 +.. date: 2018-02-02-08-50-46 +.. nonce: MNwUOQ +.. section: Core and Builtins + +Remove the new API added in bpo-31356 (gc.ensure_disabled() context +manager). + +.. + +.. bpo: 32305 +.. date: 2018-02-01-10-56-41 +.. nonce: dkU9Qa +.. section: Core and Builtins + +For namespace packages, ensure that both ``__file__`` and +``__spec__.origin`` are set to None. + +.. + +.. bpo: 32303 +.. date: 2018-02-01-10-16-28 +.. nonce: VsvhSl +.. section: Core and Builtins + +Make sure ``__spec__.loader`` matches ``__loader__`` for namespace packages. + +.. + +.. bpo: 32711 +.. date: 2018-01-29-14-36-37 +.. nonce: 8hQFJP +.. section: Core and Builtins + +Fix the warning messages for Python/ast_unparse.c. Patch by St?phane Wirtel + +.. + +.. bpo: 32583 +.. date: 2018-01-26-21-20-21 +.. 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. + +.. + +.. bpo: 32960 +.. date: 2018-02-26-20-04-40 +.. nonce: 48r0Ml +.. section: Library + +For dataclasses, disallow inheriting frozen from non-frozen classes, and +also disallow inheriting non-frozen from frozen classes. This restriction +will be relaxed at a future date. + +.. + +.. bpo: 32713 +.. date: 2018-02-26-13-16-36 +.. nonce: 55yegW +.. section: Library + +Fixed tarfile.itn handling of out-of-bounds float values. Patch by Joffrey +Fuhrer. + +.. + +.. bpo: 32951 +.. date: 2018-02-25-18-22-01 +.. nonce: gHrCXq +.. section: Library + +Direct instantiation of SSLSocket and SSLObject objects is now prohibited. +The constructors were never documented, tested, or designed as public +constructors. Users were suppose to use ssl.wrap_socket() or SSLContext. + +.. + +.. bpo: 32929 +.. date: 2018-02-25-13-47-48 +.. nonce: X2gTDH +.. section: Library + +Remove the tri-state parameter "hash", and add the boolean "unsafe_hash". If +unsafe_hash is True, add a __hash__ function, but if a __hash__ exists, +raise TypeError. If unsafe_hash is False, add a __hash__ based on the +values of eq= and frozen=. The unsafe_hash=False behavior is the same as +the old hash=None behavior. unsafe_hash=False is the default, just as +hash=None used to be. + +.. + +.. bpo: 32947 +.. date: 2018-02-25-13-06-21 +.. nonce: mqStVW +.. section: Library + +Add OP_ENABLE_MIDDLEBOX_COMPAT and test workaround for TLSv1.3 for future +compatibility with OpenSSL 1.1.1. + +.. + +.. bpo: 30622 +.. date: 2018-02-24-21-40-42 +.. nonce: dQjxSe +.. section: Library + +The ssl module now detects missing NPN support in LibreSSL. + +.. + +.. bpo: 32922 +.. date: 2018-02-23-19-12-04 +.. nonce: u-xe0B +.. section: Library + +dbm.open() now encodes filename with the filesystem encoding rather than +default encoding. + +.. + +.. bpo: 32859 +.. date: 2018-02-19-17-46-31 +.. nonce: kAT-Xp +.. section: Library + +In ``os.dup2``, don't check every call whether the ``dup3`` syscall exists +or not. + +.. + +.. bpo: 32556 +.. date: 2018-02-19-14-27-51 +.. nonce: CsRsgr +.. section: Library + +nt._getfinalpathname, nt._getvolumepathname and nt._getdiskusage now +correctly convert from bytes. + +.. + +.. bpo: 25988 +.. date: 2018-02-18-13-04-59 +.. nonce: ACidKC +.. section: Library + +Emit a :exc:`DeprecationWarning` when using or importing an ABC directly +from :mod:`collections` rather than from :mod:`collections.abc`. + +.. + +.. bpo: 21060 +.. date: 2018-02-17-19-20-19 +.. nonce: S1Z-x6 +.. section: Library + +Rewrite confusing message from setup.py upload from "No dist file created in +earlier command" to the more helpful "Must create and upload files in one +command". + +.. + +.. bpo: 32852 +.. date: 2018-02-15-12-04-29 +.. nonce: HDqIxM +.. section: Library + +Make sure sys.argv remains as a list when running trace. + +.. + +.. bpo: 31333 +.. date: 2018-02-15-08-18-52 +.. nonce: 4fF-gM +.. section: Library + +``_abc`` module is added. It is a speedup module with C implementations for +various functions and methods in ``abc``. Creating an ABC subclass and +calling ``isinstance`` or ``issubclass`` with an ABC subclass are up to 1.5x +faster. In addition, this makes Python start-up up to 10% faster. + +Note that the new implementation hides internal registry and caches, +previously accessible via private attributes ``_abc_registry``, +``_abc_cache``, and ``_abc_negative_cache``. There are three debugging +helper methods that can be used instead ``_dump_registry``, +``_abc_registry_clear``, and ``_abc_caches_clear``. + +.. + +.. bpo: 32841 +.. date: 2018-02-14-00-21-24 +.. nonce: bvHDOc +.. section: Library + +Fixed `asyncio.Condition` issue which silently ignored cancellation after +notifying and cancelling a conditional lock. Patch by Bar Harel. + +.. + +.. bpo: 32819 +.. date: 2018-02-11-15-54-41 +.. nonce: ZTRX2Q +.. section: Library + +ssl.match_hostname() has been simplified and no longer depends on re and +ipaddress module for wildcard and IP addresses. Error reporting for invalid +wildcards has been improved. + +.. + +.. bpo: 32394 +.. date: 2018-02-10-13-51-56 +.. nonce: dFM9SI +.. section: Library + +socket: Remove TCP_FASTOPEN,TCP_KEEPCNT,TCP_KEEPIDLE,TCP_KEEPINTVL flags on +older version Windows during run-time. + +.. + +.. bpo: 31787 +.. date: 2018-02-09-21-41-56 +.. nonce: owSZ2t +.. section: Library + +Fixed refleaks of ``__init__()`` methods in various modules. (Contributed by +Oren Milman) + +.. + +.. bpo: 30157 +.. date: 2018-02-09-14-44-43 +.. nonce: lEiiAK +.. section: Library + +Fixed guessing quote and delimiter in csv.Sniffer.sniff() when only the last +field is quoted. Patch by Jake Davis. + +.. + +.. bpo: 32792 +.. date: 2018-02-08-00-47-07 +.. nonce: NtyDb4 +.. section: Library + +collections.ChainMap() preserves the order of the underlying mappings. + +.. + +.. bpo: 32775 +.. date: 2018-02-07-19-12-10 +.. nonce: -T77_c +.. section: Library + +:func:`fnmatch.translate()` no longer produces patterns which contain set +operations. Sets starting with '[' or containing '--', '&&', '~~' or '||' +will be interpreted differently in regular expressions in future versions. +Currently they emit warnings. fnmatch.translate() now avoids producing +patterns containing such sets by accident. + +.. + +.. bpo: 32622 +.. date: 2018-02-06-17-58-15 +.. nonce: AE0Jz7 +.. section: Library + +Implement native fast sendfile for Windows proactor event loop. + +.. + +.. bpo: 32777 +.. date: 2018-02-05-21-28-28 +.. nonce: C-wIXF +.. section: Library + +Fix a rare but potential pre-exec child process deadlock in subprocess on +POSIX systems when marking file descriptors inheritable on exec in the child +process. This bug appears to have been introduced in 3.4. + +.. + +.. bpo: 32647 +.. date: 2018-02-05-13-31-42 +.. nonce: ktmfR_ +.. section: Library + +The ctypes module used to depend on indirect linking for dlopen. The shared +extension is now explicitly linked against libdl on platforms with dl. + +.. + +.. bpo: 32741 +.. date: 2018-02-01-17-54-08 +.. nonce: KUvOPL +.. section: Library + +Implement ``asyncio.TimerHandle.when()`` method. + +.. + +.. bpo: 32691 +.. date: 2018-02-01-15-53-35 +.. nonce: VLWVTq +.. section: Library + +Use mod_spec.parent when running modules with pdb + +.. + +.. bpo: 32734 +.. date: 2018-02-01-01-34-47 +.. nonce: gCV9AD +.. section: Library + +Fixed ``asyncio.Lock()`` safety issue which allowed acquiring and locking +the same lock multiple times, without it being free. Patch by Bar Harel. + +.. + +.. bpo: 32727 +.. date: 2018-01-30-17-46-18 +.. nonce: aHVsRC +.. section: Library + +Do not include name field in SMTP envelope from address. Patch by St?phane +Wirtel + +.. + +.. bpo: 31453 +.. date: 2018-01-21-15-01-50 +.. nonce: cZiZBe +.. section: Library + +Add TLSVersion constants and SSLContext.maximum_version / minimum_version +attributes. The new API wraps OpenSSL 1.1 +https://www.openssl.org/docs/man1.1.0/ssl/SSL_CTX_set_min_proto_version.html +feature. + +.. + +.. bpo: 24334 +.. date: 2018-01-20-23-17-25 +.. nonce: GZuQLv +.. section: Library + +Internal implementation details of ssl module were cleaned up. The SSLSocket +has one less layer of indirection. Owner and session information are now +handled by the SSLSocket and SSLObject constructor. Channel binding +implementation has been simplified. + +.. + +.. bpo: 31848 +.. date: 2018-01-18-23-34-17 +.. nonce: M2cldy +.. section: Library + +Fix the error handling in Aifc_read.initfp() when the SSND chunk is not +found. Patch by Zackery Spytz. + +.. + +.. bpo: 32585 +.. date: 2018-01-18-13-09-00 +.. nonce: qpeijr +.. section: Library + +Add Ttk spinbox widget to tkinter.ttk. Patch by Alan D Moore. + +.. + +.. bpo: 32221 +.. date: 2017-12-06-10-10-10 +.. nonce: ideco_ +.. section: Library + +Various functions returning tuple containig IPv6 addresses now omit +``%scope`` part since the same information is already encoded in *scopeid* +tuple item. Especially this speeds up :func:`socket.recvfrom` when it +receives multicast packet since useless resolving of network interface name +is omitted. + +.. + +.. bpo: 30693 +.. date: 2017-11-27-15-09-49 +.. nonce: yC4mJ8 +.. section: Library + +The TarFile class now recurses directories in a reproducible way. + +.. + +.. bpo: 30693 +.. date: 2017-11-27-15-09-49 +.. nonce: yC4mJ7 +.. section: Library + +The ZipFile class now recurses directories in a reproducible way. + +.. + +.. bpo: 28124 +.. date: 2018-02-25-16-33-35 +.. nonce: _uzkgq +.. section: Documentation + +The ssl module function ssl.wrap_socket() has been de-emphasized and +deprecated in favor of the more secure and efficient +SSLContext.wrap_socket() method. + +.. + +.. bpo: 17232 +.. date: 2018-02-23-12-48-03 +.. nonce: tmuTKL +.. section: Documentation + +Clarify docs for -O and -OO. Patch by Terry Reedy. + +.. + +.. bpo: 32436 +.. date: 2018-02-14-11-10-41 +.. nonce: TTJ2jb +.. section: Documentation + +Add documentation for the contextvars module (PEP 567). + +.. + +.. bpo: 32800 +.. date: 2018-02-10-15-16-04 +.. nonce: FyrqCk +.. section: Documentation + +Update link to w3c doc for xml default namespaces. + +.. + +.. bpo: 11015 +.. date: 2018-02-10-12-48-38 +.. nonce: -gUf34 +.. section: Documentation + +Update :mod:`test.support` documentation. + +.. + +.. bpo: 8722 +.. date: 2018-02-03-06-11-37 +.. nonce: MPyVyj +.. section: Documentation + +Document :meth:`__getattr__` behavior when property :meth:`get` method +raises :exc:`AttributeError`. + +.. + +.. bpo: 32614 +.. date: 2018-02-02-07-41-57 +.. nonce: LSqzGw +.. section: Documentation + +Modify RE examples in documentation to use raw strings to prevent +:exc:`DeprecationWarning` and add text to REGEX HOWTO to highlight the +deprecation. + +.. + +.. bpo: 31972 +.. date: 2018-01-25-14-23-12 +.. nonce: w1m_8r +.. section: Documentation + +Improve docstrings for `pathlib.PurePath` subclasses. + +.. + +.. bpo: 31809 +.. date: 2017-10-18-18-07-45 +.. nonce: KlQrkE +.. section: Tests + +Add tests to verify connection with secp ECDH curves. + +.. + +.. bpo: 32898 +.. date: 2018-02-21-12-46-00 +.. nonce: M15bZh +.. section: Build + +Fix the python debug build when using COUNT_ALLOCS. + +.. + +.. bpo: 32901 +.. date: 2018-02-23-00-47-13 +.. nonce: mGKz5_ +.. section: Windows + +Update Tcl and Tk versions to 8.6.8 + +.. + +.. bpo: 31966 +.. date: 2018-02-19-13-54-42 +.. nonce: _Q3HPb +.. section: Windows + +Fixed WindowsConsoleIO.write() for writing empty data. + +.. + +.. bpo: 32409 +.. date: 2018-02-19-10-00-57 +.. nonce: nocuDg +.. section: Windows + +Ensures activate.bat can handle Unicode contents. + +.. + +.. bpo: 32457 +.. date: 2018-02-19-08-54-06 +.. nonce: vVP0Iz +.. section: Windows + +Improves handling of denormalized executable path when launching Python. + +.. + +.. bpo: 32370 +.. date: 2018-02-10-15-38-19 +.. nonce: kcKuct +.. section: Windows + +Use the correct encoding for ipconfig output in the uuid module. Patch by +Segev Finer. + +.. + +.. bpo: 29248 +.. date: 2018-02-07-17-50-48 +.. nonce: Xzwj-6 +.. section: Windows + +Fix :func:`os.readlink` on Windows, which was mistakenly treating the +``PrintNameOffset`` field of the reparse data buffer as a number of +characters instead of bytes. Patch by Craig Holmquist and SSE4. + +.. + +.. bpo: 32901 +.. date: 2018-02-27-17-33-15 +.. nonce: hQu0w3 +.. section: macOS + +Update macOS 10.9+ installer to Tcl/Tk 8.6.8. + +.. + +.. bpo: 32916 +.. date: 2018-02-23-07-32-36 +.. nonce: 4MsQ5F +.. section: IDLE + +Change ``str`` to ``code`` in pyparse. + +.. + +.. bpo: 32905 +.. date: 2018-02-22-00-09-27 +.. nonce: VlXj0x +.. section: IDLE + +Remove unused code in pyparse module. + +.. + +.. bpo: 32874 +.. date: 2018-02-19-10-56-41 +.. nonce: 6pZ9Gv +.. section: IDLE + +Add tests for pyparse. + +.. + +.. bpo: 32837 +.. date: 2018-02-12-17-22-48 +.. nonce: -33QPl +.. section: IDLE + +Using the system and place-dependent default encoding for open() is a bad +idea for IDLE's system and location-independent files. + +.. + +.. bpo: 32826 +.. date: 2018-02-12-11-05-22 +.. nonce: IxNZrk +.. section: IDLE + +Add "encoding=utf-8" to open() in IDLE's test_help_about. GUI test +test_file_buttons() only looks at initial ascii-only lines, but failed on +systems where open() defaults to 'ascii' because readline() internally reads +and decodes far enough ahead to encounter a non-ascii character in +CREDITS.txt. + +.. + +.. bpo: 32765 +.. date: 2018-02-04-17-52-54 +.. nonce: qm0eCu +.. section: IDLE + +Update configdialog General tab docstring to add new widgets to the widget +list. + +.. + +.. bpo: 32222 +.. date: 2017-12-07-20-51-20 +.. nonce: hPBcGT +.. section: Tools/Demos + +Fix pygettext not extracting docstrings for functions with type annotated +arguments. Patch by Toby Harradine. diff --git a/Misc/NEWS.d/next/Build/2018-02-21-12-46-00.bpo-32898.M15bZh.rst b/Misc/NEWS.d/next/Build/2018-02-21-12-46-00.bpo-32898.M15bZh.rst deleted file mode 100644 index 4c75466bfd0f..000000000000 --- a/Misc/NEWS.d/next/Build/2018-02-21-12-46-00.bpo-32898.M15bZh.rst +++ /dev/null @@ -1 +0,0 @@ -Fix the python debug build when using COUNT_ALLOCS. diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-01-26-21-20-21.bpo-32583.Fh3fau.rst b/Misc/NEWS.d/next/Core and Builtins/2018-01-26-21-20-21.bpo-32583.Fh3fau.rst deleted file mode 100644 index 45f1d043f9d6..000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2018-01-26-21-20-21.bpo-32583.Fh3fau.rst +++ /dev/null @@ -1,2 +0,0 @@ -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/next/Core and Builtins/2018-01-29-14-36-37.bpo-32711.8hQFJP.rst b/Misc/NEWS.d/next/Core and Builtins/2018-01-29-14-36-37.bpo-32711.8hQFJP.rst deleted file mode 100644 index 4d55b894ce10..000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2018-01-29-14-36-37.bpo-32711.8hQFJP.rst +++ /dev/null @@ -1 +0,0 @@ -Fix the warning messages for Python/ast_unparse.c. Patch by St?phane Wirtel diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-02-01-10-16-28.bpo-32303.VsvhSl.rst b/Misc/NEWS.d/next/Core and Builtins/2018-02-01-10-16-28.bpo-32303.VsvhSl.rst deleted file mode 100644 index b84448fb25a1..000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2018-02-01-10-16-28.bpo-32303.VsvhSl.rst +++ /dev/null @@ -1 +0,0 @@ -Make sure ``__spec__.loader`` matches ``__loader__`` for namespace packages. diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-02-01-10-56-41.bpo-32305.dkU9Qa.rst b/Misc/NEWS.d/next/Core and Builtins/2018-02-01-10-56-41.bpo-32305.dkU9Qa.rst deleted file mode 100644 index 204d74a49754..000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2018-02-01-10-56-41.bpo-32305.dkU9Qa.rst +++ /dev/null @@ -1,2 +0,0 @@ -For namespace packages, ensure that both ``__file__`` and -``__spec__.origin`` are set to None. diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-02-02-08-50-46.bpo-31356.MNwUOQ.rst b/Misc/NEWS.d/next/Core and Builtins/2018-02-02-08-50-46.bpo-31356.MNwUOQ.rst deleted file mode 100644 index 5022a1370609..000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2018-02-02-08-50-46.bpo-31356.MNwUOQ.rst +++ /dev/null @@ -1,2 +0,0 @@ -Remove the new API added in bpo-31356 (gc.ensure_disabled() context -manager). diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-02-20-21-53-48.bpo-32889.J6eWy5.rst b/Misc/NEWS.d/next/Core and Builtins/2018-02-20-21-53-48.bpo-32889.J6eWy5.rst deleted file mode 100644 index 99128ccc1826..000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2018-02-20-21-53-48.bpo-32889.J6eWy5.rst +++ /dev/null @@ -1,2 +0,0 @@ -Update Valgrind suppression list to account for the rename of -``Py_ADDRESS_IN_RANG`` to ``address_in_range``. diff --git a/Misc/NEWS.d/next/Documentation/2018-01-25-14-23-12.bpo-31972.w1m_8r.rst b/Misc/NEWS.d/next/Documentation/2018-01-25-14-23-12.bpo-31972.w1m_8r.rst deleted file mode 100644 index e0361df578b3..000000000000 --- a/Misc/NEWS.d/next/Documentation/2018-01-25-14-23-12.bpo-31972.w1m_8r.rst +++ /dev/null @@ -1 +0,0 @@ -Improve docstrings for `pathlib.PurePath` subclasses. diff --git a/Misc/NEWS.d/next/Documentation/2018-02-02-07-41-57.bpo-32614.LSqzGw.rst b/Misc/NEWS.d/next/Documentation/2018-02-02-07-41-57.bpo-32614.LSqzGw.rst deleted file mode 100644 index 9e9f3e3a74df..000000000000 --- a/Misc/NEWS.d/next/Documentation/2018-02-02-07-41-57.bpo-32614.LSqzGw.rst +++ /dev/null @@ -1,3 +0,0 @@ -Modify RE examples in documentation to use raw strings to prevent -:exc:`DeprecationWarning` and add text to REGEX HOWTO to highlight the -deprecation. diff --git a/Misc/NEWS.d/next/Documentation/2018-02-03-06-11-37.bpo-8722.MPyVyj.rst b/Misc/NEWS.d/next/Documentation/2018-02-03-06-11-37.bpo-8722.MPyVyj.rst deleted file mode 100644 index 36e6ff7db3ce..000000000000 --- a/Misc/NEWS.d/next/Documentation/2018-02-03-06-11-37.bpo-8722.MPyVyj.rst +++ /dev/null @@ -1,2 +0,0 @@ -Document :meth:`__getattr__` behavior when property :meth:`get` method -raises :exc:`AttributeError`. diff --git a/Misc/NEWS.d/next/Documentation/2018-02-10-12-48-38.bpo-11015.-gUf34.rst b/Misc/NEWS.d/next/Documentation/2018-02-10-12-48-38.bpo-11015.-gUf34.rst deleted file mode 100644 index 73612dab69e5..000000000000 --- a/Misc/NEWS.d/next/Documentation/2018-02-10-12-48-38.bpo-11015.-gUf34.rst +++ /dev/null @@ -1 +0,0 @@ -Update :mod:`test.support` documentation. diff --git a/Misc/NEWS.d/next/Documentation/2018-02-10-15-16-04.bpo-32800.FyrqCk.rst b/Misc/NEWS.d/next/Documentation/2018-02-10-15-16-04.bpo-32800.FyrqCk.rst deleted file mode 100644 index eac1107bba76..000000000000 --- a/Misc/NEWS.d/next/Documentation/2018-02-10-15-16-04.bpo-32800.FyrqCk.rst +++ /dev/null @@ -1 +0,0 @@ -Update link to w3c doc for xml default namespaces. diff --git a/Misc/NEWS.d/next/Documentation/2018-02-14-11-10-41.bpo-32436.TTJ2jb.rst b/Misc/NEWS.d/next/Documentation/2018-02-14-11-10-41.bpo-32436.TTJ2jb.rst deleted file mode 100644 index b764b45cd968..000000000000 --- a/Misc/NEWS.d/next/Documentation/2018-02-14-11-10-41.bpo-32436.TTJ2jb.rst +++ /dev/null @@ -1 +0,0 @@ -Add documentation for the contextvars module (PEP 567). diff --git a/Misc/NEWS.d/next/Documentation/2018-02-23-12-48-03.bpo-17232.tmuTKL.rst b/Misc/NEWS.d/next/Documentation/2018-02-23-12-48-03.bpo-17232.tmuTKL.rst deleted file mode 100644 index 5c14e91b3919..000000000000 --- a/Misc/NEWS.d/next/Documentation/2018-02-23-12-48-03.bpo-17232.tmuTKL.rst +++ /dev/null @@ -1 +0,0 @@ -Clarify docs for -O and -OO. Patch by Terry Reedy. diff --git a/Misc/NEWS.d/next/Documentation/2018-02-25-16-33-35.bpo-28124._uzkgq.rst b/Misc/NEWS.d/next/Documentation/2018-02-25-16-33-35.bpo-28124._uzkgq.rst deleted file mode 100644 index 4f4ca001981d..000000000000 --- a/Misc/NEWS.d/next/Documentation/2018-02-25-16-33-35.bpo-28124._uzkgq.rst +++ /dev/null @@ -1,3 +0,0 @@ -The ssl module function ssl.wrap_socket() has been de-emphasized -and deprecated in favor of the more secure and efficient -SSLContext.wrap_socket() method. diff --git a/Misc/NEWS.d/next/IDLE/2018-02-04-17-52-54.bpo-32765.qm0eCu.rst b/Misc/NEWS.d/next/IDLE/2018-02-04-17-52-54.bpo-32765.qm0eCu.rst deleted file mode 100644 index 1bd6b094ca5d..000000000000 --- a/Misc/NEWS.d/next/IDLE/2018-02-04-17-52-54.bpo-32765.qm0eCu.rst +++ /dev/null @@ -1 +0,0 @@ -Update configdialog General tab docstring to add new widgets to the widget list. diff --git a/Misc/NEWS.d/next/IDLE/2018-02-12-11-05-22.bpo-32826.IxNZrk.rst b/Misc/NEWS.d/next/IDLE/2018-02-12-11-05-22.bpo-32826.IxNZrk.rst deleted file mode 100644 index 4310ed2e721a..000000000000 --- a/Misc/NEWS.d/next/IDLE/2018-02-12-11-05-22.bpo-32826.IxNZrk.rst +++ /dev/null @@ -1,5 +0,0 @@ -Add "encoding=utf-8" to open() in IDLE's test_help_about. -GUI test test_file_buttons() only looks at initial ascii-only lines, -but failed on systems where open() defaults to 'ascii' because -readline() internally reads and decodes far enough ahead to encounter -a non-ascii character in CREDITS.txt. diff --git a/Misc/NEWS.d/next/IDLE/2018-02-12-17-22-48.bpo-32837.-33QPl.rst b/Misc/NEWS.d/next/IDLE/2018-02-12-17-22-48.bpo-32837.-33QPl.rst deleted file mode 100644 index 258536a1cd0c..000000000000 --- a/Misc/NEWS.d/next/IDLE/2018-02-12-17-22-48.bpo-32837.-33QPl.rst +++ /dev/null @@ -1,2 +0,0 @@ -Using the system and place-dependent default encoding for open() is a bad -idea for IDLE's system and location-independent files. diff --git a/Misc/NEWS.d/next/IDLE/2018-02-19-10-56-41.bpo-32874.6pZ9Gv.rst b/Misc/NEWS.d/next/IDLE/2018-02-19-10-56-41.bpo-32874.6pZ9Gv.rst deleted file mode 100644 index 79655315fff4..000000000000 --- a/Misc/NEWS.d/next/IDLE/2018-02-19-10-56-41.bpo-32874.6pZ9Gv.rst +++ /dev/null @@ -1 +0,0 @@ -Add tests for pyparse. diff --git a/Misc/NEWS.d/next/IDLE/2018-02-22-00-09-27.bpo-32905.VlXj0x.rst b/Misc/NEWS.d/next/IDLE/2018-02-22-00-09-27.bpo-32905.VlXj0x.rst deleted file mode 100644 index c9bedd98f2e0..000000000000 --- a/Misc/NEWS.d/next/IDLE/2018-02-22-00-09-27.bpo-32905.VlXj0x.rst +++ /dev/null @@ -1 +0,0 @@ -Remove unused code in pyparse module. diff --git a/Misc/NEWS.d/next/IDLE/2018-02-23-07-32-36.bpo-32916.4MsQ5F.rst b/Misc/NEWS.d/next/IDLE/2018-02-23-07-32-36.bpo-32916.4MsQ5F.rst deleted file mode 100644 index 0832944f1621..000000000000 --- a/Misc/NEWS.d/next/IDLE/2018-02-23-07-32-36.bpo-32916.4MsQ5F.rst +++ /dev/null @@ -1 +0,0 @@ -Change ``str`` to ``code`` in pyparse. diff --git a/Misc/NEWS.d/next/Library/2017-11-27-15-09-49.bpo-30693.yC4mJ7.rst b/Misc/NEWS.d/next/Library/2017-11-27-15-09-49.bpo-30693.yC4mJ7.rst deleted file mode 100644 index 9c895c53de12..000000000000 --- a/Misc/NEWS.d/next/Library/2017-11-27-15-09-49.bpo-30693.yC4mJ7.rst +++ /dev/null @@ -1 +0,0 @@ -The ZipFile class now recurses directories in a reproducible way. diff --git a/Misc/NEWS.d/next/Library/2017-11-27-15-09-49.bpo-30693.yC4mJ8.rst b/Misc/NEWS.d/next/Library/2017-11-27-15-09-49.bpo-30693.yC4mJ8.rst deleted file mode 100644 index a622e7ed6e5d..000000000000 --- a/Misc/NEWS.d/next/Library/2017-11-27-15-09-49.bpo-30693.yC4mJ8.rst +++ /dev/null @@ -1 +0,0 @@ -The TarFile class now recurses directories in a reproducible way. diff --git a/Misc/NEWS.d/next/Library/2017-12-06-10-10-10.bpo-32221.ideco_.rst b/Misc/NEWS.d/next/Library/2017-12-06-10-10-10.bpo-32221.ideco_.rst deleted file mode 100644 index a88dcf48e02b..000000000000 --- a/Misc/NEWS.d/next/Library/2017-12-06-10-10-10.bpo-32221.ideco_.rst +++ /dev/null @@ -1,4 +0,0 @@ -Various functions returning tuple containig IPv6 addresses now omit ``%scope`` -part since the same information is already encoded in *scopeid* tuple item. -Especially this speeds up :func:`socket.recvfrom` when it receives multicast -packet since useless resolving of network interface name is omitted. diff --git a/Misc/NEWS.d/next/Library/2018-01-18-13-09-00.bpo-32585.qpeijr.rst b/Misc/NEWS.d/next/Library/2018-01-18-13-09-00.bpo-32585.qpeijr.rst deleted file mode 100644 index c504e8b1e538..000000000000 --- a/Misc/NEWS.d/next/Library/2018-01-18-13-09-00.bpo-32585.qpeijr.rst +++ /dev/null @@ -1 +0,0 @@ -Add Ttk spinbox widget to to tkinter.ttk. Patch by Alan D Moore. diff --git a/Misc/NEWS.d/next/Library/2018-01-18-23-34-17.bpo-31848.M2cldy.rst b/Misc/NEWS.d/next/Library/2018-01-18-23-34-17.bpo-31848.M2cldy.rst deleted file mode 100644 index c8e61acb0b06..000000000000 --- a/Misc/NEWS.d/next/Library/2018-01-18-23-34-17.bpo-31848.M2cldy.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix the error handling in Aifc_read.initfp() when the SSND chunk is not found. -Patch by Zackery Spytz. diff --git a/Misc/NEWS.d/next/Library/2018-01-20-23-17-25.bpo-24334.GZuQLv.rst b/Misc/NEWS.d/next/Library/2018-01-20-23-17-25.bpo-24334.GZuQLv.rst deleted file mode 100644 index 2b4877fad7e1..000000000000 --- a/Misc/NEWS.d/next/Library/2018-01-20-23-17-25.bpo-24334.GZuQLv.rst +++ /dev/null @@ -1,4 +0,0 @@ -Internal implementation details of ssl module were cleaned up. The SSLSocket -has one less layer of indirection. Owner and session information are now -handled by the SSLSocket and SSLObject constructor. Channel binding -implementation has been simplified. diff --git a/Misc/NEWS.d/next/Library/2018-01-21-15-01-50.bpo-31453.cZiZBe.rst b/Misc/NEWS.d/next/Library/2018-01-21-15-01-50.bpo-31453.cZiZBe.rst deleted file mode 100644 index 6d43dfd8207d..000000000000 --- a/Misc/NEWS.d/next/Library/2018-01-21-15-01-50.bpo-31453.cZiZBe.rst +++ /dev/null @@ -1,4 +0,0 @@ -Add TLSVersion constants and SSLContext.maximum_version / minimum_version -attributes. The new API wraps OpenSSL 1.1 -https://www.openssl.org/docs/man1.1.0/ssl/SSL_CTX_set_min_proto_version.html -feature. diff --git a/Misc/NEWS.d/next/Library/2018-01-30-17-46-18.bpo-32727.aHVsRC.rst b/Misc/NEWS.d/next/Library/2018-01-30-17-46-18.bpo-32727.aHVsRC.rst deleted file mode 100644 index 22c219636de2..000000000000 --- a/Misc/NEWS.d/next/Library/2018-01-30-17-46-18.bpo-32727.aHVsRC.rst +++ /dev/null @@ -1 +0,0 @@ -Do not include name field in SMTP envelope from address. Patch by St?phane Wirtel diff --git a/Misc/NEWS.d/next/Library/2018-02-01-01-34-47.bpo-32734.gCV9AD.rst b/Misc/NEWS.d/next/Library/2018-02-01-01-34-47.bpo-32734.gCV9AD.rst deleted file mode 100644 index 14d4bbdade75..000000000000 --- a/Misc/NEWS.d/next/Library/2018-02-01-01-34-47.bpo-32734.gCV9AD.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed ``asyncio.Lock()`` safety issue which allowed acquiring and locking -the same lock multiple times, without it being free. Patch by Bar Harel. diff --git a/Misc/NEWS.d/next/Library/2018-02-01-15-53-35.bpo-32691.VLWVTq.rst b/Misc/NEWS.d/next/Library/2018-02-01-15-53-35.bpo-32691.VLWVTq.rst deleted file mode 100644 index 93f898e9c689..000000000000 --- a/Misc/NEWS.d/next/Library/2018-02-01-15-53-35.bpo-32691.VLWVTq.rst +++ /dev/null @@ -1 +0,0 @@ -Use mod_spec.parent when running modules with pdb diff --git a/Misc/NEWS.d/next/Library/2018-02-01-17-54-08.bpo-32741.KUvOPL.rst b/Misc/NEWS.d/next/Library/2018-02-01-17-54-08.bpo-32741.KUvOPL.rst deleted file mode 100644 index 651e7666157a..000000000000 --- a/Misc/NEWS.d/next/Library/2018-02-01-17-54-08.bpo-32741.KUvOPL.rst +++ /dev/null @@ -1 +0,0 @@ -Implement ``asyncio.TimerHandle.when()`` method. diff --git a/Misc/NEWS.d/next/Library/2018-02-05-13-31-42.bpo-32647.ktmfR_.rst b/Misc/NEWS.d/next/Library/2018-02-05-13-31-42.bpo-32647.ktmfR_.rst deleted file mode 100644 index 04fc0247bcde..000000000000 --- a/Misc/NEWS.d/next/Library/2018-02-05-13-31-42.bpo-32647.ktmfR_.rst +++ /dev/null @@ -1,2 +0,0 @@ -The ctypes module used to depend on indirect linking for dlopen. The shared -extension is now explicitly linked against libdl on platforms with dl. diff --git a/Misc/NEWS.d/next/Library/2018-02-05-21-28-28.bpo-32777.C-wIXF.rst b/Misc/NEWS.d/next/Library/2018-02-05-21-28-28.bpo-32777.C-wIXF.rst deleted file mode 100644 index d5d7d7b27dc7..000000000000 --- a/Misc/NEWS.d/next/Library/2018-02-05-21-28-28.bpo-32777.C-wIXF.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix a rare but potential pre-exec child process deadlock in subprocess on -POSIX systems when marking file descriptors inheritable on exec in the child -process. This bug appears to have been introduced in 3.4. diff --git a/Misc/NEWS.d/next/Library/2018-02-06-17-58-15.bpo-32622.AE0Jz7.rst b/Misc/NEWS.d/next/Library/2018-02-06-17-58-15.bpo-32622.AE0Jz7.rst deleted file mode 100644 index 456a6dc55959..000000000000 --- a/Misc/NEWS.d/next/Library/2018-02-06-17-58-15.bpo-32622.AE0Jz7.rst +++ /dev/null @@ -1 +0,0 @@ -Implement native fast sendfile for Windows proactor event loop. diff --git a/Misc/NEWS.d/next/Library/2018-02-07-19-12-10.bpo-32775.-T77_c.rst b/Misc/NEWS.d/next/Library/2018-02-07-19-12-10.bpo-32775.-T77_c.rst deleted file mode 100644 index ed563c17fdc8..000000000000 --- a/Misc/NEWS.d/next/Library/2018-02-07-19-12-10.bpo-32775.-T77_c.rst +++ /dev/null @@ -1,5 +0,0 @@ -:func:`fnmatch.translate()` no longer produces patterns which contain set -operations. Sets starting with '[' or containing '--', '&&', '~~' or '||' -will be interpreted differently in regular expressions in future versions. -Currently they emit warnings. fnmatch.translate() now avoids producing -patterns containing such sets by accident. diff --git a/Misc/NEWS.d/next/Library/2018-02-08-00-47-07.bpo-32792.NtyDb4.rst b/Misc/NEWS.d/next/Library/2018-02-08-00-47-07.bpo-32792.NtyDb4.rst deleted file mode 100644 index 1f7df62cc3e1..000000000000 --- a/Misc/NEWS.d/next/Library/2018-02-08-00-47-07.bpo-32792.NtyDb4.rst +++ /dev/null @@ -1 +0,0 @@ -collections.ChainMap() preserves the order of the underlying mappings. diff --git a/Misc/NEWS.d/next/Library/2018-02-09-14-44-43.bpo-30157.lEiiAK.rst b/Misc/NEWS.d/next/Library/2018-02-09-14-44-43.bpo-30157.lEiiAK.rst deleted file mode 100644 index 9f651930ac2b..000000000000 --- a/Misc/NEWS.d/next/Library/2018-02-09-14-44-43.bpo-30157.lEiiAK.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed guessing quote and delimiter in csv.Sniffer.sniff() when only the last -field is quoted. Patch by Jake Davis. diff --git a/Misc/NEWS.d/next/Library/2018-02-09-21-41-56.bpo-31787.owSZ2t.rst b/Misc/NEWS.d/next/Library/2018-02-09-21-41-56.bpo-31787.owSZ2t.rst deleted file mode 100644 index f0cde59d740f..000000000000 --- a/Misc/NEWS.d/next/Library/2018-02-09-21-41-56.bpo-31787.owSZ2t.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed refleaks of ``__init__()`` methods in various modules. -(Contributed by Oren Milman) diff --git a/Misc/NEWS.d/next/Library/2018-02-10-13-51-56.bpo-32394.dFM9SI.rst b/Misc/NEWS.d/next/Library/2018-02-10-13-51-56.bpo-32394.dFM9SI.rst deleted file mode 100644 index ee5807619a93..000000000000 --- a/Misc/NEWS.d/next/Library/2018-02-10-13-51-56.bpo-32394.dFM9SI.rst +++ /dev/null @@ -1,2 +0,0 @@ -socket: Remove TCP_FASTOPEN,TCP_KEEPCNT,TCP_KEEPIDLE,TCP_KEEPINTVL flags on -older version Windows during run-time. diff --git a/Misc/NEWS.d/next/Library/2018-02-11-15-54-41.bpo-32819.ZTRX2Q.rst b/Misc/NEWS.d/next/Library/2018-02-11-15-54-41.bpo-32819.ZTRX2Q.rst deleted file mode 100644 index 7d57bf697826..000000000000 --- a/Misc/NEWS.d/next/Library/2018-02-11-15-54-41.bpo-32819.ZTRX2Q.rst +++ /dev/null @@ -1,3 +0,0 @@ -ssl.match_hostname() has been simplified and no longer depends on re and -ipaddress module for wildcard and IP addresses. Error reporting for invalid -wildcards has been improved. diff --git a/Misc/NEWS.d/next/Library/2018-02-14-00-21-24.bpo-32841.bvHDOc.rst b/Misc/NEWS.d/next/Library/2018-02-14-00-21-24.bpo-32841.bvHDOc.rst deleted file mode 100644 index a6d45669d027..000000000000 --- a/Misc/NEWS.d/next/Library/2018-02-14-00-21-24.bpo-32841.bvHDOc.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed `asyncio.Condition` issue which silently ignored cancellation after -notifying and cancelling a conditional lock. Patch by Bar Harel. diff --git a/Misc/NEWS.d/next/Library/2018-02-15-08-18-52.bpo-31333.4fF-gM.rst b/Misc/NEWS.d/next/Library/2018-02-15-08-18-52.bpo-31333.4fF-gM.rst deleted file mode 100644 index 63fc72a5c11b..000000000000 --- a/Misc/NEWS.d/next/Library/2018-02-15-08-18-52.bpo-31333.4fF-gM.rst +++ /dev/null @@ -1,10 +0,0 @@ -``_abc`` module is added. It is a speedup module with C implementations for -various functions and methods in ``abc``. Creating an ABC subclass and calling -``isinstance`` or ``issubclass`` with an ABC subclass are up to 1.5x faster. -In addition, this makes Python start-up up to 10% faster. - -Note that the new implementation hides internal registry and caches, previously -accessible via private attributes ``_abc_registry``, ``_abc_cache``, and -``_abc_negative_cache``. There are three debugging helper methods that can be -used instead ``_dump_registry``, ``_abc_registry_clear``, and -``_abc_caches_clear``. diff --git a/Misc/NEWS.d/next/Library/2018-02-15-12-04-29.bpo-32852.HDqIxM.rst b/Misc/NEWS.d/next/Library/2018-02-15-12-04-29.bpo-32852.HDqIxM.rst deleted file mode 100644 index 8eabbfaea222..000000000000 --- a/Misc/NEWS.d/next/Library/2018-02-15-12-04-29.bpo-32852.HDqIxM.rst +++ /dev/null @@ -1 +0,0 @@ -Make sure sys.argv remains as a list when running trace. diff --git a/Misc/NEWS.d/next/Library/2018-02-17-19-20-19.bpo-21060.S1Z-x6.rst b/Misc/NEWS.d/next/Library/2018-02-17-19-20-19.bpo-21060.S1Z-x6.rst deleted file mode 100644 index 4e0a11362086..000000000000 --- a/Misc/NEWS.d/next/Library/2018-02-17-19-20-19.bpo-21060.S1Z-x6.rst +++ /dev/null @@ -1,3 +0,0 @@ -Rewrite confusing message from setup.py upload from -"No dist file created in earlier command" to the more helpful -"Must create and upload files in one command". diff --git a/Misc/NEWS.d/next/Library/2018-02-18-13-04-59.bpo-25988.ACidKC.rst b/Misc/NEWS.d/next/Library/2018-02-18-13-04-59.bpo-25988.ACidKC.rst deleted file mode 100644 index 9730ab4a6101..000000000000 --- a/Misc/NEWS.d/next/Library/2018-02-18-13-04-59.bpo-25988.ACidKC.rst +++ /dev/null @@ -1,2 +0,0 @@ -Emit a :exc:`DeprecationWarning` when using or importing an ABC directly -from :mod:`collections` rather than from :mod:`collections.abc`. diff --git a/Misc/NEWS.d/next/Library/2018-02-19-14-27-51.bpo-32556.CsRsgr.rst b/Misc/NEWS.d/next/Library/2018-02-19-14-27-51.bpo-32556.CsRsgr.rst deleted file mode 100644 index 1a475b308f5e..000000000000 --- a/Misc/NEWS.d/next/Library/2018-02-19-14-27-51.bpo-32556.CsRsgr.rst +++ /dev/null @@ -1,2 +0,0 @@ -nt._getfinalpathname, nt._getvolumepathname and nt._getdiskusage now -correctly convert from bytes. diff --git a/Misc/NEWS.d/next/Library/2018-02-19-17-46-31.bpo-32859.kAT-Xp.rst b/Misc/NEWS.d/next/Library/2018-02-19-17-46-31.bpo-32859.kAT-Xp.rst deleted file mode 100644 index 755bdc118610..000000000000 --- a/Misc/NEWS.d/next/Library/2018-02-19-17-46-31.bpo-32859.kAT-Xp.rst +++ /dev/null @@ -1,2 +0,0 @@ -In ``os.dup2``, don't check every call whether the ``dup3`` syscall exists -or not. diff --git a/Misc/NEWS.d/next/Library/2018-02-23-19-12-04.bpo-32922.u-xe0B.rst b/Misc/NEWS.d/next/Library/2018-02-23-19-12-04.bpo-32922.u-xe0B.rst deleted file mode 100644 index 412e588586c0..000000000000 --- a/Misc/NEWS.d/next/Library/2018-02-23-19-12-04.bpo-32922.u-xe0B.rst +++ /dev/null @@ -1,2 +0,0 @@ -dbm.open() now encodes filename with the filesystem encoding rather than -default encoding. diff --git a/Misc/NEWS.d/next/Library/2018-02-24-21-40-42.bpo-30622.dQjxSe.rst b/Misc/NEWS.d/next/Library/2018-02-24-21-40-42.bpo-30622.dQjxSe.rst deleted file mode 100644 index bcb659b24dd3..000000000000 --- a/Misc/NEWS.d/next/Library/2018-02-24-21-40-42.bpo-30622.dQjxSe.rst +++ /dev/null @@ -1 +0,0 @@ -The ssl module now detects missing NPN support in LibreSSL. diff --git a/Misc/NEWS.d/next/Library/2018-02-25-13-06-21.bpo-32947.mqStVW.rst b/Misc/NEWS.d/next/Library/2018-02-25-13-06-21.bpo-32947.mqStVW.rst deleted file mode 100644 index 28de360c3671..000000000000 --- a/Misc/NEWS.d/next/Library/2018-02-25-13-06-21.bpo-32947.mqStVW.rst +++ /dev/null @@ -1,2 +0,0 @@ -Add OP_ENABLE_MIDDLEBOX_COMPAT and test workaround for TLSv1.3 for future -compatibility with OpenSSL 1.1.1. diff --git a/Misc/NEWS.d/next/Library/2018-02-25-13-47-48.bpo-32929.X2gTDH.rst b/Misc/NEWS.d/next/Library/2018-02-25-13-47-48.bpo-32929.X2gTDH.rst deleted file mode 100644 index b8a470cbf280..000000000000 --- a/Misc/NEWS.d/next/Library/2018-02-25-13-47-48.bpo-32929.X2gTDH.rst +++ /dev/null @@ -1,6 +0,0 @@ -Remove the tri-state parameter "hash", and add the boolean "unsafe_hash". If -unsafe_hash is True, add a __hash__ function, but if a __hash__ exists, -raise TypeError. If unsafe_hash is False, add a __hash__ based on the -values of eq= and frozen=. The unsafe_hash=False behavior is the same as -the old hash=None behavior. unsafe_hash=False is the default, just as -hash=None used to be. diff --git a/Misc/NEWS.d/next/Library/2018-02-25-18-22-01.bpo-32951.gHrCXq.rst b/Misc/NEWS.d/next/Library/2018-02-25-18-22-01.bpo-32951.gHrCXq.rst deleted file mode 100644 index 9c038cf25979..000000000000 --- a/Misc/NEWS.d/next/Library/2018-02-25-18-22-01.bpo-32951.gHrCXq.rst +++ /dev/null @@ -1,3 +0,0 @@ -Direct instantiation of SSLSocket and SSLObject objects is now prohibited. -The constructors were never documented, tested, or designed as public -constructors. Users were suppose to use ssl.wrap_socket() or SSLContext. diff --git a/Misc/NEWS.d/next/Library/2018-02-26-13-16-36.bpo-32713.55yegW.rst b/Misc/NEWS.d/next/Library/2018-02-26-13-16-36.bpo-32713.55yegW.rst deleted file mode 100644 index bb5d64a351cb..000000000000 --- a/Misc/NEWS.d/next/Library/2018-02-26-13-16-36.bpo-32713.55yegW.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed tarfile.itn handling of out-of-bounds float values. Patch by Joffrey Fuhrer. diff --git a/Misc/NEWS.d/next/Library/2018-02-26-20-04-40.bpo-32960.48r0Ml.rst b/Misc/NEWS.d/next/Library/2018-02-26-20-04-40.bpo-32960.48r0Ml.rst deleted file mode 100644 index 4ad1fa17571d..000000000000 --- a/Misc/NEWS.d/next/Library/2018-02-26-20-04-40.bpo-32960.48r0Ml.rst +++ /dev/null @@ -1,3 +0,0 @@ -For dataclasses, disallow inheriting frozen from non-frozen classes, and -also disallow inheriting non-frozen from frozen classes. This restriction -will be relaxed at a future date. diff --git a/Misc/NEWS.d/next/Security/2017-08-06-14-43-45.bpo-28414.mzZ6vD.rst b/Misc/NEWS.d/next/Security/2017-08-06-14-43-45.bpo-28414.mzZ6vD.rst deleted file mode 100644 index 06528c93ee19..000000000000 --- a/Misc/NEWS.d/next/Security/2017-08-06-14-43-45.bpo-28414.mzZ6vD.rst +++ /dev/null @@ -1 +0,0 @@ -The ssl module now allows users to perform their own IDN en/decoding when using SNI. diff --git a/Misc/NEWS.d/next/Tests/2017-10-18-18-07-45.bpo-31809.KlQrkE.rst b/Misc/NEWS.d/next/Tests/2017-10-18-18-07-45.bpo-31809.KlQrkE.rst deleted file mode 100644 index 8a48508b8c1f..000000000000 --- a/Misc/NEWS.d/next/Tests/2017-10-18-18-07-45.bpo-31809.KlQrkE.rst +++ /dev/null @@ -1 +0,0 @@ -Add tests to verify connection with secp ECDH curves. diff --git a/Misc/NEWS.d/next/Tools-Demos/2017-12-07-20-51-20.bpo-32222.hPBcGT.rst b/Misc/NEWS.d/next/Tools-Demos/2017-12-07-20-51-20.bpo-32222.hPBcGT.rst deleted file mode 100644 index b0b4c5e9357c..000000000000 --- a/Misc/NEWS.d/next/Tools-Demos/2017-12-07-20-51-20.bpo-32222.hPBcGT.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix pygettext not extracting docstrings for functions with type annotated -arguments. -Patch by Toby Harradine. diff --git a/Misc/NEWS.d/next/Windows/2018-02-07-17-50-48.bpo-29248.Xzwj-6.rst b/Misc/NEWS.d/next/Windows/2018-02-07-17-50-48.bpo-29248.Xzwj-6.rst deleted file mode 100644 index 3030ef6958de..000000000000 --- a/Misc/NEWS.d/next/Windows/2018-02-07-17-50-48.bpo-29248.Xzwj-6.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix :func:`os.readlink` on Windows, which was mistakenly treating the -``PrintNameOffset`` field of the reparse data buffer as a number of -characters instead of bytes. Patch by Craig Holmquist and SSE4. diff --git a/Misc/NEWS.d/next/Windows/2018-02-10-15-38-19.bpo-32370.kcKuct.rst b/Misc/NEWS.d/next/Windows/2018-02-10-15-38-19.bpo-32370.kcKuct.rst deleted file mode 100644 index 7f076d45bef9..000000000000 --- a/Misc/NEWS.d/next/Windows/2018-02-10-15-38-19.bpo-32370.kcKuct.rst +++ /dev/null @@ -1,2 +0,0 @@ -Use the correct encoding for ipconfig output in the uuid module. -Patch by Segev Finer. diff --git a/Misc/NEWS.d/next/Windows/2018-02-19-08-54-06.bpo-32457.vVP0Iz.rst b/Misc/NEWS.d/next/Windows/2018-02-19-08-54-06.bpo-32457.vVP0Iz.rst deleted file mode 100644 index b55ec821e622..000000000000 --- a/Misc/NEWS.d/next/Windows/2018-02-19-08-54-06.bpo-32457.vVP0Iz.rst +++ /dev/null @@ -1 +0,0 @@ -Improves handling of denormalized executable path when launching Python. diff --git a/Misc/NEWS.d/next/Windows/2018-02-19-10-00-57.bpo-32409.nocuDg.rst b/Misc/NEWS.d/next/Windows/2018-02-19-10-00-57.bpo-32409.nocuDg.rst deleted file mode 100644 index 36251b0b4783..000000000000 --- a/Misc/NEWS.d/next/Windows/2018-02-19-10-00-57.bpo-32409.nocuDg.rst +++ /dev/null @@ -1 +0,0 @@ -Ensures activate.bat can handle Unicode contents. diff --git a/Misc/NEWS.d/next/Windows/2018-02-19-13-54-42.bpo-31966._Q3HPb.rst b/Misc/NEWS.d/next/Windows/2018-02-19-13-54-42.bpo-31966._Q3HPb.rst deleted file mode 100644 index 042a4d835abf..000000000000 --- a/Misc/NEWS.d/next/Windows/2018-02-19-13-54-42.bpo-31966._Q3HPb.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed WindowsConsoleIO.write() for writing empty data. diff --git a/Misc/NEWS.d/next/Windows/2018-02-23-00-47-13.bpo-32901.mGKz5_.rst b/Misc/NEWS.d/next/Windows/2018-02-23-00-47-13.bpo-32901.mGKz5_.rst deleted file mode 100644 index af0ca65e3c82..000000000000 --- a/Misc/NEWS.d/next/Windows/2018-02-23-00-47-13.bpo-32901.mGKz5_.rst +++ /dev/null @@ -1 +0,0 @@ -Update Tcl and Tk versions to 8.6.8 diff --git a/Misc/NEWS.d/next/macOS/2018-02-27-17-33-15.bpo-32901.hQu0w3.rst b/Misc/NEWS.d/next/macOS/2018-02-27-17-33-15.bpo-32901.hQu0w3.rst deleted file mode 100644 index 73e69a9b7119..000000000000 --- a/Misc/NEWS.d/next/macOS/2018-02-27-17-33-15.bpo-32901.hQu0w3.rst +++ /dev/null @@ -1 +0,0 @@ -Update macOS 10.9+ installer to Tcl/Tk 8.6.8. diff --git a/README.rst b/README.rst index c82fef4a41f6..5d47d11ed101 100644 --- a/README.rst +++ b/README.rst @@ -1,5 +1,5 @@ -This is Python version 3.7.0 beta 1+ -==================================== +This is Python version 3.7.0 beta 2 +=================================== .. image:: https://travis-ci.org/python/cpython.svg?branch=master :alt: CPython build status on Travis CI From webhook-mailer at python.org Wed Feb 28 01:30:51 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 28 Feb 2018 06:30:51 -0000 Subject: [Python-checkins] Minor improvements to the Windows build/release process (GH-5935) Message-ID: https://github.com/python/cpython/commit/cefbd0101d4fd0a258be0c182cf27609ad26c100 commit: cefbd0101d4fd0a258be0c182cf27609ad26c100 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-27T22:30:48-08:00 summary: Minor improvements to the Windows build/release process (GH-5935) (cherry picked from commit 881323db717f9b6ffe30d14104a2925c77f28db7) Co-authored-by: Steve Dower files: M PCbuild/find_msbuild.bat M Tools/msi/purge.py M Tools/msi/uploadrelease.bat diff --git a/PCbuild/find_msbuild.bat b/PCbuild/find_msbuild.bat index 2b7413fbcde8..1877906e00a5 100644 --- a/PCbuild/find_msbuild.bat +++ b/PCbuild/find_msbuild.bat @@ -29,14 +29,6 @@ @where msbuild > "%TEMP%\msbuild.loc" 2> nul && set /P MSBUILD= < "%TEMP%\msbuild.loc" & del "%TEMP%\msbuild.loc" @if exist "%MSBUILD%" set MSBUILD="%MSBUILD%" & (set _Py_MSBuild_Source=PATH) & goto :found - at rem VS 2015 and earlier register MSBuild separately, so we can find it. - at rem Prefer MSBuild 14.0 over MSBuild 15.0, since the latter may not be able to find a VC14 install. - at reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions\14.0" /v MSBuildToolsPath /reg:32 >nul 2>nul - at if NOT ERRORLEVEL 1 @for /F "tokens=1,2*" %%i in ('reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions\14.0" /v MSBuildToolsPath /reg:32') DO @( - @if "%%i"=="MSBuildToolsPath" @if exist "%%k\msbuild.exe" @(set MSBUILD="%%k\msbuild.exe") -) - at if exist %MSBUILD% (set _Py_MSBuild_Source=registry) & goto :found - @rem VS 2017 sets exactly one install as the "main" install, so we may find MSBuild in there. @reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\SxS\VS7" /v 15.0 /reg:32 >nul 2>nul @if NOT ERRORLEVEL 1 @for /F "tokens=1,2*" %%i in ('reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\SxS\VS7" /v 15.0 /reg:32') DO @( @@ -44,6 +36,13 @@ ) @if exist %MSBUILD% (set _Py_MSBuild_Source=Visual Studio 2017 registry) & goto :found + at rem VS 2015 and earlier register MSBuild separately, so we can find it. + at reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions\14.0" /v MSBuildToolsPath /reg:32 >nul 2>nul + at if NOT ERRORLEVEL 1 @for /F "tokens=1,2*" %%i in ('reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions\14.0" /v MSBuildToolsPath /reg:32') DO @( + @if "%%i"=="MSBuildToolsPath" @if exist "%%k\msbuild.exe" @(set MSBUILD="%%k\msbuild.exe") +) + at if exist %MSBUILD% (set _Py_MSBuild_Source=registry) & goto :found + @exit /b 1 diff --git a/Tools/msi/purge.py b/Tools/msi/purge.py index 24fdae243884..a8b8f4d8973c 100644 --- a/Tools/msi/purge.py +++ b/Tools/msi/purge.py @@ -50,6 +50,7 @@ "test_d.msi", "test_pdb.msi", "tools.msi", + "ucrt.msi", "Windows6.0-KB2999226-x64.msu", "Windows6.0-KB2999226-x86.msu", "Windows6.1-KB2999226-x64.msu", diff --git a/Tools/msi/uploadrelease.bat b/Tools/msi/uploadrelease.bat index 3ae5dbc61bf3..f262489cce60 100644 --- a/Tools/msi/uploadrelease.bat +++ b/Tools/msi/uploadrelease.bat @@ -31,13 +31,17 @@ if "%1" NEQ "" echo Unexpected argument "%1" & exit /B 1 if not defined PLINK where plink > "%TEMP%\plink.loc" 2> nul && set /P PLINK= < "%TEMP%\plink.loc" & del "%TEMP%\plink.loc" if not defined PLINK where /R "%ProgramFiles(x86)%\PuTTY" plink > "%TEMP%\plink.loc" 2> nul && set /P PLINK= < "%TEMP%\plink.loc" & del "%TEMP%\plink.loc" +if not defined PLINK where /R "%ProgramFiles%\PuTTY" plink > "%TEMP%\plink.loc" 2> nul && set /P PLINK= < "%TEMP%\plink.loc" & del "%TEMP%\plink.loc" if not defined PLINK where /R "%ProgramFiles(x86)%" plink > "%TEMP%\plink.loc" 2> nul && set /P PLINK= < "%TEMP%\plink.loc" & del "%TEMP%\plink.loc" +if not defined PLINK where /R "%ProgramFiles%" plink > "%TEMP%\plink.loc" 2> nul && set /P PLINK= < "%TEMP%\plink.loc" & del "%TEMP%\plink.loc" if not defined PLINK echo Cannot locate plink.exe & exit /B 1 echo Found plink.exe at %PLINK% if not defined PSCP where pscp > "%TEMP%\pscp.loc" 2> nul && set /P pscp= < "%TEMP%\pscp.loc" & del "%TEMP%\pscp.loc" if not defined PSCP where /R "%ProgramFiles(x86)%\PuTTY" pscp > "%TEMP%\pscp.loc" 2> nul && set /P pscp= < "%TEMP%\pscp.loc" & del "%TEMP%\pscp.loc" +if not defined PSCP where /R "%ProgramFiles%\PuTTY" pscp > "%TEMP%\pscp.loc" 2> nul && set /P pscp= < "%TEMP%\pscp.loc" & del "%TEMP%\pscp.loc" if not defined PSCP where /R "%ProgramFiles(x86)%" pscp > "%TEMP%\pscp.loc" 2> nul && set /P pscp= < "%TEMP%\pscp.loc" & del "%TEMP%\pscp.loc" +if not defined PSCP where /R "%ProgramFiles%" pscp > "%TEMP%\pscp.loc" 2> nul && set /P pscp= < "%TEMP%\pscp.loc" & del "%TEMP%\pscp.loc" if not defined PSCP echo Cannot locate pscp.exe & exit /B 1 echo Found pscp.exe at %PSCP% From solipsis at pitrou.net Wed Feb 28 04:11:56 2018 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 28 Feb 2018 09:11:56 +0000 Subject: [Python-checkins] Daily reference leaks (4243df51fe43): sum=-1 Message-ID: <20180228091156.1.6AD1272980F4C213@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_fork leaked [-2, 2, 1] memory blocks, sum=1 test_multiprocessing_forkserver leaked [0, -2, 2] memory blocks, sum=0 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogtJXUWJ', '--timeout', '7200'] From webhook-mailer at python.org Wed Feb 28 13:59:01 2018 From: webhook-mailer at python.org (Ned Deily) Date: Wed, 28 Feb 2018 18:59:01 -0000 Subject: [Python-checkins] Fix 3.8 whatsnew changelog link Message-ID: https://github.com/python/cpython/commit/45ab51c142c2dc70a2abb7100b3cb3457bc18516 commit: 45ab51c142c2dc70a2abb7100b3cb3457bc18516 branch: master author: Ned Deily committer: Ned Deily date: 2018-02-28T13:58:38-05:00 summary: Fix 3.8 whatsnew changelog link files: M Doc/whatsnew/3.8.rst diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 1d722ef5f0cd..904a3584e67a 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -47,7 +47,7 @@ This article explains the new features in Python 3.8, compared to 3.7. -For full details, see the :source:`Misc/NEWS` file. +For full details, see the :ref:`changelog `. .. note:: From webhook-mailer at python.org Wed Feb 28 17:24:01 2018 From: webhook-mailer at python.org (Terry Jan Reedy) Date: Wed, 28 Feb 2018 22:24:01 -0000 Subject: [Python-checkins] bpo-32940: IDLE: Simplify StringTranslatePseudoMapping in pyparse (GH-5862) Message-ID: https://github.com/python/cpython/commit/f0daa880a405c8de6743e44fa46006754aa145c9 commit: f0daa880a405c8de6743e44fa46006754aa145c9 branch: master author: Cheryl Sabella committer: Terry Jan Reedy date: 2018-02-28T17:23:58-05:00 summary: bpo-32940: IDLE: Simplify StringTranslatePseudoMapping in pyparse (GH-5862) The new code also runs faster. files: A Misc/NEWS.d/next/IDLE/2018-02-24-18-20-50.bpo-32940.ZaJ1Rf.rst M Lib/idlelib/idle_test/test_pyparse.py M Lib/idlelib/pyparse.py diff --git a/Lib/idlelib/idle_test/test_pyparse.py b/Lib/idlelib/idle_test/test_pyparse.py index c7b645caa6a8..574b19d9d6f1 100644 --- a/Lib/idlelib/idle_test/test_pyparse.py +++ b/Lib/idlelib/idle_test/test_pyparse.py @@ -8,44 +8,20 @@ from idlelib import pyparse -class StringTranslatePseudoMappingTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - whitespace_chars = ' \t\n\r' - cls.preserve_dict = {ord(c): ord(c) for c in whitespace_chars} - cls.default = ord('x') - cls.mapping = pyparse.StringTranslatePseudoMapping( - cls.preserve_dict, default_value=ord('x')) - - @classmethod - def tearDownClass(cls): - del cls.preserve_dict, cls.default, cls.mapping - - def test__init__(self): - m = self.mapping - self.assertEqual(m._non_defaults, self.preserve_dict) - self.assertEqual(m._default_value, self.default) - - def test__get_item__(self): - self.assertEqual(self.mapping[ord('\t')], ord('\t')) - self.assertEqual(self.mapping[ord('a')], self.default) - - def test__len__(self): - self.assertEqual(len(self.mapping), len(self.preserve_dict)) - - def test__iter__(self): - count = 0 - for key, value in self.mapping.items(): - self.assertIn(key, self.preserve_dict) - count += 1 - self.assertEqual(count, len(self.mapping)) - - def test_get(self): - self.assertEqual(self.mapping.get(ord('\t')), ord('\t')) - self.assertEqual(self.mapping.get('a'), self.default) - # Default is a parameter, but it isn't used. - self.assertEqual(self.mapping.get('a', default=500), self.default) +class ParseMapTest(unittest.TestCase): + + def test_parsemap(self): + keepwhite = {ord(c): ord(c) for c in ' \t\n\r'} + mapping = pyparse.ParseMap(keepwhite) + self.assertEqual(mapping[ord('\t')], ord('\t')) + self.assertEqual(mapping[ord('a')], ord('x')) + self.assertEqual(mapping[1000], ord('x')) + + def test_trans(self): + # trans is the production instance of ParseMap, used in _study1 + parser = pyparse.Parser(4, 4) + self.assertEqual('\t a([{b}])b"c\'d\n'.translate(pyparse.trans), + 'xxx(((x)))x"x\'x\n') class PyParseTest(unittest.TestCase): @@ -152,10 +128,6 @@ def test_set_lo(self): p.set_lo(44) self.assertEqual(p.code, code[44:]) - def test_tran(self): - self.assertEqual('\t a([{b}])b"c\'d\n'.translate(self.parser._tran), - 'xxx(((x)))x"x\'x\n') - def test_study1(self): eq = self.assertEqual p = self.parser diff --git a/Lib/idlelib/pyparse.py b/Lib/idlelib/pyparse.py index 443d198d1efe..6196c2b7edc9 100644 --- a/Lib/idlelib/pyparse.py +++ b/Lib/idlelib/pyparse.py @@ -1,6 +1,6 @@ """Define partial Python code Parser used by editor and hyperparser. -Instances of StringTranslatePseudoMapping are used with str.translate. +Instances of ParseMap are used with str.translate. The following bound search and match functions are defined: _synchre - start of popular statement; @@ -10,7 +10,6 @@ _closere - line that must be followed by dedent. _chew_ordinaryre - non-special characters. """ -from collections.abc import Mapping import re import sys @@ -101,46 +100,27 @@ """, re.VERBOSE).match -class StringTranslatePseudoMapping(Mapping): - r"""Utility class to be used with str.translate() +class ParseMap(dict): + r"""Dict subclass that maps anything not in dict to 'x'. - This Mapping class wraps a given dict. When a value for a key is - requested via __getitem__() or get(), the key is looked up in the - given dict. If found there, the value from the dict is returned. - Otherwise, the default value given upon initialization is returned. + This is designed to be used with str.translate in study1. + Anything not specifically mapped otherwise becomes 'x'. + Example: replace everything except whitespace with 'x'. - This allows using str.translate() to make some replacements, and to - replace all characters for which no replacement was specified with - a given character instead of leaving them as-is. - - For example, to replace everything except whitespace with 'x': - - >>> whitespace_chars = ' \t\n\r' - >>> preserve_dict = {ord(c): ord(c) for c in whitespace_chars} - >>> mapping = StringTranslatePseudoMapping(preserve_dict, ord('x')) - >>> text = "a + b\tc\nd" - >>> text.translate(mapping) + >>> keepwhite = ParseMap((ord(c), ord(c)) for c in ' \t\n\r') + >>> "a + b\tc\nd".translate(keepwhite) 'x x x\tx\nx' """ - def __init__(self, non_defaults, default_value): - self._non_defaults = non_defaults - self._default_value = default_value - - def _get(key, _get=non_defaults.get, _default=default_value): - return _get(key, _default) - self._get = _get + # Calling this triples access time; see bpo-32940 + def __missing__(self, key): + return 120 # ord('x') - def __getitem__(self, item): - return self._get(item) - def __len__(self): - return len(self._non_defaults) - - def __iter__(self): - return iter(self._non_defaults) - - def get(self, key, default=None): - return self._get(key) +# Map all ascii to 120 to avoid __missing__ call, then replace some. +trans = ParseMap.fromkeys(range(128), 120) +trans.update((ord(c), ord('(')) for c in "({[") # open brackets => '('; +trans.update((ord(c), ord(')')) for c in ")}]") # close brackets => ')'. +trans.update((ord(c), ord(c)) for c in "\"'\\\n#") # Keep these. class Parser: @@ -224,16 +204,6 @@ def set_lo(self, lo): if lo > 0: self.code = self.code[lo:] - # Build a translation table to map uninteresting chars to 'x', open - # brackets to '(', close brackets to ')' while preserving quotes, - # backslashes, newlines and hashes. This is to be passed to - # str.translate() in _study1(). - _tran = {} - _tran.update((ord(c), ord('(')) for c in "({[") - _tran.update((ord(c), ord(')')) for c in ")}]") - _tran.update((ord(c), ord(c)) for c in "\"'\\\n#") - _tran = StringTranslatePseudoMapping(_tran, default_value=ord('x')) - def _study1(self): """Find the line numbers of non-continuation lines. @@ -250,7 +220,7 @@ def _study1(self): # uninteresting characters. This can cut the number of chars # by a factor of 10-40, and so greatly speed the following loop. code = self.code - code = code.translate(self._tran) + code = code.translate(trans) code = code.replace('xxxxxxxx', 'x') code = code.replace('xxxx', 'x') code = code.replace('xx', 'x') diff --git a/Misc/NEWS.d/next/IDLE/2018-02-24-18-20-50.bpo-32940.ZaJ1Rf.rst b/Misc/NEWS.d/next/IDLE/2018-02-24-18-20-50.bpo-32940.ZaJ1Rf.rst new file mode 100644 index 000000000000..958f9522d4f8 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2018-02-24-18-20-50.bpo-32940.ZaJ1Rf.rst @@ -0,0 +1 @@ +Simplify and rename StringTranslatePseudoMapping in pyparse. From webhook-mailer at python.org Wed Feb 28 18:08:24 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 28 Feb 2018 23:08:24 -0000 Subject: [Python-checkins] bpo-32940: IDLE: Simplify StringTranslatePseudoMapping in pyparse (GH-5862) Message-ID: https://github.com/python/cpython/commit/7e5763469e2fc9d08a3f6b6205f87f20a1bdd465 commit: 7e5763469e2fc9d08a3f6b6205f87f20a1bdd465 branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-28T15:08:21-08:00 summary: bpo-32940: IDLE: Simplify StringTranslatePseudoMapping in pyparse (GH-5862) The new code also runs faster. (cherry picked from commit f0daa880a405c8de6743e44fa46006754aa145c9) Co-authored-by: Cheryl Sabella files: A Misc/NEWS.d/next/IDLE/2018-02-24-18-20-50.bpo-32940.ZaJ1Rf.rst M Lib/idlelib/idle_test/test_pyparse.py M Lib/idlelib/pyparse.py diff --git a/Lib/idlelib/idle_test/test_pyparse.py b/Lib/idlelib/idle_test/test_pyparse.py index c7b645caa6a8..574b19d9d6f1 100644 --- a/Lib/idlelib/idle_test/test_pyparse.py +++ b/Lib/idlelib/idle_test/test_pyparse.py @@ -8,44 +8,20 @@ from idlelib import pyparse -class StringTranslatePseudoMappingTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - whitespace_chars = ' \t\n\r' - cls.preserve_dict = {ord(c): ord(c) for c in whitespace_chars} - cls.default = ord('x') - cls.mapping = pyparse.StringTranslatePseudoMapping( - cls.preserve_dict, default_value=ord('x')) - - @classmethod - def tearDownClass(cls): - del cls.preserve_dict, cls.default, cls.mapping - - def test__init__(self): - m = self.mapping - self.assertEqual(m._non_defaults, self.preserve_dict) - self.assertEqual(m._default_value, self.default) - - def test__get_item__(self): - self.assertEqual(self.mapping[ord('\t')], ord('\t')) - self.assertEqual(self.mapping[ord('a')], self.default) - - def test__len__(self): - self.assertEqual(len(self.mapping), len(self.preserve_dict)) - - def test__iter__(self): - count = 0 - for key, value in self.mapping.items(): - self.assertIn(key, self.preserve_dict) - count += 1 - self.assertEqual(count, len(self.mapping)) - - def test_get(self): - self.assertEqual(self.mapping.get(ord('\t')), ord('\t')) - self.assertEqual(self.mapping.get('a'), self.default) - # Default is a parameter, but it isn't used. - self.assertEqual(self.mapping.get('a', default=500), self.default) +class ParseMapTest(unittest.TestCase): + + def test_parsemap(self): + keepwhite = {ord(c): ord(c) for c in ' \t\n\r'} + mapping = pyparse.ParseMap(keepwhite) + self.assertEqual(mapping[ord('\t')], ord('\t')) + self.assertEqual(mapping[ord('a')], ord('x')) + self.assertEqual(mapping[1000], ord('x')) + + def test_trans(self): + # trans is the production instance of ParseMap, used in _study1 + parser = pyparse.Parser(4, 4) + self.assertEqual('\t a([{b}])b"c\'d\n'.translate(pyparse.trans), + 'xxx(((x)))x"x\'x\n') class PyParseTest(unittest.TestCase): @@ -152,10 +128,6 @@ def test_set_lo(self): p.set_lo(44) self.assertEqual(p.code, code[44:]) - def test_tran(self): - self.assertEqual('\t a([{b}])b"c\'d\n'.translate(self.parser._tran), - 'xxx(((x)))x"x\'x\n') - def test_study1(self): eq = self.assertEqual p = self.parser diff --git a/Lib/idlelib/pyparse.py b/Lib/idlelib/pyparse.py index 443d198d1efe..6196c2b7edc9 100644 --- a/Lib/idlelib/pyparse.py +++ b/Lib/idlelib/pyparse.py @@ -1,6 +1,6 @@ """Define partial Python code Parser used by editor and hyperparser. -Instances of StringTranslatePseudoMapping are used with str.translate. +Instances of ParseMap are used with str.translate. The following bound search and match functions are defined: _synchre - start of popular statement; @@ -10,7 +10,6 @@ _closere - line that must be followed by dedent. _chew_ordinaryre - non-special characters. """ -from collections.abc import Mapping import re import sys @@ -101,46 +100,27 @@ """, re.VERBOSE).match -class StringTranslatePseudoMapping(Mapping): - r"""Utility class to be used with str.translate() +class ParseMap(dict): + r"""Dict subclass that maps anything not in dict to 'x'. - This Mapping class wraps a given dict. When a value for a key is - requested via __getitem__() or get(), the key is looked up in the - given dict. If found there, the value from the dict is returned. - Otherwise, the default value given upon initialization is returned. + This is designed to be used with str.translate in study1. + Anything not specifically mapped otherwise becomes 'x'. + Example: replace everything except whitespace with 'x'. - This allows using str.translate() to make some replacements, and to - replace all characters for which no replacement was specified with - a given character instead of leaving them as-is. - - For example, to replace everything except whitespace with 'x': - - >>> whitespace_chars = ' \t\n\r' - >>> preserve_dict = {ord(c): ord(c) for c in whitespace_chars} - >>> mapping = StringTranslatePseudoMapping(preserve_dict, ord('x')) - >>> text = "a + b\tc\nd" - >>> text.translate(mapping) + >>> keepwhite = ParseMap((ord(c), ord(c)) for c in ' \t\n\r') + >>> "a + b\tc\nd".translate(keepwhite) 'x x x\tx\nx' """ - def __init__(self, non_defaults, default_value): - self._non_defaults = non_defaults - self._default_value = default_value - - def _get(key, _get=non_defaults.get, _default=default_value): - return _get(key, _default) - self._get = _get + # Calling this triples access time; see bpo-32940 + def __missing__(self, key): + return 120 # ord('x') - def __getitem__(self, item): - return self._get(item) - def __len__(self): - return len(self._non_defaults) - - def __iter__(self): - return iter(self._non_defaults) - - def get(self, key, default=None): - return self._get(key) +# Map all ascii to 120 to avoid __missing__ call, then replace some. +trans = ParseMap.fromkeys(range(128), 120) +trans.update((ord(c), ord('(')) for c in "({[") # open brackets => '('; +trans.update((ord(c), ord(')')) for c in ")}]") # close brackets => ')'. +trans.update((ord(c), ord(c)) for c in "\"'\\\n#") # Keep these. class Parser: @@ -224,16 +204,6 @@ def set_lo(self, lo): if lo > 0: self.code = self.code[lo:] - # Build a translation table to map uninteresting chars to 'x', open - # brackets to '(', close brackets to ')' while preserving quotes, - # backslashes, newlines and hashes. This is to be passed to - # str.translate() in _study1(). - _tran = {} - _tran.update((ord(c), ord('(')) for c in "({[") - _tran.update((ord(c), ord(')')) for c in ")}]") - _tran.update((ord(c), ord(c)) for c in "\"'\\\n#") - _tran = StringTranslatePseudoMapping(_tran, default_value=ord('x')) - def _study1(self): """Find the line numbers of non-continuation lines. @@ -250,7 +220,7 @@ def _study1(self): # uninteresting characters. This can cut the number of chars # by a factor of 10-40, and so greatly speed the following loop. code = self.code - code = code.translate(self._tran) + code = code.translate(trans) code = code.replace('xxxxxxxx', 'x') code = code.replace('xxxx', 'x') code = code.replace('xx', 'x') diff --git a/Misc/NEWS.d/next/IDLE/2018-02-24-18-20-50.bpo-32940.ZaJ1Rf.rst b/Misc/NEWS.d/next/IDLE/2018-02-24-18-20-50.bpo-32940.ZaJ1Rf.rst new file mode 100644 index 000000000000..958f9522d4f8 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2018-02-24-18-20-50.bpo-32940.ZaJ1Rf.rst @@ -0,0 +1 @@ +Simplify and rename StringTranslatePseudoMapping in pyparse. From webhook-mailer at python.org Wed Feb 28 18:12:18 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 28 Feb 2018 23:12:18 -0000 Subject: [Python-checkins] bpo-32940: IDLE: Simplify StringTranslatePseudoMapping in pyparse (GH-5862) Message-ID: https://github.com/python/cpython/commit/32f5392f64f004382e26a988b1145d2dc96c4978 commit: 32f5392f64f004382e26a988b1145d2dc96c4978 branch: 3.6 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-28T15:12:15-08:00 summary: bpo-32940: IDLE: Simplify StringTranslatePseudoMapping in pyparse (GH-5862) The new code also runs faster. (cherry picked from commit f0daa880a405c8de6743e44fa46006754aa145c9) Co-authored-by: Cheryl Sabella files: A Misc/NEWS.d/next/IDLE/2018-02-24-18-20-50.bpo-32940.ZaJ1Rf.rst M Lib/idlelib/idle_test/test_pyparse.py M Lib/idlelib/pyparse.py diff --git a/Lib/idlelib/idle_test/test_pyparse.py b/Lib/idlelib/idle_test/test_pyparse.py index c7b645caa6a8..574b19d9d6f1 100644 --- a/Lib/idlelib/idle_test/test_pyparse.py +++ b/Lib/idlelib/idle_test/test_pyparse.py @@ -8,44 +8,20 @@ from idlelib import pyparse -class StringTranslatePseudoMappingTest(unittest.TestCase): - - @classmethod - def setUpClass(cls): - whitespace_chars = ' \t\n\r' - cls.preserve_dict = {ord(c): ord(c) for c in whitespace_chars} - cls.default = ord('x') - cls.mapping = pyparse.StringTranslatePseudoMapping( - cls.preserve_dict, default_value=ord('x')) - - @classmethod - def tearDownClass(cls): - del cls.preserve_dict, cls.default, cls.mapping - - def test__init__(self): - m = self.mapping - self.assertEqual(m._non_defaults, self.preserve_dict) - self.assertEqual(m._default_value, self.default) - - def test__get_item__(self): - self.assertEqual(self.mapping[ord('\t')], ord('\t')) - self.assertEqual(self.mapping[ord('a')], self.default) - - def test__len__(self): - self.assertEqual(len(self.mapping), len(self.preserve_dict)) - - def test__iter__(self): - count = 0 - for key, value in self.mapping.items(): - self.assertIn(key, self.preserve_dict) - count += 1 - self.assertEqual(count, len(self.mapping)) - - def test_get(self): - self.assertEqual(self.mapping.get(ord('\t')), ord('\t')) - self.assertEqual(self.mapping.get('a'), self.default) - # Default is a parameter, but it isn't used. - self.assertEqual(self.mapping.get('a', default=500), self.default) +class ParseMapTest(unittest.TestCase): + + def test_parsemap(self): + keepwhite = {ord(c): ord(c) for c in ' \t\n\r'} + mapping = pyparse.ParseMap(keepwhite) + self.assertEqual(mapping[ord('\t')], ord('\t')) + self.assertEqual(mapping[ord('a')], ord('x')) + self.assertEqual(mapping[1000], ord('x')) + + def test_trans(self): + # trans is the production instance of ParseMap, used in _study1 + parser = pyparse.Parser(4, 4) + self.assertEqual('\t a([{b}])b"c\'d\n'.translate(pyparse.trans), + 'xxx(((x)))x"x\'x\n') class PyParseTest(unittest.TestCase): @@ -152,10 +128,6 @@ def test_set_lo(self): p.set_lo(44) self.assertEqual(p.code, code[44:]) - def test_tran(self): - self.assertEqual('\t a([{b}])b"c\'d\n'.translate(self.parser._tran), - 'xxx(((x)))x"x\'x\n') - def test_study1(self): eq = self.assertEqual p = self.parser diff --git a/Lib/idlelib/pyparse.py b/Lib/idlelib/pyparse.py index 443d198d1efe..6196c2b7edc9 100644 --- a/Lib/idlelib/pyparse.py +++ b/Lib/idlelib/pyparse.py @@ -1,6 +1,6 @@ """Define partial Python code Parser used by editor and hyperparser. -Instances of StringTranslatePseudoMapping are used with str.translate. +Instances of ParseMap are used with str.translate. The following bound search and match functions are defined: _synchre - start of popular statement; @@ -10,7 +10,6 @@ _closere - line that must be followed by dedent. _chew_ordinaryre - non-special characters. """ -from collections.abc import Mapping import re import sys @@ -101,46 +100,27 @@ """, re.VERBOSE).match -class StringTranslatePseudoMapping(Mapping): - r"""Utility class to be used with str.translate() +class ParseMap(dict): + r"""Dict subclass that maps anything not in dict to 'x'. - This Mapping class wraps a given dict. When a value for a key is - requested via __getitem__() or get(), the key is looked up in the - given dict. If found there, the value from the dict is returned. - Otherwise, the default value given upon initialization is returned. + This is designed to be used with str.translate in study1. + Anything not specifically mapped otherwise becomes 'x'. + Example: replace everything except whitespace with 'x'. - This allows using str.translate() to make some replacements, and to - replace all characters for which no replacement was specified with - a given character instead of leaving them as-is. - - For example, to replace everything except whitespace with 'x': - - >>> whitespace_chars = ' \t\n\r' - >>> preserve_dict = {ord(c): ord(c) for c in whitespace_chars} - >>> mapping = StringTranslatePseudoMapping(preserve_dict, ord('x')) - >>> text = "a + b\tc\nd" - >>> text.translate(mapping) + >>> keepwhite = ParseMap((ord(c), ord(c)) for c in ' \t\n\r') + >>> "a + b\tc\nd".translate(keepwhite) 'x x x\tx\nx' """ - def __init__(self, non_defaults, default_value): - self._non_defaults = non_defaults - self._default_value = default_value - - def _get(key, _get=non_defaults.get, _default=default_value): - return _get(key, _default) - self._get = _get + # Calling this triples access time; see bpo-32940 + def __missing__(self, key): + return 120 # ord('x') - def __getitem__(self, item): - return self._get(item) - def __len__(self): - return len(self._non_defaults) - - def __iter__(self): - return iter(self._non_defaults) - - def get(self, key, default=None): - return self._get(key) +# Map all ascii to 120 to avoid __missing__ call, then replace some. +trans = ParseMap.fromkeys(range(128), 120) +trans.update((ord(c), ord('(')) for c in "({[") # open brackets => '('; +trans.update((ord(c), ord(')')) for c in ")}]") # close brackets => ')'. +trans.update((ord(c), ord(c)) for c in "\"'\\\n#") # Keep these. class Parser: @@ -224,16 +204,6 @@ def set_lo(self, lo): if lo > 0: self.code = self.code[lo:] - # Build a translation table to map uninteresting chars to 'x', open - # brackets to '(', close brackets to ')' while preserving quotes, - # backslashes, newlines and hashes. This is to be passed to - # str.translate() in _study1(). - _tran = {} - _tran.update((ord(c), ord('(')) for c in "({[") - _tran.update((ord(c), ord(')')) for c in ")}]") - _tran.update((ord(c), ord(c)) for c in "\"'\\\n#") - _tran = StringTranslatePseudoMapping(_tran, default_value=ord('x')) - def _study1(self): """Find the line numbers of non-continuation lines. @@ -250,7 +220,7 @@ def _study1(self): # uninteresting characters. This can cut the number of chars # by a factor of 10-40, and so greatly speed the following loop. code = self.code - code = code.translate(self._tran) + code = code.translate(trans) code = code.replace('xxxxxxxx', 'x') code = code.replace('xxxx', 'x') code = code.replace('xx', 'x') diff --git a/Misc/NEWS.d/next/IDLE/2018-02-24-18-20-50.bpo-32940.ZaJ1Rf.rst b/Misc/NEWS.d/next/IDLE/2018-02-24-18-20-50.bpo-32940.ZaJ1Rf.rst new file mode 100644 index 000000000000..958f9522d4f8 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2018-02-24-18-20-50.bpo-32940.ZaJ1Rf.rst @@ -0,0 +1 @@ +Simplify and rename StringTranslatePseudoMapping in pyparse. From webhook-mailer at python.org Wed Feb 28 18:46:43 2018 From: webhook-mailer at python.org (Mariatta) Date: Wed, 28 Feb 2018 23:46:43 -0000 Subject: [Python-checkins] Fix typo in logging doc: picked -> pickled (GH-5942) Message-ID: https://github.com/python/cpython/commit/982c7233846e8fbdb1e0ca23c8ae3f6362645307 commit: 982c7233846e8fbdb1e0ca23c8ae3f6362645307 branch: master author: James Walker <19191463+jdswalker at users.noreply.github.com> committer: Mariatta date: 2018-02-28T15:46:35-08:00 summary: Fix typo in logging doc: picked -> pickled (GH-5942) files: M Doc/library/logging.rst diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst index 1ed129c00d49..88f804a074ec 100644 --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -328,7 +328,7 @@ is the module's name in the Python package namespace. .. versionadded:: 3.2 .. versionchanged:: 3.7 - Loggers can now be picked and unpickled. + Loggers can now be pickled and unpickled. .. _levels: From webhook-mailer at python.org Wed Feb 28 18:59:01 2018 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Wed, 28 Feb 2018 23:59:01 -0000 Subject: [Python-checkins] Fix typo in logging doc: picked -> pickled (GH-5942) Message-ID: https://github.com/python/cpython/commit/82734a6769a9b986478b130d321f8bbd18e1546a commit: 82734a6769a9b986478b130d321f8bbd18e1546a branch: 3.7 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2018-02-28T15:58:58-08:00 summary: Fix typo in logging doc: picked -> pickled (GH-5942) (cherry picked from commit 982c7233846e8fbdb1e0ca23c8ae3f6362645307) Co-authored-by: James Walker <19191463+jdswalker at users.noreply.github.com> files: M Doc/library/logging.rst diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst index 1ed129c00d49..88f804a074ec 100644 --- a/Doc/library/logging.rst +++ b/Doc/library/logging.rst @@ -328,7 +328,7 @@ is the module's name in the Python package namespace. .. versionadded:: 3.2 .. versionchanged:: 3.7 - Loggers can now be picked and unpickled. + Loggers can now be pickled and unpickled. .. _levels: